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