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: }

Defined functions

doexec defined in line 44; used 2 times
dounhash defined in line 289; used 2 times
execash defined in line 224; used 2 times
hash defined in line 304; used 9 times
hashstat defined in line 296; used 2 times
pexerr defined in line 150; used 2 times
texec defined in line 169; used 2 times
xechoit defined in line 238; used 2 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
lastsh defined in line 162; used 1 times
misses defined in line 38; used 4 times
sccsid defined in line 1; never used
xhash defined in line 36; used 3 times

Defined macros

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