Annotation of 41BSD/cmd/csh/sh.exec.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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