xref: /trueos/release/picobsd/tinyware/msh/sh4.c (revision 176502fbae082810e200c9fedfb9b7cfe31a0fdd)
1 #define Extern extern
2 #include <sys/types.h>
3 #include <sys/stat.h>
4 #include <dirent.h>
5 #include <limits.h>
6 #include <signal.h>
7 #define _NSIG NSIG
8 #include <errno.h>
9 #include <setjmp.h>
10 #include "sh.h"
11 
12 /* -------- eval.c -------- */
13 /* #include "sh.h" */
14 /* #include "word.h" */
15 
16 /*
17  * ${}
18  * `command`
19  * blank interpretation
20  * quoting
21  * glob
22  */
23 
24 _PROTOTYPE(static int expand, (char *cp, struct wdblock **wbp, int f ));
25 _PROTOTYPE(static char *blank, (int f ));
26 _PROTOTYPE(static int dollar, (int quoted ));
27 _PROTOTYPE(static int grave, (int quoted ));
28 _PROTOTYPE(void globname, (char *we, char *pp ));
29 _PROTOTYPE(static char *generate, (char *start1, char *end1, char *middle, char *end ));
30 _PROTOTYPE(static int anyspcl, (struct wdblock *wb ));
31 _PROTOTYPE(static int xstrcmp, (char *p1, char *p2 ));
32 _PROTOTYPE(void glob0, (char *a0, unsigned int a1, int a2, int (*a3)(char *, char *)));
33 _PROTOTYPE(void glob1, (char *base, char *lim ));
34 _PROTOTYPE(void glob2, (char *i, char *j ));
35 _PROTOTYPE(void glob3, (char *i, char *j, char *k ));
36 _PROTOTYPE(char *memcopy, (char *ato, char *from, int nb ));
37 
38 char **
eval(ap,f)39 eval(ap, f)
40 register char **ap;
41 int f;
42 {
43 	struct wdblock *wb;
44 	char **wp;
45 	char **wf;
46 	jmp_buf ev;
47 
48 	wp = NULL;
49 	wb = NULL;
50 	wf = NULL;
51 	if (newenv(setjmp(errpt = ev)) == 0) {
52 		while (*ap && isassign(*ap))
53 			expand(*ap++, &wb, f & ~DOGLOB);
54 		if (flag['k']) {
55 			for (wf = ap; *wf; wf++) {
56 				if (isassign(*wf))
57 					expand(*wf, &wb, f & ~DOGLOB);
58 			}
59 		}
60 		for (wb = addword((char *)0, wb); *ap; ap++) {
61 			if (!flag['k'] || !isassign(*ap))
62 				expand(*ap, &wb, f & ~DOKEY);
63 		}
64 		wb = addword((char *)0, wb);
65 		wp = getwords(wb);
66 		quitenv();
67 	} else
68 		gflg = 1;
69 	return(gflg? (char **)NULL: wp);
70 }
71 
72 /*
73  * Make the exported environment from the exported
74  * names in the dictionary. Keyword assignments
75  * will already have been done.
76  */
77 char **
makenv()78 makenv()
79 
80 {
81 	register struct wdblock *wb;
82 	register struct var *vp;
83 
84 	wb = NULL;
85 	for (vp = vlist; vp; vp = vp->next)
86 		if (vp->status & EXPORT)
87 			wb = addword(vp->name, wb);
88 	wb = addword((char *)0, wb);
89 	return(getwords(wb));
90 }
91 
92 char *
evalstr(cp,f)93 evalstr(cp, f)
94 register char *cp;
95 int f;
96 {
97 	struct wdblock *wb;
98 
99 	wb = NULL;
100 	if (expand(cp, &wb, f)) {
101 		if (wb == NULL || wb->w_nword == 0 || (cp = wb->w_words[0]) == NULL)
102 			cp = "";
103 		DELETE(wb);
104 	} else
105 		cp = NULL;
106 	return(cp);
107 }
108 
109 static int
expand(cp,wbp,f)110 expand(cp, wbp, f)
111 register char *cp;
112 register struct wdblock **wbp;
113 int f;
114 {
115 	jmp_buf ev;
116 
117 	gflg = 0;
118 	if (cp == NULL)
119 		return(0);
120 	if (!anys("$`'\"", cp) &&
121 	    !anys(ifs->value, cp) &&
122 	    ((f&DOGLOB)==0 || !anys("[*?", cp))) {
123 		cp = strsave(cp, areanum);
124 		if (f & DOTRIM)
125 			unquote(cp);
126 		*wbp = addword(cp, *wbp);
127 		return(1);
128 	}
129 	if (newenv(setjmp(errpt = ev)) == 0) {
130 		PUSHIO(aword, cp, strchar);
131 		e.iobase = e.iop;
132 		while ((cp = blank(f)) && gflg == 0) {
133 			e.linep = cp;
134 			cp = strsave(cp, areanum);
135 			if ((f&DOGLOB) == 0) {
136 				if (f & DOTRIM)
137 					unquote(cp);
138 				*wbp = addword(cp, *wbp);
139 			} else
140 				*wbp = glob(cp, *wbp);
141 		}
142 		quitenv();
143 	} else
144 		gflg = 1;
145 	return(gflg == 0);
146 }
147 
148 /*
149  * Blank interpretation and quoting
150  */
151 static char *
blank(f)152 blank(f)
153 int f;
154 {
155 	register c, c1;
156 	register char *sp;
157 	int scanequals, foundequals;
158 
159 	sp = e.linep;
160 	scanequals = f & DOKEY;
161 	foundequals = 0;
162 
163 loop:
164 	switch (c = subgetc('"', foundequals)) {
165 	case 0:
166 		if (sp == e.linep)
167 			return(0);
168 		*e.linep++ = 0;
169 		return(sp);
170 
171 	default:
172 		if (f & DOBLANK && any(c, ifs->value))
173 			goto loop;
174 		break;
175 
176 	case '"':
177 	case '\'':
178 		scanequals = 0;
179 		if (INSUB())
180 			break;
181 		for (c1 = c; (c = subgetc(c1, 1)) != c1;) {
182 			if (c == 0)
183 				break;
184 			if (c == '\'' || !any(c, "$`\""))
185 				c |= QUOTE;
186 			*e.linep++ = c;
187 		}
188 		c = 0;
189 	}
190 	unget(c);
191 	if (!letter(c))
192 		scanequals = 0;
193 	for (;;) {
194 		c = subgetc('"', foundequals);
195 		if (c == 0 ||
196 		    f & (DOBLANK && any(c, ifs->value)) ||
197 		    (!INSUB() && any(c, "\"'"))) {
198 		        scanequals = 0;
199 			unget(c);
200 			if (any(c, "\"'"))
201 				goto loop;
202 			break;
203 		}
204 		if (scanequals)
205 			if (c == '=') {
206 				foundequals = 1;
207 				scanequals  = 0;
208 			}
209 			else if (!letnum(c))
210 				scanequals = 0;
211 		*e.linep++ = c;
212 	}
213 	*e.linep++ = 0;
214 	return(sp);
215 }
216 
217 /*
218  * Get characters, substituting for ` and $
219  */
220 int
subgetc(ec,quoted)221 subgetc(ec, quoted)
222 register char ec;
223 int quoted;
224 {
225 	register char c;
226 
227 again:
228 	c = getc(ec);
229 	if (!INSUB() && ec != '\'') {
230 		if (c == '`') {
231 			if (grave(quoted) == 0)
232 				return(0);
233 			e.iop->task = XGRAVE;
234 			goto again;
235 		}
236 		if (c == '$' && (c = dollar(quoted)) == 0) {
237 			e.iop->task = XDOLL;
238 			goto again;
239 		}
240 	}
241 	return(c);
242 }
243 
244 /*
245  * Prepare to generate the string returned by ${} substitution.
246  */
247 static int
dollar(quoted)248 dollar(quoted)
249 int quoted;
250 {
251 	int otask;
252 	struct io *oiop;
253 	char *dolp;
254 	register char *s, c, *cp;
255 	struct var *vp;
256 
257 	c = readc();
258 	s = e.linep;
259 	if (c != '{') {
260 		*e.linep++ = c;
261 		if (letter(c)) {
262 			while ((c = readc())!=0 && letnum(c))
263 				if (e.linep < elinep)
264 					*e.linep++ = c;
265 			unget(c);
266 		}
267 		c = 0;
268 	} else {
269 		oiop = e.iop;
270 		otask = e.iop->task;
271 		e.iop->task = XOTHER;
272 		while ((c = subgetc('"', 0))!=0 && c!='}' && c!='\n')
273 			if (e.linep < elinep)
274 				*e.linep++ = c;
275 		if (oiop == e.iop)
276 			e.iop->task = otask;
277 		if (c != '}') {
278 			err("unclosed ${");
279 			gflg++;
280 			return(c);
281 		}
282 	}
283 	if (e.linep >= elinep) {
284 		err("string in ${} too long");
285 		gflg++;
286 		e.linep -= 10;
287 	}
288 	*e.linep = 0;
289 	if (*s)
290 		for (cp = s+1; *cp; cp++)
291 			if (any(*cp, "=-+?")) {
292 				c = *cp;
293 				*cp++ = 0;
294 				break;
295 			}
296 	if (s[1] == 0 && (*s == '*' || *s == '@')) {
297 		if (dolc > 1) {
298 			/* currently this does not distinguish $* and $@ */
299 			/* should check dollar */
300 			e.linep = s;
301 			PUSHIO(awordlist, dolv+1, dolchar);
302 			return(0);
303 		} else {	/* trap the nasty ${=} */
304 			s[0] = '1';
305 			s[1] = 0;
306 		}
307 	}
308 	vp = lookup(s);
309 	if ((dolp = vp->value) == null) {
310 		switch (c) {
311 		case '=':
312 			if (digit(*s)) {
313 				err("cannot use ${...=...} with $n");
314 				gflg++;
315 				break;
316 			}
317 			setval(vp, cp);
318 			dolp = vp->value;
319 			break;
320 
321 		case '-':
322 			dolp = strsave(cp, areanum);
323 			break;
324 
325 		case '?':
326 			if (*cp == 0) {
327 				prs("missing value for ");
328 				err(s);
329 			} else
330 				err(cp);
331 			gflg++;
332 			break;
333 		}
334 	} else if (c == '+')
335 		dolp = strsave(cp, areanum);
336 	if (flag['u'] && dolp == null) {
337 		prs("unset variable: ");
338 		err(s);
339 		gflg++;
340 	}
341 	e.linep = s;
342 	PUSHIO(aword, dolp, quoted ? qstrchar : strchar);
343 	return(0);
344 }
345 
346 /*
347  * Run the command in `...` and read its output.
348  */
349 static int
grave(quoted)350 grave(quoted)
351 int quoted;
352 {
353 	register char *cp;
354 	register int i;
355 	int pf[2];
356 
357 	for (cp = e.iop->argp->aword; *cp != '`'; cp++)
358 		if (*cp == 0) {
359 			err("no closing `");
360 			return(0);
361 		}
362 	if (openpipe(pf) < 0)
363 		return(0);
364 	if ((i = fork()) == -1) {
365 		closepipe(pf);
366 		err("try again");
367 		return(0);
368 	}
369 	if (i != 0) {
370 		e.iop->argp->aword = ++cp;
371 		close(pf[1]);
372 		PUSHIO(afile, remap(pf[0]), quoted? qgravechar: gravechar);
373 		return(1);
374 	}
375 	*cp = 0;
376 	/* allow trapped signals */
377 	for (i=0; i<=_NSIG; i++)
378 		if (ourtrap[i] && signal(i, SIG_IGN) != SIG_IGN)
379 			signal(i, SIG_DFL);
380 	dup2(pf[1], 1);
381 	closepipe(pf);
382 	flag['e'] = 0;
383 	flag['v'] = 0;
384 	flag['n'] = 0;
385 	cp = strsave(e.iop->argp->aword, 0);
386 	areanum = 1;
387 	freehere(areanum);
388 	freearea(areanum);	/* free old space */
389 	e.oenv = NULL;
390 	e.iop = (e.iobase = iostack) - 1;
391 	unquote(cp);
392 	talking = 0;
393 	PUSHIO(aword, cp, nlchar);
394 	onecommand();
395 	exit(1);
396 }
397 
398 char *
unquote(as)399 unquote(as)
400 register char *as;
401 {
402 	register char *s;
403 
404 	if ((s = as) != NULL)
405 		while (*s)
406 			*s++ &= ~QUOTE;
407 	return(as);
408 }
409 
410 /* -------- glob.c -------- */
411 /* #include "sh.h" */
412 
413 /*
414  * glob
415  */
416 
417 #define	scopy(x) strsave((x), areanum)
418 #define	BLKSIZ	512
419 #define	NDENT	((BLKSIZ+sizeof(struct dirent)-1)/sizeof(struct dirent))
420 
421 static	struct wdblock	*cl, *nl;
422 static	char	spcl[] = "[?*";
423 
424 struct wdblock *
glob(cp,wb)425 glob(cp, wb)
426 char *cp;
427 struct wdblock *wb;
428 {
429 	register i;
430 	register char *pp;
431 
432 	if (cp == 0)
433 		return(wb);
434 	i = 0;
435 	for (pp = cp; *pp; pp++)
436 		if (any(*pp, spcl))
437 			i++;
438 		else if (!any(*pp & ~QUOTE, spcl))
439 			*pp &= ~QUOTE;
440 	if (i != 0) {
441 		for (cl = addword(scopy(cp), (struct wdblock *)0); anyspcl(cl); cl = nl) {
442 			nl = newword(cl->w_nword*2);
443 			for(i=0; i<cl->w_nword; i++) { /* for each argument */
444 				for (pp = cl->w_words[i]; *pp; pp++)
445 					if (any(*pp, spcl)) {
446 						globname(cl->w_words[i], pp);
447 						break;
448 					}
449 				if (*pp == '\0')
450 					nl = addword(scopy(cl->w_words[i]), nl);
451 			}
452 			for(i=0; i<cl->w_nword; i++)
453 				DELETE(cl->w_words[i]);
454 			DELETE(cl);
455 		}
456 		for(i=0; i<cl->w_nword; i++)
457 			unquote(cl->w_words[i]);
458 		glob0((char *)cl->w_words, cl->w_nword, sizeof(char *), xstrcmp);
459 		if (cl->w_nword) {
460 			for (i=0; i<cl->w_nword; i++)
461 				wb = addword(cl->w_words[i], wb);
462 			DELETE(cl);
463 			return(wb);
464 		}
465 	}
466 	wb = addword(unquote(cp), wb);
467 	return(wb);
468 }
469 
470 void
globname(we,pp)471 globname(we, pp)
472 char *we;
473 register char *pp;
474 {
475 	register char *np, *cp;
476 	char *name, *gp, *dp;
477 	int dn, j, n, k;
478 	DIR *dirp;
479 	struct dirent *de;
480 	char dname[NAME_MAX+1];
481 	struct stat dbuf;
482 
483 	for (np = we; np != pp; pp--)
484 		if (pp[-1] == '/')
485 			break;
486 	for (dp = cp = space((int)(pp-np)+3); np < pp;)
487 		*cp++ = *np++;
488 	*cp++ = '.';
489 	*cp = '\0';
490 	for (gp = cp = space(strlen(pp)+1); *np && *np != '/';)
491 		*cp++ = *np++;
492 	*cp = '\0';
493 	dirp = opendir(dp);
494 	if (dirp == 0) {
495 		DELETE(dp);
496 		DELETE(gp);
497 		return;
498 	}
499 	dname[NAME_MAX] = '\0';
500 	while ((de=readdir(dirp))!=NULL) {
501 		/* XXX Hmmm... What this could be? (abial) */
502 		/*
503 		if (ent[j].d_ino == 0)
504 			continue;
505 		*/
506 		strncpy(dname, de->d_name, NAME_MAX);
507 			if (dname[0] == '.')
508 				if (*gp != '.')
509 					continue;
510 			for(k=0; k<NAME_MAX; k++)
511 				if (any(dname[k], spcl))
512 					dname[k] |= QUOTE;
513 			if (gmatch(dname, gp)) {
514 				name = generate(we, pp, dname, np);
515 				if (*np && !anys(np, spcl)) {
516 					if (stat(name,&dbuf)) {
517 						DELETE(name);
518 						continue;
519 					}
520 				}
521 				nl = addword(name, nl);
522 			}
523 	}
524 	closedir(dirp);
525 	DELETE(dp);
526 	DELETE(gp);
527 }
528 
529 /*
530  * generate a pathname as below.
531  * start..end1 / middle end
532  * the slashes come for free
533  */
534 static char *
generate(start1,end1,middle,end)535 generate(start1, end1, middle, end)
536 char *start1;
537 register char *end1;
538 char *middle, *end;
539 {
540 	char *p;
541 	register char *op, *xp;
542 
543 	p = op = space((int)(end1-start1)+strlen(middle)+strlen(end)+2);
544 	for (xp = start1; xp != end1;)
545 		*op++ = *xp++;
546 	for (xp = middle; (*op++ = *xp++) != '\0';)
547 		;
548 	op--;
549 	for (xp = end; (*op++ = *xp++) != '\0';)
550 		;
551 	return(p);
552 }
553 
554 static int
anyspcl(wb)555 anyspcl(wb)
556 register struct wdblock *wb;
557 {
558 	register i;
559 	register char **wd;
560 
561 	wd = wb->w_words;
562 	for (i=0; i<wb->w_nword; i++)
563 		if (anys(spcl, *wd++))
564 			return(1);
565 	return(0);
566 }
567 
568 static int
xstrcmp(p1,p2)569 xstrcmp(p1, p2)
570 char *p1, *p2;
571 {
572 	return(strcmp(*(char **)p1, *(char **)p2));
573 }
574 
575 /* -------- word.c -------- */
576 /* #include "sh.h" */
577 /* #include "word.h" */
578 
579 #define	NSTART	16	/* default number of words to allow for initially */
580 
581 struct wdblock *
newword(nw)582 newword(nw)
583 register int nw;
584 {
585 	register struct wdblock *wb;
586 
587 	wb = (struct wdblock *) space(sizeof(*wb) + nw*sizeof(char *));
588 	wb->w_bsize = nw;
589 	wb->w_nword = 0;
590 	return(wb);
591 }
592 
593 struct wdblock *
addword(wd,wb)594 addword(wd, wb)
595 char *wd;
596 register struct wdblock *wb;
597 {
598 	register struct wdblock *wb2;
599 	register nw;
600 
601 	if (wb == NULL)
602 		wb = newword(NSTART);
603 	if ((nw = wb->w_nword) >= wb->w_bsize) {
604 		wb2 = newword(nw * 2);
605 		memcopy((char *)wb2->w_words, (char *)wb->w_words, nw*sizeof(char *));
606 		wb2->w_nword = nw;
607 		DELETE(wb);
608 		wb = wb2;
609 	}
610 	wb->w_words[wb->w_nword++] = wd;
611 	return(wb);
612 }
613 
614 char **
getwords(wb)615 getwords(wb)
616 register struct wdblock *wb;
617 {
618 	register char **wd;
619 	register nb;
620 
621 	if (wb == NULL)
622 		return((char **)NULL);
623 	if (wb->w_nword == 0) {
624 		DELETE(wb);
625 		return((char **)NULL);
626 	}
627 	wd = (char **) space(nb = sizeof(*wd) * wb->w_nword);
628 	memcopy((char *)wd, (char *)wb->w_words, nb);
629 	DELETE(wb);	/* perhaps should done by caller */
630 	return(wd);
631 }
632 
633 _PROTOTYPE(int (*func), (char *, char *));
634 int	globv;
635 
636 void
glob0(a0,a1,a2,a3)637 glob0(a0, a1, a2, a3)
638 char *a0;
639 unsigned a1;
640 int a2;
641 _PROTOTYPE(int (*a3), (char *, char *));
642 {
643 	func = a3;
644 	globv = a2;
645 	glob1(a0, a0 + a1 * a2);
646 }
647 
648 void
glob1(base,lim)649 glob1(base, lim)
650 char *base, *lim;
651 {
652 	register char *i, *j;
653 	int v2;
654 	char *lptr, *hptr;
655 	int c;
656 	unsigned n;
657 
658 
659 	v2 = globv;
660 
661 top:
662 	if ((n=(int)(lim-base)) <= v2)
663 		return;
664 	n = v2 * (n / (2*v2));
665 	hptr = lptr = base+n;
666 	i = base;
667 	j = lim-v2;
668 	for(;;) {
669 		if (i < lptr) {
670 			if ((c = (*func)(i, lptr)) == 0) {
671 				glob2(i, lptr -= v2);
672 				continue;
673 			}
674 			if (c < 0) {
675 				i += v2;
676 				continue;
677 			}
678 		}
679 
680 begin:
681 		if (j > hptr) {
682 			if ((c = (*func)(hptr, j)) == 0) {
683 				glob2(hptr += v2, j);
684 				goto begin;
685 			}
686 			if (c > 0) {
687 				if (i == lptr) {
688 					glob3(i, hptr += v2, j);
689 					i = lptr += v2;
690 					goto begin;
691 				}
692 				glob2(i, j);
693 				j -= v2;
694 				i += v2;
695 				continue;
696 			}
697 			j -= v2;
698 			goto begin;
699 		}
700 
701 
702 		if (i == lptr) {
703 			if (lptr-base >= lim-hptr) {
704 				glob1(hptr+v2, lim);
705 				lim = lptr;
706 			} else {
707 				glob1(base, lptr);
708 				base = hptr+v2;
709 			}
710 			goto top;
711 		}
712 
713 
714 		glob3(j, lptr -= v2, i);
715 		j = hptr -= v2;
716 	}
717 }
718 
719 void
glob2(i,j)720 glob2(i, j)
721 char *i, *j;
722 {
723 	register char *index1, *index2, c;
724 	int m;
725 
726 	m = globv;
727 	index1 = i;
728 	index2 = j;
729 	do {
730 		c = *index1;
731 		*index1++ = *index2;
732 		*index2++ = c;
733 	} while(--m);
734 }
735 
736 void
glob3(i,j,k)737 glob3(i, j, k)
738 char *i, *j, *k;
739 {
740 	register char *index1, *index2, *index3;
741 	int c;
742 	int m;
743 
744 	m = globv;
745 	index1 = i;
746 	index2 = j;
747 	index3 = k;
748 	do {
749 		c = *index1;
750 		*index1++ = *index3;
751 		*index3++ = *index2;
752 		*index2++ = c;
753 	} while(--m);
754 }
755 
756 char *
memcopy(ato,from,nb)757 memcopy(ato, from, nb)
758 register char *ato, *from;
759 register int nb;
760 {
761 	register char *to;
762 
763 	to = ato;
764 	while (--nb >= 0)
765 		*to++ = *from++;
766 	return(ato);
767 }
768