improve behaviour under VPC, fixes from nicolas tittley.
[minix.git] / commands / sh / sh5.c
blob6e454bb3ae23d56563b8fed0fd12447644b7543d
1 #define Extern extern
2 #include <sys/types.h>
3 #include <signal.h>
4 #include <errno.h>
5 #include <setjmp.h>
6 #include "sh.h"
8 /* -------- io.c -------- */
9 /* #include "sh.h" */
12 * shell IO
15 static struct iobuf sharedbuf = {AFID_NOBUF};
16 static struct iobuf mainbuf = {AFID_NOBUF};
17 static unsigned bufid = AFID_ID; /* buffer id counter */
19 struct ioarg temparg = {0, 0, 0, AFID_NOBUF, 0};
21 _PROTOTYPE(static void readhere, (char **name, char *s, int ec ));
22 _PROTOTYPE(void pushio, (struct ioarg *argp, int (*fn)()));
23 _PROTOTYPE(static int xxchar, (struct ioarg *ap ));
24 _PROTOTYPE(void tempname, (char *tname ));
26 int
27 getc(ec)
28 register int ec;
30 register int c;
32 if(e.linep > elinep) {
33 while((c=readc()) != '\n' && c)
35 err("input line too long");
36 gflg++;
37 return(c);
39 c = readc();
40 if (ec != '\'' && e.iop->task != XGRAVE) {
41 if(c == '\\') {
42 c = readc();
43 if (c == '\n' && ec != '\"')
44 return(getc(ec));
45 c |= QUOTE;
48 return(c);
51 void
52 unget(c)
53 int c;
55 if (e.iop >= e.iobase)
56 e.iop->peekc = c;
59 int
60 eofc()
63 return e.iop < e.iobase || (e.iop->peekc == 0 && e.iop->prev == 0);
66 int
67 readc()
69 register c;
71 for (; e.iop >= e.iobase; e.iop--)
72 if ((c = e.iop->peekc) != '\0') {
73 e.iop->peekc = 0;
74 return(c);
76 else {
77 if (e.iop->prev != 0) {
78 if ((c = (*e.iop->iofn)(e.iop->argp, e.iop)) != '\0') {
79 if (c == -1) {
80 e.iop++;
81 continue;
83 if (e.iop == iostack)
84 ioecho(c);
85 return(e.iop->prev = c);
87 else if (e.iop->task == XIO && e.iop->prev != '\n') {
88 e.iop->prev = 0;
89 if (e.iop == iostack)
90 ioecho('\n');
91 return '\n';
94 if (e.iop->task == XIO) {
95 if (multiline)
96 return e.iop->prev = 0;
97 if (talking && e.iop == iostack+1)
98 prs(prompt->value);
101 if (e.iop >= iostack)
102 return(0);
103 leave();
104 /* NOTREACHED */
107 void
108 ioecho(c)
109 char c;
111 if (flag['v'])
112 write(2, &c, sizeof c);
115 void
116 pushio(argp, fn)
117 struct ioarg *argp;
118 int (*fn)();
120 if (++e.iop >= &iostack[NPUSH]) {
121 e.iop--;
122 err("Shell input nested too deeply");
123 gflg++;
124 return;
126 e.iop->iofn = fn;
128 if (argp->afid != AFID_NOBUF)
129 e.iop->argp = argp;
130 else {
131 e.iop->argp = ioargstack + (e.iop - iostack);
132 *e.iop->argp = *argp;
133 e.iop->argp->afbuf = e.iop == &iostack[0] ? &mainbuf : &sharedbuf;
134 if (isatty(e.iop->argp->afile) == 0 &&
135 (e.iop == &iostack[0] ||
136 lseek(e.iop->argp->afile, 0L, 1) != -1)) {
137 if (++bufid == AFID_NOBUF)
138 bufid = AFID_ID;
139 e.iop->argp->afid = bufid;
143 e.iop->prev = ~'\n';
144 e.iop->peekc = 0;
145 e.iop->xchar = 0;
146 e.iop->nlcount = 0;
147 if (fn == filechar || fn == linechar)
148 e.iop->task = XIO;
149 else if (fn == gravechar || fn == qgravechar)
150 e.iop->task = XGRAVE;
151 else
152 e.iop->task = XOTHER;
155 struct io *
156 setbase(ip)
157 struct io *ip;
159 register struct io *xp;
161 xp = e.iobase;
162 e.iobase = ip;
163 return(xp);
167 * Input generating functions
171 * Produce the characters of a string, then a newline, then EOF.
174 nlchar(ap)
175 register struct ioarg *ap;
177 register int c;
179 if (ap->aword == NULL)
180 return(0);
181 if ((c = *ap->aword++) == 0) {
182 ap->aword = NULL;
183 return('\n');
185 return(c);
189 * Given a list of words, produce the characters
190 * in them, with a space after each word.
193 wdchar(ap)
194 register struct ioarg *ap;
196 register char c;
197 register char **wl;
199 if ((wl = ap->awordlist) == NULL)
200 return(0);
201 if (*wl != NULL) {
202 if ((c = *(*wl)++) != 0)
203 return(c & 0177);
204 ap->awordlist++;
205 return(' ');
207 ap->awordlist = NULL;
208 return('\n');
212 * Return the characters of a list of words,
213 * producing a space between them.
216 dolchar(ap)
217 register struct ioarg *ap;
219 register char *wp;
221 if ((wp = *ap->awordlist++) != NULL) {
222 PUSHIO(aword, wp, *ap->awordlist == NULL? strchar: xxchar);
223 return(-1);
225 return(0);
228 static int
229 xxchar(ap)
230 register struct ioarg *ap;
232 register int c;
234 if (ap->aword == NULL)
235 return(0);
236 if ((c = *ap->aword++) == '\0') {
237 ap->aword = NULL;
238 return(' ');
240 return(c);
244 * Produce the characters from a single word (string).
247 strchar(ap)
248 register struct ioarg *ap;
250 register int c;
252 if (ap->aword == NULL || (c = *ap->aword++) == 0)
253 return(0);
254 return(c);
258 * Produce quoted characters from a single word (string).
261 qstrchar(ap)
262 register struct ioarg *ap;
264 register int c;
266 if (ap->aword == NULL || (c = *ap->aword++) == 0)
267 return(0);
268 return(c|QUOTE);
272 * Return the characters from a file.
275 filechar(ap)
276 register struct ioarg *ap;
278 register int i;
279 char c;
280 struct iobuf *bp = ap->afbuf;
282 if (ap->afid != AFID_NOBUF) {
283 if ((i = ap->afid != bp->id) || bp->bufp == bp->ebufp) {
284 if (i)
285 lseek(ap->afile, ap->afpos, 0);
286 do {
287 i = read(ap->afile, bp->buf, sizeof(bp->buf));
288 } while (i < 0 && errno == EINTR);
289 if (i <= 0) {
290 closef(ap->afile);
291 return 0;
293 bp->id = ap->afid;
294 bp->ebufp = (bp->bufp = bp->buf) + i;
296 ap->afpos++;
297 return *bp->bufp++ & 0177;
300 do {
301 i = read(ap->afile, &c, sizeof(c));
302 } while (i < 0 && errno == EINTR);
303 return(i == sizeof(c)? c&0177: (closef(ap->afile), 0));
307 * Return the characters from a here temp file.
310 herechar(ap)
311 register struct ioarg *ap;
313 char c;
316 if (read(ap->afile, &c, sizeof(c)) != sizeof(c)) {
317 close(ap->afile);
318 c = 0;
320 return (c);
325 * Return the characters produced by a process (`...`).
326 * Quote them if required, and remove any trailing newline characters.
329 gravechar(ap, iop)
330 struct ioarg *ap;
331 struct io *iop;
333 register int c;
335 if ((c = qgravechar(ap, iop)&~QUOTE) == '\n')
336 c = ' ';
337 return(c);
341 qgravechar(ap, iop)
342 register struct ioarg *ap;
343 struct io *iop;
345 register int c;
347 if (iop->xchar) {
348 if (iop->nlcount) {
349 iop->nlcount--;
350 return('\n'|QUOTE);
352 c = iop->xchar;
353 iop->xchar = 0;
354 } else if ((c = filechar(ap)) == '\n') {
355 iop->nlcount = 1;
356 while ((c = filechar(ap)) == '\n')
357 iop->nlcount++;
358 iop->xchar = c;
359 if (c == 0)
360 return(c);
361 iop->nlcount--;
362 c = '\n';
364 return(c!=0? c|QUOTE: 0);
368 * Return a single command (usually the first line) from a file.
371 linechar(ap)
372 register struct ioarg *ap;
374 register int c;
376 if ((c = filechar(ap)) == '\n') {
377 if (!multiline) {
378 closef(ap->afile);
379 ap->afile = -1; /* illegal value */
382 return(c);
385 void
386 prs(s)
387 register char *s;
389 if (*s)
390 write(2, s, strlen(s));
393 void
394 putc(c)
395 char c;
397 write(2, &c, sizeof c);
400 void
401 prn(u)
402 unsigned u;
404 prs(itoa(u, 0));
407 void
408 closef(i)
409 register int i;
411 if (i > 2)
412 close(i);
415 void
416 closeall()
418 register u;
420 for (u=NUFILE; u<NOFILE;)
421 close(u++);
425 * remap fd into Shell's fd space
428 remap(fd)
429 register int fd;
431 register int i;
432 int map[NOFILE];
434 if (fd < e.iofd) {
435 for (i=0; i<NOFILE; i++)
436 map[i] = 0;
437 do {
438 map[fd] = 1;
439 fd = dup(fd);
440 } while (fd >= 0 && fd < e.iofd);
441 for (i=0; i<NOFILE; i++)
442 if (map[i])
443 close(i);
444 if (fd < 0)
445 err("too many files open in shell");
447 return(fd);
451 openpipe(pv)
452 register int *pv;
454 register int i;
456 if ((i = pipe(pv)) < 0)
457 err("can't create pipe - try again");
458 return(i);
461 void
462 closepipe(pv)
463 register int *pv;
465 if (pv != NULL) {
466 close(*pv++);
467 close(*pv);
471 /* -------- here.c -------- */
472 /* #include "sh.h" */
475 * here documents
478 struct here {
479 char *h_tag;
480 int h_dosub;
481 struct ioword *h_iop;
482 struct here *h_next;
485 static struct here *inhere; /* list of hear docs while parsing */
486 static struct here *acthere; /* list of active here documents */
488 void
489 inithere()
491 inhere=acthere=(struct here*)0;
494 void
495 markhere(s, iop)
496 register char *s;
497 struct ioword *iop;
499 register struct here *h, *lh;
501 h = (struct here *) space(sizeof(struct here));
502 if (h == 0)
503 return;
504 h->h_tag = evalstr(s, DOSUB);
505 if (h->h_tag == 0)
506 return;
507 h->h_iop = iop;
508 iop->io_name = 0;
509 h->h_next = NULL;
510 if (inhere == 0)
511 inhere = h;
512 else
513 for (lh = inhere; lh!=NULL; lh = lh->h_next)
514 if (lh->h_next == 0) {
515 lh->h_next = h;
516 break;
518 iop->io_flag |= IOHERE|IOXHERE;
519 for (s = h->h_tag; *s; s++)
520 if (*s & QUOTE) {
521 iop->io_flag &= ~ IOXHERE;
522 *s &= ~ QUOTE;
524 h->h_dosub = iop->io_flag & IOXHERE;
527 void
528 gethere()
530 register struct here *h, *hp;
532 /* Scan here files first leaving inhere list in place */
533 for (hp = h = inhere; h != NULL; hp = h, h = h->h_next)
534 readhere(&h->h_iop->io_name, h->h_tag, h->h_dosub? 0: '\'');
536 /* Make inhere list active - keep list intact for scraphere */
537 if (hp != NULL) {
538 hp->h_next = acthere;
539 acthere = inhere;
540 inhere = NULL;
544 static void
545 readhere(name, s, ec)
546 char **name;
547 register char *s;
548 int ec;
550 int tf;
551 char tname[30];
552 register c;
553 jmp_buf ev;
554 char line [LINELIM+1];
555 char *next;
557 tempname(tname);
558 *name = strsave(tname, areanum);
559 tf = creat(tname, 0600);
560 if (tf < 0)
561 return;
562 if (newenv(setjmp(errpt = ev)) != 0)
563 unlink(tname);
564 else {
565 pushio(e.iop->argp, e.iop->iofn);
566 e.iobase = e.iop;
567 for (;;) {
568 if (talking && e.iop <= iostack)
569 prs(cprompt->value);
570 next = line;
571 while ((c = readc()) != '\n' && c) {
572 if (next >= &line[LINELIM]) {
573 c = 0;
574 break;
576 *next++ = c;
578 *next = 0;
579 if (strcmp(s, line) == 0 || c == 0)
580 break;
581 *next++ = '\n';
582 write (tf, line, (int)(next-line));
584 if (c == 0) {
585 prs("here document `"); prs(s); err("' unclosed");
587 quitenv();
589 close(tf);
593 * open here temp file.
594 * if unquoted here, expand here temp file into second temp file.
597 herein(hname, xdoll)
598 char *hname;
599 int xdoll;
601 register hf, tf;
603 if (hname == 0)
604 return(-1);
605 hf = open(hname, 0);
606 if (hf < 0)
607 return (-1);
608 if (xdoll) {
609 char c;
610 char tname[30];
611 jmp_buf ev;
613 tempname(tname);
614 if ((tf = creat(tname, 0600)) < 0)
615 return (-1);
616 if (newenv(setjmp(errpt = ev)) == 0) {
617 PUSHIO(afile, hf, herechar);
618 setbase(e.iop);
619 while ((c = subgetc(0, 0)) != 0) {
620 char c1 = c&~QUOTE;
622 if (c&QUOTE && !any(c1,"`$\\"))
623 write(tf,"\\",1);
624 write(tf, &c1, 1);
626 quitenv();
627 } else
628 unlink(tname);
629 close(tf);
630 tf = open(tname, 0);
631 unlink(tname);
632 return (tf);
633 } else
634 return (hf);
637 void
638 scraphere()
640 register struct here *h;
642 for (h = inhere; h != NULL; h = h->h_next) {
643 if (h->h_iop && h->h_iop->io_name)
644 unlink(h->h_iop->io_name);
646 inhere = NULL;
649 /* unlink here temp files before a freearea(area) */
650 void
651 freehere(area)
652 int area;
654 register struct here *h, *hl;
656 hl = NULL;
657 for (h = acthere; h != NULL; h = h->h_next)
658 if (getarea((char *) h) >= area) {
659 if (h->h_iop->io_name != NULL)
660 unlink(h->h_iop->io_name);
661 if (hl == NULL)
662 acthere = h->h_next;
663 else
664 hl->h_next = h->h_next;
665 } else
666 hl = h;
669 void
670 tempname(tname)
671 char *tname;
673 static int inc;
674 register char *cp, *lp;
676 for (cp = tname, lp = "/tmp/shtm"; (*cp = *lp++) != '\0'; cp++)
678 lp = putn(getpid()*1000 + inc++);
679 for (; (*cp = *lp++) != '\0'; cp++)