~ubuntu-branches/ubuntu/utopic/gridengine/utopic

« back to all changes in this revision

Viewing changes to source/3rdparty/qtcsh/sh.exec.c

  • Committer: Bazaar Package Importer
  • Author(s): Mark Hymers
  • Date: 2008-06-25 22:36:13 UTC
  • Revision ID: james.westby@ubuntu.com-20080625223613-tvd9xlhuoct9kyhm
Tags: upstream-6.2~beta2
ImportĀ upstreamĀ versionĀ 6.2~beta2

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * sh.exec.c: Search, find, and execute a command!
 
3
 */
 
4
/*-
 
5
 * Copyright (c) 1980, 1991 The Regents of the University of California.
 
6
 * All rights reserved.
 
7
 *
 
8
 * Redistribution and use in source and binary forms, with or without
 
9
 * modification, are permitted provided that the following conditions
 
10
 * are met:
 
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.
 
23
 *
 
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
 
34
 * SUCH DAMAGE.
 
35
 */
 
36
#include "sh.h"
 
37
 
 
38
RCSID("$Id$")
 
39
 
 
40
#include "tc.h"
 
41
#include "tw.h"
 
42
#ifdef WINNT
 
43
#include <nt.const.h>
 
44
#endif /*WINNT*/
 
45
 
 
46
/*
 
47
 * C shell
 
48
 */
 
49
 
 
50
#ifndef OLDHASH
 
51
# define FASTHASH       /* Fast hashing is the default */
 
52
#endif /* OLDHASH */
 
53
 
 
54
/*
 
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.
 
59
 */
 
60
 
 
61
/*
 
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.
 
67
 */
 
68
static char *exerr;             /* Execution error message */
 
69
static Char *expath;            /* Path for exerr */
 
70
 
 
71
/*
 
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.
 
76
 */
 
77
#define BITS_PER_BYTE   8
 
78
 
 
79
#ifdef FASTHASH
 
80
/*
 
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.
 
88
 */
 
89
# define HSHMUL         241
 
90
 
 
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;
 
95
 
 
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)
 
110
 
 
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) : \
 
114
                     lbit(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) : \
 
118
                     lbis(f,i))))))
 
119
#else /* OLDHASH */
 
120
/*
 
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
 
127
 * changed.
 
128
 */
 
129
# define HSHSIZ         8192    /* 1k bytes */
 
130
# define HSHMASK                (HSHSIZ - 1)
 
131
# define HSHMUL         243
 
132
static char xhash[HSHSIZ / BITS_PER_BYTE];
 
133
 
 
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 */
 
137
 
 
138
#endif /* FASTHASH */
 
139
 
 
140
#ifdef VFORK
 
141
static int hits, misses;
 
142
#endif /* VFORK */
 
143
 
 
144
#ifdef CATCH_EXEC
 
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";
 
152
#endif
 
153
 
 
154
/* Dummy search path for just absolute search when no path */
 
155
static Char *justabs[] = {STRNULL, 0};
 
156
 
 
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 *));
 
161
 
 
162
#ifdef CATCH_EXEC
 
163
 
 
164
/*ARGSUSED*/
 
165
void
 
166
doqrshmode(v, c)
 
167
    register Char **v;
 
168
    struct command *c;
 
169
{
 
170
    Char   *cp;
 
171
 
 
172
    USE(c);
 
173
  
 
174
    v++;
 
175
    cp = *v++;
 
176
    if (cp == NULL) {
 
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"));
 
181
       return;
 
182
    }
 
183
 
 
184
    if (*cp++ == '-') {
 
185
       switch (*cp) {
 
186
       case 'L': /* local */
 
187
          set_sgemode(CATCH_EXEC_MODE_REMOTE, 0);
 
188
          break;
 
189
       case 'R': /* remote */
 
190
          set_sgemode(CATCH_EXEC_MODE_REMOTE, 1);
 
191
          break;
 
192
       case 'I': /* immediate */
 
193
          set_sgemode(CATCH_EXEC_MODE_IMMEDIATE, 1);
 
194
          break;
 
195
       case 'B': /* batch */
 
196
          set_sgemode(CATCH_EXEC_MODE_IMMEDIATE, 0);
 
197
          break;
 
198
       case 'A': /* verbose */
 
199
          set_sgemode(CATCH_EXEC_MODE_VERBOSE, 1);
 
200
          break;
 
201
       case 'N': /* non-verbose */
 
202
          set_sgemode(CATCH_EXEC_MODE_VERBOSE, 0);
 
203
          break;
 
204
       default: 
 
205
          stderror(ERR_QRSHUS);
 
206
          break;
 
207
       }
 
208
    } else
 
209
       stderror(ERR_QRSHUS);
 
210
}
 
211
#endif /* CATCH_EXEC */
 
212
 
 
213
void
 
214
doexec(t)
 
215
    register struct command *t;
 
