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