Annotation of 43BSDReno/bin/csh/sh.exec.c, revision 1.1.1.1

1.1       root        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: #ifndef lint
                      8: static char *sccsid = "@(#)sh.exec.c   5.7 (Berkeley) 5/27/90";
                      9: #endif
                     10: 
                     11: #include "sh.h"
                     12: #include <sys/dir.h>
                     13: #include <string.h>
                     14: #include "pathnames.h"
                     15: 
                     16: /*
                     17:  * C shell
                     18:  */
                     19: 
                     20: /*
                     21:  * System level search and execute of a command.
                     22:  * We look in each directory for the specified command name.
                     23:  * If the name contains a '/' then we execute only the full path name.
                     24:  * If there is no search path then we execute only full path names.
                     25:  */
                     26: 
                     27: /* 
                     28:  * As we search for the command we note the first non-trivial error
                     29:  * message for presentation to the user.  This allows us often
                     30:  * to show that a file has the wrong mode/no access when the file
                     31:  * is not in the last component of the search path, so we must
                     32:  * go on after first detecting the error.
                     33:  */
                     34: char   *exerr;                 /* Execution error message */
                     35: char   *expath;                /* Path for exerr */
                     36: 
                     37: /*
                     38:  * Xhash is an array of HSHSIZ bits (HSHSIZ / 8 chars), which are used
                     39:  * to hash execs.  If it is allocated (havhash true), then to tell
                     40:  * whether ``name'' is (possibly) present in the i'th component
                     41:  * of the variable path, you look at the bit in xhash indexed by
                     42:  * hash(hashname("name"), i).  This is setup automatically
                     43:  * after .login is executed, and recomputed whenever ``path'' is
                     44:  * changed.
                     45:  * The two part hash function is designed to let texec() call the
                     46:  * more expensive hashname() only once and the simple hash() several
                     47:  * times (once for each path component checked).
                     48:  * Byte size is assumed to be 8.
                     49:  */
                     50: #define        HSHSIZ          8192                    /* 1k bytes */
                     51: #define HSHMASK                (HSHSIZ - 1)
                     52: #define HSHMUL         243
                     53: char   xhash[HSHSIZ / 8];
                     54: #define hash(a, b)     ((a) * HSHMUL + (b) & HSHMASK)
                     55: #define bit(h, b)      ((h)[(b) >> 3] & 1 << ((b) & 7))        /* bit test */
                     56: #define bis(h, b)      ((h)[(b) >> 3] |= 1 << ((b) & 7))       /* bit set */
                     57: #ifdef VFORK
                     58: int    hits, misses;
                     59: #endif
                     60: 
                     61: /* Dummy search path for just absolute search when no path */
                     62: char   *justabs[] =    { "", 0 };
                     63: 
                     64: doexec(t)
                     65:        register struct command *t;
                     66: {
                     67:        char *sav;
                     68:        register char *dp, **pv, **av;
                     69:        register struct varent *v;
                     70:        bool slash = any('/', t->t_dcom[0]);
                     71:        int hashval, hashval1, i;
                     72:        char *blk[2];
                     73: 
                     74:        /*
                     75:         * Glob the command name.  If this does anything, then we
                     76:         * will execute the command only relative to ".".  One special
                     77:         * case: if there is no PATH, then we execute only commands
                     78:         * which start with '/'.
                     79:         */
                     80:        dp = globone(t->t_dcom[0]);
                     81:        sav = t->t_dcom[0];
                     82:        exerr = 0; expath = t->t_dcom[0] = dp;
                     83:        xfree(sav);
                     84:        v = adrof("path");
                     85:        if (v == 0 && expath[0] != '/')
                     86:                pexerr();
                     87:        slash |= gflag;
                     88: 
                     89:        /*
                     90:         * Glob the argument list, if necessary.
                     91:         * Otherwise trim off the quote bits.
                     92:         */
                     93:        gflag = 0; av = &t->t_dcom[1];
                     94:        tglob(av);
                     95:        if (gflag) {
                     96:                av = glob(av);
                     97:                if (av == 0)
                     98:                        error("No match");
                     99:        }
                    100:        blk[0] = t->t_dcom[0];
                    101:        blk[1] = 0;
                    102:        av = blkspl(blk, av);
                    103: #ifdef VFORK
                    104:        Vav = av;
                    105: #endif
                    106:        trim(av);
                    107: 
                    108:        xechoit(av);            /* Echo command if -x */
                    109:        /*
                    110:         * Since all internal file descriptors are set to close on exec,
                    111:         * we don't need to close them explicitly here.  Just reorient
                    112:         * ourselves for error messages.
                    113:         */
                    114:        SHIN = 0; SHOUT = 1; SHDIAG = 2; OLDSTD = 0;
                    115: 
                    116:        /*
                    117:         * We must do this AFTER any possible forking (like `foo`
                    118:         * in glob) so that this shell can still do subprocesses.
                    119:         */
                    120:        (void) sigsetmask(0L);
                    121: 
                    122:        /*
                    123:         * If no path, no words in path, or a / in the filename
                    124:         * then restrict the command search.
                    125:         */
                    126:        if (v == 0 || v->vec[0] == 0 || slash)
                    127:                pv = justabs;
                    128:        else
                    129:                pv = v->vec;
                    130:        sav = strspl("/", *av);         /* / command name for postpending */
                    131: #ifdef VFORK
                    132:        Vsav = sav;
                    133: #endif
                    134:        if (havhash)
                    135:                hashval = hashname(*av);
                    136:        i = 0;
                    137: #ifdef VFORK
                    138:        hits++;
                    139: #endif
                    140:        do {
                    141:                if (!slash && pv[0][0] == '/' && havhash) {
                    142:                        hashval1 = hash(hashval, i);
                    143:                        if (!bit(xhash, hashval1))
                    144:                                goto cont;
                    145:                }
                    146:                if (pv[0][0] == 0 || eq(pv[0], "."))    /* don't make ./xxx */
                    147:                        texec(*av, av);
                    148:                else {
                    149:                        dp = strspl(*pv, sav);
                    150: #ifdef VFORK
                    151:                        Vdp = dp;
                    152: #endif
                    153:                        texec(dp, av);
                    154: #ifdef VFORK
                    155:                        Vdp = 0;
                    156: #endif
                    157:                        xfree(dp);
                    158:                }
                    159: #ifdef VFORK
                    160:                misses++;
                    161: #endif
                    162: cont:
                    163:                pv++;
                    164:                i++;
                    165:        } while (*pv);
                    166: #ifdef VFORK
                    167:        hits--;
                    168: #endif
                    169: #ifdef VFORK
                    170:        Vsav = 0;
                    171:        Vav = 0;
                    172: #endif
                    173:        xfree(sav);
                    174:        xfree((char *)av);
                    175:        pexerr();
                    176: }
                    177: 
                    178: pexerr()
                    179: {
                    180: 
                    181:        /* Couldn't find the damn thing */
                    182:        setname(expath);
                    183:        /* xfree(expath); */
                    184:        if (exerr)
                    185:                bferr(exerr);
                    186:        bferr("Command not found");
                    187: }
                    188: 
                    189: /*
                    190:  * Execute command f, arg list t.
                    191:  * Record error message if not found.
                    192:  * Also do shell scripts here.
                    193:  */
                    194: texec(f, t)
                    195:        char *f;
                    196:        register char **t;
                    197: {
                    198:        register struct varent *v;
                    199:        register char **vp;
                    200:        char *lastsh[2];
                    201: 
                    202:        execv(f, t);
                    203:        switch (errno) {
                    204: 
                    205:        case ENOEXEC:
                    206:                /*
                    207:                 * If there is an alias for shell, then
                    208:                 * put the words of the alias in front of the
                    209:                 * argument list replacing the command name.
                    210:                 * Note no interpretation of the words at this point.
                    211:                 */
                    212:                v = adrof1("shell", &aliases);
                    213:                if (v == 0) {
                    214:                        register int ff = open(f, 0);
                    215:                        char ch;
                    216: 
                    217:                        vp = lastsh;
                    218:                        vp[0] = adrof("shell") ? value("shell") : _PATH_CSHELL;
                    219:                        vp[1] = (char *) NULL;
                    220:                        if (ff != -1 && read(ff, &ch, 1) == 1 && ch != '#')
                    221:                                vp[0] = _PATH_BSHELL;
                    222:                        (void) close(ff);
                    223:                } else
                    224:                        vp = v->vec;
                    225:                t[0] = f;
                    226:                t = blkspl(vp, t);              /* Splice up the new arglst */
                    227:                f = *t;
                    228:                execv(f, t);
                    229:                xfree((char *)t);
                    230:                /* The sky is falling, the sky is falling! */
                    231: 
                    232:        case ENOMEM:
                    233:                Perror(f);
                    234: 
                    235:        case ENOENT:
                    236:                break;
                    237: 
                    238:        default:
                    239:                if (exerr == 0) {
                    240:                        exerr = strerror(errno);
                    241:                        expath = savestr(f);
                    242:                }
                    243:        }
                    244: }
                    245: 
                    246: /*ARGSUSED*/
                    247: execash(t, kp)
                    248:        char **t;
                    249:        register struct command *kp;
                    250: {
                    251: 
                    252:        rechist();
                    253:        (void) signal(SIGINT, parintr);
                    254:        (void) signal(SIGQUIT, parintr);
                    255:        (void) signal(SIGTERM, parterm);        /* if doexec loses, screw */
                    256:        lshift(kp->t_dcom, 1);
                    257:        exiterr++;
                    258:        doexec(kp);
                    259:        /*NOTREACHED*/
                    260: }
                    261: 
                    262: xechoit(t)
                    263:        char **t;
                    264: {
                    265: 
                    266:        if (adrof("echo")) {
                    267:                flush();
                    268:                haderr = 1;
                    269:                blkpr(t), cshputchar('\n');
                    270:                haderr = 0;
                    271:        }
                    272: }
                    273: 
                    274: /*VARARGS0*//*ARGSUSED*/
                    275: dohash()
                    276: {
                    277:        struct stat stb;
                    278:        DIR *dirp;
                    279:        register struct direct *dp;
                    280:        register int cnt;
                    281:        int i = 0;
                    282:        struct varent *v = adrof("path");
                    283:        char **pv;
                    284:        int hashval;
                    285: 
                    286:        havhash = 1;
                    287:        for (cnt = 0; cnt < sizeof xhash; cnt++)
                    288:                xhash[cnt] = 0;
                    289:        if (v == 0)
                    290:                return;
                    291:        for (pv = v->vec; *pv; pv++, i++) {
                    292:                if (pv[0][0] != '/')
                    293:                        continue;
                    294:                dirp = opendir(*pv);
                    295:                if (dirp == NULL)
                    296:                        continue;
                    297:                if (fstat(dirp->dd_fd, &stb) < 0 || !isdir(stb)) {
                    298:                        closedir(dirp);
                    299:                        continue;
                    300:                }
                    301:                while ((dp = readdir(dirp)) != NULL) {
                    302:                        if (dp->d_ino == 0)
                    303:                                continue;
                    304:                        if (dp->d_name[0] == '.' &&
                    305:                            (dp->d_name[1] == '\0' ||
                    306:                             dp->d_name[1] == '.' && dp->d_name[2] == '\0'))
                    307:                                continue;
                    308:                        hashval = hash(hashname(dp->d_name), i);
                    309:                        bis(xhash, hashval);
                    310:                }
                    311:                closedir(dirp);
                    312:        }
                    313: }
                    314: 
                    315: dounhash()
                    316: {
                    317: 
                    318:        havhash = 0;
                    319: }
                    320: 
                    321: #ifdef VFORK
                    322: hashstat()
                    323: {
                    324: 
                    325:        if (hits+misses)
                    326:                printf("%d hits, %d misses, %d%%\n",
                    327:                        hits, misses, 100 * hits / (hits + misses));
                    328: }
                    329: #endif
                    330: 
                    331: /*
                    332:  * Hash a command name.
                    333:  */
                    334: hashname(cp)
                    335:        register char *cp;
                    336: {
                    337:        register long h = 0;
                    338: 
                    339:        while (*cp)
                    340:                h = hash(h, *cp++);
                    341:        return ((int) h);
                    342: }

unix.superglobalmegacorp.com

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