216
{
 
217
    register Char *dp, **pv, **av, *sav;
 
218
    register struct varent *v;
 
219
    register bool slash;
 
220
    register int hashval, i;
 
221
    Char   *blk[2];
 
222
 
 
223
    /*
 
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 '/'.
 
227
     */
 
228
#if 0
 
229
    fprintf(stderr, "qtcsh(1): command name = \"%s\"\n", short2str(t->t_dcom[0])); 
 
230
    fflush(stderr);
 
231
#endif
 
232
 
 
233
    blk[0] = t->t_dcom[0];
 
234
    blk[1] = 0;
 
235
    gflag = 0, tglob(blk);
 
236
    if (gflag) {
 
237
        pv = globall(blk);
 
238
        if (pv == 0) {
 
239
            setname(short2str(blk[0]));
 
240
            stderror(ERR_NAME | ERR_NOMATCH);
 
241
        }
 
242
        gargv = 0;
 
243
    }
 
244
    else
 
245
        pv = saveblk(blk);
 
246
 
 
247
    trim(pv);
 
248
 
 
249
    exerr = 0;
 
250
    expath = Strsave(pv[0]);
 
251
#ifdef VFORK
 
252
    Vexpath = expath;
 
253
#endif /* VFORK */
 
254
 
 
255
    v = adrof(STRpath);
 
256
    if (v == 0 && expath[0] != '/' && expath[0] != '.') {
 
257
        blkfree(pv);
 
258
        pexerr();
 
259
    }
 
260
    slash = any(short2str(expath), '/');
 
261
 
 
262
#if 0
 
263
    fprintf(stderr, "expath = \"%s\"\n", short2str(expath)); 
 
264
    fflush(stderr);
 
265
#endif
 
266
 
 
267
    /*
 
268
     * Glob the argument list, if necessary. Otherwise trim off the quote bits.
 
269
     */
 
270
    gflag = 0;
 
271
    av = &t->t_dcom[1];
 
272
    tglob(av);
 
273
    if (gflag) {
 
274
        av = globall(av);
 
275
        if (av == 0) {
 
276
            blkfree(pv);
 
277
            setname(short2str(expath));
 
278
            stderror(ERR_NAME | ERR_NOMATCH);
 
279
        }
 
280
        gargv = 0;
 
281
    }
 
282
    else
 
283
        av = saveblk(av);
 
284
 
 
285
    blkfree(t->t_dcom);
 
286
    t->t_dcom = blkspl(pv, av);
 
287
    xfree((ptr_t) pv);
 
288
    xfree((ptr_t) av);
 
289
    av = t->t_dcom;
 
290
    trim(av);
 
291
 
 
292
    if (*av == NULL || **av == '\0')
 
293
        pexerr();
 
294
 
 
295
    xechoit(av);                /* Echo command if -x */
 
296
#ifdef CLOSE_ON_EXEC
 
297
    /*
 
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
 
300
     * messages.
 
301
     */
 
302
    SHIN = 0;
 
303
    SHOUT = 1;
 
304
    SHDIAG = 2;
 
305
    OLDSTD = 0;
 
306
    isoutatty = isatty(SHOUT);
 
307
    isdiagatty = isatty(SHDIAG);
 
308
#else
 
309
    closech();                  /* Close random fd's */
 
310
#endif
 
311
    /*
 
312
     * We must do this AFTER any possible forking (like `foo` in glob) so that
 
313
     * this shell can still do subprocesses.
 
314
     */
 
315
#ifdef BSDSIGS
 
316
    (void) sigsetmask((sigmask_t) 0);
 
317
#else /* BSDSIGS */
 
318
    (void) sigrelse(SIGINT);
 
319
    (void) sigrelse(SIGCHLD);
 
320
#endif /* BSDSIGS */
 
321
 
 
322
    /*
 
323
     * If no path, no words in path, or a / in the filename then restrict the
 
324
     * command search.
 
325
     */
 
326
    if (v == 0 || v->vec[0] == 0 || slash)
 
327
        pv = justabs;
 
328
    else
 
329
        pv = v->vec;
 
330
    sav = Strspl(STRslash, *av);/* / command name for postpending */
 
331
#ifdef VFORK
 
332
    Vsav = sav;
 
333
#endif /* VFORK */
 
334
    hashval = havhash ? hashname(*av) : 0;
 
335
 
 
336
    i = 0;
 
337
#ifdef VFORK
 
338
    hits++;
 
339
#endif /* VFORK */
 
340
    do {
 
341
        /*
 
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".
 
346
         */
 
347
        if (!slash && ABSOLUTEP(pv[0]) && havhash) {
 
348
#ifdef FASTHASH
 
349
            if (!bit(hashval, i))
 
350
                goto cont;
 
351
#else /* OLDHASH */
 
352
            int hashval1 = hash(hashval, i);
 
353
            if (!bit(xhash, hashval1))
 
354
                goto cont;
 
355
#endif /* FASTHASH */
 
356
        }
 
357
        if (pv[0][0] == 0 || eq(pv[0], STRdot)) /* don't make ./xxx */
 
358
        {
 
359
 
 
360
#ifdef COHERENT
 
361
            if (t->t_dflg & F_AMPERSAND) {
 
362
# ifdef JOBDEBUG
 
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);
 
368
            }
 
369
 
 
370
            if (gointr && eq(gointr, STRminus)) {
 
371
# ifdef JOBDEBUG
 
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);
 
377
            }
 
378
#endif /* COHERENT */
 
379
 
 
380
            texec(*av, av, t->t_dflg & F_AMPERSAND);
 
381
}
 
382
        else {
 
383
            dp = Strspl(*pv, sav);
 
384
#ifdef VFORK
 
385
            Vdp = dp;
 
386
#endif /* VFORK */
 
387
 
 
388
#ifdef COHERENT
 
389
            if ((t->t_dflg & F_AMPERSAND)) {
 
390
# ifdef JOBDEBUG
 
391
                xprintf("set SIGINT to SIG_IGN\n");
 
392
# endif /* JOBDEBUG */
 
393
                /* 
 
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) 
 
397
                 */
 
398
                (void) signal(SIGINT,SIG_IGN); 
 
399
            }
 
400
            if (gointr && eq(gointr,STRminus)) {
 
401
# ifdef JOBDEBUG
 
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);
 
407
            }
 
408
#endif /* COHERENT */
 
409
 
 
410
            texec(dp, av, t->t_dflg & F_AMPERSAND);
 
411
#ifdef VFORK
 
412
            Vdp = 0;
 
413
#endif /* VFORK */
 
414
            xfree((ptr_t) dp);
 
415
        }
 
416
#ifdef VFORK
 
417
        misses++;
 
418
#endif /* VFORK */
 
419
cont:
 
420
        pv++;
 
421
        i++;
 
422
    } while (*pv);
 
423
#ifdef VFORK
 
424
    hits--;
 
425
    Vsav = 0;
 
