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: #if !defined(lint) && defined(DOSCCS)
   8: static char *sccsid = "@(#)sh.exec.c	5.2.2 (2.11BSD) 1996/9/20";
   9: #endif
  10: 
  11: #include "sh.h"
  12: #include <string.h>
  13: #include <sys/dir.h>
  14: 
  15: /*
  16:  * C shell
  17:  */
  18: 
  19: /*
  20:  * System level search and execute of a command.
  21:  * We look in each directory for the specified command name.
  22:  * If the name contains a '/' then we execute only the full path name.
  23:  * If there is no search path then we execute only full path names.
  24:  */
  25: 
  26: /*
  27:  * As we search for the command we note the first non-trivial error
  28:  * message for presentation to the user.  This allows us often
  29:  * to show that a file has the wrong mode/no access when the file
  30:  * is not in the last component of the search path, so we must
  31:  * go on after first detecting the error.
  32:  */
  33: char    *exerr;         /* Execution error message */
  34: char    *expath;        /* Path for exerr */
  35: 
  36: #include "sh.exec.h"
  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, hashval1, 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:     tglob(av);
  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:     trim(av);
  84: 
  85:     xechoit(av);        /* Echo command if -x */
  86:     /*
  87: 	 * Since all internal file descriptors are set to close on exec,
  88: 	 * we don't need to close them explicitly here.  Just reorient
  89: 	 * ourselves for error messages.
  90: 	 */
  91:     SHIN = 0; SHOUT = 1; SHDIAG = 2; OLDSTD = 0;
  92: 
  93:     /*
  94: 	 * We must do this AFTER any possible forking (like `foo`
  95: 	 * in glob) so that this shell can still do subprocesses.
  96: 	 */
  97:     (void) sigsetmask(0L);
  98: 
  99:     /*
 100: 	 * If no path, no words in path, or a / in the filename
 101: 	 * then restrict the command search.
 102: 	 */
 103:     if (v == 0 || v->vec[0] == 0 || slash)
 104:         pv = justabs;
 105:     else
 106:         pv = v->vec;
 107:     sav = strspl("/", *av);     /* / command name for postpending */
 108: #ifdef VFORK
 109:     Vsav = sav;
 110: #endif
 111:     if (havhash)
 112:         hashval = hashname(*av);
 113:     i = 0;
 114: #ifdef VFORK
 115:     hits++;
 116: #endif
 117:     do {
 118:         if (!slash && pv[0][0] == '/' && havhash) {
 119:             hashval1 = hash(hashval, i);
 120:             if (!bit(xhash, hashval1))
 121:                 goto cont;
 122:         }
 123:         if (pv[0][0] == 0 || eq(pv[0], "."))    /* don't make ./xxx */
 124:             texec(*av, av);
 125:         else {
 126:             dp = strspl(*pv, sav);
 127: #ifdef VFORK
 128:             Vdp = dp;
 129: #endif
 130:             texec(dp, av);
 131: #ifdef VFORK
 132:             Vdp = 0;
 133: #endif
 134:             xfree(dp);
 135:         }
 136: #ifdef VFORK
 137:         misses++;
 138: #endif
 139: cont:
 140:         pv++;
 141:         i++;
 142:     } while (*pv);
 143: #ifdef VFORK
 144:     hits--;
 145: #endif
 146: #ifdef VFORK
 147:     Vsav = 0;
 148:     Vav = 0;
 149: #endif
 150:     xfree(sav);
 151:     xfree((char *)av);
 152:     pexerr();
 153: }
 154: 
 155: pexerr()
 156: {
 157: 
 158:     /* Couldn't find the damn thing */
 159:     setname(expath);
 160:     /* xfree(expath); */
 161:     if (exerr)
 162:         bferr(exerr);
 163:     bferr("Command not found");
 164: }
 165: 
 166: /*
 167:  * Execute command f, arg list t.
 168:  * Record error message if not found.
 169:  * Also do shell scripts here.
 170:  */
 171: texec(f, t)
 172:     char *f;
 173:     register char **t;
 174: {
 175:     register struct varent *v;
 176:     register char **vp;
 177:     char *lastsh[2];
 178: 
 179:     execv(f, t);
 180:     switch (errno) {
 181: 
 182:     case ENOEXEC:
 183:         /*
 184: 		 * If there is an alias for shell, then
 185: 		 * put the words of the alias in front of the
 186: 		 * argument list replacing the command name.
 187: 		 * Note no interpretation of the words at this point.
 188: 		 */
 189:         v = adrof1("shell", &aliases);
 190:         if (v == 0) {
 191: #ifdef OTHERSH
 192:             register int ff = open(f, 0);
 193:             char ch;
 194: #endif
 195: 
 196:             vp = lastsh;
 197:             vp[0] = adrof("shell") ? value("shell") : SHELLPATH;
 198:             vp[1] = (char *) NULL;
 199: #ifdef OTHERSH
 200:             if (ff != -1 && read(ff, &ch, 1) == 1 && ch != '#')
 201:                 vp[0] = OTHERSH;
 202:             (void) close(ff);
 203: #endif
 204:         } else
 205:             vp = v->vec;
 206:         t[0] = f;
 207:         t = blkspl(vp, t);      /* Splice up the new arglst */
 208:         f = *t;
 209:         xfree((char *)t);
 210:         execv(f, t);
 211:         /* The sky is falling, the sky is falling! */
 212: 
 213:     case ENOMEM:
 214:         Perror(f);
 215: 
 216:     case ENOENT:
 217:         break;
 218: 
 219:     default:
 220:         if (exerr == 0) {
 221:             exerr = syserrlst(errno);
 222:             expath = savestr(f);
 223:         }
 224:     }
 225: }
 226: 
 227: /*ARGSUSED*/
 228: execash(t, kp)
 229:     char **t;
 230:     register struct command *kp;
 231: {
 232: 
 233:     rechist();
 234:     (void) signal(SIGINT, parintr);
 235:     (void) signal(SIGQUIT, parintr);
 236:     (void) signal(SIGTERM, parterm);    /* if doexec loses, screw */
 237:     lshift(kp->t_dcom, 1);
 238:     exiterr++;
 239:     doexec(kp);
 240:     /*NOTREACHED*/
 241: }
 242: 
 243: xechoit(t)
 244:     char **t;
 245: {
 246: 
 247:     if (adrof("echo")) {
 248:         flush();
 249:         haderr = 1;
 250:         blkpr(t), putchar('\n');
 251:         haderr = 0;
 252:     }
 253: }
 254: 
 255: /*VARARGS0*//*ARGSUSED*/
 256: dohash()
 257: {
 258:     struct stat stb;
 259:     DIR *dirp;
 260:     register struct direct *dp;
 261:     register int cnt;
 262:     int i = 0;
 263:     struct varent *v = adrof("path");
 264:     char **pv;
 265:     int hashval;
 266: 
 267:     havhash = 1;
 268:     for (cnt = 0; cnt < sizeof xhash; cnt++)
 269:         xhash[cnt] = 0;
 270:     if (v == 0)
 271:         return;
 272:     for (pv = v->vec; *pv; pv++, i++) {
 273:         if (pv[0][0] != '/')
 274:             continue;
 275:         dirp = opendir(*pv);
 276:         if (dirp == NULL)
 277:             continue;
 278:         if (fstat(dirp->dd_fd, &stb) < 0 || !S_ISDIR(stb.st_mode)) {
 279:             closedir(dirp);
 280:             continue;
 281:         }
 282:         while ((dp = readdir(dirp)) != NULL) {
 283:             if (dp->d_ino == 0)
 284:                 continue;
 285:             if (dp->d_name[0] == '.' &&
 286:                 (dp->d_name[1] == '\0' ||
 287:                  dp->d_name[1] == '.' && dp->d_name[2] == '\0'))
 288:                 continue;
 289:             hashval = hash(hashname(dp->d_name), i);
 290:             bis(xhash, hashval);
 291:         }
 292:         closedir(dirp);
 293:     }
 294: }
 295: 
 296: dounhash()
 297: {
 298: 
 299:     havhash = 0;
 300: }
 301: 
 302: #ifdef VFORK
 303: hashstat()
 304: {
 305: 
 306:     if (hits+misses)
 307:         printf("%d hits, %d misses, %d%%\n",
 308:             hits, misses,
 309:             (int)(100L * hits / (hits + misses)));
 310: }
 311: #endif
 312: 
 313: /*
 314:  * Hash a command name.
 315:  */
 316: hashname(cp)
 317:     register char *cp;
 318: {
 319:     register long h = 0;
 320: 
 321:     while (*cp)
 322:         h = hash(h, *cp++);
 323:     return ((int) h);
 324: }

Defined functions

doexec defined in line 41; used 2 times
dounhash defined in line 296; used 2 times
execash defined in line 228; used 2 times
hashname defined in line 316; used 3 times
hashstat defined in line 303; used 2 times
pexerr defined in line 155; used 2 times
texec defined in line 171; used 2 times
xechoit defined in line 243; used 2 times

Defined variables

exerr defined in line 33; used 5 times
expath defined in line 34; used 4 times
justabs defined in line 39; used 3 times
sccsid defined in line 8; never used
Last modified: 1996-09-22
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 4463
Valid CSS Valid XHTML 1.0 Strict