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