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