Annotation of 42BSD/bin/csh/sh.exec.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.