426
#endif /* VFORK */
 
427
    xfree((ptr_t) sav);
 
428
    pexerr();
 
429
}
 
430
 
 
431
static void
 
432
pexerr()
 
433
{
 
434
    /* Couldn't find the damn thing */
 
435
    if (expath) {
 
436
        setname(short2str(expath));
 
437
#ifdef VFORK
 
438
        Vexpath = 0;
 
439
#endif /* VFORK */
 
440
        xfree((ptr_t) expath);
 
441
        expath = 0;
 
442
    }
 
443
    else
 
444
        setname("");
 
445
    if (exerr)
 
446
        stderror(ERR_NAME | ERR_STRING, exerr);
 
447
    stderror(ERR_NAME | ERR_COMMAND);
 
448
}
 
449
 
 
450
/*
 
451
 * Execute command f, arg list t.
 
452
 * Record error message if not found.
 
453
 * Also do shell scripts here.
 
454
 */
 
455
static void
 
456
texec(sf, st, background)
 
457
    Char   *sf;
 
458
    register Char **st;
 
459
    int background;
 
460
{
 
461
    register char **t;
 
462
    register char *f;
 
463
    register struct varent *v;
 
464
    Char  **vp;
 
465
    Char   *lastsh[2];
 
466
    char    pref[2];
 
467
    int     fd;
 
468
    Char   *st0, **ost;
 
469
 
 
470
    /* The order for the conversions is significant */
 
471
    t = short2blk(st);
 
472
    f = short2str(sf);
 
473
#ifdef VFORK
 
474
    Vt = t;
 
475
#endif /* VFORK */
 
476
    errno = 0;                  /* don't use a previous error */
 
477
#ifdef apollo
 
478
    /*
 
479
     * If we try to execute an nfs mounted directory on the apollo, we
 
480
     * hang forever. So until apollo fixes that..
 
481
     */
 
482
    {
 
483
        struct stat stb;
 
484
        if (stat(f, &stb) == 0 && S_ISDIR(stb.st_mode))
 
485
            errno = EISDIR;
 
486
    }
 
487
    if (errno == 0)
 
488
#endif /* apollo */
 
489
    {
 
490
#ifdef ISC_POSIX_EXEC_BUG
 
491
        __setostype(0);         /* "0" is "__OS_SYSV" in <sys/user.h> */
 
492
#endif /* ISC_POSIX_EXEC_BUG */
 
493
 
 
494
#ifdef CATCH_EXEC
 
495
   if (expath) {
 
496
      char *tt = (char *)malloc(strlen(f)+1);
 
497
      strcpy(tt, f);
 
498
      (void) sge_execv(tt, t, short2str(expath), background);
 
499
      free(tt);
 
500
      f = short2str(sf);
 
501
   } else
 
502
           (void) execv(f, t);
 
503
#else
 
504
        (void) execv(f, t);
 
505
#endif
 
506
 
 
507
 
 
508
#ifdef ISC_POSIX_EXEC_BUG
 
509
        __setostype(1);         /* "1" is "__OS_POSIX" in <sys/user.h> */
 
510
#endif /* ISC_POSIX_EXEC_BUG */
 
511
    }
 
512
#ifdef VFORK
 
513
    Vt = 0;
 
514
#endif /* VFORK */
 
515
    blkfree((Char **) t);
 
516
    switch (errno) {
 
517
 
 
518
    case ENOEXEC:
 
519
#ifdef WINNT
 
520
                nt_feed_to_cmd(f,t);
 
521
#endif /* WINNT */
 
522
        /*
 
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!
 
525
         */
 
526
        if ((fd = open(f, O_RDONLY)) != -1) {
 
527
            int nread;
 
528
            if ((nread = read(fd, (char *) pref, 2)) == 2) {
 
529
                if (!Isprint(pref[0]) && (pref[0] != '\n' && pref[0] != '\t')) {
 
530
                    (void) close(fd);
 
531
                    /*
 
532
                     * We *know* what ENOEXEC means.
 
533
                     */
 
534
                    stderror(ERR_ARCH, f, strerror(errno));
 
535
                }
 
536
            }
 
537
            else if (nread < 0 && errno != EINTR) {
 
538
#ifdef convex
 
539
                /* need to print error incase the file is migrated */
 
540
                stderror(ERR_SYSTEM, f, strerror(errno));
 
541
#endif
 
542
            }
 
543
#ifdef _PATH_BSHELL
 
544
            else {
 
545
                pref[0] = '#';
 
546
                pref[1] = '\0';
 
547
            }
 
548
#endif
 
549
        }
 
550
#ifdef HASHBANG
 
551
        if (fd == -1 ||
 
552
            pref[0] != '#' || pref[1] != '!' || hashbang(fd, &vp) == -1) {
 
553
#endif /* HASHBANG */
 
554
        /*
 
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.
 
558
         */
 
559
            v = adrof1(STRshell, &aliases);
 
560
            if (v == 0) {
 
561
                vp = lastsh;
 
562
                vp[0] = adrof(STRshell) ? varval(STRshell) : STR_SHELLPATH;
 
563
#if 0
 
564
    fprintf(stderr, "vp[0] = \"%s\"\n", short2str(vp[0])); 
 
565
#endif
 
566
                vp[1] = NULL;
 
567
#ifdef _PATH_BSHELL
 
568
                if (fd != -1 
 
569
# ifndef ISC    /* Compatible with ISC's /bin/csh */
 
570
                    && pref[0] != '#'
 
571
# endif /* ISC */
 
572
                    )
 
573
                    vp[0] = STR_BSHELL;
 
574
#endif
 
575
                vp = saveblk(vp);
 
576
            }
 
577
            else
 
578
                vp = saveblk(v->vec);
 
579
#ifdef HASHBANG
 
580
        }
 
581
#endif /* HASHBANG */
 
582
        if (fd != -1)
 
583
            (void) close(fd);
 
584
 
 
585
        st0 = st[0];
 
586
        st[0] = sf;
 
587
        ost = st;
 
588
        st = blkspl(vp, st);    /* Splice up the new arglst */
 
589
        ost[0] = st0;
 
590
        sf = *st;
 
591
        /* The order for the conversions is significant */
 
592
        t = short2blk(st);
 
593
        f = short2str(sf);
 
594
        xfree((ptr_t) st);
 
595
        blkfree((Char **) vp);
 
596
#ifdef VFORK
 
597
        Vt = t;
 
598
#endif /* VFORK */
 
599
#ifdef ISC_POSIX_EXEC_BUG
 
600
        __setostype(0);         /* "0" is "__OS_SYSV" in <sys/user.h> */
 
601
#endif /* ISC_POSIX_EXEC_BUG */
 
602
#ifdef CATCH_EXEC
 
603
   if (expath) {
 
604
      char *tt = (char *)malloc(strlen(f)+1);
 
605
      strcpy(tt, f);
 
606
      (void) sge_execv(tt, t, short2str(expath), background);
 
607
      free(tt);
 
608
      f = short2str(sf);
 
609
   } else
 
610
           (void) execv(f, t);
 
611
#else
 
612
        (void) execv(f, t);
 
613
#endif
 
614
#ifdef ISC_POSIX_EXEC_BUG
 
615
        __setostype(1);         /* "1" is "__OS_POSIX" in <sys/user.h> */
 
616
#endif /* ISC_POSIX_EXEC_BUG */
 
617
#ifdef VFORK
 
618
        Vt = 0;
 
619
#endif /* VFORK */
 
620
        blkfree((Char **) t);
 
621
        /* The sky is falling, the sky is falling! */
 
622
        stderror(ERR_SYSTEM, f, strerror(errno));
 
623
        break;
 
624
 
 
625
    case ENOMEM:
 
626
        stderror(ERR_SYSTEM, f, strerror(errno));
 
627
        break;
 
628
 
 
629
#ifdef _IBMR2
 
630
    case 0:                     /* execv fails and returns 0! */
 
631
#endif /* _IBMR2 */
 
632
    case ENOENT:
 
633
        break;
 
634
 
 
635
    default:
 
636
        if (exerr == 0) {
 
637
            exerr = strerror(errno);
 
638
            if (expath)
 
639
                xfree((ptr_t) expath);
 
640
            expath = Strsave(sf);
 
641
#ifdef VFORK
 
642
            Vexpath = expath;
 
643
#endif /* VFORK */
 
644
        }
 
645
        break;
 
646
    }
 
647
}
 
