17c478bd9Sstevel@tonic-gate /*
2134a1f4eSCasper H.S. Dik * Copyright (c) 1989, 2010, Oracle and/or its affiliates. All rights reserved.
37c478bd9Sstevel@tonic-gate */
47c478bd9Sstevel@tonic-gate
57c478bd9Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
67c478bd9Sstevel@tonic-gate /* All Rights Reserved */
77c478bd9Sstevel@tonic-gate
87c478bd9Sstevel@tonic-gate /*
97c478bd9Sstevel@tonic-gate * Copyright (c) 1980 Regents of the University of California.
107c478bd9Sstevel@tonic-gate * All rights reserved. The Berkeley Software License Agreement
117c478bd9Sstevel@tonic-gate * specifies the terms and conditions for redistribution.
127c478bd9Sstevel@tonic-gate */
137c478bd9Sstevel@tonic-gate
147c478bd9Sstevel@tonic-gate #include "sh.h"
157c478bd9Sstevel@tonic-gate #include <dirent.h>
167c478bd9Sstevel@tonic-gate #include <string.h>
177c478bd9Sstevel@tonic-gate #include "sh.tconst.h"
187c478bd9Sstevel@tonic-gate
197c478bd9Sstevel@tonic-gate
207c478bd9Sstevel@tonic-gate /*
217c478bd9Sstevel@tonic-gate * C shell
227c478bd9Sstevel@tonic-gate */
237c478bd9Sstevel@tonic-gate
247c478bd9Sstevel@tonic-gate /*
257c478bd9Sstevel@tonic-gate * System level search and execute of a command.
267c478bd9Sstevel@tonic-gate * We look in each directory for the specified command name.
277c478bd9Sstevel@tonic-gate * If the name contains a '/' then we execute only the full path name.
287c478bd9Sstevel@tonic-gate * If there is no search path then we execute only full path names.
297c478bd9Sstevel@tonic-gate */
307c478bd9Sstevel@tonic-gate
31*258f91c6SToomas Soome char xhash[HSHSIZ / 8];
32*258f91c6SToomas Soome tchar **Vav;
33*258f91c6SToomas Soome tchar *Vdp;
34*258f91c6SToomas Soome tchar *Vsav;
35*258f91c6SToomas Soome
36*258f91c6SToomas Soome struct varent aliases;
37*258f91c6SToomas Soome bool havhash;
38*258f91c6SToomas Soome static int hits;
39*258f91c6SToomas Soome static int misses;
40*258f91c6SToomas Soome short SHOUT;
41*258f91c6SToomas Soome short SHIN;
42*258f91c6SToomas Soome
43*258f91c6SToomas Soome void (*parintr)();
44*258f91c6SToomas Soome void (*parterm)();
45*258f91c6SToomas Soome
4665b0c20eSnakanon /*
477c478bd9Sstevel@tonic-gate * As we search for the command we note the first non-trivial error
487c478bd9Sstevel@tonic-gate * message for presentation to the user. This allows us often
497c478bd9Sstevel@tonic-gate * to show that a file has the wrong mode/no access when the file
507c478bd9Sstevel@tonic-gate * is not in the last component of the search path, so we must
517c478bd9Sstevel@tonic-gate * go on after first detecting the error.
527c478bd9Sstevel@tonic-gate */
537c478bd9Sstevel@tonic-gate char *exerr; /* Execution error message */
547c478bd9Sstevel@tonic-gate
556c02b4a4Smuffin void pexerr(void);
566c02b4a4Smuffin void texec(struct command *, tchar *, tchar **);
576c02b4a4Smuffin void xechoit(tchar **);
586c02b4a4Smuffin void dohash(char []);
597c478bd9Sstevel@tonic-gate
606c02b4a4Smuffin static void tconvert(struct command *, tchar *, tchar **);
617c478bd9Sstevel@tonic-gate
627c478bd9Sstevel@tonic-gate
636c02b4a4Smuffin extern DIR *opendir_(tchar *);
646c02b4a4Smuffin
656c02b4a4Smuffin void
doexec(struct command * t)666c02b4a4Smuffin doexec(struct command *t)
677c478bd9Sstevel@tonic-gate {
687c478bd9Sstevel@tonic-gate tchar *sav;
696c02b4a4Smuffin tchar *dp, **pv, **av;
706c02b4a4Smuffin struct varent *v;
717c478bd9Sstevel@tonic-gate bool slash;
727c478bd9Sstevel@tonic-gate int hashval, hashval1, i;
737c478bd9Sstevel@tonic-gate tchar *blk[2];
747c478bd9Sstevel@tonic-gate #ifdef TRACE
757c478bd9Sstevel@tonic-gate tprintf("TRACE- doexec()\n");
767c478bd9Sstevel@tonic-gate #endif
777c478bd9Sstevel@tonic-gate
787c478bd9Sstevel@tonic-gate /*
797c478bd9Sstevel@tonic-gate * Glob the command name. If this does anything, then we
807c478bd9Sstevel@tonic-gate * will execute the command only relative to ".". One special
817c478bd9Sstevel@tonic-gate * case: if there is no PATH, then we execute only commands
827c478bd9Sstevel@tonic-gate * which start with '/'.
837c478bd9Sstevel@tonic-gate */
847c478bd9Sstevel@tonic-gate dp = globone(t->t_dcom[0]);
857c478bd9Sstevel@tonic-gate sav = t->t_dcom[0];
867c478bd9Sstevel@tonic-gate exerr = 0; t->t_dcom[0] = dp;
877c478bd9Sstevel@tonic-gate setname(dp);
887c478bd9Sstevel@tonic-gate xfree(sav);
8965b0c20eSnakanon v = adrof(S_path /* "path" */);
907c478bd9Sstevel@tonic-gate if (v == 0 && dp[0] != '/') {
917c478bd9Sstevel@tonic-gate pexerr();
927c478bd9Sstevel@tonic-gate }
937c478bd9Sstevel@tonic-gate slash = gflag;
947c478bd9Sstevel@tonic-gate
957c478bd9Sstevel@tonic-gate /*
967c478bd9Sstevel@tonic-gate * Glob the argument list, if necessary.
977c478bd9Sstevel@tonic-gate * Otherwise trim off the quote bits.
987c478bd9Sstevel@tonic-gate */
997c478bd9Sstevel@tonic-gate gflag = 0; av = &t->t_dcom[1];
1007c478bd9Sstevel@tonic-gate tglob(av);
1017c478bd9Sstevel@tonic-gate if (gflag) {
1027c478bd9Sstevel@tonic-gate av = glob(av);
1037c478bd9Sstevel@tonic-gate if (av == 0)
1047c478bd9Sstevel@tonic-gate error("No match");
1057c478bd9Sstevel@tonic-gate }
1067c478bd9Sstevel@tonic-gate blk[0] = t->t_dcom[0];
1077c478bd9Sstevel@tonic-gate blk[1] = 0;
1087c478bd9Sstevel@tonic-gate av = blkspl(blk, av);
1097c478bd9Sstevel@tonic-gate #ifdef VFORK
1107c478bd9Sstevel@tonic-gate Vav = av;
1117c478bd9Sstevel@tonic-gate #endif
1127c478bd9Sstevel@tonic-gate trim(av);
1137c478bd9Sstevel@tonic-gate slash |= any('/', av[0]);
1147c478bd9Sstevel@tonic-gate
1157c478bd9Sstevel@tonic-gate xechoit(av); /* Echo command if -x */
1167c478bd9Sstevel@tonic-gate /*
1177c478bd9Sstevel@tonic-gate * Since all internal file descriptors are set to close on exec,
1187c478bd9Sstevel@tonic-gate * we don't need to close them explicitly here. Just reorient
1197c478bd9Sstevel@tonic-gate * ourselves for error messages.
1207c478bd9Sstevel@tonic-gate */
1217c478bd9Sstevel@tonic-gate SHIN = 0; SHOUT = 1; SHDIAG = 2; OLDSTD = 0;
1227c478bd9Sstevel@tonic-gate
1237c478bd9Sstevel@tonic-gate /*
1247c478bd9Sstevel@tonic-gate * We must do this AFTER any possible forking (like `foo`
1257c478bd9Sstevel@tonic-gate * in glob) so that this shell can still do subprocesses.
1267c478bd9Sstevel@tonic-gate */
1277c478bd9Sstevel@tonic-gate (void) sigsetmask(0);
1287c478bd9Sstevel@tonic-gate
1297c478bd9Sstevel@tonic-gate /*
1307c478bd9Sstevel@tonic-gate * If no path, no words in path, or a / in the filename
1317c478bd9Sstevel@tonic-gate * then restrict the command search.
1327c478bd9Sstevel@tonic-gate */
1337c478bd9Sstevel@tonic-gate if (v == 0 || v->vec[0] == 0 || slash)
1347c478bd9Sstevel@tonic-gate pv = justabs;
1357c478bd9Sstevel@tonic-gate else
1367c478bd9Sstevel@tonic-gate pv = v->vec;
137134a1f4eSCasper H.S. Dik /* / command name for postpending */
138134a1f4eSCasper H.S. Dik sav = strspl(S_SLASH /* "/" */, *av);
1397c478bd9Sstevel@tonic-gate #ifdef VFORK
1407c478bd9Sstevel@tonic-gate Vsav = sav;
1417c478bd9Sstevel@tonic-gate #endif
1427c478bd9Sstevel@tonic-gate if (havhash)
1437c478bd9Sstevel@tonic-gate hashval = hashname(*av);
1447c478bd9Sstevel@tonic-gate i = 0;
1457c478bd9Sstevel@tonic-gate #ifdef VFORK
1467c478bd9Sstevel@tonic-gate hits++;
1477c478bd9Sstevel@tonic-gate #endif
1487c478bd9Sstevel@tonic-gate do {
1497c478bd9Sstevel@tonic-gate if (!slash && pv[0][0] == '/' && havhash) {
1507c478bd9Sstevel@tonic-gate hashval1 = hash(hashval, i);
1517c478bd9Sstevel@tonic-gate if (!bit(xhash, hashval1))
1527c478bd9Sstevel@tonic-gate goto cont;
1537c478bd9Sstevel@tonic-gate }
1547c478bd9Sstevel@tonic-gate
155134a1f4eSCasper H.S. Dik /* don't make ./xxx */
156134a1f4eSCasper H.S. Dik if (pv[0][0] == 0 || eq(pv[0], S_DOT /* "." */)) {
1577c478bd9Sstevel@tonic-gate texec(t, *av, av);
1587c478bd9Sstevel@tonic-gate } else {
1597c478bd9Sstevel@tonic-gate dp = strspl(*pv, sav);
1607c478bd9Sstevel@tonic-gate #ifdef VFORK
1617c478bd9Sstevel@tonic-gate Vdp = dp;
1627c478bd9Sstevel@tonic-gate #endif
1637c478bd9Sstevel@tonic-gate texec(t, dp, av);
1647c478bd9Sstevel@tonic-gate #ifdef VFORK
1657c478bd9Sstevel@tonic-gate Vdp = 0;
1667c478bd9Sstevel@tonic-gate #endif
1677c478bd9Sstevel@tonic-gate xfree(dp);
1687c478bd9Sstevel@tonic-gate }
1697c478bd9Sstevel@tonic-gate #ifdef VFORK
1707c478bd9Sstevel@tonic-gate misses++;
1717c478bd9Sstevel@tonic-gate #endif
1727c478bd9Sstevel@tonic-gate cont:
1737c478bd9Sstevel@tonic-gate pv++;
1747c478bd9Sstevel@tonic-gate i++;
1757c478bd9Sstevel@tonic-gate } while (*pv);
1767c478bd9Sstevel@tonic-gate #ifdef VFORK
1777c478bd9Sstevel@tonic-gate hits--;
1787c478bd9Sstevel@tonic-gate #endif
1797c478bd9Sstevel@tonic-gate #ifdef VFORK
1807c478bd9Sstevel@tonic-gate Vsav = 0;
1817c478bd9Sstevel@tonic-gate Vav = 0;
1827c478bd9Sstevel@tonic-gate #endif
1837c478bd9Sstevel@tonic-gate xfree(sav);
18465b0c20eSnakanon xfree((char *)av);
1857c478bd9Sstevel@tonic-gate pexerr();
1867c478bd9Sstevel@tonic-gate }
1877c478bd9Sstevel@tonic-gate
1886c02b4a4Smuffin void
pexerr(void)1896c02b4a4Smuffin pexerr(void)
1907c478bd9Sstevel@tonic-gate {
1917c478bd9Sstevel@tonic-gate
1927c478bd9Sstevel@tonic-gate #ifdef TRACE
1937c478bd9Sstevel@tonic-gate tprintf("TRACE- pexerr()\n");
1947c478bd9Sstevel@tonic-gate #endif
1957c478bd9Sstevel@tonic-gate /* Couldn't find the damn thing */
1967c478bd9Sstevel@tonic-gate if (exerr)
1977c478bd9Sstevel@tonic-gate bferr(exerr);
1987c478bd9Sstevel@tonic-gate bferr("Command not found");
1997c478bd9Sstevel@tonic-gate }
2007c478bd9Sstevel@tonic-gate
2017c478bd9Sstevel@tonic-gate /*
2027c478bd9Sstevel@tonic-gate * Execute command f, arg list t.
2037c478bd9Sstevel@tonic-gate * Record error message if not found.
2047c478bd9Sstevel@tonic-gate * Also do shell scripts here.
2057c478bd9Sstevel@tonic-gate */
2066c02b4a4Smuffin void
texec(struct command * cmd,tchar * f,tchar ** t)2076c02b4a4Smuffin texec(struct command *cmd, tchar *f, tchar **t)
2087c478bd9Sstevel@tonic-gate {
2096c02b4a4Smuffin struct varent *v;
2106c02b4a4Smuffin tchar **vp;
2117c478bd9Sstevel@tonic-gate tchar *lastsh[2];
21265b0c20eSnakanon
2137c478bd9Sstevel@tonic-gate #ifdef TRACE
2147c478bd9Sstevel@tonic-gate tprintf("TRACE- texec()\n");
2157c478bd9Sstevel@tonic-gate #endif
2167c478bd9Sstevel@tonic-gate /* convert cfname and cargs from tchar to char */
2177c478bd9Sstevel@tonic-gate tconvert(cmd, f, t);
2187c478bd9Sstevel@tonic-gate
219134a1f4eSCasper H.S. Dik execv(cmd->cfname, cmd->cargs);
2207c478bd9Sstevel@tonic-gate
2217c478bd9Sstevel@tonic-gate /*
2227c478bd9Sstevel@tonic-gate * exec returned, free up allocations from above
2237c478bd9Sstevel@tonic-gate * tconvert(), zero cfname and cargs to prevent
2247c478bd9Sstevel@tonic-gate * duplicate free() in freesyn()
2257c478bd9Sstevel@tonic-gate */
2267c478bd9Sstevel@tonic-gate xfree(cmd->cfname);
2277c478bd9Sstevel@tonic-gate chr_blkfree(cmd->cargs);
22865b0c20eSnakanon cmd->cfname = (char *)0;
22965b0c20eSnakanon cmd->cargs = (char **)0;
2307c478bd9Sstevel@tonic-gate
2317c478bd9Sstevel@tonic-gate switch (errno) {
2327c478bd9Sstevel@tonic-gate case ENOEXEC:
2337c478bd9Sstevel@tonic-gate /* check that this is not a binary file */
23465b0c20eSnakanon {
2356c02b4a4Smuffin int ff = open_(f, 0);
23665b0c20eSnakanon tchar ch[MB_LEN_MAX];
2377c478bd9Sstevel@tonic-gate
23865b0c20eSnakanon if (ff != -1 && read_(ff, ch, 1) == 1 &&
23965b0c20eSnakanon !isprint(ch[0]) && !isspace(ch[0])) {
2407c478bd9Sstevel@tonic-gate printf("Cannot execute binary file.\n");
2417c478bd9Sstevel@tonic-gate Perror(f);
2427c478bd9Sstevel@tonic-gate (void) close(ff);
2437c478bd9Sstevel@tonic-gate unsetfd(ff);
2447c478bd9Sstevel@tonic-gate return;
24565b0c20eSnakanon }
2467c478bd9Sstevel@tonic-gate (void) close(ff);
2477c478bd9Sstevel@tonic-gate unsetfd(ff);
24865b0c20eSnakanon }
2497c478bd9Sstevel@tonic-gate /*
2507c478bd9Sstevel@tonic-gate * If there is an alias for shell, then
2517c478bd9Sstevel@tonic-gate * put the words of the alias in front of the
2527c478bd9Sstevel@tonic-gate * argument list replacing the command name.
2537c478bd9Sstevel@tonic-gate * Note no interpretation of the words at this point.
2547c478bd9Sstevel@tonic-gate */
25565b0c20eSnakanon v = adrof1(S_shell /* "shell" */, &aliases);
2567c478bd9Sstevel@tonic-gate if (v == 0) {
2577c478bd9Sstevel@tonic-gate #ifdef OTHERSH
2586c02b4a4Smuffin int ff = open_(f, 0);
25965b0c20eSnakanon tchar ch[MB_LEN_MAX];
2607c478bd9Sstevel@tonic-gate #endif
2617c478bd9Sstevel@tonic-gate
2627c478bd9Sstevel@tonic-gate vp = lastsh;
263134a1f4eSCasper H.S. Dik vp[0] = adrof(S_shell /* "shell" */) ?
264134a1f4eSCasper H.S. Dik value(S_shell /* "shell" */) :
265134a1f4eSCasper H.S. Dik S_SHELLPATH /* SHELLPATH */;
2667c478bd9Sstevel@tonic-gate vp[1] = (tchar *) NULL;
2677c478bd9Sstevel@tonic-gate #ifdef OTHERSH
26865b0c20eSnakanon if (ff != -1 && read_(ff, ch, 1) == 1 && ch[0] != '#')
26965b0c20eSnakanon vp[0] = S_OTHERSH /* OTHERSH */;
2707c478bd9Sstevel@tonic-gate (void) close(ff);
2717c478bd9Sstevel@tonic-gate unsetfd(ff);
2727c478bd9Sstevel@tonic-gate #endif
2737c478bd9Sstevel@tonic-gate } else
2747c478bd9Sstevel@tonic-gate vp = v->vec;
2757c478bd9Sstevel@tonic-gate t[0] = f;
2767c478bd9Sstevel@tonic-gate t = blkspl(vp, t); /* Splice up the new arglst */
2777c478bd9Sstevel@tonic-gate f = *t;
2787c478bd9Sstevel@tonic-gate
2797c478bd9Sstevel@tonic-gate tconvert(cmd, f, t); /* convert tchar to char */
2807c478bd9Sstevel@tonic-gate
2817c478bd9Sstevel@tonic-gate /*
2827c478bd9Sstevel@tonic-gate * now done with tchar arg list t,
2837c478bd9Sstevel@tonic-gate * free the space calloc'd by above blkspl()
2847c478bd9Sstevel@tonic-gate */
28565b0c20eSnakanon xfree((char *)t);
2867c478bd9Sstevel@tonic-gate
2877c478bd9Sstevel@tonic-gate execv(cmd->cfname, cmd->cargs); /* exec the command */
2887c478bd9Sstevel@tonic-gate
2897c478bd9Sstevel@tonic-gate /* exec returned, same free'ing as above */
2907c478bd9Sstevel@tonic-gate xfree(cmd->cfname);
2917c478bd9Sstevel@tonic-gate chr_blkfree(cmd->cargs);
29265b0c20eSnakanon cmd->cfname = (char *)0;
29365b0c20eSnakanon cmd->cargs = (char **)0;
2947c478bd9Sstevel@tonic-gate
2957c478bd9Sstevel@tonic-gate /* The sky is falling, the sky is falling! */
2967c478bd9Sstevel@tonic-gate
2977c478bd9Sstevel@tonic-gate case ENOMEM:
2987c478bd9Sstevel@tonic-gate Perror(f);
2997c478bd9Sstevel@tonic-gate
3007c478bd9Sstevel@tonic-gate case ENOENT:
3017c478bd9Sstevel@tonic-gate break;
3027c478bd9Sstevel@tonic-gate
3037c478bd9Sstevel@tonic-gate default:
3047c478bd9Sstevel@tonic-gate if (exerr == 0) {
3057c478bd9Sstevel@tonic-gate exerr = strerror(errno);
3067c478bd9Sstevel@tonic-gate setname(f);
3077c478bd9Sstevel@tonic-gate }
3087c478bd9Sstevel@tonic-gate }
3097c478bd9Sstevel@tonic-gate }
3107c478bd9Sstevel@tonic-gate
3117c478bd9Sstevel@tonic-gate
3126c02b4a4Smuffin static void
tconvert(struct command * cmd,tchar * fname,tchar ** list)3136c02b4a4Smuffin tconvert(struct command *cmd, tchar *fname, tchar **list)
3147c478bd9Sstevel@tonic-gate {
3156c02b4a4Smuffin char **rc;
3166c02b4a4Smuffin int len;
3177c478bd9Sstevel@tonic-gate
3187c478bd9Sstevel@tonic-gate cmd->cfname = tstostr(NULL, fname);
3197c478bd9Sstevel@tonic-gate
3207c478bd9Sstevel@tonic-gate len = blklen(list);
3217c478bd9Sstevel@tonic-gate rc = cmd->cargs = (char **)
322134a1f4eSCasper H.S. Dik xcalloc((uint_t)(len + 1), sizeof (char **));
3237c478bd9Sstevel@tonic-gate while (len--)
3247c478bd9Sstevel@tonic-gate *rc++ = tstostr(NULL, *list++);
3257c478bd9Sstevel@tonic-gate *rc = NULL;
3267c478bd9Sstevel@tonic-gate }
3277c478bd9Sstevel@tonic-gate
3287c478bd9Sstevel@tonic-gate
3297c478bd9Sstevel@tonic-gate /*ARGSUSED*/
3306c02b4a4Smuffin void
execash(tchar ** t,struct command * kp)3316c02b4a4Smuffin execash(tchar **t, struct command *kp)
3327c478bd9Sstevel@tonic-gate {
3337c478bd9Sstevel@tonic-gate #ifdef TRACE
3347c478bd9Sstevel@tonic-gate tprintf("TRACE- execash()\n");
3357c478bd9Sstevel@tonic-gate #endif
3367c478bd9Sstevel@tonic-gate
3377c478bd9Sstevel@tonic-gate rechist();
3387c478bd9Sstevel@tonic-gate (void) signal(SIGINT, parintr);
3397c478bd9Sstevel@tonic-gate (void) signal(SIGQUIT, parintr);
3407c478bd9Sstevel@tonic-gate (void) signal(SIGTERM, parterm); /* if doexec loses, screw */
3417c478bd9Sstevel@tonic-gate lshift(kp->t_dcom, 1);
3427c478bd9Sstevel@tonic-gate exiterr++;
3437c478bd9Sstevel@tonic-gate doexec(kp);
3447c478bd9Sstevel@tonic-gate /*NOTREACHED*/
3457c478bd9Sstevel@tonic-gate }
3467c478bd9Sstevel@tonic-gate
3476c02b4a4Smuffin void
xechoit(tchar ** t)3486c02b4a4Smuffin xechoit(tchar **t)
3497c478bd9Sstevel@tonic-gate {
3507c478bd9Sstevel@tonic-gate #ifdef TRACE
3517c478bd9Sstevel@tonic-gate tprintf("TRACE- xechoit()\n");
3527c478bd9Sstevel@tonic-gate #endif
3537c478bd9Sstevel@tonic-gate
35465b0c20eSnakanon if (adrof(S_echo /* "echo" */)) {
3557c478bd9Sstevel@tonic-gate flush();
3567c478bd9Sstevel@tonic-gate haderr = 1;
3577c478bd9Sstevel@tonic-gate blkpr(t), Putchar('\n');
3587c478bd9Sstevel@tonic-gate haderr = 0;
3597c478bd9Sstevel@tonic-gate }
3607c478bd9Sstevel@tonic-gate }
3617c478bd9Sstevel@tonic-gate
36265b0c20eSnakanon /*
3637c478bd9Sstevel@tonic-gate * This routine called when user enters "rehash".
3647c478bd9Sstevel@tonic-gate * Both the path and cdpath caching arrays will
3657c478bd9Sstevel@tonic-gate * be rehashed, via calling dohash. If either
3667c478bd9Sstevel@tonic-gate * variable is not set with a value, then dohash
3677c478bd9Sstevel@tonic-gate * just exits.
3687c478bd9Sstevel@tonic-gate */
3696c02b4a4Smuffin void
dorehash(void)3706c02b4a4Smuffin dorehash(void)
3717c478bd9Sstevel@tonic-gate {
3727c478bd9Sstevel@tonic-gate dohash(xhash);
3737c478bd9Sstevel@tonic-gate dohash(xhash2);
3747c478bd9Sstevel@tonic-gate }
3757c478bd9Sstevel@tonic-gate
3767c478bd9Sstevel@tonic-gate /*
3777c478bd9Sstevel@tonic-gate * Fill up caching arrays for path and cdpath
3787c478bd9Sstevel@tonic-gate */
3796c02b4a4Smuffin void
dohash(char cachearray[])3806c02b4a4Smuffin dohash(char cachearray[])
3817c478bd9Sstevel@tonic-gate {
3827c478bd9Sstevel@tonic-gate struct stat stb;
3837c478bd9Sstevel@tonic-gate DIR *dirp;
3846c02b4a4Smuffin struct dirent *dp;
3856c02b4a4Smuffin int cnt;
3867c478bd9Sstevel@tonic-gate int i = 0;
3877c478bd9Sstevel@tonic-gate struct varent *v;
3887c478bd9Sstevel@tonic-gate tchar **pv;
3897c478bd9Sstevel@tonic-gate int hashval;
3907c478bd9Sstevel@tonic-gate tchar curdir_[MAXNAMLEN+1];
3917c478bd9Sstevel@tonic-gate
3927c478bd9Sstevel@tonic-gate #ifdef TRACE
3937c478bd9Sstevel@tonic-gate tprintf("TRACE- dohash()\n");
3947c478bd9Sstevel@tonic-gate #endif
3957c478bd9Sstevel@tonic-gate /* Caching $path */
39665b0c20eSnakanon if (cachearray == xhash) {
3977c478bd9Sstevel@tonic-gate havhash = 1;
39865b0c20eSnakanon v = adrof(S_path /* "path" */);
39965b0c20eSnakanon } else { /* Caching $cdpath */
4007c478bd9Sstevel@tonic-gate havhash2 = 1;
40165b0c20eSnakanon v = adrof(S_cdpath /* "cdpath" */);
4027c478bd9Sstevel@tonic-gate }
4037c478bd9Sstevel@tonic-gate
40465b0c20eSnakanon for (cnt = 0; cnt < (HSHSIZ / 8); cnt++)
4057c478bd9Sstevel@tonic-gate cachearray[cnt] = 0;
4067c478bd9Sstevel@tonic-gate if (v == 0)
4077c478bd9Sstevel@tonic-gate return;
4087c478bd9Sstevel@tonic-gate for (pv = v->vec; *pv; pv++, i++) {
4097c478bd9Sstevel@tonic-gate if (pv[0][0] != '/')
4107c478bd9Sstevel@tonic-gate continue;
4117c478bd9Sstevel@tonic-gate dirp = opendir_(*pv);
4127c478bd9Sstevel@tonic-gate if (dirp == NULL)
4137c478bd9Sstevel@tonic-gate continue;
4147c478bd9Sstevel@tonic-gate if (fstat(dirp->dd_fd, &stb) < 0 || !isdir(stb)) {
4157c478bd9Sstevel@tonic-gate unsetfd(dirp->dd_fd);
4167c478bd9Sstevel@tonic-gate closedir_(dirp);
4177c478bd9Sstevel@tonic-gate continue;
4187c478bd9Sstevel@tonic-gate }
4197c478bd9Sstevel@tonic-gate while ((dp = readdir(dirp)) != NULL) {
4207c478bd9Sstevel@tonic-gate if (dp->d_ino == 0)
4217c478bd9Sstevel@tonic-gate continue;
4227c478bd9Sstevel@tonic-gate if (dp->d_name[0] == '.' &&
4237c478bd9Sstevel@tonic-gate (dp->d_name[1] == '\0' ||
42465b0c20eSnakanon dp->d_name[1] == '.' && dp->d_name[2] == '\0'))
4257c478bd9Sstevel@tonic-gate continue;
426134a1f4eSCasper H.S. Dik hashval = hash(hashname(strtots(curdir_, dp->d_name)),
427134a1f4eSCasper H.S. Dik i);
4287c478bd9Sstevel@tonic-gate bis(cachearray, hashval);
4297c478bd9Sstevel@tonic-gate }
4307c478bd9Sstevel@tonic-gate unsetfd(dirp->dd_fd);
4317c478bd9Sstevel@tonic-gate closedir_(dirp);
4327c478bd9Sstevel@tonic-gate }
4337c478bd9Sstevel@tonic-gate }
4347c478bd9Sstevel@tonic-gate
4356c02b4a4Smuffin void
dounhash(void)4366c02b4a4Smuffin dounhash(void)
4377c478bd9Sstevel@tonic-gate {
4387c478bd9Sstevel@tonic-gate
4397c478bd9Sstevel@tonic-gate #ifdef TRACE
4407c478bd9Sstevel@tonic-gate tprintf("TRACE- dounhash()\n");
4417c478bd9Sstevel@tonic-gate #endif
4427c478bd9Sstevel@tonic-gate havhash = 0;
4437c478bd9Sstevel@tonic-gate havhash2 = 0;
4447c478bd9Sstevel@tonic-gate }
4457c478bd9Sstevel@tonic-gate
4467c478bd9Sstevel@tonic-gate #ifdef VFORK
4476c02b4a4Smuffin void
hashstat(void)4486c02b4a4Smuffin hashstat(void)
4497c478bd9Sstevel@tonic-gate {
4507c478bd9Sstevel@tonic-gate #ifdef TRACE
4517c478bd9Sstevel@tonic-gate tprintf("TRACE- hashstat_()\n");
4527c478bd9Sstevel@tonic-gate #endif
4537c478bd9Sstevel@tonic-gate
4547c478bd9Sstevel@tonic-gate if (hits+misses)
4557c478bd9Sstevel@tonic-gate printf("%d hits, %d misses, %d%%\n",
456134a1f4eSCasper H.S. Dik hits, misses, 100 * hits / (hits + misses));
4577c478bd9Sstevel@tonic-gate }
4587c478bd9Sstevel@tonic-gate #endif
4597c478bd9Sstevel@tonic-gate
4607c478bd9Sstevel@tonic-gate /*
4617c478bd9Sstevel@tonic-gate * Hash a command name.
4627c478bd9Sstevel@tonic-gate */
4636c02b4a4Smuffin int
hashname(tchar * cp)4646c02b4a4Smuffin hashname(tchar *cp)
4657c478bd9Sstevel@tonic-gate {
4666c02b4a4Smuffin long h = 0;
4677c478bd9Sstevel@tonic-gate
4687c478bd9Sstevel@tonic-gate #ifdef TRACE
4697c478bd9Sstevel@tonic-gate tprintf("TRACE- hashname()\n");
4707c478bd9Sstevel@tonic-gate #endif
4717c478bd9Sstevel@tonic-gate while (*cp)
4727c478bd9Sstevel@tonic-gate h = hash(h, *cp++);
47365b0c20eSnakanon return ((int)h);
4747c478bd9Sstevel@tonic-gate }
475