Annotation of researchv10no/lbin/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: #include <ndir.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:        sigsys(SIGCHLD, SIG_IGN);       /* sigsys for vforks sake */
                     97: 
                     98:        /*
                     99:         * If no path, no words in path, or a / in the filename
                    100:         * then restrict the command search.
                    101:         */
                    102:        if (v == 0 || v->vec[0] == 0 || slash)
                    103:                pv = justabs;
                    104:        else
                    105:                pv = v->vec;
                    106:        sav = strspl("/", *av);         /* / command name for postpending */
                    107: #ifdef VFORK
                    108:        Vsav = sav;
                    109: #endif
                    110:        if (havhash)
                    111:                hashval = xhash[hash(*av)];
                    112:        i = 0;
                    113: #ifdef VFORK
                    114:        hits++;
                    115: #endif
                    116:        do {
                    117:                if (!slash && pv[0][0] == '/' && havhash && (hashval & (1 << (i % 8))) == 0)
                    118:                        goto cont;
                    119:                if (pv[0][0] == 0 || eq(pv[0], "."))    /* don't make ./xxx */
                    120:                        texec(*av, av);
                    121:                else {
                    122:                        dp = strspl(*pv, sav);
                    123: #ifdef VFORK
                    124:                        Vdp = dp;
                    125: #endif
                    126:                        texec(dp, av);
                    127: #ifdef VFORK
                    128:                        Vdp = 0;
                    129: #endif
                    130:                        xfree(dp);
                    131:                }
                    132: #ifdef VFORK
                    133:                misses++;
                    134: #endif
                    135: cont:
                    136:                pv++;
                    137:                i++;
                    138:        } while (*pv);
                    139: #ifdef VFORK
                    140:        hits--;
                    141: #endif
                    142: #ifdef VFORK
                    143:        Vsav = 0;
                    144:        Vav = 0;
                    145: #endif
                    146:        xfree(sav);
                    147:        xfree(av);
                    148:        pexerr();
                    149: }
                    150: 
                    151: pexerr()
                    152: {
                    153: 
                    154:        /* Couldn't find the damn thing */
                    155:        setname(expath);
                    156:        /* xfree(expath); */
                    157:        if (exerr)
                    158:                bferr(exerr);
                    159:        bferr("Command not found");
                    160: }
                    161: 
                    162: /* Last resort shell */
                    163: char   *lastsh[] =     { SHELLPATH, 0 };
                    164: 
                    165: /*
                    166:  * Execute command f, arg list t.
                    167:  * Record error message if not found.
                    168:  * Also do shell scripts here.
                    169:  */
                    170: texec(f, t)
                    171:        char *f;
                    172:        register char **t;
                    173: {
                    174:        register struct varent *v;
                    175:        register char **vp;
                    176:        extern char *sys_errlist[];
                    177: 
                    178:        execv(f, t);
                    179:        switch (errno) {
                    180: 
                    181:        case ENOEXEC:
                    182:                /*
                    183:                 * If there is an alias for shell, then
                    184:                 * put the words of the alias in front of the
                    185:                 * argument list replacing the command name.
                    186:                 * Note no interpretation of the words at this point.
                    187:                 */
                    188:                v = adrof1("shell", &aliases);
                    189:                if (v == 0) {
                    190: #ifdef OTHERSH
                    191:                        register int ff = open(f, 0);
                    192:                        char ch;
                    193: #endif
                    194: 
                    195:                        vp = lastsh;
                    196:                        vp[0] = adrof("shell") ? value("shell") : SHELLPATH;
                    197: #ifdef OTHERSH
                    198:                        if (ff != -1 && read(ff, &ch, 1) == 1 && ch != '#')
                    199:                                vp[0] = OTHERSH;
                    200:                        close(ff);
                    201: #endif
                    202:                } else
                    203:                        vp = v->vec;
                    204:                t[0] = f;
                    205:                t = blkspl(vp, t);              /* Splice up the new arglst */
                    206:                f = *t;
                    207:                execv(f, t);
                    208:                xfree((char *)t);
                    209:                /* The sky is falling, the sky is falling! */
                    210: 
                    211:        case ENOMEM:
                    212:                Perror(f);
                    213: 
                    214:        case ENOENT:
                    215:                break;
                    216: 
                    217:        default:
                    218:                if (exerr == 0) {
                    219:                        exerr = sys_errlist[errno];
                    220:                        expath = savestr(f);
                    221:                }
                    222:        }
                    223: }
                    224: 
                    225: execash(t, kp)
                    226:        register struct command *kp;
                    227: {
                    228: 
                    229:        didcch++;
                    230:        signal(SIGINT, parintr);
                    231:        signal(SIGQUIT, parintr);
                    232:        signal(SIGTERM, parterm);               /* if doexec loses, screw */
                    233:        lshift(kp->t_dcom, 1);
                    234:        exiterr++;
                    235:        doexec(kp);
                    236:        /*NOTREACHED*/
                    237: }
                    238: 
                    239: xechoit(t)
                    240:        char **t;
                    241: {
                    242: 
                    243:        if (adrof("echo")) {
                    244:                flush();
                    245:                haderr = 1;
                    246:                blkpr(t), printf("\n");
                    247:                haderr = 0;
                    248:        }
                    249: }
                    250: 
                    251: dohash()
                    252: {
                    253:        struct stat stb;
                    254:        register struct direct *dp;
                    255:        DIR *df;
                    256:        int i = 0;
                    257:        register int cnt;
                    258:        struct varent *v = adrof("path");
                    259:        register char **pv;
                    260: 
                    261:        havhash = 1;
                    262:        for (cnt = 0; cnt < HSHSIZ; cnt++)
                    263:                xhash[cnt] = 0;
                    264:        if (v == 0)
                    265:                return;
                    266:        for (pv = v->vec; *pv; pv++, i = (i + 1) % 8) {
                    267:                if (pv[0][0] != '/')
                    268:                        continue;
                    269:                df = opendir(*pv);
                    270:                if (df == 0)
                    271:                        continue;
                    272:                if (stat(*pv, &stb) < 0 || !isdir(stb)) {
                    273:                        closedir(df);
                    274:                        continue;
                    275:                }
                    276:                while ((dp = readdir(df)) != 0) {
                    277:                        if (dp->d_ino == 0)
                    278:                                continue;
                    279:                        xhash[hash(dp->d_name)] |= (1 << i);
                    280:                }
                    281:                closedir(df);
                    282:        }
                    283: }
                    284: 
                    285: dounhash()
                    286: {
                    287: 
                    288:        havhash = 0;
                    289: }
                    290: 
                    291: #ifdef VFORK
                    292: hashstat()
                    293: {
                    294: 
                    295:        if (hits+misses)
                    296:        printf("%d hits, %d misses, %2d%%\n", hits, misses, 100 * hits / (hits + misses));
                    297: }
                    298: #endif
                    299: 
                    300: hash(cp)
                    301:        register char *cp;
                    302: {
                    303:        register long hash = 0;
                    304:        int retval;
                    305: 
                    306:        while (*cp)
                    307:                hash += hash + *cp++;
                    308:        if (hash < 0)
                    309:                hash = -hash;
                    310:        retval = hash % HSHSIZ;
                    311:        return (retval);
                    312: }

unix.superglobalmegacorp.com

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