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