|
|
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.