648
 
 
649
/*ARGSUSED*/
 
650
void
 
651
execash(t, kp)
 
652
    Char  **t;
 
653
    register struct command *kp;
 
654
{
 
655
    int     saveIN, saveOUT, saveDIAG, saveSTD;
 
656
    int     oSHIN;
 
657
    int     oSHOUT;
 
658
    int     oSHDIAG;
 
659
    int     oOLDSTD;
 
660
    jmp_buf_t osetexit;
 
661
    int     my_reenter;
 
662
    int     odidfds;
 
663
#ifndef CLOSE_ON_EXEC
 
664
    int     odidcch;
 
665
#endif /* CLOSE_ON_EXEC */
 
666
    signalfun_t osigint, osigquit, osigterm;
 
667
 
 
668
    USE(t);
 
669
    if (chkstop == 0 && setintr)
 
670
        panystop(0);
 
671
    /*
 
672
     * Hmm, we don't really want to do that now because we might
 
673
     * fail, but what is the choice
 
674
     */
 
675
    rechist(NULL, adrof(STRsavehist) != NULL);
 
676
 
 
677
 
 
678
    osigint  = signal(SIGINT, parintr);
 
679
    osigquit = signal(SIGQUIT, parintr);
 
680
    osigterm = signal(SIGTERM, parterm);
 
681
 
 
682
    odidfds = didfds;
 
683
#ifndef CLOSE_ON_EXEC
 
684
    odidcch = didcch;
 
685
#endif /* CLOSE_ON_EXEC */
 
686
    oSHIN = SHIN;
 
687
    oSHOUT = SHOUT;
 
688
    oSHDIAG = SHDIAG;
 
689
    oOLDSTD = OLDSTD;
 
690
 
 
691
    saveIN = dcopy(SHIN, -1);
 
692
    saveOUT = dcopy(SHOUT, -1);
 
693
    saveDIAG = dcopy(SHDIAG, -1);
 
694
    saveSTD = dcopy(OLDSTD, -1);
 
695
        
 
696
    lshift(kp->t_dcom, 1);
 
697
 
 
698
    getexit(osetexit);
 
699
 
 
700
    /* PWP: setjmp/longjmp bugfix for optimizing compilers */
 
701
#ifdef cray
 
702
    my_reenter = 1;             /* assume non-zero return val */
 
703
    if (setexit() == 0) {
 
704
        my_reenter = 0;         /* Oh well, we were wrong */
 
705
#else /* !cray */
 
706
    if ((my_reenter = setexit()) == 0) {
 
707
#endif /* cray */
 
708
        SHIN = dcopy(0, -1);
 
709
        SHOUT = dcopy(1, -1);
 
710
        SHDIAG = dcopy(2, -1);
 
711
#ifndef CLOSE_ON_EXEC
 
712
        didcch = 0;
 
713
#endif /* CLOSE_ON_EXEC */
 
714
        didfds = 0;
 
715
        /*
 
716
         * Decrement the shell level
 
717
         */
 
718
        shlvl(-1);
 
719
#ifdef WINNT
 
720
        __nt_really_exec=1;
 
721
#endif /* WINNT */
 
722
        doexec(kp);
 
723
    }
 
724
 
 
725
    (void) sigset(SIGINT, osigint);
 
726
    (void) sigset(SIGQUIT, osigquit);
 
727
    (void) sigset(SIGTERM, osigterm);
 
728
 
 
729
    doneinp = 0;
 
730
#ifndef CLOSE_ON_EXEC
 
731
    didcch = odidcch;
 
732
#endif /* CLOSE_ON_EXEC */
 
733
    didfds = odidfds;
 
734
    (void) close(SHIN);
 
735
    (void) close(SHOUT);
 
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);
 
742
 
 
743
    resexit(osetexit);
 
744
    if (my_reenter)
 
745
        stderror(ERR_SILENT);
 
746
}
 
