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 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 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 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 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 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 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 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 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 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 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 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