# 2.11BSD#431 - /usr/src/bin/tcsh/sh.exec.c

##### Functions

    doexec            X
    dohash            X
    dounhash          X
    execash           X
    executable        X
    hashstat          X
    iscommand         X
    tellmewhat        X
    xechoit           X

##### Macros

    HSHMASK           X
    HSHMUL            X
    HSHSIZ            X
    bis               X
    bit               X
    hash              X

       1: /* $Header: /home/hyperion/mu/christos/src/sys/tcsh-6.00/RCS/sh.exec.c,v 3.0 1991/07/04 21:49:28 christos Exp $ */
       2: /*
       3:  * sh.exec.c: Search, find, and execute a command!
       4:  */
       5: /*-
       6:  * Copyright (c) 1980, 1991 The Regents of the University of California.
       7:  * All rights reserved.
       8:  *
       9:  * Redistribution and use in source and binary forms, with or without
      10:  * modification, are permitted provided that the following conditions
      11:  * are met:
      12:  * 1. Redistributions of source code must retain the above copyright
      13:  *    notice, this list of conditions and the following disclaimer.
      14:  * 2. Redistributions in binary form must reproduce the above copyright
      15:  *    notice, this list of conditions and the following disclaimer in the
      16:  *    documentation and/or other materials provided with the distribution.
      17:  * 3. All advertising materials mentioning features or use of this software
      18:  *    must display the following acknowledgement:
      19:  *	This product includes software developed by the University of
      20:  *	California, Berkeley and its contributors.
      21:  * 4. Neither the name of the University nor the names of its contributors
      22:  *    may be used to endorse or promote products derived from this software
      23:  *    without specific prior written permission.
      24:  *
      25:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
      26:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
      27:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
      28:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
      29:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
      30:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
      31:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
      32:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
      33:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
      34:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
      35:  * SUCH DAMAGE.
      36:  */
      37: #include "config.h"
      38: #if !defined(lint) && !defined(pdp11)
      39: static char *rcsid()
      40:     { return "$Id: sh.exec.c,v 3.0 1991/07/04 21:49:28 christos Exp $"; }
      41: #endif
      42:
      43: #include "sh.h"
      44: #include "tw.h"
      45:
      46: /*
      47:  * C shell
      48:  */
      49:
      50: /*
      51:  * System level search and execute of a command.
      52:  * We look in each directory for the specified command name.
      53:  * If the name contains a '/' then we execute only the full path name.
      54:  * If there is no search path then we execute only full path names.
      55:  */
      56:
      57: /*
      58:  * As we search for the command we note the first non-trivial error
      59:  * message for presentation to the user.  This allows us often
      60:  * to show that a file has the wrong mode/no access when the file
      61:  * is not in the last component of the search path, so we must
      62:  * go on after first detecting the error.
      63:  */
      64: static char *exerr;     /* Execution error message */
      65: static Char *expath;        /* Path for exerr */
      66:
      67: /*
      68:  * Xhash is an array of HSHSIZ bits (HSHSIZ / 8 chars), which are used
      69:  * to hash execs.  If it is allocated (havhash true), then to tell
      70:  * whether ``name'' is (possibly) present in the i'th component
      71:  * of the variable path, you look at the bit in xhash indexed by
      72:  * hash(hashname("name"), i).  This is setup automatically
      73:  * after .login is executed, and recomputed whenever ``path'' is
      74:  * changed.
      75:  * The two part hash function is designed to let texec() call the
      76:  * more expensive hashname() only once and the simple hash() several
      77:  * times (once for each path component checked).
      78:  * Byte size is assumed to be 8.
      79:  */
      80: #define HSHSIZ      8192    /* 1k bytes */
      81: #define HSHMASK     (HSHSIZ - 1)
      82: #define HSHMUL      243
      83: static char xhash[HSHSIZ / 8];
      84:
      85: #define hash(a, b)  ((a) * HSHMUL + (b) & HSHMASK)
      86: #define bit(h, b)   ((h)[(b) >> 3] & 1 << ((b) & 7))    /* bit test */
      87: #define bis(h, b)   ((h)[(b) >> 3] |= 1 << ((b) & 7))   /* bit set */
      88: #ifdef VFORK
      89: static int hits, misses;
      90:
      91: #endif
      92:
      93: /* Dummy search path for just absolute search when no path */
      94: static Char *justabs[] = {STRNULL, 0};
      95:
      96: static  void    pexerr      __P((void));
      97: static  void    texec       __P((Char *, Char **));
      98: static  int hashname    __P((Char *));
      99:
     100: void
     101: doexec(t)
     102:     register struct command *t;
     103: {
     104:     register Char *dp, **pv, **av, *sav;
     105:     register struct varent *v;
     106:     register bool slash;
     107:     register int hshval = 0, hshval1, i;
     108:     Char   *blk[2];
     109:
     110:     /*
     111:      * Glob the command name. We will search $path even if this does something,
     112:      * as in sh but not in csh.  One special case: if there is no PATH, then we
     113:      * execute only commands which start with '/'.
     114:      */
     115:     blk[0] = t->t_dcom[0];
     116:     blk[1] = 0;
     117:     gflag = 0, tglob(blk);
     118:     if (gflag) {
     119:     pv = globall(blk);
     120:     if (pv == 0) {
     121:         setname(short2str(blk[0]));
     122:         stderror(ERR_NAME | ERR_NOMATCH);
     123:     }
     124:     gargv = 0;
     125:     }
     126:     else
     127:     pv = saveblk(blk);
     128:
     129:     trim(pv);
     130:
     131:     exerr = 0;
     132:     expath = Strsave(pv[0]);
     133: #ifdef VFORK
     134:     Vexpath = expath;
     135: #endif
     136:
     137:     v = adrof(STRpath);
     138:     if (v == 0 && expath[0] != '/') {
     139:     blkfree(pv);
     140:     pexerr();
     141:     }
     142:     slash = any(short2str(expath), '/');
     143:
     144:     /*
     145:      * Glob the argument list, if necessary. Otherwise trim off the quote bits.
     146:      */
     147:     gflag = 0;
     148:     av = &t->t_dcom[1];
     149:     tglob(av);
     150:     if (gflag) {
     151:     av = globall(av);
     152:     if (av == 0) {
     153:         blkfree(pv);
     154:         setname(short2str(expath));
     155:         stderror(ERR_NAME | ERR_NOMATCH);
     156:     }
     157:     gargv = 0;
     158:     }
     159:     else
     160:     av = saveblk(av);
     161:
     162:     blkfree(t->t_dcom);
     163:     t->t_dcom = blkspl(pv, av);
     164:     xfree((ptr_t) pv);
     165:     xfree((ptr_t) av);
     166:     av = t->t_dcom;
     167:     trim(av);
     168:
     169:     if (*av == NULL || **av == '\0')
     170:     pexerr();
     171:
     172:     xechoit(av);        /* Echo command if -x */
     173: #ifdef FIOCLEX
     174:     /*
     175:      * Since all internal file descriptors are set to close on exec, we don't
     176:      * need to close them explicitly here.  Just reorient ourselves for error
     177:      * messages.
     178:      */
     179:     SHIN = 0;
     180:     SHOUT = 1;
     181:     SHDIAG = 2;
     182:     OLDSTD = 0;
     183:     isoutatty = isatty(SHOUT);
     184:     isdiagatty = isatty(SHDIAG);
     185: #else
     186:     closech();          /* Close random fd's */
     187: #endif
     188:     /*
     189:      * We must do this AFTER any possible forking (like `foo` in glob) so that
     190:      * this shell can still do subprocesses.
     191:      */
     192: #ifdef BSDSIGS
     193:     (void) sigsetmask((sigmask_t) 0);
     194: #else               /* BSDSIGS */
     195:     (void) sigrelse(SIGINT);
     196:     (void) sigrelse(SIGCHLD);
     197: #endif				/* BSDSIGS */
     198:
     199:     /*
     200:      * If no path, no words in path, or a / in the filename then restrict the
     201:      * command search.
     202:      */
     203:     if (v == 0 || v->vec[0] == 0 || slash)
     204:     pv = justabs;
     205:     else
     206:     pv = v->vec;
     207:     sav = Strspl(STRslash, *av);/* / command name for postpending */
     208: #ifdef VFORK
     209:     Vsav = sav;
     210: #endif
     211:     if (havhash)
     212:     hshval = hashname(*av);
     213:     i = 0;
     214: #ifdef VFORK
     215:     hits++;
     216: #endif
     217:     do {
     218:     /*
     219: 	 * Try to save time by looking at the hash table for where this command
     220: 	 * could be.  If we are doing delayed hashing, then we put the names in
     221: 	 * one at a time, as the user enters them.  This is kinda like Korn
     222: 	 * Shell's "tracked aliases".
     223: 	 */
     224:     if (!slash && pv[0][0] == '/' && havhash) {
     225:         hshval1 = hash(hshval, i);
     226:         if (!bit(xhash, hshval1))
     227:         goto cont;
     228:     }
     229:     if (pv[0][0] == 0 || eq(pv[0], STRdot)) /* don't make ./xxx */
     230:         texec(*av, av);
     231:     else {
     232:         dp = Strspl(*pv, sav);
     233: #ifdef VFORK
     234:         Vdp = dp;
     235: #endif
     236:         texec(dp, av);
     237: #ifdef VFORK
     238:         Vdp = 0;
     239: #endif
     240:         xfree((ptr_t) dp);
     241:     }
     242: #ifdef VFORK
     243:     misses++;
     244: #endif
     245: cont:
     246:     pv++;
     247:     i++;
     248:     } while (*pv);
     249: #ifdef VFORK
     250:     hits--;
     251: #endif
     252: #ifdef VFORK
     253:     Vsav = 0;
     254: #endif
     255:     xfree((ptr_t) sav);
     256:     pexerr();
     257: }
     258:
     259: static void
     260: pexerr()
     261: {
     262:     /* Couldn't find the damn thing */
     263:     if (expath) {
     264:     setname(short2str(expath));
     265: #ifdef VFORK
     266:     Vexpath = 0;
     267: #endif
     268:     xfree((ptr_t) expath);
     269:     expath = 0;
     270:     }
     271:     else
     272:     setname("");
     273:     if (exerr)
     274:     stderror(ERR_NAME | ERR_STRING, exerr);
     275:     stderror(ERR_NAME | ERR_COMMAND);
     276: }
     277:
     278: /*
     279:  * Execute command f, arg list t.
     280:  * Record error message if not found.
     281:  * Also do shell scripts here.
     282:  */
     283: static void
     284: texec(sf, st)
     285:     Char   *sf;
     286:     register Char **st;
     287: {
     288:     register char **t;
     289:     register char *f;
     290:     register struct varent *v;
     291:     register Char **vp;
     292:     Char   *lastsh[2];
     293:     int     fd;
     294:     unsigned char c;
     295:     Char   *st0, **ost;
     296:
     297:     /* The order for the conversions is significant */
     298:     t = short2blk(st);
     299:     f = short2str(sf);
     300: #ifdef VFORK
     301:     Vt = t;
     302: #endif
     303:     errno = 0;          /* don't use a previous error */
     304: #ifdef apollo
     305:     /*
     306:      * If we try to execute an nfs mounted directory on the apollo, we
     307:      * hang forever. So until apollo fixes that..
     308:      */
     309:     {
     310:     struct stat stb;
     311:     if (stat(f, &stb) == 0 && S_ISDIR(stb.st_mode))
     312:         errno = EISDIR;
     313:     }
     314:     if (errno == 0)
     315: #endif
     316:     (void) execv(f, t);
     317: #ifdef VFORK
     318:     Vt = 0;
     319: #endif
     320:     blkfree((Char **) t);
     321:     switch (errno) {
     322:
     323:     case ENOEXEC:
     324:     /*
     325: 	 * From: casper@fwi.uva.nl (Casper H.S. Dik) If we could not execute
     326: 	 * it, don't feed it to the shell if it looks like a binary!
     327: 	 */
     328:     if ((fd = open(f, O_RDONLY)) != -1) {
     329:         if (read(fd, (char *) &c, 1) == 1) {
     330:         if (!Isprint(c) && (c != '\n' && c != '\t')) {
     331:             (void) close(fd);
     332:             /*
     333: 		     * We *know* what ENOEXEC means.
     334: 		     */
     335:             stderror(ERR_ARCH, f, strerror(errno));
     336:         }
     337:         }
     338: #ifdef _PATH_BSHELL
     339:         else
     340:         c = '#';
     341: #endif
     342:         (void) close(fd);
     343:     }
     344:     /*
     345: 	 * If there is an alias for shell, then put the words of the alias in
     346: 	 * front of the argument list replacing the command name. Note no
     347: 	 * interpretation of the words at this point.
     348: 	 */
     349:     v = adrof1(STRshell, &aliases);
     350:     if (v == 0) {
     351:         vp = lastsh;
     352:         vp[0] = adrof(STRshell) ? value(STRshell) : STR_SHELLPATH;
     353:         vp[1] = NOSTR;
     354: #ifdef _PATH_BSHELL
     355:         if (fd != -1 && c != '#')
     356:         vp[0] = STR_BSHELL;
     357: #endif
     358:     }
     359:     else
     360:         vp = v->vec;
     361:     st0 = st[0];
     362:     st[0] = sf;
     363:     ost = st;
     364:     st = blkspl(vp, st);    /* Splice up the new arglst */
     365:     ost[0] = st0;
     366:     sf = *st;
     367:     /* The order for the conversions is significant */
     368:     t = short2blk(st);
     369:     f = short2str(sf);
     370:     xfree((ptr_t) st);
     371: #ifdef VFORK
     372:     Vt = t;
     373: #endif
     374:     (void) execv(f, t);
     375: #ifdef VFORK
     376:     Vt = 0;
     377: #endif
     378:     blkfree((Char **) t);
     379:     /* The sky is falling, the sky is falling! */
     380:
     381:     case ENOMEM:
     382:     stderror(ERR_SYSTEM, f, strerror(errno));
     383:
     384: #ifdef _IBMR2
     385:     case 0:         /* execv fails and returns 0! */
     386: #endif				/* _IBMR2 */
     387:     case ENOENT:
     388:     break;
     389:
     390:     default:
     391:     if (exerr == 0) {
     392:         exerr = strerror(errno);
     393:         if (expath)
     394:         xfree((ptr_t) expath);
     395:         expath = Strsave(sf);
     396: #ifdef VFORK
     397:         Vexpath = expath;
     398: #endif
     399:     }
     400:     }
     401: }
     402:
     403: /*ARGSUSED*/
     404: void
     405: execash(t, kp)
     406:     char  **t;
     407:     register struct command *kp;
     408: {
     409:     if (chkstop == 0 && setintr)
     410:     panystop(0);
     411: #ifdef notdef
     412:     /*
     413:      * Why we don't want to close SH* on exec? I think we do... Christos
     414:      */
     415: #ifndef FIOCLEX
     416:     didcch = 1;
     417: #endif
     418: #endif				/* notdef */
     419:     rechist();
     420:     (void) signal(SIGINT, parintr);
     421:     (void) signal(SIGQUIT, parintr);
     422:     (void) signal(SIGTERM, parterm);    /* if doexec loses, screw */
     423:     lshift(kp->t_dcom, 1);
     424:     exiterr = 1;
     425:     doexec(kp);
     426:     /* NOTREACHED */
     427: }
     428:
     429: void
     430: xechoit(t)
     431:     Char  **t;
     432: {
     433:     if (adrof(STRecho)) {
     434:     flush();
     435:     haderr = 1;
     436:     blkpr(t), xputchar('\n');
     437:     haderr = 0;
     438:     }
     439: }
     440:
     441: /*VARARGS0*/
     442: void
     443: dohash()
     444: {
     445: #ifdef COMMENT
     446:     struct stat stb;
     447: #endif
     448:     DIR    *dirp;
     449:     register struct dirent *dp;
     450:     register int cnt;
     451:     int     i = 0;
     452:     struct varent *v = adrof(STRpath);
     453:     Char  **pv;
     454:     int     hshval;
     455:
     456:     tw_clear_comm_list();
     457:     havhash = 1;
     458:     for (cnt = 0; cnt < sizeof xhash; cnt++)
     459:     xhash[cnt] = 0;
     460:     if (v == 0)
     461:     return;
     462:     for (pv = v->vec; *pv; pv++, i++) {
     463:     if (pv[0][0] != '/')
     464:         continue;
     465:     dirp = opendir(short2str(*pv));
     466:     if (dirp == NULL)
     467:         continue;
     468: #ifdef COMMENT          /* this isn't needed.  opendir won't open
     469: 				 * non-dirs */
     470:     if (fstat(dirp->dd_fd, &stb) < 0 || !S_ISDIR(stb.st_mode)) {
     471:         (void) closedir(dirp);
     472:         continue;
     473:     }
     474: #endif
     475:     while ((dp = readdir(dirp)) != NULL) {
     476:         if (dp->d_ino == 0)
     477:         continue;
     478:         if (dp->d_name[0] == '.' &&
     479:         (dp->d_name[1] == '\0' ||
     480:          dp->d_name[1] == '.' && dp->d_name[2] == '\0'))
     481:         continue;
     482:         hshval = hash(hashname(str2short(dp->d_name)), i);
     483:         bis(xhash, hshval);
     484:         /* tw_comm_name_add (dp->d_name); */
     485:     }
     486:     (void) closedir(dirp);
     487:     }
     488: }
     489:
     490: void
     491: dounhash()
     492: {
     493:     havhash = 0;
     494: }
     495:
     496: #ifdef VFORK
     497: void
     498: hashstat()
     499: {
     500:     if (hits + misses)
     501:     xprintf("%d hits, %d misses, %d%%\n",
     502:         hits, misses, 100 * hits / (hits + misses));
     503: }
     504:
     505: #endif
     506:
     507: /*
     508:  * Hash a command name.
     509:  */
     510: static int
     511: hashname(cp)
     512:     register Char *cp;
     513: {
     514:     register long h = 0;
     515:
     516:     while (*cp)
     517:     h = hash(h, *cp++);
     518:     return ((int) h);
     519: }
     520:
     521: int
     522: iscommand(name)
     523:     Char   *name;
     524: {
     525:     register Char **pv;
     526:     register Char *sav;
     527:     register struct varent *v;
     528:     register bool slash = any(short2str(name), '/');
     529:     register int hshval = 0, hshval1, i;
     530:
     531:     v = adrof(STRpath);
     532:     if (v == 0 || v->vec[0] == 0 || slash)
     533:     pv = justabs;
     534:     else
     535:     pv = v->vec;
     536:     sav = Strspl(STRslash, name);   /* / command name for postpending */
     537:     if (havhash)
     538:     hshval = hashname(name);
     539:     i = 0;
     540:     do {
     541:     if (!slash && pv[0][0] == '/' && havhash) {
     542:         hshval1 = hash(hshval, i);
     543:         if (!bit(xhash, hshval1))
     544:         goto cont;
     545:     }
     546:     if (pv[0][0] == 0 || eq(pv[0], STRdot)) {   /* don't make ./xxx */
     547:         if (executable(NULL, name, 0)) {
     548:         xfree((ptr_t) sav);
     549:         return i + 1;
     550:         }
     551:     }
     552:     else {
     553:         if (executable(*pv, sav, 0)) {
     554:         xfree((ptr_t) sav);
     555:         return i + 1;
     556:         }
     557:     }
     558: cont:
     559:     pv++;
     560:     i++;
     561:     } while (*pv);
     562:     xfree((ptr_t) sav);
     563:     return 0;
     564: }
     565:
     566: /* Also by:
     567:  *  Andreas Luik <luik@isaak.isa.de>
     568:  *  I S A  GmbH - Informationssysteme fuer computerintegrierte Automatisierung
     569:  *  Azenberstr. 35
     570:  *  D-7000 Stuttgart 1
     571:  *  West-Germany
     572:  * is the executable() routine below and changes to iscommand().
     573:  * Thanks again!!
     574:  */
     575:
     576: /*
     577:  * executable() examines the pathname obtained by concatenating dir and name
     578:  * (dir may be NULL), and returns 1 either if it is executable by us, or
     579:  * if dir_ok is set and the pathname refers to a directory.
     580:  * This is a bit kludgy, but in the name of optimization...
     581:  */
     582: int
     583: executable(dir, name, dir_ok)
     584:     Char   *dir, *name;
     585:     bool    dir_ok;
     586: {
     587:     struct stat stbuf;
     588:     Char    path[MAXPATHLEN + 1];
     589:     char   *strname;
     590:
     591:     if (dir && *dir) {
     592:     copyn(path, dir, MAXPATHLEN);
     593:     catn(path, name, MAXPATHLEN);
     594:     strname = short2str(path);
     595:     }
     596:     else
     597:     strname = short2str(name);
     598:     return (stat(strname, &stbuf) != -1 &&
     599:         ((S_ISREG(stbuf.st_mode) &&
     600:     /* save time by not calling access() in the hopeless case */
     601:           (stbuf.st_mode & (S_IXOTH | S_IXGRP | S_IXUSR)) &&
     602:           access(strname, X_OK) == 0) ||
     603:          (dir_ok && S_ISDIR(stbuf.st_mode))));
     604: }
     605:
     606: void
     607: tellmewhat(lex)
     608:     struct wordent *lex;
     609: {
     610:     register int i;
     611:     register struct biltins *bptr;
     612:     register struct wordent *sp = lex->next;
     613:     bool    aliased = 0;
     614:     Char   *s0, *s1, *s2;
     615:     Char    qc;
     616:
     617:     if (adrof1(sp->word, &aliases)) {
     618:     alias(lex);
     619:     sp = lex->next;
     620:     aliased = 1;
     621:     }
     622:
     623:     s0 = sp->word;      /* to get the memory freeing right... */
     624:
     625:     /* handle quoted alias hack */
     626:     if ((*(sp->word) & (QUOTE | TRIM)) == QUOTE)
     627:     (sp->word)++;
     628:
     629:     /* do quoting, if it hasn't been done */
     630:     s1 = s2 = sp->word;
     631:     while (*s2)
     632:     switch (*s2) {
     633:     case '\'':
     634:     case '"':
     635:         qc = *s2++;
     636:         while (*s2 && *s2 != qc)
     637:         *s1++ = *s2++ | QUOTE;
     638:         if (*s2)
     639:         s2++;
     640:         break;
     641:     case '\\':
     642:         if (*++s2)
     643:         *s1++ = *s2++ | QUOTE;
     644:         break;
     645:     default:
     646:         *s1++ = *s2++;
     647:     }
     648:     *s1 = '\0';
     649:
     650:     for (bptr = bfunc; bptr < &bfunc[nbfunc]; bptr++) {
     651:     if (eq(sp->word, str2short(bptr->bname))) {
     652:         if (aliased)
     653:         prlex(lex);
     654:         xprintf("%s: shell built-in command.\n", short2str(sp->word));
     655:         flush();
     656:         sp->word = s0;  /* we save and then restore this */
     657:         return;
     658:     }
     659:     }
     660:
     661:     if (i = iscommand(strip(sp->word))) {
     662:     register Char **pv;
     663:     register struct varent *v;
     664:     bool    slash = any(short2str(sp->word), '/');
     665:
     666:     v = adrof(STRpath);
     667:     if (v == 0 || v->vec[0] == 0 || slash)
     668:         pv = justabs;
     669:     else
     670:         pv = v->vec;
     671:
     672:     while (--i)
     673:         pv++;
     674:     if (pv[0][0] == 0 || eq(pv[0], STRdot)) {
     675:         sp->word = Strspl(STRdt_l, sp->word);
     676:         prlex(lex);
     677:         xfree((ptr_t) sp->word);
     678:         sp->word = s0;  /* we save and then restore this */
     679:         return;
     680:     }
     681:     s1 = Strspl(*pv, STRslash);
     682:     sp->word = Strspl(s1, sp->word);
     683:     xfree((ptr_t) s1);
     684:     prlex(lex);
     685:     xfree((ptr_t) sp->word);
     686:     }
     687:     else {
     688:     if (aliased)
     689:         prlex(lex);
     690:     xprintf("%s: Command not found.\n", short2str(sp->word));
     691:     flush();
     692:     }
     693:     sp->word = s0;      /* we save and then restore this */
     694: }

