|
|
1.1 ! root 1: static char *sccsid = "@(#)sh.exec.c 4.1 10/9/80"; ! 2: ! 3: #include "sh.h" ! 4: ! 5: /* ! 6: * C shell ! 7: */ ! 8: ! 9: /* ! 10: * System level search and execute of a command. ! 11: * We look in each directory for the specified command name. ! 12: * If the name contains a '/' then we execute only the full path name. ! 13: * If there is no search path then we execute only full path names. ! 14: */ ! 15: ! 16: /* ! 17: * As we search for the command we note the first non-trivial error ! 18: * message for presentation to the user. This allows us often ! 19: * to show that a file has the wrong mode/no access when the file ! 20: * is not in the last component of the search path, so we must ! 21: * go on after first detecting the error. ! 22: */ ! 23: char *exerr; /* Execution error message */ ! 24: char *expath; /* Path for exerr */ ! 25: ! 26: /* ! 27: * Xhash is an array of HSHSIZ chars, which are used to hash execs. ! 28: * If it is allocated, then to tell whether ``name'' is (possibly) ! 29: * present in the i'th component of the variable path, you look at ! 30: * the i'th bit of xhash[hash("name")]. This is setup automatically ! 31: * after .login is executed, and recomputed whenever ``path'' is ! 32: * changed. ! 33: */ ! 34: int havhash; ! 35: #define HSHSIZ 511 ! 36: char xhash[HSHSIZ]; ! 37: #ifdef VFORK ! 38: int hits, misses; ! 39: #endif ! 40: ! 41: /* Dummy search path for just absolute search when no path */ ! 42: char *justabs[] = { "", 0 }; ! 43: ! 44: doexec(t) ! 45: register struct command *t; ! 46: { ! 47: char *sav; ! 48: register char *dp, **pv, **av; ! 49: register struct varent *v; ! 50: bool slash = any('/', t->t_dcom[0]); ! 51: int hashval, i; ! 52: char *blk[2]; ! 53: ! 54: /* ! 55: * Glob the command name. If this does anything, then we ! 56: * will execute the command only relative to ".". One special ! 57: * case: if there is no PATH, then we execute only commands ! 58: * which start with '/'. ! 59: */ ! 60: dp = globone(t->t_dcom[0]); ! 61: sav = t->t_dcom[0]; ! 62: exerr = 0; expath = t->t_dcom[0] = dp; ! 63: xfree(sav); ! 64: v = adrof("path"); ! 65: if (v == 0 && expath[0] != '/') ! 66: pexerr(); ! 67: slash |= gflag; ! 68: ! 69: /* ! 70: * Glob the argument list, if necessary. ! 71: * Otherwise trim off the quote bits. ! 72: */ ! 73: gflag = 0; av = &t->t_dcom[1]; ! 74: rscan(av, tglob); ! 75: if (gflag) { ! 76: av = glob(av); ! 77: if (av == 0) ! 78: error("No match"); ! 79: } ! 80: blk[0] = t->t_dcom[0]; ! 81: blk[1] = 0; ! 82: av = blkspl(blk, av); ! 83: #ifdef VFORK ! 84: Vav = av; ! 85: #endif ! 86: scan(av, trim); ! 87: ! 88: xechoit(av); /* Echo command if -x */ ! 89: closech(); /* Close random fd's */ ! 90: ! 91: /* ! 92: * We must do this after any possible forking (like `foo` ! 93: * in glob) so that this shell can still do subprocesses. ! 94: */ ! 95: sigsys(SIGCHLD, SIG_IGN); /* sigsys for vforks sake */ ! 96: ! 97: /* ! 98: * If no path, no words in path, or a / in the filename ! 99: * then restrict the command search. ! 100: */ ! 101: if (v == 0 || v->vec[0] == 0 || slash) ! 102: pv = justabs; ! 103: else ! 104: pv = v->vec; ! 105: sav = strspl("/", *av); /* / command name for postpending */ ! 106: #ifdef VFORK ! 107: Vsav = sav; ! 108: #endif ! 109: if (havhash) ! 110: hashval = xhash[hash(*av)]; ! 111: i = 0; ! 112: #ifdef VFORK ! 113: hits++; ! 114: #endif ! 115: do { ! 116: if (!slash && pv[0][0] == '/' && havhash && (hashval & (1 << (i % 8))) == 0) ! 117: goto cont; ! 118: if (pv[0][0] == 0 || eq(pv[0], ".")) /* don't make ./xxx */ ! 119: texec(*av, av); ! 120: else { ! 121: dp = strspl(*pv, sav); ! 122: #ifdef VFORK ! 123: Vdp = dp; ! 124: #endif ! 125: texec(dp, av); ! 126: #ifdef VFORK ! 127: Vdp = 0; ! 128: #endif ! 129: xfree(dp); ! 130: } ! 131: #ifdef VFORK ! 132: misses++; ! 133: #endif ! 134: cont: ! 135: pv++; ! 136: i++; ! 137: } while (*pv); ! 138: #ifdef VFORK ! 139: hits--; ! 140: #endif ! 141: #ifdef VFORK ! 142: Vsav = 0; ! 143: Vav = 0; ! 144: #endif ! 145: xfree(sav); ! 146: xfree(av); ! 147: pexerr(); ! 148: } ! 149: ! 150: pexerr() ! 151: { ! 152: ! 153: /* Couldn't find the damn thing */ ! 154: setname(expath); ! 155: /* xfree(expath); */ ! 156: if (exerr) ! 157: bferr(exerr); ! 158: bferr("Command not found"); ! 159: } ! 160: ! 161: /* Last resort shell */ ! 162: char *lastsh[] = { SHELLPATH, 0 }; ! 163: ! 164: /* ! 165: * Execute command f, arg list t. ! 166: * Record error message if not found. ! 167: * Also do shell scripts here. ! 168: */ ! 169: texec(f, t) ! 170: char *f; ! 171: register char **t; ! 172: { ! 173: register struct varent *v; ! 174: register char **vp; ! 175: extern char *sys_errlist[]; ! 176: ! 177: execv(f, t); ! 178: switch (errno) { ! 179: ! 180: case ENOEXEC: ! 181: /* ! 182: * If there is an alias for shell, then ! 183: * put the words of the alias in front of the ! 184: * argument list replacing the command name. ! 185: * Note no interpretation of the words at this point. ! 186: */ ! 187: v = adrof1("shell", &aliases); ! 188: if (v == 0) { ! 189: #ifdef OTHERSH ! 190: register int ff = open(f, 0); ! 191: char ch; ! 192: #endif ! 193: ! 194: vp = lastsh; ! 195: vp[0] = adrof("shell") ? value("shell") : SHELLPATH; ! 196: #ifdef OTHERSH ! 197: if (ff != -1 && read(ff, &ch, 1) == 1 && ch != '#') ! 198: vp[0] = OTHERSH; ! 199: close(ff); ! 200: #endif ! 201: } else ! 202: vp = v->vec; ! 203: t[0] = f; ! 204: t = blkspl(vp, t); /* Splice up the new arglst */ ! 205: f = *t; ! 206: execv(f, t); ! 207: xfree((char *)t); ! 208: /* The sky is falling, the sky is falling! */ ! 209: ! 210: case ENOMEM: ! 211: Perror(f); ! 212: ! 213: case ENOENT: ! 214: break; ! 215: ! 216: default: ! 217: if (exerr == 0) { ! 218: exerr = sys_errlist[errno]; ! 219: expath = savestr(f); ! 220: } ! 221: } ! 222: } ! 223: ! 224: execash(t, kp) ! 225: register struct command *kp; ! 226: { ! 227: ! 228: didcch++; ! 229: signal(SIGINT, parintr); ! 230: signal(SIGQUIT, parintr); ! 231: signal(SIGTERM, parterm); /* if doexec loses, screw */ ! 232: lshift(kp->t_dcom, 1); ! 233: exiterr++; ! 234: doexec(kp); ! 235: /*NOTREACHED*/ ! 236: } ! 237: ! 238: xechoit(t) ! 239: char **t; ! 240: { ! 241: ! 242: if (adrof("echo")) { ! 243: flush(); ! 244: haderr = 1; ! 245: blkpr(t), printf("\n"); ! 246: haderr = 0; ! 247: } ! 248: } ! 249: ! 250: dohash() ! 251: { ! 252: struct stat stb; ! 253: struct direct dirbuf[BUFSIZ / sizeof (struct direct)]; ! 254: char d_name[DIRSIZ + 1]; ! 255: register int dirf, cnt; ! 256: int i = 0; ! 257: struct varent *v = adrof("path"); ! 258: char **pv; ! 259: ! 260: havhash = 1; ! 261: for (cnt = 0; cnt < HSHSIZ; cnt++) ! 262: xhash[cnt] = 0; ! 263: if (v == 0) ! 264: return; ! 265: for (pv = v->vec; *pv; pv++, i = (i + 1) % 8) { ! 266: if (pv[0][0] != '/') ! 267: continue; ! 268: dirf = open(*pv, 0); ! 269: if (dirf < 0) ! 270: continue; ! 271: if (fstat(dirf, &stb) < 0 || !isdir(stb)) { ! 272: close(dirf); ! 273: continue; ! 274: } ! 275: while ((cnt = read(dirf, (char *) dirbuf, sizeof dirbuf)) >= sizeof dirbuf[0]) { ! 276: register struct direct *ep = dirbuf; ! 277: ! 278: for (cnt /= sizeof(struct direct); cnt > 0; cnt--, ep++) { ! 279: if (ep->d_ino == 0) ! 280: continue; ! 281: copdent(d_name, ep->d_name); ! 282: xhash[hash(d_name)] |= (1 << i); ! 283: } ! 284: } ! 285: close(dirf); ! 286: } ! 287: } ! 288: ! 289: dounhash() ! 290: { ! 291: ! 292: havhash = 0; ! 293: } ! 294: ! 295: #ifdef VFORK ! 296: hashstat() ! 297: { ! 298: ! 299: if (hits+misses) ! 300: printf("%d hits, %d misses, %2d%%\n", hits, misses, 100 * hits / (hits + misses)); ! 301: } ! 302: #endif ! 303: ! 304: hash(cp) ! 305: register char *cp; ! 306: { ! 307: register long hash = 0; ! 308: int retval; ! 309: ! 310: while (*cp) ! 311: hash += hash + *cp++; ! 312: if (hash < 0) ! 313: hash = -hash; ! 314: retval = hash % HSHSIZ; ! 315: return (retval); ! 316: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.