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