2
* sh.exec.c: Search, find, and execute a command!
5
* Copyright (c) 1980, 1991 The Regents of the University of California.
8
* Redistribution and use in source and binary forms, with or without
9
* modification, are permitted provided that the following conditions
11
* 1. Redistributions of source code must retain the above copyright
12
* notice, this list of conditions and the following disclaimer.
13
* 2. Redistributions in binary form must reproduce the above copyright
14
* notice, this list of conditions and the following disclaimer in the
15
* documentation and/or other materials provided with the distribution.
16
* 3. All advertising materials mentioning features or use of this software
17
* must display the following acknowledgement:
18
* This product includes software developed by the University of
19
* California, Berkeley and its contributors.
20
* 4. Neither the name of the University nor the names of its contributors
21
* may be used to endorse or promote products derived from this software
22
* without specific prior written permission.
24
* THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
25
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27
* ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
28
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51
# define FASTHASH /* Fast hashing is the default */
55
* System level search and execute of a command.
56
* We look in each directory for the specified command name.
57
* If the name contains a '/' then we execute only the full path name.
58
* If there is no search path then we execute only full path names.
62
* As we search for the command we note the first non-trivial error
63
* message for presentation to the user. This allows us often
64
* to show that a file has the wrong mode/no access when the file
65
* is not in the last component of the search path, so we must
66
* go on after first detecting the error.
68
static char *exerr; /* Execution error message */
69
static Char *expath; /* Path for exerr */
72
* The two part hash function is designed to let texec() call the
73
* more expensive hashname() only once and the simple hash() several
74
* times (once for each path component checked).
75
* Byte size is assumed to be 8.
77
#define BITS_PER_BYTE 8
81
* xhash is an array of hash buckets which are used to hash execs. If
82
* it is allocated (havhash true), then to tell if ``name'' is
83
* (possibly) presend in the i'th component of the variable path, look
84
* at the [hashname(name)] bucket of size [hashwidth] bytes, in the [i
85
* mod size*8]'th bit. The cache size is defaults to a length of 1024
86
* buckets, each 1 byte wide. This implementation guarantees that
87
* objects n bytes wide will be aligned on n byte boundaries.
91
static unsigned long *xhash = NULL;
92
static unsigned int hashlength = 0, uhashlength = 0;
93
static unsigned int hashwidth = 0, uhashwidth = 0;
94
static int hashdebug = 0;
96
# define hash(a, b) (((a) * HSHMUL + (b)) % (hashlength))
97
# define widthof(t) (sizeof(t) * BITS_PER_BYTE)
98
# define tbit(f, i, t) (((t *) xhash)[(f)] & \
99
(1L << (i & (widthof(t) - 1))))
100
# define tbis(f, i, t) (((t *) xhash)[(f)] |= \
101
(1L << (i & (widthof(t) - 1))))
102
# define cbit(f, i) tbit(f, i, unsigned char)
103
# define cbis(f, i) tbis(f, i, unsigned char)
104
# define sbit(f, i) tbit(f, i, unsigned short)
105
# define sbis(f, i) tbis(f, i, unsigned short)
106
# define ibit(f, i) tbit(f, i, unsigned int)
107
# define ibis(f, i) tbis(f, i, unsigned int)
108
# define lbit(f, i) tbit(f, i, unsigned long)
109
# define lbis(f, i) tbis(f, i, unsigned long)
111
# define bit(f, i) (hashwidth==sizeof(unsigned char) ? cbit(f,i) : \
112
((hashwidth==sizeof(unsigned short) ? sbit(f,i) : \
113
((hashwidth==sizeof(unsigned int) ? ibit(f,i) : \
115
# define bis(f, i) (hashwidth==sizeof(unsigned char) ? cbis(f,i) : \
116
((hashwidth==sizeof(unsigned short) ? sbis(f,i) : \
117
((hashwidth==sizeof(unsigned int) ? ibis(f,i) : \
121
* Xhash is an array of HSHSIZ bits (HSHSIZ / 8 chars), which are used
122
* to hash execs. If it is allocated (havhash true), then to tell
123
* whether ``name'' is (possibly) present in the i'th component
124
* of the variable path, you look at the bit in xhash indexed by
125
* hash(hashname("name"), i). This is setup automatically
126
* after .login is executed, and recomputed whenever ``path'' is
129
# define HSHSIZ 8192 /* 1k bytes */
130
# define HSHMASK (HSHSIZ - 1)
132
static char xhash[HSHSIZ / BITS_PER_BYTE];
134
# define hash(a, b) (((a) * HSHMUL + (b)) & HSHMASK)
135
# define bit(h, b) ((h)[(b) >> 3] & 1 << ((b) & 7)) /* bit test */
136
# define bis(h, b) ((h)[(b) >> 3] |= 1 << ((b) & 7)) /* bit set */
138
#endif /* FASTHASH */
141
static int hits, misses;
145
static char qrshmode_status_line[] = "qrshmode: ";
146
static char qrshmode_remote_true[] = "remote";
147
static char qrshmode_remote_false[] = "local";
148
static char qrshmode_immediate_true[] = "immediate";
149
static char qrshmode_immediate_false[] = "batch";
150
static char qrshmode_verbose_true[] = "verbose";
151
static char qrshmode_verbose_false[] = "non-verbose";
154
/* Dummy search path for just absolute search when no path */
155
static Char *justabs[] = {STRNULL, 0};
157
static void pexerr __P((void));
158
static void texec __P((Char *, Char **, int));
159
static int hashname __P((Char *));
160
static int iscommand __P((Char *));
177
xprintf("qrshmode: [%s] [%s] [%s]\n",
178
(get_sgemode(CATCH_EXEC_MODE_REMOTE)?"remote":"local"),
179
(get_sgemode(CATCH_EXEC_MODE_IMMEDIATE)?"immediate":"batch"),
180
(get_sgemode(CATCH_EXEC_MODE_VERBOSE)?"verbose":"silent"));
186
case 'L': /* local */
187
set_sgemode(CATCH_EXEC_MODE_REMOTE, 0);
189
case 'R': /* remote */
190
set_sgemode(CATCH_EXEC_MODE_REMOTE, 1);
192
case 'I': /* immediate */
193
set_sgemode(CATCH_EXEC_MODE_IMMEDIATE, 1);
195
case 'B': /* batch */
196
set_sgemode(CATCH_EXEC_MODE_IMMEDIATE, 0);
198
case 'A': /* verbose */
199
set_sgemode(CATCH_EXEC_MODE_VERBOSE, 1);
201
case 'N': /* non-verbose */
202
set_sgemode(CATCH_EXEC_MODE_VERBOSE, 0);
205
stderror(ERR_QRSHUS);
209
stderror(ERR_QRSHUS);
211
#endif /* CATCH_EXEC */
215
register struct command *t;
217
register Char *dp, **pv, **av, *sav;
218
register struct varent *v;
220
register int hashval, i;
224
* Glob the command name. We will search $path even if this does something,
225
* as in sh but not in csh. One special case: if there is no PATH, then we
226
* execute only commands which start with '/'.
229
fprintf(stderr, "qtcsh(1): command name = \"%s\"\n", short2str(t->t_dcom[0]));
233
blk[0] = t->t_dcom[0];
235
gflag = 0, tglob(blk);
239
setname(short2str(blk[0]));
240
stderror(ERR_NAME | ERR_NOMATCH);
250
expath = Strsave(pv[0]);
256
if (v == 0 && expath[0] != '/' && expath[0] != '.') {
260
slash = any(short2str(expath), '/');
263
fprintf(stderr, "expath = \"%s\"\n", short2str(expath));
268
* Glob the argument list, if necessary. Otherwise trim off the quote bits.
277
setname(short2str(expath));
278
stderror(ERR_NAME | ERR_NOMATCH);
286
t->t_dcom = blkspl(pv, av);
292
if (*av == NULL || **av == '\0')
295
xechoit(av); /* Echo command if -x */
298
* Since all internal file descriptors are set to close on exec, we don't
299
* need to close them explicitly here. Just reorient ourselves for error
306
isoutatty = isatty(SHOUT);
307
isdiagatty = isatty(SHDIAG);
309
closech(); /* Close random fd's */
312
* We must do this AFTER any possible forking (like `foo` in glob) so that
313
* this shell can still do subprocesses.
316
(void) sigsetmask((sigmask_t) 0);
318
(void) sigrelse(SIGINT);
319
(void) sigrelse(SIGCHLD);
323
* If no path, no words in path, or a / in the filename then restrict the
326
if (v == 0 || v->vec[0] == 0 || slash)
330
sav = Strspl(STRslash, *av);/* / command name for postpending */
334
hashval = havhash ? hashname(*av) : 0;
342
* Try to save time by looking at the hash table for where this command
343
* could be. If we are doing delayed hashing, then we put the names in
344
* one at a time, as the user enters them. This is kinda like Korn
345
* Shell's "tracked aliases".
347
if (!slash && ABSOLUTEP(pv[0]) && havhash) {
349
if (!bit(hashval, i))
352
int hashval1 = hash(hashval, i);
353
if (!bit(xhash, hashval1))
355
#endif /* FASTHASH */
357
if (pv[0][0] == 0 || eq(pv[0], STRdot)) /* don't make ./xxx */
361
if (t->t_dflg & F_AMPERSAND) {
363
xprintf("set SIGINT to SIG_IGN\n");
364
xprintf("set SIGQUIT to SIG_DFL\n");
365
# endif /* JOBDEBUG */
366
(void) signal(SIGINT,SIG_IGN); /* may not be necessary */
367
(void) signal(SIGQUIT,SIG_DFL);
370
if (gointr && eq(gointr, STRminus)) {
372
xprintf("set SIGINT to SIG_IGN\n");
373
xprintf("set SIGQUIT to SIG_IGN\n");
374
# endif /* JOBDEBUG */
375
(void) signal(SIGINT,SIG_IGN); /* may not be necessary */
376
(void) signal(SIGQUIT,SIG_IGN);
378
#endif /* COHERENT */
380
texec(*av, av, t->t_dflg & F_AMPERSAND);
383
dp = Strspl(*pv, sav);
389
if ((t->t_dflg & F_AMPERSAND)) {
391
xprintf("set SIGINT to SIG_IGN\n");
392
# endif /* JOBDEBUG */
394
* this is necessary on Coherent or all background
395
* jobs are killed by CTRL-C
396
* (there must be a better fix for this)
398
(void) signal(SIGINT,SIG_IGN);
400
if (gointr && eq(gointr,STRminus)) {
402
xprintf("set SIGINT to SIG_IGN\n");
403
xprintf("set SIGQUIT to SIG_IGN\n");
404
# endif /* JOBDEBUG */
405
(void) signal(SIGINT,SIG_IGN); /* may not be necessary */
406
(void) signal(SIGQUIT,SIG_IGN);
408
#endif /* COHERENT */
410
texec(dp, av, t->t_dflg & F_AMPERSAND);
434
/* Couldn't find the damn thing */
436
setname(short2str(expath));
440
xfree((ptr_t) expath);
446
stderror(ERR_NAME | ERR_STRING, exerr);
447
stderror(ERR_NAME | ERR_COMMAND);
451
* Execute command f, arg list t.
452
* Record error message if not found.
453
* Also do shell scripts here.
456
texec(sf, st, background)
463
register struct varent *v;
470
/* The order for the conversions is significant */
476
errno = 0; /* don't use a previous error */
479
* If we try to execute an nfs mounted directory on the apollo, we
480
* hang forever. So until apollo fixes that..
484
if (stat(f, &stb) == 0 && S_ISDIR(stb.st_mode))
490
#ifdef ISC_POSIX_EXEC_BUG
491
__setostype(0); /* "0" is "__OS_SYSV" in <sys/user.h> */
492
#endif /* ISC_POSIX_EXEC_BUG */
496
char *tt = (char *)malloc(strlen(f)+1);
498
(void) sge_execv(tt, t, short2str(expath), background);
508
#ifdef ISC_POSIX_EXEC_BUG
509
__setostype(1); /* "1" is "__OS_POSIX" in <sys/user.h> */
510
#endif /* ISC_POSIX_EXEC_BUG */
515
blkfree((Char **) t);
523
* From: casper@fwi.uva.nl (Casper H.S. Dik) If we could not execute
524
* it, don't feed it to the shell if it looks like a binary!
526
if ((fd = open(f, O_RDONLY)) != -1) {
528
if ((nread = read(fd, (char *) pref, 2)) == 2) {
529
if (!Isprint(pref[0]) && (pref[0] != '\n' && pref[0] != '\t')) {
532
* We *know* what ENOEXEC means.
534
stderror(ERR_ARCH, f, strerror(errno));
537
else if (nread < 0 && errno != EINTR) {
539
/* need to print error incase the file is migrated */
540
stderror(ERR_SYSTEM, f, strerror(errno));
552
pref[0] != '#' || pref[1] != '!' || hashbang(fd, &vp) == -1) {
553
#endif /* HASHBANG */
555
* If there is an alias for shell, then put the words of the alias in
556
* front of the argument list replacing the command name. Note no
557
* interpretation of the words at this point.
559
v = adrof1(STRshell, &aliases);
562
vp[0] = adrof(STRshell) ? varval(STRshell) : STR_SHELLPATH;
564
fprintf(stderr, "vp[0] = \"%s\"\n", short2str(vp[0]));
569
# ifndef ISC /* Compatible with ISC's /bin/csh */
578
vp = saveblk(v->vec);
581
#endif /* HASHBANG */
588
st = blkspl(vp, st); /* Splice up the new arglst */
591
/* The order for the conversions is significant */
595
blkfree((Char **) vp);
599
#ifdef ISC_POSIX_EXEC_BUG
600
__setostype(0); /* "0" is "__OS_SYSV" in <sys/user.h> */
601
#endif /* ISC_POSIX_EXEC_BUG */
604
char *tt = (char *)malloc(strlen(f)+1);
606
(void) sge_execv(tt, t, short2str(expath), background);
614
#ifdef ISC_POSIX_EXEC_BUG
615
__setostype(1); /* "1" is "__OS_POSIX" in <sys/user.h> */
616
#endif /* ISC_POSIX_EXEC_BUG */
620
blkfree((Char **) t);
621
/* The sky is falling, the sky is falling! */
622
stderror(ERR_SYSTEM, f, strerror(errno));
626
stderror(ERR_SYSTEM, f, strerror(errno));
630
case 0: /* execv fails and returns 0! */
637
exerr = strerror(errno);
639
xfree((ptr_t) expath);
640
expath = Strsave(sf);
653
register struct command *kp;
655
int saveIN, saveOUT, saveDIAG, saveSTD;
663
#ifndef CLOSE_ON_EXEC
665
#endif /* CLOSE_ON_EXEC */
666
signalfun_t osigint, osigquit, osigterm;
669
if (chkstop == 0 && setintr)
672
* Hmm, we don't really want to do that now because we might
673
* fail, but what is the choice
675
rechist(NULL, adrof(STRsavehist) != NULL);
678
osigint = signal(SIGINT, parintr);
679
osigquit = signal(SIGQUIT, parintr);
680
osigterm = signal(SIGTERM, parterm);
683
#ifndef CLOSE_ON_EXEC
685
#endif /* CLOSE_ON_EXEC */
691
saveIN = dcopy(SHIN, -1);
692
saveOUT = dcopy(SHOUT, -1);
693
saveDIAG = dcopy(SHDIAG, -1);
694
saveSTD = dcopy(OLDSTD, -1);
696
lshift(kp->t_dcom, 1);
700
/* PWP: setjmp/longjmp bugfix for optimizing compilers */
702
my_reenter = 1; /* assume non-zero return val */
703
if (setexit() == 0) {
704
my_reenter = 0; /* Oh well, we were wrong */
706
if ((my_reenter = setexit()) == 0) {
709
SHOUT = dcopy(1, -1);
710
SHDIAG = dcopy(2, -1);
711
#ifndef CLOSE_ON_EXEC
713
#endif /* CLOSE_ON_EXEC */
716
* Decrement the shell level
725
(void) sigset(SIGINT, osigint);
726
(void) sigset(SIGQUIT, osigquit);
727
(void) sigset(SIGTERM, osigterm);
730
#ifndef CLOSE_ON_EXEC
732
#endif /* CLOSE_ON_EXEC */
736
(void) close(SHDIAG);
737
(void) close(OLDSTD);
738
SHIN = dmove(saveIN, oSHIN);
739
SHOUT = dmove(saveOUT, oSHOUT);
740
SHDIAG = dmove(saveDIAG, oSHDIAG);
741
OLDSTD = dmove(saveSTD, oOLDSTD);
745
stderror(ERR_SILENT);
752
if (adrof(STRecho)) {
755
blkpr(t), xputchar('\n');
770
register struct dirent *dp;
772
struct varent *v = adrof(STRpath);
776
int is_windir; /* check if it is the windows directory */
783
uhashlength = atoi(short2str(vv[1]));
785
uhashwidth = atoi(short2str(vv[2]));
786
if ((uhashwidth != sizeof(unsigned char)) &&
787
(uhashwidth != sizeof(unsigned short)) &&
788
(uhashwidth != sizeof(unsigned long)))
791
hashdebug = atoi(short2str(vv[3]));
796
hashwidth = uhashwidth;
799
for (pv = v->vec; *pv; pv++, hashwidth++)
801
if (hashwidth <= widthof(unsigned char))
802
hashwidth = sizeof(unsigned char);
803
else if (hashwidth <= widthof(unsigned short))
804
hashwidth = sizeof(unsigned short);
805
else if (hashwidth <= widthof(unsigned int))
806
hashwidth = sizeof(unsigned int);
808
hashwidth = sizeof(unsigned long);
812
hashlength = uhashlength;
814
hashlength = hashwidth * (8*64);/* "average" files per dir in path */
817
xfree((ptr_t) xhash);
818
xhash = (unsigned long *) xcalloc((size_t) (hashlength * hashwidth),
820
#endif /* FASTHASH */
822
(void) getusername(NULL); /* flush the tilde cashe */
827
for (pv = v->vec; *pv; pv++, i++) {
828
if (!ABSOLUTEP(pv[0]))
830
dirp = opendir(short2str(*pv));
833
#ifdef COMMENT /* this isn't needed. opendir won't open
835
if (fstat(dirp->dd_fd, &stb) < 0 || !S_ISDIR(stb.st_mode)) {
836
(void) closedir(dirp);
841
is_windir = nt_check_if_windir(short2str(*pv));
843
while ((dp = readdir(dirp)) != NULL) {
848
if (dp->d_name[0] == '.' &&
849
(dp->d_name[1] == '\0' ||
850
(dp->d_name[1] == '.' && dp->d_name[2] == '\0')))
853
nt_check_name_and_hash(is_windir, dp->d_name, i);
855
#if defined(_UWIN) /* XXX: Add cygwin too */
856
/* Turn foo.{exe,com,bat} into foo since UWIN's readdir returns
857
* the file with the .exe, .com, .bat extension
860
size_t ext = strlen(dp->d_name) - 4;
861
if ((ext > 0) && (strcmp(&dp->d_name[ext], ".exe") == 0 ||
862
strcmp(&dp->d_name[ext], ".bat") == 0 ||
863
strcmp(&dp->d_name[ext], ".com") == 0))
864
dp->d_name[ext] = '\0';
868
hashval = hashname(str2short(dp->d_name));
871
xprintf(CGETS(13, 1, "hash=%-4d dir=%-2d prog=%s\n"),
872
hashname(str2short(dp->d_name)), i, dp->d_name);
873
# else /* OLD HASH */
874
hashval = hash(hashname(str2short(dp->d_name)), i);
876
# endif /* FASTHASH */
877
/* tw_add_comm_name (dp->d_name); */
880
(void) closedir(dirp);
895
xfree((ptr_t) xhash);
898
#endif /* FASTHASH */
910
if (havhash && hashlength && hashwidth)
911
xprintf(CGETS(13, 2, "%d hash buckets of %d bits each\n"),
912
hashlength, hashwidth*8);
914
xprintf(CGETS(13, 3, "debug mask = 0x%08x\n"), hashdebug);
915
#endif /* FASTHASH */
918
xprintf(CGETS(13, 4, "%d hits, %d misses, %d%%\n"),
919
hits, misses, 100 * hits / (hits + misses));
925
* Hash a command name.
933
for (h = 0; *cp; cp++)
944
register struct varent *v;
945
register bool slash = any(short2str(name), '/');
946
register int hashval, i;
949
if (v == 0 || v->vec[0] == 0 || slash)
953
sav = Strspl(STRslash, name); /* / command name for postpending */
954
hashval = havhash ? hashname(name) : 0;
957
if (!slash && ABSOLUTEP(pv[0]) && havhash) {
959
if (!bit(hashval, i))
962
int hashval1 = hash(hashval, i);
963
if (!bit(xhash, hashval1))
965
#endif /* FASTHASH */
967
if (pv[0][0] == 0 || eq(pv[0], STRdot)) { /* don't make ./xxx */
968
if (executable(NULL, name, 0)) {
974
if (executable(*pv, sav, 0)) {
988
* Andreas Luik <luik@isaak.isa.de>
989
* I S A GmbH - Informationssysteme fuer computerintegrierte Automatisierung
993
* is the executable() routine below and changes to iscommand().
998
* executable() examines the pathname obtained by concatenating dir and name
999
* (dir may be NULL), and returns 1 either if it is executable by us, or
1000
* if dir_ok is set and the pathname refers to a directory.
1001
* This is a bit kludgy, but in the name of optimization...
1004
executable(dir, name, dir_ok)
1009
Char path[MAXPATHLEN + 1];
1014
(void) memset(path, 0, sizeof(path));
1017
copyn(path, dir, MAXPATHLEN);
1018
catn(path, name, MAXPATHLEN);
1021
char *ptr = short2str(path);
1038
if (!has_ext && (stat(p2, &stbuf) == -1))
1039
catn(path, STRdotEXE, MAXPATHLEN);
1042
strname = short2str(path);
1045
strname = short2str(name);
1047
return (stat(strname, &stbuf) != -1 &&
1048
((dir_ok && S_ISDIR(stbuf.st_mode)) ||
1049
(S_ISREG(stbuf.st_mode) &&
1050
/* save time by not calling access() in the hopeless case */
1052
(GetBinaryType(strname,&nt_exetype) ||
1053
(stbuf.st_mode & (S_IXOTH | S_IXGRP | S_IXUSR)))
1055
(stbuf.st_mode & (S_IXOTH | S_IXGRP | S_IXUSR)) &&
1056
access(strname, X_OK) == 0
1062
tellmewhat(lexp, str)
1063
struct wordent *lexp;
1067
register struct biltins *bptr;
1068
register struct wordent *sp = lexp->next;
1069
bool aliased = 0, found;
1070
Char *s0, *s1, *s2, *cmd;
1073
if (adrof1(sp->word, &aliases)) {
1079
s0 = sp->word; /* to get the memory freeing right... */
1081
/* handle quoted alias hack */
1082
if ((*(sp->word) & (QUOTE | TRIM)) == QUOTE)
1085
/* do quoting, if it hasn't been done */
1092
while (*s2 && *s2 != qc)
1093
*s1++ = *s2++ | QUOTE;
1099
*s1++ = *s2++ | QUOTE;
1106
for (bptr = bfunc; bptr < &bfunc[nbfunc]; bptr++) {
1107
if (eq(sp->word, str2short(bptr->bname))) {
1111
xprintf(CGETS(13, 5, "%S: shell built-in command.\n"),
1116
(void) Strcpy(str, sp->word);
1117
sp->word = s0; /* we save and then restore this */
1122
for (bptr = nt_bfunc; bptr < &nt_bfunc[nt_nbfunc]; bptr++) {
1123
if (eq(sp->word, str2short(bptr->bname))) {
1127
xprintf(CGETS(13, 5, "%S: shell built-in command.\n"),
1132
(void) Strcpy(str, sp->word);
1133
sp->word = s0; /* we save and then restore this */
1139
sp->word = cmd = globone(sp->word, G_IGNORE);
1141
if ((i = iscommand(sp->word)) != 0) {
1143
register struct varent *v;
1144
bool slash = any(short2str(sp->word), '/');
1147
if (v == 0 || v->vec[0] == 0 || slash)
1154
if (pv[0][0] == 0 || eq(pv[0], STRdot)) {
1156
sp->word = Strspl(STRdotsl, sp->word);
1158
xfree((ptr_t) sp->word);
1164
s1 = Strspl(*pv, STRslash);
1165
sp->word = Strspl(s1, sp->word);
1170
(void) Strcpy(str, sp->word);
1171
xfree((ptr_t) sp->word);
1179
xprintf(CGETS(13, 6, "%S: Command not found.\n"), sp->word);
1183
(void) Strcpy(str, sp->word);
1186
sp->word = s0; /* we save and then restore this */
1192
* Builtin to look at and list all places a command may be defined:
1193
* aliases, shell builtins, and the path.
1195
* Marc Horowitz <marc@mit.edu>
1196
* MIT Student Information Processing Board
1208
found &= find_cmd(*v, 1);
1209
/* Make status nonzero if any command is not found. */
1211
set(STRstatus, Strsave(STR1), VAR_READWRITE);
1220
struct biltins *bptr;
1223
int hashval, i, ex, rval = 0;
1225
if (prt && any(short2str(cmd), '/')) {
1226
xprintf(CGETS(13, 7, "where: / in command makes no sense\n"));
1230
/* first, look for an alias */
1232
if (prt && adrof1(cmd, &aliases)) {
1233
if ((var = adrof1(cmd, &aliases)) != NULL) {
1234
xprintf(CGETS(13, 8, "%S is aliased to "), cmd);
1241
/* next, look for a shell builtin */
1243
for (bptr = bfunc; bptr < &bfunc[nbfunc]; bptr++) {
1244
if (eq(cmd, str2short(bptr->bname))) {
1247
xprintf(CGETS(13, 9, "%S is a shell built-in\n"), cmd);
1253
for (bptr = nt_bfunc; bptr < &nt_bfunc[nt_nbfunc]; bptr++) {
1254
if (eq(cmd, str2short(bptr->bname))) {
1257
xprintf(CGETS(13, 9, "%S is a shell built-in\n"), cmd);
1264
/* last, look through the path for the command */
1266
if ((var = adrof(STRpath)) == NULL)
1269
hashval = havhash ? hashname(cmd) : 0;
1271
sv = Strspl(STRslash, cmd);
1273
for (pv = var->vec, i = 0; *pv; pv++, i++) {
1274
if (havhash && !eq(*pv, STRdot)) {
1276
if (!bit(hashval, i))
1279
int hashval1 = hash(hashval, i);
1280
if (!bit(xhash, hashval1))
1282
#endif /* FASTHASH */
1284
ex = executable(*pv, sv, 0);
1286
if (!ex && (hashdebug & 2)) {
1287
xprintf(CGETS(13, 10, "hash miss: "));
1288
ex = 1; /* Force printing */
1290
#endif /* FASTHASH */
1294
xprintf("%S/", *pv);
1295
xprintf("%S\n", cmd);
1307
nt_check_if_windir(path)
1310
char windir[MAX_PATH];
1312
(void)GetWindowsDirectory(windir, sizeof(windir));
1315
return (strstr(path, windir) != NULL);
1319
nt_check_name_and_hash(is_windir, file, i)
1324
char name_only[MAX_PATH];
1325
char *tmp = (char *)strrchr(file, '.');
1326
char uptmp[5], *nameptr, *np2;
1327
int icount, hashval;
1332
for (icount = 0; icount < 4; icount++)
1333
uptmp[icount] = toupper(tmp[icount]);
1337
if((uptmp[1] != 'E') || (uptmp[2] != 'X') || (uptmp[3] != 'E'))
1339
(void) memset(name_only, 0, MAX_PATH);
1342
while(nameptr != tmp) {
1343
*np2++= tolower(*nameptr);
1346
hashval = hashname(str2short(name_only));
1349
hashval = hashname(str2short(file));
1352
int hashval_extern(cp)
1355
return havhash?hashname(cp):0;
1357
int bit_extern(val,i)