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