Return to BSD News archive
Newsgroups: comp.bugs.2bsd
Path: euryale.cc.adfa.oz.au!newshost.carno.net.au!harbinger.cc.monash.edu.au!news.mira.net.au!news.mel.connect.com.au!munnari.OZ.AU!news.ecn.uoknor.edu!news.wildstar.net!cancer.vividnet.com!hunter.premier.net!news1.erols.com!howland.erols.net!newsfeed.internetmci.com!in2.uu.net!news.new-york.net!wlbr!moe.2bsd.com!sms
From: sms@moe.2bsd.com (Steven M. Schultz)
Subject: csh lacks 'which' builtin (#330)
Organization: 2BSD, Simi Valley CA USA
Message-ID: <Dy49xF.FAH@moe.2bsd.com>
Date: Sun, 22 Sep 1996 04:32:03 GMT
Lines: 728
Subject: csh lacks 'which' builtin (#330)
Index: bin/csh/sh.exec.c,sh.exec2.c,sh.h 2.11BSD
Description:
csh does not have the 'which' command as a builtin. This causes
the very slow script /usr/ucb/which to be used.
tcsh has 'which' as a builtin as does 4.4BSD's csh.
Repeat-By:
time which which
/usr/ucb/which
1.4u 1.5s 0:03 76% 44+5io 3ov 0sw
Fix:
The 'which' code was borrowed from 4.4-Lite2's csh source.
To ease porting the /sys/h/stat.h file was augmented with the
macros for testing the file type (S_IFDIR, etc).
Adding 'which' caused the sh.exec.o module to become too large for
the overlay it resided in. To get around this a new source module
(sh.exec2.c) was created. This new module was then placed into
the second overlay.
sh.exec2.c referenced the hash macros and definitions so these
were moved from sh.exec.c into an include file (sh.exec.h).
After rebuilding and installing csh the 'which' command is almost
instantaneous:
Script started on Sat Sep 21 21:05:21 1996
# time which which
which: shell built-in command.
0.0u 0.0s 0:00 83% 0+0io 2ov 0sw
# exit
#
script done on Sat Sep 21 21:05:31 1996
The update consists of two files: a shar archive of new files to
be added to the system and a patch file which updates existing files.
To install this update cut where indicated, saving to a file (/tmp/330).
Then:
cd /tmp
sh 330
sh 330.shar
patch -p0 < 330.patch
cd /usr/src/bin/csh
make csh tags
make install
make clean
It will be necessary to log out and back in for the new shell to
take effect.
This and previous updates are available via anonymous FTP to either
FTP.IIPO.GTEGSC.COM or MOE.2BSD.COM in the directory /pub/2.11BSD.
---------------------------cut here---------------------------
#! /bin/sh
# This is a shell archive, meaning:
# 1. Remove everything above the #! /bin/sh line.
# 2. Save the resulting text in a file.
# 3. Execute the file with /bin/sh (not csh) to create:
# 330.patch
# 330.shar
# This archive created: Sat Sep 21 21:15:39 1996
export PATH; PATH=/bin:/usr/bin:$PATH
if test -f '330.patch'
then
echo shar: "will not over-write existing file '330.patch'"
else
sed 's/^X//' << \SHAR_EOF > '330.patch'
X*** /usr/src/bin/csh/Makefile.old Sat Apr 9 00:19:41 1994
X--- /usr/src/bin/csh/Makefile Sat Sep 21 20:36:13 1996
X***************
X*** 3,9 ****
X # All rights reserved. The Berkeley Software License Agreement
X # specifies the terms and conditions for redistribution.
X #
X! # @(#)Makefile 5.3.1 (2.11BSD GTE) 4/9/94
X #
X # C Shell with process control; VM/UNIX VAX Makefile
X # Bill Joy UC Berkeley; Jim Kulp IIASA, Austria
X--- 3,9 ----
X # All rights reserved. The Berkeley Software License Agreement
X # specifies the terms and conditions for redistribution.
X #
X! # @(#)Makefile 5.3.2 (2.11BSD GTE) 1996/9/20
X #
X # C Shell with process control; VM/UNIX VAX Makefile
X # Bill Joy UC Berkeley; Jim Kulp IIASA, Austria
X***************
X*** 29,36 ****
X sh.init.o sh.lex.o sh.misc.o sh.parse.o sh.print.o sh.proc.o sh.sem.o \
X sh.set.o
X OV1= sh.o sh.exec.o sh.time.o
X
X! OBJS= ${BASE} ${OV1}
X
X LIBOBJS= ndbm.o getpwent.o
X
X--- 29,37 ----
X sh.init.o sh.lex.o sh.misc.o sh.parse.o sh.print.o sh.proc.o sh.sem.o \
X sh.set.o
X OV1= sh.o sh.exec.o sh.time.o
X+ OV2= sh.exec2.o
X
X! OBJS= ${BASE} ${OV1} ${OV2}
X
X LIBOBJS= ndbm.o getpwent.o
X
X***************
X*** 47,53 ****
X rm -f csh
X /bin/ld ${SEPFLAG} /lib/crt0.o ${BASE} \
X -Z ${OV1} \
X! -Z ${LIBOBJS} \
X -Y strings.o -o csh ${LIBES};
X
X .DEFAULT:
X--- 48,54 ----
X rm -f csh
X /bin/ld ${SEPFLAG} /lib/crt0.o ${BASE} \
X -Z ${OV1} \
X! -Z ${OV2} ${LIBOBJS} \
X -Y strings.o -o csh ${LIBES};
X
X .DEFAULT:
X***************
X*** 91,97 ****
X ${VGRIND} -t -x -h Index index >grind/index.t
X
X install: csh
X! install -s csh ${DESTDIR}/bin/csh
X
X clean:
X ${RM} -f a.out strings x.c xs.c csh errs
X--- 92,98 ----
X ${VGRIND} -t -x -h Index index >grind/index.t
X
X install: csh
X! install -m 755 -o bin -g bin -s csh ${DESTDIR}/bin/csh
X
X clean:
X ${RM} -f a.out strings x.c xs.c csh errs
X***************
X*** 98,104 ****
X ${RM} -f *.o
X ${RM} -rf vgrind
X
X! tags:
X ${CTAGS} -t *.h sh*.c
X
X sh.o: sh.h sh.local.h sh.char.h
X--- 99,105 ----
X ${RM} -f *.o
X ${RM} -rf vgrind
X
X! tags: *.h sh*.c
X ${CTAGS} -t *.h sh*.c
X
X sh.o: sh.h sh.local.h sh.char.h
X***************
X*** 107,112 ****
X--- 108,114 ----
X sh.dol.o: sh.h sh.local.h sh.char.h
X sh.err.o: sh.h sh.local.h sh.char.h
X sh.exec.o: sh.h sh.local.h sh.char.h
X+ sh.exec2.o: sh.h sh.local.h sh.char.h
X sh.exp.o: sh.h sh.local.h sh.char.h
X sh.file.o: sh.h sh.local.h sh.char.h
X sh.func.o: sh.h sh.local.h sh.char.h
X*** /usr/src/bin/csh/sh.exec.c.old Sat Mar 30 23:09:13 1996
X--- /usr/src/bin/csh/sh.exec.c Sat Sep 21 20:17:59 1996
X***************
X*** 5,11 ****
X */
X
X #if !defined(lint) && defined(DOSCCS)
X! static char *sccsid = "@(#)sh.exec.c 5.2.1 (2.11BSD) 1996/3/20";
X #endif
X
X #include "sh.h"
X--- 5,11 ----
X */
X
X #if !defined(lint) && defined(DOSCCS)
X! static char *sccsid = "@(#)sh.exec.c 5.2.2 (2.11BSD) 1996/9/20";
X #endif
X
X #include "sh.h"
X***************
X*** 33,61 ****
X char *exerr; /* Execution error message */
X char *expath; /* Path for exerr */
X
X! /*
X! * Xhash is an array of HSHSIZ bits (HSHSIZ / 8 chars), which are used
X! * to hash execs. If it is allocated (havhash true), then to tell
X! * whether ``name'' is (possibly) present in the i'th component
X! * of the variable path, you look at the bit in xhash indexed by
X! * hash(hashname("name"), i). This is setup automatically
X! * after .login is executed, and recomputed whenever ``path'' is
X! * changed.
X! * The two part hash function is designed to let texec() call the
X! * more expensive hashname() only once and the simple hash() several
X! * times (once for each path component checked).
X! * Byte size is assumed to be 8.
X! */
X! #define HSHSIZ 8192 /* 1k bytes */
X! #define HSHMASK (HSHSIZ - 1)
X! #define HSHMUL 243
X! char xhash[HSHSIZ / 8];
X! #define hash(a, b) ((a) * HSHMUL + (b) & HSHMASK)
X! #define bit(h, b) ((h)[(b) >> 3] & 1 << ((b) & 7)) /* bit test */
X! #define bis(h, b) ((h)[(b) >> 3] |= 1 << ((b) & 7)) /* bit set */
X! #ifdef VFORK
X! int hits, misses;
X! #endif
X
X /* Dummy search path for just absolute search when no path */
X char *justabs[] = { "", 0 };
X--- 33,39 ----
X char *exerr; /* Execution error message */
X char *expath; /* Path for exerr */
X
X! #include "sh.exec.h"
X
X /* Dummy search path for just absolute search when no path */
X char *justabs[] = { "", 0 };
X***************
X*** 297,303 ****
X dirp = opendir(*pv);
X if (dirp == NULL)
X continue;
X! if (fstat(dirp->dd_fd, &stb) < 0 || !isdir(stb)) {
X closedir(dirp);
X continue;
X }
X--- 275,281 ----
X dirp = opendir(*pv);
X if (dirp == NULL)
X continue;
X! if (fstat(dirp->dd_fd, &stb) < 0 || !S_ISDIR(stb.st_mode)) {
X closedir(dirp);
X continue;
X }
X*** /usr/src/bin/csh/sh.glob.c.old Sat Aug 31 00:08:21 1991
X--- /usr/src/bin/csh/sh.glob.c Fri Sep 20 01:34:49 1996
X***************
X*** 5,11 ****
X */
X
X #if !defined(lint) && defined(DOSCCS)
X! static char *sccsid = "@(#)sh.glob.c 5.4 (Berkeley) 5/13/86";
X #endif
X
X #include "sh.h"
X--- 5,11 ----
X */
X
X #if !defined(lint) && defined(DOSCCS)
X! static char *sccsid = "@(#)sh.glob.c 5.4.1 (2.11BSD) 1996/9/20";
X #endif
X
X #include "sh.h"
X***************
X*** 189,195 ****
X }
X if (fstat(dirp->dd_fd, &stb) < 0)
X goto patherr1;
X! if (!isdir(stb)) {
X errno = ENOTDIR;
X goto patherr1;
X }
X--- 189,195 ----
X }
X if (fstat(dirp->dd_fd, &stb) < 0)
X goto patherr1;
X! if (!S_ISDIR(stb.st_mode)) {
X errno = ENOTDIR;
X goto patherr1;
X }
X***************
X*** 376,382 ****
X while (*s)
X addpath(*s++);
X addpath('/');
X! if (stat(gpath, &stb) == 0 && isdir(stb))
X if (*p == 0) {
X Gcat(gpath, "");
X globcnt++;
X--- 376,382 ----
X while (*s)
X addpath(*s++);
X addpath('/');
X! if (stat(gpath, &stb) == 0 && S_ISDIR(stb.st_mode))
X if (*p == 0) {
X Gcat(gpath, "");
X globcnt++;
X*** /usr/src/bin/csh/sh.h.old Mon Jan 10 21:38:15 1994
X--- /usr/src/bin/csh/sh.h Fri Sep 20 01:27:43 1996
X***************
X*** 3,9 ****
X * All rights reserved. The Berkeley Software License Agreement
X * specifies the terms and conditions for redistribution.
X *
X! * @(#)sh.h 5.3.1 (2.11BSD GTE) 1/1/94
X */
X
X #include <sys/time.h>
X--- 3,9 ----
X * All rights reserved. The Berkeley Software License Agreement
X * specifies the terms and conditions for redistribution.
X *
X! * @(#)sh.h 5.3.2 (2.11BSD GTE) 1996/9/20
X */
X
X #include <sys/time.h>
X***************
X*** 25,32 ****
X * Jim Kulp, IIASA, Laxenburg Austria
X * April, 1980
X */
X-
X- #define isdir(d) ((d.st_mode & S_IFMT) == S_IFDIR)
X
X typedef char bool;
X
X--- 25,30 ----
X*** /usr/src/bin/csh/sh.init.c.old Sat Aug 31 00:09:14 1991
X--- /usr/src/bin/csh/sh.init.c Fri Sep 20 00:19:18 1996
X***************
X*** 5,11 ****
X */
X
X #if !defined(lint) && defined(DOSCCS)
X! static char *sccsid = "@(#)sh.init.c 5.2 (Berkeley) 6/6/85";
X #endif
X
X #include "sh.local.h"
X--- 5,11 ----
X */
X
X #if !defined(lint) && defined(DOSCCS)
X! static char *sccsid = "@(#)sh.init.c 5.2.1 (2.11BSD) 1996/9/20";
X #endif
X
X #include "sh.local.h"
X***************
X*** 66,71 ****
X--- 66,72 ----
X extern int doumask();
X extern int dowait();
X extern int dowhile();
X+ extern int dowhich();
X extern int dozip();
X extern int execash();
X extern int goodbye();
X***************
X*** 159,164 ****
X--- 160,166 ----
X "unset", unset, 1, INF,
X "unsetenv", dounsetenv, 1, INF,
X "wait", dowait, 0, 0,
X+ "which", dowhich, 1, INF,
X "while", dowhile, 1, INF,
X };
X int nbfunc = sizeof bfunc / sizeof *bfunc;
X*** /usr/src/sys/h/stat.h.old Mon Mar 13 21:06:42 1995
X--- /usr/src/sys/h/stat.h Fri Sep 20 00:50:01 1996
X***************
X*** 3,9 ****
X * All rights reserved. The Berkeley software License Agreement
X * specifies the terms and conditions for redistribution.
X *
X! * @(#)stat.h 7.1.4 (2.11BSD) 1995/03/13
X */
X
X #ifndef _STAT_H_
X--- 3,9 ----
X * All rights reserved. The Berkeley software License Agreement
X * specifies the terms and conditions for redistribution.
X *
X! * @(#)stat.h 7.1.5 (2.11BSD) 1996/09/20
X */
X
X #ifndef _STAT_H_
X***************
X*** 65,70 ****
X--- 65,75 ----
X #define S_IROTH 0000004 /* R for other */
X #define S_IWOTH 0000002 /* W for other */
X #define S_IXOTH 0000001 /* X for other */
X+
X+ #define S_ISDIR(m) ((m & 0170000) == 0040000) /* directory */
X+ #define S_ISCHR(m) ((m & 0170000) == 0020000) /* char special */
X+ #define S_ISBLK(m) ((m & 0170000) == 0060000) /* block special */
X+ #define S_ISREG(m) ((m & 0170000) == 0100000) /* regular file */
X
X /*
X * Definitions of flags stored in file flags word. Different from 4.4 because
X*** /VERSION.old Sun Sep 15 22:15:36 1996
X--- /VERSION Mon Sep 16 21:00:09 1996
X***************
X*** 1,4 ****
X! Current Patch Level: 329
X
X 2.11 BSD
X ============
X--- 1,4 ----
X! Current Patch Level: 330
X
X 2.11 BSD
X ============
SHAR_EOF
fi
if test -f '330.shar'
then
echo shar: "will not over-write existing file '330.shar'"
else
sed 's/^X//' << \SHAR_EOF > '330.shar'
X#! /bin/sh
X# This is a shell archive, meaning:
X# 1. Remove everything above the #! /bin/sh line.
X# 2. Save the resulting text in a file.
X# 3. Execute the file with /bin/sh (not csh) to create:
X# /usr/src/bin/csh/sh.exec2.c
X# /usr/src/bin/csh/sh.exec.h
X# This archive created: Sat Sep 21 20:46:01 1996
Xexport PATH; PATH=/bin:/usr/bin:$PATH
Xif test -f '/usr/src/bin/csh/sh.exec2.c'
Xthen
X echo shar: "will not over-write existing file '/usr/src/bin/csh/sh.exec2.c'"
Xelse
Xsed 's/^Z//' << \SHAR_EOF > '/usr/src/bin/csh/sh.exec2.c'
XZ/*
XZ * From the 4.4-Lite2 CD's csh sources and modified appropriately.
XZ*/
XZ
XZ#if !defined(lint) && defined(DOSCCS)
XZstatic char *sccsid = "@(#)sh.exec2.c 1.0 (2.11BSD) 1996/9/20";
XZ#endif
XZ
XZ#include "sh.h"
XZ#include <string.h>
XZ#include <sys/file.h>
XZ#include <sys/stat.h>
XZ#include <sys/dir.h>
XZ#include "sh.exec.h"
XZ
XZextern char *justabs[]; /* in sh.exec.c */
XZ
XZstatic int
XZiscommand(name)
XZ char *name;
XZ{
XZ register char **pv;
XZ register char *sav;
XZ register struct varent *v;
XZ bool slash = any(name, '/');
XZ int hashval = 0, hashval1, i;
XZ
XZ v = adrof("path");
XZ if (v == 0 || v->vec[0] == 0 || slash)
XZ pv = justabs;
XZ else
XZ pv = v->vec;
XZ sav = strspl("/", name); /* / command name for postpending */
XZ if (havhash)
XZ hashval = hashname(name);
XZ i = 0;
XZ do {
XZ if (!slash && pv[0][0] == '/' && havhash) {
XZ hashval1 = hash(hashval, i);
XZ if (!bit(xhash, hashval1))
XZ goto cont;
XZ }
XZ if (pv[0][0] == 0 || eq(pv[0], ".")) { /* don't make ./xxx */
XZ if (executable(NULL, name, 0)) {
XZ xfree(sav);
XZ return i + 1;
XZ }
XZ }
XZ else {
XZ if (executable(*pv, sav, 0)) {
XZ xfree(sav);
XZ return i + 1;
XZ }
XZ }
XZcont:
XZ pv++;
XZ i++;
XZ } while (*pv);
XZ xfree(sav);
XZ return 0;
XZ}
XZ
XZ/* Also by:
XZ * Andreas Luik <luik@isaak.isa.de>
XZ * I S A GmbH - Informationssysteme fuer computerintegrierte Automatisierung
XZ * Azenberstr. 35
XZ * D-7000 Stuttgart 1
XZ * West-Germany
XZ * is the executable() routine below and changes to iscommand().
XZ * Thanks again!!
XZ */
XZ
XZ/*
XZ * executable() examines the pathname obtained by concatenating dir and name
XZ * (dir may be NULL), and returns 1 either if it is executable by us, or
XZ * if dir_ok is set and the pathname refers to a directory.
XZ * This is a bit kludgy, but in the name of optimization...
XZ */
XZstatic int
XZexecutable(dir, name, dir_ok)
XZ char *dir, *name;
XZ bool dir_ok;
XZ{
XZ struct stat stbuf;
XZ char path[MAXPATHLEN + 1];
XZ register char *dp, *sp;
XZ char *strname;
XZ
XZ if (dir && *dir) {
XZ for (dp = path, sp = dir; *sp; *dp++ = *sp++)
XZ if (dp == &path[MAXPATHLEN + 1]) {
XZ *--dp = '\0';
XZ break;
XZ }
XZ for (sp = name; *sp; *dp++ = *sp++)
XZ if (dp == &path[MAXPATHLEN + 1]) {
XZ *--dp = '\0';
XZ break;
XZ }
XZ *dp = '\0';
XZ strname = path;
XZ }
XZ else
XZ strname = name;
XZ return (stat(strname, &stbuf) != -1 &&
XZ ((S_ISREG(stbuf.st_mode) &&
XZ /* save time by not calling access() in the hopeless case */
XZ (stbuf.st_mode & (S_IXOTH | S_IXGRP | S_IXUSR)) &&
XZ access(strname, X_OK) == 0) ||
XZ (dir_ok && S_ISDIR(stbuf.st_mode))));
XZ}
XZ/* The dowhich() is by:
XZ * Andreas Luik <luik@isaak.isa.de>
XZ * I S A GmbH - Informationssysteme fuer computerintegrierte Automatisierung
XZ * Azenberstr. 35
XZ * D-7000 Stuttgart 1
XZ * West-Germany
XZ * Thanks!!
XZ */
XZ/*ARGSUSED*/
XZvoid
XZdowhich(v, c)
XZ register char **v;
XZ struct command *c;
XZ{
XZ struct wordent lex[3];
XZ struct varent *vp;
XZ
XZ lex[0].next = &lex[1];
XZ lex[1].next = &lex[2];
XZ lex[2].next = &lex[0];
XZ
XZ lex[0].prev = &lex[2];
XZ lex[1].prev = &lex[0];
XZ lex[2].prev = &lex[1];
XZ
XZ lex[0].word = "";
XZ lex[2].word = "\n";
XZ
XZ while (*++v) {
XZ if ((vp = adrof1(*v, &aliases)) != NULL) {
XZ (void) printf("%s: \t aliased to ", *v);
XZ blkpr(vp->vec);
XZ (void) putchar('\n');
XZ }
XZ else {
XZ lex[1].word = *v;
XZ tellmewhat(lex);
XZ }
XZ }
XZ}
XZ
XZstatic void
XZtellmewhat(lex)
XZ struct wordent *lex;
XZ{
XZ int i;
XZ struct biltins *bptr;
XZ register struct wordent *sp = lex->next;
XZ bool aliased = 0;
XZ register char *s2;
XZ char *s0, *s1, *cmd;
XZ char qc;
XZ
XZ if (adrof1(sp->word, &aliases)) {
XZ alias(lex);
XZ sp = lex->next;
XZ aliased = 1;
XZ }
XZ
XZ s0 = sp->word; /* to get the memory freeing right... */
XZ
XZ /* handle quoted alias hack */
XZ if ((*(sp->word) & (QUOTE | TRIM)) == QUOTE)
XZ (sp->word)++;
XZ
XZ /* do quoting, if it hasn't been done */
XZ s1 = s2 = sp->word;
XZ while (*s2)
XZ switch (*s2) {
XZ case '\'':
XZ case '"':
XZ qc = *s2++;
XZ while (*s2 && *s2 != qc)
XZ *s1++ = *s2++ | QUOTE;
XZ if (*s2)
XZ s2++;
XZ break;
XZ case '\\':
XZ if (*++s2)
XZ *s1++ = *s2++ | QUOTE;
XZ break;
XZ default:
XZ *s1++ = *s2++;
XZ }
XZ *s1 = '\0';
XZ
XZ for (bptr = bfunc; bptr < &bfunc[nbfunc]; bptr++) {
XZ if (eq(sp->word, bptr->bname)) {
XZ if (aliased)
XZ prlex(lex);
XZ (void) printf("%s: shell built-in command.\n", sp->word);
XZ sp->word = s0; /* we save and then restore this */
XZ return;
XZ }
XZ }
XZ
XZ sp->word = cmd = globone(sp->word);
XZ
XZ if ((i = iscommand(strip(sp->word))) != 0) {
XZ register char **pv;
XZ register struct varent *v;
XZ bool slash = any(sp->word, '/');
XZ
XZ v = adrof("path");
XZ if (v == 0 || v->vec[0] == 0 || slash)
XZ pv = justabs;
XZ else
XZ pv = v->vec;
XZ
XZ while (--i)
XZ pv++;
XZ if (pv[0][0] == 0 || eq(pv[0], ".")) {
XZ if (!slash) {
XZ sp->word = strspl("./", sp->word);
XZ prlex(lex);
XZ xfree(sp->word);
XZ }
XZ else
XZ prlex(lex);
XZ sp->word = s0; /* we save and then restore this */
XZ xfree(cmd);
XZ return;
XZ }
XZ s1 = strspl(*pv, "/");
XZ sp->word = strspl(s1, sp->word);
XZ xfree(s1);
XZ prlex(lex);
XZ xfree(sp->word);
XZ }
XZ else {
XZ if (aliased)
XZ prlex(lex);
XZ (void) printf("%s: Command not found.\n", sp->word);
XZ }
XZ sp->word = s0; /* we save and then restore this */
XZ xfree(cmd);
XZ}
XSHAR_EOF
Xchmod 644 '/usr/src/bin/csh/sh.exec2.c'
Xfi
Xif test -f '/usr/src/bin/csh/sh.exec.h'
Xthen
X echo shar: "will not over-write existing file '/usr/src/bin/csh/sh.exec.h'"
Xelse
Xsed 's/^Z//' << \SHAR_EOF > '/usr/src/bin/csh/sh.exec.h'
XZ/*
XZ * Xhash is an array of HSHSIZ bits (HSHSIZ / 8 chars), which are used
XZ * to hash execs. If it is allocated (havhash true), then to tell
XZ * whether ``name'' is (possibly) present in the i'th component
XZ * of the variable path, you look at the bit in xhash indexed by
XZ * hash(hashname("name"), i). This is setup automatically
XZ * after .login is executed, and recomputed whenever ``path'' is
XZ * changed.
XZ * The two part hash function is designed to let texec() call the
XZ * more expensive hashname() only once and the simple hash() several
XZ * times (once for each path component checked).
XZ * Byte size is assumed to be 8.
XZ */
XZ#define HSHSIZ 8192 /* 1k bytes */
XZ#define HSHMASK (HSHSIZ - 1)
XZ#define HSHMUL 243
XZchar xhash[HSHSIZ / 8];
XZ#define hash(a, b) ((a) * HSHMUL + (b) & HSHMASK)
XZ#define bit(h, b) ((h)[(b) >> 3] & 1 << ((b) & 7)) /* bit test */
XZ#define bis(h, b) ((h)[(b) >> 3] |= 1 << ((b) & 7)) /* bit set */
XZ#ifdef VFORK
XZint hits, misses;
XZ#endif
XSHAR_EOF
Xchmod 644 '/usr/src/bin/csh/sh.exec.h'
Xfi
Xexit 0
X# End of shell archive
SHAR_EOF
fi
exit 0
# End of shell archive