1: /*	@(#)sh.exec.c	2.1	SCCS id keyword	*/
   2: /* Copyright (c) 1980 Regents of the University of California */
   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: 	 * If no path, no words in path, or a / in the filename
  93: 	 * then restrict the command search.
  94: 	 */
  95:     if (v == 0 || v->vec[0] == 0 || slash)
  96:         pv = justabs;
  97:     else
  98:         pv = v->vec;
  99:     sav = strspl("/", *av);     /* / command name for postpending */
 100: #ifdef VFORK
 101:     Vsav = sav;
 102: #endif
 103:     if (havhash)
 104:         hashval = xhash[hash(*av)];
 105:     i = 0;
 106: #ifdef VFORK
 107:     hits++;
 108: #endif
 109:     do {
 110:         if (!slash && pv[0][0] == '/' && havhash && (hashval & (1 << (i % 8))) == 0)
 111:             goto cont;
 112:         if (pv[0][0] == 0 || eq(pv[0], "."))    /* don't make ./xxx */
 113:             texec(*av, av);
 114:         else {
 115:             dp = strspl(*pv, sav);
 116: #ifdef VFORK
 117:             Vdp = dp;
 118: #endif
 119:             texec(dp, av);
 120: #ifdef VFORK
 121:             Vdp = 0;
 122: #endif
 123:             xfree(dp);
 124:         }
 125: #ifdef VFORK
 126:         misses++;
 127: #endif
 128: cont:
 129:         pv++;
 130:         i++;
 131:     } while (*pv);
 132: #ifdef VFORK
 133:     hits--;
 134: #endif
 135: #ifdef VFORK
 136:     Vsav = 0;
 137:     Vav = 0;
 138: #endif
 139:     xfree(sav);
 140:     xfree(av);
 141:     pexerr();
 142: }
 143: 
 144: pexerr()
 145: {
 146: 
 147:     /* Couldn't find the damn thing */
 148:     setname(expath);
 149:     /* xfree(expath); */
 150:     if (exerr)
 151:         bferr(exerr);
 152:     bferr("Command not found");
 153: }
 154: 
 155: /* Last resort shell */
 156: char    *lastsh[] = { SHELLPATH, 0 };
 157: 
 158: /*
 159:  * Execute command f, arg list t.
 160:  * Record error message if not found.
 161:  * Also do shell scripts here.
 162:  */
 163: texec(f, t)
 164:     char *f;
 165:     register char **t;
 166: {
 167:     register struct varent *v;
 168:     register char **vp;
 169:     extern char *sys_errlist[];
 170: 
 171:     execv(f, t);
 172:     switch (errno) {
 173: 
 174:     case ENOEXEC:
 175:         /*
 176: 		 * If there is an alias for shell, then
 177: 		 * put the words of the alias in front of the
 178: 		 * argument list replacing the command name.
 179: 		 * Note no interpretation of the words at this point.
 180: 		 */
 181:         v = adrof1("shell", &aliases);
 182:         if (v == 0) {
 183: #ifdef OTHERSH
 184:             register int ff = open(f, 0);
 185:             char ch;
 186: #endif
 187: 
 188:             vp = lastsh;
 189:             vp[0] = adrof("shell") ? value("shell") : SHELLPATH;
 190: #ifdef OTHERSH
 191:             if (ff != -1 && read(ff, &ch, 1) == 1 && ch != '#')
 192:                 vp[0] = OTHERSH;
 193:             close(ff);
 194: #endif
 195:         } else
 196:             vp = v->vec;
 197:         t[0] = f;
 198:         t = blkspl(vp, t);      /* Splice up the new arglst */
 199:         f = *t;
 200:         execv(f, t);
 201:         xfree(t);
 202:         /* The sky is falling, the sky is falling! */
 203: 
 204:     case ENOMEM:
 205:         Perror(f);
 206: 
 207:     case ENOENT:
 208:         break;
 209: 
 210:     default:
 211:         if (exerr == 0) {
 212:             exerr = sys_errlist[errno];
 213:             expath = savestr(f);
 214:         }
 215:     }
 216: }
 217: 
 218: execash(t, kp)
 219:     register struct command *kp;
 220: {
 221: 
 222:     didcch++;
 223:     signal(SIGINT, parintr);
 224:     lshift(kp->t_dcom, 1);
 225:     doexec(kp);
 226:     /*NOTREACHED*/
 227: }
 228: 
 229: xechoit(t)
 230:     char **t;
 231: {
 232: 
 233:     if (adrof("echo")) {
 234:         flush();
 235:         haderr = 1;
 236:         blkpr(t), printf("\n");
 237:         haderr = 0;
 238:     }
 239: }
 240: 
 241: dohash()
 242: {
 243:     struct stat stb;
 244:     struct direct dirbuf[BUFSIZ / sizeof (struct direct)];
 245:     char d_name[DIRSIZ + 1];
 246:     register int dirf, cnt;
 247:     int i = 0;
 248:     struct varent *v = adrof("path");
 249:     char **pv;
 250: 
 251:     havhash = 1;
 252:     for (cnt = 0; cnt < HSHSIZ; cnt++)
 253:         xhash[cnt] = 0;
 254:     if (v == 0)
 255:         return;
 256:     for (pv = v->vec; *pv; pv++, i = (i + 1) % 8) {
 257:         if (pv[0][0] != '/')
 258:             continue;
 259:         dirf = open(*pv, 0);
 260:         if (dirf < 0)
 261:             continue;
 262:         if (fstat(dirf, &stb) < 0 || !isdir(stb)) {
 263:             close(dirf);
 264:             continue;
 265:         }
 266:         while ((cnt = read(dirf, (char *) dirbuf, sizeof dirbuf)) >= sizeof dirbuf[0]) {
 267:             register struct direct *ep = dirbuf;
 268: 
 269:             for (cnt /= sizeof(struct direct); cnt > 0; cnt--, ep++) {
 270:                 if (ep->d_ino == 0)
 271:                     continue;
 272:                 copdent(d_name, ep->d_name);
 273:                 xhash[hash(d_name)] |= (1 << i);
 274:             }
 275:         }
 276:         close(dirf);
 277:     }
 278: }
 279: 
 280: dounhash()
 281: {
 282: 
 283:     havhash = 0;
 284: }
 285: 
 286: #ifdef VFORK
 287: hashstat()
 288: {
 289: 
 290:     if (hits+misses)
 291:     printf("%d hits, %d misses, %2d%%\n", hits, misses, 100 * hits / (hits + misses));
 292: }
 293: #endif
 294: 
 295: hash(cp)
 296:     register char *cp;
 297: {
 298:     register long hash = 0;
 299:     int retval;
 300: 
 301:     while (*cp)
 302:         hash += hash + *cp++;
 303:     if (hash < 0)
 304:         hash = -hash;
 305:     retval = hash % HSHSIZ;
 306:     return (retval);
 307: }

Defined functions

doexec defined in line 44; used 2 times
dounhash defined in line 280; used 4 times
execash defined in line 218; used 4 times
hash defined in line 295; used 9 times
hashstat defined in line 287; used 2 times
pexerr defined in line 144; used 2 times
texec defined in line 163; used 2 times
xechoit defined in line 229; used 3 times

Defined variables

exerr defined in line 23; used 5 times
expath defined in line 24; used 4 times
havhash defined in line 34; used 4 times
hits defined in line 38; used 6 times
justabs defined in line 42; used 1 times
  • in line 96
lastsh defined in line 156; used 1 times
misses defined in line 38; used 4 times
xhash defined in line 36; used 3 times

Defined macros

HSHSIZ defined in line 35; used 3 times
Last modified: 1980-09-12
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 1014
Valid CSS Valid XHTML 1.0 Strict