|
|
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, 0); ! 61: if (!(n->namflg & N_ENVNAM)) ! 62: free_val(&n->namval); ! 63: ! 64: if (funcnt && f->fndval) ! 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, 0); ! 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, 0); ! 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, 0); ! 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, 0); ! 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: if(flags & noexec) ! 617: break; ! 618: i = execute(whptr(t)->dotre, 0, errorflg); ! 619: if (breakcnt < 0) ! 620: execbrk = (++breakcnt != 0); ! 621: } ! 622: if (breakcnt > 0) ! 623: execbrk = (--breakcnt != 0); ! 624: ! 625: loopcnt--; ! 626: exitval = i; ! 627: } ! 628: break; ! 629: ! 630: case TIF: ! 631: if (execute(ifptr(t)->iftre, 0, 0) == 0) ! 632: execute(ifptr(t)->thtre, exec_link, errorflg); ! 633: else if (ifptr(t)->eltre) ! 634: execute(ifptr(t)->eltre, exec_link, errorflg); ! 635: else ! 636: exitval = 0; /* force zero exit for if-then-fi */ ! 637: break; ! 638: ! 639: case TSW: ! 640: { ! 641: register char *r = mactrim(swptr(t)->swarg); ! 642: register struct regnod *regp; ! 643: ! 644: regp = swptr(t)->swlst; ! 645: while (regp) ! 646: { ! 647: struct argnod *rex = regp->regptr; ! 648: ! 649: while (rex) ! 650: { ! 651: register char *s; ! 652: ! 653: if (gmatch(r, s = macro(rex->argval)) || (trim(s), eq(r, s))) ! 654: { ! 655: execute(regp->regcom, 0, errorflg); ! 656: regp = 0; ! 657: break; ! 658: } ! 659: else ! 660: rex = rex->argnxt; ! 661: } ! 662: if (regp) ! 663: regp = regp->regnxt; ! 664: } ! 665: } ! 666: break; ! 667: } ! 668: exitset(); ! 669: } ! 670: sigchk(); ! 671: tdystak(sav); ! 672: flags |= eflag; ! 673: return(exitval); ! 674: } ! 675: ! 676: dochdir(place, cdpath) ! 677: char *place, *cdpath; ! 678: { ! 679: char *dir; ! 680: char bestplace[256]; ! 681: char tempdir[256]; ! 682: int score, bestscore=1000; ! 683: char *spname(); ! 684: struct stat sb; ! 685: ! 686: do ! 687: { ! 688: dir = cdpath; ! 689: cdpath = catpath(cdpath,place); ! 690: /* kludge: will call opendir, so must lock down the string */ ! 691: movstr(curstak(), tempdir); ! 692: if (chdir(tempdir) < 0) ! 693: { ! 694: char *dir1; ! 695: ! 696: if (flags&ttyflg && (dir1=spname(tempdir, &score)) ! 697: && stat(dir1, &sb)==0 ! 698: && (sb.st_mode&S_IFMT)==S_IFDIR ! 699: && access(dir1, 1)==0) ! 700: { ! 701: if (score < bestscore) ! 702: { ! 703: movstr(dir1, bestplace); ! 704: bestscore = score; ! 705: } ! 706: } ! 707: } ! 708: else ! 709: { ! 710: if (cf(nullstr, dir) && ! 711: *dir != ':' && ! 712: any('/', tempdir) && ! 713: flags & prompt) ! 714: { ! 715: prs_buff(tempdir); ! 716: prc_buff(NL); ! 717: } ! 718: return; ! 719: } ! 720: } while (cdpath); ! 721: if (bestscore < 1000 && chdir(bestplace) >= 0) { ! 722: prs_buff(bestplace); ! 723: prc_buff(NL); ! 724: return; ! 725: } ! 726: failed(place, baddir, 0); ! 727: } ! 728: ! 729: execexp(s, f) ! 730: char *s; ! 731: int f; ! 732: { ! 733: struct fileblk fb; ! 734: ! 735: push(&fb); ! 736: if (s) ! 737: { ! 738: estabf(s); ! 739: fb.feval = (char **)(f); ! 740: } ! 741: else if (f >= 0) ! 742: initf(f); ! 743: execute(cmd(NL, NLFLG | MTFLG), 0, (int)(flags & errflg)); ! 744: pop(); ! 745: } ! 746: ! 747: execprint(com) ! 748: char **com; ! 749: { ! 750: register int argn = 0; ! 751: ! 752: prs(execpmsg); ! 753: ! 754: while(com[argn] != ENDARGS) ! 755: { ! 756: prs(quotedstring(com[argn++])); ! 757: blank(); ! 758: } ! 759: ! 760: newline(); ! 761: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.