17c478bd9Sstevel@tonic-gate /*
2*134a1f4eSCasper 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
317c478bd9Sstevel@tonic-gate /*
327c478bd9Sstevel@tonic-gate * As we search for the command we note the first non-trivial error
337c478bd9Sstevel@tonic-gate * message for presentation to the user. This allows us often
347c478bd9Sstevel@tonic-gate * to show that a file has the wrong mode/no access when the file
357c478bd9Sstevel@tonic-gate * is not in the last component of the search path, so we must
367c478bd9Sstevel@tonic-gate * go on after first detecting the error.
377c478bd9Sstevel@tonic-gate */
387c478bd9Sstevel@tonic-gate char *exerr; /* Execution error message */
397c478bd9Sstevel@tonic-gate
406c02b4a4Smuffin void pexerr(void);
416c02b4a4Smuffin void texec(struct command *, tchar *, tchar **);
426c02b4a4Smuffin void xechoit(tchar **);
436c02b4a4Smuffin void dohash(char []);
447c478bd9Sstevel@tonic-gate
456c02b4a4Smuffin static void tconvert(struct command *, tchar *, tchar **);
467c478bd9Sstevel@tonic-gate
477c478bd9Sstevel@tonic-gate
486c02b4a4Smuffin extern DIR *opendir_(tchar *);
496c02b4a4Smuffin
506c02b4a4Smuffin void
doexec(struct command * t)516c02b4a4Smuffin doexec(struct command *t)
527c478bd9Sstevel@tonic-gate {
537c478bd9Sstevel@tonic-gate tchar *sav;
546c02b4a4Smuffin tchar *dp, **pv, **av;
556c02b4a4Smuffin struct varent *v;
567c478bd9Sstevel@tonic-gate bool slash;
577c478bd9Sstevel@tonic-gate int hashval, hashval1, i;
587c478bd9Sstevel@tonic-gate tchar *blk[2];
597c478bd9Sstevel@tonic-gate #ifdef TRACE
607c478bd9Sstevel@tonic-gate tprintf("TRACE- doexec()\n");
617c478bd9Sstevel@tonic-gate #endif
627c478bd9Sstevel@tonic-gate
637c478bd9Sstevel@tonic-gate /*
647c478bd9Sstevel@tonic-gate * Glob the command name. If this does anything, then we
657c478bd9Sstevel@tonic-gate * will execute the command only relative to ".". One special
667c478bd9Sstevel@tonic-gate * case: if there is no PATH, then we execute only commands
677c478bd9Sstevel@tonic-gate * which start with '/'.
687c478bd9Sstevel@tonic-gate */
697c478bd9Sstevel@tonic-gate dp = globone(t->t_dcom[0]);
707c478bd9Sstevel@tonic-gate sav = t->t_dcom[0];
717c478bd9Sstevel@tonic-gate exerr = 0; t->t_dcom[0] = dp;
727c478bd9Sstevel@tonic-gate setname(dp);
737c478bd9Sstevel@tonic-gate xfree(sav);
747c478bd9Sstevel@tonic-gate v = adrof(S_path /* "path" */);
757c478bd9Sstevel@tonic-gate if (v == 0 && dp[0] != '/') {
767c478bd9Sstevel@tonic-gate pexerr();
777c478bd9Sstevel@tonic-gate }
787c478bd9Sstevel@tonic-gate slash = gflag;
797c478bd9Sstevel@tonic-gate
807c478bd9Sstevel@tonic-gate /*
817c478bd9Sstevel@tonic-gate * Glob the argument list, if necessary.
827c478bd9Sstevel@tonic-gate * Otherwise trim off the quote bits.
837c478bd9Sstevel@tonic-gate */
847c478bd9Sstevel@tonic-gate gflag = 0; av = &t->t_dcom[1];
857c478bd9Sstevel@tonic-gate tglob(av);
867c478bd9Sstevel@tonic-gate if (gflag) {
877c478bd9Sstevel@tonic-gate av = glob(av);
887c478bd9Sstevel@tonic-gate if (av == 0)
897c478bd9Sstevel@tonic-gate error("No match");
907c478bd9Sstevel@tonic-gate }
917c478bd9Sstevel@tonic-gate blk[0] = t->t_dcom[0];
927c478bd9Sstevel@tonic-gate blk[1] = 0;
937c478bd9Sstevel@tonic-gate av = blkspl(blk, av);
947c478bd9Sstevel@tonic-gate #ifdef VFORK
957c478bd9Sstevel@tonic-gate Vav = av;
967c478bd9Sstevel@tonic-gate #endif
977c478bd9Sstevel@tonic-gate trim(av);
987c478bd9Sstevel@tonic-gate slash |= any('/', av[0]);
997c478bd9Sstevel@tonic-gate
1007c478bd9Sstevel@tonic-gate xechoit(av); /* Echo command if -x */
1017c478bd9Sstevel@tonic-gate /*
1027c478bd9Sstevel@tonic-gate * Since all internal file descriptors are set to close on exec,
1037c478bd9Sstevel@tonic-gate * we don't need to close them explicitly here. Just reorient
1047c478bd9Sstevel@tonic-gate * ourselves for error messages.
1057c478bd9Sstevel@tonic-gate */
1067c478bd9Sstevel@tonic-gate SHIN = 0; SHOUT = 1; SHDIAG = 2; OLDSTD = 0;
1077c478bd9Sstevel@tonic-gate
1087c478bd9Sstevel@tonic-gate /*
1097c478bd9Sstevel@tonic-gate * We must do this AFTER any possible forking (like `foo`
1107c478bd9Sstevel@tonic-gate * in glob) so that this shell can still do subprocesses.
1117c478bd9Sstevel@tonic-gate */
1127c478bd9Sstevel@tonic-gate (void) sigsetmask(0);
1137c478bd9Sstevel@tonic-gate
1147c478bd9Sstevel@tonic-gate /*
1157c478bd9Sstevel@tonic-gate * If no path, no words in path, or a / in the filename
1167c478bd9Sstevel@tonic-gate * then restrict the command search.
1177c478bd9Sstevel@tonic-gate */
1187c478bd9Sstevel@tonic-gate if (v == 0 || v->vec[0] == 0 || slash)
1197c478bd9Sstevel@tonic-gate pv = justabs;
1207c478bd9Sstevel@tonic-gate else
1217c478bd9Sstevel@tonic-gate pv = v->vec;
122*134a1f4eSCasper H.S. Dik /* / command name for postpending */
123*134a1f4eSCasper H.S. Dik sav = strspl(S_SLASH /* "/" */, *av);
1247c478bd9Sstevel@tonic-gate #ifdef VFORK
1257c478bd9Sstevel@tonic-gate Vsav = sav;
1267c478bd9Sstevel@tonic-gate #endif
1277c478bd9Sstevel@tonic-gate if (havhash)
1287c478bd9Sstevel@tonic-gate hashval = hashname(*av);
1297c478bd9Sstevel@tonic-gate i = 0;
1307c478bd9Sstevel@tonic-gate #ifdef VFORK
1317c478bd9Sstevel@tonic-gate hits++;
1327c478bd9Sstevel@tonic-gate #endif
1337c478bd9Sstevel@tonic-gate do {
1347c478bd9Sstevel@tonic-gate if (!slash && pv[0][0] == '/' && havhash) {
1357c478bd9Sstevel@tonic-gate hashval1 = hash(hashval, i);
1367c478bd9Sstevel@tonic-gate if (!bit(xhash, hashval1))
1377c478bd9Sstevel@tonic-gate goto cont;
1387c478bd9Sstevel@tonic-gate }
1397c478bd9Sstevel@tonic-gate
140*134a1f4eSCasper H.S. Dik /* don't make ./xxx */
141*134a1f4eSCasper H.S. Dik if (pv[0][0] == 0 || eq(pv[0], S_DOT /* "." */)) {
1427c478bd9Sstevel@tonic-gate texec(t, *av, av);
1437c478bd9Sstevel@tonic-gate } else {
1447c478bd9Sstevel@tonic-gate dp = strspl(*pv, sav);
1457c478bd9Sstevel@tonic-gate #ifdef VFORK
1467c478bd9Sstevel@tonic-gate Vdp = dp;
1477c478bd9Sstevel@tonic-gate #endif
1487c478bd9Sstevel@tonic-gate texec(t, dp, av);
1497c478bd9Sstevel@tonic-gate #ifdef VFORK
1507c478bd9Sstevel@tonic-gate Vdp = 0;
1517c478bd9Sstevel@tonic-gate #endif
1527c478bd9Sstevel@tonic-gate xfree(dp);
1537c478bd9Sstevel@tonic-gate }
1547c478bd9Sstevel@tonic-gate #ifdef VFORK
1557c478bd9Sstevel@tonic-gate misses++;
1567c478bd9Sstevel@tonic-gate #endif
1577c478bd9Sstevel@tonic-gate cont:
1587c478bd9Sstevel@tonic-gate pv++;
1597c478bd9Sstevel@tonic-gate i++;
1607c478bd9Sstevel@tonic-gate } while (*pv);
1617c478bd9Sstevel@tonic-gate #ifdef VFORK
1627c478bd9Sstevel@tonic-gate hits--;
1637c478bd9Sstevel@tonic-gate #endif
1647c478bd9Sstevel@tonic-gate #ifdef VFORK
1657c478bd9Sstevel@tonic-gate Vsav = 0;
1667c478bd9Sstevel@tonic-gate Vav = 0;
1677c478bd9Sstevel@tonic-gate #endif
1687c478bd9Sstevel@tonic-gate xfree(sav);
1697c478bd9Sstevel@tonic-gate xfree((char *)av);
1707c478bd9Sstevel@tonic-gate pexerr();
1717c478bd9Sstevel@tonic-gate }
1727c478bd9Sstevel@tonic-gate
1736c02b4a4Smuffin void
pexerr(void)1746c02b4a4Smuffin pexerr(void)
1757c478bd9Sstevel@tonic-gate {
1767c478bd9Sstevel@tonic-gate
1777c478bd9Sstevel@tonic-gate #ifdef TRACE
1787c478bd9Sstevel@tonic-gate tprintf("TRACE- pexerr()\n");
1797c478bd9Sstevel@tonic-gate #endif
1807c478bd9Sstevel@tonic-gate /* Couldn't find the damn thing */
1817c478bd9Sstevel@tonic-gate if (exerr)
1827c478bd9Sstevel@tonic-gate bferr(exerr);
1837c478bd9Sstevel@tonic-gate bferr("Command not found");
1847c478bd9Sstevel@tonic-gate }
1857c478bd9Sstevel@tonic-gate
1867c478bd9Sstevel@tonic-gate /*
1877c478bd9Sstevel@tonic-gate * Execute command f, arg list t.
1887c478bd9Sstevel@tonic-gate * Record error message if not found.
1897c478bd9Sstevel@tonic-gate * Also do shell scripts here.
1907c478bd9Sstevel@tonic-gate */
1916c02b4a4Smuffin void
texec(struct command * cmd,tchar * f,tchar ** t)1926c02b4a4Smuffin texec(struct command *cmd, tchar *f, tchar **t)
1937c478bd9Sstevel@tonic-gate {
1946c02b4a4Smuffin struct varent *v;
1956c02b4a4Smuffin tchar **vp;
1967c478bd9Sstevel@tonic-gate tchar *lastsh[2];
1977c478bd9Sstevel@tonic-gate
1987c478bd9Sstevel@tonic-gate #ifdef TRACE
1997c478bd9Sstevel@tonic-gate tprintf("TRACE- texec()\n");
2007c478bd9Sstevel@tonic-gate #endif
2017c478bd9Sstevel@tonic-gate /* convert cfname and cargs from tchar to char */
2027c478bd9Sstevel@tonic-gate tconvert(cmd, f, t);
2037c478bd9Sstevel@tonic-gate
2047c478bd9Sstevel@tonic-gate execv(cmd->cfname, cmd->cargs);
2057c478bd9Sstevel@tonic-gate
2067c478bd9Sstevel@tonic-gate /*
2077c478bd9Sstevel@tonic-gate * exec returned, free up allocations from above
2087c478bd9Sstevel@tonic-gate * tconvert(), zero cfname and cargs to prevent
2097c478bd9Sstevel@tonic-gate * duplicate free() in freesyn()
2107c478bd9Sstevel@tonic-gate */
2117c478bd9Sstevel@tonic-gate xfree(cmd->cfname);
2127c478bd9Sstevel@tonic-gate chr_blkfree(cmd->cargs);
2137c478bd9Sstevel@tonic-gate cmd->cfname = (char *)0;
2147c478bd9Sstevel@tonic-gate cmd->cargs = (char **)0;
2157c478bd9Sstevel@tonic-gate
2167c478bd9Sstevel@tonic-gate switch (errno) {
2177c478bd9Sstevel@tonic-gate case ENOEXEC:
2187c478bd9Sstevel@tonic-gate /* check that this is not a binary file */
2197c478bd9Sstevel@tonic-gate {
2206c02b4a4Smuffin int ff = open_(f, 0);
22165b0c20eSnakanon tchar ch[MB_LEN_MAX];
2227c478bd9Sstevel@tonic-gate
22365b0c20eSnakanon if (ff != -1 && read_(ff, ch, 1) == 1 &&
22465b0c20eSnakanon !isprint(ch[0]) && !isspace(ch[0])) {
2257c478bd9Sstevel@tonic-gate printf("Cannot execute binary file.\n");
2267c478bd9Sstevel@tonic-gate Perror(f);
2277c478bd9Sstevel@tonic-gate (void) close(ff);
2287c478bd9Sstevel@tonic-gate unsetfd(ff);
2297c478bd9Sstevel@tonic-gate return;
2307c478bd9Sstevel@tonic-gate }
2317c478bd9Sstevel@tonic-gate (void) close(ff);
2327c478bd9Sstevel@tonic-gate unsetfd(ff);
2337c478bd9Sstevel@tonic-gate }
2347c478bd9Sstevel@tonic-gate /*
2357c478bd9Sstevel@tonic-gate * If there is an alias for shell, then
2367c478bd9Sstevel@tonic-gate * put the words of the alias in front of the
2377c478bd9Sstevel@tonic-gate * argument list replacing the command name.
2387c478bd9Sstevel@tonic-gate * Note no interpretation of the words at this point.
2397c478bd9Sstevel@tonic-gate */
2407c478bd9Sstevel@tonic-gate v = adrof1(S_shell /* "shell" */, &aliases);
2417c478bd9Sstevel@tonic-gate if (v == 0) {
2427c478bd9Sstevel@tonic-gate #ifdef OTHERSH
2436c02b4a4Smuffin int ff = open_(f, 0);
24465b0c20eSnakanon tchar ch[MB_LEN_MAX];
2457c478bd9Sstevel@tonic-gate #endif
2467c478bd9Sstevel@tonic-gate
2477c478bd9Sstevel@tonic-gate vp = lastsh;
248*134a1f4eSCasper H.S. Dik vp[0] = adrof(S_shell /* "shell" */) ?
249*134a1f4eSCasper H.S. Dik value(S_shell /* "shell" */) :
250*134a1f4eSCasper H.S. Dik S_SHELLPATH /* SHELLPATH */;
2517c478bd9Sstevel@tonic-gate vp[1] = (tchar *) NULL;
2527c478bd9Sstevel@tonic-gate #ifdef OTHERSH
25365b0c20eSnakanon if (ff != -1 && read_(ff, ch, 1) == 1 && ch[0] != '#')
2547c478bd9Sstevel@tonic-gate vp[0] = S_OTHERSH /* OTHERSH */;
2557c478bd9Sstevel@tonic-gate (void) close(ff);
2567c478bd9Sstevel@tonic-gate unsetfd(ff);
2577c478bd9Sstevel@tonic-gate #endif
2587c478bd9Sstevel@tonic-gate } else
2597c478bd9Sstevel@tonic-gate vp = v->vec;
2607c478bd9Sstevel@tonic-gate t[0] = f;
2617c478bd9Sstevel@tonic-gate t = blkspl(vp, t); /* Splice up the new arglst */
2627c478bd9Sstevel@tonic-gate f = *t;
2637c478bd9Sstevel@tonic-gate
2647c478bd9Sstevel@tonic-gate tconvert(cmd, f, t); /* convert tchar to char */
2657c478bd9Sstevel@tonic-gate
2667c478bd9Sstevel@tonic-gate /*
2677c478bd9Sstevel@tonic-gate * now done with tchar arg list t,
2687c478bd9Sstevel@tonic-gate * free the space calloc'd by above blkspl()
2697c478bd9Sstevel@tonic-gate */
2707c478bd9Sstevel@tonic-gate xfree((char *)t);
2717c478bd9Sstevel@tonic-gate
2727c478bd9Sstevel@tonic-gate execv(cmd->cfname, cmd->cargs); /* exec the command */
2737c478bd9Sstevel@tonic-gate
2747c478bd9Sstevel@tonic-gate /* exec returned, same free'ing as above */
2757c478bd9Sstevel@tonic-gate xfree(cmd->cfname);
2767c478bd9Sstevel@tonic-gate chr_blkfree(cmd->cargs);
2777c478bd9Sstevel@tonic-gate cmd->cfname = (char *)0;
2787c478bd9Sstevel@tonic-gate cmd->cargs = (char **)0;
2797c478bd9Sstevel@tonic-gate
2807c478bd9Sstevel@tonic-gate /* The sky is falling, the sky is falling! */
2817c478bd9Sstevel@tonic-gate
2827c478bd9Sstevel@tonic-gate case ENOMEM:
2837c478bd9Sstevel@tonic-gate Perror(f);
2847c478bd9Sstevel@tonic-gate
2857c478bd9Sstevel@tonic-gate case ENOENT:
2867c478bd9Sstevel@tonic-gate break;
2877c478bd9Sstevel@tonic-gate
2887c478bd9Sstevel@tonic-gate default:
2897c478bd9Sstevel@tonic-gate if (exerr == 0) {
2907c478bd9Sstevel@tonic-gate exerr = strerror(errno);
2917c478bd9Sstevel@tonic-gate setname(f);
2927c478bd9Sstevel@tonic-gate }
2937c478bd9Sstevel@tonic-gate }
2947c478bd9Sstevel@tonic-gate }
2957c478bd9Sstevel@tonic-gate
2967c478bd9Sstevel@tonic-gate
2976c02b4a4Smuffin static void
tconvert(struct command * cmd,tchar * fname,tchar ** list)2986c02b4a4Smuffin tconvert(struct command *cmd, tchar *fname, tchar **list)
2997c478bd9Sstevel@tonic-gate {
3006c02b4a4Smuffin char **rc;
3016c02b4a4Smuffin int len;
3027c478bd9Sstevel@tonic-gate
3037c478bd9Sstevel@tonic-gate cmd->cfname = tstostr(NULL, fname);
3047c478bd9Sstevel@tonic-gate
3057c478bd9Sstevel@tonic-gate len = blklen(list);
3067c478bd9Sstevel@tonic-gate rc = cmd->cargs = (char **)
30765b0c20eSnakanon xcalloc((uint_t)(len + 1), sizeof (char **));
3087c478bd9Sstevel@tonic-gate while (len--)
3097c478bd9Sstevel@tonic-gate *rc++ = tstostr(NULL, *list++);
3107c478bd9Sstevel@tonic-gate *rc = NULL;
3117c478bd9Sstevel@tonic-gate }
3127c478bd9Sstevel@tonic-gate
3137c478bd9Sstevel@tonic-gate
3147c478bd9Sstevel@tonic-gate /*ARGSUSED*/
3156c02b4a4Smuffin void
execash(tchar ** t,struct command * kp)3166c02b4a4Smuffin execash(tchar **t, struct command *kp)
3177c478bd9Sstevel@tonic-gate {
3187c478bd9Sstevel@tonic-gate #ifdef TRACE
3197c478bd9Sstevel@tonic-gate tprintf("TRACE- execash()\n");
3207c478bd9Sstevel@tonic-gate #endif
3217c478bd9Sstevel@tonic-gate
3227c478bd9Sstevel@tonic-gate rechist();
3237c478bd9Sstevel@tonic-gate (void) signal(SIGINT, parintr);
3247c478bd9Sstevel@tonic-gate (void) signal(SIGQUIT, parintr);
3257c478bd9Sstevel@tonic-gate (void) signal(SIGTERM, parterm); /* if doexec loses, screw */
3267c478bd9Sstevel@tonic-gate lshift(kp->t_dcom, 1);
3277c478bd9Sstevel@tonic-gate exiterr++;
3287c478bd9Sstevel@tonic-gate doexec(kp);
3297c478bd9Sstevel@tonic-gate /*NOTREACHED*/
3307c478bd9Sstevel@tonic-gate }
3317c478bd9Sstevel@tonic-gate
3326c02b4a4Smuffin void
xechoit(tchar ** t)3336c02b4a4Smuffin xechoit(tchar **t)
3347c478bd9Sstevel@tonic-gate {
3357c478bd9Sstevel@tonic-gate #ifdef TRACE
3367c478bd9Sstevel@tonic-gate tprintf("TRACE- xechoit()\n");
3377c478bd9Sstevel@tonic-gate #endif
3387c478bd9Sstevel@tonic-gate
3397c478bd9Sstevel@tonic-gate if (adrof(S_echo /* "echo" */)) {
3407c478bd9Sstevel@tonic-gate flush();
3417c478bd9Sstevel@tonic-gate haderr = 1;
3427c478bd9Sstevel@tonic-gate blkpr(t), Putchar('\n');
3437c478bd9Sstevel@tonic-gate haderr = 0;
3447c478bd9Sstevel@tonic-gate }
3457c478bd9Sstevel@tonic-gate }
3467c478bd9Sstevel@tonic-gate
3477c478bd9Sstevel@tonic-gate /*
3487c478bd9Sstevel@tonic-gate * This routine called when user enters "rehash".
3497c478bd9Sstevel@tonic-gate * Both the path and cdpath caching arrays will
3507c478bd9Sstevel@tonic-gate * be rehashed, via calling dohash. If either
3517c478bd9Sstevel@tonic-gate * variable is not set with a value, then dohash
3527c478bd9Sstevel@tonic-gate * just exits.
3537c478bd9Sstevel@tonic-gate */
3546c02b4a4Smuffin void
dorehash(void)3556c02b4a4Smuffin dorehash(void)
3567c478bd9Sstevel@tonic-gate {
3577c478bd9Sstevel@tonic-gate dohash(xhash);
3587c478bd9Sstevel@tonic-gate dohash(xhash2);
3597c478bd9Sstevel@tonic-gate }
3607c478bd9Sstevel@tonic-gate
3617c478bd9Sstevel@tonic-gate /*
3627c478bd9Sstevel@tonic-gate * Fill up caching arrays for path and cdpath
3637c478bd9Sstevel@tonic-gate */
3646c02b4a4Smuffin void
dohash(char cachearray[])3656c02b4a4Smuffin dohash(char cachearray[])
3667c478bd9Sstevel@tonic-gate {
3677c478bd9Sstevel@tonic-gate struct stat stb;
3687c478bd9Sstevel@tonic-gate DIR *dirp;
3696c02b4a4Smuffin struct dirent *dp;
3706c02b4a4Smuffin int cnt;
3717c478bd9Sstevel@tonic-gate int i = 0;
3727c478bd9Sstevel@tonic-gate struct varent *v;
3737c478bd9Sstevel@tonic-gate tchar **pv;
3747c478bd9Sstevel@tonic-gate int hashval;
3757c478bd9Sstevel@tonic-gate tchar curdir_[MAXNAMLEN+1];
3767c478bd9Sstevel@tonic-gate
3777c478bd9Sstevel@tonic-gate #ifdef TRACE
3787c478bd9Sstevel@tonic-gate tprintf("TRACE- dohash()\n");
3797c478bd9Sstevel@tonic-gate #endif
3807c478bd9Sstevel@tonic-gate /* Caching $path */
3817c478bd9Sstevel@tonic-gate if (cachearray == xhash) {
3827c478bd9Sstevel@tonic-gate havhash = 1;
3837c478bd9Sstevel@tonic-gate v = adrof(S_path /* "path" */);
3847c478bd9Sstevel@tonic-gate } else { /* Caching $cdpath */
3857c478bd9Sstevel@tonic-gate havhash2 = 1;
3867c478bd9Sstevel@tonic-gate v = adrof(S_cdpath /* "cdpath" */);
3877c478bd9Sstevel@tonic-gate }
3887c478bd9Sstevel@tonic-gate
3897c478bd9Sstevel@tonic-gate for (cnt = 0; cnt < (HSHSIZ / 8); cnt++)
3907c478bd9Sstevel@tonic-gate cachearray[cnt] = 0;
3917c478bd9Sstevel@tonic-gate if (v == 0)
3927c478bd9Sstevel@tonic-gate return;
3937c478bd9Sstevel@tonic-gate for (pv = v->vec; *pv; pv++, i++) {
3947c478bd9Sstevel@tonic-gate if (pv[0][0] != '/')
3957c478bd9Sstevel@tonic-gate continue;
3967c478bd9Sstevel@tonic-gate dirp = opendir_(*pv);
3977c478bd9Sstevel@tonic-gate if (dirp == NULL)
3987c478bd9Sstevel@tonic-gate continue;
3997c478bd9Sstevel@tonic-gate if (fstat(dirp->dd_fd, &stb) < 0 || !isdir(stb)) {
4007c478bd9Sstevel@tonic-gate unsetfd(dirp->dd_fd);
4017c478bd9Sstevel@tonic-gate closedir_(dirp);
4027c478bd9Sstevel@tonic-gate continue;
4037c478bd9Sstevel@tonic-gate }
4047c478bd9Sstevel@tonic-gate while ((dp = readdir(dirp)) != NULL) {
4057c478bd9Sstevel@tonic-gate if (dp->d_ino == 0)
4067c478bd9Sstevel@tonic-gate continue;
4077c478bd9Sstevel@tonic-gate if (dp->d_name[0] == '.' &&
4087c478bd9Sstevel@tonic-gate (dp->d_name[1] == '\0' ||
4097c478bd9Sstevel@tonic-gate dp->d_name[1] == '.' && dp->d_name[2] == '\0'))
4107c478bd9Sstevel@tonic-gate continue;
411*134a1f4eSCasper H.S. Dik hashval = hash(hashname(strtots(curdir_, dp->d_name)),
412*134a1f4eSCasper H.S. Dik i);
4137c478bd9Sstevel@tonic-gate bis(cachearray, hashval);
4147c478bd9Sstevel@tonic-gate }
4157c478bd9Sstevel@tonic-gate unsetfd(dirp->dd_fd);
4167c478bd9Sstevel@tonic-gate closedir_(dirp);
4177c478bd9Sstevel@tonic-gate }
4187c478bd9Sstevel@tonic-gate }
4197c478bd9Sstevel@tonic-gate
4206c02b4a4Smuffin void
dounhash(void)4216c02b4a4Smuffin dounhash(void)
4227c478bd9Sstevel@tonic-gate {
4237c478bd9Sstevel@tonic-gate
4247c478bd9Sstevel@tonic-gate #ifdef TRACE
4257c478bd9Sstevel@tonic-gate tprintf("TRACE- dounhash()\n");
4267c478bd9Sstevel@tonic-gate #endif
4277c478bd9Sstevel@tonic-gate havhash = 0;
4287c478bd9Sstevel@tonic-gate havhash2 = 0;
4297c478bd9Sstevel@tonic-gate }
4307c478bd9Sstevel@tonic-gate
4317c478bd9Sstevel@tonic-gate #ifdef VFORK
4326c02b4a4Smuffin void
hashstat(void)4336c02b4a4Smuffin hashstat(void)
4347c478bd9Sstevel@tonic-gate {
4357c478bd9Sstevel@tonic-gate #ifdef TRACE
4367c478bd9Sstevel@tonic-gate tprintf("TRACE- hashstat_()\n");
4377c478bd9Sstevel@tonic-gate #endif
4387c478bd9Sstevel@tonic-gate
4397c478bd9Sstevel@tonic-gate if (hits+misses)
4407c478bd9Sstevel@tonic-gate printf("%d hits, %d misses, %d%%\n",
4417c478bd9Sstevel@tonic-gate hits, misses, 100 * hits / (hits + misses));
4427c478bd9Sstevel@tonic-gate }
4437c478bd9Sstevel@tonic-gate #endif
4447c478bd9Sstevel@tonic-gate
4457c478bd9Sstevel@tonic-gate /*
4467c478bd9Sstevel@tonic-gate * Hash a command name.
4477c478bd9Sstevel@tonic-gate */
4486c02b4a4Smuffin int
hashname(tchar * cp)4496c02b4a4Smuffin hashname(tchar *cp)
4507c478bd9Sstevel@tonic-gate {
4516c02b4a4Smuffin long h = 0;
4527c478bd9Sstevel@tonic-gate
4537c478bd9Sstevel@tonic-gate #ifdef TRACE
4547c478bd9Sstevel@tonic-gate tprintf("TRACE- hashname()\n");
4557c478bd9Sstevel@tonic-gate #endif
4567c478bd9Sstevel@tonic-gate while (*cp)
4577c478bd9Sstevel@tonic-gate h = hash(h, *cp++);
4587c478bd9Sstevel@tonic-gate return ((int)h);
4597c478bd9Sstevel@tonic-gate }
460