|
|
1.1 ! root 1: /* ! 2: * sh/exec1.c ! 3: * The Bourne shell. ! 4: * Shell part of execution. ! 5: */ ! 6: ! 7: #include <assert.h> ! 8: #include "sh.h" ! 9: ! 10: static char no_last_command [] = ""; ! 11: static char * lastcmd = no_last_command; ! 12: ! 13: char *skipredir(); ! 14: ! 15: /* ! 16: * Execute the given node, wait for completion, return status. ! 17: */ ! 18: command (np) ! 19: register NODE *np; ! 20: { ! 21: register int f; /* Pid of command */ ! 22: int mynllflag; /* Saved fork not forced flag */ ! 23: CON con; /* Control link for break/continue */ ! 24: char *innp, **inlp; /* for NFOR */ ! 25: NODE *cnode; /* for NCASE */ ! 26: char *cname; /* for NCASE */ ! 27: ! 28: if (ret_done) ! 29: return; ! 30: mynllflag = nllflag; ! 31: innp = NULL; ! 32: inlp = NULL; ! 33: cnode = NULL; ! 34: f = 0; ! 35: ! 36: con.c_next = sesp->s_con; ! 37: con.c_node = np; ! 38: con.c_bpp = savebuf (); ! 39: con.c_temp = NULL; ! 40: sesp->s_con = & con; ! 41: ! 42: switch (setjmp (con.c_envl)) { ! 43: case 0: /* initial setjmp */ ! 44: break; ! 45: case 1: /* continue */ ! 46: np = con.c_node; ! 47: break; ! 48: case 2: /* break */ ! 49: goto break2; ! 50: default: ! 51: panic (1); ! 52: NOTREACHED; ! 53: } ! 54: ! 55: for ( ; np != NULL; np = np->n_next) { ! 56: if (ret_done) ! 57: break; /* "return" interrupts control flow */ ! 58: recover(ICMD); ! 59: f = 0; ! 60: nllflag = mynllflag; ! 61: ! 62: switch (np->n_type) { ! 63: case NCOMS: ! 64: f = comscom (np->n_auxp); ! 65: break; ! 66: ! 67: case NFOR: ! 68: if (innp == NULL) { ! 69: innp = np->n_strp; ! 70: nargc = 0; ! 71: nargv = makargl(); ! 72: for (np = np->n_next->n_auxp; np; np = np->n_next) ! 73: eval (np->n_strp, EARGS); ! 74: inlp = nargv; ! 75: np = con.c_node; ! 76: ! 77: assert (con.c_temp == NULL); ! 78: con.c_temp = capture_temp (); ! 79: } ! 80: continue; ! 81: ! 82: case NFOR2: ! 83: /* do_done_list->n_next == this node */ ! 84: if (* inlp == NULL || assnvar (innp, * inlp ++) == NULL) ! 85: break; ! 86: continue; ! 87: ! 88: case NWHILE: ! 89: /* do_done_list->n_next == this node */ ! 90: nllflag = 0; ! 91: ! 92: if (con.c_temp == NULL) ! 93: con.c_temp = capture_temp (); ! 94: ! 95: if (command (np->n_auxp)) ! 96: break; ! 97: continue; ! 98: ! 99: case NUNTIL: ! 100: /* do_done_list->n_next == this node */ ! 101: nllflag = 0; ! 102: ! 103: if (con.c_temp == NULL) ! 104: con.c_temp = capture_temp (); ! 105: ! 106: if (! command (np->n_auxp)) ! 107: break; ! 108: continue; ! 109: ! 110: case NBRAC: ! 111: command (np->n_auxp); ! 112: break; ! 113: ! 114: case NPARN: ! 115: if (nllflag || (f = clone()) == 0) { ! 116: exit (command (np->n_auxp)); ! 117: NOTREACHED; ! 118: } ! 119: break; ! 120: ! 121: case NIF: ! 122: nllflag = 0; ! 123: if (! command (np->n_auxp->n_auxp)) ! 124: np = np->n_auxp; ! 125: else if (np->n_next == NULL) ! 126: slret = 0; /* exit status 0 if no elsepart */ ! 127: continue; ! 128: ! 129: case NELSE: ! 130: command (np->n_auxp); ! 131: break; ! 132: ! 133: case NCASE: ! 134: eval (np->n_strp, EWORD); ! 135: if (errflag) ! 136: break; ! 137: cname = duplstr (strt, 0); ! 138: continue; ! 139: ! 140: case NCASE2: ! 141: cnode = np->n_auxp; ! 142: continue; ! 143: ! 144: case NCASE3: ! 145: /* end of pattern list == next NCASE2 node */ ! 146: eval (np->n_strp, EPATT); ! 147: if (errflag) ! 148: break; ! 149: if (match (strt, cname)) { ! 150: command (cnode); ! 151: break; ! 152: } ! 153: continue; ! 154: ! 155: case NLIST: ! 156: nllflag = 0; ! 157: command (np->n_auxp); ! 158: continue; ! 159: ! 160: case NANDF: ! 161: nllflag = 0; ! 162: if (command (np->n_auxp)) ! 163: break; ! 164: continue; ! 165: ! 166: case NORF: ! 167: nllflag = 0; ! 168: if (! command (np->n_auxp)) ! 169: break; ! 170: continue; ! 171: ! 172: case NBACK: ! 173: if ((f = clone ()) == 0) { ! 174: static char *iov[] = { "0</dev/null", NULL }; ! 175: ! 176: bckflag++; ! 177: dflttrp (IBACK); ! 178: redirect (iov, NULL); ! 179: exit (command (np->n_auxp)); ! 180: NOTREACHED; ! 181: } ! 182: sback = f; ! 183: prints ("%d\n", f); ! 184: f = 0; ! 185: continue; ! 186: ! 187: case NPIPE: ! 188: f = pipecoms (np); ! 189: break; ! 190: ! 191: case NFUNC: ! 192: def_shell_fn (np, capture_temp ()); ! 193: break; ! 194: ! 195: case NRET: ! 196: if (in_sh_fn == 0) { ! 197: printe ("return not inside shell function"); ! 198: break; ! 199: } ! 200: ret_done ++; /* to interrupt control flow */ ! 201: if (np->n_strp [0] != '\0') { ! 202: eval (np->n_strp, EARGS); ! 203: slret = atoi (strt); ! 204: } ! 205: return slret; ! 206: ! 207: default: ! 208: panic (2); ! 209: NOTREACHED; ! 210: } ! 211: break; ! 212: ! 213: } ! 214: break2: ! 215: nllflag = mynllflag; ! 216: if (sesp->s_con != NULL) ! 217: sesp->s_con = sesp->s_con->c_next; ! 218: if (f) ! 219: waitc (f); ! 220: if (slret) ! 221: assnvar ("LASTERROR", lastcmd); ! 222: ! 223: DESTROY_CON (& con); ! 224: ! 225: if (eflag && (slret || errflag)) { ! 226: reset (RUABORT); ! 227: NOTREACHED; ! 228: } ! 229: return slret; ! 230: } ! 231: ! 232: /* ! 233: * Run a simple command. ! 234: * Anything but. ! 235: */ ! 236: #define FARGS 1 ! 237: #define FIORS 2 ! 238: #define FASSG 4 ! 239: ! 240: comscom (np) ! 241: register NODE *np; ! 242: { ! 243: register int f; ! 244: register char **app, *s, *s1, *sp; ! 245: int nputs, nargs; ! 246: ! 247: nargc = 1; ! 248: nargv = makargl(); ! 249: nargv = addargl(nargv, "sh"); ! 250: niovp = makargl(); ! 251: nenvp = makargl(); ! 252: nctlp = NULL; ! 253: /* ! 254: * Scan for arguments. ! 255: * or a control node. ! 256: */ ! 257: nputs = 0; ! 258: f = 0; ! 259: for ( ; np; np = np->n_next) { ! 260: #ifdef VERBOSE ! 261: prints (" <node %d>", np->n_type); ! 262: #endif ! 263: switch (np->n_type) { ! 264: case NIORS: ! 265: f |= FIORS; ! 266: #if 0 ! 267: /* Old code. */ ! 268: eval(np->n_strp, EWORD); ! 269: niovp = addargl(niovp, duplstr(strt, 0)); ! 270: if (xflag) ! 271: nputs += puta(nputs, strt); ! 272: #else ! 273: /* ! 274: * New code by steve 1/24/91. ! 275: * This allows globs in redirection args. ! 276: */ ! 277: s = skipredir(np->n_strp); ! 278: nargs = nargc; ! 279: eval(s, EARGS); /* expand as arg */ ! 280: for (s1 = np->n_strp, sp = strt; s1 < s; ) ! 281: *sp++ = *s1++; ! 282: strcpy(sp, nargv[nargs]); /* build redir arg */ ! 283: niovp = addargl(niovp, duplstr(strt, 0)); ! 284: if (xflag) ! 285: nputs += puta(nputs, strt); ! 286: --nargc; ! 287: for (app = nargv+nargs; *app; app++) { ! 288: *app = *(app + 1); /* shift remaining args */ ! 289: if (xflag && *app != NULL) ! 290: nputs += puta(nputs, *app); ! 291: } ! 292: #endif ! 293: continue; ! 294: case NARGS: ! 295: f |= FARGS; ! 296: nargs = nargc; ! 297: eval(np->n_strp, EARGS); ! 298: if (xflag) ! 299: for (app = nargv+nargs; *app; ) ! 300: nputs += puta(nputs, *app++); ! 301: continue; ! 302: case NASSG: ! 303: if (kflag || (f&FARGS)==0) { ! 304: f |= FASSG; ! 305: eval(np->n_strp, EWORD); ! 306: nenvp = addargl(nenvp, duplstr(strt, 0)); ! 307: if (xflag) ! 308: nputs += puta(nputs, strt); ! 309: } else { ! 310: nargs = nargc; ! 311: eval(np->n_strp, EARGS); ! 312: if (xflag) ! 313: for (app = nargv+nargs; *app; ) ! 314: nputs += puta(nputs, *app++); ! 315: } ! 316: continue; ! 317: case NCTRL: ! 318: if (nctlp != NULL) { ! 319: panic (3); ! 320: NOTREACHED; ! 321: } ! 322: f |= FARGS; ! 323: nctlp = np; ! 324: continue; ! 325: default: ! 326: panic (4); ! 327: NOTREACHED; ! 328: } ! 329: } ! 330: if (xflag && nputs) ! 331: prints ("\n"); ! 332: #ifdef VERBOSE ! 333: if (xflag) { ! 334: prints("\t<%o flag, %d put, %d arg, %o arv, %o env, %o iov>\n", ! 335: f, nputs, nargc-1, *(nargv+1), *nenvp, *niovp); ! 336: } ! 337: #endif ! 338: ! 339: nargv += 1; /* Skip over "sh" */ ! 340: nargc -= 1; ! 341: ! 342: /* Last chance to quit */ ! 343: #ifdef VERBOSE ! 344: if (xflag) prints("errflag = %o\n", errflag); ! 345: #endif ! 346: if (errflag || nflag) ! 347: return 0; ! 348: ! 349: /* And away we go */ ! 350: if (lastcmd != no_last_command) ! 351: sfree (lastcmd); ! 352: if (* nargv) ! 353: lastcmd = duplstr (* nargv, 1); ! 354: else ! 355: lastcmd = no_last_command; ! 356: switch (f) { ! 357: case 0: ! 358: return 0; ! 359: case FARGS: ! 360: if (nctlp) { ! 361: command(nctlp->n_auxp); ! 362: return 0; ! 363: } ! 364: case FARGS| FIORS: ! 365: case FARGS| FASSG: ! 366: case FARGS| FIORS| FASSG: ! 367: if (shell_function () || shell_builtin ()) ! 368: return 0; ! 369: break; ! 370: case FIORS: ! 371: break; ! 372: case FASSG: ! 373: case FIORS| FASSG: ! 374: for (app = nenvp ; * app !=NULL; ) ! 375: setsvar (* app ++); ! 376: if ((f & ~ FASSG) ==0) { ! 377: slret = 0; ! 378: return 0; ! 379: } ! 380: break; ! 381: default: ! 382: panic (5); ! 383: NOTREACHED; ! 384: } ! 385: if (nllflag || (f = clone ()) == 0) { ! 386: if (redirect (niovp, NULL) < 0) { ! 387: slret = 1; ! 388: } else if (nargc) { ! 389: dflttrp (ICMD); ! 390: nenvp = envlvar (nenvp); ! 391: flexec (); ! 392: slret = 1; ! 393: } else if (nctlp) ! 394: command (nctlp->n_auxp); ! 395: exit (slret); ! 396: NOTREACHED; ! 397: } ! 398: return f; ! 399: } ! 400: ! 401: puta(n, p) ! 402: char *p; ! 403: { ! 404: if (n) ! 405: prints(" "); ! 406: #ifdef VERBOSE ! 407: else ! 408: prints("<%d> ", getpid()); ! 409: #endif ! 410: prints("%s", p); ! 411: return (1); ! 412: } ! 413: ! 414: /* ! 415: * Execute a pipe command. ! 416: * Fork, if necessary, a subshell to execute the pipe. ! 417: * Fork each segment off. ! 418: * Wait for last, save slret, wait for all, return slret from last. ! 419: */ ! 420: pipecoms(np) ! 421: register NODE *np; ! 422: { ! 423: register int f; ! 424: register int p1st = 0; ! 425: int pipev[2]; ! 426: ! 427: if ( ! nllflag && (f = clone()) != 0) ! 428: return (f); ! 429: while (np->n_type == NPIPE) { ! 430: if (f = pipeline(pipev)) { ! 431: /* Parent takes right hand side */ ! 432: np = np->n_next; ! 433: if (p1st == 0) ! 434: p1st = f; ! 435: dup2(pipev[0], 0); ! 436: if (pipev[0] != 0) ! 437: close(pipev[0]); ! 438: close(pipev[1]); ! 439: } else { ! 440: /* Child takes left hand side */ ! 441: np = np->n_auxp; ! 442: dup2(pipev[1], 1); ! 443: close(pipev[0]); ! 444: if (pipev[1] != 1) ! 445: close(pipev[1]); ! 446: exit(command(np)); ! 447: NOTREACHED; ! 448: } ! 449: } ! 450: if (f = clone()) { ! 451: /* Parent waits out pipe line */ ! 452: spipe = p1st; ! 453: close(0); ! 454: if (f = waitc(f)) ! 455: waitc(p1st); ! 456: exit(f); ! 457: NOTREACHED; ! 458: } else { ! 459: /* Child takes the pipe tail */ ! 460: exit(command(np)); ! 461: NOTREACHED; ! 462: } ! 463: } ! 464: ! 465: /* ! 466: * Skip a redirection arg, return pointer to following nonspace. ! 467: */ ! 468: char * ! 469: skipredir(s) register char *s; ! 470: { ! 471: if (*s >= '1' && *s <= '9') ! 472: ++s; ! 473: if (*s == '>' || *s == '<') ! 474: ++s; ! 475: if (*s == '>' || *s == '<') ! 476: ++s; ! 477: if (*s == '&') ! 478: ++s; ! 479: while (*s == ' ' || *s == '\t') ! 480: ++s; ! 481: return s; ! 482: } ! 483: ! 484: /* end of sh/exec1.c */
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.