747
 
 
748
void
 
749
xechoit(t)
 
750
    Char  **t;
 
751
{
 
752
    if (adrof(STRecho)) {
 
753
        flush();
 
754
        haderr = 1;
 
755
        blkpr(t), xputchar('\n');
 
756
        haderr = 0;
 
757
    }
 
758
}
 
759
 
 
760
/*ARGSUSED*/
 
761
void
 
762
dohash(vv, c)
 
763
    Char **vv;
 
764
    struct command *c;
 
765
{
 
766
#ifdef COMMENT
 
767
    struct stat stb;
 
768
#endif
 
769
    DIR    *dirp;
 
770
    register struct dirent *dp;
 
771
    int     i = 0;
 
772
    struct varent *v = adrof(STRpath);
 
773
    Char  **pv;
 
774
    int hashval;
 
775
#ifdef WINNT
 
776
    int is_windir; /* check if it is the windows directory */
 
777
    USE(hashval);
 
778
#endif /* WINNT */
 
779
 
 
780
    USE(c);
 
781
#ifdef FASTHASH
 
782
    if (vv && vv[1]) {
 
783
        uhashlength = atoi(short2str(vv[1]));
 
784
        if (vv[2]) {
 
785
            uhashwidth = atoi(short2str(vv[2]));
 
786
            if ((uhashwidth != sizeof(unsigned char)) && 
 
787
                (uhashwidth != sizeof(unsigned short)) && 
 
788
                (uhashwidth != sizeof(unsigned long)))
 
789
                uhashwidth = 0;
 
790
            if (vv[3])
 
791
                hashdebug = atoi(short2str(vv[3]));
 
792
        }
 
793
    }
 
794
 
 
795
    if (uhashwidth)
 
796
        hashwidth = uhashwidth;
 
797
    else {
 
798
        hashwidth = 0;
 
799
        for (pv = v->vec; *pv; pv++, hashwidth++)
 
800
            continue;
 
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);
 
807
        else
 
808
            hashwidth = sizeof(unsigned long);
 
809
    }
 
810
 
 
811
    if (uhashlength)
 
812
        hashlength = uhashlength;
 
813
    else
 
814
        hashlength = hashwidth * (8*64);/* "average" files per dir in path */
 
815
    
 
816
    if (xhash)
 
817
        xfree((ptr_t) xhash);
 
818
    xhash = (unsigned long *) xcalloc((size_t) (hashlength * hashwidth), 
 
819
                                      (size_t) 1);
 
820
#endif /* FASTHASH */
 
821
 
 
822
    (void) getusername(NULL);   /* flush the tilde cashe */
 
823
    tw_cmd_free();
 
824
    havhash = 1;
 
825
    if (v == NULL)
 
826
        return;
 
827
    for (pv = v->vec; *pv; pv++, i++) {
 
828
        if (!ABSOLUTEP(pv[0]))
 
829
            continue;
 
830
        dirp = opendir(short2str(*pv));
 
831
        if (dirp == NULL)
 
832
            continue;
 
833
#ifdef COMMENT                  /* this isn't needed.  opendir won't open
 
834
                                 * non-dirs */
 
835
        if (fstat(dirp->dd_fd, &stb) < 0 || !S_ISDIR(stb.st_mode)) {
 
836
            (void) closedir(dirp);
 
837
            continue;
 
838
        }
 
839
#endif
 
840
#ifdef WINNT
 
841
        is_windir = nt_check_if_windir(short2str(*pv));
 
842
#endif /* WINNT */
 
843
        while ((dp = readdir(dirp)) != NULL) {
 
844
#ifndef INTERIX
 
845
            if (dp->d_ino == 0)
 
846
                continue;
 
847
#endif
 
848
            if (dp->d_name[0] == '.' &&
 
849
                (dp->d_name[1] == '\0' ||
 
850
                 (dp->d_name[1] == '.' && dp->d_name[2] == '\0')))
 
851
                continue;
 
852
#ifdef WINNT
 
853
            nt_check_name_and_hash(is_windir, dp->d_name, i);
 
854
#else /* !WINNT */
 
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
 
858
             */
 
859
            {
 
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';
 
865
            }
 
866
#endif /* _UWIN */
 
867
# ifdef FASTHASH
 
868
            hashval = hashname(str2short(dp->d_name));
 
869
            bis(hashval, i);
 
870
            if (hashdebug & 1)
 
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);
 
875
            bis(xhash, hashval);
 
876
# endif /* FASTHASH */
 
877
            /* tw_add_comm_name (dp->d_name); */
 
878
#endif /* WINNT */
 
879
        }
 
880
        (void) closedir(dirp);
 
881
    }
 
882
}
 
883
 
 
884
/*ARGSUSED*/
 
885
void
 
886
dounhash(v, c)
 
887
    Char **v;
 
888
    struct command *c;
 
889
{
 
890
    USE(c);
 
891
    USE(v);
 
892
    havhash = 0;
 
893
#ifdef FASTHASH
 
894
    if (xhash) {
 
895
       xfree((ptr_t) xhash);
 
896
       xhash = NULL;
 
897
    }
 
898
#endif /* FASTHASH */
 
899
}
 
900
 
 
901
/*ARGSUSED*/
 
902
void
 
903
hashstat(v, c)
 
904
    Char **v;
 
905
    struct command *c;
 
