From c5fd306cd921b236730e63d695e48b1f297c06d1 Mon Sep 17 00:00:00 2001 From: Bill Joy Date: Thu, 9 Oct 1980 20:40:50 -0800 Subject: [PATCH 1/1] date and time created 80/10/09 12:40:50 by bill SCCS-vsn: bin/csh/exec.c 4.1 --- usr/src/bin/csh/exec.c | 316 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 316 insertions(+) create mode 100644 usr/src/bin/csh/exec.c diff --git a/usr/src/bin/csh/exec.c b/usr/src/bin/csh/exec.c new file mode 100644 index 0000000000..ba3f3aa177 --- /dev/null +++ b/usr/src/bin/csh/exec.c @@ -0,0 +1,316 @@ +static char *sccsid = "@(#)exec.c 4.1 %G%"; + +#include "sh.h" + +/* + * C shell + */ + +/* + * System level search and execute of a command. + * We look in each directory for the specified command name. + * If the name contains a '/' then we execute only the full path name. + * If there is no search path then we execute only full path names. + */ + +/* + * As we search for the command we note the first non-trivial error + * message for presentation to the user. This allows us often + * to show that a file has the wrong mode/no access when the file + * is not in the last component of the search path, so we must + * go on after first detecting the error. + */ +char *exerr; /* Execution error message */ +char *expath; /* Path for exerr */ + +/* + * Xhash is an array of HSHSIZ chars, which are used to hash execs. + * If it is allocated, then to tell whether ``name'' is (possibly) + * present in the i'th component of the variable path, you look at + * the i'th bit of xhash[hash("name")]. This is setup automatically + * after .login is executed, and recomputed whenever ``path'' is + * changed. + */ +int havhash; +#define HSHSIZ 511 +char xhash[HSHSIZ]; +#ifdef VFORK +int hits, misses; +#endif + +/* Dummy search path for just absolute search when no path */ +char *justabs[] = { "", 0 }; + +doexec(t) + register struct command *t; +{ + char *sav; + register char *dp, **pv, **av; + register struct varent *v; + bool slash = any('/', t->t_dcom[0]); + int hashval, i; + char *blk[2]; + + /* + * Glob the command name. If this does anything, then we + * will execute the command only relative to ".". One special + * case: if there is no PATH, then we execute only commands + * which start with '/'. + */ + dp = globone(t->t_dcom[0]); + sav = t->t_dcom[0]; + exerr = 0; expath = t->t_dcom[0] = dp; + xfree(sav); + v = adrof("path"); + if (v == 0 && expath[0] != '/') + pexerr(); + slash |= gflag; + + /* + * Glob the argument list, if necessary. + * Otherwise trim off the quote bits. + */ + gflag = 0; av = &t->t_dcom[1]; + rscan(av, tglob); + if (gflag) { + av = glob(av); + if (av == 0) + error("No match"); + } + blk[0] = t->t_dcom[0]; + blk[1] = 0; + av = blkspl(blk, av); +#ifdef VFORK + Vav = av; +#endif + scan(av, trim); + + xechoit(av); /* Echo command if -x */ + closech(); /* Close random fd's */ + + /* + * We must do this after any possible forking (like `foo` + * in glob) so that this shell can still do subprocesses. + */ + sigsys(SIGCHLD, SIG_IGN); /* sigsys for vforks sake */ + + /* + * If no path, no words in path, or a / in the filename + * then restrict the command search. + */ + if (v == 0 || v->vec[0] == 0 || slash) + pv = justabs; + else + pv = v->vec; + sav = strspl("/", *av); /* / command name for postpending */ +#ifdef VFORK + Vsav = sav; +#endif + if (havhash) + hashval = xhash[hash(*av)]; + i = 0; +#ifdef VFORK + hits++; +#endif + do { + if (!slash && pv[0][0] == '/' && havhash && (hashval & (1 << (i % 8))) == 0) + goto cont; + if (pv[0][0] == 0 || eq(pv[0], ".")) /* don't make ./xxx */ + texec(*av, av); + else { + dp = strspl(*pv, sav); +#ifdef VFORK + Vdp = dp; +#endif + texec(dp, av); +#ifdef VFORK + Vdp = 0; +#endif + xfree(dp); + } +#ifdef VFORK + misses++; +#endif +cont: + pv++; + i++; + } while (*pv); +#ifdef VFORK + hits--; +#endif +#ifdef VFORK + Vsav = 0; + Vav = 0; +#endif + xfree(sav); + xfree(av); + pexerr(); +} + +pexerr() +{ + + /* Couldn't find the damn thing */ + setname(expath); + /* xfree(expath); */ + if (exerr) + bferr(exerr); + bferr("Command not found"); +} + +/* Last resort shell */ +char *lastsh[] = { SHELLPATH, 0 }; + +/* + * Execute command f, arg list t. + * Record error message if not found. + * Also do shell scripts here. + */ +texec(f, t) + char *f; + register char **t; +{ + register struct varent *v; + register char **vp; + extern char *sys_errlist[]; + + execv(f, t); + switch (errno) { + + case ENOEXEC: + /* + * If there is an alias for shell, then + * put the words of the alias in front of the + * argument list replacing the command name. + * Note no interpretation of the words at this point. + */ + v = adrof1("shell", &aliases); + if (v == 0) { +#ifdef OTHERSH + register int ff = open(f, 0); + char ch; +#endif + + vp = lastsh; + vp[0] = adrof("shell") ? value("shell") : SHELLPATH; +#ifdef OTHERSH + if (ff != -1 && read(ff, &ch, 1) == 1 && ch != '#') + vp[0] = OTHERSH; + close(ff); +#endif + } else + vp = v->vec; + t[0] = f; + t = blkspl(vp, t); /* Splice up the new arglst */ + f = *t; + execv(f, t); + xfree((char *)t); + /* The sky is falling, the sky is falling! */ + + case ENOMEM: + Perror(f); + + case ENOENT: + break; + + default: + if (exerr == 0) { + exerr = sys_errlist[errno]; + expath = savestr(f); + } + } +} + +execash(t, kp) + register struct command *kp; +{ + + didcch++; + signal(SIGINT, parintr); + signal(SIGQUIT, parintr); + signal(SIGTERM, parterm); /* if doexec loses, screw */ + lshift(kp->t_dcom, 1); + exiterr++; + doexec(kp); + /*NOTREACHED*/ +} + +xechoit(t) + char **t; +{ + + if (adrof("echo")) { + flush(); + haderr = 1; + blkpr(t), printf("\n"); + haderr = 0; + } +} + +dohash() +{ + struct stat stb; + struct direct dirbuf[BUFSIZ / sizeof (struct direct)]; + char d_name[DIRSIZ + 1]; + register int dirf, cnt; + int i = 0; + struct varent *v = adrof("path"); + char **pv; + + havhash = 1; + for (cnt = 0; cnt < HSHSIZ; cnt++) + xhash[cnt] = 0; + if (v == 0) + return; + for (pv = v->vec; *pv; pv++, i = (i + 1) % 8) { + if (pv[0][0] != '/') + continue; + dirf = open(*pv, 0); + if (dirf < 0) + continue; + if (fstat(dirf, &stb) < 0 || !isdir(stb)) { + close(dirf); + continue; + } + while ((cnt = read(dirf, (char *) dirbuf, sizeof dirbuf)) >= sizeof dirbuf[0]) { + register struct direct *ep = dirbuf; + + for (cnt /= sizeof(struct direct); cnt > 0; cnt--, ep++) { + if (ep->d_ino == 0) + continue; + copdent(d_name, ep->d_name); + xhash[hash(d_name)] |= (1 << i); + } + } + close(dirf); + } +} + +dounhash() +{ + + havhash = 0; +} + +#ifdef VFORK +hashstat() +{ + + if (hits+misses) + printf("%d hits, %d misses, %2d%%\n", hits, misses, 100 * hits / (hits + misses)); +} +#endif + +hash(cp) + register char *cp; +{ + register long hash = 0; + int retval; + + while (*cp) + hash += hash + *cp++; + if (hash < 0) + hash = -hash; + retval = hash % HSHSIZ; + return (retval); +} -- 2.20.1