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
getc(ec)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
unget(c)53 unget(c)
54 int c;
55 {
56 if (e.iop >= e.iobase)
57 e.iop->peekc = c;
58 }
59
60 int
eofc()61 eofc()
62
63 {
64 return e.iop < e.iobase || (e.iop->peekc == 0 && e.iop->prev == 0);
65 }
66
67 int
readc()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
ioecho(c)109 ioecho(c)
110 char c;
111 {
112 if (flag['v'])
113 write(2, &c, sizeof c);
114 }
115
116 void
pushio(argp,fn)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 *
setbase(ip)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
nlchar(ap)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
wdchar(ap)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
dolchar(ap)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
xxchar(ap)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
strchar(ap)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
qstrchar(ap)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
filechar(ap)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
herechar(ap)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
gravechar(ap,iop)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
qgravechar(ap,iop)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
linechar(ap)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
prs(s)387 prs(s)
388 register char *s;
389 {
390 if (*s)
391 write(2, s, strlen(s));
392 }
393
394 void
putc(c)395 putc(c)
396 char c;
397 {
398 write(2, &c, sizeof c);
399 }
400
401 void
prn(u)402 prn(u)
403 unsigned u;
404 {
405 prs(itoa(u, 0));
406 }
407
408 void
closef(i)409 closef(i)
410 register int i;
411 {
412 if (i > 2)
413 close(i);
414 }
415
416 void
closeall()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
remap(fd)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
openpipe(pv)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
closepipe(pv)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
markhere(s,iop)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
gethere()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
readhere(name,s,ec)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
herein(hname,xdoll)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
scraphere()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
freehere(area)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
tempname(tname)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 }
676