906
{
 
907
    USE(c);
 
908
    USE(v);
 
909
#ifdef FASTHASH 
 
910
   if (havhash && hashlength && hashwidth)
 
911
      xprintf(CGETS(13, 2, "%d hash buckets of %d bits each\n"),
 
912
              hashlength, hashwidth*8);
 
913
   if (hashdebug)
 
914
      xprintf(CGETS(13, 3, "debug mask = 0x%08x\n"), hashdebug);
 
915
#endif /* FASTHASH */
 
916
#ifdef VFORK
 
917
   if (hits + misses)
 
918
      xprintf(CGETS(13, 4, "%d hits, %d misses, %d%%\n"),
 
919
              hits, misses, 100 * hits / (hits + misses));
 
920
#endif
 
921
}
 
922
 
 
923
 
 
924
/*
 
925
 * Hash a command name.
 
926
 */
 
927
static int
 
928
hashname(cp)
 
929
    register Char *cp;
 
930
{
 
931
    register long h;
 
932
 
 
933
    for (h = 0; *cp; cp++)
 
934
        h = hash(h, *cp);
 
935
    return ((int) h);
 
936
}
 
937
 
 
938
static int
 
939
iscommand(name)
 
940
    Char   *name;
 
941
{
 
942
    register Char **pv;
 
943
    register Char *sav;
 
944
    register struct varent *v;
 
945
    register bool slash = any(short2str(name), '/');
 
946
    register int hashval, i;
 
947
 
 
948
    v = adrof(STRpath);
 
949
    if (v == 0 || v->vec[0] == 0 || slash)
 
950
        pv = justabs;
 
951
    else
 
952
        pv = v->vec;
 
953
    sav = Strspl(STRslash, name);       /* / command name for postpending */
 
954
    hashval = havhash ? hashname(name) : 0;
 
955
    i = 0;
 
956
    do {
 
957
        if (!slash && ABSOLUTEP(pv[0]) && havhash) {
 
958
#ifdef FASTHASH
 
959
            if (!bit(hashval, i))
 
960
                goto cont;
 
961
#else /* OLDHASH */
 
962
            int hashval1 = hash(hashval, i);
 
963
            if (!bit(xhash, hashval1))
 
964
                goto cont;
 
965
#endif /* FASTHASH */
 
966
        }
 
967
        if (pv[0][0] == 0 || eq(pv[0], STRdot)) {       /* don't make ./xxx */
 
968
            if (executable(NULL, name, 0)) {
 
969
                xfree((ptr_t) sav);
 
970
                return i + 1;
 
971
            }
 
972
        }
 
973
        else {
 
974
            if (executable(*pv, sav, 0)) {
 
975
                xfree((ptr_t) sav);
 
976
                return i + 1;
 
977
            }
 
978
        }
 
979
cont:
 
980
        pv++;
 
981
        i++;
 
982
    } while (*pv);
 
983
    xfree((ptr_t) sav);
 
984
    return 0;
 
985
}
 
986
 
 
987
/* Also by:
 
988
 *  Andreas Luik <luik@isaak.isa.de>
 
989
 *  I S A  GmbH - Informationssysteme fuer computerintegrierte Automatisierung
 
990
 *  Azenberstr. 35
 
991
 *  D-7000 Stuttgart 1
 
992
 *  West-Germany
 
993
 * is the executable() routine below and changes to iscommand().
 
994
 * Thanks again!!
 
995
 */
 
996
 
 
997
/*
 
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...
 
1002
 */
 
1003
int
 
1004
executable(dir, name, dir_ok)
 
1005
    Char   *dir, *name;
 
1006
    bool    dir_ok;
 
1007
{
 
1008
    struct stat stbuf;
 
1009
    Char    path[MAXPATHLEN + 1];
 
1010
    char   *strname;
 
1011
#ifdef WINNT
 
1012
    int     nt_exetype;
 
1013
#endif /* WINNT */
 
1014
    (void) memset(path, 0, sizeof(path));
 
1015
 
 
1016
    if (dir && *dir) {
 
1017
        copyn(path, dir, MAXPATHLEN);
 
1018
        catn(path, name, MAXPATHLEN);
 
1019
#ifdef WINNT
 
1020
        {
 
1021
            char *ptr = short2str(path);
 
1022
            char *p2 = ptr;
 
1023
            int has_ext = 0;
 
1024
 
 
1025
            while (*ptr++)
 
1026
                continue;
 
1027
            --ptr;
 
1028
 
 
1029
            while(ptr > p2) { 
 
1030
                if (*ptr == '/')
 
1031
                    break;
 
1032
                if (*ptr == '.') {
 
1033
                    has_ext = 1;
 
1034
                    break;
 
1035
                }
 
1036
                ptr--;
 
1037
            }
 
1038
            if (!has_ext && (stat(p2, &stbuf) == -1))
 
1039
                catn(path, STRdotEXE, MAXPATHLEN);
 
1040
        }
 
1041
#endif /* WINNT */
 
1042
        strname = short2str(path);
 
1043
    }
 
1044
    else
 
1045
        strname = short2str(name);
 
1046
    
 
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 */
 
1051
#ifdef WINNT
 
1052
              (GetBinaryType(strname,&nt_exetype) ||
 
1053
              (stbuf.st_mode & (S_IXOTH | S_IXGRP | S_IXUSR)))
 
1054
#else /* !WINNT */
 
1055
              (stbuf.st_mode & (S_IXOTH | S_IXGRP | S_IXUSR)) &&
 
1056
              access(strname, X_OK) == 0
 
1057
#endif /* WINNT */
 
1058
        )));
 
1059
}
 
1060
 
 
1061
int
 
1062
tellmewhat(lexp, str)
 
1063
    struct wordent *lexp;
 
1064
    Char *str;
 
