|
|
1.1 root 1: /* Copyright (c) 1979 Regents of the University of California */
2: #include "sh.h"
3:
4: /*
5: * C Shell
6: */
7:
8: int globcnt;
9:
10: char *globchars = "`{[*?";
11:
12: char *gpath, *gpathp, *lastgpathp;
13: int globbed;
14: bool noglob;
15: bool nonomatch;
16: char *entp;
17: char **sortbas;
18:
19: char **
20: glob(v)
21: register char **v;
22: {
23: char agpath[160];
24: char *agargv[GAVSIZ];
25:
26: gpath = agpath; gpathp = gpath; *gpathp = 0;
27: lastgpathp = &gpath[sizeof agpath - 2];
28: ginit(agargv); globcnt = 0;
29: #ifdef GDEBUG
30: printf("glob entered: "); blkpr(v); printf("\n");
31: #endif
32: noglob = adrof("noglob") != 0;
33: nonomatch = adrof("nonomatch") != 0;
34: globcnt = noglob | nonomatch;
35: while (*v)
36: collect(*v++);
37: #ifdef GDEBUG
38: printf("glob done, globcnt=%d, gflag=%d: ", globcnt, gflag); blkpr(gargv); printf("\n");
39: #endif
40: if (globcnt == 0 && (gflag&1)) {
41: blkfree(gargv), gargv = 0;
42: return (0);
43: } else
44: return (gargv = copyblk(gargv));
45: }
46:
47: ginit(agargv)
48: char **agargv;
49: {
50:
51: agargv[0] = 0; gargv = agargv; sortbas = agargv; gargc = 0;
52: gnleft = NCARGS - 4;
53: }
54:
55: collect(as)
56: register char *as;
57: {
58: register int i;
59:
60: if (any('`', as)) {
61: #ifdef GDEBUG
62: printf("doing backp of %s\n", as);
63: #endif
64: dobackp(as, 0);
65: #ifdef GDEBUG
66: printf("backp done, acollect'ing\n");
67: #endif
68: for (i = 0; i < pargc; i++)
69: if (noglob)
70: Gcat(pargv[i], "");
71: else
72: acollect(pargv[i]);
73: if (pargv)
74: blkfree(pargv), pargv = 0;
75: #ifdef GDEBUG
76: printf("acollect done\n");
77: #endif
78: } else if (noglob)
79: Gcat(as, "");
80: else
81: acollect(as);
82: }
83:
84: acollect(as)
85: register char *as;
86: {
87: register int ogargc = gargc;
88:
89: gpathp = gpath; *gpathp = 0; globbed = 0;
90: expand(as);
91: if (gargc == ogargc) {
92: if (nonomatch)
93: Gcat(as, "");
94: } else
95: sort();
96: }
97:
98: sort()
99: {
100: register char **p1, **p2, *c;
101: char **Gvp = &gargv[gargc];
102:
103: p1 = sortbas;
104: while (p1 < Gvp-1) {
105: p2 = p1;
106: while (++p2 < Gvp)
107: if (strcmp(*p1, *p2) > 0)
108: c = *p1, *p1 = *p2, *p2 = c;
109: p1++;
110: }
111: sortbas = Gvp;
112: }
113:
114: expand(as)
115: char *as;
116: {
117: register char *cs;
118: register char *sgpathp, *oldcs;
119: struct stat stb;
120:
121: sgpathp = gpathp;
122: cs = as;
123: if (*cs == '~' && gpathp == gpath) {
124: addpath('~');
125: for (cs++; letter(*cs) || digit(*cs) || *cs == '-';)
126: addpath(*cs++);
127: if (!*cs || *cs == '/') {
128: if (gpathp != gpath + 1) {
129: *gpathp = 0;
130: if (gethdir(gpath + 1))
131: error("Unknown user: %s", gpath + 1);
132: strcpy(gpath, gpath + 1);
133: } else
134: strcpy(gpath, value("home"));
135: gpathp = strend(gpath);
136: }
137: }
138: while (!any(*cs, globchars)) {
139: if (*cs == 0) {
140: if (!globbed)
141: Gcat(gpath, "");
142: else if (stat(gpath, &stb) >= 0) {
143: Gcat(gpath, "");
144: globcnt++;
145: }
146: goto endit;
147: }
148: addpath(*cs++);
149: }
150: oldcs = cs;
151: while (cs > as && *cs != '/')
152: cs--, gpathp--;
153: if (*cs == '/')
154: cs++, gpathp++;
155: *gpathp = 0;
156: if (*oldcs == '{') {
157: execbrc(cs, 0);
158: return;
159: }
160: matchdir(cs);
161: endit:
162: gpathp = sgpathp;
163: *gpathp = 0;
164: }
165:
166: matchdir(pattern)
167: char *pattern;
168: {
169: struct stat stb;
170: struct direct dirbuf[BUFSIZ / sizeof (struct direct)];
171: char d_name[DIRSIZ+1];
172: register int dirf, cnt;
173:
174: dirf = open(gpath, 0);
175: if (dirf < 0) {
176: if (globbed)
177: return;
178: goto patherr;
179: }
180: if (fstat(dirf, &stb) < 0)
181: goto patherr;
182: if (!isdir(stb)) {
183: errno = ENOTDIR;
184: goto patherr;
185: }
186: while ((cnt = read(dirf, (char *) dirbuf, sizeof dirbuf)) >= sizeof dirbuf[0]) {
187: register struct direct *ep = dirbuf;
188:
189: for (cnt /= sizeof (struct direct); cnt > 0; cnt--, ep++) {
190: if (ep->d_ino == 0)
191: continue;
192: copdent(d_name, ep->d_name);
193: if (match(d_name, pattern)) {
194: Gcat(gpath, d_name);
195: globcnt++;
196: }
197: }
198: }
199: close(dirf);
200: return;
201:
202: patherr:
203: Perror(gpath);
204: }
205:
206: copdent(to, from)
207: register char *to, *from;
208: {
209: register int cnt = DIRSIZ;
210:
211: do
212: *to++ = *from++;
213: while (--cnt);
214: *to = 0;
215: }
216:
217: execbrc(p, s)
218: char *p, *s;
219: {
220: char restbuf[BUFSIZ + 2];
221: register char *pe, *pm, *pl;
222: int brclev = 0;
223: char *lm, savec, *sgpathp;
224:
225: for (lm = restbuf; *p != '{'; *lm++ = *p++)
226: continue;
227: for (pe = ++p; *pe; pe++)
228: switch (*pe) {
229:
230: case '{':
231: brclev++;
232: continue;
233: case '}':
234: if (brclev == 0)
235: goto pend;
236: brclev--;
237: continue;
238: case '[':
239: for (pe++; *pe && *pe != ']'; pe++)
240: continue;
241: if (!*pe)
242: error("Missing ]");
243: continue;
244:
245: }
246: pend:
247: if (brclev || !*pe)
248: error("Missing }");
249: for (pl = pm = p; pm <= pe; pm++)
250: switch (*pm) {
251:
252: case '{':
253: brclev++;
254: continue;
255: case '}':
256: if (brclev) {
257: brclev--;
258: continue;
259: }
260: goto doit;
261: case ',':
262: if (brclev)
263: continue;
264: doit:
265: savec = *pm;
266: *pm = 0;
267: strcpy(lm, pl);
268: strcat(restbuf, pe + 1);
269: *pm = savec;
270: if (s == 0) {
271: sgpathp = gpathp;
272: expand(restbuf);
273: gpathp = sgpathp;
274: *gpathp = 0;
275: } else if (amatch(s, restbuf))
276: return (1);
277: sort();
278: pl = pm + 1;
279: continue;
280: case '[':
281: for (pm++; *pm && *pm != ']'; pm++)
282: continue;
283: if (!*pm)
284: error("Missing ]");
285: continue;
286: }
287: return (0);
288: }
289:
290: match(s, p)
291: char *s, *p;
292: {
293: register int c;
294: register char *sentp;
295: char sglobbed = globbed;
296:
297: if (*s == '.' && *p != '.')
298: return (0);
299: sentp = entp;
300: entp = s;
301: c = amatch(s, p);
302: entp = sentp;
303: globbed = sglobbed;
304: return (c);
305: }
306:
307: amatch(s, p)
308: register char *s, *p;
309: {
310: register int scc;
311: int ok, lc;
312: char *sgpathp;
313: struct stat stb;
314: int c, cc;
315:
316: globbed = 1;
317: for (;;) {
318: scc = *s++ & TRIM;
319: switch (c = *p++) {
320:
321: case '{':
322: return (execbrc(p - 1, s - 1));
323:
324: case '[':
325: ok = 0;
326: lc = 077777;
327: while (cc = *p++) {
328: if (cc == ']') {
329: if (ok)
330: break;
331: return (0);
332: }
333: if (cc == '-') {
334: if (lc <= scc && scc <= *p++)
335: ok++;
336: } else
337: if (scc == (lc = cc))
338: ok++;
339: }
340: if (cc == 0)
341: error("Missing ]");
342: continue;
343:
344: case '*':
345: if (!*p)
346: return (1);
347: if (*p == '/') {
348: p++;
349: goto slash;
350: }
351: for (s--; *s; s++)
352: if (amatch(s, p))
353: return (1);
354: return (0);
355:
356: case 0:
357: return (scc == 0);
358:
359: default:
360: if (c != scc)
361: return (0);
362: continue;
363:
364: case '?':
365: if (scc == 0)
366: return (0);
367: continue;
368:
369: case '/':
370: if (scc)
371: return (0);
372: slash:
373: s = entp;
374: sgpathp = gpathp;
375: while (*s)
376: addpath(*s++);
377: addpath('/');
378: if (stat(gpath, &stb) == 0 && isdir(stb))
379: if (*p == 0) {
380: Gcat(gpath, "");
381: globcnt++;
382: } else
383: expand(p);
384: gpathp = sgpathp;
385: *gpathp = 0;
386: return (0);
387: }
388: }
389: }
390:
391: Gmatch(s, p)
392: register char *s, *p;
393: {
394: register int scc;
395: int ok, lc;
396: int c, cc;
397:
398: for (;;) {
399: scc = *s++ & TRIM;
400: switch (c = *p++) {
401:
402: case '[':
403: ok = 0;
404: lc = 077777;
405: while (cc = *p++) {
406: if (cc == ']') {
407: if (ok)
408: break;
409: return (0);
410: }
411: if (cc == '-') {
412: if (lc <= scc && scc <= *p++)
413: ok++;
414: } else
415: if (scc == (lc = cc))
416: ok++;
417: }
418: if (cc == 0)
419: bferr("Missing ]");
420: continue;
421:
422: case '*':
423: if (!*p)
424: return (1);
425: for (s--; *s; s++)
426: if (Gmatch(s, p))
427: return (1);
428: return (0);
429:
430: case 0:
431: return (scc == 0);
432:
433: default:
434: if ((c & TRIM) != scc)
435: return (0);
436: continue;
437:
438: case '?':
439: if (scc == 0)
440: return (0);
441: continue;
442:
443: }
444: }
445: }
446:
447: Gcat(s1, s2)
448: register char *s1, *s2;
449: {
450:
451: gnleft -= strlen(s1) + strlen(s2) + 1;
452: if (gnleft <= 0 || ++gargc >= GAVSIZ)
453: error("Arguments too long");
454: gargv[gargc] = 0;
455: gargv[gargc - 1] = strspl(s1, s2);
456: }
457:
458: addpath(c)
459: char c;
460: {
461:
462: if (gpathp >= lastgpathp)
463: error("Pathname too long");
464: *gpathp++ = c;
465: *gpathp = 0;
466: }
467:
468: rscan(t, f)
469: register char **t;
470: int (*f)();
471: {
472: register char *p, c;
473:
474: while (p = *t++) {
475: if (f == tglob)
476: if (*p == '~')
477: gflag |= 2;
478: else if (eq(p, "{") || eq(p, "{}"))
479: continue;
480: while (c = *p++)
481: (*f)(c);
482: }
483: }
484:
485: scan(t, f)
486: register char **t;
487: int (*f)();
488: {
489: register char *p, c;
490:
491: while (p = *t++)
492: while (c = *p)
493: *p++ = (*f)(c);
494: }
495:
496: tglob(c)
497: register char c;
498: {
499:
500: if (any(c, globchars))
501: gflag |= c == '{' ? 2 : 1;
502: return (c);
503: }
504:
505: trim(c)
506: char c;
507: {
508:
509: return (c & TRIM);
510: }
511:
512: char *
513: globone(str)
514: register char *str;
515: {
516: char *gv[2];
517: register char **gvp;
518: register char *cp;
519:
520: gv[0] = str;
521: gv[1] = 0;
522: gflag = 0;
523: rscan(gv, tglob);
524: if (gflag) {
525: gvp = glob(gv);
526: if (gvp == 0) {
527: setname(str);
528: bferr("No match");
529: }
530: cp = *gvp++;
531: if (cp == 0)
532: cp = "";
533: else if (*gvp) {
534: setname(str);
535: bferr("Ambiguous");
536: }
537: /*
538: if (cp == 0 || *gvp) {
539: setname(str);
540: bferr(cp ? "Ambiguous" : "No output");
541: }
542: */
543: xfree(gargv); gargv = 0;
544: } else {
545: scan(gv, trim);
546: cp = savestr(gv[0]);
547: }
548: return (cp);
549: }
550:
551: /*
552: * Command substitute cp. If literal, then this is
553: * a substitution from a << redirection, and so we should
554: * not crunch blanks and tabs, separating words only at newlines.
555: */
556: char **
557: dobackp(cp, literal)
558: char *cp;
559: bool literal;
560: {
561: register char *lp, *rp;
562: char *ep;
563: char word[BUFSIZ];
564: char *apargv[GAVSIZ + 2];
565:
566: if (pargv) {
567: abort();
568: blkfree(pargv);
569: }
570: pargv = apargv;
571: pargv[0] = NOSTR;
572: pargcp = pargs = word;
573: pargc = 0;
574: pnleft = BUFSIZ - 4;
575: for (;;) {
576: for (lp = cp; *lp != '`'; lp++) {
577: if (*lp == 0) {
578: if (pargcp != pargs)
579: pword();
580: #ifdef GDEBUG
581: printf("leaving dobackp\n");
582: #endif
583: return (pargv = copyblk(pargv));
584: }
585: psave(*lp);
586: }
587: lp++;
588: for (rp = lp; *rp && *rp != '`'; rp++)
589: if (*rp == '\\') {
590: rp++;
591: if (!*rp)
592: goto oops;
593: }
594: if (!*rp)
595: oops:
596: error("Unmatched `");
597: ep = savestr(lp);
598: ep[rp - lp] = 0;
599: backeval(ep, literal);
600: #ifdef GDEBUG
601: printf("back from backeval\n");
602: #endif
603: cp = rp + 1;
604: }
605: }
606:
607: backeval(cp, literal)
608: char *cp;
609: bool literal;
610: {
611: int pvec[2], pid;
612: int quoted = (literal || (cp[0] & QUOTE)) ? QUOTE : 0;
613: int (*oldint)();
614: char ibuf[BUFSIZ];
615: register int icnt = 0, c;
616: register char *ip;
617: bool hadnl = 0;
618:
619: oldint = signal(SIGINT, SIG_IGN);
620: mypipe(pvec);
621: pid = fork();
622: if (pid < 0)
623: bferr("No more processes");
624: if (pid == 0) {
625: struct wordent paraml;
626: struct command *t;
627:
628: child++;
629: signal(SIGINT, oldint);
630: close(pvec[0]);
631: dmove(pvec[1], 1);
632: dmove(SHDIAG, 2);
633: initdesc();
634: arginp = cp;
635: while (*cp)
636: *cp++ &= TRIM;
637: lex(¶ml);
638: if (err)
639: error(err);
640: alias(¶ml);
641: t = syntax(paraml.next, ¶ml);
642: if (err)
643: error(err);
644: if (t)
645: t->t_dflg |= FPAR;
646: execute(t);
647: exitstat();
648: }
649: cadd(pid, "``");
650: xfree(cp);
651: signal(SIGINT, oldint);
652: close(pvec[1]);
653: do {
654: int cnt = 0;
655: for (;;) {
656: if (icnt == 0) {
657: ip = ibuf;
658: icnt = read(pvec[0], ip, BUFSIZ);
659: if (icnt <= 0) {
660: c = -1;
661: break;
662: }
663: }
664: if (hadnl)
665: break;
666: --icnt;
667: c = (*ip++ & TRIM);
668: if (c == 0)
669: break;
670: if (c == '\n') {
671: /*
672: * Continue around the loop one
673: * more time, so that we can eat
674: * the last newline without terminating
675: * this word.
676: */
677: hadnl = 1;
678: continue;
679: }
680: if (!quoted && (c == ' ' || c == '\t'))
681: break;
682: cnt++;
683: psave(c | quoted);
684: }
685: /*
686: * Unless at end-of-file, we will form a new word
687: * here if there were characters in the word, or in
688: * any case when we take text literally. If
689: * we didn't make empty words here when literal was
690: * set then we would lose blank lines.
691: */
692: if (c != -1 && (cnt || literal))
693: pword();
694: hadnl = 0;
695: } while (c >= 0);
696: #ifdef GDEBUG
697: printf("done in backeval, pvec: %d %d\n", pvec[0], pvec[1]);
698: printf("also c = %c <%o>\n", c, c);
699: #endif
700: close(pvec[0]);
701: pwait(pid);
702: }
703:
704: psave(c)
705: char c;
706: {
707:
708: if (--pnleft <= 0)
709: error("Word too long");
710: *pargcp++ = c;
711: }
712:
713: pword()
714: {
715:
716: psave(0);
717: if (pargc == GAVSIZ)
718: error("Too many words from ``");
719: pargv[pargc++] = savestr(pargs);
720: pargv[pargc] = NOSTR;
721: #ifdef GDEBUG
722: printf("got word %s\n", pargv[pargc-1]);
723: #endif
724: pargcp = pargs;
725: pnleft = BUFSIZ - 4;
726: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.