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