1065
{
 
1066
    register int i;
 
1067
    register struct biltins *bptr;
 
1068
    register struct wordent *sp = lexp->next;
 
1069
    bool    aliased = 0, found;
 
1070
    Char   *s0, *s1, *s2, *cmd;
 
1071
    Char    qc;
 
1072
 
 
1073
    if (adrof1(sp->word, &aliases)) {
 
1074
        alias(lexp);
 
1075
        sp = lexp->next;
 
1076
        aliased = 1;
 
1077
    }
 
1078
 
 
1079
    s0 = sp->word;              /* to get the memory freeing right... */
 
1080
 
 
1081
    /* handle quoted alias hack */
 
1082
    if ((*(sp->word) & (QUOTE | TRIM)) == QUOTE)
 
1083
        (sp->word)++;
 
1084
 
 
1085
    /* do quoting, if it hasn't been done */
 
1086
    s1 = s2 = sp->word;
 
1087
    while (*s2)
 
1088
        switch (*s2) {
 
1089
        case '\'':
 
1090
        case '"':
 
1091
            qc = *s2++;
 
1092
            while (*s2 && *s2 != qc)
 
1093
                *s1++ = *s2++ | QUOTE;
 
1094
            if (*s2)
 
1095
                s2++;
 
1096
            break;
 
1097
        case '\\':
 
1098
            if (*++s2)
 
1099
                *s1++ = *s2++ | QUOTE;
 
1100
            break;
 
1101
        default:
 
1102
            *s1++ = *s2++;
 
1103
        }
 
1104
    *s1 = '\0';
 
1105
 
 
1106
    for (bptr = bfunc; bptr < &bfunc[nbfunc]; bptr++) {
 
1107
        if (eq(sp->word, str2short(bptr->bname))) {
 
1108
            if (str == NULL) {
 
1109
                if (aliased)
 
1110
                    prlex(lexp);
 
1111
                xprintf(CGETS(13, 5, "%S: shell built-in command.\n"),
 
1112
                              sp->word);
 
1113
                flush();
 
1114
            }
 
1115
            else 
 
1116
                (void) Strcpy(str, sp->word);
 
1117
            sp->word = s0;      /* we save and then restore this */
 
1118
            return TRUE;
 
1119
        }
 
1120
    }
 
1121
#ifdef WINNT
 
1122
    for (bptr = nt_bfunc; bptr < &nt_bfunc[nt_nbfunc]; bptr++) {
 
1123
        if (eq(sp->word, str2short(bptr->bname))) {
 
1124
            if (str == NULL) {
 
1125
                if (aliased)
 
1126
                    prlex(lexp);
 
1127
                xprintf(CGETS(13, 5, "%S: shell built-in command.\n"),
 
1128
                              sp->word);
 
1129
                flush();
 
1130
            }
 
1131
            else 
 
1132
                (void) Strcpy(str, sp->word);
 
1133
            sp->word = s0;      /* we save and then restore this */
 
1134
            return TRUE;
 
1135
        }
 
1136
    }
 
1137
#endif /* WINNT*/
 
1138
 
 
1139
    sp->word = cmd = globone(sp->word, G_IGNORE);
 
1140
 
 
1141
    if ((i = iscommand(sp->word)) != 0) {
 
1142
        register Char **pv;
 
1143
        register struct varent *v;
 
1144
        bool    slash = any(short2str(sp->word), '/');
 
1145
 
 
1146
        v = adrof(STRpath);
 
1147
        if (v == 0 || v->vec[0] == 0 || slash)
 
1148
            pv = justabs;
 
1149
        else
 
1150
            pv = v->vec;
 
1151
 
 
1152
        while (--i)
 
1153
            pv++;
 
1154
        if (pv[0][0] == 0 || eq(pv[0], STRdot)) {
 
1155
            if (!slash) {
 
1156
                sp->word = Strspl(STRdotsl, sp->word);
 
1157
                prlex(lexp);
 
1158
                xfree((ptr_t) sp->word);
 
1159
            }
 
1160
            else
 
1161
                prlex(lexp);
 
1162
        }
 
1163
        else {
 
1164
            s1 = Strspl(*pv, STRslash);
 
1165
            sp->word = Strspl(s1, sp->word);
 
1166
            xfree((ptr_t) s1);
 
1167
            if (str == NULL)
 
1168
                prlex(lexp);
 
1169
            else
 
1170
                (void) Strcpy(str, sp->word);
 
1171
            xfree((ptr_t) sp->word);
 
1172
        }
 
1173
        found = 1;
 
1174
    }
 
1175
    else {
 
1176
        if (str == NULL) {
 
1177
            if (aliased)
 
1178
                prlex(lexp);
 
1179
            xprintf(CGETS(13, 6, "%S: Command not found.\n"), sp->word);
 
1180
            flush();
 
1181
        }
 
1182
        else
 
1183
            (void) Strcpy(str, sp->word);
 
1184
        found = 0;
 
1185
    }
 
1186
    sp->word = s0;              /* we save and then restore this */
 
1187
    xfree((ptr_t) cmd);
 
1188
    return found;
 
1189
}
 
1190
 
 
1191
/*
 
1192
 * Builtin to look at and list all places a command may be defined:
 
1193
 * aliases, shell builtins, and the path.
 
1194
 *
 
1195
 * Marc Horowitz <marc@mit.edu>
 
1196
 * MIT Student Information Processing Board
 
1197
 */
 
1198
 
 
1199
/*ARGSUSED*/
 
1200
void
 
1201
dowhere(v, c)
 
1202
    register Char **v;
 
1203
    struct command *c;
 
1204
{
 
1205
    int found = 1;
 
1206
    USE(c);
 
1207
    for (v++; *v; v++)
 
1208
        found &= find_cmd(*v, 1);
 
1209
    /* Make status nonzero if any command is not found. */
 
1210
    if (!found)
 
1211
      set(STRstatus, Strsave(STR1), VAR_READWRITE);
 
1212
}
 
1213
 
 
1214
int
 
1215
find_cmd(cmd, prt)
 
