17c478bd9Sstevel@tonic-gate /* 26c02b4a4Smuffin * Copyright 2005 Sun Microsystems, Inc. All rights reserved. 37c478bd9Sstevel@tonic-gate * Use is subject to license terms. 47c478bd9Sstevel@tonic-gate */ 57c478bd9Sstevel@tonic-gate 67c478bd9Sstevel@tonic-gate /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 77c478bd9Sstevel@tonic-gate /* All Rights Reserved */ 87c478bd9Sstevel@tonic-gate 97c478bd9Sstevel@tonic-gate /* 107c478bd9Sstevel@tonic-gate * Copyright (c) 1980 Regents of the University of California. 117c478bd9Sstevel@tonic-gate * All rights reserved. The Berkeley Software License Agreement 127c478bd9Sstevel@tonic-gate * specifies the terms and conditions for redistribution. 137c478bd9Sstevel@tonic-gate */ 147c478bd9Sstevel@tonic-gate 157c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 167c478bd9Sstevel@tonic-gate 177c478bd9Sstevel@tonic-gate #include "sh.h" 187c478bd9Sstevel@tonic-gate #include <dirent.h> 197c478bd9Sstevel@tonic-gate #include <string.h> 207c478bd9Sstevel@tonic-gate #include "sh.tconst.h" 217c478bd9Sstevel@tonic-gate #include "sh_policy.h" 227c478bd9Sstevel@tonic-gate 237c478bd9Sstevel@tonic-gate 247c478bd9Sstevel@tonic-gate /* 257c478bd9Sstevel@tonic-gate * C shell 267c478bd9Sstevel@tonic-gate */ 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate /* 297c478bd9Sstevel@tonic-gate * System level search and execute of a command. 307c478bd9Sstevel@tonic-gate * We look in each directory for the specified command name. 317c478bd9Sstevel@tonic-gate * If the name contains a '/' then we execute only the full path name. 327c478bd9Sstevel@tonic-gate * If there is no search path then we execute only full path names. 337c478bd9Sstevel@tonic-gate */ 347c478bd9Sstevel@tonic-gate 357c478bd9Sstevel@tonic-gate /* 367c478bd9Sstevel@tonic-gate * As we search for the command we note the first non-trivial error 377c478bd9Sstevel@tonic-gate * message for presentation to the user. This allows us often 387c478bd9Sstevel@tonic-gate * to show that a file has the wrong mode/no access when the file 397c478bd9Sstevel@tonic-gate * is not in the last component of the search path, so we must 407c478bd9Sstevel@tonic-gate * go on after first detecting the error. 417c478bd9Sstevel@tonic-gate */ 427c478bd9Sstevel@tonic-gate char *exerr; /* Execution error message */ 437c478bd9Sstevel@tonic-gate 446c02b4a4Smuffin void pexerr(void); 456c02b4a4Smuffin void texec(struct command *, tchar *, tchar **); 466c02b4a4Smuffin void xechoit(tchar **); 476c02b4a4Smuffin void dohash(char []); 487c478bd9Sstevel@tonic-gate 496c02b4a4Smuffin static void tconvert(struct command *, tchar *, tchar **); 507c478bd9Sstevel@tonic-gate 517c478bd9Sstevel@tonic-gate 526c02b4a4Smuffin extern DIR *opendir_(tchar *); 536c02b4a4Smuffin 546c02b4a4Smuffin void 556c02b4a4Smuffin doexec(struct command *t) 567c478bd9Sstevel@tonic-gate { 577c478bd9Sstevel@tonic-gate tchar *sav; 586c02b4a4Smuffin tchar *dp, **pv, **av; 596c02b4a4Smuffin struct varent *v; 607c478bd9Sstevel@tonic-gate bool slash; 617c478bd9Sstevel@tonic-gate int hashval, hashval1, i; 627c478bd9Sstevel@tonic-gate tchar *blk[2]; 637c478bd9Sstevel@tonic-gate #ifdef TRACE 647c478bd9Sstevel@tonic-gate tprintf("TRACE- doexec()\n"); 657c478bd9Sstevel@tonic-gate #endif 667c478bd9Sstevel@tonic-gate 677c478bd9Sstevel@tonic-gate /* 687c478bd9Sstevel@tonic-gate * Glob the command name. If this does anything, then we 697c478bd9Sstevel@tonic-gate * will execute the command only relative to ".". One special 707c478bd9Sstevel@tonic-gate * case: if there is no PATH, then we execute only commands 717c478bd9Sstevel@tonic-gate * which start with '/'. 727c478bd9Sstevel@tonic-gate */ 737c478bd9Sstevel@tonic-gate dp = globone(t->t_dcom[0]); 747c478bd9Sstevel@tonic-gate sav = t->t_dcom[0]; 757c478bd9Sstevel@tonic-gate exerr = 0; t->t_dcom[0] = dp; 767c478bd9Sstevel@tonic-gate setname(dp); 777c478bd9Sstevel@tonic-gate xfree(sav); 787c478bd9Sstevel@tonic-gate v = adrof(S_path /* "path" */); 797c478bd9Sstevel@tonic-gate if (v == 0 && dp[0] != '/') { 807c478bd9Sstevel@tonic-gate pexerr(); 817c478bd9Sstevel@tonic-gate } 827c478bd9Sstevel@tonic-gate slash = gflag; 837c478bd9Sstevel@tonic-gate 847c478bd9Sstevel@tonic-gate /* 857c478bd9Sstevel@tonic-gate * Glob the argument list, if necessary. 867c478bd9Sstevel@tonic-gate * Otherwise trim off the quote bits. 877c478bd9Sstevel@tonic-gate */ 887c478bd9Sstevel@tonic-gate gflag = 0; av = &t->t_dcom[1]; 897c478bd9Sstevel@tonic-gate tglob(av); 907c478bd9Sstevel@tonic-gate if (gflag) { 917c478bd9Sstevel@tonic-gate av = glob(av); 927c478bd9Sstevel@tonic-gate if (av == 0) 937c478bd9Sstevel@tonic-gate error("No match"); 947c478bd9Sstevel@tonic-gate } 957c478bd9Sstevel@tonic-gate blk[0] = t->t_dcom[0]; 967c478bd9Sstevel@tonic-gate blk[1] = 0; 977c478bd9Sstevel@tonic-gate av = blkspl(blk, av); 987c478bd9Sstevel@tonic-gate #ifdef VFORK 997c478bd9Sstevel@tonic-gate Vav = av; 1007c478bd9Sstevel@tonic-gate #endif 1017c478bd9Sstevel@tonic-gate trim(av); 1027c478bd9Sstevel@tonic-gate slash |= any('/', av[0]); 1037c478bd9Sstevel@tonic-gate 1047c478bd9Sstevel@tonic-gate xechoit(av); /* Echo command if -x */ 1057c478bd9Sstevel@tonic-gate /* 1067c478bd9Sstevel@tonic-gate * Since all internal file descriptors are set to close on exec, 1077c478bd9Sstevel@tonic-gate * we don't need to close them explicitly here. Just reorient 1087c478bd9Sstevel@tonic-gate * ourselves for error messages. 1097c478bd9Sstevel@tonic-gate */ 1107c478bd9Sstevel@tonic-gate SHIN = 0; SHOUT = 1; SHDIAG = 2; OLDSTD = 0; 1117c478bd9Sstevel@tonic-gate 1127c478bd9Sstevel@tonic-gate /* 1137c478bd9Sstevel@tonic-gate * We must do this AFTER any possible forking (like `foo` 1147c478bd9Sstevel@tonic-gate * in glob) so that this shell can still do subprocesses. 1157c478bd9Sstevel@tonic-gate */ 1167c478bd9Sstevel@tonic-gate (void) sigsetmask(0); 1177c478bd9Sstevel@tonic-gate 1187c478bd9Sstevel@tonic-gate /* 1197c478bd9Sstevel@tonic-gate * If no path, no words in path, or a / in the filename 1207c478bd9Sstevel@tonic-gate * then restrict the command search. 1217c478bd9Sstevel@tonic-gate */ 1227c478bd9Sstevel@tonic-gate if (v == 0 || v->vec[0] == 0 || slash) 1237c478bd9Sstevel@tonic-gate pv = justabs; 1247c478bd9Sstevel@tonic-gate else 1257c478bd9Sstevel@tonic-gate pv = v->vec; 1267c478bd9Sstevel@tonic-gate sav = strspl(S_SLASH /* "/" */, *av); /* / command name for postpending */ 1277c478bd9Sstevel@tonic-gate #ifdef VFORK 1287c478bd9Sstevel@tonic-gate Vsav = sav; 1297c478bd9Sstevel@tonic-gate #endif 1307c478bd9Sstevel@tonic-gate if (havhash) 1317c478bd9Sstevel@tonic-gate hashval = hashname(*av); 1327c478bd9Sstevel@tonic-gate i = 0; 1337c478bd9Sstevel@tonic-gate #ifdef VFORK 1347c478bd9Sstevel@tonic-gate hits++; 1357c478bd9Sstevel@tonic-gate #endif 1367c478bd9Sstevel@tonic-gate do { 1377c478bd9Sstevel@tonic-gate if (!slash && pv[0][0] == '/' && havhash) { 1387c478bd9Sstevel@tonic-gate hashval1 = hash(hashval, i); 1397c478bd9Sstevel@tonic-gate if (!bit(xhash, hashval1)) 1407c478bd9Sstevel@tonic-gate goto cont; 1417c478bd9Sstevel@tonic-gate } 1427c478bd9Sstevel@tonic-gate 1437c478bd9Sstevel@tonic-gate if (pv[0][0] == 0 || eq(pv[0], S_DOT /* "." */)) { /* don't make ./xxx */ 1447c478bd9Sstevel@tonic-gate texec(t, *av, av); 1457c478bd9Sstevel@tonic-gate } else { 1467c478bd9Sstevel@tonic-gate dp = strspl(*pv, sav); 1477c478bd9Sstevel@tonic-gate #ifdef VFORK 1487c478bd9Sstevel@tonic-gate Vdp = dp; 1497c478bd9Sstevel@tonic-gate #endif 1507c478bd9Sstevel@tonic-gate texec(t, dp, av); 1517c478bd9Sstevel@tonic-gate #ifdef VFORK 1527c478bd9Sstevel@tonic-gate Vdp = 0; 1537c478bd9Sstevel@tonic-gate #endif 1547c478bd9Sstevel@tonic-gate xfree(dp); 1557c478bd9Sstevel@tonic-gate } 1567c478bd9Sstevel@tonic-gate #ifdef VFORK 1577c478bd9Sstevel@tonic-gate misses++; 1587c478bd9Sstevel@tonic-gate #endif 1597c478bd9Sstevel@tonic-gate cont: 1607c478bd9Sstevel@tonic-gate pv++; 1617c478bd9Sstevel@tonic-gate i++; 1627c478bd9Sstevel@tonic-gate } while (*pv); 1637c478bd9Sstevel@tonic-gate #ifdef VFORK 1647c478bd9Sstevel@tonic-gate hits--; 1657c478bd9Sstevel@tonic-gate #endif 1667c478bd9Sstevel@tonic-gate #ifdef VFORK 1677c478bd9Sstevel@tonic-gate Vsav = 0; 1687c478bd9Sstevel@tonic-gate Vav = 0; 1697c478bd9Sstevel@tonic-gate #endif 1707c478bd9Sstevel@tonic-gate xfree(sav); 1717c478bd9Sstevel@tonic-gate xfree((char *)av); 1727c478bd9Sstevel@tonic-gate pexerr(); 1737c478bd9Sstevel@tonic-gate } 1747c478bd9Sstevel@tonic-gate 1756c02b4a4Smuffin void 1766c02b4a4Smuffin pexerr(void) 1777c478bd9Sstevel@tonic-gate { 1787c478bd9Sstevel@tonic-gate 1797c478bd9Sstevel@tonic-gate #ifdef TRACE 1807c478bd9Sstevel@tonic-gate tprintf("TRACE- pexerr()\n"); 1817c478bd9Sstevel@tonic-gate #endif 1827c478bd9Sstevel@tonic-gate /* Couldn't find the damn thing */ 1837c478bd9Sstevel@tonic-gate if (exerr) 1847c478bd9Sstevel@tonic-gate bferr(exerr); 1857c478bd9Sstevel@tonic-gate bferr("Command not found"); 1867c478bd9Sstevel@tonic-gate } 1877c478bd9Sstevel@tonic-gate 1887c478bd9Sstevel@tonic-gate /* 1897c478bd9Sstevel@tonic-gate * Execute command f, arg list t. 1907c478bd9Sstevel@tonic-gate * Record error message if not found. 1917c478bd9Sstevel@tonic-gate * Also do shell scripts here. 1927c478bd9Sstevel@tonic-gate */ 1936c02b4a4Smuffin void 1946c02b4a4Smuffin texec(struct command *cmd, tchar *f, tchar **t) 1957c478bd9Sstevel@tonic-gate { 1966c02b4a4Smuffin int pfstatus = 0; 1976c02b4a4Smuffin struct varent *v; 1986c02b4a4Smuffin tchar **vp; 1997c478bd9Sstevel@tonic-gate tchar *lastsh[2]; 2007c478bd9Sstevel@tonic-gate 2017c478bd9Sstevel@tonic-gate #ifdef TRACE 2027c478bd9Sstevel@tonic-gate tprintf("TRACE- texec()\n"); 2037c478bd9Sstevel@tonic-gate #endif 2047c478bd9Sstevel@tonic-gate /* convert cfname and cargs from tchar to char */ 2057c478bd9Sstevel@tonic-gate tconvert(cmd, f, t); 2067c478bd9Sstevel@tonic-gate 2077c478bd9Sstevel@tonic-gate if (pfcshflag == 1) { 2087c478bd9Sstevel@tonic-gate pfstatus = secpolicy_pfexec((const char *)(cmd->cfname), 2097c478bd9Sstevel@tonic-gate cmd->cargs, (const char **)NULL); 2107c478bd9Sstevel@tonic-gate if (pfstatus != NOATTRS) { 2117c478bd9Sstevel@tonic-gate errno = pfstatus; 2127c478bd9Sstevel@tonic-gate } 2137c478bd9Sstevel@tonic-gate } 2147c478bd9Sstevel@tonic-gate if ((pfcshflag == 0) || (pfstatus == NOATTRS)) { 2157c478bd9Sstevel@tonic-gate execv(cmd->cfname, cmd->cargs); 2167c478bd9Sstevel@tonic-gate } 2177c478bd9Sstevel@tonic-gate 2187c478bd9Sstevel@tonic-gate /* 2197c478bd9Sstevel@tonic-gate * exec returned, free up allocations from above 2207c478bd9Sstevel@tonic-gate * tconvert(), zero cfname and cargs to prevent 2217c478bd9Sstevel@tonic-gate * duplicate free() in freesyn() 2227c478bd9Sstevel@tonic-gate */ 2237c478bd9Sstevel@tonic-gate xfree(cmd->cfname); 2247c478bd9Sstevel@tonic-gate chr_blkfree(cmd->cargs); 2257c478bd9Sstevel@tonic-gate cmd->cfname = (char *)0; 2267c478bd9Sstevel@tonic-gate cmd->cargs = (char **)0; 2277c478bd9Sstevel@tonic-gate 2287c478bd9Sstevel@tonic-gate switch (errno) { 2297c478bd9Sstevel@tonic-gate case ENOEXEC: 2307c478bd9Sstevel@tonic-gate /* check that this is not a binary file */ 2317c478bd9Sstevel@tonic-gate { 2326c02b4a4Smuffin int ff = open_(f, 0); 233*65b0c20eSnakanon tchar ch[MB_LEN_MAX]; 2347c478bd9Sstevel@tonic-gate 235*65b0c20eSnakanon if (ff != -1 && read_(ff, ch, 1) == 1 && 236*65b0c20eSnakanon !isprint(ch[0]) && !isspace(ch[0])) { 2377c478bd9Sstevel@tonic-gate printf("Cannot execute binary file.\n"); 2387c478bd9Sstevel@tonic-gate Perror(f); 2397c478bd9Sstevel@tonic-gate (void) close(ff); 2407c478bd9Sstevel@tonic-gate unsetfd(ff); 2417c478bd9Sstevel@tonic-gate return; 2427c478bd9Sstevel@tonic-gate } 2437c478bd9Sstevel@tonic-gate (void) close(ff); 2447c478bd9Sstevel@tonic-gate unsetfd(ff); 2457c478bd9Sstevel@tonic-gate } 2467c478bd9Sstevel@tonic-gate /* 2477c478bd9Sstevel@tonic-gate * If there is an alias for shell, then 2487c478bd9Sstevel@tonic-gate * put the words of the alias in front of the 2497c478bd9Sstevel@tonic-gate * argument list replacing the command name. 2507c478bd9Sstevel@tonic-gate * Note no interpretation of the words at this point. 2517c478bd9Sstevel@tonic-gate */ 2527c478bd9Sstevel@tonic-gate v = adrof1(S_shell /* "shell" */, &aliases); 2537c478bd9Sstevel@tonic-gate if (v == 0) { 2547c478bd9Sstevel@tonic-gate #ifdef OTHERSH 2556c02b4a4Smuffin int ff = open_(f, 0); 256*65b0c20eSnakanon tchar ch[MB_LEN_MAX]; 2577c478bd9Sstevel@tonic-gate #endif 2587c478bd9Sstevel@tonic-gate 2597c478bd9Sstevel@tonic-gate vp = lastsh; 2607c478bd9Sstevel@tonic-gate vp[0] = adrof(S_shell /* "shell" */) ? value(S_shell /* "shell" */) : S_SHELLPATH /* SHELLPATH */; 2617c478bd9Sstevel@tonic-gate vp[1] = (tchar *) NULL; 2627c478bd9Sstevel@tonic-gate #ifdef OTHERSH 263*65b0c20eSnakanon if (ff != -1 && read_(ff, ch, 1) == 1 && ch[0] != '#') 2647c478bd9Sstevel@tonic-gate vp[0] = S_OTHERSH /* OTHERSH */; 2657c478bd9Sstevel@tonic-gate (void) close(ff); 2667c478bd9Sstevel@tonic-gate unsetfd(ff); 2677c478bd9Sstevel@tonic-gate #endif 2687c478bd9Sstevel@tonic-gate } else 2697c478bd9Sstevel@tonic-gate vp = v->vec; 2707c478bd9Sstevel@tonic-gate t[0] = f; 2717c478bd9Sstevel@tonic-gate t = blkspl(vp, t); /* Splice up the new arglst */ 2727c478bd9Sstevel@tonic-gate f = *t; 2737c478bd9Sstevel@tonic-gate 2747c478bd9Sstevel@tonic-gate tconvert(cmd, f, t); /* convert tchar to char */ 2757c478bd9Sstevel@tonic-gate 2767c478bd9Sstevel@tonic-gate /* 2777c478bd9Sstevel@tonic-gate * now done with tchar arg list t, 2787c478bd9Sstevel@tonic-gate * free the space calloc'd by above blkspl() 2797c478bd9Sstevel@tonic-gate */ 2807c478bd9Sstevel@tonic-gate xfree((char *)t); 2817c478bd9Sstevel@tonic-gate 2827c478bd9Sstevel@tonic-gate execv(cmd->cfname, cmd->cargs); /* exec the command */ 2837c478bd9Sstevel@tonic-gate 2847c478bd9Sstevel@tonic-gate /* exec returned, same free'ing as above */ 2857c478bd9Sstevel@tonic-gate xfree(cmd->cfname); 2867c478bd9Sstevel@tonic-gate chr_blkfree(cmd->cargs); 2877c478bd9Sstevel@tonic-gate cmd->cfname = (char *)0; 2887c478bd9Sstevel@tonic-gate cmd->cargs = (char **)0; 2897c478bd9Sstevel@tonic-gate 2907c478bd9Sstevel@tonic-gate /* The sky is falling, the sky is falling! */ 2917c478bd9Sstevel@tonic-gate 2927c478bd9Sstevel@tonic-gate case ENOMEM: 2937c478bd9Sstevel@tonic-gate Perror(f); 2947c478bd9Sstevel@tonic-gate 2957c478bd9Sstevel@tonic-gate case ENOENT: 2967c478bd9Sstevel@tonic-gate break; 2977c478bd9Sstevel@tonic-gate 2987c478bd9Sstevel@tonic-gate default: 2997c478bd9Sstevel@tonic-gate if (exerr == 0) { 3007c478bd9Sstevel@tonic-gate exerr = strerror(errno); 3017c478bd9Sstevel@tonic-gate setname(f); 3027c478bd9Sstevel@tonic-gate } 3037c478bd9Sstevel@tonic-gate } 3047c478bd9Sstevel@tonic-gate } 3057c478bd9Sstevel@tonic-gate 3067c478bd9Sstevel@tonic-gate 3076c02b4a4Smuffin static void 3086c02b4a4Smuffin tconvert(struct command *cmd, tchar *fname, tchar **list) 3097c478bd9Sstevel@tonic-gate { 3106c02b4a4Smuffin char **rc; 3116c02b4a4Smuffin int len; 3127c478bd9Sstevel@tonic-gate 3137c478bd9Sstevel@tonic-gate cmd->cfname = tstostr(NULL, fname); 3147c478bd9Sstevel@tonic-gate 3157c478bd9Sstevel@tonic-gate len = blklen(list); 3167c478bd9Sstevel@tonic-gate rc = cmd->cargs = (char **) 317*65b0c20eSnakanon xcalloc((uint_t)(len + 1), sizeof (char **)); 3187c478bd9Sstevel@tonic-gate while (len--) 3197c478bd9Sstevel@tonic-gate *rc++ = tstostr(NULL, *list++); 3207c478bd9Sstevel@tonic-gate *rc = NULL; 3217c478bd9Sstevel@tonic-gate } 3227c478bd9Sstevel@tonic-gate 3237c478bd9Sstevel@tonic-gate 3247c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 3256c02b4a4Smuffin void 3266c02b4a4Smuffin execash(tchar **t, struct command *kp) 3277c478bd9Sstevel@tonic-gate { 3287c478bd9Sstevel@tonic-gate #ifdef TRACE 3297c478bd9Sstevel@tonic-gate tprintf("TRACE- execash()\n"); 3307c478bd9Sstevel@tonic-gate #endif 3317c478bd9Sstevel@tonic-gate 3327c478bd9Sstevel@tonic-gate rechist(); 3337c478bd9Sstevel@tonic-gate (void) signal(SIGINT, parintr); 3347c478bd9Sstevel@tonic-gate (void) signal(SIGQUIT, parintr); 3357c478bd9Sstevel@tonic-gate (void) signal(SIGTERM, parterm); /* if doexec loses, screw */ 3367c478bd9Sstevel@tonic-gate lshift(kp->t_dcom, 1); 3377c478bd9Sstevel@tonic-gate exiterr++; 3387c478bd9Sstevel@tonic-gate doexec(kp); 3397c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 3407c478bd9Sstevel@tonic-gate } 3417c478bd9Sstevel@tonic-gate 3426c02b4a4Smuffin void 3436c02b4a4Smuffin xechoit(tchar **t) 3447c478bd9Sstevel@tonic-gate { 3457c478bd9Sstevel@tonic-gate #ifdef TRACE 3467c478bd9Sstevel@tonic-gate tprintf("TRACE- xechoit()\n"); 3477c478bd9Sstevel@tonic-gate #endif 3487c478bd9Sstevel@tonic-gate 3497c478bd9Sstevel@tonic-gate if (adrof(S_echo /* "echo" */)) { 3507c478bd9Sstevel@tonic-gate flush(); 3517c478bd9Sstevel@tonic-gate haderr = 1; 3527c478bd9Sstevel@tonic-gate blkpr(t), Putchar('\n'); 3537c478bd9Sstevel@tonic-gate haderr = 0; 3547c478bd9Sstevel@tonic-gate } 3557c478bd9Sstevel@tonic-gate } 3567c478bd9Sstevel@tonic-gate 3577c478bd9Sstevel@tonic-gate /* 3587c478bd9Sstevel@tonic-gate * This routine called when user enters "rehash". 3597c478bd9Sstevel@tonic-gate * Both the path and cdpath caching arrays will 3607c478bd9Sstevel@tonic-gate * be rehashed, via calling dohash. If either 3617c478bd9Sstevel@tonic-gate * variable is not set with a value, then dohash 3627c478bd9Sstevel@tonic-gate * just exits. 3637c478bd9Sstevel@tonic-gate */ 3646c02b4a4Smuffin void 3656c02b4a4Smuffin dorehash(void) 3667c478bd9Sstevel@tonic-gate { 3677c478bd9Sstevel@tonic-gate dohash(xhash); 3687c478bd9Sstevel@tonic-gate dohash(xhash2); 3697c478bd9Sstevel@tonic-gate } 3707c478bd9Sstevel@tonic-gate 3717c478bd9Sstevel@tonic-gate /* 3727c478bd9Sstevel@tonic-gate * Fill up caching arrays for path and cdpath 3737c478bd9Sstevel@tonic-gate */ 3746c02b4a4Smuffin void 3756c02b4a4Smuffin dohash(char cachearray[]) 3767c478bd9Sstevel@tonic-gate { 3777c478bd9Sstevel@tonic-gate struct stat stb; 3787c478bd9Sstevel@tonic-gate DIR *dirp; 3796c02b4a4Smuffin struct dirent *dp; 3806c02b4a4Smuffin int cnt; 3817c478bd9Sstevel@tonic-gate int i = 0; 3827c478bd9Sstevel@tonic-gate struct varent *v; 3837c478bd9Sstevel@tonic-gate tchar **pv; 3847c478bd9Sstevel@tonic-gate int hashval; 3857c478bd9Sstevel@tonic-gate tchar curdir_[MAXNAMLEN+1]; 3867c478bd9Sstevel@tonic-gate 3877c478bd9Sstevel@tonic-gate #ifdef TRACE 3887c478bd9Sstevel@tonic-gate tprintf("TRACE- dohash()\n"); 3897c478bd9Sstevel@tonic-gate #endif 3907c478bd9Sstevel@tonic-gate /* Caching $path */ 3917c478bd9Sstevel@tonic-gate if (cachearray == xhash) { 3927c478bd9Sstevel@tonic-gate havhash = 1; 3937c478bd9Sstevel@tonic-gate v = adrof(S_path /* "path" */); 3947c478bd9Sstevel@tonic-gate } else { /* Caching $cdpath */ 3957c478bd9Sstevel@tonic-gate havhash2 = 1; 3967c478bd9Sstevel@tonic-gate v = adrof(S_cdpath /* "cdpath" */); 3977c478bd9Sstevel@tonic-gate } 3987c478bd9Sstevel@tonic-gate 3997c478bd9Sstevel@tonic-gate for (cnt = 0; cnt < (HSHSIZ / 8); cnt++) 4007c478bd9Sstevel@tonic-gate cachearray[cnt] = 0; 4017c478bd9Sstevel@tonic-gate if (v == 0) 4027c478bd9Sstevel@tonic-gate { 4037c478bd9Sstevel@tonic-gate return; 4047c478bd9Sstevel@tonic-gate } 4057c478bd9Sstevel@tonic-gate for (pv = v->vec; *pv; pv++, i++) { 4067c478bd9Sstevel@tonic-gate if (pv[0][0] != '/') 4077c478bd9Sstevel@tonic-gate continue; 4087c478bd9Sstevel@tonic-gate dirp = opendir_(*pv); 4097c478bd9Sstevel@tonic-gate if (dirp == NULL) 4107c478bd9Sstevel@tonic-gate continue; 4117c478bd9Sstevel@tonic-gate if (fstat(dirp->dd_fd, &stb) < 0 || !isdir(stb)) { 4127c478bd9Sstevel@tonic-gate unsetfd(dirp->dd_fd); 4137c478bd9Sstevel@tonic-gate closedir_(dirp); 4147c478bd9Sstevel@tonic-gate continue; 4157c478bd9Sstevel@tonic-gate } 4167c478bd9Sstevel@tonic-gate while ((dp = readdir(dirp)) != NULL) { 4177c478bd9Sstevel@tonic-gate if (dp->d_ino == 0) 4187c478bd9Sstevel@tonic-gate continue; 4197c478bd9Sstevel@tonic-gate if (dp->d_name[0] == '.' && 4207c478bd9Sstevel@tonic-gate (dp->d_name[1] == '\0' || 4217c478bd9Sstevel@tonic-gate dp->d_name[1] == '.' && dp->d_name[2] == '\0')) 4227c478bd9Sstevel@tonic-gate continue; 4237c478bd9Sstevel@tonic-gate hashval = hash(hashname(strtots(curdir_, dp->d_name)), i); 4247c478bd9Sstevel@tonic-gate bis(cachearray, hashval); 4257c478bd9Sstevel@tonic-gate } 4267c478bd9Sstevel@tonic-gate unsetfd(dirp->dd_fd); 4277c478bd9Sstevel@tonic-gate closedir_(dirp); 4287c478bd9Sstevel@tonic-gate } 4297c478bd9Sstevel@tonic-gate } 4307c478bd9Sstevel@tonic-gate 4316c02b4a4Smuffin void 4326c02b4a4Smuffin dounhash(void) 4337c478bd9Sstevel@tonic-gate { 4347c478bd9Sstevel@tonic-gate 4357c478bd9Sstevel@tonic-gate #ifdef TRACE 4367c478bd9Sstevel@tonic-gate tprintf("TRACE- dounhash()\n"); 4377c478bd9Sstevel@tonic-gate #endif 4387c478bd9Sstevel@tonic-gate havhash = 0; 4397c478bd9Sstevel@tonic-gate havhash2 = 0; 4407c478bd9Sstevel@tonic-gate } 4417c478bd9Sstevel@tonic-gate 4427c478bd9Sstevel@tonic-gate #ifdef VFORK 4436c02b4a4Smuffin void 4446c02b4a4Smuffin hashstat(void) 4457c478bd9Sstevel@tonic-gate { 4467c478bd9Sstevel@tonic-gate #ifdef TRACE 4477c478bd9Sstevel@tonic-gate tprintf("TRACE- hashstat_()\n"); 4487c478bd9Sstevel@tonic-gate #endif 4497c478bd9Sstevel@tonic-gate 4507c478bd9Sstevel@tonic-gate if (hits+misses) 4517c478bd9Sstevel@tonic-gate printf("%d hits, %d misses, %d%%\n", 4527c478bd9Sstevel@tonic-gate hits, misses, 100 * hits / (hits + misses)); 4537c478bd9Sstevel@tonic-gate } 4547c478bd9Sstevel@tonic-gate #endif 4557c478bd9Sstevel@tonic-gate 4567c478bd9Sstevel@tonic-gate /* 4577c478bd9Sstevel@tonic-gate * Hash a command name. 4587c478bd9Sstevel@tonic-gate */ 4596c02b4a4Smuffin int 4606c02b4a4Smuffin hashname(tchar *cp) 4617c478bd9Sstevel@tonic-gate { 4626c02b4a4Smuffin long h = 0; 4637c478bd9Sstevel@tonic-gate 4647c478bd9Sstevel@tonic-gate #ifdef TRACE 4657c478bd9Sstevel@tonic-gate tprintf("TRACE- hashname()\n"); 4667c478bd9Sstevel@tonic-gate #endif 4677c478bd9Sstevel@tonic-gate while (*cp) 4687c478bd9Sstevel@tonic-gate h = hash(h, *cp++); 4697c478bd9Sstevel@tonic-gate return ((int)h); 4707c478bd9Sstevel@tonic-gate } 471