]> CyberLeo.Net >> Repos - FreeBSD/releng/10.0.git/blob - release/picobsd/tinyware/msh/sh5.c
- Copy stable/10 (r259064) to releng/10.0 as part of the
[FreeBSD/releng/10.0.git] / release / picobsd / tinyware / msh / sh5.c
1 #define Extern extern
2 #include <sys/types.h>
3 #include <signal.h>
4 #define _NSIG NSIG
5 #include <errno.h>
6 #include <setjmp.h>
7 #include "sh.h"
8
9 /* -------- io.c -------- */
10 /* #include "sh.h" */
11
12 /*
13  * shell IO
14  */
15
16 static struct iobuf sharedbuf = {AFID_NOBUF};
17 static struct iobuf mainbuf = {AFID_NOBUF};
18 static unsigned bufid = AFID_ID;        /* buffer id counter */
19
20 struct ioarg temparg = {0, 0, 0, AFID_NOBUF, 0};
21
22 _PROTOTYPE(static void readhere, (char **name, char *s, int ec ));
23 _PROTOTYPE(void pushio, (struct ioarg *argp, int (*fn)()));
24 _PROTOTYPE(static int xxchar, (struct ioarg *ap ));
25 _PROTOTYPE(void tempname, (char *tname ));
26
27 int
28 getc(ec)
29 register int ec;
30 {
31         register int c;
32
33         if(e.linep > elinep) {
34                 while((c=readc()) != '\n' && c)
35                         ;
36                 err("input line too long");
37                 gflg++;
38                 return(c);
39         }
40         c = readc();
41         if (ec != '\'' && e.iop->task != XGRAVE) {
42                 if(c == '\\') {
43                         c = readc();
44                         if (c == '\n' && ec != '\"')
45                                 return(getc(ec));
46                         c |= QUOTE;
47                 }
48         }
49         return(c);
50 }
51
52 void
53 unget(c)
54 int c;
55 {
56         if (e.iop >= e.iobase)
57                 e.iop->peekc = c;
58 }
59
60 int
61 eofc()
62
63 {
64   return e.iop < e.iobase || (e.iop->peekc == 0 && e.iop->prev == 0);
65 }
66
67 int
68 readc()
69 {
70         register c;
71
72         for (; e.iop >= e.iobase; e.iop--)
73                 if ((c = e.iop->peekc) != '\0') {
74                         e.iop->peekc = 0;
75                         return(c);
76                 }
77                 else {
78                     if (e.iop->prev != 0) {
79                         if ((c = (*e.iop->iofn)(e.iop->argp, e.iop)) != '\0') {
80                                 if (c == -1) {
81                                         e.iop++;
82                                         continue;
83                                 }
84                                 if (e.iop == iostack)
85                                         ioecho(c);
86                                 return(e.iop->prev = c);
87                         }
88                         else if (e.iop->task == XIO && e.iop->prev != '\n') {
89                                 e.iop->prev = 0;
90                                 if (e.iop == iostack)
91                                         ioecho('\n');
92                                 return '\n';
93                         }
94                     }
95                     if (e.iop->task == XIO) {
96                         if (multiline)
97                             return e.iop->prev = 0;
98                         if (talking && e.iop == iostack+1)
99                             prs(prompt->value);
100                     }
101                 }
102         if (e.iop >= iostack)
103                 return(0);
104         leave();
105         /* NOTREACHED */
106 }
107
108 void
109 ioecho(c)
110 char c;
111 {
112         if (flag['v'])
113                 write(2, &c, sizeof c);
114 }
115
116 void
117 pushio(argp, fn)
118 struct ioarg *argp;
119 int (*fn)();
120 {
121         if (++e.iop >= &iostack[NPUSH]) {
122                 e.iop--;
123                 err("Shell input nested too deeply");
124                 gflg++;
125                 return;
126         }
127         e.iop->iofn = fn;
128
129         if (argp->afid != AFID_NOBUF)
130           e.iop->argp = argp;
131         else {
132           e.iop->argp  = ioargstack + (e.iop - iostack);
133           *e.iop->argp = *argp;
134           e.iop->argp->afbuf = e.iop == &iostack[0] ? &mainbuf : &sharedbuf;
135           if (isatty(e.iop->argp->afile) == 0 &&
136               (e.iop == &iostack[0] ||
137                lseek(e.iop->argp->afile, 0L, 1) != -1)) {
138             if (++bufid == AFID_NOBUF)
139               bufid = AFID_ID;
140             e.iop->argp->afid  = bufid;
141           }
142         }
143
144         e.iop->prev  = ~'\n';
145         e.iop->peekc = 0;
146         e.iop->xchar = 0;
147         e.iop->nlcount = 0;
148         if (fn == filechar || fn == linechar)
149                 e.iop->task = XIO;
150         else if (fn == gravechar || fn == qgravechar)
151                 e.iop->task = XGRAVE;
152         else
153                 e.iop->task = XOTHER;
154 }
155
156 struct io *
157 setbase(ip)
158 struct io *ip;
159 {
160         register struct io *xp;
161
162         xp = e.iobase;
163         e.iobase = ip;
164         return(xp);
165 }
166
167 /*
168  * Input generating functions
169  */
170
171 /*
172  * Produce the characters of a string, then a newline, then EOF.
173  */
174 int
175 nlchar(ap)
176 register struct ioarg *ap;
177 {
178         register int c;
179
180         if (ap->aword == NULL)
181                 return(0);
182         if ((c = *ap->aword++) == 0) {
183                 ap->aword = NULL;
184                 return('\n');
185         }
186         return(c);
187 }
188
189 /*
190  * Given a list of words, produce the characters
191  * in them, with a space after each word.
192  */
193 int
194 wdchar(ap)
195 register struct ioarg *ap;
196 {
197         register char c;
198         register char **wl;
199
200         if ((wl = ap->awordlist) == NULL)
201                 return(0);
202         if (*wl != NULL) {
203                 if ((c = *(*wl)++) != 0)
204                         return(c & 0177);
205                 ap->awordlist++;
206                 return(' ');
207         }
208         ap->awordlist = NULL;
209         return('\n');
210 }
211
212 /*
213  * Return the characters of a list of words,
214  * producing a space between them.
215  */
216 int
217 dolchar(ap)
218 register struct ioarg *ap;
219 {
220         register char *wp;
221
222         if ((wp = *ap->awordlist++) != NULL) {
223                 PUSHIO(aword, wp, *ap->awordlist == NULL? strchar: xxchar);
224                 return(-1);
225         }
226         return(0);
227 }
228
229 static int
230 xxchar(ap)
231 register struct ioarg *ap;
232 {
233         register int c;
234
235         if (ap->aword == NULL)
236                 return(0);
237         if ((c = *ap->aword++) == '\0') {
238                 ap->aword = NULL;
239                 return(' ');
240         }
241         return(c);
242 }
243
244 /*
245  * Produce the characters from a single word (string).
246  */
247 int
248 strchar(ap)
249 register struct ioarg *ap;
250 {
251         register int c;
252
253         if (ap->aword == NULL || (c = *ap->aword++) == 0)
254                 return(0);
255         return(c);
256 }
257
258 /*
259  * Produce quoted characters from a single word (string).
260  */
261 int
262 qstrchar(ap)
263 register struct ioarg *ap;
264 {
265         register int c;
266
267         if (ap->aword == NULL || (c = *ap->aword++) == 0)
268                 return(0);
269         return(c|QUOTE);
270 }
271
272 /*
273  * Return the characters from a file.
274  */
275 int
276 filechar(ap)
277 register struct ioarg *ap;
278 {
279         register int i;
280         char c;
281         struct iobuf *bp = ap->afbuf;
282
283         if (ap->afid != AFID_NOBUF) {
284           if ((i = ap->afid != bp->id) || bp->bufp == bp->ebufp) {
285             if (i)
286               lseek(ap->afile, ap->afpos, 0);
287             do {
288               i = read(ap->afile, bp->buf, sizeof(bp->buf));
289             } while (i < 0 && errno == EINTR);
290             if (i <= 0) {
291               closef(ap->afile);
292               return 0;
293             }
294             bp->id = ap->afid;
295             bp->ebufp = (bp->bufp  = bp->buf) + i;
296           }
297           ap->afpos++;
298           return *bp->bufp++ & 0177;
299         }
300
301         do {
302                 i = read(ap->afile, &c, sizeof(c));
303         } while (i < 0 && errno == EINTR);
304         return(i == sizeof(c)? c&0177: (closef(ap->afile), 0));
305 }
306
307 /*
308  * Return the characters from a here temp file.
309  */
310 int
311 herechar(ap)
312 register struct ioarg *ap;
313 {
314         char c;
315
316
317         if (read(ap->afile, &c, sizeof(c)) != sizeof(c)) {
318                 close(ap->afile);
319                 c = 0;
320         }
321         return (c);
322
323 }
324
325 /*
326  * Return the characters produced by a process (`...`).
327  * Quote them if required, and remove any trailing newline characters.
328  */
329 int
330 gravechar(ap, iop)
331 struct ioarg *ap;
332 struct io *iop;
333 {
334         register int c;
335
336         if ((c = qgravechar(ap, iop)&~QUOTE) == '\n')
337                 c = ' ';
338         return(c);
339 }
340
341 int
342 qgravechar(ap, iop)
343 register struct ioarg *ap;
344 struct io *iop;
345 {
346         register int c;
347
348         if (iop->xchar) {
349                 if (iop->nlcount) {
350                         iop->nlcount--;
351                         return('\n'|QUOTE);
352                 }
353                 c = iop->xchar;
354                 iop->xchar = 0;
355         } else if ((c = filechar(ap)) == '\n') {
356                 iop->nlcount = 1;
357                 while ((c = filechar(ap)) == '\n')
358                         iop->nlcount++;
359                 iop->xchar = c;
360                 if (c == 0)
361                         return(c);
362                 iop->nlcount--;
363                 c = '\n';
364         }
365         return(c!=0? c|QUOTE: 0);
366 }
367
368 /*
369  * Return a single command (usually the first line) from a file.
370  */
371 int
372 linechar(ap)
373 register struct ioarg *ap;
374 {
375         register int c;
376
377         if ((c = filechar(ap)) == '\n') {
378                 if (!multiline) {
379                         closef(ap->afile);
380                         ap->afile = -1; /* illegal value */
381                 }
382         }
383         return(c);
384 }
385
386 void
387 prs(s)
388 register char *s;
389 {
390         if (*s)
391                 write(2, s, strlen(s));
392 }
393
394 void
395 putc(c)
396 char c;
397 {
398         write(2, &c, sizeof c);
399 }
400
401 void
402 prn(u)
403 unsigned u;
404 {
405         prs(itoa(u, 0));
406 }
407
408 void
409 closef(i)
410 register int i;
411 {
412         if (i > 2)
413                 close(i);
414 }
415
416 void
417 closeall()
418 {
419         register u;
420
421         for (u=NUFILE; u<NOFILE;)
422                 close(u++);
423 }
424
425 /*
426  * remap fd into Shell's fd space
427  */
428 int
429 remap(fd)
430 register int fd;
431 {
432         register int i;
433         int map[NOFILE];
434
435         if (fd < e.iofd) {
436                 for (i=0; i<NOFILE; i++)
437                         map[i] = 0;
438                 do {
439                         map[fd] = 1;
440                         fd = dup(fd);
441                 } while (fd >= 0 && fd < e.iofd);
442                 for (i=0; i<NOFILE; i++)
443                         if (map[i])
444                                 close(i);
445                 if (fd < 0)
446                         err("too many files open in shell");
447         }
448         return(fd);
449 }
450
451 int
452 openpipe(pv)
453 register int *pv;
454 {
455         register int i;
456
457         if ((i = pipe(pv)) < 0)
458                 err("can't create pipe - try again");
459         return(i);
460 }
461
462 void
463 closepipe(pv)
464 register int *pv;
465 {
466         if (pv != NULL) {
467                 close(*pv++);
468                 close(*pv);
469         }
470 }
471
472 /* -------- here.c -------- */
473 /* #include "sh.h" */
474
475 /*
476  * here documents
477  */
478
479 struct  here {
480         char    *h_tag;
481         int     h_dosub;
482         struct  ioword *h_iop;
483         struct  here    *h_next;
484 };
485
486 static  struct here *inhere;            /* list of hear docs while parsing */
487 static  struct here *acthere;           /* list of active here documents */
488
489 void
490 markhere(s, iop)
491 register char *s;
492 struct ioword *iop;
493 {
494         register struct here *h, *lh;
495
496         h = (struct here *) space(sizeof(struct here));
497         if (h == 0)
498                 return;
499         h->h_tag = evalstr(s, DOSUB);
500         if (h->h_tag == 0)
501                 return;
502         h->h_iop = iop;
503         iop->io_name = 0;
504         h->h_next = NULL;
505         if (inhere == 0)
506                 inhere = h;
507         else
508                 for (lh = inhere; lh!=NULL; lh = lh->h_next)
509                         if (lh->h_next == 0) {
510                                 lh->h_next = h;
511                                 break;
512                         }
513         iop->io_flag |= IOHERE|IOXHERE;
514         for (s = h->h_tag; *s; s++)
515                 if (*s & QUOTE) {
516                         iop->io_flag &= ~ IOXHERE;
517                         *s &= ~ QUOTE;
518                 }
519         h->h_dosub = iop->io_flag & IOXHERE;
520 }
521
522 void
523 gethere()
524 {
525         register struct here *h, *hp;
526
527         /* Scan here files first leaving inhere list in place */
528         for (hp = h = inhere; h != NULL; hp = h, h = h->h_next)
529           readhere(&h->h_iop->io_name, h->h_tag, h->h_dosub? 0: '\'');
530
531         /* Make inhere list active - keep list intact for scraphere */
532         if (hp != NULL) {
533           hp->h_next = acthere;
534           acthere    = inhere;
535           inhere     = NULL;
536         }
537 }
538
539 static void
540 readhere(name, s, ec)
541 char **name;
542 register char *s;
543 int ec;
544 {
545         int tf;
546         char tname[30];
547         register c;
548         jmp_buf ev;
549         char line [LINELIM+1];
550         char *next;
551
552         tempname(tname);
553         *name = strsave(tname, areanum);
554         tf = creat(tname, 0600);
555         if (tf < 0)
556                 return;
557         if (newenv(setjmp(errpt = ev)) != 0)
558                 unlink(tname);
559         else {
560                 pushio(e.iop->argp, e.iop->iofn);
561                 e.iobase = e.iop;
562                 for (;;) {
563                         if (talking && e.iop <= iostack)
564                                 prs(cprompt->value);
565                         next = line;
566                         while ((c = getc(ec)) != '\n' && c) {
567                                 if (ec == '\'')
568                                         c &= ~ QUOTE;
569                                 if (next >= &line[LINELIM]) {
570                                         c = 0;
571                                         break;
572                                 }
573                                 *next++ = c;
574                         }
575                         *next = 0;
576                         if (strcmp(s, line) == 0 || c == 0)
577                                 break;
578                         *next++ = '\n';
579                         write (tf, line, (int)(next-line));
580                 }
581                 if (c == 0) {
582                         prs("here document `"); prs(s); err("' unclosed");
583                 }
584                 quitenv();
585         }
586         close(tf);
587 }
588
589 /*
590  * open here temp file.
591  * if unquoted here, expand here temp file into second temp file.
592  */
593 int
594 herein(hname, xdoll)
595 char *hname;
596 int xdoll;
597 {
598         register hf, tf;
599
600         if (hname == 0)
601                 return(-1);
602         hf = open(hname, 0);
603         if (hf < 0)
604                 return (-1);
605         if (xdoll) {
606                 char c;
607                 char tname[30];
608                 jmp_buf ev;
609
610                 tempname(tname);
611                 if ((tf = creat(tname, 0600)) < 0)
612                         return (-1);
613                 if (newenv(setjmp(errpt = ev)) == 0) {
614                         PUSHIO(afile, hf, herechar);
615                         setbase(e.iop);
616                         while ((c = subgetc(0, 0)) != 0) {
617                                 c &= ~ QUOTE;
618                                 write(tf, &c, sizeof c);
619                         }
620                         quitenv();
621                 } else
622                         unlink(tname);
623                 close(tf);
624                 tf = open(tname, 0);
625                 unlink(tname);
626                 return (tf);
627         } else
628                 return (hf);
629 }
630
631 void
632 scraphere()
633 {
634         register struct here *h;
635
636         for (h = inhere; h != NULL; h = h->h_next) {
637                 if (h->h_iop && h->h_iop->io_name)
638                   unlink(h->h_iop->io_name);
639         }
640         inhere = NULL;
641 }
642
643 /* unlink here temp files before a freearea(area) */
644 void
645 freehere(area)
646 int area;
647 {
648         register struct here *h, *hl;
649
650         hl = NULL;
651         for (h = acthere; h != NULL; h = h->h_next)
652                 if (getarea((char *) h) >= area) {
653                         if (h->h_iop->io_name != NULL)
654                                 unlink(h->h_iop->io_name);
655                         if (hl == NULL)
656                                 acthere = h->h_next;
657                         else
658                                 hl->h_next = h->h_next;
659                 } else
660                         hl = h;
661 }
662
663 void
664 tempname(tname)
665 char *tname;
666 {
667         static int inc;
668         register char *cp, *lp;
669
670         for (cp = tname, lp = "/tmp/shtm"; (*cp = *lp++) != '\0'; cp++)
671                 ;
672         lp = putn(getpid()*1000 + inc++);
673         for (; (*cp = *lp++) != '\0'; cp++)
674                 ;
675 }