#### Defined functions

doexec defined in line 100; used 3 times

- in line 425
- in /usr/src/bin/tcsh/sh.exec.c line 425
- in /usr/src/bin/tcsh/sh.sem.c line 515

dohash defined in line 442; used 12 times

- in /usr/src/bin/tcsh/sh.func.c line 1040-1044(2), 1107
- in /usr/src/bin/tcsh/sh.init.c line 123
- in /usr/src/bin/tcsh/sh.proc.c line 1739
- in /usr/src/bin/tcsh/sh.sem.c line 467
- in /usr/src/bin/tcsh/sh.set.c line 134, 324
- in /usr/src/bin/tcsh/tc.os.c line 180, 939, 977
- in /usr/src/bin/tcsh/tw.parse.c line 752

dounhash defined in line 490; used 1 times

- in /usr/src/bin/tcsh/sh.init.c line 150

execash defined in line 404; used 1 times

- in /usr/src/bin/tcsh/sh.init.c line 77

executable defined in line 582; used 9 times

- in line 547, 553
- in /usr/src/bin/tcsh/sh.exec.c line 547, 553
- in /usr/src/bin/tcsh/tw.parse.c line 806, 816, 830, 875, 1476

hashname defined in line 510; used 3 times

- in line 212, 482, 538

hashstat defined in line 497; used 1 times

