xref: /titanic_51/usr/src/cmd/csh/sh.exec.c (revision 134a1f4e3289b54e0f980e9cf05352e419a60bee)
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