|
|
1.1 root 1: /* @(#)xec.c 1.8 */
2: /*
3: *
4: * UNIX shell
5: *
6: * Bell Telephone Laboratories
7: *
8: */
9:
10:
11: #include "defs.h"
12: #include <errno.h>
13: #include "sym.h"
14: #include <sys/types.h>
15: #include <sys/stat.h>
16:
17: static int parent;
18:
19: /* ======== command execution ========*/
20:
21:
22: execute(argt, exec_link, errorflg, pf1, pf2)
23: struct trenod *argt;
24: int *pf1, *pf2;
25: {
26: /*
27: * `stakbot' is preserved by this routine
28: */
29: register struct trenod *t;
30: char *sav = savstak();
31:
32: sigchk();
33: if (!errorflg)
34: flags &= ~errflg;
35:
36: if ((t = argt) && execbrk == 0)
37: {
38: register int treeflgs;
39: int type;
40: register char **com;
41: int linked;
42: int execflg;
43:
44: linked = exec_link >> 1;
45: execflg = exec_link & 01;
46:
47: treeflgs = t->tretyp;
48: type = treeflgs & COMMSK;
49:
50: switch (type)
51: {
52: case TFND:
53: {
54: struct fndnod *f = (struct fndnod *)t;
55: struct namnod *n = lookup(f->fndnam);
56:
57: exitval = 0;
58:
59: if (special(n->namid))
60: failed(n->namid, badfname);
61: if (!(n->namflg & N_ENVNAM))
62: free_val(&n->namval);
63:
64: if (funcnt)
65: f->fndval->tretyp++;
66:
67: n->namval.val = (char *)f->fndval;
68: n->namval.flg = N_FUNCTN;
69: if (flags & exportflg)
70: attrib(n, N_EXPORT);
71: break;
72: }
73:
74: case TCOM:
75: {
76: char *a1;
77: int argn, internal;
78: struct argnod *schain = gchain;
79: struct ionod *io = t->treio;
80: struct namnod *n;
81: exitval = 0;
82:
83: gchain = 0;
84: argn = getarg(t);
85: com = scan(argn);
86: a1 = com[1];
87: gchain = schain;
88:
89: if((n = findnam(com[0])) && !(n->namval.flg & N_FUNCTN))
90: n = 0;
91: if ((internal = syslook(com[0], commands, no_commands)) || argn == 0)
92: setlist(comptr(t)->comset, 0);
93:
94: if (argn && (flags&noexec) == 0)
95: {
96: /* print command if execpr */
97:
98: if (flags & execpr)
99: execprint(com);
100:
101: if (n) /* function */
102: {
103: short index;
104:
105: funcnt++;
106: index = initio(io, 1);
107: pushargs(com);
108: execute((struct trenod *)(n->namval.val), exec_link, errorflg, pf1, pf2);
109: execbrk = 0;
110: restore(index);
111: popargs();
112: funcnt--;
113:
114: break;
115: }
116:
117: else if (internal)
118: {
119: short index;
120: index = initio(io, (internal != SYSEXEC));
121:
122: isbltin:
123: switch (internal)
124: {
125: case SYSBLTIN:
126: if (--argn > 0)
127: {
128: com++;
129: a1 = com[1];
130: if (internal = syslook(com[0], commands, no_commands))
131: goto isbltin;
132: failed(*com, notbltin);
133: }
134: break;
135:
136: case SYSDOT:
137: if (a1)
138: {
139: register int f;
140:
141: if ((f = pathopen(getpath(a1), a1)) < 0)
142: failed(a1, notfound);
143: else
144: execexp(0, f);
145: }
146: break;
147:
148: case SYSTIMES:
149: {
150: long int t[4];
151:
152: times(t);
153: prt(t[2]);
154: prc_buff(SP);
155: prt(t[3]);
156: prc_buff(NL);
157: }
158: break;
159:
160: case SYSEXIT:
161: flags |= forked; /* force exit */
162: exitsh(a1 ? stoi(a1) : retval);
163:
164: case SYSNULL:
165: io = 0;
166: break;
167:
168: case SYSCONT:
169: if (loopcnt)
170: {
171: execbrk = breakcnt = 1;
172: if (a1)
173: breakcnt = stoi(a1);
174: if (breakcnt > loopcnt)
175: breakcnt = loopcnt;
176: else
177: breakcnt = -breakcnt;
178: }
179: break;
180:
181: case SYSBREAK:
182: if (loopcnt)
183: {
184: execbrk = breakcnt = 1;
185: if (a1)
186: breakcnt = stoi(a1);
187: if (breakcnt > loopcnt)
188: breakcnt = loopcnt;
189: }
190: break;
191:
192: case SYSTRAP:
193: if (a1)
194: {
195: BOOL clear;
196:
197: if ((clear = digit(*a1)) == 0)
198: ++com;
199: while (*++com)
200: {
201: int i;
202:
203: if ((i = stoi(*com)) >= MAXTRAP || i < MINTRAP)
204: failed(*com, badtrap);
205: else if (clear)
206: clrsig(i);
207: else
208: {
209: replace(&trapcom[i], a1);
210: if (*a1)
211: getsig(i);
212: else
213: ignsig(i);
214: }
215: }
216: }
217: else /* print out current traps */
218: {
219: int i;
220:
221: for (i = 0; i < MAXTRAP; i++)
222: {
223: if (trapcom[i])
224: {
225: prs_buff("trap ");
226: prs_buff(quotedstring(trapcom[i]));
227: prc_buff(SP);
228: prn_buff(i);
229: prc_buff(NL);
230: }
231: }
232: }
233: break;
234:
235: case SYSEXEC:
236: com++;
237: ioset = 0;
238: io = 0;
239: if (a1 == 0)
240: {
241: break;
242: }
243:
244: case SYSNEWGRP:
245: oldsigs();
246: execa(com);
247: done();
248:
249: case SYSCD:
250: if ((a1 && *a1) || (a1 == 0 && (a1 = homenod.namval.val)))
251: {
252: char *cdpath;
253:
254: if ((cdpath = cdpnod.namval.val) == 0 ||
255: *a1 == '/' ||
256: cf(a1, ".") == 0 ||
257: cf(a1, "..") == 0 ||
258: (*a1 == '.' && (*(a1+1) == '/' || *(a1+1) == '.' && *(a1+2) == '/')))
259: cdpath = nullstr;
260: dochdir(a1, cdpath);
261: }
262: else
263: {
264: if (a1)
265: failed(a1, baddir);
266: else
267: error(nohome);
268: }
269:
270: break;
271:
272: case SYSSHFT:
273: {
274: int places;
275:
276: places = a1 ? stoi(a1) : 1;
277:
278: if ((dolc -= places) < 0)
279: {
280: dolc = 0;
281: error(badshift);
282: }
283: else
284: dolv += places;
285: }
286:
287: break;
288:
289: case SYSWAIT:
290: await(a1 ? stoi(a1) : -1, 1);
291: break;
292:
293: case SYSREAD:
294: rwait = 1;
295: exitval = a1? readvar(&com[1]) : 0;
296: rwait = 0;
297: break;
298:
299: case SYSSET:
300: if (a1)
301: {
302: int argc;
303:
304: argc = options(argn, com);
305: if (argc > 1)
306: setargs(com + argn - argc);
307: }
308: else if (comptr(t)->comset == 0)
309: {
310: /*
311: * scan name chain and print
312: */
313: namscan(printnam);
314: }
315: break;
316:
317: case SYSXPORT:
318: {
319: struct namnod *n;
320:
321: exitval = 0;
322: if (a1)
323: {
324: while (*++com)
325: {
326: n = lookup(*com);
327: attrib(n, N_EXPORT);
328: }
329: }
330: else
331: namscan(printexp);
332: }
333: break;
334:
335: case SYSEVAL:
336: if (a1)
337: execexp(a1, &com[2]);
338: break;
339:
340: case SYSUMASK:
341: if (a1)
342: {
343: int c, i;
344:
345: i = 0;
346: while ((c = *a1++) >= '0' && c <= '7')
347: i = (i << 3) + c - '0';
348: umask(i);
349: }
350: else
351: {
352: int i, j;
353:
354: umask(i = umask(0));
355: prc_buff('0');
356: for (j = 6; j >= 0; j -= 3)
357: prc_buff(((i >> j) & 07) +'0');
358: prc_buff(NL);
359: }
360: break;
361:
362: case SYSRETURN:
363: if (funcnt == 0)
364: error(badreturn);
365:
366: execbrk = 1;
367: exitval = (a1 ? stoi(a1) : retval);
368: break;
369:
370: case SYSWHATIS:
371: exitval = 0;
372: if (a1)
373: {
374: while (*++com)
375: what_is(*com);
376: }
377: break;
378:
379: case SYSUNS:
380: exitval = 0;
381: if (a1)
382: {
383: while (*++com)
384: unset_name(*com);
385: }
386: break;
387:
388: case SYSMEM:
389: exitval = 0;
390: chkmem();
391: break;
392: default:
393: prs_buff("unknown builtin\n");
394: }
395:
396:
397: flushb();
398: restore(index);
399: chktrap();
400: break;
401: }
402: }
403: else if (t->treio == 0)
404: {
405: chktrap();
406: break;
407: }
408:
409: }
410:
411: case TFORK:
412: exitval = 0;
413: if (execflg && (treeflgs & (FAMP | FPOU)) == 0)
414: parent = 0;
415: else
416: {
417: int forkcnt = 1;
418:
419: if (treeflgs & (FAMP | FPOU))
420: {
421: link_iodocs(iotemp);
422: linked = 1;
423: }
424:
425:
426: /*
427: * FORKLIM is the max period between forks -
428: * power of 2 usually. Currently shell tries after
429: * 2,4,8,16, and 32 seconds and then quits
430: */
431:
432: while ((parent = fork()) == -1)
433: {
434: if ((forkcnt = (forkcnt * 2)) > FORKLIM) /* 32 */
435: {
436: switch (errno)
437: {
438: case ENOMEM:
439: error(noswap);
440: break;
441: default:
442: case EAGAIN:
443: error(nofork);
444: break;
445: }
446: }
447: sigchk();
448: alarm(forkcnt);
449: pause();
450: }
451: }
452: if (parent)
453: {
454: /*
455: * This is the parent branch of fork;
456: * it may or may not wait for the child
457: */
458: if (treeflgs & FPRS && flags & ttyflg)
459: {
460: prn(parent);
461: newline();
462: }
463: if (treeflgs & FPCL)
464: closepipe(pf1);
465: if ((treeflgs & (FAMP | FPOU)) == 0)
466: await(parent, 0);
467: else if ((treeflgs & FAMP) == 0)
468: post(parent);
469: else
470: assnum(&pcsadr, parent);
471: chktrap();
472: break;
473: }
474: else /* this is the forked branch (child) of execute */
475: {
476: flags |= forked;
477: fiotemp = 0;
478:
479: if (linked == 1)
480: {
481: swap_iodoc_nm(iotemp);
482: exec_link |= 06;
483: }
484: else if (linked == 0)
485: iotemp = 0;
486:
487: postclr();
488: settmp();
489: /*
490: * Turn off INTR and QUIT if `FINT'
491: * Reset ramaining signals to parent
492: * except for those `lost' by trap
493: */
494: oldsigs();
495: if (treeflgs & FINT)
496: {
497: signal(SIGINT, 1);
498: signal(SIGQUIT, 1);
499:
500: #ifdef NICE
501: nice(NICEVAL);
502: #endif
503:
504: }
505: /*
506: * pipe in or out
507: */
508: if (treeflgs & FPIN)
509: {
510: rename(pf1[INPIPE], 0);
511: close(pf1[OTPIPE]);
512: }
513: if (treeflgs & FPOU)
514: {
515: close(pf2[INPIPE]);
516: rename(pf2[OTPIPE], 1);
517: }
518: /*
519: * default std input for &
520: */
521: if (treeflgs & FINT && ioset == 0)
522: rename(chkopen(devnull), 0);
523: /*
524: * io redirection
525: */
526: initio(t->treio, 0);
527:
528: if (type != TCOM)
529: {
530: execute(forkptr(t)->forktre, exec_link | 01, errorflg);
531: }
532: else if (com[0] != ENDARGS)
533: {
534: eflag = 0;
535: setlist(comptr(t)->comset, N_EXPORT);
536: rmtemp(0);
537: execa(com);
538: }
539: done();
540: }
541:
542: case TPAR:
543: execute(parptr(t)->partre, exec_link, errorflg);
544: done();
545:
546: case TFIL:
547: {
548: int pv[2];
549:
550: chkpipe(pv);
551: if (execute(lstptr(t)->lstlef, 0, errorflg, pf1, pv) == 0)
552: execute(lstptr(t)->lstrit, exec_link, errorflg, pv, pf2);
553: else
554: closepipe(pv);
555: }
556: break;
557:
558: case TLST:
559: execute(lstptr(t)->lstlef, 0, errorflg);
560: execute(lstptr(t)->lstrit, exec_link, errorflg);
561: break;
562:
563: case TAND:
564: if (execute(lstptr(t)->lstlef, 0, 0) == 0)
565: execute(lstptr(t)->lstrit, exec_link, errorflg);
566: break;
567:
568: case TORF:
569: if (execute(lstptr(t)->lstlef, 0, 0) != 0)
570: execute(lstptr(t)->lstrit, exec_link, errorflg);
571: break;
572:
573: case TFOR:
574: {
575: struct namnod *n = lookup(forptr(t)->fornam);
576: char **args;
577: struct dolnod *argsav = 0;
578:
579: if (forptr(t)->forlst == 0)
580: {
581: args = dolv + 1;
582: argsav = useargs();
583: }
584: else
585: {
586: struct argnod *schain = gchain;
587:
588: gchain = 0;
589: trim((args = scan(getarg(forptr(t)->forlst)))[0]);
590: gchain = schain;
591: }
592: loopcnt++;
593: while (*args != ENDARGS && execbrk == 0)
594: {
595: assign(n, *args++);
596: execute(forptr(t)->fortre, 0, errorflg);
597: if (breakcnt < 0)
598: execbrk = (++breakcnt != 0);
599: }
600: if (breakcnt > 0)
601: execbrk = (--breakcnt != 0);
602:
603: loopcnt--;
604: argfor = (struct dolnod *)freeargs(argsav);
605: }
606: break;
607:
608: case TWH:
609: case TUN:
610: {
611: int i = 0;
612:
613: loopcnt++;
614: while (execbrk == 0 && (execute(whptr(t)->whtre, 0, 0) == 0) == (type == TWH))
615: {
616: i = execute(whptr(t)->dotre, 0, errorflg);
617: if (breakcnt < 0)
618: execbrk = (++breakcnt != 0);
619: }
620: if (breakcnt > 0)
621: execbrk = (--breakcnt != 0);
622:
623: loopcnt--;
624: exitval = i;
625: }
626: break;
627:
628: case TIF:
629: if (execute(ifptr(t)->iftre, 0, 0) == 0)
630: execute(ifptr(t)->thtre, exec_link, errorflg);
631: else if (ifptr(t)->eltre)
632: execute(ifptr(t)->eltre, exec_link, errorflg);
633: else
634: exitval = 0; /* force zero exit for if-then-fi */
635: break;
636:
637: case TSW:
638: {
639: register char *r = mactrim(swptr(t)->swarg);
640: register struct regnod *regp;
641:
642: regp = swptr(t)->swlst;
643: while (regp)
644: {
645: struct argnod *rex = regp->regptr;
646:
647: while (rex)
648: {
649: register char *s;
650:
651: if (gmatch(r, s = macro(rex->argval)) || (trim(s), eq(r, s)))
652: {
653: execute(regp->regcom, 0, errorflg);
654: regp = 0;
655: break;
656: }
657: else
658: rex = rex->argnxt;
659: }
660: if (regp)
661: regp = regp->regnxt;
662: }
663: }
664: break;
665: }
666: exitset();
667: }
668: sigchk();
669: tdystak(sav);
670: flags |= eflag;
671: return(exitval);
672: }
673:
674: dochdir(place, cdpath)
675: char *place, *cdpath;
676: {
677: char *dir;
678: char bestplace[256];
679: char tempdir[256];
680: int score, bestscore=1000;
681: char *spname();
682: struct stat sb;
683:
684: do
685: {
686: dir = cdpath;
687: cdpath = catpath(cdpath,place);
688: /* kludge: will call opendir, so must lock down the string */
689: movstr(curstak(), tempdir);
690: if (chdir(tempdir) < 0)
691: {
692: char *dir1;
693:
694: if (flags&ttyflg && (dir1=spname(tempdir, &score))
695: && stat(dir1, &sb)==0
696: && (sb.st_mode&S_IFMT)==S_IFDIR
697: && access(dir1, 1)==0)
698: {
699: if (score < bestscore)
700: {
701: movstr(dir1, bestplace);
702: bestscore = score;
703: }
704: }
705: }
706: else
707: {
708: if (cf(nullstr, dir) &&
709: *dir != ':' &&
710: any('/', tempdir) &&
711: flags & prompt)
712: {
713: prs_buff(tempdir);
714: prc_buff(NL);
715: }
716: return;
717: }
718: } while (cdpath);
719: if (bestscore < 1000 && chdir(bestplace) >= 0) {
720: prs_buff(bestplace);
721: prc_buff(NL);
722: return;
723: }
724: failed(place, baddir);
725: }
726:
727: execexp(s, f)
728: char *s;
729: int f;
730: {
731: struct fileblk fb;
732:
733: push(&fb);
734: if (s)
735: {
736: estabf(s);
737: fb.feval = (char **)(f);
738: }
739: else if (f >= 0)
740: initf(f);
741: execute(cmd(NL, NLFLG | MTFLG), 0, (int)(flags & errflg));
742: pop();
743: }
744:
745: execprint(com)
746: char **com;
747: {
748: register int argn = 0;
749:
750: prs(execpmsg);
751:
752: while(com[argn] != ENDARGS)
753: {
754: prs(quotedstring(com[argn++]));
755: blank();
756: }
757:
758: newline();
759: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.