- in /usr/src/bin/tcsh/sh.init.c line 91

iscommand defined in line 521; used 2 times

- in line 661
- in /usr/src/bin/tcsh/sh.exec.c line 661

pexerr defined in line 259; used 3 times

- in line 140, 170, 256

rcsid defined in line 39; never used
tellmewhat defined in line 606; used 1 times

- in /usr/src/bin/tcsh/tc.func.c line 387

texec defined in line 283; used 2 times

- in line 230, 236

xechoit defined in line 429; used 3 times

- in line 172
- in /usr/src/bin/tcsh/sh.exec.c line 172
- in /usr/src/bin/tcsh/sh.func.c line 131

#### Defined variables

exerr defined in line 64; used 5 times

- in line 131, 273-274(2), 391-392(2)

expath defined in line 65; used 13 times

- in line 132-142(4), 154, 263-269(4), 393-397(4)

hits defined in line 89; used 6 times

- in line 215, 250, 500-502(4)

justabs defined in line 94; used 3 times

- in line 204, 533, 668

misses defined in line 89; used 4 times

- in line 243, 500-502(3)

xhash defined in line 83; used 5 times

- in line 226, 458-459(2), 483, 543

#### Defined macros

HSHMASK defined in line 81; used 1 times

- in line 85

HSHMUL defined in line 82; used 1 times

- in line 85

HSHSIZ defined in line 80; used 2 times

- in line 81-83(2)

bis defined in line 87; used 1 times

- in line 483

bit defined in line 86; used 2 times

- in line 226, 543

hash defined in line 85; used 4 times

- in line 225, 482, 517, 542

Last modified: 1991-08-21 Generated: 2016-12-26 | Generated by src2html V0.67 page hit count: 1625 |