Annotation of 43BSDReno/bin/csh/sh.exec.c, revision 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.