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

1.1       root        1: /* Copyright (c) 1979 Regents of the University of California */
                      2: #include "sh.h"
                      3: 
                      4: /*
                      5:  * C shell
                      6:  */
                      7: 
                      8: /*
                      9:  * System level search and execute of a command.
                     10:  * We look in each directory for the specified command name.
                     11:  * If the name contains a '/' then we execute only the full path name.
                     12:  * If there is no search path then we execute only full path names.
                     13:  */
                     14: 
                     15: /* 
                     16:  * As we search for the command we note the first non-trivial error
                     17:  * message for presentation to the user.  This allows us often
                     18:  * to show that a file has the wrong mode/no access when the file
                     19:  * is not in the last component of the search path, so we must
                     20:  * go on after first detecting the error.
                     21:  */
                     22: char   *exerr;                 /* Execution error message */
                     23: char   *expath;                /* Path for exerr */
                     24: 
                     25: /*
                     26:  * Xhash is an array of HSHSIZ chars, which are used to hash execs.
                     27:  * If it is allocated, then to tell whether ``name'' is (possibly)
                     28:  * present in the i'th component of the variable path, you look at
                     29:  * the i'th bit of xhash[hash("name")].  This is setup automatically
                     30:  * after .login is executed, and recomputed whenever ``path'' is
                     31:  * changed.
                     32:  */
                     33: int    havhash;
                     34: #define        HSHSIZ  511
                     35: char   xhash[HSHSIZ];
                     36: int    hits, misses;
                     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, 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:        rscan(av, tglob);
                     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:        scan(av, trim);
                     84: 
                     85:        xechoit(av);            /* Echo command if -x */
                     86:        closech();              /* Close random fd's */
                     87: 
                     88:        /*
                     89:         * If no path, no words in path, or a / in the filename
                     90:         * then restrict the command search.
                     91:         */
                     92:        if (v == 0 || v->vec[0] == 0 || slash)
                     93:                pv = justabs;
                     94:        else
                     95:                pv = v->vec;
                     96:        sav = strspl("/", *av);         /* / command name for postpending */
                     97: #ifdef VFORK
                     98:        Vsav = sav;
                     99: #endif
                    100:        if (havhash)
                    101:                hashval = xhash[hash(*av)];
                    102:        i = 0;
                    103:        hits++;
                    104:        do {
                    105:                if (!slash && pv[0][0] == '/' && havhash && (hashval & (1 << (i % 8))) == 0)
                    106:                        goto cont;
                    107:                if (pv[0][0] == 0 || eq(pv[0], "."))    /* don't make ./xxx */
                    108:                        texec(*av, av);
                    109:                else {
                    110:                        dp = strspl(*pv, sav);
                    111: #ifdef VFORK
                    112:                        Vdp = dp;
                    113: #endif
                    114:                        texec(dp, av);
                    115: #ifdef VFORK
                    116:                        Vdp = 0;
                    117: #endif
                    118:                        xfree(dp);
                    119:                }
                    120:                misses++;
                    121: cont:
                    122:                pv++;
                    123:                i++;
                    124:        } while (*pv);
                    125:        hits--;
                    126: #ifdef VFORK
                    127:        Vsav = 0;
                    128:        Vav = 0;
                    129: #endif
                    130:        xfree(sav);
                    131:        xfree(av);
                    132:        pexerr();
                    133: }
                    134: 
                    135: pexerr()
                    136: {
                    137: 
                    138:        /* Couldn't find the damn thing */
                    139:        setname(expath);
                    140:        /* xfree(expath); */
                    141:        if (exerr)
                    142:                bferr(exerr);
                    143:        bferr("Command not found");
                    144: }
                    145: 
                    146: /* Last resort shell */
                    147: char   *lastsh[] =     { SHELLPATH, 0 };
                    148: 
                    149: /*
                    150:  * Execute command f, arg list t.
                    151:  * Record error message if not found.
                    152:  * Also do shell scripts here.
                    153:  */
                    154: texec(f, t)
                    155:        char *f;
                    156:        register char **t;
                    157: {
                    158:        register struct varent *v;
                    159:        register char **vp;
                    160:        extern char *sys_errlist[];
                    161: 
                    162:        execv(f, t);
                    163:        switch (errno) {
                    164: 
                    165:        case ENOEXEC:
                    166:                /*
                    167:                 * If there is an alias for shell, then
                    168:                 * put the words of the alias in front of the
                    169:                 * argument list replacing the command name.
                    170:                 * Note no interpretation of the words at this point.
                    171:                 */
                    172:                v = adrof1("shell", &aliases);
                    173:                if (v == 0) {
                    174: #ifdef OTHERSH
                    175:                        register int ff = open(f, 0);
                    176:                        char ch;
                    177: #endif
                    178: 
                    179:                        vp = lastsh;
                    180:                        vp[0] = adrof("shell") ? value("shell") : SHELLPATH;
                    181: #ifdef OTHERSH
                    182:                        if (ff != -1 && read(ff, &ch, 1) == 1 && ch != '#')
                    183:                                vp[0] = OTHERSH;
                    184:                        close(ff);
                    185: #endif
                    186:                } else
                    187:                        vp = v->vec;
                    188:                t[0] = f;
                    189:                t = blkspl(vp, t);              /* Splice up the new arglst */
                    190:                f = *t;
                    191:                execv(f, t);
                    192:                xfree(t);
                    193:                /* The sky is falling, the sky is falling! */
                    194: 
                    195:        case ENOMEM:
                    196:                Perror(f);
                    197: 
                    198:        case ENOENT:
                    199:                break;
                    200: 
                    201:        default:
                    202:                if (exerr == 0) {
                    203:                        exerr = sys_errlist[errno];
                    204:                        expath = savestr(f);
                    205:                }
                    206:        }
                    207: }
                    208: 
                    209: execash(t, kp)
                    210:        register struct command *kp;
                    211: {
                    212: 
                    213:        didcch++;
                    214:        lshift(kp->t_dcom, 1);
                    215:        doexec(kp);
                    216:        /*NOTREACHED*/
                    217: }
                    218: 
                    219: xechoit(t)
                    220:        char **t;
                    221: {
                    222: 
                    223:        if (adrof("echo")) {
                    224:                flush();
                    225:                haderr = 1;
                    226:                blkpr(t), printf("\n");
                    227:                haderr = 0;
                    228:        }
                    229: }
                    230: 
                    231: dohash()
                    232: {
                    233:        struct stat stb;
                    234:        struct direct dirbuf[BUFSIZ / sizeof (struct direct)];
                    235:        char d_name[DIRSIZ + 1];
                    236:        register int dirf, cnt;
                    237:        int i = 0;
                    238:        struct varent *v = adrof("path");
                    239:        char **pv;
                    240: 
                    241:        havhash = 1;
                    242:        for (cnt = 0; cnt < HSHSIZ; cnt++)
                    243:                xhash[cnt] = 0;
                    244:        if (v == 0)
                    245:                return;
                    246:        for (pv = v->vec; *pv; pv++, i = (i + 1) % 8) {
                    247:                if (pv[0][0] != '/')
                    248:                        continue;
                    249:                dirf = open(*pv, 0);
                    250:                if (dirf < 0)
                    251:                        continue;
                    252:                if (fstat(dirf, &stb) < 0 || !isdir(stb)) {
                    253:                        close(dirf);
                    254:                        continue;
                    255:                }
                    256:                while ((cnt = read(dirf, (char *) dirbuf, sizeof dirbuf)) >= sizeof dirbuf[0]) {
                    257:                        register struct direct *ep = dirbuf;
                    258: 
                    259:                        for (cnt /= sizeof(struct direct); cnt > 0; cnt--, ep++) {
                    260:                                if (ep->d_ino == 0)
                    261:                                        continue;
                    262:                                copdent(d_name, ep->d_name);
                    263:                                xhash[hash(d_name)] |= (1 << i);
                    264:                        }
                    265:                }
                    266:                close(dirf);
                    267:        }
                    268: }
                    269: 
                    270: dounhash()
                    271: {
                    272: 
                    273:        havhash = 0;
                    274: }
                    275: 
                    276: hashstat()
                    277: {
                    278: 
                    279:        if (hits+misses)
                    280:        printf("%d hits, %d misses, %2d%%\n", hits, misses, 100 * hits / (hits + misses));
                    281: }
                    282: 
                    283: hash(cp)
                    284:        register char *cp;
                    285: {
                    286:        register int hash = 0;
                    287: 
                    288:        while (*cp)
                    289:                hash += hash + *cp++;
                    290:        return (hash % HSHSIZ);
                    291: }

unix.superglobalmegacorp.com

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