1216
    Char *cmd;
 
1217
    int prt;
 
1218
{
 
1219
    struct varent *var;
 
1220
    struct biltins *bptr;
 
1221
    Char **pv;
 
1222
    Char *sv;
 
1223
    int hashval, i, ex, rval = 0;
 
1224
 
 
1225
    if (prt && any(short2str(cmd), '/')) {
 
1226
        xprintf(CGETS(13, 7, "where: / in command makes no sense\n"));
 
1227
        return rval;
 
1228
    }
 
1229
 
 
1230
    /* first, look for an alias */
 
1231
 
 
1232
    if (prt && adrof1(cmd, &aliases)) {
 
1233
        if ((var = adrof1(cmd, &aliases)) != NULL) {
 
1234
            xprintf(CGETS(13, 8, "%S is aliased to "), cmd);
 
1235
            blkpr(var->vec);
 
1236
            xputchar('\n');
 
1237
            rval = 1;
 
1238
        }
 
1239
    }
 
1240
 
 
1241
    /* next, look for a shell builtin */
 
1242
 
 
1243
    for (bptr = bfunc; bptr < &bfunc[nbfunc]; bptr++) {
 
1244
        if (eq(cmd, str2short(bptr->bname))) {
 
1245
            rval = 1;
 
1246
            if (prt)
 
1247
                xprintf(CGETS(13, 9, "%S is a shell built-in\n"), cmd);
 
1248
            else
 
1249
                return rval;
 
1250
        }
 
1251
    }
 
1252
#ifdef WINNT
 
1253
    for (bptr = nt_bfunc; bptr < &nt_bfunc[nt_nbfunc]; bptr++) {
 
1254
        if (eq(cmd, str2short(bptr->bname))) {
 
1255
            rval = 1;
 
1256
            if (prt)
 
1257
                xprintf(CGETS(13, 9, "%S is a shell built-in\n"), cmd);
 
1258
            else
 
1259
                return rval;
 
1260
        }
 
1261
    }
 
1262
#endif /* WINNT*/
 
1263
 
 
1264
    /* last, look through the path for the command */
 
1265
 
 
1266
    if ((var = adrof(STRpath)) == NULL)
 
1267
        return rval;
 
1268
 
 
1269
    hashval = havhash ? hashname(cmd) : 0;
 
1270
 
 
1271
    sv = Strspl(STRslash, cmd);
 
1272
 
 
1273
    for (pv = var->vec, i = 0; *pv; pv++, i++) {
 
1274
        if (havhash && !eq(*pv, STRdot)) {
 
1275
#ifdef FASTHASH
 
1276
            if (!bit(hashval, i))
 
1277
                continue;
 
1278
#else /* OLDHASH */
 
1279
            int hashval1 = hash(hashval, i);
 
1280
            if (!bit(xhash, hashval1))
 
1281
                continue;
 
1282
#endif /* FASTHASH */
 
1283
        }
 
1284
        ex = executable(*pv, sv, 0);
 
1285
#ifdef FASTHASH
 
1286
        if (!ex && (hashdebug & 2)) {
 
1287
            xprintf(CGETS(13, 10, "hash miss: "));
 
1288
            ex = 1;     /* Force printing */
 
1289
        }
 
1290
#endif /* FASTHASH */
 
1291
        if (ex) {
 
1292
            rval = 1;
 
1293
            if (prt) {
 
1294
                xprintf("%S/", *pv);
 
1295
                xprintf("%S\n", cmd);
 
1296
            }
 
1297
            else
 
1298
                return rval;
 
1299
        }
 
1300
    }
 
1301
    xfree((ptr_t) sv);
 
1302
    return rval;
 
1303
}
 
1304
 
 
1305
#ifdef WINNT
 
1306
int
 
1307
nt_check_if_windir(path)
 
1308
    char *path;
 
1309
{
 
1310
    char windir[MAX_PATH];
 
1311
 
 
1312
    (void)GetWindowsDirectory(windir, sizeof(windir));
 
1313
    windir[2] = '/';
 
1314
 
 
1315
    return (strstr(path, windir) != NULL);
 
1316
}
 
1317
 
 
1318
void
 
1319
nt_check_name_and_hash(is_windir, file, i)
 
1320
    int is_windir;
 
1321
    char *file;
 
1322
    int i;
 
1323
{
 
1324
    char name_only[MAX_PATH];
 
1325
    char *tmp = (char *)strrchr(file, '.');
 
1326
    char uptmp[5], *nameptr, *np2;
 
1327
    int icount, hashval;
 
1328
 
 
1329
    if(!tmp || tmp[4]) 
 
1330
        goto nodot;
 
1331
 
 
1332
    for (icount = 0; icount < 4; icount++)
 
1333
        uptmp[icount] = toupper(tmp[icount]);
 
1334
    uptmp[4]=0;
 
1335
 
 
1336
    if (is_windir)
 
1337
        if((uptmp[1] != 'E') || (uptmp[2] != 'X') || (uptmp[3] != 'E'))
 
1338
            return;
 
1339
    (void) memset(name_only, 0, MAX_PATH);
 
1340
    nameptr = file;
 
1341
    np2 = name_only;
 
1342
    while(nameptr != tmp) {
 
1343
        *np2++= tolower(*nameptr);
 
1344
        nameptr++;
 
1345
    }
 
1346
    hashval = hashname(str2short(name_only));
 
1347
    bis(hashval, i);
 
1348
nodot:
 
1349
    hashval = hashname(str2short(file));
 
1350
    bis(hashval, i);
 
1351
}
 
1352
int hashval_extern(cp)
 
1353
        Char *cp;
 
1354
{
 
1355
        return havhash?hashname(cp):0;
 
1356
}
 
1357
int bit_extern(val,i)
 
1358
        int val;
 
1359
        int i;
 
1360
{
 
1361
        return bit(val,i);
 
1362
}
 
1363
#endif /* WINNT */