Annotation of 40BSD/cmd/csh/sh.exec.c, revision 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.