aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Andersen <andersen@codepoet.org>2001-07-02 17:27:21 +0000
committerEric Andersen <andersen@codepoet.org>2001-07-02 17:27:21 +0000
commit2870d964f8c849d00be20927085f45a30e4e8e53 (patch)
tree25f18218a6fd6dfc976f8d6886aa0be972b927bb
parent8f6978405ddf1c7e280b097b655b6acbb8aa46ab (diff)
downloadbusybox-w32-2870d964f8c849d00be20927085f45a30e4e8e53.tar.gz
busybox-w32-2870d964f8c849d00be20927085f45a30e4e8e53.tar.bz2
busybox-w32-2870d964f8c849d00be20927085f45a30e4e8e53.zip
Some updates to ash from vodz. Makes ash smaller. I made a few
changes, esp describing all the current ash configuration options. Now ash adds 66k in the default configuration.
-rw-r--r--ash.c5459
-rw-r--r--ash.h1225
-rw-r--r--shell/ash.c5459
3 files changed, 5576 insertions, 6567 deletions
diff --git a/ash.c b/ash.c
index 7d394b617..489ccaa95 100644
--- a/ash.c
+++ b/ash.c
@@ -3,7 +3,7 @@
3 * ash shell port for busybox 3 * ash shell port for busybox
4 * 4 *
5 * Copyright (c) 1989, 1991, 1993, 1994 5 * Copyright (c) 1989, 1991, 1993, 1994
6 * The Regents of the University of California. All rights reserved. 6 * The Regents of the University of California. All rights reserved.
7 * 7 *
8 * This code is derived from software contributed to Berkeley by 8 * This code is derived from software contributed to Berkeley by
9 * Kenneth Almquist. 9 * Kenneth Almquist.
@@ -22,20 +22,74 @@
22 * along with this program; if not, write to the Free Software 22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 * 24 *
25 * This version of ash is adapted from the source in Debian's ash 0.3.8-5 25 * This version of ash is adapted from the source in Debian's ash 0.3.8-5
26 * package. 26 * package.
27 *
28 * Modified by Erik Andersen <andersee@debian.org> and
29 * Vladimir Oleynik <vodz@usa.net> to be used in busybox
27 * 30 *
28 * Modified by Erik Andersen <andersee@debian.org> to be used in busybox.
29 * 31 *
30 * Original copyright notice is retained at the end of this file. 32 * Original copyright notice is retained at the end of this file.
31 */ 33 */
32 34
33#undef _GNU_SOURCE 35
36/* These defines allow you to adjust the feature set to be compiled
37 * into the ash shell. As a rule, enabling these options will make
38 * ash get bigger... With all of these options off, ash adds about
39 * 62k to busybox on an x86 system.*/
40
41
42
43/* Enable job control. This allows you to run jobs in the background,
44 * which is great when ash is being used as an interactive shell, but
45 * it completely useless for is all you are doing is running scripts.
46 * This adds about 2.5k on an x86 system. */
47#define JOBS
48
49/* This enables alias support in ash. If you want to support things
50 * like "alias ls='ls -l'" with ash, enable this. This is only useful
51 * when ash is used as an intractive shell. This adds about 1.5k */
52#define ASH_ALIAS
53
54/* If you need ash to act as a full Posix shell, with full math
55 * support, enable this. This option needs some work, since it
56 * doesn't compile right now... */
57#undef ASH_MATH_SUPPORT
58
59/* This shell builtin is used to indicate how the shell would interpret
60 * what you give it. This command is only useful when debugging, and
61 * is obsolete anyways. Adds about 670 bytes... You probably want to
62 * leave this disabled. */
34#undef ASH_TYPE 63#undef ASH_TYPE
64
65/* Getopts is used by shell procedures to parse positional parameters.
66 * You probably want to leave this disabled, and use the busybox getopt
67 * applet if you want to do this sort of thing. There are some scripts
68 * out there that use it, so it you need it, enable. Most people will
69 * leave this disabled. This adds 1k on an x86 system. */
35#undef ASH_GETOPTS 70#undef ASH_GETOPTS
36#undef ASH_MATH_SUPPORT 71
72/* This allows you to override shell builtins and use whatever is on
73 * the filesystem. This is most useful when ash is acting as a
74 * standalone shell. Adds about 320 bytes. */
75#undef ASH_CMDCMD
76
77/* This makes a few common apps that are usually part of busybox
78 * anyways to be used as builtins. This may cause these builtins to be
79 * a little bit faster, but leaving this disabled will save you 2k. */
80#undef ASH_BBAPPS_AS_BUILTINS
81
82/* Enable this to compile in extra debugging noise. When debugging is
83 * on, debugging info will be written to $HOME/trace and a quit signal
84 * will generate a core dump. */
85#undef DEBUG
86
87
88
89/* These are here to work with glibc -- Don't change these... */
37#undef FNMATCH_BROKEN 90#undef FNMATCH_BROKEN
38#undef GLOB_BROKEN 91#undef GLOB_BROKEN
92#undef _GNU_SOURCE
39 93
40#include <assert.h> 94#include <assert.h>
41#include <ctype.h> 95#include <ctype.h>
@@ -72,39 +126,1282 @@
72#include <glob.h> 126#include <glob.h>
73#endif 127#endif
74 128
75#if JOBS 129#ifdef JOBS
76#include <termios.h> 130#include <termios.h>
77#undef CEOF /* syntax.h redefines this */
78#endif 131#endif
79 132
80#include "cmdedit.h"
81#include "busybox.h" 133#include "busybox.h"
82#include "ash.h" 134#include "cmdedit.h"
135
136/* if BB_PWD is defined, then disable ASH_PWD to save space */
137#ifdef BB_PWD
138#undef ASH_PWD
139#endif
140
141
142/*
143 * This file was generated by the mksyntax program.
144 */
145
146/* Syntax classes */
147#define CWORD 0 /* character is nothing special */
148#define CNL 1 /* newline character */
149#define CBACK 2 /* a backslash character */
150#define CSQUOTE 3 /* single quote */
151#define CDQUOTE 4 /* double quote */
152#define CENDQUOTE 5 /* a terminating quote */
153#define CBQUOTE 6 /* backwards single quote */
154#define CVAR 7 /* a dollar sign */
155#define CENDVAR 8 /* a '}' character */
156#define CLP 9 /* a left paren in arithmetic */
157#define CRP 10 /* a right paren in arithmetic */
158#define CENDFILE 11 /* end of file */
159#define CCTL 12 /* like CWORD, except it must be escaped */
160#define CSPCL 13 /* these terminate a word */
161#define CIGN 14 /* character should be ignored */
162
163/* Syntax classes for is_ functions */
164#define ISDIGIT 01 /* a digit */
165#define ISUPPER 02 /* an upper case letter */
166#define ISLOWER 04 /* a lower case letter */
167#define ISUNDER 010 /* an underscore */
168#define ISSPECL 020 /* the name of a special parameter */
169
170#define SYNBASE 130
171#define PEOF -130
172
173#define PEOA -129
174
175#define TEOF 0
176#define TNL 1
177#define TSEMI 2
178#define TBACKGND 3
179#define TAND 4
180#define TOR 5
181#define TPIPE 6
182#define TLP 7
183#define TRP 8
184#define TENDCASE 9
185#define TENDBQUOTE 10
186#define TREDIR 11
187#define TWORD 12
188#define TASSIGN 13
189#define TNOT 14
190#define TCASE 15
191#define TDO 16
192#define TDONE 17
193#define TELIF 18
194#define TELSE 19
195#define TESAC 20
196#define TFI 21
197#define TFOR 22
198#define TIF 23
199#define TIN 24
200#define TTHEN 25
201#define TUNTIL 26
202#define TWHILE 27
203#define TBEGIN 28
204#define TEND 29
205
206
207#define BASESYNTAX (basesyntax + SYNBASE)
208#define DQSYNTAX (dqsyntax + SYNBASE)
209#define SQSYNTAX (sqsyntax + SYNBASE)
210#define ARISYNTAX (arisyntax + SYNBASE)
211
212/* control characters in argument strings */
213#define CTLESC '\201'
214#define CTLVAR '\202'
215#define CTLENDVAR '\203'
216#define CTLBACKQ '\204'
217#define CTLQUOTE 01 /* ored with CTLBACKQ code if in quotes */
218/* CTLBACKQ | CTLQUOTE == '\205' */
219#define CTLARI '\206'
220#define CTLENDARI '\207'
221#define CTLQUOTEMARK '\210'
222
223#define is_digit(c) ((((unsigned char)(c)) - '0') <= 9)
224#define is_alpha(c) (((c) < CTLESC || (c) > CTLENDARI) && isalpha((unsigned char) (c)))
225#define is_name(c) (((c) < CTLESC || (c) > CTLENDARI) && ((c) == '_' || isalpha((unsigned char) (c))))
226#define is_in_name(c) (((c) < CTLESC || (c) > CTLENDARI) && ((c) == '_' || isalnum((unsigned char) (c))))
227#define is_special(c) ((is_type+SYNBASE)[c] & (ISSPECL|ISDIGIT))
228#define digit_val(c) ((c) - '0')
83 229
84 230
85#define _DIAGASSERT(x) 231#define _DIAGASSERT(x)
86 232
87#define ATABSIZE 39 233#define ATABSIZE 39
88 234
89#define S_DFL 1 /* default signal handling (SIG_DFL) */ 235#define S_DFL 1 /* default signal handling (SIG_DFL) */
90#define S_CATCH 2 /* signal is caught */ 236#define S_CATCH 2 /* signal is caught */
91#define S_IGN 3 /* signal is ignored (SIG_IGN) */ 237#define S_IGN 3 /* signal is ignored (SIG_IGN) */
92#define S_HARD_IGN 4 /* signal is ignored permenantly */ 238#define S_HARD_IGN 4 /* signal is ignored permenantly */
93#define S_RESET 5 /* temporary - to reset a hard ignored sig */ 239#define S_RESET 5 /* temporary - to reset a hard ignored sig */
240
241
242/* variable substitution byte (follows CTLVAR) */
243#define VSTYPE 0x0f /* type of variable substitution */
244#define VSNUL 0x10 /* colon--treat the empty string as unset */
245#define VSQUOTE 0x80 /* inside double quotes--suppress splitting */
246
247/* values of VSTYPE field */
248#define VSNORMAL 0x1 /* normal variable: $var or ${var} */
249#define VSMINUS 0x2 /* ${var-text} */
250#define VSPLUS 0x3 /* ${var+text} */
251#define VSQUESTION 0x4 /* ${var?message} */
252#define VSASSIGN 0x5 /* ${var=text} */
253#define VSTRIMLEFT 0x6 /* ${var#pattern} */
254#define VSTRIMLEFTMAX 0x7 /* ${var##pattern} */
255#define VSTRIMRIGHT 0x8 /* ${var%pattern} */
256#define VSTRIMRIGHTMAX 0x9 /* ${var%%pattern} */
257#define VSLENGTH 0xa /* ${#var} */
258
259/* flags passed to redirect */
260#define REDIR_PUSH 01 /* save previous values of file descriptors */
261#define REDIR_BACKQ 02 /* save the command output in memory */
262
263/*
264 * BSD setjmp saves the signal mask, which violates ANSI C and takes time,
265 * so we use _setjmp instead.
266 */
267
268#if !defined(__GLIBC__)
269#define setjmp(jmploc) _setjmp(jmploc)
270#define longjmp(jmploc, val) _longjmp(jmploc, val)
271#endif
272
273/*
274 * Most machines require the value returned from malloc to be aligned
275 * in some way. The following macro will get this right on many machines.
276 */
277
278#ifndef ALIGN
279union align {
280 int i;
281 char *cp;
282};
283
284#define ALIGN(nbytes) (((nbytes) + sizeof(union align) - 1) & ~(sizeof(union align) - 1))
285#endif
286
287#ifdef BB_LOCALE_SUPPORT
288#include <locale.h>
289static void change_lc_all(const char *value);
290static void change_lc_ctype(const char *value);
291#endif
292
293/*
294 * These macros allow the user to suspend the handling of interrupt signals
295 * over a period of time. This is similar to SIGHOLD to or sigblock, but
296 * much more efficient and portable. (But hacking the kernel is so much
297 * more fun than worrying about efficiency and portability. :-))
298 */
299
300static void onint (void);
301static volatile int suppressint;
302static volatile int intpending;
303
304#define INTOFF suppressint++
305#ifdef ASH_BBAPPS_AS_BUILTINS
306#define INTON { if (--suppressint == 0 && intpending) onint(); }
307#else
308static void __inton (void);
309#define INTON __inton()
310#endif
311#define FORCEINTON {suppressint = 0; if (intpending) onint();}
312#define CLEAR_PENDING_INT intpending = 0
313#define int_pending() intpending
314
315
316typedef void *pointer;
317#ifndef NULL
318#define NULL (void *)0
319#endif
320
321static inline pointer ckmalloc (int sz) { return xmalloc(sz); }
322static inline pointer ckrealloc(void *p, int sz) { return xrealloc(p, sz); }
323static inline char * savestr (const char *s) { return xstrdup(s); }
324
325static pointer stalloc (int);
326static void stunalloc (pointer);
327static void ungrabstackstr (char *, char *);
328static char * growstackstr(void);
329static char *sstrdup (const char *);
330
331/*
332 * Parse trees for commands are allocated in lifo order, so we use a stack
333 * to make this more efficient, and also to avoid all sorts of exception
334 * handling code to handle interrupts in the middle of a parse.
335 *
336 * The size 504 was chosen because the Ultrix malloc handles that size
337 * well.
338 */
339
340#define MINSIZE 504 /* minimum size of a block */
341
342
343struct stack_block {
344 struct stack_block *prev;
345 char space[MINSIZE];
346};
347
348static struct stack_block stackbase;
349static struct stack_block *stackp = &stackbase;
350static struct stackmark *markp;
351static char *stacknxt = stackbase.space;
352static int stacknleft = MINSIZE;
353
354
355#define equal(s1, s2) (strcmp(s1, s2) == 0)
356
357#define stackblock() stacknxt
358#define stackblocksize() stacknleft
359#define STARTSTACKSTR(p) p = stackblock(), sstrnleft = stackblocksize()
360#define STPUTC(c, p) (--sstrnleft >= 0? (*p++ = (c)) : (p = growstackstr(), *p++ = (c)))
361#define CHECKSTRSPACE(n, p) { if (sstrnleft < n) p = makestrspace(n); }
362#define USTPUTC(c, p) (--sstrnleft, *p++ = (c))
363#define STACKSTRNUL(p) (sstrnleft == 0? (p = growstackstr(), *p = '\0') : (*p = '\0'))
364#define STUNPUTC(p) (++sstrnleft, --p)
365#define STTOPC(p) p[-1]
366#define STADJUST(amount, p) (p += (amount), sstrnleft -= (amount))
367#define grabstackstr(p) stalloc(stackblocksize() - sstrnleft)
368
369#define ckfree(p) free((pointer)(p))
370
371static char * makestrspace(size_t newlen);
372
373#ifdef DEBUG
374#define TRACE(param) trace param
375static void trace (const char *, ...);
376static void trargs (char **);
377static void showtree (union node *);
378static void trputc (int);
379static void trputs (const char *);
380static void opentrace (void);
381#else
382#define TRACE(param)
383#endif
384
385#define NSEMI 0
386#define NCMD 1
387#define NPIPE 2
388#define NREDIR 3
389#define NBACKGND 4
390#define NSUBSHELL 5
391#define NAND 6
392#define NOR 7
393#define NIF 8
394#define NWHILE 9
395#define NUNTIL 10
396#define NFOR 11
397#define NCASE 12
398#define NCLIST 13
399#define NDEFUN 14
400#define NARG 15
401#define NTO 16
402#define NFROM 17
403#define NFROMTO 18
404#define NAPPEND 19
405#define NTOOV 20
406#define NTOFD 21
407#define NFROMFD 22
408#define NHERE 23
409#define NXHERE 24
410#define NNOT 25
411
412/*
413 * expandarg() flags
414 */
415#define EXP_FULL 0x1 /* perform word splitting & file globbing */
416#define EXP_TILDE 0x2 /* do normal tilde expansion */
417#define EXP_VARTILDE 0x4 /* expand tildes in an assignment */
418#define EXP_REDIR 0x8 /* file glob for a redirection (1 match only) */
419#define EXP_CASE 0x10 /* keeps quotes around for CASE pattern */
420#define EXP_RECORD 0x20 /* need to record arguments for ifs breakup */
421
422
423#define NOPTS 16
424
425static char optet_vals[NOPTS];
426
427static const char * const optlist[NOPTS] = {
428 "e" "errexit",
429 "f" "noglob",
430 "I" "ignoreeof",
431 "i" "interactive",
432 "m" "monitor",
433 "n" "noexec",
434 "s" "stdin",
435 "x" "xtrace",
436 "v" "verbose",
437 "V" "vi",
438 "E" "emacs",
439 "C" "noclobber",
440 "a" "allexport",
441 "b" "notify",
442 "u" "nounset",
443 "q" "quietprofile"
444};
445
446#define optent_name(optent) (optent+1)
447#define optent_letter(optent) optent[0]
448#define optent_val(optent) optet_vals[optent]
449
450#define eflag optent_val(0)
451#define fflag optent_val(1)
452#define Iflag optent_val(2)
453#define iflag optent_val(3)
454#define mflag optent_val(4)
455#define nflag optent_val(5)
456#define sflag optent_val(6)
457#define xflag optent_val(7)
458#define vflag optent_val(8)
459#define Vflag optent_val(9)
460#define Eflag optent_val(10)
461#define Cflag optent_val(11)
462#define aflag optent_val(12)
463#define bflag optent_val(13)
464#define uflag optent_val(14)
465#define qflag optent_val(15)
466
467
468/* Mode argument to forkshell. Don't change FORK_FG or FORK_BG. */
469#define FORK_FG 0
470#define FORK_BG 1
471#define FORK_NOJOB 2
472
473
474struct nbinary {
475 int type;
476 union node *ch1;
477 union node *ch2;
478};
479
480
481struct ncmd {
482 int type;
483 int backgnd;
484 union node *assign;
485 union node *args;
486 union node *redirect;
487};
488
489
490struct npipe {
491 int type;
492 int backgnd;
493 struct nodelist *cmdlist;
494};
495
496
497struct nredir {
498 int type;
499 union node *n;
500 union node *redirect;
501};
502
503
504struct nif {
505 int type;
506 union node *test;
507 union node *ifpart;
508 union node *elsepart;
509};
510
511
512struct nfor {
513 int type;
514 union node *args;
515 union node *body;
516 char *var;
517};
518
519
520struct ncase {
521 int type;
522 union node *expr;
523 union node *cases;
524};
525
526
527struct nclist {
528 int type;
529 union node *next;
530 union node *pattern;
531 union node *body;
532};
533
534
535struct narg {
536 int type;
537 union node *next;
538 char *text;
539 struct nodelist *backquote;
540};
541
542
543struct nfile {
544 int type;
545 union node *next;
546 int fd;
547 union node *fname;
548 char *expfname;
549};
550
551
552struct ndup {
553 int type;
554 union node *next;
555 int fd;
556 int dupfd;
557 union node *vname;
558};
559
560
561struct nhere {
562 int type;
563 union node *next;
564 int fd;
565 union node *doc;
566};
567
568
569struct nnot {
570 int type;
571 union node *com;
572};
573
574
575union node {
576 int type;
577 struct nbinary nbinary;
578 struct ncmd ncmd;
579 struct npipe npipe;
580 struct nredir nredir;
581 struct nif nif;
582 struct nfor nfor;
583 struct ncase ncase;
584 struct nclist nclist;
585 struct narg narg;
586 struct nfile nfile;
587 struct ndup ndup;
588 struct nhere nhere;
589 struct nnot nnot;
590};
591
592
593struct nodelist {
594 struct nodelist *next;
595 union node *n;
596};
597
598struct backcmd { /* result of evalbackcmd */
599 int fd; /* file descriptor to read from */
600 char *buf; /* buffer */
601 int nleft; /* number of chars in buffer */
602 struct job *jp; /* job structure for command */
603};
604
605struct cmdentry {
606 int cmdtype;
607 union param {
608 int index;
609 union node *func;
610 const struct builtincmd *cmd;
611 } u;
612};
613
614struct strlist {
615 struct strlist *next;
616 char *text;
617};
618
619
620struct arglist {
621 struct strlist *list;
622 struct strlist **lastp;
623};
624
625struct strpush {
626 struct strpush *prev; /* preceding string on stack */
627 char *prevstring;
628 int prevnleft;
629#ifdef ASH_ALIAS
630 struct alias *ap; /* if push was associated with an alias */
631#endif
632 char *string; /* remember the string since it may change */
633};
634
635struct parsefile {
636 struct parsefile *prev; /* preceding file on stack */
637 int linno; /* current line */
638 int fd; /* file descriptor (or -1 if string) */
639 int nleft; /* number of chars left in this line */
640 int lleft; /* number of chars left in this buffer */
641 char *nextc; /* next char in buffer */
642 char *buf; /* input buffer */
643 struct strpush *strpush; /* for pushing strings at this level */
644 struct strpush basestrpush; /* so pushing one is fast */
645};
646
647struct stackmark {
648 struct stack_block *stackp;
649 char *stacknxt;
650 int stacknleft;
651 struct stackmark *marknext;
652};
653
654struct shparam {
655 int nparam; /* # of positional parameters (without $0) */
656 unsigned char malloc; /* if parameter list dynamically allocated */
657 char **p; /* parameter list */
658 int optind; /* next parameter to be processed by getopts */
659 int optoff; /* used by getopts */
660};
661
662struct output {
663#ifdef USE_GLIBC_STDIO
664 FILE *stream;
665#endif
666 char *nextc;
667 int nleft;
668 char *buf;
669 int bufsize;
670 int fd;
671 short flags;
672};
673
674#define OUTBUFSIZ BUFSIZ
675#define MEM_OUT -3 /* output to dynamically allocated memory */
676
677
678#ifdef USE_GLIBC_STDIO
679static struct output output = {NULL, NULL, 0, NULL, 0, 1, 0};
680static struct output errout = {NULL, NULL, 0, NULL, 0, 2, 0};
681static struct output memout = {NULL, NULL, 0, NULL, 0, MEM_OUT, 0};
682#else
683static struct output output = {NULL, 0, NULL, OUTBUFSIZ, 1, 0};
684static struct output errout = {NULL, 0, NULL, 0, 2, 0};
685static struct output memout = {NULL, 0, NULL, 0, MEM_OUT, 0};
686#endif
687static struct output *out1 = &output;
688static struct output *out2 = &errout;
689
690#ifndef USE_GLIBC_STDIO
691static void outcslow (char, struct output *);
692#endif
693static void flushall (void);
694static void flushout (struct output *);
695static void freestdout (void);
696static void outfmt (struct output *, const char *, ...)
697 __attribute__((__format__(__printf__,2,3)));
698static void out1fmt (const char *, ...)
699 __attribute__((__format__(__printf__,1,2)));
700static void fmtstr (char *, size_t, const char *, ...)
701 __attribute__((__format__(__printf__,3,4)));
702#ifndef USE_GLIBC_STDIO
703static void doformat (struct output *, const char *, va_list);
704#endif
705static int xwrite (int, const char *, int);
706#ifdef USE_GLIBC_STDIO
707static void initstreams (void);
708static void openmemout (void);
709static int __closememout (void);
710#endif
711
712static void outstr(const char *p, struct output *file);
713
714#define OUTPUT_ERR 01 /* error occurred on output */
715
716#ifdef USE_GLIBC_STDIO
717#define outc(c, o) putc((c), (o)->stream)
718#define doformat(d, f, a) vfprintf((d)->stream, (f), (a))
719#else
720#define outc(c, file) (--(file)->nleft < 0? outcslow((c), (file)) : (*(file)->nextc = (c), (file)->nextc++))
721#endif
722#define out1c(c) outc((c), out1)
723#define out2c(c) outc((c), out2)
724#define out1str(s) outstr((s), out1)
725#define out2str(s) outstr((s), out2)
726#define outerr(f) ((f)->flags & OUTPUT_ERR)
727
728/* syntax table used when not in quotes */
729static const char basesyntax[257] = {
730 CENDFILE, CSPCL, CWORD, CCTL,
731 CCTL, CCTL, CCTL, CCTL,
732 CCTL, CCTL, CCTL, CWORD,
733 CWORD, CWORD, CWORD, CWORD,
734 CWORD, CWORD, CWORD, CWORD,
735 CWORD, CWORD, CWORD, CWORD,
736 CWORD, CWORD, CWORD, CWORD,
737 CWORD, CWORD, CWORD, CWORD,
738 CWORD, CWORD, CWORD, CWORD,
739 CWORD, CWORD, CWORD, CWORD,
740 CWORD, CWORD, CWORD, CWORD,
741 CWORD, CWORD, CWORD, CWORD,
742 CWORD, CWORD, CWORD, CWORD,
743 CWORD, CWORD, CWORD, CWORD,
744 CWORD, CWORD, CWORD, CWORD,
745 CWORD, CWORD, CWORD, CWORD,
746 CWORD, CWORD, CWORD, CWORD,
747 CWORD, CWORD, CWORD, CWORD,
748 CWORD, CWORD, CWORD, CWORD,
749 CWORD, CWORD, CWORD, CWORD,
750 CWORD, CWORD, CWORD, CWORD,
751 CWORD, CWORD, CWORD, CWORD,
752 CWORD, CWORD, CWORD, CWORD,
753 CWORD, CWORD, CWORD, CWORD,
754 CWORD, CWORD, CWORD, CWORD,
755 CWORD, CWORD, CWORD, CWORD,
756 CWORD, CWORD, CWORD, CWORD,
757 CWORD, CWORD, CWORD, CWORD,
758 CWORD, CWORD, CWORD, CWORD,
759 CWORD, CWORD, CWORD, CWORD,
760 CWORD, CWORD, CWORD, CWORD,
761 CWORD, CWORD, CWORD, CWORD,
762 CWORD, CWORD, CWORD, CWORD,
763 CWORD, CWORD, CWORD, CWORD,
764 CWORD, CWORD, CWORD, CSPCL,
765 CNL, CWORD, CWORD, CWORD,
766 CWORD, CWORD, CWORD, CWORD,
767 CWORD, CWORD, CWORD, CWORD,
768 CWORD, CWORD, CWORD, CWORD,
769 CWORD, CWORD, CWORD, CWORD,
770 CWORD, CWORD, CSPCL, CWORD,
771 CDQUOTE, CWORD, CVAR, CWORD,
772 CSPCL, CSQUOTE, CSPCL, CSPCL,
773 CWORD, CWORD, CWORD, CWORD,
774 CWORD, CWORD, CWORD, CWORD,
775 CWORD, CWORD, CWORD, CWORD,
776 CWORD, CWORD, CWORD, CWORD,
777 CWORD, CSPCL, CSPCL, CWORD,
778 CSPCL, CWORD, CWORD, CWORD,
779 CWORD, CWORD, CWORD, CWORD,
780 CWORD, CWORD, CWORD, CWORD,
781 CWORD, CWORD, CWORD, CWORD,
782 CWORD, CWORD, CWORD, CWORD,
783 CWORD, CWORD, CWORD, CWORD,
784 CWORD, CWORD, CWORD, CWORD,
785 CWORD, CWORD, CBACK, CWORD,
786 CWORD, CWORD, CBQUOTE, CWORD,
787 CWORD, CWORD, CWORD, CWORD,
788 CWORD, CWORD, CWORD, CWORD,
789 CWORD, CWORD, CWORD, CWORD,
790 CWORD, CWORD, CWORD, CWORD,
791 CWORD, CWORD, CWORD, CWORD,
792 CWORD, CWORD, CWORD, CWORD,
793 CWORD, CWORD, CSPCL, CENDVAR,
794 CWORD
795};
796
797/* syntax table used when in double quotes */
798static const char dqsyntax[257] = {
799 CENDFILE, CIGN, CWORD, CCTL,
800 CCTL, CCTL, CCTL, CCTL,
801 CCTL, CCTL, CCTL, CWORD,
802 CWORD, CWORD, CWORD, CWORD,
803 CWORD, CWORD, CWORD, CWORD,
804 CWORD, CWORD, CWORD, CWORD,
805 CWORD, CWORD, CWORD, CWORD,
806 CWORD, CWORD, CWORD, CWORD,
807 CWORD, CWORD, CWORD, CWORD,
808 CWORD, CWORD, CWORD, CWORD,
809 CWORD, CWORD, CWORD, CWORD,
810 CWORD, CWORD, CWORD, CWORD,
811 CWORD, CWORD, CWORD, CWORD,
812 CWORD, CWORD, CWORD, CWORD,
813 CWORD, CWORD, CWORD, CWORD,
814 CWORD, CWORD, CWORD, CWORD,
815 CWORD, CWORD, CWORD, CWORD,
816 CWORD, CWORD, CWORD, CWORD,
817 CWORD, CWORD, CWORD, CWORD,
818 CWORD, CWORD, CWORD, CWORD,
819 CWORD, CWORD, CWORD, CWORD,
820 CWORD, CWORD, CWORD, CWORD,
821 CWORD, CWORD, CWORD, CWORD,
822 CWORD, CWORD, CWORD, CWORD,
823 CWORD, CWORD, CWORD, CWORD,
824 CWORD, CWORD, CWORD, CWORD,
825 CWORD, CWORD, CWORD, CWORD,
826 CWORD, CWORD, CWORD, CWORD,
827 CWORD, CWORD, CWORD, CWORD,
828 CWORD, CWORD, CWORD, CWORD,
829 CWORD, CWORD, CWORD, CWORD,
830 CWORD, CWORD, CWORD, CWORD,
831 CWORD, CWORD, CWORD, CWORD,
832 CWORD, CWORD, CWORD, CWORD,
833 CWORD, CWORD, CWORD, CWORD,
834 CNL, CWORD, CWORD, CWORD,
835 CWORD, CWORD, CWORD, CWORD,
836 CWORD, CWORD, CWORD, CWORD,
837 CWORD, CWORD, CWORD, CWORD,
838 CWORD, CWORD, CWORD, CWORD,
839 CWORD, CWORD, CWORD, CCTL,
840 CENDQUOTE,CWORD, CVAR, CWORD,
841 CWORD, CWORD, CWORD, CWORD,
842 CCTL, CWORD, CWORD, CCTL,
843 CWORD, CCTL, CWORD, CWORD,
844 CWORD, CWORD, CWORD, CWORD,
845 CWORD, CWORD, CWORD, CWORD,
846 CCTL, CWORD, CWORD, CCTL,
847 CWORD, CCTL, CWORD, CWORD,
848 CWORD, CWORD, CWORD, CWORD,
849 CWORD, CWORD, CWORD, CWORD,
850 CWORD, CWORD, CWORD, CWORD,
851 CWORD, CWORD, CWORD, CWORD,
852 CWORD, CWORD, CWORD, CWORD,
853 CWORD, CWORD, CWORD, CWORD,
854 CWORD, CCTL, CBACK, CCTL,
855 CWORD, CWORD, CBQUOTE, CWORD,
856 CWORD, CWORD, CWORD, CWORD,
857 CWORD, CWORD, CWORD, CWORD,
858 CWORD, CWORD, CWORD, CWORD,
859 CWORD, CWORD, CWORD, CWORD,
860 CWORD, CWORD, CWORD, CWORD,
861 CWORD, CWORD, CWORD, CWORD,
862 CWORD, CWORD, CWORD, CENDVAR,
863 CCTL
864};
865
866/* syntax table used when in single quotes */
867static const char sqsyntax[257] = {
868 CENDFILE, CIGN, CWORD, CCTL,
869 CCTL, CCTL, CCTL, CCTL,
870 CCTL, CCTL, CCTL, CWORD,
871 CWORD, CWORD, CWORD, CWORD,
872 CWORD, CWORD, CWORD, CWORD,
873 CWORD, CWORD, CWORD, CWORD,
874 CWORD, CWORD, CWORD, CWORD,
875 CWORD, CWORD, CWORD, CWORD,
876 CWORD, CWORD, CWORD, CWORD,
877 CWORD, CWORD, CWORD, CWORD,
878 CWORD, CWORD, CWORD, CWORD,
879 CWORD, CWORD, CWORD, CWORD,
880 CWORD, CWORD, CWORD, CWORD,
881 CWORD, CWORD, CWORD, CWORD,
882 CWORD, CWORD, CWORD, CWORD,
883 CWORD, CWORD, CWORD, CWORD,
884 CWORD, CWORD, CWORD, CWORD,
885 CWORD, CWORD, CWORD, CWORD,
886 CWORD, CWORD, CWORD, CWORD,
887 CWORD, CWORD, CWORD, CWORD,
888 CWORD, CWORD, CWORD, CWORD,
889 CWORD, CWORD, CWORD, CWORD,
890 CWORD, CWORD, CWORD, CWORD,
891 CWORD, CWORD, CWORD, CWORD,
892 CWORD, CWORD, CWORD, CWORD,
893 CWORD, CWORD, CWORD, CWORD,
894 CWORD, CWORD, CWORD, CWORD,
895 CWORD, CWORD, CWORD, CWORD,
896 CWORD, CWORD, CWORD, CWORD,
897 CWORD, CWORD, CWORD, CWORD,
898 CWORD, CWORD, CWORD, CWORD,
899 CWORD, CWORD, CWORD, CWORD,
900 CWORD, CWORD, CWORD, CWORD,
901 CWORD, CWORD, CWORD, CWORD,
902 CWORD, CWORD, CWORD, CWORD,
903 CNL, CWORD, CWORD, CWORD,
904 CWORD, CWORD, CWORD, CWORD,
905 CWORD, CWORD, CWORD, CWORD,
906 CWORD, CWORD, CWORD, CWORD,
907 CWORD, CWORD, CWORD, CWORD,
908 CWORD, CWORD, CWORD, CCTL,
909 CWORD, CWORD, CWORD, CWORD,
910 CWORD, CENDQUOTE,CWORD, CWORD,
911 CCTL, CWORD, CWORD, CCTL,
912 CWORD, CCTL, CWORD, CWORD,
913 CWORD, CWORD, CWORD, CWORD,
914 CWORD, CWORD, CWORD, CWORD,
915 CCTL, CWORD, CWORD, CCTL,
916 CWORD, CCTL, CWORD, CWORD,
917 CWORD, CWORD, CWORD, CWORD,
918 CWORD, CWORD, CWORD, CWORD,
919 CWORD, CWORD, CWORD, CWORD,
920 CWORD, CWORD, CWORD, CWORD,
921 CWORD, CWORD, CWORD, CWORD,
922 CWORD, CWORD, CWORD, CWORD,
923 CWORD, CCTL, CCTL, CCTL,
924 CWORD, CWORD, CWORD, CWORD,
925 CWORD, CWORD, CWORD, CWORD,
926 CWORD, CWORD, CWORD, CWORD,
927 CWORD, CWORD, CWORD, CWORD,
928 CWORD, CWORD, CWORD, CWORD,
929 CWORD, CWORD, CWORD, CWORD,
930 CWORD, CWORD, CWORD, CWORD,
931 CWORD, CWORD, CWORD, CWORD,
932 CCTL
933};
94 934
935/* syntax table used when in arithmetic */
936static const char arisyntax[257] = {
937 CENDFILE, CIGN, CWORD, CCTL,
938 CCTL, CCTL, CCTL, CCTL,
939 CCTL, CCTL, CCTL, CWORD,
940 CWORD, CWORD, CWORD, CWORD,
941 CWORD, CWORD, CWORD, CWORD,
942 CWORD, CWORD, CWORD, CWORD,
943 CWORD, CWORD, CWORD, CWORD,
944 CWORD, CWORD, CWORD, CWORD,
945 CWORD, CWORD, CWORD, CWORD,
946 CWORD, CWORD, CWORD, CWORD,
947 CWORD, CWORD, CWORD, CWORD,
948 CWORD, CWORD, CWORD, CWORD,
949 CWORD, CWORD, CWORD, CWORD,
950 CWORD, CWORD, CWORD, CWORD,
951 CWORD, CWORD, CWORD, CWORD,
952 CWORD, CWORD, CWORD, CWORD,
953 CWORD, CWORD, CWORD, CWORD,
954 CWORD, CWORD, CWORD, CWORD,
955 CWORD, CWORD, CWORD, CWORD,
956 CWORD, CWORD, CWORD, CWORD,
957 CWORD, CWORD, CWORD, CWORD,
958 CWORD, CWORD, CWORD, CWORD,
959 CWORD, CWORD, CWORD, CWORD,
960 CWORD, CWORD, CWORD, CWORD,
961 CWORD, CWORD, CWORD, CWORD,
962 CWORD, CWORD, CWORD, CWORD,
963 CWORD, CWORD, CWORD, CWORD,
964 CWORD, CWORD, CWORD, CWORD,
965 CWORD, CWORD, CWORD, CWORD,
966 CWORD, CWORD, CWORD, CWORD,
967 CWORD, CWORD, CWORD, CWORD,
968 CWORD, CWORD, CWORD, CWORD,
969 CWORD, CWORD, CWORD, CWORD,
970 CWORD, CWORD, CWORD, CWORD,
971 CWORD, CWORD, CWORD, CWORD,
972 CNL, CWORD, CWORD, CWORD,
973 CWORD, CWORD, CWORD, CWORD,
974 CWORD, CWORD, CWORD, CWORD,
975 CWORD, CWORD, CWORD, CWORD,
976 CWORD, CWORD, CWORD, CWORD,
977 CWORD, CWORD, CWORD, CWORD,
978 CDQUOTE, CWORD, CVAR, CWORD,
979 CWORD, CSQUOTE, CLP, CRP,
980 CWORD, CWORD, CWORD, CWORD,
981 CWORD, CWORD, CWORD, CWORD,
982 CWORD, CWORD, CWORD, CWORD,
983 CWORD, CWORD, CWORD, CWORD,
984 CWORD, CWORD, CWORD, CWORD,
985 CWORD, CWORD, CWORD, CWORD,
986 CWORD, CWORD, CWORD, CWORD,
987 CWORD, CWORD, CWORD, CWORD,
988 CWORD, CWORD, CWORD, CWORD,
989 CWORD, CWORD, CWORD, CWORD,
990 CWORD, CWORD, CWORD, CWORD,
991 CWORD, CWORD, CWORD, CWORD,
992 CWORD, CWORD, CBACK, CWORD,
993 CWORD, CWORD, CBQUOTE, CWORD,
994 CWORD, CWORD, CWORD, CWORD,
995 CWORD, CWORD, CWORD, CWORD,
996 CWORD, CWORD, CWORD, CWORD,
997 CWORD, CWORD, CWORD, CWORD,
998 CWORD, CWORD, CWORD, CWORD,
999 CWORD, CWORD, CWORD, CWORD,
1000 CWORD, CWORD, CWORD, CENDVAR,
1001 CWORD
1002};
95 1003
1004/* character classification table */
1005static const char is_type[257] = {
1006 0, 0, 0, 0,
1007 0, 0, 0, 0,
1008 0, 0, 0, 0,
1009 0, 0, 0, 0,
1010 0, 0, 0, 0,
1011 0, 0, 0, 0,
1012 0, 0, 0, 0,
1013 0, 0, 0, 0,
1014 0, 0, 0, 0,
1015 0, 0, 0, 0,
1016 0, 0, 0, 0,
1017 0, 0, 0, 0,
1018 0, 0, 0, 0,
1019 0, 0, 0, 0,
1020 0, 0, 0, 0,
1021 0, 0, 0, 0,
1022 0, 0, 0, 0,
1023 0, 0, 0, 0,
1024 0, 0, 0, 0,
1025 0, 0, 0, 0,
1026 0, 0, 0, 0,
1027 0, 0, 0, 0,
1028 0, 0, 0, 0,
1029 0, 0, 0, 0,
1030 0, 0, 0, 0,
1031 0, 0, 0, 0,
1032 0, 0, 0, 0,
1033 0, 0, 0, 0,
1034 0, 0, 0, 0,
1035 0, 0, 0, 0,
1036 0, 0, 0, 0,
1037 0, 0, 0, 0,
1038 0, 0, 0, 0,
1039 0, 0, 0, 0,
1040 0, 0, 0, 0,
1041 0, 0, 0, 0,
1042 0, 0, 0, 0,
1043 0, 0, 0, 0,
1044 0, 0, 0, 0,
1045 0, 0, 0, 0,
1046 0, 0, 0, ISSPECL,
1047 0, ISSPECL, ISSPECL, 0,
1048 0, 0, 0, 0,
1049 ISSPECL, 0, 0, ISSPECL,
1050 0, 0, ISDIGIT, ISDIGIT,
1051 ISDIGIT, ISDIGIT, ISDIGIT, ISDIGIT,
1052 ISDIGIT, ISDIGIT, ISDIGIT, ISDIGIT,
1053 0, 0, 0, 0,
1054 0, ISSPECL, ISSPECL, ISUPPER,
1055 ISUPPER, ISUPPER, ISUPPER, ISUPPER,
1056 ISUPPER, ISUPPER, ISUPPER, ISUPPER,
1057 ISUPPER, ISUPPER, ISUPPER, ISUPPER,
1058 ISUPPER, ISUPPER, ISUPPER, ISUPPER,
1059 ISUPPER, ISUPPER, ISUPPER, ISUPPER,
1060 ISUPPER, ISUPPER, ISUPPER, ISUPPER,
1061 ISUPPER, 0, 0, 0,
1062 0, ISUNDER, 0, ISLOWER,
1063 ISLOWER, ISLOWER, ISLOWER, ISLOWER,
1064 ISLOWER, ISLOWER, ISLOWER, ISLOWER,
1065 ISLOWER, ISLOWER, ISLOWER, ISLOWER,
1066 ISLOWER, ISLOWER, ISLOWER, ISLOWER,
1067 ISLOWER, ISLOWER, ISLOWER, ISLOWER,
1068 ISLOWER, ISLOWER, ISLOWER, ISLOWER,
1069 ISLOWER, 0, 0, 0,
1070 0
1071};
96 1072
97struct alias *atab[ATABSIZE]; 1073/* Array indicating which tokens mark the end of a list */
1074static const char tokendlist[] = {
1075 1,
1076 0,
1077 0,
1078 0,
1079 0,
1080 0,
1081 0,
1082 0,
1083 1,
1084 1,
1085 1,
1086 0,
1087 0,
1088 0,
1089 0,
1090 0,
1091 1,
1092 1,
1093 1,
1094 1,
1095 1,
1096 1,
1097 0,
1098 0,
1099 0,
1100 1,
1101 0,
1102 0,
1103 0,
1104 1,
1105};
98 1106
99static void setalias __P((char *, char *)); 1107static const char *const tokname[] = {
100static struct alias **hashalias __P((const char *)); 1108 "end of file",
101static struct alias *freealias __P((struct alias *)); 1109 "newline",
102static struct alias **__lookupalias __P((const char *)); 1110 "\";\"",
103static char *trap[NSIG]; /* trap handler commands */ 1111 "\"&\"",
104static char sigmode[NSIG - 1]; /* current value of signal */ 1112 "\"&&\"",
105static char gotsig[NSIG - 1]; /* indicates specified signal received */ 1113 "\"||\"",
106static int pendingsigs; /* indicates some signal received */ 1114 "\"|\"",
1115 "\"(\"",
1116 "\")\"",
1117 "\";;\"",
1118 "\"`\"",
1119 "redirection",
1120 "word",
1121 "assignment",
1122 "\"!\"",
1123 "\"case\"",
1124 "\"do\"",
1125 "\"done\"",
1126 "\"elif\"",
1127 "\"else\"",
1128 "\"esac\"",
1129 "\"fi\"",
1130 "\"for\"",
1131 "\"if\"",
1132 "\"in\"",
1133 "\"then\"",
1134 "\"until\"",
1135 "\"while\"",
1136 "\"{\"",
1137 "\"}\"",
1138};
107 1139
1140#define KWDOFFSET 14
1141
1142static const char *const parsekwd[] = {
1143 "!",
1144 "case",
1145 "do",
1146 "done",
1147 "elif",
1148 "else",
1149 "esac",
1150 "fi",
1151 "for",
1152 "if",
1153 "in",
1154 "then",
1155 "until",
1156 "while",
1157 "{",
1158 "}"
1159};
1160
1161
1162static int plinno = 1; /* input line number */
1163
1164static int parselleft; /* copy of parsefile->lleft */
1165
1166static struct parsefile basepf; /* top level input file */
1167static char basebuf[BUFSIZ]; /* buffer for top level input file */
1168static struct parsefile *parsefile = &basepf; /* current input file */
1169
1170/*
1171 * NEOF is returned by parsecmd when it encounters an end of file. It
1172 * must be distinct from NULL, so we use the address of a variable that
1173 * happens to be handy.
1174 */
1175
1176static int tokpushback; /* last token pushed back */
1177#define NEOF ((union node *)&tokpushback)
1178static int checkkwd; /* 1 == check for kwds, 2 == also eat newlines */
1179
1180
1181static void error (const char *, ...) __attribute__((__noreturn__));
1182static void exerror (int, const char *, ...) __attribute__((__noreturn__));
1183static void shellexec (char **, char **, const char *, int)
1184 __attribute__((noreturn));
1185static void exitshell (int) __attribute__((noreturn));
1186
1187static int goodname(const char *);
1188static void ignoresig (int);
1189static void onsig (int);
1190static void dotrap (void);
1191static int decode_signal (const char *, int);
1192
1193static void shprocvar(void);
1194static void deletefuncs(void);
1195static void setparam (char **);
1196static void freeparam (volatile struct shparam *);
1197
1198/* reasons for skipping commands (see comment on breakcmd routine) */
1199#define SKIPBREAK 1
1200#define SKIPCONT 2
1201#define SKIPFUNC 3
1202#define SKIPFILE 4
1203
1204/* values of cmdtype */
1205#define CMDUNKNOWN -1 /* no entry in table for command */
1206#define CMDNORMAL 0 /* command is an executable program */
1207#define CMDBUILTIN 1 /* command is a shell builtin */
1208#define CMDFUNCTION 2 /* command is a shell function */
1209
1210#define DO_ERR 1 /* find_command prints errors */
1211#define DO_ABS 2 /* find_command checks absolute paths */
1212#define DO_NOFUN 4 /* find_command ignores functions */
1213#define DO_BRUTE 8 /* find_command ignores hash table */
1214
1215/*
1216 * Shell variables.
1217 */
1218
1219/* flags */
1220#define VEXPORT 0x01 /* variable is exported */
1221#define VREADONLY 0x02 /* variable cannot be modified */
1222#define VSTRFIXED 0x04 /* variable struct is staticly allocated */
1223#define VTEXTFIXED 0x08 /* text is staticly allocated */
1224#define VSTACK 0x10 /* text is allocated on the stack */
1225#define VUNSET 0x20 /* the variable is not set */
1226#define VNOFUNC 0x40 /* don't call the callback function */
1227
1228
1229struct var {
1230 struct var *next; /* next entry in hash list */
1231 int flags; /* flags are defined above */
1232 char *text; /* name=value */
1233 void (*func) (const char *);
1234 /* function to be called when */
1235 /* the variable gets set/unset */
1236};
1237
1238struct localvar {
1239 struct localvar *next; /* next local variable in list */
1240 struct var *vp; /* the variable that was made local */
1241 int flags; /* saved flags */
1242 char *text; /* saved text */
1243};
1244
1245
1246#if defined(__GLIBC__) && !defined(FNMATCH_BROKEN)
1247#define rmescapes(p) _rmescapes((p), 0)
1248static char *_rmescapes (char *, int);
1249#else
1250static void rmescapes (char *);
1251#endif
1252
1253static int casematch (union node *, const char *);
1254static void clearredir(void);
1255static void popstring(void);
1256static void readcmdfile (const char *);
1257
1258static int number (const char *);
1259static int is_number (const char *, int *num);
1260static char *single_quote (const char *);
1261static int nextopt (const char *);
1262
1263static void redirect (union node *, int);
1264static void popredir (void);
1265static int dup_as_newfd (int, int);
1266
1267static void changepath(const char *newval);
1268static void getoptsreset(const char *value);
1269
1270
1271static int parsenleft; /* copy of parsefile->nleft */
1272static char *parsenextc; /* copy of parsefile->nextc */
1273static int rootpid; /* pid of main shell */
1274static int rootshell; /* true if we aren't a child of the main shell */
1275
1276static const char spcstr[] = " ";
1277static const char snlfmt[] = "%s\n";
1278
1279static int sstrnleft;
1280static int herefd = -1;
1281
1282static struct localvar *localvars;
1283
1284static struct var vifs;
1285static struct var vmail;
1286static struct var vmpath;
1287static struct var vpath;
1288static struct var vps1;
1289static struct var vps2;
1290static struct var voptind;
1291#ifdef BB_LOCALE_SUPPORT
1292static struct var vlc_all;
1293static struct var vlc_ctype;
1294#endif
1295
1296struct varinit {
1297 struct var *var;
1298 int flags;
1299 const char *text;
1300 void (*func) (const char *);
1301};
1302
1303static const char defpathvar[] =
1304 "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin";
1305#define defpath (defpathvar + 5)
1306
1307#ifdef IFS_BROKEN
1308static const char defifsvar[] = "IFS= \t\n";
1309#define defifs (defifsvar + 4)
1310#else
1311static const char defifs[] = " \t\n";
1312#endif
1313
1314static const struct varinit varinit[] = {
1315#ifdef IFS_BROKEN
1316 { &vifs, VSTRFIXED|VTEXTFIXED, defifsvar,
1317#else
1318 { &vifs, VSTRFIXED|VTEXTFIXED|VUNSET, "IFS=",
1319#endif
1320 NULL },
1321 { &vmail, VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL=",
1322 NULL },
1323 { &vmpath, VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH=",
1324 NULL },
1325 { &vpath, VSTRFIXED|VTEXTFIXED, defpathvar,
1326 changepath },
1327 /*
1328 * vps1 depends on uid
1329 */
1330 { &vps2, VSTRFIXED|VTEXTFIXED, "PS2=> ",
1331 NULL },
1332 { &voptind, VSTRFIXED|VTEXTFIXED, "OPTIND=1",
1333 getoptsreset },
1334#ifdef BB_LOCALE_SUPPORT
1335 { &vlc_all, VSTRFIXED|VTEXTFIXED|VUNSET, "LC_ALL=",
1336 change_lc_all },
1337 { &vlc_ctype, VSTRFIXED|VTEXTFIXED|VUNSET, "LC_CTYPE=",
1338 change_lc_ctype },
1339#endif
1340 { NULL, 0, NULL,
1341 NULL }
1342};
1343
1344#define VTABSIZE 39
1345
1346static struct var *vartab[VTABSIZE];
1347
1348/*
1349 * The following macros access the values of the above variables.
1350 * They have to skip over the name. They return the null string
1351 * for unset variables.
1352 */
1353
1354#define ifsval() (vifs.text + 4)
1355#define ifsset() ((vifs.flags & VUNSET) == 0)
1356#define mailval() (vmail.text + 5)
1357#define mpathval() (vmpath.text + 9)
1358#define pathval() (vpath.text + 5)
1359#define ps1val() (vps1.text + 4)
1360#define ps2val() (vps2.text + 4)
1361#define optindval() (voptind.text + 7)
1362
1363#define mpathset() ((vmpath.flags & VUNSET) == 0)
1364
1365static void initvar (void);
1366static void setvar (const char *, const char *, int);
1367static void setvareq (char *, int);
1368static void listsetvar (struct strlist *);
1369static char *lookupvar (const char *);
1370static char *bltinlookup (const char *);
1371static char **environment (void);
1372static int showvarscmd (int, char **);
1373static void mklocal (char *);
1374static void poplocalvars (void);
1375static int unsetvar (const char *);
1376static int varequal (const char *, const char *);
1377
1378
1379static char *arg0; /* value of $0 */
1380static struct shparam shellparam; /* current positional parameters */
1381static char **argptr; /* argument list for builtin commands */
1382static char *optionarg; /* set by nextopt (like getopt) */
1383static char *optptr; /* used by nextopt */
1384static char *minusc; /* argument to -c option */
1385
1386
1387#ifdef ASH_ALIAS
1388
1389#define ALIASINUSE 1
1390#define ALIASDEAD 2
1391
1392struct alias {
1393 struct alias *next;
1394 char *name;
1395 char *val;
1396 int flag;
1397};
1398
1399static struct alias *atab[ATABSIZE];
1400
1401static void setalias (char *, char *);
1402static struct alias **hashalias (const char *);
1403static struct alias *freealias (struct alias *);
1404static struct alias **__lookupalias (const char *);
108 1405
109static void 1406static void
110setalias(name, val) 1407setalias(name, val)
@@ -119,7 +1416,7 @@ setalias(name, val)
119 if (!(ap->flag & ALIASINUSE)) { 1416 if (!(ap->flag & ALIASINUSE)) {
120 ckfree(ap->val); 1417 ckfree(ap->val);
121 } 1418 }
122 ap->val = savestr(val); 1419 ap->val = savestr(val);
123 ap->flag &= ~ALIASDEAD; 1420 ap->flag &= ~ALIASDEAD;
124 } else { 1421 } else {
125 /* not found */ 1422 /* not found */
@@ -134,9 +1431,8 @@ setalias(name, val)
134} 1431}
135 1432
136static int 1433static int
137unalias(name) 1434unalias(char *name)
138 char *name; 1435{
139 {
140 struct alias **app; 1436 struct alias **app;
141 1437
142 app = __lookupalias(name); 1438 app = __lookupalias(name);
@@ -151,16 +1447,9 @@ unalias(name)
151 return (1); 1447 return (1);
152} 1448}
153 1449
154#ifdef mkinit
155static void rmaliases __P((void));
156
157SHELLPROC {
158 rmaliases();
159}
160#endif
161
162static void 1450static void
163rmaliases() { 1451rmaliases(void)
1452{
164 struct alias *ap, **app; 1453 struct alias *ap, **app;
165 int i; 1454 int i;
166 1455
@@ -177,10 +1466,8 @@ rmaliases() {
177 INTON; 1466 INTON;
178} 1467}
179 1468
180struct alias * 1469static struct alias *
181lookupalias(name, check) 1470lookupalias(const char *name, int check)
182 const char *name;
183 int check;
184{ 1471{
185 struct alias *ap = *__lookupalias(name); 1472 struct alias *ap = *__lookupalias(name);
186 1473
@@ -189,14 +1476,21 @@ lookupalias(name, check)
189 return (ap); 1476 return (ap);
190} 1477}
191 1478
1479static void
1480printalias(const struct alias *ap) {
1481 char *p;
1482
1483 p = single_quote(ap->val);
1484 out1fmt("alias %s=%s\n", ap->name, p);
1485 stunalloc(p);
1486}
1487
192 1488
193/* 1489/*
194 * TODO - sort output 1490 * TODO - sort output
195 */ 1491 */
196static int 1492static int
197aliascmd(argc, argv) 1493aliascmd(int argc, char **argv)
198 int argc;
199 char **argv;
200{ 1494{
201 char *n, *v; 1495 char *n, *v;
202 int ret = 0; 1496 int ret = 0;
@@ -229,9 +1523,7 @@ aliascmd(argc, argv)
229} 1523}
230 1524
231static int 1525static int
232unaliascmd(argc, argv) 1526unaliascmd(int argc, char **argv)
233 int argc;
234 char **argv;
235{ 1527{
236 int i; 1528 int i;
237 1529
@@ -279,14 +1571,6 @@ freealias(struct alias *ap) {
279 return next; 1571 return next;
280} 1572}
281 1573
282static void
283printalias(const struct alias *ap) {
284 char *p;
285
286 p = single_quote(ap->val);
287 out1fmt("alias %s=%s\n", ap->name, p);
288 stunalloc(p);
289}
290 1574
291static struct alias ** 1575static struct alias **
292__lookupalias(const char *name) { 1576__lookupalias(const char *name) {
@@ -300,64 +1584,132 @@ __lookupalias(const char *name) {
300 1584
301 return app; 1585 return app;
302} 1586}
1587#endif
303 1588
304#ifdef ASH_MATH_SUPPORT 1589#ifdef ASH_MATH_SUPPORT
305/* The generated file arith.c has been snipped. If you want this 1590/* The generated file arith.c has been snipped. If you want this
306 * stuff back in, feel free to add it to your own copy. */ 1591 * stuff back in, feel free to add it to your own copy. */
307#endif 1592#define ARITH_NUM 257
1593#define ARITH_LPAREN 258
1594#define ARITH_RPAREN 259
1595#define ARITH_OR 260
1596#define ARITH_AND 261
1597#define ARITH_BOR 262
1598#define ARITH_BXOR 263
1599#define ARITH_BAND 264
1600#define ARITH_EQ 265
1601#define ARITH_NE 266
1602#define ARITH_LT 267
1603#define ARITH_GT 268
1604#define ARITH_GE 269
1605#define ARITH_LE 270
1606#define ARITH_LSHIFT 271
1607#define ARITH_RSHIFT 272
1608#define ARITH_ADD 273
1609#define ARITH_SUB 274
1610#define ARITH_MUL 275
1611#define ARITH_DIV 276
1612#define ARITH_REM 277
1613#define ARITH_UNARYMINUS 278
1614#define ARITH_UNARYPLUS 279
1615#define ARITH_NOT 280
1616#define ARITH_BNOT 281
1617
1618static void expari (int);
1619/* From arith.y */
1620static int arith (const char *);
1621static int expcmd (int , char **);
1622static void arith_lex_reset (void);
1623static int yylex (void);
1624
1625#endif
1626
1627static char *trap[NSIG]; /* trap handler commands */
1628static char sigmode[NSIG - 1]; /* current value of signal */
1629static char gotsig[NSIG - 1]; /* indicates specified signal received */
1630static int pendingsigs; /* indicates some signal received */
308 1631
309/* 1632/*
310 * This file was generated by the mkbuiltins program. 1633 * This file was generated by the mkbuiltins program.
311 */ 1634 */
312 1635
313static int bgcmd __P((int, char **)); 1636#ifdef JOBS
314static int breakcmd __P((int, char **)); 1637static int bgcmd (int, char **);
315static int cdcmd __P((int, char **)); 1638static int fgcmd (int, char **);
316static int commandcmd __P((int, char **)); 1639static int killcmd (int, char **);
317static int dotcmd __P((int, char **)); 1640#endif
318static int evalcmd __P((int, char **)); 1641#ifdef ASH_BBAPPS_AS_BUILTINS
319static int execcmd __P((int, char **)); 1642static int bltincmd (int, char **);
320static int exitcmd __P((int, char **)); 1643#endif
321static int exportcmd __P((int, char **)); 1644static int cdcmd (int, char **);
322static int histcmd __P((int, char **)); 1645static int breakcmd (int, char **);
323static int fgcmd __P((int, char **)); 1646#ifdef ASH_CMDCMD
324static int hashcmd __P((int, char **)); 1647static int commandcmd (int, char **);
325static int jobscmd __P((int, char **)); 1648#endif
326static int killcmd __P((int, char **)); 1649static int dotcmd (int, char **);
327static int localcmd __P((int, char **)); 1650static int evalcmd (int, char **);
328static int pwdcmd __P((int, char **)); 1651static int execcmd (int, char **);
329static int readcmd __P((int, char **)); 1652static int exitcmd (int, char **);
330static int returncmd __P((int, char **)); 1653static int exportcmd (int, char **);
331static int setcmd __P((int, char **)); 1654static int histcmd (int, char **);
332static int setvarcmd __P((int, char **)); 1655static int hashcmd (int, char **);
333static int shiftcmd __P((int, char **)); 1656static int jobscmd (int, char **);
334static int trapcmd __P((int, char **)); 1657static int localcmd (int, char **);
335static int umaskcmd __P((int, char **)); 1658#ifdef ASH_PWD
336static int unaliascmd __P((int, char **)); 1659static int pwdcmd (int, char **);
337static int unsetcmd __P((int, char **)); 1660#endif
338static int waitcmd __P((int, char **)); 1661static int readcmd (int, char **);
339static int aliascmd __P((int, char **)); 1662static int returncmd (int, char **);
340static int ulimitcmd __P((int, char **)); 1663static int setcmd (int, char **);
341static int timescmd __P((int, char **)); 1664static int setvarcmd (int, char **);
1665static int shiftcmd (int, char **);
1666static int trapcmd (int, char **);
1667static int umaskcmd (int, char **);
1668#ifdef ASH_ALIAS
1669static int aliascmd (int, char **);
1670static int unaliascmd (int, char **);
1671#endif
1672static int unsetcmd (int, char **);
1673static int waitcmd (int, char **);
1674static int ulimitcmd (int, char **);
1675static int timescmd (int, char **);
342#ifdef ASH_MATH_SUPPORT 1676#ifdef ASH_MATH_SUPPORT
343static int expcmd __P((int, char **)); 1677static int expcmd (int, char **);
344#endif 1678#endif
345#ifdef ASH_TYPE 1679#ifdef ASH_TYPE
346static int typecmd __P((int, char **)); 1680static int typecmd (int, char **);
347#endif 1681#endif
348#ifdef ASH_GETOPTS 1682#ifdef ASH_GETOPTS
349static int getoptscmd __P((int, char **)); 1683static int getoptscmd (int, char **);
350#endif 1684#endif
1685
351#ifndef BB_TRUE_FALSE 1686#ifndef BB_TRUE_FALSE
352static int true_main __P((int, char **)); 1687# ifdef ASH_BBAPPS_AS_BUILTINS
353static int false_main __P((int, char **)); 1688static int true_main (int, char **);
1689static int false_main (int, char **);
1690# endif
354#endif 1691#endif
355 1692
356static struct builtincmd *DOTCMD; 1693static void setpwd (const char *, int);
357static struct builtincmd *BLTINCMD; 1694
358static struct builtincmd *COMMANDCMD; 1695
359static struct builtincmd *EXECCMD; 1696#define BUILTIN_NOSPEC "0"
360static struct builtincmd *EVALCMD; 1697#define BUILTIN_SPECIAL "1"
1698#define BUILTIN_REGULAR "2"
1699#define BUILTIN_ASSIGN "4"
1700#define BUILTIN_SPEC_ASSG "5"
1701#define BUILTIN_REG_ASSG "6"
1702
1703#define IS_BUILTIN_SPECIAL(builtincmd) ((builtincmd)->name[0] & 1)
1704#define IS_BUILTIN_REGULAR(builtincmd) ((builtincmd)->name[0] & 2)
1705#define IS_BUILTIN_ASSIGN(builtincmd) ((builtincmd)->name[0] & 4)
1706
1707struct builtincmd {
1708 const char *name;
1709 int (*const builtinfunc) (int, char **);
1710 //unsigned flags;
1711};
1712
361 1713
362/* It is CRUCIAL that this listing be kept in ascii order, otherwise 1714/* It is CRUCIAL that this listing be kept in ascii order, otherwise
363 * the binary search in find_builtin() will stop working. If you value 1715 * the binary search in find_builtin() will stop working. If you value
@@ -366,75 +1718,149 @@ static struct builtincmd *EVALCMD;
366 * have been warned. 1718 * have been warned.
367 */ 1719 */
368static const struct builtincmd builtincmds[] = { 1720static const struct builtincmd builtincmds[] = {
369 { ".", dotcmd, 1 }, 1721 { BUILTIN_SPECIAL ".", dotcmd },
370 { ":", true_main, 1 }, 1722 { BUILTIN_SPECIAL ":", true_main },
371 { "alias", aliascmd, 6 }, 1723#ifdef ASH_ALIAS
372 { "bg", bgcmd, 2 }, 1724 { BUILTIN_REG_ASSG "alias", aliascmd },
373 { "break", breakcmd, 1 }, 1725#endif
374 { "builtin", bltincmd, 1 }, 1726#ifdef JOBS
375 { "cd", cdcmd, 2 }, 1727 { BUILTIN_REGULAR "bg", bgcmd },
376 { "chdir", cdcmd, 0 }, 1728#endif
377 { "command", commandcmd, 2 }, 1729 { BUILTIN_SPECIAL "break", breakcmd },
378 { "continue", breakcmd, 1 }, 1730#ifdef ASH_BBAPPS_AS_BUILTINS
379 { "eval", evalcmd, 1 }, 1731 { BUILTIN_SPECIAL "builtin", bltincmd },
380 { "exec", execcmd, 1 }, 1732#endif
381 { "exit", exitcmd, 1 }, 1733 { BUILTIN_REGULAR "cd", cdcmd },
1734#ifdef ASH_BBAPPS_AS_BUILTINS
1735 { BUILTIN_NOSPEC "chdir", cdcmd },
1736#endif
1737#ifdef ASH_CMDCMD
1738 { BUILTIN_REGULAR "command", commandcmd },
1739#endif
1740 { BUILTIN_SPECIAL "continue", breakcmd },
1741 { BUILTIN_SPECIAL "eval", evalcmd },
1742 { BUILTIN_SPECIAL "exec", execcmd },
1743 { BUILTIN_SPECIAL "exit", exitcmd },
382#ifdef ASH_MATH_SUPPORT 1744#ifdef ASH_MATH_SUPPORT
383 { "exp", expcmd, 0 }, 1745 { BUILTIN_NOSPEC "exp", expcmd },
1746#endif
1747 { BUILTIN_SPEC_ASSG "export", exportcmd },
1748#ifdef ASH_BBAPPS_AS_BUILTINS
1749 { BUILTIN_REGULAR "false", false_main },
1750#endif
1751 { BUILTIN_REGULAR "fc", histcmd },
1752#ifdef JOBS
1753 { BUILTIN_REGULAR "fg", fgcmd },
384#endif 1754#endif
385 { "export", exportcmd, 5 },
386 { "false", false_main, 2 },
387 { "fc", histcmd, 2 },
388 { "fg", fgcmd, 2 },
389#ifdef ASH_GETOPTS 1755#ifdef ASH_GETOPTS
390 { "getopts", getoptscmd, 2 }, 1756 { BUILTIN_REGULAR "getopts", getoptscmd },
391#endif 1757#endif
392 { "hash", hashcmd, 0 }, 1758 { BUILTIN_NOSPEC "hash", hashcmd },
393 { "jobs", jobscmd, 2 }, 1759 { BUILTIN_REGULAR "jobs", jobscmd },
394 { "kill", killcmd, 2 }, 1760#ifdef JOBS
1761 { BUILTIN_REGULAR "kill", killcmd },
1762#endif
395#ifdef ASH_MATH_SUPPORT 1763#ifdef ASH_MATH_SUPPORT
396 { "let", expcmd, 0 }, 1764 { BUILTIN_NOSPEC "let", expcmd },
397#endif 1765#endif
398 { "local", localcmd, 4 }, 1766 { BUILTIN_ASSIGN "local", localcmd },
399 { "pwd", pwdcmd, 0 }, 1767#ifdef ASH_PWD
400 { "read", readcmd, 2 }, 1768 { BUILTIN_NOSPEC "pwd", pwdcmd },
401 { "readonly", exportcmd, 5 }, 1769#endif
402 { "return", returncmd, 1 }, 1770 { BUILTIN_REGULAR "read", readcmd },
403 { "set", setcmd, 1 }, 1771 { BUILTIN_SPEC_ASSG "readonly", exportcmd },
404 { "setvar", setvarcmd, 0 }, 1772 { BUILTIN_SPECIAL "return", returncmd },
405 { "shift", shiftcmd, 1 }, 1773 { BUILTIN_SPECIAL "set", setcmd },
406 { "times", timescmd, 1 }, 1774 { BUILTIN_NOSPEC "setvar", setvarcmd },
407 { "trap", trapcmd, 1 }, 1775 { BUILTIN_SPECIAL "shift", shiftcmd },
408 { "true", true_main, 2 }, 1776 { BUILTIN_SPECIAL "times", timescmd },
1777 { BUILTIN_SPECIAL "trap", trapcmd },
1778#ifdef ASH_BBAPPS_AS_BUILTINS
1779 { BUILTIN_REGULAR "true", true_main },
1780#endif
409#ifdef ASH_TYPE 1781#ifdef ASH_TYPE
410 { "type", typecmd, 0 }, 1782 { BUILTIN_NOSPEC "type", typecmd },
411#endif 1783#endif
412 { "ulimit", ulimitcmd, 0 }, 1784 { BUILTIN_NOSPEC "ulimit", ulimitcmd },
413 { "umask", umaskcmd, 2 }, 1785 { BUILTIN_REGULAR "umask", umaskcmd },
414 { "unalias", unaliascmd, 2 }, 1786#ifdef ASH_ALIAS
415 { "unset", unsetcmd, 1 }, 1787 { BUILTIN_REGULAR "unalias", unaliascmd },
416 { "wait", waitcmd, 2 }, 1788#endif
1789 { BUILTIN_SPECIAL "unset", unsetcmd },
1790 { BUILTIN_REGULAR "wait", waitcmd },
417}; 1791};
418#define NUMBUILTINS (sizeof (builtincmds) / sizeof (struct builtincmd) ) 1792#define NUMBUILTINS (sizeof (builtincmds) / sizeof (struct builtincmd) )
419 1793
1794static const struct builtincmd *DOTCMD = &builtincmds[0];
1795static struct builtincmd *BLTINCMD;
1796static struct builtincmd *EXECCMD;
1797static struct builtincmd *EVALCMD;
1798
1799/* states */
1800#define JOBSTOPPED 1 /* all procs are stopped */
1801#define JOBDONE 2 /* all procs are completed */
1802
1803/*
1804 * A job structure contains information about a job. A job is either a
1805 * single process or a set of processes contained in a pipeline. In the
1806 * latter case, pidlist will be non-NULL, and will point to a -1 terminated
1807 * array of pids.
1808 */
420 1809
421/* $NetBSD: cd.c,v 1.27 1999/07/09 03:05:49 christos Exp $ */ 1810struct procstat {
1811 pid_t pid; /* process id */
1812 int status; /* status flags (defined above) */
1813 char *cmd; /* text of command being run */
1814};
422 1815
423static int docd __P((char *, int));
424static char *getcomponent __P((void));
425static void updatepwd __P((char *));
426static void getpwd __P((void));
427 1816
428static char *curdir = nullstr; /* current working directory */ 1817static int job_warning; /* user was warned about stopped jobs */
429static char *cdcomppath;
430 1818
431#ifdef mkinit 1819#ifdef JOBS
432INCLUDE "cd.h" 1820static void setjobctl(int enable);
433INIT { 1821#else
434 setpwd(0, 0); 1822#define setjobctl(on) /* do nothing */
435}
436#endif 1823#endif
437 1824
1825
1826struct job {
1827 struct procstat ps0; /* status of process */
1828 struct procstat *ps; /* status or processes when more than one */
1829 short nprocs; /* number of processes */
1830 short pgrp; /* process group of this job */
1831 char state; /* true if job is finished */
1832 char used; /* true if this entry is in used */
1833 char changed; /* true if status has changed */
1834#ifdef JOBS
1835 char jobctl; /* job running under job control */
1836#endif
1837};
1838
1839static struct job *jobtab; /* array of jobs */
1840static int njobs; /* size of array */
1841static int backgndpid = -1; /* pid of last background process */
1842#ifdef JOBS
1843static int initialpgrp; /* pgrp of shell on invocation */
1844static int curjob; /* current job */
1845static int jobctl;
1846#endif
1847static int intreceived;
1848
1849static struct job *makejob (union node *, int);
1850static int forkshell (struct job *, union node *, int);
1851static int waitforjob (struct job *);
1852
1853static int docd (char *, int);
1854static char *getcomponent (void);
1855static void updatepwd (const char *);
1856static void getpwd (void);
1857
1858static char *padvance (const char **, const char *);
1859
1860static char nullstr[1]; /* zero length string */
1861static char *curdir = nullstr; /* current working directory */
1862static char *cdcomppath;
1863
438static int 1864static int
439cdcmd(argc, argv) 1865cdcmd(argc, argv)
440 int argc; 1866 int argc;
@@ -450,7 +1876,7 @@ cdcmd(argc, argv)
450 if ((dest = *argptr) == NULL && (dest = bltinlookup("HOME")) == NULL) 1876 if ((dest = *argptr) == NULL && (dest = bltinlookup("HOME")) == NULL)
451 error("HOME not set"); 1877 error("HOME not set");
452 if (*dest == '\0') 1878 if (*dest == '\0')
453 dest = "."; 1879 dest = ".";
454 if (dest[0] == '-' && dest[1] == '\0') { 1880 if (dest[0] == '-' && dest[1] == '\0') {
455 dest = bltinlookup("OLDPWD"); 1881 dest = bltinlookup("OLDPWD");
456 if (!dest || !*dest) { 1882 if (!dest || !*dest) {
@@ -458,9 +1884,9 @@ cdcmd(argc, argv)
458 } 1884 }
459 print = 1; 1885 print = 1;
460 if (dest) 1886 if (dest)
461 print = 1; 1887 print = 1;
462 else 1888 else
463 dest = "."; 1889 dest = ".";
464 } 1890 }
465 if (*dest == '/' || (path = bltinlookup("CDPATH")) == NULL) 1891 if (*dest == '/' || (path = bltinlookup("CDPATH")) == NULL)
466 path = nullstr; 1892 path = nullstr;
@@ -581,15 +2007,16 @@ getcomponent() {
581 * that the current directory has changed. 2007 * that the current directory has changed.
582 */ 2008 */
583 2009
2010static void hashcd (void);
2011
584static void 2012static void
585updatepwd(dir) 2013updatepwd(const char *dir)
586 char *dir; 2014{
587 {
588 char *new; 2015 char *new;
589 char *p; 2016 char *p;
590 size_t len; 2017 size_t len;
591 2018
592 hashcd(); /* update command hash table */ 2019 hashcd(); /* update command hash table */
593 2020
594 /* 2021 /*
595 * If our argument is NULL, we don't know the current directory 2022 * If our argument is NULL, we don't know the current directory
@@ -626,7 +2053,7 @@ updatepwd(dir)
626} 2053}
627 2054
628 2055
629 2056#ifdef ASH_PWD
630static int 2057static int
631pwdcmd(argc, argv) 2058pwdcmd(argc, argv)
632 int argc; 2059 int argc;
@@ -635,89 +2062,18 @@ pwdcmd(argc, argv)
635 out1fmt(snlfmt, curdir); 2062 out1fmt(snlfmt, curdir);
636 return 0; 2063 return 0;
637} 2064}
638 2065#endif
639
640
641
642#define MAXPWD 256
643 2066
644/* 2067/*
645 * Find out what the current directory is. If we already know the current 2068 * Find out what the current directory is. If we already know the current
646 * directory, this routine returns immediately. 2069 * directory, this routine returns immediately.
647 */ 2070 */
648static void 2071static void
649getpwd() 2072getpwd(void)
650{ 2073{
651 char buf[MAXPWD]; 2074 curdir = xgetcwd(0);
652 2075 if(curdir==0)
653 /* 2076 curdir = nullstr;
654 * Things are a bit complicated here; we could have just used
655 * getcwd, but traditionally getcwd is implemented using popen
656 * to /bin/pwd. This creates a problem for us, since we cannot
657 * keep track of the job if it is being ran behind our backs.
658 * So we re-implement getcwd(), and we suppress interrupts
659 * throughout the process. This is not completely safe, since
660 * the user can still break out of it by killing the pwd program.
661 * We still try to use getcwd for systems that we know have a
662 * c implementation of getcwd, that does not open a pipe to
663 * /bin/pwd.
664 */
665#if defined(__NetBSD__) || defined(__SVR4) || defined(__GLIBC__)
666
667 if (getcwd(buf, sizeof(buf)) == NULL) {
668 char *pwd = getenv("PWD");
669 struct stat stdot, stpwd;
670
671 if (pwd && *pwd == '/' && stat(".", &stdot) != -1 &&
672 stat(pwd, &stpwd) != -1 &&
673 stdot.st_dev == stpwd.st_dev &&
674 stdot.st_ino == stpwd.st_ino) {
675 curdir = savestr(pwd);
676 return;
677 }
678 error("getcwd() failed: %s", strerror(errno));
679 }
680 curdir = savestr(buf);
681#else
682 {
683 char *p;
684 int i;
685 int status;
686 struct job *jp;
687 int pip[2];
688
689 if (pipe(pip) < 0)
690 error("Pipe call failed");
691 jp = makejob((union node *)NULL, 1);
692 if (forkshell(jp, (union node *)NULL, FORK_NOJOB) == 0) {
693 (void) close(pip[0]);
694 if (pip[1] != 1) {
695 close(1);
696 dup_as_newfd(pip[1], 1);
697 close(pip[1]);
698 }
699 (void) execl("/bin/pwd", "pwd", (char *)0);
700 error("Cannot exec /bin/pwd");
701 }
702 (void) close(pip[1]);
703 pip[1] = -1;
704 p = buf;
705 while ((i = read(pip[0], p, buf + MAXPWD - p)) > 0
706 || (i == -1 && errno == EINTR)) {
707 if (i > 0)
708 p += i;
709 }
710 (void) close(pip[0]);
711 pip[0] = -1;
712 status = waitforjob(jp);
713 if (status != 0)
714 error((char *)0);
715 if (i < 0 || p == buf || p[-1] != '\n')
716 error("pwd command failed");
717 p[-1] = '\0';
718 }
719 curdir = savestr(buf);
720#endif
721} 2077}
722 2078
723static void 2079static void
@@ -740,8 +2096,6 @@ setpwd(const char *val, int setold)
740 setvar("PWD", curdir, VEXPORT); 2096 setvar("PWD", curdir, VEXPORT);
741} 2097}
742 2098
743/* $NetBSD: error.c,v 1.23 2000/07/03 03:26:19 matt Exp $ */
744
745/* 2099/*
746 * Errors and exceptions. 2100 * Errors and exceptions.
747 */ 2101 */
@@ -750,13 +2104,30 @@ setpwd(const char *val, int setold)
750 * Code to handle exceptions in C. 2104 * Code to handle exceptions in C.
751 */ 2105 */
752 2106
753struct jmploc *handler; 2107/*
754static int exception; 2108 * We enclose jmp_buf in a structure so that we can declare pointers to
755volatile int suppressint; 2109 * jump locations. The global variable handler contains the location to
756volatile int intpending; 2110 * jump to when an exception occurs, and the global variable exception
2111 * contains a code identifying the exeception. To implement nested
2112 * exception handlers, the user should save the value of handler on entry
2113 * to an inner scope, set handler to point to a jmploc structure for the
2114 * inner scope, and restore handler on exit from the scope.
2115 */
2116
2117struct jmploc {
2118 jmp_buf loc;
2119};
757 2120
2121/* exceptions */
2122#define EXINT 0 /* SIGINT received */
2123#define EXERROR 1 /* a generic error */
2124#define EXSHELLPROC 2 /* execute a shell procedure */
2125#define EXEXEC 3 /* command execution failed */
2126
2127static struct jmploc *handler;
2128static int exception;
758 2129
759static void exverror __P((int, const char *, va_list)) 2130static void exverror (int, const char *, va_list)
760 __attribute__((__noreturn__)); 2131 __attribute__((__noreturn__));
761 2132
762/* 2133/*
@@ -765,9 +2136,10 @@ static void exverror __P((int, const char *, va_list))
765 * stored in the global variable "exception". 2136 * stored in the global variable "exception".
766 */ 2137 */
767 2138
2139static void exraise (int) __attribute__((__noreturn__));
2140
768static void 2141static void
769exraise(e) 2142exraise(int e)
770 int e;
771{ 2143{
772#ifdef DEBUG 2144#ifdef DEBUG
773 if (handler == NULL) 2145 if (handler == NULL)
@@ -789,7 +2161,7 @@ exraise(e)
789 */ 2161 */
790 2162
791static void 2163static void
792onint() { 2164onint(void) {
793 sigset_t mysigset; 2165 sigset_t mysigset;
794 2166
795 if (suppressint) { 2167 if (suppressint) {
@@ -809,16 +2181,15 @@ onint() {
809} 2181}
810 2182
811 2183
2184static char *commandname; /* currently executing command */
2185
812/* 2186/*
813 * Exverror is called to raise the error exception. If the first argument 2187 * Exverror is called to raise the error exception. If the first argument
814 * is not NULL then error prints an error message using printf style 2188 * is not NULL then error prints an error message using printf style
815 * formatting. It then raises the error exception. 2189 * formatting. It then raises the error exception.
816 */ 2190 */
817static void 2191static void
818exverror(cond, msg, ap) 2192exverror(int cond, const char *msg, va_list ap)
819 int cond;
820 const char *msg;
821 va_list ap;
822{ 2193{
823 CLEAR_PENDING_INT; 2194 CLEAR_PENDING_INT;
824 INTOFF; 2195 INTOFF;
@@ -903,69 +2274,75 @@ exerror(va_alist)
903 */ 2274 */
904 2275
905struct errname { 2276struct errname {
906 short errcode; /* error number */ 2277 short errcode; /* error number */
907 short action; /* operation which encountered the error */ 2278 short action; /* operation which encountered the error */
908 const char *msg; /* text describing the error */
909}; 2279};
910 2280
2281/*
2282 * Types of operations (passed to the errmsg routine).
2283 */
2284
2285#define E_OPEN 01 /* opening a file */
2286#define E_CREAT 02 /* creating a file */
2287#define E_EXEC 04 /* executing a program */
911 2288
912#define ALL (E_OPEN|E_CREAT|E_EXEC) 2289#define ALL (E_OPEN|E_CREAT|E_EXEC)
913 2290
914static const struct errname errormsg[] = { 2291static const struct errname errormsg[] = {
915 { EINTR, ALL, "interrupted" }, 2292 { EINTR, ALL },
916 { EACCES, ALL, "permission denied" }, 2293 { EACCES, ALL },
917 { EIO, ALL, "I/O error" }, 2294 { EIO, ALL },
918 { ENOENT, E_OPEN, "no such file" }, 2295 { ENOENT, E_OPEN },
919 { ENOENT, E_CREAT,"directory nonexistent" }, 2296 { ENOENT, E_CREAT },
920 { ENOENT, E_EXEC, "not found" }, 2297 { ENOENT, E_EXEC },
921 { ENOTDIR, E_OPEN, "no such file" }, 2298 { ENOTDIR, E_OPEN },
922 { ENOTDIR, E_CREAT,"directory nonexistent" }, 2299 { ENOTDIR, E_CREAT },
923 { ENOTDIR, E_EXEC, "not found" }, 2300 { ENOTDIR, E_EXEC },
924 { EISDIR, ALL, "is a directory" }, 2301 { EISDIR, ALL },
925 { EEXIST, E_CREAT,"file exists" }, 2302 { EEXIST, E_CREAT },
926#ifdef notdef 2303#ifdef EMFILE
927 { EMFILE, ALL, "too many open files" }, 2304 { EMFILE, ALL },
928#endif 2305#endif
929 { ENFILE, ALL, "file table overflow" }, 2306 { ENFILE, ALL },
930 { ENOSPC, ALL, "file system full" }, 2307 { ENOSPC, ALL },
931#ifdef EDQUOT 2308#ifdef EDQUOT
932 { EDQUOT, ALL, "disk quota exceeded" }, 2309 { EDQUOT, ALL },
933#endif 2310#endif
934#ifdef ENOSR 2311#ifdef ENOSR
935 { ENOSR, ALL, "no streams resources" }, 2312 { ENOSR, ALL },
936#endif 2313#endif
937 { ENXIO, ALL, "no such device or address" }, 2314 { ENXIO, ALL },
938 { EROFS, ALL, "read-only file system" }, 2315 { EROFS, ALL },
939 { ETXTBSY, ALL, "text busy" }, 2316 { ETXTBSY, ALL },
940#ifdef SYSV 2317#ifdef EAGAIN
941 { EAGAIN, E_EXEC, "not enough memory" }, 2318 { EAGAIN, E_EXEC },
942#endif 2319#endif
943 { ENOMEM, ALL, "not enough memory" }, 2320 { ENOMEM, ALL },
944#ifdef ENOLINK 2321#ifdef ENOLINK
945 { ENOLINK, ALL, "remote access failed" }, 2322 { ENOLINK, ALL },
946#endif 2323#endif
947#ifdef EMULTIHOP 2324#ifdef EMULTIHOP
948 { EMULTIHOP, ALL, "remote access failed" }, 2325 { EMULTIHOP, ALL },
949#endif 2326#endif
950#ifdef ECOMM 2327#ifdef ECOMM
951 { ECOMM, ALL, "remote access failed" }, 2328 { ECOMM, ALL },
952#endif 2329#endif
953#ifdef ESTALE 2330#ifdef ESTALE
954 { ESTALE, ALL, "remote access failed" }, 2331 { ESTALE, ALL },
955#endif 2332#endif
956#ifdef ETIMEDOUT 2333#ifdef ETIMEDOUT
957 { ETIMEDOUT, ALL, "remote access failed" }, 2334 { ETIMEDOUT, ALL },
958#endif 2335#endif
959#ifdef ELOOP 2336#ifdef ELOOP
960 { ELOOP, ALL, "symbolic link loop" }, 2337 { ELOOP, ALL },
961#endif 2338#endif
962 { E2BIG, E_EXEC, "argument list too long" }, 2339 { E2BIG, E_EXEC },
963#ifdef ELIBACC 2340#ifdef ELIBACC
964 { ELIBACC, E_EXEC, "shared library missing" }, 2341 { ELIBACC, E_EXEC },
965#endif 2342#endif
966 { 0, 0, NULL },
967}; 2343};
968 2344
2345#define ERRNAME_SIZE (sizeof(errormsg)/sizeof(struct errname))
969 2346
970/* 2347/*
971 * Return a string describing an error. The returned string may be a 2348 * Return a string describing an error. The returned string may be a
@@ -974,23 +2351,22 @@ static const struct errname errormsg[] = {
974 */ 2351 */
975 2352
976static const char * 2353static const char *
977errmsg(e, action) 2354errmsg(int e, int action)
978 int e;
979 int action;
980{ 2355{
981 struct errname const *ep; 2356 struct errname const *ep;
982 static char buf[12]; 2357 static char buf[12];
983 2358
984 for (ep = errormsg ; ep->errcode ; ep++) { 2359 for (ep = errormsg ; ep < errormsg+ERRNAME_SIZE; ep++) {
985 if (ep->errcode == e && (ep->action & action) != 0) 2360 if (ep->errcode == e && (ep->action & action) != 0)
986 return ep->msg; 2361 return strerror(e);
987 } 2362 }
2363
988 fmtstr(buf, sizeof buf, "error %d", e); 2364 fmtstr(buf, sizeof buf, "error %d", e);
989 return buf; 2365 return buf;
990} 2366}
991 2367
992 2368
993#ifdef REALLY_SMALL 2369#ifndef ASH_BBAPPS_AS_BUILTINS
994static void 2370static void
995__inton() { 2371__inton() {
996 if (--suppressint == 0 && intpending) { 2372 if (--suppressint == 0 && intpending) {
@@ -998,104 +2374,91 @@ __inton() {
998 } 2374 }
999} 2375}
1000#endif 2376#endif
1001/* $NetBSD: eval.c,v 1.57 2001/02/04 19:52:06 christos Exp $ */
1002
1003 2377
1004/* flags in argument to evaltree */ 2378/* flags in argument to evaltree */
1005#define EV_EXIT 01 /* exit after evaluating tree */ 2379#define EV_EXIT 01 /* exit after evaluating tree */
1006#define EV_TESTED 02 /* exit status is checked; ignore -e flag */ 2380#define EV_TESTED 02 /* exit status is checked; ignore -e flag */
1007#define EV_BACKCMD 04 /* command executing within back quotes */ 2381#define EV_BACKCMD 04 /* command executing within back quotes */
2382
2383static int evalskip; /* set if we are skipping commands */
2384static int skipcount; /* number of levels to skip */
2385static int loopnest; /* current loop nesting level */
2386static int funcnest; /* depth of function calls */
1008 2387
1009static int evalskip; /* set if we are skipping commands */
1010static int skipcount; /* number of levels to skip */
1011static int loopnest; /* current loop nesting level */
1012static int funcnest; /* depth of function calls */
1013 2388
1014 2389
1015static char *commandname; 2390static struct strlist *cmdenviron; /* environment for builtin command */
1016struct strlist *cmdenviron; 2391static int exitstatus; /* exit status of last command */
1017static int exitstatus; /* exit status of last command */ 2392static int oexitstatus; /* saved exit status */
1018static int oexitstatus; /* saved exit status */
1019 2393
1020 2394
1021static void evalloop __P((union node *, int)); 2395static void evalloop (union node *, int);
1022static void evalfor __P((union node *, int)); 2396static void evalfor (union node *, int);
1023static void evalcase __P((union node *, int)); 2397static void evalcase (union node *, int);
1024static void evalsubshell __P((union node *, int)); 2398static void evalsubshell (union node *, int);
1025static void expredir __P((union node *)); 2399static void expredir (union node *);
1026static void evalpipe __P((union node *)); 2400static void evalpipe (union node *);
1027#ifdef notyet 2401#ifdef notyet
1028static void evalcommand __P((union node *, int, struct backcmd *)); 2402static void evalcommand (union node *, int, struct backcmd *);
1029#else 2403#else
1030static void evalcommand __P((union node *, int)); 2404static void evalcommand (union node *, int);
1031#endif 2405#endif
1032static void prehash __P((union node *)); 2406static void prehash (union node *);
1033static void eprintlist __P((struct strlist *)); 2407static void eprintlist (struct strlist *);
1034
1035 2408
2409static union node *parsecmd(int);
1036/* 2410/*
1037 * Called to reset things after an exception. 2411 * Called to reset things after an exception.
1038 */ 2412 */
1039 2413
1040#ifdef mkinit
1041INCLUDE "eval.h"
1042
1043RESET {
1044 evalskip = 0;
1045 loopnest = 0;
1046 funcnest = 0;
1047}
1048
1049SHELLPROC {
1050 exitstatus = 0;
1051}
1052#endif
1053
1054
1055
1056/* 2414/*
1057 * The eval commmand. 2415 * The eval commmand.
1058 */ 2416 */
2417static void evalstring (char *, int);
1059 2418
1060static int 2419static int
1061evalcmd(argc, argv) 2420evalcmd(argc, argv)
1062 int argc; 2421 int argc;
1063 char **argv; 2422 char **argv;
1064{ 2423{
1065 char *p; 2424 char *p;
1066 char *concat; 2425 char *concat;
1067 char **ap; 2426 char **ap;
1068 2427
1069 if (argc > 1) { 2428 if (argc > 1) {
1070 p = argv[1]; 2429 p = argv[1];
1071 if (argc > 2) { 2430 if (argc > 2) {
1072 STARTSTACKSTR(concat); 2431 STARTSTACKSTR(concat);
1073 ap = argv + 2; 2432 ap = argv + 2;
1074 for (;;) { 2433 for (;;) {
1075 while (*p) 2434 while (*p)
1076 STPUTC(*p++, concat); 2435 STPUTC(*p++, concat);
1077 if ((p = *ap++) == NULL) 2436 if ((p = *ap++) == NULL)
1078 break; 2437 break;
1079 STPUTC(' ', concat); 2438 STPUTC(' ', concat);
1080 } 2439 }
1081 STPUTC('\0', concat); 2440 STPUTC('\0', concat);
1082 p = grabstackstr(concat); 2441 p = grabstackstr(concat);
1083 } 2442 }
1084 evalstring(p, EV_TESTED); 2443 evalstring(p, EV_TESTED);
1085 } 2444 }
1086 return exitstatus; 2445 return exitstatus;
1087} 2446}
1088 2447
1089
1090/* 2448/*
1091 * Execute a command or commands contained in a string. 2449 * Execute a command or commands contained in a string.
1092 */ 2450 */
1093 2451
2452static void evaltree (union node *, int);
2453static void setinputstring (char *);
2454static void popfile (void);
2455static void setstackmark(struct stackmark *mark);
2456static void popstackmark(struct stackmark *mark);
2457
2458
1094static void 2459static void
1095evalstring(s, flag) 2460evalstring(char *s, int flag)
1096 char *s; 2461{
1097 int flag;
1098 {
1099 union node *n; 2462 union node *n;
1100 struct stackmark smark; 2463 struct stackmark smark;
1101 2464
@@ -1109,12 +2472,12 @@ evalstring(s, flag)
1109 popstackmark(&smark); 2472 popstackmark(&smark);
1110} 2473}
1111 2474
1112
1113
1114/* 2475/*
1115 * Evaluate a parse tree. The value is left in the global variable 2476 * Evaluate a parse tree. The value is left in the global variable
1116 * exitstatus. 2477 * exitstatus.
1117 */ 2478 */
2479static struct builtincmd *find_builtin (const char *);
2480static void defun (char *, union node *);
1118 2481
1119static void 2482static void
1120evaltree(n, flags) 2483evaltree(n, flags)
@@ -1184,7 +2547,7 @@ evaltree(n, flags)
1184 struct builtincmd *bcmd; 2547 struct builtincmd *bcmd;
1185 if ( 2548 if (
1186 (bcmd = find_builtin(n->narg.text)) && 2549 (bcmd = find_builtin(n->narg.text)) &&
1187 bcmd->flags & BUILTIN_SPECIAL 2550 IS_BUILTIN_SPECIAL(bcmd)
1188 ) { 2551 ) {
1189 outfmt(out2, "%s is a special built-in\n", n->narg.text); 2552 outfmt(out2, "%s is a special built-in\n", n->narg.text);
1190 exitstatus = 1; 2553 exitstatus = 1;
@@ -1243,7 +2606,7 @@ evalloop(n, flags)
1243 for (;;) { 2606 for (;;) {
1244 evaltree(n->nbinary.ch1, EV_TESTED); 2607 evaltree(n->nbinary.ch1, EV_TESTED);
1245 if (evalskip) { 2608 if (evalskip) {
1246skipping: if (evalskip == SKIPCONT && --skipcount <= 0) { 2609skipping: if (evalskip == SKIPCONT && --skipcount <= 0) {
1247 evalskip = 0; 2610 evalskip = 0;
1248 continue; 2611 continue;
1249 } 2612 }
@@ -1267,7 +2630,8 @@ skipping: if (evalskip == SKIPCONT && --skipcount <= 0) {
1267 exitstatus = status; 2630 exitstatus = status;
1268} 2631}
1269 2632
1270 2633static void expandarg (union node *, struct arglist *, int);
2634static void fixredir(union node *n, const char *text, int err);
1271 2635
1272static void 2636static void
1273evalfor(n, flags) 2637evalfor(n, flags)
@@ -1310,7 +2674,6 @@ out:
1310} 2674}
1311 2675
1312 2676
1313
1314static void 2677static void
1315evalcase(n, flags) 2678evalcase(n, flags)
1316 union node *n; 2679 union node *n;
@@ -1339,8 +2702,6 @@ out:
1339 popstackmark(&smark); 2702 popstackmark(&smark);
1340} 2703}
1341 2704
1342
1343
1344/* 2705/*
1345 * Kick off a subshell to evaluate a tree. 2706 * Kick off a subshell to evaluate a tree.
1346 */ 2707 */
@@ -1359,7 +2720,7 @@ evalsubshell(n, flags)
1359 if (backgnd) 2720 if (backgnd)
1360 flags &=~ EV_TESTED; 2721 flags &=~ EV_TESTED;
1361 redirect(n->nredir.redirect, 0); 2722 redirect(n->nredir.redirect, 0);
1362 evaltree(n->nredir.n, flags | EV_EXIT); /* never returns */ 2723 evaltree(n->nredir.n, flags | EV_EXIT); /* never returns */
1363 } 2724 }
1364 if (! backgnd) { 2725 if (! backgnd) {
1365 INTOFF; 2726 INTOFF;
@@ -1404,8 +2765,6 @@ expredir(n)
1404 } 2765 }
1405} 2766}
1406 2767
1407
1408
1409/* 2768/*
1410 * Evaluate a pipeline. All the processes in the pipeline are children 2769 * Evaluate a pipeline. All the processes in the pipeline are children
1411 * of the process creating the pipeline. (This differs from some versions 2770 * of the process creating the pipeline. (This differs from some versions
@@ -1485,13 +2844,11 @@ evalpipe(n)
1485 */ 2844 */
1486 2845
1487static void 2846static void
1488evalbackcmd(n, result) 2847evalbackcmd(union node *n, struct backcmd *result)
1489 union node *n;
1490 struct backcmd *result;
1491{ 2848{
1492 int pip[2]; 2849 int pip[2];
1493 struct job *jp; 2850 struct job *jp;
1494 struct stackmark smark; /* unnecessary */ 2851 struct stackmark smark; /* unnecessary */
1495 2852
1496 setstackmark(&smark); 2853 setstackmark(&smark);
1497 result->fd = -1; 2854 result->fd = -1;
@@ -1546,6 +2903,19 @@ out:
1546 * Execute a simple command. 2903 * Execute a simple command.
1547 */ 2904 */
1548 2905
2906static void find_command (const char *, struct cmdentry *, int, const char *);
2907
2908static int
2909isassignment(const char *word) {
2910 if (!is_name(*word)) {
2911 return 0;
2912 }
2913 do {
2914 word++;
2915 } while (is_in_name(*word));
2916 return *word == '=';
2917}
2918
1549static void 2919static void
1550#ifdef notyet 2920#ifdef notyet
1551evalcommand(cmd, flags, backcmd) 2921evalcommand(cmd, flags, backcmd)
@@ -1611,7 +2981,7 @@ evalcommand(cmd, flags)
1611 struct builtincmd *bcmd; 2981 struct builtincmd *bcmd;
1612 bool pseudovarflag; 2982 bool pseudovarflag;
1613 bcmd = find_builtin(arglist.list->text); 2983 bcmd = find_builtin(arglist.list->text);
1614 pseudovarflag = bcmd && bcmd->flags & BUILTIN_ASSIGN; 2984 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
1615 for (; argp; argp = argp->narg.next) { 2985 for (; argp; argp = argp->narg.next) {
1616 if (pseudovarflag && isassignment(argp->narg.text)) { 2986 if (pseudovarflag && isassignment(argp->narg.text)) {
1617 expandarg(argp, &arglist, EXP_VARTILDE); 2987 expandarg(argp, &arglist, EXP_VARTILDE);
@@ -1678,7 +3048,7 @@ evalcommand(cmd, flags)
1678 firstbltin = 0; 3048 firstbltin = 0;
1679 for(;;) { 3049 for(;;) {
1680 find_command(argv[0], &cmdentry, findflag, path); 3050 find_command(argv[0], &cmdentry, findflag, path);
1681 if (cmdentry.cmdtype == CMDUNKNOWN) { /* command not found */ 3051 if (cmdentry.cmdtype == CMDUNKNOWN) { /* command not found */
1682 exitstatus = 127; 3052 exitstatus = 127;
1683#ifdef FLUSHERR 3053#ifdef FLUSHERR
1684 flushout(&errout); 3054 flushout(&errout);
@@ -1712,7 +3082,7 @@ evalcommand(cmd, flags)
1712 break; 3082 break;
1713 } 3083 }
1714 } 3084 }
1715 if (cmdentry.u.cmd == COMMANDCMD) { 3085 if (cmdentry.u.cmd == find_builtin("command")) {
1716 argv++; 3086 argv++;
1717 if (--argc == 0) { 3087 if (--argc == 0) {
1718 goto found; 3088 goto found;
@@ -1761,7 +3131,7 @@ found:
1761 } 3131 }
1762#endif 3132#endif
1763 if (forkshell(jp, cmd, mode) != 0) 3133 if (forkshell(jp, cmd, mode) != 0)
1764 goto parent; /* at end of routine */ 3134 goto parent; /* at end of routine */
1765#ifdef notyet 3135#ifdef notyet
1766 if (flags & EV_BACKCMD) { 3136 if (flags & EV_BACKCMD) {
1767 FORCEINTON; 3137 FORCEINTON;
@@ -1849,7 +3219,7 @@ found:
1849#endif 3219#endif
1850 redirect(cmd->ncmd.redirect, mode); 3220 redirect(cmd->ncmd.redirect, mode);
1851 savecmdname = commandname; 3221 savecmdname = commandname;
1852 if (firstbltin->flags & BUILTIN_SPECIAL) { 3222 if (IS_BUILTIN_SPECIAL(firstbltin)) {
1853 listsetvar(varlist.list); 3223 listsetvar(varlist.list);
1854 } else { 3224 } else {
1855 cmdenviron = varlist.list; 3225 cmdenviron = varlist.list;
@@ -1864,7 +3234,7 @@ found:
1864 handler = &jmploc; 3234 handler = &jmploc;
1865 commandname = argv[0]; 3235 commandname = argv[0];
1866 argptr = argv + 1; 3236 argptr = argv + 1;
1867 optptr = NULL; /* initialize nextopt */ 3237 optptr = NULL; /* initialize nextopt */
1868 exitstatus = (*cmdentry.u.cmd->builtinfunc)(argc, argv); 3238 exitstatus = (*cmdentry.u.cmd->builtinfunc)(argc, argv);
1869 flushall(); 3239 flushall();
1870cmddone: 3240cmddone:
@@ -1894,12 +3264,8 @@ cmddone:
1894 if (flags == EV_BACKCMD) { 3264 if (flags == EV_BACKCMD) {
1895 INTOFF; 3265 INTOFF;
1896#ifdef USE_GLIBC_STDIO 3266#ifdef USE_GLIBC_STDIO
1897 if (__closememout()) { 3267 if (__closememout())
1898 error( 3268 error("__closememout() failed: %m");
1899 "__closememout() failed: %s",
1900 strerror(errno)
1901 );
1902 }
1903#endif 3269#endif
1904 backcmd->buf = memout.buf; 3270 backcmd->buf = memout.buf;
1905#ifdef USE_GLIBC_STDIO 3271#ifdef USE_GLIBC_STDIO
@@ -1924,8 +3290,8 @@ cmddone:
1924 } 3290 }
1925 goto out; 3291 goto out;
1926 3292
1927parent: /* parent process gets here (if we forked) */ 3293parent: /* parent process gets here (if we forked) */
1928 if (mode == 0) { /* argument to fork */ 3294 if (mode == 0) { /* argument to fork */
1929 INTOFF; 3295 INTOFF;
1930 exitstatus = waitforjob(jp); 3296 exitstatus = waitforjob(jp);
1931 INTON; 3297 INTON;
@@ -2043,6 +3409,7 @@ returncmd(argc, argv)
2043 3409
2044 3410
2045#ifndef BB_TRUE_FALSE 3411#ifndef BB_TRUE_FALSE
3412#ifdef ASH_BBAPPS_AS_BUILTINS
2046static int 3413static int
2047false_main(argc, argv) 3414false_main(argc, argv)
2048 int argc; 3415 int argc;
@@ -2060,6 +3427,37 @@ true_main(argc, argv)
2060 return 0; 3427 return 0;
2061} 3428}
2062#endif 3429#endif
3430#endif
3431
3432/*
3433 * Controls whether the shell is interactive or not.
3434 */
3435
3436static void setsignal(int signo);
3437static void chkmail(int silent);
3438
3439
3440static void
3441setinteractive(int on)
3442{
3443 static int is_interactive;
3444
3445 if (on == is_interactive)
3446 return;
3447 setsignal(SIGINT);
3448 setsignal(SIGQUIT);
3449 setsignal(SIGTERM);
3450 chkmail(1);
3451 is_interactive = on;
3452}
3453
3454static void
3455optschanged(void)
3456{
3457 setinteractive(iflag);
3458 setjobctl(mflag);
3459}
3460
2063 3461
2064static int 3462static int
2065execcmd(argc, argv) 3463execcmd(argc, argv)
@@ -2069,7 +3467,7 @@ execcmd(argc, argv)
2069 if (argc > 1) { 3467 if (argc > 1) {
2070 struct strlist *sp; 3468 struct strlist *sp;
2071 3469
2072 iflag = 0; /* exit on error */ 3470 iflag = 0; /* exit on error */
2073 mflag = 0; 3471 mflag = 0;
2074 optschanged(); 3472 optschanged();
2075 for (sp = cmdenviron; sp ; sp = sp->next) 3473 for (sp = cmdenviron; sp ; sp = sp->next)
@@ -2086,8 +3484,6 @@ eprintlist(struct strlist *sp)
2086 outfmt(&errout, " %s",sp->text); 3484 outfmt(&errout, " %s",sp->text);
2087 } 3485 }
2088} 3486}
2089/* $NetBSD: exec.c,v 1.32 2001/02/04 19:52:06 christos Exp $ */
2090
2091/* 3487/*
2092 * When commands are first encountered, they are entered in a hash table. 3488 * When commands are first encountered, they are entered in a hash table.
2093 * This ensures that a full path search will not have to be done for them 3489 * This ensures that a full path search will not have to be done for them
@@ -2096,37 +3492,34 @@ eprintlist(struct strlist *sp)
2096 * We should investigate converting to a linear search, even though that 3492 * We should investigate converting to a linear search, even though that
2097 * would make the command name "hash" a misnomer. 3493 * would make the command name "hash" a misnomer.
2098 */ 3494 */
2099#define CMDTABLESIZE 31 /* should be prime */ 3495#define CMDTABLESIZE 31 /* should be prime */
2100#define ARB 1 /* actual size determined at run time */ 3496#define ARB 1 /* actual size determined at run time */
2101 3497
2102 3498
2103 3499
2104struct tblentry { 3500struct tblentry {
2105 struct tblentry *next; /* next entry in hash chain */ 3501 struct tblentry *next; /* next entry in hash chain */
2106 union param param; /* definition of builtin function */ 3502 union param param; /* definition of builtin function */
2107 short cmdtype; /* index identifying command */ 3503 short cmdtype; /* index identifying command */
2108 char rehash; /* if set, cd done since entry created */ 3504 char rehash; /* if set, cd done since entry created */
2109 char cmdname[ARB]; /* name of command */ 3505 char cmdname[ARB]; /* name of command */
2110}; 3506};
2111 3507
2112 3508
2113static struct tblentry *cmdtable[CMDTABLESIZE]; 3509static struct tblentry *cmdtable[CMDTABLESIZE];
2114static int builtinloc = -1; /* index in path of %builtin, or -1 */ 3510static int builtinloc = -1; /* index in path of %builtin, or -1 */
2115static int exerrno = 0; /* Last exec error */ 3511static int exerrno = 0; /* Last exec error */
2116 3512
2117 3513
2118static void tryexec __P((char *, char **, char **)); 3514static void tryexec (char *, char **, char **);
2119#if !defined(BSD) && !defined(linux) 3515static void printentry (struct tblentry *, int);
2120static void execinterp __P((char **, char **)); 3516static void clearcmdentry (int);
2121#endif 3517static struct tblentry *cmdlookup (const char *, int);
2122static void printentry __P((struct tblentry *, int)); 3518static void delete_cmd_entry (void);
2123static void clearcmdentry __P((int));
2124static struct tblentry *cmdlookup __P((char *, int));
2125static void delete_cmd_entry __P((void));
2126#ifdef ASH_TYPE 3519#ifdef ASH_TYPE
2127static int describe_command __P((char *, int)); 3520static int describe_command (char *, int);
2128#endif 3521#endif
2129static int path_change __P((const char *, int *)); 3522static int path_change (const char *, int *);
2130 3523
2131 3524
2132/* 3525/*
@@ -2134,6 +3527,8 @@ static int path_change __P((const char *, int *));
2134 * have to change the find_command routine as well. 3527 * have to change the find_command routine as well.
2135 */ 3528 */
2136 3529
3530static const char *pathopt; /* set by padvance */
3531
2137static void 3532static void
2138shellexec(argv, envp, path, idx) 3533shellexec(argv, envp, path, idx)
2139 char **argv, **envp; 3534 char **argv, **envp;
@@ -2174,6 +3569,225 @@ shellexec(argv, envp, path, idx)
2174 /* NOTREACHED */ 3569 /* NOTREACHED */
2175} 3570}
2176 3571
3572/*
3573 * Clear traps on a fork.
3574 */
3575static void
3576clear_traps(void) {
3577 char **tp;
3578
3579 for (tp = trap ; tp < &trap[NSIG] ; tp++) {
3580 if (*tp && **tp) { /* trap not NULL or SIG_IGN */
3581 INTOFF;
3582 ckfree(*tp);
3583 *tp = NULL;
3584 if (tp != &trap[0])
3585 setsignal(tp - trap);
3586 INTON;
3587 }
3588 }
3589}
3590
3591
3592static void
3593initshellproc(void) {
3594
3595#ifdef ASH_ALIAS
3596 /* from alias.c: */
3597 {
3598 rmaliases();
3599 }
3600#endif
3601 /* from eval.c: */
3602 {
3603 exitstatus = 0;
3604 }
3605
3606 /* from exec.c: */
3607 {
3608 deletefuncs();
3609 }
3610
3611 /* from jobs.c: */
3612 {
3613 backgndpid = -1;
3614#ifdef JOBS
3615 jobctl = 0;
3616#endif
3617 }
3618
3619 /* from options.c: */
3620 {
3621 int i;
3622
3623 for (i = 0; i < NOPTS; i++)
3624 optent_val(i) = 0;
3625 optschanged();
3626
3627 }
3628
3629 /* from redir.c: */
3630 {
3631 clearredir();
3632 }
3633
3634 /* from trap.c: */
3635 {
3636 char *sm;
3637
3638 clear_traps();
3639 for (sm = sigmode ; sm < sigmode + NSIG - 1; sm++) {
3640 if (*sm == S_IGN)
3641 *sm = S_HARD_IGN;
3642 }
3643 }
3644
3645 /* from var.c: */
3646 {
3647 shprocvar();
3648 }
3649}
3650
3651static int preadbuffer(void);
3652static void pushfile (void);
3653static int preadfd (void);
3654
3655/*
3656 * Read a character from the script, returning PEOF on end of file.
3657 * Nul characters in the input are silently discarded.
3658 */
3659
3660#ifdef ASH_BBAPPS_AS_BUILTINS
3661#define pgetc_macro() (--parsenleft >= 0? *parsenextc++ : preadbuffer())
3662static int
3663pgetc(void)
3664{
3665 return pgetc_macro();
3666}
3667#else
3668static int
3669pgetc_macro(void)
3670{
3671 return --parsenleft >= 0? *parsenextc++ : preadbuffer();
3672}
3673
3674static inline int
3675pgetc(void)
3676{
3677 return pgetc_macro();
3678}
3679#endif
3680
3681
3682/*
3683 * Undo the last call to pgetc. Only one character may be pushed back.
3684 * PEOF may be pushed back.
3685 */
3686
3687static void
3688pungetc() {
3689 parsenleft++;
3690 parsenextc--;
3691}
3692
3693
3694static void
3695popfile(void) {
3696 struct parsefile *pf = parsefile;
3697
3698 INTOFF;
3699 if (pf->fd >= 0)
3700 close(pf->fd);
3701 if (pf->buf)
3702 ckfree(pf->buf);
3703 while (pf->strpush)
3704 popstring();
3705 parsefile = pf->prev;
3706 ckfree(pf);
3707 parsenleft = parsefile->nleft;
3708 parselleft = parsefile->lleft;
3709 parsenextc = parsefile->nextc;
3710 plinno = parsefile->linno;
3711 INTON;
3712}
3713
3714
3715/*
3716 * Return to top level.
3717 */
3718
3719static void
3720popallfiles(void) {
3721 while (parsefile != &basepf)
3722 popfile();
3723}
3724
3725/*
3726 * Close the file(s) that the shell is reading commands from. Called
3727 * after a fork is done.
3728 */
3729
3730static void
3731closescript() {
3732 popallfiles();
3733 if (parsefile->fd > 0) {
3734 close(parsefile->fd);
3735 parsefile->fd = 0;
3736 }
3737}
3738
3739
3740/*
3741 * Like setinputfile, but takes an open file descriptor. Call this with
3742 * interrupts off.
3743 */
3744
3745static void
3746setinputfd(fd, push)
3747 int fd, push;
3748{
3749 (void) fcntl(fd, F_SETFD, FD_CLOEXEC);
3750 if (push) {
3751 pushfile();
3752 parsefile->buf = 0;
3753 } else {
3754 closescript();
3755 while (parsefile->strpush)
3756 popstring();
3757 }
3758 parsefile->fd = fd;
3759 if (parsefile->buf == NULL)
3760 parsefile->buf = ckmalloc(BUFSIZ);
3761 parselleft = parsenleft = 0;
3762 plinno = 1;
3763}
3764
3765
3766/*
3767 * Set the input to take input from a file. If push is set, push the
3768 * old input onto the stack first.
3769 */
3770
3771static void
3772setinputfile(const char *fname, int push)
3773{
3774 int fd;
3775 int myfileno2;
3776
3777 INTOFF;
3778 if ((fd = open(fname, O_RDONLY)) < 0)
3779 error("Can't open %s", fname);
3780 if (fd < 10) {
3781 myfileno2 = dup_as_newfd(fd, 10);
3782 close(fd);
3783 if (myfileno2 < 0)
3784 error("Out of file descriptors");
3785 fd = myfileno2;
3786 }
3787 setinputfd(fd, push);
3788 INTON;
3789}
3790
2177 3791
2178static void 3792static void
2179tryexec(cmd, argv, envp) 3793tryexec(cmd, argv, envp)
@@ -2182,119 +3796,21 @@ tryexec(cmd, argv, envp)
2182 char **envp; 3796 char **envp;
2183 { 3797 {
2184 int e; 3798 int e;
2185#if !defined(BSD) && !defined(linux)
2186 char *p;
2187#endif
2188 3799
2189#ifdef SYSV
2190 do {
2191 execve(cmd, argv, envp);
2192 } while (errno == EINTR);
2193#else
2194 execve(cmd, argv, envp); 3800 execve(cmd, argv, envp);
2195#endif
2196 e = errno; 3801 e = errno;
2197 if (e == ENOEXEC) { 3802 if (e == ENOEXEC) {
2198 INTOFF; 3803 INTOFF;
2199 initshellproc(); 3804 initshellproc();
2200 setinputfile(cmd, 0); 3805 setinputfile(cmd, 0);
2201 commandname = arg0 = savestr(argv[0]); 3806 commandname = arg0 = savestr(argv[0]);
2202#if !defined(BSD) && !defined(linux)
2203 INTON;
2204 pgetc(); pungetc(); /* fill up input buffer */
2205 p = parsenextc;
2206 if (parsenleft > 2 && p[0] == '#' && p[1] == '!') {
2207 argv[0] = cmd;
2208 execinterp(argv, envp);
2209 }
2210 INTOFF;
2211#endif
2212 setparam(argv + 1); 3807 setparam(argv + 1);
2213 exraise(EXSHELLPROC); 3808 exraise(EXSHELLPROC);
2214 } 3809 }
2215 errno = e; 3810 errno = e;
2216} 3811}
2217 3812
2218 3813static char *commandtext (const union node *);
2219#if !defined(BSD) && !defined(linux)
2220/*
2221 * Execute an interpreter introduced by "#!", for systems where this
2222 * feature has not been built into the kernel. If the interpreter is
2223 * the shell, return (effectively ignoring the "#!"). If the execution
2224 * of the interpreter fails, exit.
2225 *
2226 * This code peeks inside the input buffer in order to avoid actually
2227 * reading any input. It would benefit from a rewrite.
2228 */
2229
2230#define NEWARGS 5
2231
2232static void
2233execinterp(argv, envp)
2234 char **argv, **envp;
2235 {
2236 int n;
2237 char *inp;
2238 char *outp;
2239 char c;
2240 char *p;
2241 char **ap;
2242 char *newargs[NEWARGS];
2243 int i;
2244 char **ap2;
2245 char **new;
2246
2247 n = parsenleft - 2;
2248 inp = parsenextc + 2;
2249 ap = newargs;
2250 for (;;) {
2251 while (--n >= 0 && (*inp == ' ' || *inp == '\t'))
2252 inp++;
2253 if (n < 0)
2254 goto bad;
2255 if ((c = *inp++) == '\n')
2256 break;
2257 if (ap == &newargs[NEWARGS])
2258bad: error("Bad #! line");
2259 STARTSTACKSTR(outp);
2260 do {
2261 STPUTC(c, outp);
2262 } while (--n >= 0 && (c = *inp++) != ' ' && c != '\t' && c != '\n');
2263 STPUTC('\0', outp);
2264 n++, inp--;
2265 *ap++ = grabstackstr(outp);
2266 }
2267 if (ap == newargs + 1) { /* if no args, maybe no exec is needed */
2268 p = newargs[0];
2269 for (;;) {
2270 if (equal(p, "sh") || equal(p, "ash")) {
2271 return;
2272 }
2273 while (*p != '/') {
2274 if (*p == '\0')
2275 goto break2;
2276 p++;
2277 }
2278 p++;
2279 }
2280break2:;
2281 }
2282 i = (char *)ap - (char *)newargs; /* size in bytes */
2283 if (i == 0)
2284 error("Bad #! line");
2285 for (ap2 = argv ; *ap2++ != NULL ; );
2286 new = ckmalloc(i + ((char *)ap2 - (char *)argv));
2287 ap = newargs, ap2 = new;
2288 while ((i -= sizeof (char **)) >= 0)
2289 *ap2++ = *ap++;
2290 ap = argv;
2291 while (*ap2++ = *ap++);
2292 shellexec(new, envp, pathval(), 0);
2293 /* NOTREACHED */
2294}
2295#endif
2296
2297
2298 3814
2299/* 3815/*
2300 * Do a path search. The variable path (passed by reference) should be 3816 * Do a path search. The variable path (passed by reference) should be
@@ -2308,11 +3824,12 @@ break2:;
2308 3824
2309static const char *pathopt; 3825static const char *pathopt;
2310 3826
3827static void growstackblock(void);
3828
3829
2311static char * 3830static char *
2312padvance(path, name) 3831padvance(const char **path, const char *name)
2313 const char **path; 3832{
2314 const char *name;
2315 {
2316 const char *p; 3833 const char *p;
2317 char *q; 3834 char *q;
2318 const char *start; 3835 const char *start;
@@ -2322,7 +3839,7 @@ padvance(path, name)
2322 return NULL; 3839 return NULL;
2323 start = *path; 3840 start = *path;
2324 for (p = start ; *p && *p != ':' && *p != '%' ; p++); 3841 for (p = start ; *p && *p != ':' && *p != '%' ; p++);
2325 len = p - start + strlen(name) + 2; /* "2" is for '/' and '\0' */ 3842 len = p - start + strlen(name) + 2; /* "2" is for '/' and '\0' */
2326 while (stackblocksize() < len) 3843 while (stackblocksize() < len)
2327 growstackblock(); 3844 growstackblock();
2328 q = stackblock(); 3845 q = stackblock();
@@ -2442,12 +3959,10 @@ printentry(cmdp, verbose)
2442 * change the shellexec routine as well. 3959 * change the shellexec routine as well.
2443 */ 3960 */
2444 3961
3962static int prefix (const char *, const char *);
3963
2445static void 3964static void
2446find_command(name, entry, act, path) 3965find_command(const char *name, struct cmdentry *entry, int act, const char *path)
2447 char *name;
2448 struct cmdentry *entry;
2449 int act;
2450 const char *path;
2451{ 3966{
2452 struct tblentry *cmdp; 3967 struct tblentry *cmdp;
2453 int idx; 3968 int idx;
@@ -2465,10 +3980,6 @@ find_command(name, entry, act, path)
2465 if (strchr(name, '/') != NULL) { 3980 if (strchr(name, '/') != NULL) {
2466 if (act & DO_ABS) { 3981 if (act & DO_ABS) {
2467 while (stat(name, &statb) < 0) { 3982 while (stat(name, &statb) < 0) {
2468 #ifdef SYSV
2469 if (errno == EINTR)
2470 continue;
2471 #endif
2472 if (errno != ENOENT && errno != ENOTDIR) 3983 if (errno != ENOENT && errno != ENOTDIR)
2473 e = errno; 3984 e = errno;
2474 entry->cmdtype = CMDUNKNOWN; 3985 entry->cmdtype = CMDUNKNOWN;
@@ -2516,11 +4027,11 @@ find_command(name, entry, act, path)
2516 } 4027 }
2517 4028
2518 bcmd = find_builtin(name); 4029 bcmd = find_builtin(name);
2519 regular = bcmd && bcmd->flags & BUILTIN_REGULAR; 4030 regular = bcmd && IS_BUILTIN_REGULAR(bcmd);
2520 4031
2521 if (regular) { 4032 if (regular) {
2522 if (cmdp && (cmdp->cmdtype == CMDBUILTIN)) { 4033 if (cmdp && (cmdp->cmdtype == CMDBUILTIN)) {
2523 goto success; 4034 goto success;
2524 } 4035 }
2525 } else if (act & DO_BRUTE) { 4036 } else if (act & DO_BRUTE) {
2526 if (firstchange == 0) { 4037 if (firstchange == 0) {
@@ -2545,8 +4056,8 @@ builtin:
2545 } 4056 }
2546 4057
2547 /* We have to search path. */ 4058 /* We have to search path. */
2548 prev = -1; /* where to start */ 4059 prev = -1; /* where to start */
2549 if (cmdp && cmdp->rehash) { /* doing a rehash */ 4060 if (cmdp && cmdp->rehash) { /* doing a rehash */
2550 if (cmdp->cmdtype == CMDBUILTIN) 4061 if (cmdp->cmdtype == CMDBUILTIN)
2551 prev = builtinloc; 4062 prev = builtinloc;
2552 else 4063 else
@@ -2572,7 +4083,7 @@ loop:
2572 prefix("func", pathopt)) { 4083 prefix("func", pathopt)) {
2573 /* handled below */ 4084 /* handled below */
2574 } else { 4085 } else {
2575 continue; /* ignore unimplemented options */ 4086 continue; /* ignore unimplemented options */
2576 } 4087 }
2577 } 4088 }
2578 /* if rehash, don't redo absolute path names */ 4089 /* if rehash, don't redo absolute path names */
@@ -2584,18 +4095,14 @@ loop:
2584 goto success; 4095 goto success;
2585 } 4096 }
2586 while (stat(fullname, &statb) < 0) { 4097 while (stat(fullname, &statb) < 0) {
2587#ifdef SYSV
2588 if (errno == EINTR)
2589 continue;
2590#endif
2591 if (errno != ENOENT && errno != ENOTDIR) 4098 if (errno != ENOENT && errno != ENOTDIR)
2592 e = errno; 4099 e = errno;
2593 goto loop; 4100 goto loop;
2594 } 4101 }
2595 e = EACCES; /* if we fail, this will be the error */ 4102 e = EACCES; /* if we fail, this will be the error */
2596 if (!S_ISREG(statb.st_mode)) 4103 if (!S_ISREG(statb.st_mode))
2597 continue; 4104 continue;
2598 if (pathopt) { /* this is a %func directory */ 4105 if (pathopt) { /* this is a %func directory */
2599 stalloc(strlen(fullname) + 1); 4106 stalloc(strlen(fullname) + 1);
2600 readcmdfile(fullname); 4107 readcmdfile(fullname);
2601 if ((cmdp = cmdlookup(name, 0)) == NULL || cmdp->cmdtype != CMDFUNCTION) 4108 if ((cmdp = cmdlookup(name, 0)) == NULL || cmdp->cmdtype != CMDFUNCTION)
@@ -2603,18 +4110,6 @@ loop:
2603 stunalloc(fullname); 4110 stunalloc(fullname);
2604 goto success; 4111 goto success;
2605 } 4112 }
2606#ifdef notdef
2607 if (statb.st_uid == geteuid()) {
2608 if ((statb.st_mode & 0100) == 0)
2609 goto loop;
2610 } else if (statb.st_gid == getegid()) {
2611 if ((statb.st_mode & 010) == 0)
2612 goto loop;
2613 } else {
2614 if ((statb.st_mode & 01) == 0)
2615 goto loop;
2616 }
2617#endif
2618 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname)); 4113 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
2619 /* If we aren't called with DO_BRUTE and cmdp is set, it must 4114 /* If we aren't called with DO_BRUTE and cmdp is set, it must
2620 be a function and we're being called with DO_NOFUN */ 4115 be a function and we're being called with DO_NOFUN */
@@ -2651,14 +4146,19 @@ success:
2651 * Search the table of builtin commands. 4146 * Search the table of builtin commands.
2652 */ 4147 */
2653 4148
2654struct builtincmd * 4149static int
2655find_builtin(name) 4150bstrcmp(const void *name, const void *b)
2656 char *name; 4151{
4152 return strcmp((const char *)name, (*(const char *const *) b)+1);
4153}
4154
4155static struct builtincmd *
4156find_builtin(const char *name)
2657{ 4157{
2658 struct builtincmd *bp; 4158 struct builtincmd *bp;
2659 4159
2660 bp = bsearch( &name, builtincmds, NUMBUILTINS, sizeof(struct builtincmd), 4160 bp = bsearch(name, builtincmds, NUMBUILTINS, sizeof(struct builtincmd),
2661 pstrcmp 4161 bstrcmp
2662 ); 4162 );
2663 return bp; 4163 return bp;
2664} 4164}
@@ -2670,7 +4170,7 @@ find_builtin(name)
2670 */ 4170 */
2671 4171
2672static void 4172static void
2673hashcd() { 4173hashcd(void) {
2674 struct tblentry **pp; 4174 struct tblentry **pp;
2675 struct tblentry *cmdp; 4175 struct tblentry *cmdp;
2676 4176
@@ -2692,15 +4192,14 @@ hashcd() {
2692 */ 4192 */
2693 4193
2694static void 4194static void
2695changepath(newval) 4195changepath(const char *newval)
2696 const char *newval;
2697{ 4196{
2698 int firstchange; 4197 int firstchange;
2699 int bltin; 4198 int bltin;
2700 4199
2701 firstchange = path_change(newval, &bltin); 4200 firstchange = path_change(newval, &bltin);
2702 if (builtinloc < 0 && bltin >= 0) 4201 if (builtinloc < 0 && bltin >= 0)
2703 builtinloc = bltin; /* zap builtins */ 4202 builtinloc = bltin; /* zap builtins */
2704 clearcmdentry(firstchange); 4203 clearcmdentry(firstchange);
2705 builtinloc = bltin; 4204 builtinloc = bltin;
2706} 4205}
@@ -2737,21 +4236,24 @@ clearcmdentry(firstchange)
2737 INTON; 4236 INTON;
2738} 4237}
2739 4238
2740
2741/* 4239/*
2742 * Delete all functions. 4240 * Free a parse tree.
2743 */ 4241 */
2744 4242
2745#ifdef mkinit 4243static void
2746static void deletefuncs __P((void)); 4244freefunc(union node *n)
2747 4245{
2748SHELLPROC { 4246 if (n)
2749 deletefuncs(); 4247 ckfree(n);
2750} 4248}
2751#endif 4249
4250
4251/*
4252 * Delete all functions.
4253 */
2752 4254
2753static void 4255static void
2754deletefuncs() { 4256deletefuncs(void) {
2755 struct tblentry **tblp; 4257 struct tblentry **tblp;
2756 struct tblentry **pp; 4258 struct tblentry **pp;
2757 struct tblentry *cmdp; 4259 struct tblentry *cmdp;
@@ -2782,16 +4284,13 @@ deletefuncs() {
2782 * entry. 4284 * entry.
2783 */ 4285 */
2784 4286
2785struct tblentry **lastcmdentry; 4287static struct tblentry **lastcmdentry;
2786
2787 4288
2788static struct tblentry * 4289static struct tblentry *
2789cmdlookup(name, add) 4290cmdlookup(const char *name, int add)
2790 char *name;
2791 int add;
2792{ 4291{
2793 int hashval; 4292 int hashval;
2794 char *p; 4293 const char *p;
2795 struct tblentry *cmdp; 4294 struct tblentry *cmdp;
2796 struct tblentry **pp; 4295 struct tblentry **pp;
2797 4296
@@ -2837,35 +4336,14 @@ delete_cmd_entry() {
2837 4336
2838 4337
2839 4338
2840#ifdef notdef
2841static void
2842getcmdentry(name, entry)
2843 char *name;
2844 struct cmdentry *entry;
2845 {
2846 struct tblentry *cmdp = cmdlookup(name, 0);
2847
2848 if (cmdp) {
2849 entry->u = cmdp->param;
2850 entry->cmdtype = cmdp->cmdtype;
2851 } else {
2852 entry->cmdtype = CMDUNKNOWN;
2853 entry->u.index = 0;
2854 }
2855}
2856#endif
2857
2858
2859/* 4339/*
2860 * Add a new command entry, replacing any existing command entry for 4340 * Add a new command entry, replacing any existing command entry for
2861 * the same name. 4341 * the same name.
2862 */ 4342 */
2863 4343
2864static void 4344static void
2865addcmdentry(name, entry) 4345addcmdentry(char *name, struct cmdentry *entry)
2866 char *name; 4346{
2867 struct cmdentry *entry;
2868 {
2869 struct tblentry *cmdp; 4347 struct tblentry *cmdp;
2870 4348
2871 INTOFF; 4349 INTOFF;
@@ -2883,11 +4361,11 @@ addcmdentry(name, entry)
2883 * Define a shell function. 4361 * Define a shell function.
2884 */ 4362 */
2885 4363
4364static union node *copyfunc(union node *);
4365
2886static void 4366static void
2887defun(name, func) 4367defun(char *name, union node *func)
2888 char *name; 4368{
2889 union node *func;
2890 {
2891 struct cmdentry entry; 4369 struct cmdentry entry;
2892 4370
2893 entry.cmdtype = CMDFUNCTION; 4371 entry.cmdtype = CMDFUNCTION;
@@ -2901,9 +4379,8 @@ defun(name, func)
2901 */ 4379 */
2902 4380
2903static void 4381static void
2904unsetfunc(name) 4382unsetfunc(char *name)
2905 char *name; 4383{
2906 {
2907 struct tblentry *cmdp; 4384 struct tblentry *cmdp;
2908 4385
2909 if ((cmdp = cmdlookup(name, 0)) != NULL && cmdp->cmdtype == CMDFUNCTION) { 4386 if ((cmdp = cmdlookup(name, 0)) != NULL && cmdp->cmdtype == CMDFUNCTION) {
@@ -2912,6 +4389,26 @@ unsetfunc(name)
2912 } 4389 }
2913} 4390}
2914 4391
4392/*
4393 * Wrapper around strcmp for qsort/bsearch/...
4394 */
4395static int
4396pstrcmp(const void *a, const void *b)
4397{
4398 return strcmp((const char *) a, *(const char *const *) b);
4399}
4400
4401/*
4402 * Find a keyword is in a sorted array.
4403 */
4404
4405static const char *const *
4406findkwd(const char *s)
4407{
4408 return bsearch(s, parsekwd, sizeof(parsekwd) / sizeof(const char *),
4409 sizeof(const char *), pstrcmp);
4410}
4411
2915#ifdef ASH_TYPE 4412#ifdef ASH_TYPE
2916/* 4413/*
2917 * Locate and print what a word is... 4414 * Locate and print what a word is...
@@ -2932,13 +4429,13 @@ typecmd(argc, argv)
2932} 4429}
2933 4430
2934static int 4431static int
2935describe_command(command, verbose) 4432describe_command(char *command, int verbose)
2936 char *command;
2937 int verbose;
2938{ 4433{
2939 struct cmdentry entry; 4434 struct cmdentry entry;
2940 struct tblentry *cmdp; 4435 struct tblentry *cmdp;
4436#ifdef ASH_ALIAS
2941 const struct alias *ap; 4437 const struct alias *ap;
4438#endif
2942 const char *path = pathval(); 4439 const char *path = pathval();
2943 4440
2944 if (verbose) { 4441 if (verbose) {
@@ -2951,6 +4448,7 @@ describe_command(command, verbose)
2951 goto out; 4448 goto out;
2952 } 4449 }
2953 4450
4451#ifdef ASH_ALIAS
2954 /* Then look at the aliases */ 4452 /* Then look at the aliases */
2955 if ((ap = lookupalias(command, 0)) != NULL) { 4453 if ((ap = lookupalias(command, 0)) != NULL) {
2956 if (verbose) { 4454 if (verbose) {
@@ -2960,7 +4458,7 @@ describe_command(command, verbose)
2960 } 4458 }
2961 goto out; 4459 goto out;
2962 } 4460 }
2963 4461#endif
2964 /* Then check if it is a tracked alias */ 4462 /* Then check if it is a tracked alias */
2965 if ((cmdp = cmdlookup(command, 0)) != NULL) { 4463 if ((cmdp = cmdlookup(command, 0)) != NULL) {
2966 entry.cmdtype = cmdp->cmdtype; 4464 entry.cmdtype = cmdp->cmdtype;
@@ -3005,7 +4503,7 @@ describe_command(command, verbose)
3005 if (verbose) { 4503 if (verbose) {
3006 out1fmt( 4504 out1fmt(
3007 " is a %sshell builtin", 4505 " is a %sshell builtin",
3008 entry.u.cmd->flags & BUILTIN_SPECIAL ? 4506 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
3009 "special " : nullstr 4507 "special " : nullstr
3010 ); 4508 );
3011 } else { 4509 } else {
@@ -3024,8 +4522,9 @@ out:
3024 out1c('\n'); 4522 out1c('\n');
3025 return 0; 4523 return 0;
3026} 4524}
3027#endif 4525#endif
3028 4526
4527#ifdef ASH_CMDCMD
3029static int 4528static int
3030commandcmd(argc, argv) 4529commandcmd(argc, argv)
3031 int argc; 4530 int argc;
@@ -3066,10 +4565,11 @@ commandcmd(argc, argv)
3066 if (verify_only || verbose_verify_only) { 4565 if (verify_only || verbose_verify_only) {
3067 return describe_command(*argptr, verbose_verify_only); 4566 return describe_command(*argptr, verbose_verify_only);
3068 } 4567 }
3069#endif 4568#endif
3070 4569
3071 return 0; 4570 return 0;
3072} 4571}
4572#endif
3073 4573
3074static int 4574static int
3075path_change(newval, bltin) 4575path_change(newval, bltin)
@@ -3082,7 +4582,7 @@ path_change(newval, bltin)
3082 4582
3083 old = pathval(); 4583 old = pathval();
3084 new = newval; 4584 new = newval;
3085 firstchange = 9999; /* assume no change */ 4585 firstchange = 9999; /* assume no change */
3086 idx = 0; 4586 idx = 0;
3087 *bltin = -1; 4587 *bltin = -1;
3088 for (;;) { 4588 for (;;) {
@@ -3091,7 +4591,7 @@ path_change(newval, bltin)
3091 if ((*old == '\0' && *new == ':') 4591 if ((*old == '\0' && *new == ':')
3092 || (*old == ':' && *new == '\0')) 4592 || (*old == ':' && *new == '\0'))
3093 firstchange++; 4593 firstchange++;
3094 old = new; /* ignore subsequent differences */ 4594 old = new; /* ignore subsequent differences */
3095 } 4595 }
3096 if (*new == '\0') 4596 if (*new == '\0')
3097 break; 4597 break;
@@ -3106,8 +4606,6 @@ path_change(newval, bltin)
3106 firstchange = 0; 4606 firstchange = 0;
3107 return firstchange; 4607 return firstchange;
3108} 4608}
3109/* $NetBSD: expand.c,v 1.50 2001/02/04 19:52:06 christos Exp $ */
3110
3111/* 4609/*
3112 * Routines to expand arguments to commands. We have to deal with 4610 * Routines to expand arguments to commands. We have to deal with
3113 * backquotes, shell variables, and file metacharacters. 4611 * backquotes, shell variables, and file metacharacters.
@@ -3115,8 +4613,8 @@ path_change(newval, bltin)
3115/* 4613/*
3116 * _rmescape() flags 4614 * _rmescape() flags
3117 */ 4615 */
3118#define RMESCAPE_ALLOC 0x1 /* Allocate a new string */ 4616#define RMESCAPE_ALLOC 0x1 /* Allocate a new string */
3119#define RMESCAPE_GLOB 0x2 /* Add backslashes for glob */ 4617#define RMESCAPE_GLOB 0x2 /* Add backslashes for glob */
3120 4618
3121/* 4619/*
3122 * Structure specifying which parts of the string should be searched 4620 * Structure specifying which parts of the string should be searched
@@ -3124,66 +4622,62 @@ path_change(newval, bltin)
3124 */ 4622 */
3125 4623
3126struct ifsregion { 4624struct ifsregion {
3127 struct ifsregion *next; /* next region in list */ 4625 struct ifsregion *next; /* next region in list */
3128 int begoff; /* offset of start of region */ 4626 int begoff; /* offset of start of region */
3129 int endoff; /* offset of end of region */ 4627 int endoff; /* offset of end of region */
3130 int nulonly; /* search for nul bytes only */ 4628 int nulonly; /* search for nul bytes only */
3131}; 4629};
3132 4630
3133 4631
3134static char *expdest; /* output of current string */ 4632static char *expdest; /* output of current string */
3135struct nodelist *argbackq; /* list of back quote expressions */ 4633static struct nodelist *argbackq; /* list of back quote expressions */
3136struct ifsregion ifsfirst; /* first struct in list of ifs regions */ 4634static struct ifsregion ifsfirst; /* first struct in list of ifs regions */
3137struct ifsregion *ifslastp; /* last struct in list */ 4635static struct ifsregion *ifslastp; /* last struct in list */
3138struct arglist exparg; /* holds expanded arg list */ 4636static struct arglist exparg; /* holds expanded arg list */
3139 4637
3140static void argstr __P((char *, int)); 4638static void argstr (char *, int);
3141static char *exptilde __P((char *, int)); 4639static char *exptilde (char *, int);
3142static void expbackq __P((union node *, int, int)); 4640static void expbackq (union node *, int, int);
3143static int subevalvar __P((char *, char *, int, int, int, int, int)); 4641static int subevalvar (char *, char *, int, int, int, int, int);
3144static char *evalvar __P((char *, int)); 4642static char *evalvar (char *, int);
3145static int varisset __P((char *, int)); 4643static int varisset (char *, int);
3146static void strtodest __P((const char *, const char *, int)); 4644static void strtodest (const char *, const char *, int);
3147static void varvalue __P((char *, int, int)); 4645static void varvalue (char *, int, int);
3148static void recordregion __P((int, int, int)); 4646static void recordregion (int, int, int);
3149static void removerecordregions __P((int)); 4647static void removerecordregions (int);
3150static void ifsbreakup __P((char *, struct arglist *)); 4648static void ifsbreakup (char *, struct arglist *);
3151static void ifsfree __P((void)); 4649static void ifsfree (void);
3152static void expandmeta __P((struct strlist *, int)); 4650static void expandmeta (struct strlist *, int);
3153#if defined(__GLIBC__) && !defined(FNMATCH_BROKEN) 4651#if defined(__GLIBC__) && !defined(FNMATCH_BROKEN)
3154#define preglob(p) _rmescapes((p), RMESCAPE_ALLOC | RMESCAPE_GLOB) 4652#define preglob(p) _rmescapes((p), RMESCAPE_ALLOC | RMESCAPE_GLOB)
3155#if !defined(GLOB_BROKEN) 4653#if !defined(GLOB_BROKEN)
3156static void addglob __P((const glob_t *)); 4654static void addglob (const glob_t *);
3157#endif 4655#endif
3158#endif 4656#endif
3159#if !(defined(__GLIBC__) && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN)) 4657#if !(defined(__GLIBC__) && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN))
3160static void expmeta __P((char *, char *)); 4658static void expmeta (char *, char *);
3161#endif 4659#endif
3162static void addfname __P((char *));
3163#if !(defined(__GLIBC__) && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN)) 4660#if !(defined(__GLIBC__) && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN))
3164static struct strlist *expsort __P((struct strlist *)); 4661static struct strlist *expsort (struct strlist *);
3165static struct strlist *msort __P((struct strlist *, int)); 4662static struct strlist *msort (struct strlist *, int);
3166#endif 4663#endif
3167#if defined(__GLIBC__) && !defined(FNMATCH_BROKEN) 4664#if defined(__GLIBC__) && !defined(FNMATCH_BROKEN)
3168static int patmatch __P((char *, char *, int)); 4665static int patmatch (char *, char *, int);
3169static int patmatch2 __P((char *, char *, int)); 4666static int patmatch2 (char *, char *, int);
3170#else 4667#else
3171static int pmatch __P((char *, char *, int)); 4668static int pmatch (char *, char *, int);
3172#define patmatch2 patmatch 4669#define patmatch2 patmatch
3173#endif 4670#endif
3174static char *cvtnum __P((int, char *)); 4671static char *cvtnum (int, char *);
3175
3176extern int oexitstatus;
3177 4672
3178/* 4673/*
3179 * Expand shell variables and backquotes inside a here document. 4674 * Expand shell variables and backquotes inside a here document.
3180 */ 4675 */
3181 4676
4677/* arg: the document, fd: where to write the expanded version */
3182static void 4678static void
3183expandhere(arg, fd) 4679expandhere(union node *arg, int fd)
3184 union node *arg; /* the document */ 4680{
3185 int fd; /* where to write the expanded version */
3186 {
3187 herefd = fd; 4681 herefd = fd;
3188 expandarg(arg, (struct arglist *)NULL, 0); 4682 expandarg(arg, (struct arglist *)NULL, 0);
3189 xwrite(fd, stackblock(), expdest - stackblock()); 4683 xwrite(fd, stackblock(), expdest - stackblock());
@@ -3212,7 +4706,7 @@ expandarg(arg, arglist, flag)
3212 ifslastp = NULL; 4706 ifslastp = NULL;
3213 argstr(arg->narg.text, flag); 4707 argstr(arg->narg.text, flag);
3214 if (arglist == NULL) { 4708 if (arglist == NULL) {
3215 return; /* here document expanded */ 4709 return; /* here document expanded */
3216 } 4710 }
3217 STPUTC('\0', expdest); 4711 STPUTC('\0', expdest);
3218 p = grabstackstr(expdest); 4712 p = grabstackstr(expdest);
@@ -3255,7 +4749,7 @@ argstr(p, flag)
3255 int flag; 4749 int flag;
3256{ 4750{
3257 char c; 4751 char c;
3258 int quotes = flag & (EXP_FULL | EXP_CASE); /* do CTLESC */ 4752 int quotes = flag & (EXP_FULL | EXP_CASE); /* do CTLESC */
3259 int firsteq = 1; 4753 int firsteq = 1;
3260 4754
3261 if (*p == '~' && (flag & (EXP_TILDE | EXP_VARTILDE))) 4755 if (*p == '~' && (flag & (EXP_TILDE | EXP_VARTILDE)))
@@ -3290,7 +4784,7 @@ argstr(p, flag)
3290 case CTLENDARI: 4784 case CTLENDARI:
3291 expari(flag); 4785 expari(flag);
3292 break; 4786 break;
3293#endif 4787#endif
3294 case ':': 4788 case ':':
3295 case '=': 4789 case '=':
3296 /* 4790 /*
@@ -3362,9 +4856,8 @@ lose:
3362} 4856}
3363 4857
3364 4858
3365static void 4859static void
3366removerecordregions(endoff) 4860removerecordregions(int endoff)
3367 int endoff;
3368{ 4861{
3369 if (ifslastp == NULL) 4862 if (ifslastp == NULL)
3370 return; 4863 return;
@@ -3386,7 +4879,7 @@ removerecordregions(endoff)
3386 } 4879 }
3387 return; 4880 return;
3388 } 4881 }
3389 4882
3390 ifslastp = &ifsfirst; 4883 ifslastp = &ifsfirst;
3391 while (ifslastp->next && ifslastp->next->begoff < endoff) 4884 while (ifslastp->next && ifslastp->next->begoff < endoff)
3392 ifslastp=ifslastp->next; 4885 ifslastp=ifslastp->next;
@@ -3409,8 +4902,7 @@ removerecordregions(endoff)
3409 * evaluate, place result in (backed up) result, adjust string position. 4902 * evaluate, place result in (backed up) result, adjust string position.
3410 */ 4903 */
3411static void 4904static void
3412expari(flag) 4905expari(int flag)
3413 int flag;
3414{ 4906{
3415 char *p, *start; 4907 char *p, *start;
3416 int result; 4908 int result;
@@ -3418,7 +4910,7 @@ expari(flag)
3418 int quotes = flag & (EXP_FULL | EXP_CASE); 4910 int quotes = flag & (EXP_FULL | EXP_CASE);
3419 int quoted; 4911 int quoted;
3420 4912
3421 /* ifsfree(); */ 4913 /* ifsfree(); */
3422 4914
3423 /* 4915 /*
3424 * This routine is slightly over-complicated for 4916 * This routine is slightly over-complicated for
@@ -3462,8 +4954,7 @@ expari(flag)
3462 result = expdest - p + 1; 4954 result = expdest - p + 1;
3463 STADJUST(-result, expdest); 4955 STADJUST(-result, expdest);
3464} 4956}
3465#endif 4957#endif
3466
3467 4958
3468/* 4959/*
3469 * Expand stuff in backwards quotes. 4960 * Expand stuff in backwards quotes.
@@ -3573,8 +5064,6 @@ err2:
3573 INTON; 5064 INTON;
3574} 5065}
3575 5066
3576
3577
3578static int 5067static int
3579subevalvar(p, str, strloc, subtype, startloc, varflags, quotes) 5068subevalvar(p, str, strloc, subtype, startloc, varflags, quotes)
3580 char *p; 5069 char *p;
@@ -3630,7 +5119,7 @@ subevalvar(p, str, strloc, subtype, startloc, varflags, quotes)
3630 goto recordleft; 5119 goto recordleft;
3631 *loc = c; 5120 *loc = c;
3632 if (quotes && *loc == CTLESC) 5121 if (quotes && *loc == CTLESC)
3633 loc++; 5122 loc++;
3634 } 5123 }
3635 return 0; 5124 return 0;
3636 5125
@@ -3653,11 +5142,11 @@ subevalvar(p, str, strloc, subtype, startloc, varflags, quotes)
3653 return 0; 5142 return 0;
3654 5143
3655 case VSTRIMRIGHT: 5144 case VSTRIMRIGHT:
3656 for (loc = str - 1; loc >= startp;) { 5145 for (loc = str - 1; loc >= startp;) {
3657 if (patmatch2(str, loc, quotes)) 5146 if (patmatch2(str, loc, quotes))
3658 goto recordright; 5147 goto recordright;
3659 loc--; 5148 loc--;
3660 if (quotes && loc > startp && *(loc - 1) == CTLESC) { 5149 if (quotes && loc > startp && *(loc - 1) == CTLESC) {
3661 for (q = startp; q < loc; q++) 5150 for (q = startp; q < loc; q++)
3662 if (*q == CTLESC) 5151 if (*q == CTLESC)
3663 q++; 5152 q++;
@@ -3672,7 +5161,7 @@ subevalvar(p, str, strloc, subtype, startloc, varflags, quotes)
3672 if (patmatch2(str, loc, quotes)) 5161 if (patmatch2(str, loc, quotes))
3673 goto recordright; 5162 goto recordright;
3674 if (quotes && *loc == CTLESC) 5163 if (quotes && *loc == CTLESC)
3675 loc++; 5164 loc++;
3676 } 5165 }
3677 return 0; 5166 return 0;
3678 5167
@@ -3788,7 +5277,7 @@ record:
3788 case VSPLUS: 5277 case VSPLUS:
3789 case VSMINUS: 5278 case VSMINUS:
3790 if (!set) { 5279 if (!set) {
3791 argstr(p, flag); 5280 argstr(p, flag);
3792 break; 5281 break;
3793 } 5282 }
3794 if (easy) 5283 if (easy)
@@ -3822,9 +5311,9 @@ record:
3822 if (subevalvar(p, var, 0, subtype, startloc, 5311 if (subevalvar(p, var, 0, subtype, startloc,
3823 varflags, quotes)) { 5312 varflags, quotes)) {
3824 varflags &= ~VSNUL; 5313 varflags &= ~VSNUL;
3825 /* 5314 /*
3826 * Remove any recorded regions beyond 5315 * Remove any recorded regions beyond
3827 * start of variable 5316 * start of variable
3828 */ 5317 */
3829 removerecordregions(startloc); 5318 removerecordregions(startloc);
3830 goto again; 5319 goto again;
@@ -3841,7 +5330,7 @@ record:
3841#endif 5330#endif
3842 } 5331 }
3843 5332
3844 if (subtype != VSNORMAL) { /* skip to end of alternative */ 5333 if (subtype != VSNORMAL) { /* skip to end of alternative */
3845 int nesting = 1; 5334 int nesting = 1;
3846 for (;;) { 5335 for (;;) {
3847 if ((c = *p++) == CTLESC) 5336 if ((c = *p++) == CTLESC)
@@ -3861,8 +5350,6 @@ record:
3861 return p; 5350 return p;
3862} 5351}
3863 5352
3864
3865
3866/* 5353/*
3867 * Test whether a specialized variable is set. 5354 * Test whether a specialized variable is set.
3868 */ 5355 */
@@ -3904,8 +5391,6 @@ varisset(name, nulok)
3904 return 1; 5391 return 1;
3905} 5392}
3906 5393
3907
3908
3909/* 5394/*
3910 * Put a string on the stack. 5395 * Put a string on the stack.
3911 */ 5396 */
@@ -3923,8 +5408,6 @@ strtodest(p, syntax, quotes)
3923 } 5408 }
3924} 5409}
3925 5410
3926
3927
3928/* 5411/*
3929 * Add the value of a specialized variable to the stack string. 5412 * Add the value of a specialized variable to the stack string.
3930 */ 5413 */
@@ -3963,8 +5446,8 @@ numvar:
3963 break; 5446 break;
3964 case '-': 5447 case '-':
3965 for (i = 0 ; i < NOPTS ; i++) { 5448 for (i = 0 ; i < NOPTS ; i++) {
3966 if (optlist[i].val) 5449 if (optent_val(i))
3967 STPUTC(optlist[i].letter, expdest); 5450 STPUTC(optent_letter(optlist[i]), expdest);
3968 } 5451 }
3969 break; 5452 break;
3970 case '@': 5453 case '@':
@@ -4001,7 +5484,6 @@ param:
4001} 5484}
4002 5485
4003 5486
4004
4005/* 5487/*
4006 * Record the fact that we have to scan this region of the 5488 * Record the fact that we have to scan this region of the
4007 * string for IFS characters. 5489 * string for IFS characters.
@@ -4136,7 +5618,22 @@ ifsfree()
4136 ifsfirst.next = NULL; 5618 ifsfirst.next = NULL;
4137} 5619}
4138 5620
5621/*
5622 * Add a file name to the list.
5623 */
5624
5625static void
5626addfname(const char *name)
5627{
5628 char *p;
5629 struct strlist *sp;
4139 5630
5631 p = sstrdup(name);
5632 sp = (struct strlist *)stalloc(sizeof *sp);
5633 sp->text = p;
5634 *exparg.lastp = sp;
5635 exparg.lastp = &sp->next;
5636}
4140 5637
4141/* 5638/*
4142 * Expand shell metacharacters. At this point, the only control characters 5639 * Expand shell metacharacters. At this point, the only control characters
@@ -4175,7 +5672,7 @@ nometa:
4175 rmescapes(str->text); 5672 rmescapes(str->text);
4176 exparg.lastp = &str->next; 5673 exparg.lastp = &str->next;
4177 break; 5674 break;
4178 default: /* GLOB_NOSPACE */ 5675 default: /* GLOB_NOSPACE */
4179 error("Out of space"); 5676 error("Out of space");
4180 } 5677 }
4181 str = str->next; 5678 str = str->next;
@@ -4199,7 +5696,7 @@ addglob(pglob)
4199} 5696}
4200 5697
4201 5698
4202#else /* defined(__GLIBC__) && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN) */ 5699#else /* defined(__GLIBC__) && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN) */
4203static char *expdir; 5700static char *expdir;
4204 5701
4205 5702
@@ -4218,7 +5715,7 @@ expandmeta(str, flag)
4218 if (fflag) 5715 if (fflag)
4219 goto nometa; 5716 goto nometa;
4220 p = str->text; 5717 p = str->text;
4221 for (;;) { /* fast check for meta chars */ 5718 for (;;) { /* fast check for meta chars */
4222 if ((c = *p++) == '\0') 5719 if ((c = *p++) == '\0')
4223 goto nometa; 5720 goto nometa;
4224 if (c == '*' || c == '?' || c == '[' || c == '!') 5721 if (c == '*' || c == '?' || c == '[' || c == '!')
@@ -4297,7 +5794,7 @@ expmeta(enddir, name)
4297 break; 5794 break;
4298 } 5795 }
4299 } 5796 }
4300 } else if (*p == '!' && p[1] == '!' && (p == name || p[-1] == '/')) { 5797 } else if (*p == '!' && p[1] == '!' && (p == name || p[-1] == '/')) {
4301 metaflag = 1; 5798 metaflag = 1;
4302 } else if (*p == '\0') 5799 } else if (*p == '\0')
4303 break; 5800 break;
@@ -4311,7 +5808,7 @@ expmeta(enddir, name)
4311 start = p + 1; 5808 start = p + 1;
4312 } 5809 }
4313 } 5810 }
4314 if (metaflag == 0) { /* we've reached the end of the file name */ 5811 if (metaflag == 0) { /* we've reached the end of the file name */
4315 if (enddir != expdir) 5812 if (enddir != expdir)
4316 metaflag++; 5813 metaflag++;
4317 for (p = name ; ; p++) { 5814 for (p = name ; ; p++) {
@@ -4369,7 +5866,7 @@ expmeta(enddir, name)
4369 continue; 5866 continue;
4370 if (patmatch(start, dp->d_name, 0)) { 5867 if (patmatch(start, dp->d_name, 0)) {
4371 if (atend) { 5868 if (atend) {
4372 scopy(dp->d_name, enddir); 5869 strcpy(enddir, dp->d_name);
4373 addfname(expdir); 5870 addfname(expdir);
4374 } else { 5871 } else {
4375 for (p = enddir, cp = dp->d_name; 5872 for (p = enddir, cp = dp->d_name;
@@ -4384,27 +5881,9 @@ expmeta(enddir, name)
4384 if (! atend) 5881 if (! atend)
4385 endname[-1] = '/'; 5882 endname[-1] = '/';
4386} 5883}
4387#endif /* defined(__GLIBC__) && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN) */ 5884#endif /* defined(__GLIBC__) && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN) */
4388 5885
4389 5886
4390/*
4391 * Add a file name to the list.
4392 */
4393
4394static void
4395addfname(name)
4396 char *name;
4397 {
4398 char *p;
4399 struct strlist *sp;
4400
4401 p = sstrdup(name);
4402 sp = (struct strlist *)stalloc(sizeof *sp);
4403 sp->text = p;
4404 *exparg.lastp = sp;
4405 exparg.lastp = &sp->next;
4406}
4407
4408 5887
4409#if !(defined(__GLIBC__) && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN)) 5888#if !(defined(__GLIBC__) && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN))
4410/* 5889/*
@@ -4445,9 +5924,9 @@ msort(list, len)
4445 q = p; 5924 q = p;
4446 p = p->next; 5925 p = p->next;
4447 } 5926 }
4448 q->next = NULL; /* terminate first half of list */ 5927 q->next = NULL; /* terminate first half of list */
4449 q = msort(list, half); /* sort first half of list */ 5928 q = msort(list, half); /* sort first half of list */
4450 p = msort(p, len - half); /* sort second half */ 5929 p = msort(p, len - half); /* sort second half */
4451 lpp = &list; 5930 lpp = &list;
4452 for (;;) { 5931 for (;;) {
4453 if (strcmp(p->text, q->text) < 0) { 5932 if (strcmp(p->text, q->text) < 0) {
@@ -4477,12 +5956,10 @@ msort(list, len)
4477 */ 5956 */
4478 5957
4479#if defined(__GLIBC__) && !defined(FNMATCH_BROKEN) 5958#if defined(__GLIBC__) && !defined(FNMATCH_BROKEN)
5959/* squoted: string might have quote chars */
4480static int 5960static int
4481patmatch(pattern, string, squoted) 5961patmatch(char *pattern, char *string, int squoted)
4482 char *pattern; 5962{
4483 char *string;
4484 int squoted; /* string might have quote chars */
4485 {
4486 const char *p; 5963 const char *p;
4487 char *q; 5964 char *q;
4488 5965
@@ -4494,11 +5971,8 @@ patmatch(pattern, string, squoted)
4494 5971
4495 5972
4496static int 5973static int
4497patmatch2(pattern, string, squoted) 5974patmatch2(char *pattern, char *string, int squoted)
4498 char *pattern; 5975{
4499 char *string;
4500 int squoted; /* string might have quote chars */
4501 {
4502 char *p; 5976 char *p;
4503 int res; 5977 int res;
4504 5978
@@ -4510,26 +5984,14 @@ patmatch2(pattern, string, squoted)
4510} 5984}
4511#else 5985#else
4512static int 5986static int
4513patmatch(pattern, string, squoted) 5987patmatch(char *pattern, char *string, int squoted) {
4514 char *pattern; 5988 return pmatch(pattern, string, squoted);
4515 char *string;
4516 int squoted; /* string might have quote chars */
4517 {
4518#ifdef notdef
4519 if (pattern[0] == '!' && pattern[1] == '!')
4520 return 1 - pmatch(pattern + 2, string);
4521 else
4522#endif
4523 return pmatch(pattern, string, squoted);
4524} 5989}
4525 5990
4526 5991
4527static int 5992static int
4528pmatch(pattern, string, squoted) 5993pmatch(char *pattern, char *string, int squoted)
4529 char *pattern; 5994{
4530 char *string;
4531 int squoted;
4532 {
4533 char *p, *q; 5995 char *p, *q;
4534 char c; 5996 char c;
4535 5997
@@ -4589,7 +6051,7 @@ pmatch(pattern, string, squoted)
4589 while (*endp == CTLQUOTEMARK) 6051 while (*endp == CTLQUOTEMARK)
4590 endp++; 6052 endp++;
4591 if (*endp == '\0') 6053 if (*endp == '\0')
4592 goto dft; /* no matching ] */ 6054 goto dft; /* no matching ] */
4593 if (*endp == CTLESC) 6055 if (*endp == CTLESC)
4594 endp++; 6056 endp++;
4595 if (*++endp == ']') 6057 if (*++endp == ']')
@@ -4630,7 +6092,7 @@ pmatch(pattern, string, squoted)
4630 return 0; 6092 return 0;
4631 break; 6093 break;
4632 } 6094 }
4633dft: default: 6095dft: default:
4634 if (squoted && *q == CTLESC) 6096 if (squoted && *q == CTLESC)
4635 q++; 6097 q++;
4636 if (*q++ != c) 6098 if (*q++ != c)
@@ -4653,9 +6115,7 @@ breakloop:
4653 6115
4654#if defined(__GLIBC__) && !defined(FNMATCH_BROKEN) 6116#if defined(__GLIBC__) && !defined(FNMATCH_BROKEN)
4655static char * 6117static char *
4656_rmescapes(str, flag) 6118_rmescapes(char *str, int flag)
4657 char *str;
4658 int flag;
4659{ 6119{
4660 char *p, *q, *r; 6120 char *p, *q, *r;
4661 static const char qchars[] = { CTLESC, CTLQUOTEMARK, 0 }; 6121 static const char qchars[] = { CTLESC, CTLQUOTEMARK, 0 };
@@ -4727,10 +6187,8 @@ rmescapes(str)
4727 */ 6187 */
4728 6188
4729static int 6189static int
4730casematch(pattern, val) 6190casematch(union node *pattern, const char *val)
4731 union node *pattern; 6191{
4732 char *val;
4733 {
4734 struct stackmark smark; 6192 struct stackmark smark;
4735 int result; 6193 int result;
4736 char *p; 6194 char *p;
@@ -4742,7 +6200,7 @@ casematch(pattern, val)
4742 argstr(pattern->narg.text, EXP_TILDE | EXP_CASE); 6200 argstr(pattern->narg.text, EXP_TILDE | EXP_CASE);
4743 STPUTC('\0', expdest); 6201 STPUTC('\0', expdest);
4744 p = grabstackstr(expdest); 6202 p = grabstackstr(expdest);
4745 result = patmatch(p, val, 0); 6203 result = patmatch(p, (char *)val, 0);
4746 popstackmark(&smark); 6204 popstackmark(&smark);
4747 return result; 6205 return result;
4748} 6206}
@@ -4763,8 +6221,6 @@ cvtnum(num, buf)
4763 STADJUST(len, buf); 6221 STADJUST(len, buf);
4764 return buf; 6222 return buf;
4765} 6223}
4766/* $NetBSD: histedit.c,v 1.25 2001/02/04 19:52:06 christos Exp $ */
4767
4768/* 6224/*
4769 * Editline and history functions (and glue). 6225 * Editline and history functions (and glue).
4770 */ 6226 */
@@ -4777,54 +6233,15 @@ static int histcmd(argc, argv)
4777} 6233}
4778 6234
4779 6235
4780/* 6236static int whichprompt; /* 1 == PS1, 2 == PS2 */
4781 * This file was generated by the mkinit program.
4782 */
4783
4784extern void rmaliases __P((void));
4785
4786extern int loopnest; /* current loop nesting level */
4787
4788extern void deletefuncs __P((void));
4789 6237
4790struct strpush {
4791 struct strpush *prev; /* preceding string on stack */
4792 char *prevstring;
4793 int prevnleft;
4794 struct alias *ap; /* if push was associated with an alias */
4795 char *string; /* remember the string since it may change */
4796};
4797
4798struct parsefile {
4799 struct parsefile *prev; /* preceding file on stack */
4800 int linno; /* current line */
4801 int fd; /* file descriptor (or -1 if string) */
4802 int nleft; /* number of chars left in this line */
4803 int lleft; /* number of chars left in this buffer */
4804 char *nextc; /* next char in buffer */
4805 char *buf; /* input buffer */
4806 struct strpush *strpush; /* for pushing strings at this level */
4807 struct strpush basestrpush; /* so pushing one is fast */
4808};
4809
4810extern int parselleft; /* copy of parsefile->lleft */
4811extern struct parsefile basepf; /* top level input file */
4812extern char basebuf[BUFSIZ]; /* buffer for top level input file */
4813
4814extern short backgndpid; /* pid of last background process */
4815extern int jobctl;
4816
4817extern int tokpushback; /* last token pushed back */
4818extern int checkkwd; /* 1 == check for kwds, 2 == also eat newlines */
4819 6238
4820struct redirtab { 6239struct redirtab {
4821 struct redirtab *next; 6240 struct redirtab *next;
4822 short renamed[10]; 6241 short renamed[10];
4823}; 6242};
4824 6243
4825extern struct redirtab *redirlist; 6244static struct redirtab *redirlist;
4826
4827extern char sigmode[NSIG - 1]; /* current value of signal */
4828 6245
4829extern char **environ; 6246extern char **environ;
4830 6247
@@ -4835,7 +6252,7 @@ extern char **environ;
4835 */ 6252 */
4836 6253
4837static void 6254static void
4838init() { 6255init(void) {
4839 6256
4840 /* from cd.c: */ 6257 /* from cd.c: */
4841 { 6258 {
@@ -4878,8 +6295,13 @@ init() {
4878 * interactive shell and control is returned to the main command loop. 6295 * interactive shell and control is returned to the main command loop.
4879 */ 6296 */
4880 6297
6298#ifdef ASH_ALIAS
6299/* 1 == check for aliases, 2 == also check for assignments */
6300static int checkalias;
6301#endif
6302
4881static void 6303static void
4882reset() { 6304reset(void) {
4883 6305
4884 /* from eval.c: */ 6306 /* from eval.c: */
4885 { 6307 {
@@ -4891,7 +6313,7 @@ reset() {
4891 /* from input.c: */ 6313 /* from input.c: */
4892 { 6314 {
4893 if (exception != EXSHELLPROC) 6315 if (exception != EXSHELLPROC)
4894 parselleft = parsenleft = 0; /* clear input buffer */ 6316 parselleft = parsenleft = 0; /* clear input buffer */
4895 popallfiles(); 6317 popallfiles();
4896 } 6318 }
4897 6319
@@ -4899,7 +6321,9 @@ reset() {
4899 { 6321 {
4900 tokpushback = 0; 6322 tokpushback = 0;
4901 checkkwd = 0; 6323 checkkwd = 0;
6324#ifdef ASH_ALIAS
4902 checkalias = 0; 6325 checkalias = 0;
6326#endif
4903 } 6327 }
4904 6328
4905 /* from redir.c: */ 6329 /* from redir.c: */
@@ -4926,69 +6350,6 @@ reset() {
4926 6350
4927 6351
4928/* 6352/*
4929 * This routine is called to initialize the shell to run a shell procedure.
4930 */
4931
4932static void
4933initshellproc() {
4934
4935 /* from alias.c: */
4936 {
4937 rmaliases();
4938 }
4939
4940 /* from eval.c: */
4941 {
4942 exitstatus = 0;
4943 }
4944
4945 /* from exec.c: */
4946 {
4947 deletefuncs();
4948 }
4949
4950 /* from jobs.c: */
4951 {
4952 backgndpid = -1;
4953#if JOBS
4954 jobctl = 0;
4955#endif
4956 }
4957
4958 /* from options.c: */
4959 {
4960 int i;
4961
4962 for (i = 0; i < NOPTS; i++)
4963 optlist[i].val = 0;
4964 optschanged();
4965
4966 }
4967
4968 /* from redir.c: */
4969 {
4970 clearredir();
4971 }
4972
4973 /* from trap.c: */
4974 {
4975 char *sm;
4976
4977 clear_traps();
4978 for (sm = sigmode ; sm < sigmode + NSIG - 1; sm++) {
4979 if (*sm == S_IGN)
4980 *sm = S_HARD_IGN;
4981 }
4982 }
4983
4984 /* from var.c: */
4985 {
4986 shprocvar();
4987 }
4988}
4989/* $NetBSD: input.c,v 1.35 2001/02/04 19:52:06 christos Exp $ */
4990
4991/*
4992 * This file implements the input routines used by the parser. 6353 * This file implements the input routines used by the parser.
4993 */ 6354 */
4994 6355
@@ -5004,45 +6365,34 @@ static inline void putprompt(const char *s) {
5004} 6365}
5005#endif 6366#endif
5006 6367
5007#define EOF_NLEFT -99 /* value of parsenleft when EOF pushed back */ 6368#define EOF_NLEFT -99 /* value of parsenleft when EOF pushed back */
5008
5009static int plinno = 1; /* input line number */
5010static int parsenleft; /* copy of parsefile->nleft */
5011static int parselleft; /* copy of parsefile->lleft */
5012static char *parsenextc; /* copy of parsefile->nextc */
5013struct parsefile basepf; /* top level input file */
5014static char basebuf[BUFSIZ]; /* buffer for top level input file */
5015struct parsefile *parsefile = &basepf; /* current input file */
5016static int whichprompt; /* 1 == PS1, 2 == PS2 */
5017 6369
5018static void pushfile __P((void));
5019static int preadfd __P((void));
5020 6370
5021#ifdef mkinit
5022INCLUDE <stdio.h>
5023INCLUDE "input.h"
5024INCLUDE "error.h"
5025 6371
5026INIT { 6372/*
5027 basepf.nextc = basepf.buf = basebuf; 6373 * Same as pgetc(), but ignores PEOA.
5028} 6374 */
5029 6375
5030RESET { 6376#ifdef ASH_ALIAS
5031 if (exception != EXSHELLPROC) 6377static int
5032 parselleft = parsenleft = 0; /* clear input buffer */ 6378pgetc2()
5033 popallfiles(); 6379{
6380 int c;
6381 do {
6382 c = pgetc_macro();
6383 } while (c == PEOA);
6384 return c;
5034} 6385}
6386#else
6387static inline int pgetc2() { return pgetc_macro(); }
5035#endif 6388#endif
5036 6389
5037
5038/* 6390/*
5039 * Read a line from the script. 6391 * Read a line from the script.
5040 */ 6392 */
5041 6393
5042static char * 6394static char *
5043pfgets(line, len) 6395pfgets(char *line, int len)
5044 char *line;
5045 int len;
5046{ 6396{
5047 char *p = line; 6397 char *p = line;
5048 int nleft = len; 6398 int nleft = len;
@@ -5063,36 +6413,8 @@ pfgets(line, len)
5063 return line; 6413 return line;
5064} 6414}
5065 6415
5066
5067/*
5068 * Read a character from the script, returning PEOF on end of file.
5069 * Nul characters in the input are silently discarded.
5070 */
5071
5072static int
5073pgetc()
5074{
5075 return pgetc_macro();
5076}
5077
5078
5079/*
5080 * Same as pgetc(), but ignores PEOA.
5081 */
5082
5083static int 6416static int
5084pgetc2() 6417preadfd(void)
5085{
5086 int c;
5087 do {
5088 c = pgetc_macro();
5089 } while (c == PEOA);
5090 return c;
5091}
5092
5093
5094static int
5095preadfd()
5096{ 6418{
5097 int nr; 6419 int nr;
5098 char *buf = parsefile->buf; 6420 char *buf = parsefile->buf;
@@ -5103,7 +6425,7 @@ retry:
5103 { 6425 {
5104 if (parsefile->fd) 6426 if (parsefile->fd)
5105 nr = read(parsefile->fd, buf, BUFSIZ - 1); 6427 nr = read(parsefile->fd, buf, BUFSIZ - 1);
5106 else { 6428 else {
5107 do { 6429 do {
5108 cmdedit_read_input((char*)cmdedit_prompt, buf); 6430 cmdedit_read_input((char*)cmdedit_prompt, buf);
5109 nr = strlen(buf); 6431 nr = strlen(buf);
@@ -5132,6 +6454,39 @@ retry:
5132 return nr; 6454 return nr;
5133} 6455}
5134 6456
6457static void
6458popstring(void)
6459{
6460 struct strpush *sp = parsefile->strpush;
6461
6462 INTOFF;
6463#ifdef ASH_ALIAS
6464 if (sp->ap) {
6465 if (parsenextc[-1] == ' ' || parsenextc[-1] == '\t') {
6466 if (!checkalias) {
6467 checkalias = 1;
6468 }
6469 }
6470 if (sp->string != sp->ap->val) {
6471 ckfree(sp->string);
6472 }
6473
6474 sp->ap->flag &= ~ALIASINUSE;
6475 if (sp->ap->flag & ALIASDEAD) {
6476 unalias(sp->ap->name);
6477 }
6478 }
6479#endif
6480 parsenextc = sp->prevstring;
6481 parsenleft = sp->prevnleft;
6482/*dprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/
6483 parsefile->strpush = sp->prev;
6484 if (sp != &(parsefile->basestrpush))
6485 ckfree(sp);
6486 INTON;
6487}
6488
6489
5135/* 6490/*
5136 * Refill the input buffer and return the next input character: 6491 * Refill the input buffer and return the next input character:
5137 * 6492 *
@@ -5143,19 +6498,19 @@ retry:
5143 */ 6498 */
5144 6499
5145static int 6500static int
5146preadbuffer() 6501preadbuffer(void)
5147{ 6502{
5148 char *p, *q; 6503 char *p, *q;
5149 int more; 6504 int more;
5150 char savec; 6505 char savec;
5151 6506
5152 while (parsefile->strpush) { 6507 while (parsefile->strpush) {
5153 if ( 6508#ifdef ASH_ALIAS
5154 parsenleft == -1 && parsefile->strpush->ap && 6509 if (parsenleft == -1 && parsefile->strpush->ap &&
5155 parsenextc[-1] != ' ' && parsenextc[-1] != '\t' 6510 parsenextc[-1] != ' ' && parsenextc[-1] != '\t') {
5156 ) {
5157 return PEOA; 6511 return PEOA;
5158 } 6512 }
6513#endif
5159 popstring(); 6514 popstring();
5160 if (--parsenleft >= 0) 6515 if (--parsenleft >= 0)
5161 return (*parsenextc++); 6516 return (*parsenextc++);
@@ -5181,7 +6536,7 @@ again:
5181 for (more = 1; more;) { 6536 for (more = 1; more;) {
5182 switch (*p) { 6537 switch (*p) {
5183 case '\0': 6538 case '\0':
5184 p++; /* Skip nul */ 6539 p++; /* Skip nul */
5185 goto check; 6540 goto check;
5186 6541
5187 6542
@@ -5216,27 +6571,14 @@ check:
5216 return *parsenextc++; 6571 return *parsenextc++;
5217} 6572}
5218 6573
5219/*
5220 * Undo the last call to pgetc. Only one character may be pushed back.
5221 * PEOF may be pushed back.
5222 */
5223
5224static void
5225pungetc() {
5226 parsenleft++;
5227 parsenextc--;
5228}
5229 6574
5230/* 6575/*
5231 * Push a string back onto the input at this current parsefile level. 6576 * Push a string back onto the input at this current parsefile level.
5232 * We handle aliases this way. 6577 * We handle aliases this way.
5233 */ 6578 */
5234static void 6579static void
5235pushstring(s, len, ap) 6580pushstring(char *s, int len, void *ap)
5236 char *s; 6581{
5237 int len;
5238 void *ap;
5239 {
5240 struct strpush *sp; 6582 struct strpush *sp;
5241 6583
5242 INTOFF; 6584 INTOFF;
@@ -5249,97 +6591,19 @@ pushstring(s, len, ap)
5249 sp = parsefile->strpush = &(parsefile->basestrpush); 6591 sp = parsefile->strpush = &(parsefile->basestrpush);
5250 sp->prevstring = parsenextc; 6592 sp->prevstring = parsenextc;
5251 sp->prevnleft = parsenleft; 6593 sp->prevnleft = parsenleft;
6594#ifdef ASH_ALIAS
5252 sp->ap = (struct alias *)ap; 6595 sp->ap = (struct alias *)ap;
5253 if (ap) { 6596 if (ap) {
5254 ((struct alias *)ap)->flag |= ALIASINUSE; 6597 ((struct alias *)ap)->flag |= ALIASINUSE;
5255 sp->string = s; 6598 sp->string = s;
5256 } 6599 }
6600#endif
5257 parsenextc = s; 6601 parsenextc = s;
5258 parsenleft = len; 6602 parsenleft = len;
5259 INTON; 6603 INTON;
5260} 6604}
5261 6605
5262static void
5263popstring()
5264{
5265 struct strpush *sp = parsefile->strpush;
5266 6606
5267 INTOFF;
5268 if (sp->ap) {
5269 if (parsenextc[-1] == ' ' || parsenextc[-1] == '\t') {
5270 if (!checkalias) {
5271 checkalias = 1;
5272 }
5273 }
5274 if (sp->string != sp->ap->val) {
5275 ckfree(sp->string);
5276 }
5277 sp->ap->flag &= ~ALIASINUSE;
5278 if (sp->ap->flag & ALIASDEAD) {
5279 unalias(sp->ap->name);
5280 }
5281 }
5282 parsenextc = sp->prevstring;
5283 parsenleft = sp->prevnleft;
5284/*dprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/
5285 parsefile->strpush = sp->prev;
5286 if (sp != &(parsefile->basestrpush))
5287 ckfree(sp);
5288 INTON;
5289}
5290
5291/*
5292 * Set the input to take input from a file. If push is set, push the
5293 * old input onto the stack first.
5294 */
5295
5296static void
5297setinputfile(fname, push)
5298 const char *fname;
5299 int push;
5300{
5301 int fd;
5302 int myfileno2;
5303
5304 INTOFF;
5305 if ((fd = open(fname, O_RDONLY)) < 0)
5306 error("Can't open %s", fname);
5307 if (fd < 10) {
5308 myfileno2 = dup_as_newfd(fd, 10);
5309 close(fd);
5310 if (myfileno2 < 0)
5311 error("Out of file descriptors");
5312 fd = myfileno2;
5313 }
5314 setinputfd(fd, push);
5315 INTON;
5316}
5317
5318
5319/*
5320 * Like setinputfile, but takes an open file descriptor. Call this with
5321 * interrupts off.
5322 */
5323
5324static void
5325setinputfd(fd, push)
5326 int fd, push;
5327{
5328 (void) fcntl(fd, F_SETFD, FD_CLOEXEC);
5329 if (push) {
5330 pushfile();
5331 parsefile->buf = 0;
5332 } else {
5333 closescript();
5334 while (parsefile->strpush)
5335 popstring();
5336 }
5337 parsefile->fd = fd;
5338 if (parsefile->buf == NULL)
5339 parsefile->buf = ckmalloc(BUFSIZ);
5340 parselleft = parsenleft = 0;
5341 plinno = 1;
5342}
5343 6607
5344 6608
5345/* 6609/*
@@ -5367,7 +6631,7 @@ setinputstring(string)
5367 */ 6631 */
5368 6632
5369static void 6633static void
5370pushfile() { 6634pushfile(void) {
5371 struct parsefile *pf; 6635 struct parsefile *pf;
5372 6636
5373 parsefile->nleft = parsenleft; 6637 parsefile->nleft = parsenleft;
@@ -5382,79 +6646,42 @@ pushfile() {
5382 parsefile = pf; 6646 parsefile = pf;
5383} 6647}
5384 6648
5385 6649#ifdef JOBS
5386static void 6650static void restartjob (struct job *);
5387popfile() { 6651#endif
5388 struct parsefile *pf = parsefile; 6652static void freejob (struct job *);
5389 6653static struct job *getjob (const char *);
5390 INTOFF; 6654static int dowait (int, struct job *);
5391 if (pf->fd >= 0) 6655static int waitproc (int, int *);
5392 close(pf->fd); 6656static void waitonint(int);
5393 if (pf->buf)
5394 ckfree(pf->buf);
5395 while (pf->strpush)
5396 popstring();
5397 parsefile = pf->prev;
5398 ckfree(pf);
5399 parsenleft = parsefile->nleft;
5400 parselleft = parsefile->lleft;
5401 parsenextc = parsefile->nextc;
5402 plinno = parsefile->linno;
5403 INTON;
5404}
5405 6657
5406 6658
5407/* 6659/*
5408 * Return to top level. 6660 * We keep track of whether or not fd0 has been redirected. This is for
5409 */ 6661 * background commands, where we want to redirect fd0 to /dev/null only
6662 * if it hasn't already been redirected.
6663*/
6664static int fd0_redirected = 0;
5410 6665
5411static void 6666/* Return true if fd 0 has already been redirected at least once. */
5412popallfiles() { 6667static inline int
5413 while (parsefile != &basepf) 6668fd0_redirected_p () {
5414 popfile(); 6669 return fd0_redirected != 0;
5415} 6670}
5416 6671
5417
5418
5419/* 6672/*
5420 * Close the file(s) that the shell is reading commands from. Called 6673 * We also keep track of where fileno2 goes.
5421 * after a fork is done.
5422 */ 6674 */
6675static int fileno2 = 2;
5423 6676
5424static void 6677static int openredirect (union node *);
5425closescript() { 6678static void dupredirect (union node *, int, char[10 ]);
5426 popallfiles(); 6679static int openhere (union node *);
5427 if (parsefile->fd > 0) { 6680static int noclobberopen (const char *);
5428 close(parsefile->fd);
5429 parsefile->fd = 0;
5430 }
5431}
5432/* $NetBSD: jobs.c,v 1.36 2000/05/22 10:18:47 elric Exp $ */
5433
5434
5435struct job *jobtab; /* array of jobs */
5436static int njobs; /* size of array */
5437short backgndpid = -1; /* pid of last background process */
5438#if JOBS
5439static int initialpgrp; /* pgrp of shell on invocation */
5440short curjob; /* current job */
5441#endif
5442static int intreceived;
5443 6681
5444static void restartjob __P((struct job *));
5445static void freejob __P((struct job *));
5446static struct job *getjob __P((char *));
5447static int dowait __P((int, struct job *));
5448#ifdef SYSV
5449static int onsigchild __P((void));
5450#endif
5451static int waitproc __P((int, int *));
5452static void cmdtxt __P((union node *));
5453static void cmdputs __P((const char *));
5454static void waitonint(int);
5455 6682
5456 6683
5457#if JOBS 6684#ifdef JOBS
5458/* 6685/*
5459 * Turn job control on and off. 6686 * Turn job control on and off.
5460 * 6687 *
@@ -5463,7 +6690,7 @@ static void waitonint(int);
5463 * System V doesn't have job control yet, this isn't a problem now. 6690 * System V doesn't have job control yet, this isn't a problem now.
5464 */ 6691 */
5465 6692
5466static int jobctl; 6693
5467 6694
5468static void setjobctl(int enable) 6695static void setjobctl(int enable)
5469{ 6696{
@@ -5524,22 +6751,6 @@ static void setjobctl(int enable)
5524#endif 6751#endif
5525 6752
5526 6753
5527#ifdef mkinit
5528INCLUDE <stdlib.h>
5529
5530SHELLPROC {
5531 backgndpid = -1;
5532#if JOBS
5533 jobctl = 0;
5534#endif
5535}
5536
5537#endif
5538
5539
5540/* This file was automatically created by ./mksignames.
5541 Do not edit. Edit support/mksignames.c instead. */
5542
5543/* A translation list so we can be polite to our users. */ 6754/* A translation list so we can be polite to our users. */
5544static char *signal_names[NSIG + 2] = { 6755static char *signal_names[NSIG + 2] = {
5545 "EXIT", 6756 "EXIT",
@@ -5612,7 +6823,7 @@ static char *signal_names[NSIG + 2] = {
5612 6823
5613 6824
5614 6825
5615#if JOBS 6826#ifdef JOBS
5616static int 6827static int
5617killcmd(argc, argv) 6828killcmd(argc, argv)
5618 int argc; 6829 int argc;
@@ -5650,7 +6861,7 @@ usage:
5650 optionarg 6861 optionarg
5651 ); 6862 );
5652 } 6863 }
5653 break; 6864 break;
5654#ifdef DEBUG 6865#ifdef DEBUG
5655 default: 6866 default:
5656 error( 6867 error(
@@ -5697,7 +6908,7 @@ usage:
5697 } else 6908 } else
5698 pid = atoi(*argptr); 6909 pid = atoi(*argptr);
5699 if (kill(pid, signo) != 0) 6910 if (kill(pid, signo) != 0)
5700 error("%s: %s", *argptr, strerror(errno)); 6911 error("%s: %m", *argptr);
5701 } while (*++argptr); 6912 } while (*++argptr);
5702 6913
5703 return 0; 6914 return 0;
@@ -5767,6 +6978,8 @@ restartjob(jp)
5767} 6978}
5768#endif 6979#endif
5769 6980
6981static void showjobs(int change);
6982
5770 6983
5771static int 6984static int
5772jobscmd(argc, argv) 6985jobscmd(argc, argv)
@@ -5811,12 +7024,12 @@ showjobs(change)
5811 if (change && ! jp->changed) 7024 if (change && ! jp->changed)
5812 continue; 7025 continue;
5813 procno = jp->nprocs; 7026 procno = jp->nprocs;
5814 for (ps = jp->ps ; ; ps++) { /* for each process */ 7027 for (ps = jp->ps ; ; ps++) { /* for each process */
5815 if (ps == jp->ps) 7028 if (ps == jp->ps)
5816 fmtstr(s, 64, "[%d] %ld ", jobno, 7029 fmtstr(s, 64, "[%d] %ld ", jobno,
5817 (long)ps->pid); 7030 (long)ps->pid);
5818 else 7031 else
5819 fmtstr(s, 64, " %ld ", 7032 fmtstr(s, 64, " %ld ",
5820 (long)ps->pid); 7033 (long)ps->pid);
5821 out1str(s); 7034 out1str(s);
5822 col = strlen(s); 7035 col = strlen(s);
@@ -5824,17 +7037,17 @@ showjobs(change)
5824 if (ps->status == -1) { 7037 if (ps->status == -1) {
5825 /* don't print anything */ 7038 /* don't print anything */
5826 } else if (WIFEXITED(ps->status)) { 7039 } else if (WIFEXITED(ps->status)) {
5827 fmtstr(s, 64, "Exit %d", 7040 fmtstr(s, 64, "Exit %d",
5828 WEXITSTATUS(ps->status)); 7041 WEXITSTATUS(ps->status));
5829 } else { 7042 } else {
5830#if JOBS 7043#ifdef JOBS
5831 if (WIFSTOPPED(ps->status)) 7044 if (WIFSTOPPED(ps->status))
5832 i = WSTOPSIG(ps->status); 7045 i = WSTOPSIG(ps->status);
5833 else /* WIFSIGNALED(ps->status) */ 7046 else /* WIFSIGNALED(ps->status) */
5834#endif 7047#endif
5835 i = WTERMSIG(ps->status); 7048 i = WTERMSIG(ps->status);
5836 if ((i & 0x7F) < NSIG && sys_siglist[i & 0x7F]) 7049 if ((i & 0x7F) < NSIG && sys_siglist[i & 0x7F])
5837 scopy(sys_siglist[i & 0x7F], s); 7050 strcpy(s, sys_siglist[i & 0x7F]);
5838 else 7051 else
5839 fmtstr(s, 64, "Signal %d", i & 0x7F); 7052 fmtstr(s, 64, "Signal %d", i & 0x7F);
5840 if (WCOREDUMP(ps->status)) 7053 if (WCOREDUMP(ps->status))
@@ -5876,7 +7089,7 @@ freejob(jp)
5876 if (jp->ps != &jp->ps0) 7089 if (jp->ps != &jp->ps0)
5877 ckfree(jp->ps); 7090 ckfree(jp->ps);
5878 jp->used = 0; 7091 jp->used = 0;
5879#if JOBS 7092#ifdef JOBS
5880 if (curjob == jp - jobtab + 1) 7093 if (curjob == jp - jobtab + 1)
5881 curjob = 0; 7094 curjob = 0;
5882#endif 7095#endif
@@ -5900,7 +7113,7 @@ start:
5900 } else { 7113 } else {
5901 job = NULL; 7114 job = NULL;
5902 } 7115 }
5903 for (;;) { /* loop until process terminated or stopped */ 7116 for (;;) { /* loop until process terminated or stopped */
5904 if (job != NULL) { 7117 if (job != NULL) {
5905 if (job->state) { 7118 if (job->state) {
5906 status = job->ps[job->nprocs - 1].status; 7119 status = job->ps[job->nprocs - 1].status;
@@ -5911,7 +7124,7 @@ start:
5911 } 7124 }
5912 if (WIFEXITED(status)) 7125 if (WIFEXITED(status))
5913 retval = WEXITSTATUS(status); 7126 retval = WEXITSTATUS(status);
5914#if JOBS 7127#ifdef JOBS
5915 else if (WIFSTOPPED(status)) 7128 else if (WIFSTOPPED(status))
5916 retval = WSTOPSIG(status) + 128; 7129 retval = WSTOPSIG(status) + 128;
5917#endif 7130#endif
@@ -5923,7 +7136,7 @@ start:
5923 } 7136 }
5924 } else { 7137 } else {
5925 for (jp = jobtab ; ; jp++) { 7138 for (jp = jobtab ; ; jp++) {
5926 if (jp >= jobtab + njobs) { /* no running procs */ 7139 if (jp >= jobtab + njobs) { /* no running procs */
5927 return 0; 7140 return 0;
5928 } 7141 }
5929 if (jp->used && jp->state == 0) 7142 if (jp->used && jp->state == 0)
@@ -5943,16 +7156,15 @@ start:
5943 */ 7156 */
5944 7157
5945static struct job * 7158static struct job *
5946getjob(name) 7159getjob(const char *name)
5947 char *name; 7160{
5948 {
5949 int jobno; 7161 int jobno;
5950 struct job *jp; 7162 struct job *jp;
5951 int pid; 7163 int pid;
5952 int i; 7164 int i;
5953 7165
5954 if (name == NULL) { 7166 if (name == NULL) {
5955#if JOBS 7167#ifdef JOBS
5956currentjob: 7168currentjob:
5957 if ((jobno = curjob) == 0 || jobtab[jobno - 1].used == 0) 7169 if ((jobno = curjob) == 0 || jobtab[jobno - 1].used == 0)
5958 error("No current job"); 7170 error("No current job");
@@ -5966,7 +7178,7 @@ currentjob:
5966 if (jobno > 0 && jobno <= njobs 7178 if (jobno > 0 && jobno <= njobs
5967 && jobtab[jobno - 1].used != 0) 7179 && jobtab[jobno - 1].used != 0)
5968 return &jobtab[jobno - 1]; 7180 return &jobtab[jobno - 1];
5969#if JOBS 7181#ifdef JOBS
5970 } else if (name[1] == '%' && name[2] == '\0') { 7182 } else if (name[1] == '%' && name[2] == '\0') {
5971 goto currentjob; 7183 goto currentjob;
5972#endif 7184#endif
@@ -5983,8 +7195,7 @@ currentjob:
5983 if (found) 7195 if (found)
5984 return found; 7196 return found;
5985 } 7197 }
5986 } else if (is_number(name)) { 7198 } else if (is_number(name, &pid)) {
5987 pid = number(name);
5988 for (jp = jobtab, i = njobs ; --i >= 0 ; jp++) { 7199 for (jp = jobtab, i = njobs ; --i >= 0 ; jp++) {
5989 if (jp->used && jp->nprocs > 0 7200 if (jp->used && jp->nprocs > 0
5990 && jp->ps[jp->nprocs - 1].pid == pid) 7201 && jp->ps[jp->nprocs - 1].pid == pid)
@@ -6001,7 +7212,7 @@ currentjob:
6001 * Return a new job structure, 7212 * Return a new job structure,
6002 */ 7213 */
6003 7214
6004struct job * 7215static struct job *
6005makejob(node, nprocs) 7216makejob(node, nprocs)
6006 union node *node; 7217 union node *node;
6007 int nprocs; 7218 int nprocs;
@@ -6037,7 +7248,7 @@ makejob(node, nprocs)
6037 jp->used = 1; 7248 jp->used = 1;
6038 jp->changed = 0; 7249 jp->changed = 0;
6039 jp->nprocs = 0; 7250 jp->nprocs = 0;
6040#if JOBS 7251#ifdef JOBS
6041 jp->jobctl = jobctl; 7252 jp->jobctl = jobctl;
6042#endif 7253#endif
6043 if (nprocs > 1) { 7254 if (nprocs > 1) {
@@ -6057,21 +7268,20 @@ makejob(node, nprocs)
6057 * own process group. Jp is a job structure that the job is to be added to. 7268 * own process group. Jp is a job structure that the job is to be added to.
6058 * N is the command that will be evaluated by the child. Both jp and n may 7269 * N is the command that will be evaluated by the child. Both jp and n may
6059 * be NULL. The mode parameter can be one of the following: 7270 * be NULL. The mode parameter can be one of the following:
6060 * FORK_FG - Fork off a foreground process. 7271 * FORK_FG - Fork off a foreground process.
6061 * FORK_BG - Fork off a background process. 7272 * FORK_BG - Fork off a background process.
6062 * FORK_NOJOB - Like FORK_FG, but don't give the process its own 7273 * FORK_NOJOB - Like FORK_FG, but don't give the process its own
6063 * process group even if job control is on. 7274 * process group even if job control is on.
6064 * 7275 *
6065 * When job control is turned off, background processes have their standard 7276 * When job control is turned off, background processes have their standard
6066 * input redirected to /dev/null (except for the second and later processes 7277 * input redirected to /dev/null (except for the second and later processes
6067 * in a pipeline). 7278 * in a pipeline).
6068 */ 7279 */
6069 7280
7281
7282
6070static int 7283static int
6071forkshell(jp, n, mode) 7284forkshell(struct job *jp, union node *n, int mode)
6072 union node *n;
6073 struct job *jp;
6074 int mode;
6075{ 7285{
6076 int pid; 7286 int pid;
6077 int pgrp; 7287 int pgrp;
@@ -6098,8 +7308,8 @@ forkshell(jp, n, mode)
6098 closescript(); 7308 closescript();
6099 INTON; 7309 INTON;
6100 clear_traps(); 7310 clear_traps();
6101#if JOBS 7311#ifdef JOBS
6102 jobctl = 0; /* do job control only in root shell */ 7312 jobctl = 0; /* do job control only in root shell */
6103 if (wasroot && mode != FORK_NOJOB && mflag) { 7313 if (wasroot && mode != FORK_NOJOB && mflag) {
6104 if (jp == NULL || jp->nprocs == 0) 7314 if (jp == NULL || jp->nprocs == 0)
6105 pgrp = getpid(); 7315 pgrp = getpid();
@@ -6158,7 +7368,7 @@ forkshell(jp, n, mode)
6158 setpgid(pid, pgrp); 7368 setpgid(pid, pgrp);
6159 } 7369 }
6160 if (mode == FORK_BG) 7370 if (mode == FORK_BG)
6161 backgndpid = pid; /* set $! */ 7371 backgndpid = pid; /* set $! */
6162 if (jp) { 7372 if (jp) {
6163 struct procstat *ps = &jp->ps[jp->nprocs++]; 7373 struct procstat *ps = &jp->ps[jp->nprocs++];
6164 ps->pid = pid; 7374 ps->pid = pid;
@@ -6197,7 +7407,7 @@ static int
6197waitforjob(jp) 7407waitforjob(jp)
6198 struct job *jp; 7408 struct job *jp;
6199 { 7409 {
6200#if JOBS 7410#ifdef JOBS
6201 int mypgrp = getpgrp(); 7411 int mypgrp = getpgrp();
6202#endif 7412#endif
6203 int status; 7413 int status;
@@ -6206,7 +7416,7 @@ waitforjob(jp)
6206 7416
6207 INTOFF; 7417 INTOFF;
6208 intreceived = 0; 7418 intreceived = 0;
6209#if JOBS 7419#ifdef JOBS
6210 if (!jobctl) { 7420 if (!jobctl) {
6211#else 7421#else
6212 if (!iflag) { 7422 if (!iflag) {
@@ -6219,7 +7429,7 @@ waitforjob(jp)
6219 while (jp->state == 0) { 7429 while (jp->state == 0) {
6220 dowait(1, jp); 7430 dowait(1, jp);
6221 } 7431 }
6222#if JOBS 7432#ifdef JOBS
6223 if (!jobctl) { 7433 if (!jobctl) {
6224#else 7434#else
6225 if (!iflag) { 7435 if (!iflag) {
@@ -6227,7 +7437,7 @@ waitforjob(jp)
6227 sigaction(SIGINT, &oact, 0); 7437 sigaction(SIGINT, &oact, 0);
6228 if (intreceived && trap[SIGINT]) kill(getpid(), SIGINT); 7438 if (intreceived && trap[SIGINT]) kill(getpid(), SIGINT);
6229 } 7439 }
6230#if JOBS 7440#ifdef JOBS
6231 if (jp->jobctl) { 7441 if (jp->jobctl) {
6232#ifdef OLD_TTY_DRIVER 7442#ifdef OLD_TTY_DRIVER
6233 if (ioctl(fileno2, TIOCSPGRP, (char *)&mypgrp) < 0) 7443 if (ioctl(fileno2, TIOCSPGRP, (char *)&mypgrp) < 0)
@@ -6244,13 +7454,13 @@ waitforjob(jp)
6244 /* convert to 8 bits */ 7454 /* convert to 8 bits */
6245 if (WIFEXITED(status)) 7455 if (WIFEXITED(status))
6246 st = WEXITSTATUS(status); 7456 st = WEXITSTATUS(status);
6247#if JOBS 7457#ifdef JOBS
6248 else if (WIFSTOPPED(status)) 7458 else if (WIFSTOPPED(status))
6249 st = WSTOPSIG(status) + 128; 7459 st = WSTOPSIG(status) + 128;
6250#endif 7460#endif
6251 else 7461 else
6252 st = WTERMSIG(status) + 128; 7462 st = WTERMSIG(status) + 128;
6253#if JOBS 7463#ifdef JOBS
6254 if (jp->jobctl) { 7464 if (jp->jobctl) {
6255 /* 7465 /*
6256 * This is truly gross. 7466 * This is truly gross.
@@ -6263,8 +7473,9 @@ waitforjob(jp)
6263 if (WIFSIGNALED(status) && WTERMSIG(status) == SIGINT) 7473 if (WIFSIGNALED(status) && WTERMSIG(status) == SIGINT)
6264 raise(SIGINT); 7474 raise(SIGINT);
6265 } 7475 }
7476 if (jp->state == JOBDONE)
7477
6266#endif 7478#endif
6267 if (! JOBS || jp->state == JOBDONE)
6268 freejob(jp); 7479 freejob(jp);
6269 INTON; 7480 INTON;
6270 return st; 7481 return st;
@@ -6317,14 +7528,14 @@ dowait(block, job)
6317 else if (WIFSTOPPED(sp->status)) 7528 else if (WIFSTOPPED(sp->status))
6318 done = 0; 7529 done = 0;
6319 } 7530 }
6320 if (stopped) { /* stopped or done */ 7531 if (stopped) { /* stopped or done */
6321 int state = done? JOBDONE : JOBSTOPPED; 7532 int state = done? JOBDONE : JOBSTOPPED;
6322 if (jp->state != state) { 7533 if (jp->state != state) {
6323 TRACE(("Job %d: changing state from %d to %d\n", jp - jobtab + 1, jp->state, state)); 7534 TRACE(("Job %d: changing state from %d to %d\n", jp - jobtab + 1, jp->state, state));
6324 jp->state = state; 7535 jp->state = state;
6325#if JOBS 7536#ifdef JOBS
6326 if (done && curjob == jp - jobtab + 1) 7537 if (done && curjob == jp - jobtab + 1)
6327 curjob = 0; /* no current job */ 7538 curjob = 0; /* no current job */
6328#endif 7539#endif
6329 } 7540 }
6330 } 7541 }
@@ -6333,7 +7544,7 @@ dowait(block, job)
6333 INTON; 7544 INTON;
6334 if (! rootshell || ! iflag || (job && thisjob == job)) { 7545 if (! rootshell || ! iflag || (job && thisjob == job)) {
6335 core = WCOREDUMP(status); 7546 core = WCOREDUMP(status);
6336#if JOBS 7547#ifdef JOBS
6337 if (WIFSTOPPED(status)) sig = WSTOPSIG(status); 7548 if (WIFSTOPPED(status)) sig = WSTOPSIG(status);
6338 else 7549 else
6339#endif 7550#endif
@@ -6343,7 +7554,7 @@ dowait(block, job)
6343 if (sig != 0 && sig != SIGINT && sig != SIGPIPE) { 7554 if (sig != 0 && sig != SIGINT && sig != SIGPIPE) {
6344 if (thisjob != job) 7555 if (thisjob != job)
6345 outfmt(out2, "%d: ", pid); 7556 outfmt(out2, "%d: ", pid);
6346#if JOBS 7557#ifdef JOBS
6347 if (sig == SIGTSTP && rootshell && iflag) 7558 if (sig == SIGTSTP && rootshell && iflag)
6348 outfmt(out2, "%%%ld ", 7559 outfmt(out2, "%%%ld ",
6349 (long)(job - jobtab + 1)); 7560 (long)(job - jobtab + 1));
@@ -6359,7 +7570,7 @@ dowait(block, job)
6359 flushout(&errout); 7570 flushout(&errout);
6360#endif 7571#endif
6361 } else { 7572 } else {
6362 TRACE(("Not printing status: status=%d, sig=%d\n", 7573 TRACE(("Not printing status: status=%d, sig=%d\n",
6363 status, sig)); 7574 status, sig));
6364 } 7575 }
6365 } else { 7576 } else {
@@ -6394,64 +7605,30 @@ dowait(block, job)
6394 * then checking to see whether it was called. If there are any 7605 * then checking to see whether it was called. If there are any
6395 * children to be waited for, it will be. 7606 * children to be waited for, it will be.
6396 * 7607 *
6397 * If neither SYSV nor BSD is defined, we don't implement nonblocking
6398 * waits at all. In this case, the user will not be informed when
6399 * a background process until the next time she runs a real program
6400 * (as opposed to running a builtin command or just typing return),
6401 * and the jobs command may give out of date information.
6402 */ 7608 */
6403 7609
6404#ifdef SYSV
6405static int gotsigchild;
6406
6407static int onsigchild() {
6408 gotsigchild = 1;
6409}
6410#endif
6411
6412
6413static int 7610static int
6414waitproc(block, status) 7611waitproc(block, status)
6415 int block; 7612 int block;
6416 int *status; 7613 int *status;
6417{ 7614{
6418#ifdef BSD
6419 int flags; 7615 int flags;
6420 7616
6421 flags = 0; 7617 flags = 0;
6422#if JOBS 7618#ifdef JOBS
6423 if (jobctl) 7619 if (jobctl)
6424 flags |= WUNTRACED; 7620 flags |= WUNTRACED;
6425#endif 7621#endif
6426 if (block == 0) 7622 if (block == 0)
6427 flags |= WNOHANG; 7623 flags |= WNOHANG;
6428 return wait3(status, flags, (struct rusage *)NULL); 7624 return wait3(status, flags, (struct rusage *)NULL);
6429#else
6430#ifdef SYSV
6431 int (*save)();
6432
6433 if (block == 0) {
6434 gotsigchild = 0;
6435 save = signal(SIGCLD, onsigchild);
6436 signal(SIGCLD, save);
6437 if (gotsigchild == 0)
6438 return 0;
6439 }
6440 return wait(status);
6441#else
6442 if (block == 0)
6443 return 0;
6444 return wait(status);
6445#endif
6446#endif
6447} 7625}
6448 7626
6449/* 7627/*
6450 * return 1 if there are stopped jobs, otherwise 0 7628 * return 1 if there are stopped jobs, otherwise 0
6451 */ 7629 */
6452static int job_warning = 0;
6453static int 7630static int
6454stoppedjobs() 7631stoppedjobs(void)
6455{ 7632{
6456 int jobno; 7633 int jobno;
6457 struct job *jp; 7634 struct job *jp;
@@ -6478,26 +7655,51 @@ stoppedjobs()
6478 7655
6479static char *cmdnextc; 7656static char *cmdnextc;
6480static int cmdnleft; 7657static int cmdnleft;
6481#define MAXCMDTEXT 200 7658#define MAXCMDTEXT 200
6482 7659
6483static char * 7660static void
6484commandtext(n) 7661cmdputs(const char *s)
6485 union node *n; 7662{
6486 { 7663 const char *p;
6487 char *name; 7664 char *q;
7665 char c;
7666 int subtype = 0;
6488 7667
6489 cmdnextc = name = ckmalloc(MAXCMDTEXT); 7668 if (cmdnleft <= 0)
6490 cmdnleft = MAXCMDTEXT - 4; 7669 return;
6491 cmdtxt(n); 7670 p = s;
6492 *cmdnextc = '\0'; 7671 q = cmdnextc;
6493 return name; 7672 while ((c = *p++) != '\0') {
7673 if (c == CTLESC)
7674 *q++ = *p++;
7675 else if (c == CTLVAR) {
7676 *q++ = '$';
7677 if (--cmdnleft > 0)
7678 *q++ = '{';
7679 subtype = *p++;
7680 } else if (c == '=' && subtype != 0) {
7681 *q++ = "}-+?="[(subtype & VSTYPE) - VSNORMAL];
7682 subtype = 0;
7683 } else if (c == CTLENDVAR) {
7684 *q++ = '}';
7685 } else if (c == CTLBACKQ || c == CTLBACKQ+CTLQUOTE)
7686 cmdnleft++; /* ignore it */
7687 else
7688 *q++ = c;
7689 if (--cmdnleft <= 0) {
7690 *q++ = '.';
7691 *q++ = '.';
7692 *q++ = '.';
7693 break;
7694 }
7695 }
7696 cmdnextc = q;
6494} 7697}
6495 7698
6496 7699
6497static void 7700static void
6498cmdtxt(n) 7701cmdtxt(const union node *n)
6499 union node *n; 7702{
6500 {
6501 union node *np; 7703 union node *np;
6502 struct nodelist *lp; 7704 struct nodelist *lp;
6503 const char *p; 7705 const char *p;
@@ -6624,53 +7826,23 @@ redir:
6624} 7826}
6625 7827
6626 7828
7829static char *
7830commandtext(const union node *n)
7831{
7832 char *name;
6627 7833
6628static void 7834 cmdnextc = name = ckmalloc(MAXCMDTEXT);
6629cmdputs(s) 7835 cmdnleft = MAXCMDTEXT - 4;
6630 const char *s; 7836 cmdtxt(n);
6631 { 7837 *cmdnextc = '\0';
6632 const char *p; 7838 return name;
6633 char *q;
6634 char c;
6635 int subtype = 0;
6636
6637 if (cmdnleft <= 0)
6638 return;
6639 p = s;
6640 q = cmdnextc;
6641 while ((c = *p++) != '\0') {
6642 if (c == CTLESC)
6643 *q++ = *p++;
6644 else if (c == CTLVAR) {
6645 *q++ = '$';
6646 if (--cmdnleft > 0)
6647 *q++ = '{';
6648 subtype = *p++;
6649 } else if (c == '=' && subtype != 0) {
6650 *q++ = "}-+?="[(subtype & VSTYPE) - VSNORMAL];
6651 subtype = 0;
6652 } else if (c == CTLENDVAR) {
6653 *q++ = '}';
6654 } else if (c == CTLBACKQ || c == CTLBACKQ+CTLQUOTE)
6655 cmdnleft++; /* ignore it */
6656 else
6657 *q++ = c;
6658 if (--cmdnleft <= 0) {
6659 *q++ = '.';
6660 *q++ = '.';
6661 *q++ = '.';
6662 break;
6663 }
6664 }
6665 cmdnextc = q;
6666} 7839}
6667 7840
7841
6668static void waitonint(int sig) { 7842static void waitonint(int sig) {
6669 intreceived = 1; 7843 intreceived = 1;
6670 return; 7844 return;
6671} 7845}
6672/* $NetBSD: mail.c,v 1.14 2000/07/03 03:26:19 matt Exp $ */
6673
6674/* 7846/*
6675 * Routines to check for mail. (Perhaps make part of main.c?) 7847 * Routines to check for mail. (Perhaps make part of main.c?)
6676 */ 7848 */
@@ -6679,8 +7851,8 @@ static void waitonint(int sig) {
6679#define MAXMBOXES 10 7851#define MAXMBOXES 10
6680 7852
6681 7853
6682static int nmboxes; /* number of mailboxes */ 7854static int nmboxes; /* number of mailboxes */
6683static time_t mailtime[MAXMBOXES]; /* times of mailboxes */ 7855static time_t mailtime[MAXMBOXES]; /* times of mailboxes */
6684 7856
6685 7857
6686 7858
@@ -6691,8 +7863,7 @@ static time_t mailtime[MAXMBOXES]; /* times of mailboxes */
6691 */ 7863 */
6692 7864
6693static void 7865static void
6694chkmail(silent) 7866chkmail(int silent)
6695 int silent;
6696{ 7867{
6697 int i; 7868 int i;
6698 const char *mpath; 7869 const char *mpath;
@@ -6718,18 +7889,7 @@ chkmail(silent)
6718 if (q[-1] != '/') 7889 if (q[-1] != '/')
6719 abort(); 7890 abort();
6720#endif 7891#endif
6721 q[-1] = '\0'; /* delete trailing '/' */ 7892 q[-1] = '\0'; /* delete trailing '/' */
6722#ifdef notdef /* this is what the System V shell claims to do (it lies) */
6723 if (stat(p, &statb) < 0)
6724 statb.st_mtime = 0;
6725 if (statb.st_mtime > mailtime[i] && ! silent) {
6726 outfmt(
6727 &errout, snlfmt,
6728 pathopt? pathopt : "you have mail"
6729 );
6730 }
6731 mailtime[i] = statb.st_mtime;
6732#else /* this is what it should do */
6733 if (stat(p, &statb) < 0) 7893 if (stat(p, &statb) < 0)
6734 statb.st_size = 0; 7894 statb.st_size = 0;
6735 if (statb.st_size > mailtime[i] && ! silent) { 7895 if (statb.st_size > mailtime[i] && ! silent) {
@@ -6739,28 +7899,27 @@ chkmail(silent)
6739 ); 7899 );
6740 } 7900 }
6741 mailtime[i] = statb.st_size; 7901 mailtime[i] = statb.st_size;
6742#endif
6743 } 7902 }
6744 nmboxes = i; 7903 nmboxes = i;
6745 popstackmark(&smark); 7904 popstackmark(&smark);
6746} 7905}
6747/* $NetBSD: main.c,v 1.40 2001/02/04 19:52:06 christos Exp $ */
6748
6749 7906
6750#define PROFILE 0 7907#define PROFILE 0
6751 7908
6752static int rootpid;
6753static int rootshell;
6754#if PROFILE 7909#if PROFILE
6755short profile_buf[16384]; 7910static short profile_buf[16384];
6756extern int etext(); 7911extern int etext();
6757#endif 7912#endif
6758 7913
6759static void read_profile __P((const char *)); 7914static void read_profile (const char *);
6760static char *find_dot_file __P((char *)); 7915static char *find_dot_file (char *);
6761int shell_main __P((int, char **)); 7916static void cmdloop (int);
7917static void options (int);
7918static void minus_o (char *, int);
7919static void setoption (int, int);
7920static void procargs (int, char **);
7921
6762 7922
6763extern int oexitstatus;
6764/* 7923/*
6765 * Main routine. We initialize things, parse the arguments, execute 7924 * Main routine. We initialize things, parse the arguments, execute
6766 * profiles if we're a login shell, and then call cmdloop to execute 7925 * profiles if we're a login shell, and then call cmdloop to execute
@@ -6781,7 +7940,6 @@ shell_main(argc, argv)
6781 7940
6782 DOTCMD = find_builtin("."); 7941 DOTCMD = find_builtin(".");
6783 BLTINCMD = find_builtin("builtin"); 7942 BLTINCMD = find_builtin("builtin");
6784 COMMANDCMD = find_builtin("command");
6785 EXECCMD = find_builtin("exec"); 7943 EXECCMD = find_builtin("exec");
6786 EVALCMD = find_builtin("eval"); 7944 EVALCMD = find_builtin("eval");
6787 7945
@@ -6824,18 +7982,14 @@ shell_main(argc, argv)
6824 exitshell(exitstatus); 7982 exitshell(exitstatus);
6825 } 7983 }
6826 reset(); 7984 reset();
6827 if (exception == EXINT 7985 if (exception == EXINT) {
6828#if ATTY
6829 && (! attyset() || equal(termval(), "emacs"))
6830#endif
6831 ) {
6832 out2c('\n'); 7986 out2c('\n');
6833#ifdef FLUSHERR 7987#ifdef FLUSHERR
6834 flushout(out2); 7988 flushout(out2);
6835#endif 7989#endif
6836 } 7990 }
6837 popstackmark(&smark); 7991 popstackmark(&smark);
6838 FORCEINTON; /* enable interrupts */ 7992 FORCEINTON; /* enable interrupts */
6839 if (state == 1) 7993 if (state == 1)
6840 goto state1; 7994 goto state1;
6841 else if (state == 2) 7995 else if (state == 2)
@@ -6878,7 +8032,7 @@ state3:
6878 state = 4; 8032 state = 4;
6879 if (sflag == 0 || minusc) { 8033 if (sflag == 0 || minusc) {
6880 static int sigs[] = { 8034 static int sigs[] = {
6881 SIGINT, SIGQUIT, SIGHUP, 8035 SIGINT, SIGQUIT, SIGHUP,
6882#ifdef SIGTSTP 8036#ifdef SIGTSTP
6883 SIGTSTP, 8037 SIGTSTP,
6884#endif 8038#endif
@@ -6895,7 +8049,7 @@ state3:
6895 evalstring(minusc, 0); 8049 evalstring(minusc, 0);
6896 8050
6897 if (sflag || minusc == NULL) { 8051 if (sflag || minusc == NULL) {
6898state4: /* XXX ??? - why isn't this before the "if" statement */ 8052state4: /* XXX ??? - why isn't this before the "if" statement */
6899 cmdloop(1); 8053 cmdloop(1);
6900 } 8054 }
6901#if PROFILE 8055#if PROFILE
@@ -6912,8 +8066,7 @@ state4: /* XXX ??? - why isn't this before the "if" statement */
6912 */ 8066 */
6913 8067
6914static void 8068static void
6915cmdloop(top) 8069cmdloop(int top)
6916 int top;
6917{ 8070{
6918 union node *n; 8071 union node *n;
6919 struct stackmark smark; 8072 struct stackmark smark;
@@ -7002,8 +8155,7 @@ read_profile(name)
7002 */ 8155 */
7003 8156
7004static void 8157static void
7005readcmdfile(name) 8158readcmdfile(const char *name)
7006 char *name;
7007{ 8159{
7008 int fd; 8160 int fd;
7009 8161
@@ -7064,7 +8216,7 @@ dotcmd(argc, argv)
7064 for (sp = cmdenviron; sp ; sp = sp->next) 8216 for (sp = cmdenviron; sp ; sp = sp->next)
7065 setvareq(savestr(sp->text), VSTRFIXED|VTEXTFIXED); 8217 setvareq(savestr(sp->text), VSTRFIXED|VTEXTFIXED);
7066 8218
7067 if (argc >= 2) { /* That's what SVR2 does */ 8219 if (argc >= 2) { /* That's what SVR2 does */
7068 char *fullname; 8220 char *fullname;
7069 struct stackmark smark; 8221 struct stackmark smark;
7070 8222
@@ -7094,38 +8246,8 @@ exitcmd(argc, argv)
7094 exitshell(exitstatus); 8246 exitshell(exitstatus);
7095 /* NOTREACHED */ 8247 /* NOTREACHED */
7096} 8248}
7097/* $NetBSD: memalloc.c,v 1.23 2000/11/01 19:56:01 christos Exp $ */ 8249static pointer
7098 8250stalloc(int nbytes)
7099/*
7100 * Parse trees for commands are allocated in lifo order, so we use a stack
7101 * to make this more efficient, and also to avoid all sorts of exception
7102 * handling code to handle interrupts in the middle of a parse.
7103 *
7104 * The size 504 was chosen because the Ultrix malloc handles that size
7105 * well.
7106 */
7107
7108#define MINSIZE 504 /* minimum size of a block */
7109
7110
7111struct stack_block {
7112 struct stack_block *prev;
7113 char space[MINSIZE];
7114};
7115
7116struct stack_block stackbase;
7117struct stack_block *stackp = &stackbase;
7118struct stackmark *markp;
7119static char *stacknxt = stackbase.space;
7120static int stacknleft = MINSIZE;
7121static int sstrnleft;
7122static int herefd = -1;
7123
7124
7125
7126pointer
7127stalloc(nbytes)
7128 int nbytes;
7129{ 8251{
7130 char *p; 8252 char *p;
7131 8253
@@ -7153,11 +8275,10 @@ stalloc(nbytes)
7153 8275
7154 8276
7155static void 8277static void
7156stunalloc(p) 8278stunalloc(pointer p)
7157 pointer p; 8279{
7158 {
7159#ifdef DEBUG 8280#ifdef DEBUG
7160 if (p == NULL) { /*DEBUG */ 8281 if (p == NULL) { /*DEBUG */
7161 write(2, "stunalloc\n", 10); 8282 write(2, "stunalloc\n", 10);
7162 abort(); 8283 abort();
7163 } 8284 }
@@ -7170,11 +8291,9 @@ stunalloc(p)
7170} 8291}
7171 8292
7172 8293
7173
7174static void 8294static void
7175setstackmark(mark) 8295setstackmark(struct stackmark *mark)
7176 struct stackmark *mark; 8296{
7177 {
7178 mark->stackp = stackp; 8297 mark->stackp = stackp;
7179 mark->stacknxt = stacknxt; 8298 mark->stacknxt = stacknxt;
7180 mark->stacknleft = stacknleft; 8299 mark->stacknleft = stacknleft;
@@ -7184,9 +8303,8 @@ setstackmark(mark)
7184 8303
7185 8304
7186static void 8305static void
7187popstackmark(mark) 8306popstackmark(struct stackmark *mark)
7188 struct stackmark *mark; 8307{
7189 {
7190 struct stack_block *sp; 8308 struct stack_block *sp;
7191 8309
7192 INTOFF; 8310 INTOFF;
@@ -7213,7 +8331,7 @@ popstackmark(mark)
7213 */ 8331 */
7214 8332
7215static void 8333static void
7216growstackblock() { 8334growstackblock(void) {
7217 char *p; 8335 char *p;
7218 int newlen = ALIGN(stacknleft * 2 + 100); 8336 int newlen = ALIGN(stacknleft * 2 + 100);
7219 char *oldspace = stacknxt; 8337 char *oldspace = stacknxt;
@@ -7233,7 +8351,7 @@ growstackblock() {
7233 stacknleft = newlen; 8351 stacknleft = newlen;
7234 { 8352 {
7235 /* Stack marks pointing to the start of the old block 8353 /* Stack marks pointing to the start of the old block
7236 * must be relocated to point to the new block 8354 * must be relocated to point to the new block
7237 */ 8355 */
7238 struct stackmark *xmark; 8356 struct stackmark *xmark;
7239 xmark = markp; 8357 xmark = markp;
@@ -7248,16 +8366,15 @@ growstackblock() {
7248 } else { 8366 } else {
7249 p = stalloc(newlen); 8367 p = stalloc(newlen);
7250 memcpy(p, oldspace, oldlen); 8368 memcpy(p, oldspace, oldlen);
7251 stacknxt = p; /* free the space */ 8369 stacknxt = p; /* free the space */
7252 stacknleft += newlen; /* we just allocated */ 8370 stacknleft += newlen; /* we just allocated */
7253 } 8371 }
7254} 8372}
7255 8373
7256 8374
7257 8375
7258static void 8376static inline void
7259grabstackblock(len) 8377grabstackblock(int len)
7260 int len;
7261{ 8378{
7262 len = ALIGN(len); 8379 len = ALIGN(len);
7263 stacknxt += len; 8380 stacknxt += len;
@@ -7286,7 +8403,7 @@ grabstackblock(len)
7286 8403
7287 8404
7288static char * 8405static char *
7289growstackstr() { 8406growstackstr(void) {
7290 int len = stackblocksize(); 8407 int len = stackblocksize();
7291 if (herefd >= 0 && len >= 1024) { 8408 if (herefd >= 0 && len >= 1024) {
7292 xwrite(herefd, stackblock(), len); 8409 xwrite(herefd, stackblock(), len);
@@ -7316,16 +8433,12 @@ makestrspace(size_t newlen) {
7316 8433
7317 8434
7318static void 8435static void
7319ungrabstackstr(s, p) 8436ungrabstackstr(char *s, char *p)
7320 char *s; 8437{
7321 char *p;
7322 {
7323 stacknleft += stacknxt - s; 8438 stacknleft += stacknxt - s;
7324 stacknxt = s; 8439 stacknxt = s;
7325 sstrnleft = stacknleft - (p - s); 8440 sstrnleft = stacknleft - (p - s);
7326} 8441}
7327/* $NetBSD: miscbltin.c,v 1.30 2001/02/04 19:52:06 christos Exp $ */
7328
7329/* 8442/*
7330 * Miscelaneous builtins. 8443 * Miscelaneous builtins.
7331 */ 8444 */
@@ -7334,7 +8447,7 @@ ungrabstackstr(s, p)
7334#undef rflag 8447#undef rflag
7335 8448
7336#ifdef __GLIBC__ 8449#ifdef __GLIBC__
7337mode_t getmode(const void *, mode_t); 8450static mode_t getmode(const void *, mode_t);
7338static void *setmode(const char *); 8451static void *setmode(const char *);
7339 8452
7340#if !defined(__GLIBC__) || __GLIBC__ == 2 && __GLIBC_MINOR__ < 1 8453#if !defined(__GLIBC__) || __GLIBC__ == 2 && __GLIBC_MINOR__ < 1
@@ -7531,46 +8644,46 @@ umaskcmd(argc, argv)
7531 8644
7532struct limits { 8645struct limits {
7533 const char *name; 8646 const char *name;
7534 int cmd; 8647 int cmd;
7535 int factor; /* multiply by to get rlim_{cur,max} values */ 8648 int factor; /* multiply by to get rlim_{cur,max} values */
7536 char option; 8649 char option;
7537}; 8650};
7538 8651
7539static const struct limits limits[] = { 8652static const struct limits limits[] = {
7540#ifdef RLIMIT_CPU 8653#ifdef RLIMIT_CPU
7541 { "time(seconds)", RLIMIT_CPU, 1, 't' }, 8654 { "time(seconds)", RLIMIT_CPU, 1, 't' },
7542#endif 8655#endif
7543#ifdef RLIMIT_FSIZE 8656#ifdef RLIMIT_FSIZE
7544 { "file(blocks)", RLIMIT_FSIZE, 512, 'f' }, 8657 { "file(blocks)", RLIMIT_FSIZE, 512, 'f' },
7545#endif 8658#endif
7546#ifdef RLIMIT_DATA 8659#ifdef RLIMIT_DATA
7547 { "data(kbytes)", RLIMIT_DATA, 1024, 'd' }, 8660 { "data(kbytes)", RLIMIT_DATA, 1024, 'd' },
7548#endif 8661#endif
7549#ifdef RLIMIT_STACK 8662#ifdef RLIMIT_STACK
7550 { "stack(kbytes)", RLIMIT_STACK, 1024, 's' }, 8663 { "stack(kbytes)", RLIMIT_STACK, 1024, 's' },
7551#endif 8664#endif
7552#ifdef RLIMIT_CORE 8665#ifdef RLIMIT_CORE
7553 { "coredump(blocks)", RLIMIT_CORE, 512, 'c' }, 8666 { "coredump(blocks)", RLIMIT_CORE, 512, 'c' },
7554#endif 8667#endif
7555#ifdef RLIMIT_RSS 8668#ifdef RLIMIT_RSS
7556 { "memory(kbytes)", RLIMIT_RSS, 1024, 'm' }, 8669 { "memory(kbytes)", RLIMIT_RSS, 1024, 'm' },
7557#endif 8670#endif
7558#ifdef RLIMIT_MEMLOCK 8671#ifdef RLIMIT_MEMLOCK
7559 { "locked memory(kbytes)", RLIMIT_MEMLOCK, 1024, 'l' }, 8672 { "locked memory(kbytes)", RLIMIT_MEMLOCK, 1024, 'l' },
7560#endif 8673#endif
7561#ifdef RLIMIT_NPROC 8674#ifdef RLIMIT_NPROC
7562 { "process(processes)", RLIMIT_NPROC, 1, 'p' }, 8675 { "process(processes)", RLIMIT_NPROC, 1, 'p' },
7563#endif 8676#endif
7564#ifdef RLIMIT_NOFILE 8677#ifdef RLIMIT_NOFILE
7565 { "nofiles(descriptors)", RLIMIT_NOFILE, 1, 'n' }, 8678 { "nofiles(descriptors)", RLIMIT_NOFILE, 1, 'n' },
7566#endif 8679#endif
7567#ifdef RLIMIT_VMEM 8680#ifdef RLIMIT_VMEM
7568 { "vmemory(kbytes)", RLIMIT_VMEM, 1024, 'v' }, 8681 { "vmemory(kbytes)", RLIMIT_VMEM, 1024, 'v' },
7569#endif 8682#endif
7570#ifdef RLIMIT_SWAP 8683#ifdef RLIMIT_SWAP
7571 { "swap(kbytes)", RLIMIT_SWAP, 1024, 'w' }, 8684 { "swap(kbytes)", RLIMIT_SWAP, 1024, 'w' },
7572#endif 8685#endif
7573 { (char *) 0, 0, 0, '\0' } 8686 { (char *) 0, 0, 0, '\0' }
7574}; 8687};
7575 8688
7576static int 8689static int
@@ -7578,14 +8691,14 @@ ulimitcmd(argc, argv)
7578 int argc; 8691 int argc;
7579 char **argv; 8692 char **argv;
7580{ 8693{
7581 int c; 8694 int c;
7582 rlim_t val = 0; 8695 rlim_t val = 0;
7583 enum { SOFT = 0x1, HARD = 0x2 } 8696 enum { SOFT = 0x1, HARD = 0x2 }
7584 how = SOFT | HARD; 8697 how = SOFT | HARD;
7585 const struct limits *l; 8698 const struct limits *l;
7586 int set, all = 0; 8699 int set, all = 0;
7587 int optc, what; 8700 int optc, what;
7588 struct rlimit limit; 8701 struct rlimit limit;
7589 8702
7590 what = 'f'; 8703 what = 'f';
7591 while ((optc = nextopt("HSatfdsmcnpl")) != '\0') 8704 while ((optc = nextopt("HSatfdsmcnpl")) != '\0')
@@ -7644,11 +8757,7 @@ ulimitcmd(argc, argv)
7644 else 8757 else
7645 { 8758 {
7646 val /= l->factor; 8759 val /= l->factor;
7647#ifdef BSD4_4
7648 out1fmt("%lld\n", (long long) val); 8760 out1fmt("%lld\n", (long long) val);
7649#else
7650 out1fmt("%ld\n", (long) val);
7651#endif
7652 } 8761 }
7653 } 8762 }
7654 return 0; 8763 return 0;
@@ -7661,7 +8770,7 @@ ulimitcmd(argc, argv)
7661 if (how & SOFT) 8770 if (how & SOFT)
7662 limit.rlim_cur = val; 8771 limit.rlim_cur = val;
7663 if (setrlimit(l->cmd, &limit) < 0) 8772 if (setrlimit(l->cmd, &limit) < 0)
7664 error("error setting limit (%s)", strerror(errno)); 8773 error("error setting limit (%m)");
7665 } else { 8774 } else {
7666 if (how & SOFT) 8775 if (how & SOFT)
7667 val = limit.rlim_cur; 8776 val = limit.rlim_cur;
@@ -7673,63 +8782,11 @@ ulimitcmd(argc, argv)
7673 else 8782 else
7674 { 8783 {
7675 val /= l->factor; 8784 val /= l->factor;
7676#ifdef BSD4_4
7677 out1fmt("%lld\n", (long long) val); 8785 out1fmt("%lld\n", (long long) val);
7678#else
7679 out1fmt("%ld\n", (long) val);
7680#endif
7681 } 8786 }
7682 } 8787 }
7683 return 0; 8788 return 0;
7684} 8789}
7685/* $NetBSD: mystring.c,v 1.14 1999/07/09 03:05:50 christos Exp $ */
7686
7687/*
7688 * String functions.
7689 *
7690 * equal(s1, s2) Return true if strings are equal.
7691 * scopy(from, to) Copy a string.
7692 * scopyn(from, to, n) Like scopy, but checks for overflow.
7693 * number(s) Convert a string of digits to an integer.
7694 * is_number(s) Return true if s is a string of digits.
7695 */
7696
7697static char nullstr[1]; /* zero length string */
7698static const char spcstr[] = " ";
7699static const char snlfmt[] = "%s\n";
7700
7701/*
7702 * equal - #defined in mystring.h
7703 */
7704
7705/*
7706 * scopy - #defined in mystring.h
7707 */
7708
7709
7710#if 0
7711/*
7712 * scopyn - copy a string from "from" to "to", truncating the string
7713 * if necessary. "To" is always nul terminated, even if
7714 * truncation is performed. "Size" is the size of "to".
7715 */
7716
7717static void
7718scopyn(from, to, size)
7719 char const *from;
7720 char *to;
7721 int size;
7722 {
7723
7724 while (--size > 0) {
7725 if ((*to++ = *from++) == '\0')
7726 return;
7727 }
7728 *to = '\0';
7729}
7730#endif
7731
7732
7733/* 8790/*
7734 * prefix -- see if pfx is a prefix of string. 8791 * prefix -- see if pfx is a prefix of string.
7735 */ 8792 */
@@ -7746,40 +8803,42 @@ prefix(pfx, string)
7746 return 1; 8803 return 1;
7747} 8804}
7748 8805
7749
7750/* 8806/*
7751 * Convert a string of digits to an integer, printing an error message on 8807 * Return true if s is a string of digits, and save munber in intptr
7752 * failure. 8808 * nagative is bad
7753 */ 8809 */
7754 8810
7755static int 8811static int
7756number(s) 8812is_number(const char *p, int *intptr)
7757 const char *s; 8813{
7758 { 8814 int ret = 0;
7759
7760 if (! is_number(s))
7761 error("Illegal number: %s", s);
7762 return atoi(s);
7763}
7764 8815
8816 do {
8817 if (! is_digit(*p))
8818 return 0;
8819 ret *= 10;
8820 ret += digit_val(*p);
8821 p++;
8822 } while (*p != '\0');
7765 8823
8824 *intptr = ret;
8825 return 1;
8826}
7766 8827
7767/* 8828/*
7768 * Check for a valid number. This should be elsewhere. 8829 * Convert a string of digits to an integer, printing an error message on
8830 * failure.
7769 */ 8831 */
7770 8832
7771static int 8833static int
7772is_number(p) 8834number(const char *s)
7773 const char *p; 8835{
7774 { 8836 int i;
7775 do { 8837 if (! is_number(s, &i))
7776 if (! is_digit(*p)) 8838 error("Illegal number: %s", s);
7777 return 0; 8839 return i;
7778 } while (*++p != '\0');
7779 return 1;
7780} 8840}
7781 8841
7782
7783/* 8842/*
7784 * Produce a possibly single quoted string suitable as input to the shell. 8843 * Produce a possibly single quoted string suitable as input to the shell.
7785 * The return string is allocated on the stack. 8844 * The return string is allocated on the stack.
@@ -7863,38 +8922,20 @@ sstrdup(const char *p)
7863 return memcpy(stalloc(len), p, len); 8922 return memcpy(stalloc(len), p, len);
7864} 8923}
7865 8924
7866/*
7867 * Wrapper around strcmp for qsort/bsearch/...
7868 */
7869static int
7870pstrcmp(const void *a, const void *b)
7871{
7872 return strcmp(*(const char *const *) a, *(const char *const *) b);
7873}
7874 8925
7875/* 8926/*
7876 * Find a string is in a sorted array.
7877 */
7878static const char *const *
7879findstring(const char *s, const char *const *array, size_t nmemb)
7880{
7881 return bsearch(&s, array, nmemb, sizeof(const char *), pstrcmp);
7882}
7883/*
7884 * This file was generated by the mknodes program. 8927 * This file was generated by the mknodes program.
7885 */ 8928 */
7886 8929
7887/* $NetBSD: nodes.c.pat,v 1.8 1997/04/11 23:03:09 christos Exp $ */
7888
7889/* 8930/*
7890 * Routine for dealing with parsed shell commands. 8931 * Routine for dealing with parsed shell commands.
7891 */ 8932 */
7892 8933
7893 8934
7894static int funcblocksize; /* size of structures in function */ 8935static int funcblocksize; /* size of structures in function */
7895static int funcstringsize; /* size of strings in node */ 8936static int funcstringsize; /* size of strings in node */
7896pointer funcblock; /* block to allocate function from */ 8937static pointer funcblock; /* block to allocate function from */
7897static char *funcstring; /* block to allocate strings from */ 8938static char *funcstring; /* block to allocate strings from */
7898 8939
7899static const short nodesize[26] = { 8940static const short nodesize[26] = {
7900 ALIGN(sizeof (struct nbinary)), 8941 ALIGN(sizeof (struct nbinary)),
@@ -7926,11 +8967,11 @@ static const short nodesize[26] = {
7926}; 8967};
7927 8968
7928 8969
7929static void calcsize __P((union node *)); 8970static void calcsize (union node *);
7930static void sizenodelist __P((struct nodelist *)); 8971static void sizenodelist (struct nodelist *);
7931static union node *copynode __P((union node *)); 8972static union node *copynode (union node *);
7932static struct nodelist *copynodelist __P((struct nodelist *)); 8973static struct nodelist *copynodelist (struct nodelist *);
7933static char *nodesavestr __P((char *)); 8974static char *nodesavestr (char *);
7934 8975
7935 8976
7936 8977
@@ -7938,9 +8979,8 @@ static char *nodesavestr __P((char *));
7938 * Make a copy of a parse tree. 8979 * Make a copy of a parse tree.
7939 */ 8980 */
7940 8981
7941union node * 8982static union node *
7942copyfunc(n) 8983copyfunc(union node *n)
7943 union node *n;
7944{ 8984{
7945 if (n == NULL) 8985 if (n == NULL)
7946 return NULL; 8986 return NULL;
@@ -8181,54 +9221,8 @@ nodesavestr(s)
8181#endif 9221#endif
8182} 9222}
8183 9223
8184
8185
8186/*
8187 * Free a parse tree.
8188 */
8189
8190static void
8191freefunc(n)
8192 union node *n;
8193{
8194 if (n)
8195 ckfree(n);
8196}
8197/* $NetBSD: options.c,v 1.31 2001/02/26 13:06:43 wiz Exp $ */
8198
8199
8200struct optent optlist[NOPTS] = {
8201 { "errexit", 'e', 0 },
8202 { "noglob", 'f', 0 },
8203 { "ignoreeof", 'I', 0 },
8204 { "interactive",'i', 0 },
8205 { "monitor", 'm', 0 },
8206 { "noexec", 'n', 0 },
8207 { "stdin", 's', 0 },
8208 { "xtrace", 'x', 0 },
8209 { "verbose", 'v', 0 },
8210 { "vi", 'V', 0 },
8211 { "emacs", 'E', 0 },
8212 { "noclobber", 'C', 0 },
8213 { "allexport", 'a', 0 },
8214 { "notify", 'b', 0 },
8215 { "nounset", 'u', 0 },
8216 { "quietprofile", 'q', 0 },
8217};
8218static char *arg0; /* value of $0 */
8219struct shparam shellparam; /* current positional parameters */
8220static char **argptr; /* argument list for builtin commands */
8221static char *optionarg; /* set by nextopt (like getopt) */
8222static char *optptr; /* used by nextopt */
8223
8224static char *minusc; /* argument to -c option */
8225
8226
8227static void options __P((int));
8228static void minus_o __P((char *, int));
8229static void setoption __P((int, int));
8230#ifdef ASH_GETOPTS 9224#ifdef ASH_GETOPTS
8231static int getopts __P((char *, char *, char **, int *, int *)); 9225static int getopts (char *, char *, char **, int *, int *);
8232#endif 9226#endif
8233 9227
8234 9228
@@ -8247,7 +9241,7 @@ procargs(argc, argv)
8247 if (argc > 0) 9241 if (argc > 0)
8248 argptr++; 9242 argptr++;
8249 for (i = 0; i < NOPTS; i++) 9243 for (i = 0; i < NOPTS; i++)
8250 optlist[i].val = 2; 9244 optent_val(i) = 2;
8251 options(1); 9245 options(1);
8252 if (*argptr == NULL && minusc == NULL) 9246 if (*argptr == NULL && minusc == NULL)
8253 sflag = 1; 9247 sflag = 1;
@@ -8256,8 +9250,8 @@ procargs(argc, argv)
8256 if (mflag == 2) 9250 if (mflag == 2)
8257 mflag = iflag; 9251 mflag = iflag;
8258 for (i = 0; i < NOPTS; i++) 9252 for (i = 0; i < NOPTS; i++)
8259 if (optlist[i].val == 2) 9253 if (optent_val(i) == 2)
8260 optlist[i].val = 0; 9254 optent_val(i) = 0;
8261 arg0 = argv[0]; 9255 arg0 = argv[0];
8262 if (sflag == 0 && minusc == NULL) { 9256 if (sflag == 0 && minusc == NULL) {
8263 commandname = argv[0]; 9257 commandname = argv[0];
@@ -8267,7 +9261,7 @@ procargs(argc, argv)
8267 } 9261 }
8268 /* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */ 9262 /* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
8269 if (argptr && minusc && *argptr) 9263 if (argptr && minusc && *argptr)
8270 arg0 = *argptr++; 9264 arg0 = *argptr++;
8271 9265
8272 shellparam.p = argptr; 9266 shellparam.p = argptr;
8273 shellparam.optind = 1; 9267 shellparam.optind = 1;
@@ -8281,12 +9275,6 @@ procargs(argc, argv)
8281} 9275}
8282 9276
8283 9277
8284static void
8285optschanged()
8286{
8287 setinteractive(iflag);
8288 setjobctl(mflag);
8289}
8290 9278
8291/* 9279/*
8292 * Process shell options. The global variable argptr contains a pointer 9280 * Process shell options. The global variable argptr contains a pointer
@@ -8307,16 +9295,16 @@ options(cmdline)
8307 argptr++; 9295 argptr++;
8308 if ((c = *p++) == '-') { 9296 if ((c = *p++) == '-') {
8309 val = 1; 9297 val = 1;
8310 if (p[0] == '\0' || (p[0] == '-' && p[1] == '\0')) { 9298 if (p[0] == '\0' || (p[0] == '-' && p[1] == '\0')) {
8311 if (!cmdline) { 9299 if (!cmdline) {
8312 /* "-" means turn off -x and -v */ 9300 /* "-" means turn off -x and -v */
8313 if (p[0] == '\0') 9301 if (p[0] == '\0')
8314 xflag = vflag = 0; 9302 xflag = vflag = 0;
8315 /* "--" means reset params */ 9303 /* "--" means reset params */
8316 else if (*argptr == NULL) 9304 else if (*argptr == NULL)
8317 setparam(argptr); 9305 setparam(argptr);
8318 } 9306 }
8319 break; /* "-" or "--" terminates options */ 9307 break; /* "-" or "--" terminates options */
8320 } 9308 }
8321 } else if (c == '+') { 9309 } else if (c == '+') {
8322 val = 0; 9310 val = 0;
@@ -8327,7 +9315,7 @@ options(cmdline)
8327 while ((c = *p++) != '\0') { 9315 while ((c = *p++) != '\0') {
8328 if (c == 'c' && cmdline) { 9316 if (c == 'c' && cmdline) {
8329 char *q; 9317 char *q;
8330#ifdef NOHACK /* removing this code allows sh -ce 'foo' for compat */ 9318#ifdef NOHACK /* removing this code allows sh -ce 'foo' for compat */
8331 if (*p == '\0') 9319 if (*p == '\0')
8332#endif 9320#endif
8333 q = *argptr++; 9321 q = *argptr++;
@@ -8358,12 +9346,12 @@ minus_o(name, val)
8358 if (name == NULL) { 9346 if (name == NULL) {
8359 out1str("Current option settings\n"); 9347 out1str("Current option settings\n");
8360 for (i = 0; i < NOPTS; i++) 9348 for (i = 0; i < NOPTS; i++)
8361 out1fmt("%-16s%s\n", optlist[i].name, 9349 out1fmt("%-16s%s\n", optent_name(optlist[i]),
8362 optlist[i].val ? "on" : "off"); 9350 optent_val(i) ? "on" : "off");
8363 } else { 9351 } else {
8364 for (i = 0; i < NOPTS; i++) 9352 for (i = 0; i < NOPTS; i++)
8365 if (equal(name, optlist[i].name)) { 9353 if (equal(name, optent_name(optlist[i]))) {
8366 setoption(optlist[i].letter, val); 9354 setoption(optent_letter(optlist[i]), val);
8367 return; 9355 return;
8368 } 9356 }
8369 error("Illegal option -o %s", name); 9357 error("Illegal option -o %s", name);
@@ -8372,15 +9360,13 @@ minus_o(name, val)
8372 9360
8373 9361
8374static void 9362static void
8375setoption(flag, val) 9363setoption(int flag, int val)
8376 char flag; 9364{
8377 int val;
8378 {
8379 int i; 9365 int i;
8380 9366
8381 for (i = 0; i < NOPTS; i++) 9367 for (i = 0; i < NOPTS; i++)
8382 if (optlist[i].letter == flag) { 9368 if (optent_letter(optlist[i]) == flag) {
8383 optlist[i].val = val; 9369 optent_val(i) = val;
8384 if (val) { 9370 if (val) {
8385 /* #%$ hack for ksh semantics */ 9371 /* #%$ hack for ksh semantics */
8386 if (flag == 'V') 9372 if (flag == 'V')
@@ -8396,26 +9382,13 @@ setoption(flag, val)
8396 9382
8397 9383
8398 9384
8399#ifdef mkinit
8400SHELLPROC {
8401 int i;
8402
8403 for (i = 0; i < NOPTS; i++)
8404 optlist[i].val = 0;
8405 optschanged();
8406
8407}
8408#endif
8409
8410
8411/* 9385/*
8412 * Set the shell parameters. 9386 * Set the shell parameters.
8413 */ 9387 */
8414 9388
8415static void 9389static void
8416setparam(argv) 9390setparam(char **argv)
8417 char **argv; 9391{
8418 {
8419 char **newparam; 9392 char **newparam;
8420 char **ap; 9393 char **ap;
8421 int nparam; 9394 int nparam;
@@ -8440,9 +9413,8 @@ setparam(argv)
8440 */ 9413 */
8441 9414
8442static void 9415static void
8443freeparam(param) 9416freeparam(volatile struct shparam *param)
8444 volatile struct shparam *param; 9417{
8445 {
8446 char **ap; 9418 char **ap;
8447 9419
8448 if (param->malloc) { 9420 if (param->malloc) {
@@ -8510,13 +9482,27 @@ setcmd(argc, argv)
8510 9482
8511 9483
8512static void 9484static void
8513getoptsreset(value) 9485getoptsreset(const char *value)
8514 const char *value;
8515{ 9486{
8516 shellparam.optind = number(value); 9487 shellparam.optind = number(value);
8517 shellparam.optoff = -1; 9488 shellparam.optoff = -1;
8518} 9489}
8519 9490
9491#ifdef BB_LOCALE_SUPPORT
9492static void change_lc_all(const char *value)
9493{
9494 if(value != 0 && *value != 0)
9495 setlocale(LC_ALL, value);
9496}
9497
9498static void change_lc_ctype(const char *value)
9499{
9500 if(value != 0 && *value != 0)
9501 setlocale(LC_CTYPE, value);
9502}
9503
9504#endif
9505
8520#ifdef ASH_GETOPTS 9506#ifdef ASH_GETOPTS
8521/* 9507/*
8522 * The getopts builtin. Shellparam.optnext points to the next argument 9508 * The getopts builtin. Shellparam.optnext points to the next argument
@@ -8612,7 +9598,7 @@ atend:
8612 goto out; 9598 goto out;
8613 } 9599 }
8614 optnext++; 9600 optnext++;
8615 if (p[0] == '-' && p[1] == '\0') /* check for "--" */ 9601 if (p[0] == '-' && p[1] == '\0') /* check for "--" */
8616 goto atend; 9602 goto atend;
8617 } 9603 }
8618 9604
@@ -8679,7 +9665,7 @@ out:
8679 } 9665 }
8680 return done; 9666 return done;
8681} 9667}
8682#endif 9668#endif
8683 9669
8684/* 9670/*
8685 * XXX - should get rid of. have all builtins use getopt(3). the 9671 * XXX - should get rid of. have all builtins use getopt(3). the
@@ -8705,7 +9691,7 @@ nextopt(optstring)
8705 if (p == NULL || *p != '-' || *++p == '\0') 9691 if (p == NULL || *p != '-' || *++p == '\0')
8706 return '\0'; 9692 return '\0';
8707 argptr++; 9693 argptr++;
8708 if (p[0] == '-' && p[1] == '\0') /* check for "--" */ 9694 if (p[0] == '-' && p[1] == '\0') /* check for "--" */
8709 return '\0'; 9695 return '\0';
8710 } 9696 }
8711 c = *p++; 9697 c = *p++;
@@ -8726,66 +9712,21 @@ nextopt(optstring)
8726} 9712}
8727 9713
8728 9714
8729/* $NetBSD: output.c,v 1.23 2001/01/07 23:39:07 lukem Exp $ */
8730
8731/* 9715/*
8732 * Shell output routines. We use our own output routines because: 9716 * Shell output routines. We use our own output routines because:
8733 * When a builtin command is interrupted we have to discard 9717 * When a builtin command is interrupted we have to discard
8734 * any pending output. 9718 * any pending output.
8735 * When a builtin command appears in back quotes, we want to 9719 * When a builtin command appears in back quotes, we want to
8736 * save the output of the command in a region obtained 9720 * save the output of the command in a region obtained
8737 * via malloc, rather than doing a fork and reading the 9721 * via malloc, rather than doing a fork and reading the
8738 * output of the command via a pipe. 9722 * output of the command via a pipe.
8739 * Our output routines may be smaller than the stdio routines. 9723 * Our output routines may be smaller than the stdio routines.
8740 */ 9724 */
8741 9725
8742 9726
8743#define OUTBUFSIZ BUFSIZ
8744#define MEM_OUT -3 /* output to dynamically allocated memory */
8745
8746
8747#ifdef USE_GLIBC_STDIO
8748struct output output = {NULL, NULL, 0, NULL, 0, 1, 0};
8749struct output errout = {NULL, NULL, 0, NULL, 0, 2, 0};
8750struct output memout = {NULL, NULL, 0, NULL, 0, MEM_OUT, 0};
8751#else
8752struct output output = {NULL, 0, NULL, OUTBUFSIZ, 1, 0};
8753struct output errout = {NULL, 0, NULL, 0, 2, 0};
8754struct output memout = {NULL, 0, NULL, 0, MEM_OUT, 0};
8755#endif
8756struct output *out1 = &output;
8757struct output *out2 = &errout;
8758
8759 9727
8760#ifndef USE_GLIBC_STDIO 9728#ifndef USE_GLIBC_STDIO
8761static void __outstr __P((const char *, size_t, struct output*)); 9729static void __outstr (const char *, size_t, struct output*);
8762#endif
8763
8764
8765#ifdef mkinit
8766
8767INCLUDE "output.h"
8768INCLUDE "memalloc.h"
8769
8770INIT {
8771#ifdef USE_GLIBC_STDIO
8772 initstreams();
8773#endif
8774}
8775
8776RESET {
8777 out1 = &output;
8778 out2 = &errout;
8779#ifdef USE_GLIBC_STDIO
8780 if (memout.stream != NULL)
8781 __closememout();
8782#endif
8783 if (memout.buf != NULL) {
8784 ckfree(memout.buf);
8785 memout.buf = NULL;
8786 }
8787}
8788
8789#endif 9730#endif
8790 9731
8791 9732
@@ -8835,10 +9776,8 @@ __outstr(const char *p, size_t len, struct output *dest) {
8835 9776
8836 9777
8837static void 9778static void
8838outstr(p, file) 9779outstr(const char *p, struct output *file)
8839 const char *p; 9780{
8840 struct output *file;
8841 {
8842#ifdef USE_GLIBC_STDIO 9781#ifdef USE_GLIBC_STDIO
8843 INTOFF; 9782 INTOFF;
8844 fputs(p, file->stream); 9783 fputs(p, file->stream);
@@ -8990,232 +9929,26 @@ fmtstr(va_alist)
8990} 9929}
8991 9930
8992#ifndef USE_GLIBC_STDIO 9931#ifndef USE_GLIBC_STDIO
8993/*
8994 * Formatted output. This routine handles a subset of the printf formats:
8995 * - Formats supported: d, u, o, p, X, s, and c.
8996 * - The x format is also accepted but is treated like X.
8997 * - The l, ll and q modifiers are accepted.
8998 * - The - and # flags are accepted; # only works with the o format.
8999 * - Width and precision may be specified with any format except c.
9000 * - An * may be given for the width or precision.
9001 * - The obsolete practice of preceding the width with a zero to get
9002 * zero padding is not supported; use the precision field.
9003 * - A % may be printed by writing %% in the format string.
9004 */
9005
9006#define TEMPSIZE 24
9007
9008#ifdef BSD4_4
9009#define HAVE_VASPRINTF 1
9010#endif
9011
9012#if !HAVE_VASPRINTF
9013static const char digit[] = "0123456789ABCDEF";
9014#endif
9015
9016 9932
9017static void 9933static void
9018doformat(dest, f, ap) 9934doformat(struct output *dest, const char *f, va_list ap)
9019 struct output *dest;
9020 const char *f; /* format string */
9021 va_list ap;
9022{ 9935{
9023#if HAVE_VASPRINTF 9936 char *pm;
9024 char *s, *t; 9937 int size = BUFSIZ;
9025 int len;
9026 9938
9027 INTOFF; 9939 while(size) {
9028 len = vasprintf(&t, f, ap); 9940 int nchars;
9029 if (len < 0) {
9030 return;
9031 }
9032 s = stalloc(++len);
9033 memcpy(s, t, len);
9034 free(t);
9035 INTON;
9036 outstr(s, dest);
9037 stunalloc(s);
9038#else /* !HAVE_VASPRINTF */
9039 char c;
9040 char temp[TEMPSIZE];
9041 int flushleft;
9042 int sharp;
9043 int width;
9044 int prec;
9045 int islong;
9046 int isquad;
9047 char *p;
9048 int sign;
9049#ifdef BSD4_4
9050 quad_t l;
9051 u_quad_t num;
9052#else
9053 long l;
9054 u_long num;
9055#endif
9056 unsigned base;
9057 int len;
9058 int size;
9059 int pad;
9060 9941
9061 while ((c = *f++) != '\0') { 9942 pm = xmalloc(size);
9062 if (c != '%') { 9943 nchars = vsnprintf(pm, size, f, ap);
9063 outc(c, dest); 9944 if(nchars > -1) {
9064 continue; 9945 outstr(pm, dest);
9065 } 9946 size = 0;
9066 flushleft = 0;
9067 sharp = 0;
9068 width = 0;
9069 prec = -1;
9070 islong = 0;
9071 isquad = 0;
9072 for (;;) {
9073 if (*f == '-')
9074 flushleft++;
9075 else if (*f == '#')
9076 sharp++;
9077 else
9078 break;
9079 f++;
9080 }
9081 if (*f == '*') {
9082 width = va_arg(ap, int);
9083 f++;
9084 } else {
9085 while (is_digit(*f)) {
9086 width = 10 * width + digit_val(*f++);
9087 }
9088 }
9089 if (*f == '.') {
9090 if (*++f == '*') {
9091 prec = va_arg(ap, int);
9092 f++;
9093 } else {
9094 prec = 0;
9095 while (is_digit(*f)) {
9096 prec = 10 * prec + digit_val(*f++);
9097 }
9098 } 9947 }
9099 } 9948 else
9100 if (*f == 'l') { 9949 size *= 2;
9101 f++; 9950 free(pm);
9102 if (*f == 'l') {
9103 isquad++;
9104 f++;
9105 } else
9106 islong++;
9107 } else if (*f == 'q') {
9108 isquad++;
9109 f++;
9110 }
9111 switch (*f) {
9112 case 'd':
9113#ifdef BSD4_4
9114 if (isquad)
9115 l = va_arg(ap, quad_t);
9116 else
9117#endif
9118 if (islong)
9119 l = va_arg(ap, long);
9120 else
9121 l = va_arg(ap, int);
9122 sign = 0;
9123 num = l;
9124 if (l < 0) {
9125 num = -l;
9126 sign = 1;
9127 }
9128 base = 10;
9129 goto number;
9130 case 'u':
9131 base = 10;
9132 goto uns_number;
9133 case 'o':
9134 base = 8;
9135 goto uns_number;
9136 case 'p':
9137 outc('0', dest);
9138 outc('x', dest);
9139 /*FALLTHROUGH*/
9140 case 'x':
9141 /* we don't implement 'x'; treat like 'X' */
9142 case 'X':
9143 base = 16;
9144uns_number: /* an unsigned number */
9145 sign = 0;
9146#ifdef BSD4_4
9147 if (isquad)
9148 num = va_arg(ap, u_quad_t);
9149 else
9150#endif
9151 if (islong)
9152 num = va_arg(ap, unsigned long);
9153 else
9154 num = va_arg(ap, unsigned int);
9155number: /* process a number */
9156 p = temp + TEMPSIZE - 1;
9157 *p = '\0';
9158 while (num) {
9159 *--p = digit[num % base];
9160 num /= base;
9161 }
9162 len = (temp + TEMPSIZE - 1) - p;
9163 if (prec < 0)
9164 prec = 1;
9165 if (sharp && *f == 'o' && prec <= len)
9166 prec = len + 1;
9167 pad = 0;
9168 if (width) {
9169 size = len;
9170 if (size < prec)
9171 size = prec;
9172 size += sign;
9173 pad = width - size;
9174 if (flushleft == 0) {
9175 while (--pad >= 0)
9176 outc(' ', dest);
9177 }
9178 }
9179 if (sign)
9180 outc('-', dest);
9181 prec -= len;
9182 while (--prec >= 0)
9183 outc('0', dest);
9184 while (*p)
9185 outc(*p++, dest);
9186 while (--pad >= 0)
9187 outc(' ', dest);
9188 break;
9189 case 's':
9190 p = va_arg(ap, char *);
9191 pad = 0;
9192 if (width) {
9193 len = strlen(p);
9194 if (prec >= 0 && len > prec)
9195 len = prec;
9196 pad = width - len;
9197 if (flushleft == 0) {
9198 while (--pad >= 0)
9199 outc(' ', dest);
9200 }
9201 }
9202 prec++;
9203 while (--prec != 0 && *p)
9204 outc(*p++, dest);
9205 while (--pad >= 0)
9206 outc(' ', dest);
9207 break;
9208 case 'c':
9209 c = va_arg(ap, int);
9210 outc(c, dest);
9211 break;
9212 default:
9213 outc(*f, dest);
9214 break;
9215 }
9216 f++;
9217 } 9951 }
9218#endif /* !HAVE_VASPRINTF */
9219} 9952}
9220#endif 9953#endif
9221 9954
@@ -9226,11 +9959,8 @@ number: /* process a number */
9226 */ 9959 */
9227 9960
9228static int 9961static int
9229xwrite(fd, buf, nbytes) 9962xwrite(int fd, const char *buf, int nbytes)
9230 int fd; 9963{
9231 const char *buf;
9232 int nbytes;
9233 {
9234 int ntry; 9964 int ntry;
9235 int i; 9965 int i;
9236 int n; 9966 int n;
@@ -9254,26 +9984,6 @@ xwrite(fd, buf, nbytes)
9254} 9984}
9255 9985
9256 9986
9257#ifdef notdef
9258/*
9259 * Version of ioctl that retries after a signal is caught.
9260 * XXX unused function
9261 */
9262
9263static int
9264xioctl(fd, request, arg)
9265 int fd;
9266 unsigned long request;
9267 char * arg;
9268{
9269 int i;
9270
9271 while ((i = ioctl(fd, request, arg)) == -1 && errno == EINTR);
9272 return i;
9273}
9274#endif
9275
9276
9277#ifdef USE_GLIBC_STDIO 9987#ifdef USE_GLIBC_STDIO
9278static void initstreams() { 9988static void initstreams() {
9279 output.stream = stdout; 9989 output.stream = stdout;
@@ -9297,8 +10007,6 @@ __closememout() {
9297 return error; 10007 return error;
9298} 10008}
9299#endif 10009#endif
9300/* $NetBSD: parser.c,v 1.46 2001/02/04 19:52:06 christos Exp $ */
9301
9302/* 10010/*
9303 * Shell command parser. 10011 * Shell command parser.
9304 */ 10012 */
@@ -9308,47 +10016,42 @@ __closememout() {
9308 10016
9309 10017
9310struct heredoc { 10018struct heredoc {
9311 struct heredoc *next; /* next here document in list */ 10019 struct heredoc *next; /* next here document in list */
9312 union node *here; /* redirection node */ 10020 union node *here; /* redirection node */
9313 char *eofmark; /* string indicating end of input */ 10021 char *eofmark; /* string indicating end of input */
9314 int striptabs; /* if set, strip leading tabs */ 10022 int striptabs; /* if set, strip leading tabs */
9315}; 10023};
9316 10024
10025static struct heredoc *heredoclist; /* list of here documents to read */
10026static int parsebackquote; /* nonzero if we are inside backquotes */
10027static int doprompt; /* if set, prompt the user */
10028static int needprompt; /* true if interactive and at start of line */
10029static int lasttoken; /* last token read */
9317 10030
10031static char *wordtext; /* text of last word returned by readtoken */
9318 10032
9319struct heredoc *heredoclist; /* list of here documents to read */ 10033static struct nodelist *backquotelist;
9320static int parsebackquote; /* nonzero if we are inside backquotes */ 10034static union node *redirnode;
9321static int doprompt; /* if set, prompt the user */
9322static int needprompt; /* true if interactive and at start of line */
9323static int lasttoken; /* last token read */
9324static int tokpushback; /* last token pushed back */
9325static char *wordtext; /* text of last word returned by readtoken */
9326static int checkkwd; /* 1 == check for kwds, 2 == also eat newlines */
9327/* 1 == check for aliases, 2 == also check for assignments */
9328static int checkalias;
9329struct nodelist *backquotelist;
9330union node *redirnode;
9331struct heredoc *heredoc; 10035struct heredoc *heredoc;
9332static int quoteflag; /* set if (part of) last token was quoted */ 10036static int quoteflag; /* set if (part of) last token was quoted */
9333static int startlinno; /* line # where last token started */ 10037static int startlinno; /* line # where last token started */
9334 10038
9335 10039
9336static union node *list __P((int)); 10040static union node *list (int);
9337static union node *andor __P((void)); 10041static union node *andor (void);
9338static union node *pipeline __P((void)); 10042static union node *pipeline (void);
9339static union node *command __P((void)); 10043static union node *command (void);
9340static union node *simplecmd __P((void)); 10044static union node *simplecmd (void);
9341static union node *makename __P((void)); 10045static void parsefname (void);
9342static void parsefname __P((void)); 10046static void parseheredoc (void);
9343static void parseheredoc __P((void)); 10047static int peektoken (void);
9344static int peektoken __P((void)); 10048static int readtoken (void);
9345static int readtoken __P((void)); 10049static int xxreadtoken (void);
9346static int xxreadtoken __P((void)); 10050static int readtoken1 (int, char const *, char *, int);
9347static int readtoken1 __P((int, char const *, char *, int)); 10051static int noexpand (char *);
9348static int noexpand __P((char *)); 10052static void synexpect (int) __attribute__((noreturn));
9349static void synexpect __P((int)) __attribute__((noreturn)); 10053static void synerror (const char *) __attribute__((noreturn));
9350static void synerror __P((const char *)) __attribute__((noreturn)); 10054static void setprompt (int);
9351static void setprompt __P((int));
9352 10055
9353 10056
9354/* 10057/*
@@ -9356,7 +10059,7 @@ static void setprompt __P((int));
9356 * valid parse tree indicating a blank line.) 10059 * valid parse tree indicating a blank line.)
9357 */ 10060 */
9358 10061
9359union node * 10062static union node *
9360parsecmd(int interact) 10063parsecmd(int interact)
9361{ 10064{
9362 int t; 10065 int t;
@@ -9436,7 +10139,7 @@ list(nlflag)
9436 if (heredoclist) 10139 if (heredoclist)
9437 parseheredoc(); 10140 parseheredoc();
9438 else 10141 else
9439 pungetc(); /* push back EOF on input */ 10142 pungetc(); /* push back EOF on input */
9440 return n1; 10143 return n1;
9441 default: 10144 default:
9442 if (nlflag) 10145 if (nlflag)
@@ -9746,7 +10449,9 @@ simplecmd() {
9746 redir = NULL; 10449 redir = NULL;
9747 rpp = &redir; 10450 rpp = &redir;
9748 10451
10452#ifdef ASH_ALIAS
9749 checkalias = 2; 10453 checkalias = 2;
10454#endif
9750 for (;;) { 10455 for (;;) {
9751 switch (readtoken()) { 10456 switch (readtoken()) {
9752 case TWORD: 10457 case TWORD:
@@ -9766,7 +10471,7 @@ simplecmd() {
9766 case TREDIR: 10471 case TREDIR:
9767 *rpp = n = redirnode; 10472 *rpp = n = redirnode;
9768 rpp = &n->nfile.next; 10473 rpp = &n->nfile.next;
9769 parsefname(); /* read name of redirection file */ 10474 parsefname(); /* read name of redirection file */
9770 break; 10475 break;
9771 case TLP: 10476 case TLP:
9772 if ( 10477 if (
@@ -9776,10 +10481,6 @@ simplecmd() {
9776 /* We have a function */ 10481 /* We have a function */
9777 if (readtoken() != TRP) 10482 if (readtoken() != TRP)
9778 synexpect(TRP); 10483 synexpect(TRP);
9779#ifdef notdef
9780 if (! goodname(n->narg.text))
9781 synerror("Bad function name");
9782#endif
9783 n->type = NDEFUN; 10484 n->type = NDEFUN;
9784 checkkwd = 2; 10485 checkkwd = 2;
9785 n->narg.next = command(); 10486 n->narg.next = command();
@@ -9805,7 +10506,7 @@ out:
9805} 10506}
9806 10507
9807static union node * 10508static union node *
9808makename() { 10509makename(void) {
9809 union node *n; 10510 union node *n;
9810 10511
9811 n = (union node *)stalloc(sizeof (struct narg)); 10512 n = (union node *)stalloc(sizeof (struct narg));
@@ -9817,7 +10518,7 @@ makename() {
9817} 10518}
9818 10519
9819static void fixredir(union node *n, const char *text, int err) 10520static void fixredir(union node *n, const char *text, int err)
9820 { 10521{
9821 TRACE(("Fix redir %s %d\n", text, err)); 10522 TRACE(("Fix redir %s %d\n", text, err));
9822 if (!err) 10523 if (!err)
9823 n->ndup.vname = NULL; 10524 n->ndup.vname = NULL;
@@ -9837,7 +10538,7 @@ static void fixredir(union node *n, const char *text, int err)
9837 10538
9838 10539
9839static void 10540static void
9840parsefname() { 10541parsefname(void) {
9841 union node *n = redirnode; 10542 union node *n = redirnode;
9842 10543
9843 if (readtoken() != TWORD) 10544 if (readtoken() != TWORD)
@@ -9912,16 +10613,25 @@ peektoken() {
9912static int 10613static int
9913readtoken() { 10614readtoken() {
9914 int t; 10615 int t;
10616#ifdef ASH_ALIAS
9915 int savecheckkwd = checkkwd; 10617 int savecheckkwd = checkkwd;
9916 int savecheckalias = checkalias; 10618 int savecheckalias = checkalias;
9917 struct alias *ap; 10619 struct alias *ap;
10620#endif
10621
9918#ifdef DEBUG 10622#ifdef DEBUG
9919 int alreadyseen = tokpushback; 10623 int alreadyseen = tokpushback;
9920#endif 10624#endif
9921 10625
10626#ifdef ASH_ALIAS
9922top: 10627top:
10628#endif
10629
9923 t = xxreadtoken(); 10630 t = xxreadtoken();
10631
10632#ifdef ASH_ALIAS
9924 checkalias = savecheckalias; 10633 checkalias = savecheckalias;
10634#endif
9925 10635
9926 if (checkkwd) { 10636 if (checkkwd) {
9927 /* 10637 /*
@@ -9950,6 +10660,7 @@ top:
9950 } 10660 }
9951 } 10661 }
9952 10662
10663#ifdef ASH_ALIAS
9953 if (t != TWORD) { 10664 if (t != TWORD) {
9954 if (t != TREDIR) { 10665 if (t != TREDIR) {
9955 checkalias = 0; 10666 checkalias = 0;
@@ -9966,6 +10677,7 @@ top:
9966 } 10677 }
9967 checkalias = 0; 10678 checkalias = 0;
9968 } 10679 }
10680#endif
9969out: 10681out:
9970#ifdef DEBUG 10682#ifdef DEBUG
9971 if (!alreadyseen) 10683 if (!alreadyseen)
@@ -9980,12 +10692,12 @@ out:
9980/* 10692/*
9981 * Read the next input token. 10693 * Read the next input token.
9982 * If the token is a word, we set backquotelist to the list of cmds in 10694 * If the token is a word, we set backquotelist to the list of cmds in
9983 * backquotes. We set quoteflag to true if any part of the word was 10695 * backquotes. We set quoteflag to true if any part of the word was
9984 * quoted. 10696 * quoted.
9985 * If the token is TREDIR, then we set redirnode to a structure containing 10697 * If the token is TREDIR, then we set redirnode to a structure containing
9986 * the redirection. 10698 * the redirection.
9987 * In all cases, the variable startlinno is set to the number of the line 10699 * In all cases, the variable startlinno is set to the number of the line
9988 * on which the token starts. 10700 * on which the token starts.
9989 * 10701 *
9990 * [Change comment: here documents and internal procedures] 10702 * [Change comment: here documents and internal procedures]
9991 * [Readtoken shouldn't have any arguments. Perhaps we should make the 10703 * [Readtoken shouldn't have any arguments. Perhaps we should make the
@@ -9995,7 +10707,7 @@ out:
9995 * have parseword (readtoken1?) handle both words and redirection.] 10707 * have parseword (readtoken1?) handle both words and redirection.]
9996 */ 10708 */
9997 10709
9998#define RETURN(token) return lasttoken = token 10710#define RETURN(token) return lasttoken = token
9999 10711
10000static int 10712static int
10001xxreadtoken() { 10713xxreadtoken() {
@@ -10010,7 +10722,7 @@ xxreadtoken() {
10010 needprompt = 0; 10722 needprompt = 0;
10011 } 10723 }
10012 startlinno = plinno; 10724 startlinno = plinno;
10013 for (;;) { /* until token or start of word found */ 10725 for (;;) { /* until token or start of word found */
10014 c = pgetc_macro(); 10726 c = pgetc_macro();
10015 switch (c) { 10727 switch (c) {
10016 case ' ': case '\t': 10728 case ' ': case '\t':
@@ -10079,12 +10791,12 @@ breakloop:
10079 * will run code that appears at the end of readtoken1. 10791 * will run code that appears at the end of readtoken1.
10080 */ 10792 */
10081 10793
10082#define CHECKEND() {goto checkend; checkend_return:;} 10794#define CHECKEND() {goto checkend; checkend_return:;}
10083#define PARSEREDIR() {goto parseredir; parseredir_return:;} 10795#define PARSEREDIR() {goto parseredir; parseredir_return:;}
10084#define PARSESUB() {goto parsesub; parsesub_return:;} 10796#define PARSESUB() {goto parsesub; parsesub_return:;}
10085#define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;} 10797#define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
10086#define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;} 10798#define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
10087#define PARSEARITH() {goto parsearith; parsearith_return:;} 10799#define PARSEARITH() {goto parsearith; parsearith_return:;}
10088 10800
10089static int 10801static int
10090readtoken1(firstc, syntax, eofmark, striptabs) 10802readtoken1(firstc, syntax, eofmark, striptabs)
@@ -10100,12 +10812,12 @@ readtoken1(firstc, syntax, eofmark, striptabs)
10100 struct nodelist *bqlist; 10812 struct nodelist *bqlist;
10101 int quotef; 10813 int quotef;
10102 int dblquote; 10814 int dblquote;
10103 int varnest; /* levels of variables expansion */ 10815 int varnest; /* levels of variables expansion */
10104 int arinest; /* levels of arithmetic expansion */ 10816 int arinest; /* levels of arithmetic expansion */
10105 int parenlevel; /* levels of parens in arithmetic */ 10817 int parenlevel; /* levels of parens in arithmetic */
10106 int dqvarnest; /* levels of variables expansion within double quotes */ 10818 int dqvarnest; /* levels of variables expansion within double quotes */
10107 int oldstyle; 10819 int oldstyle;
10108 char const *prevsyntax; /* syntax before arithmetic */ 10820 char const *prevsyntax; /* syntax before arithmetic */
10109#if __GNUC__ 10821#if __GNUC__
10110 /* Avoid longjmp clobbering */ 10822 /* Avoid longjmp clobbering */
10111 (void) &out; 10823 (void) &out;
@@ -10132,24 +10844,14 @@ readtoken1(firstc, syntax, eofmark, striptabs)
10132 dqvarnest = 0; 10844 dqvarnest = 0;
10133 10845
10134 STARTSTACKSTR(out); 10846 STARTSTACKSTR(out);
10135 loop: { /* for each line, until end of word */ 10847 loop: { /* for each line, until end of word */
10136#if ATTY 10848 CHECKEND(); /* set c to PEOF if at end of here document */
10137 if (c == '\034' && doprompt 10849 for (;;) { /* until end of line or end of word */
10138 && attyset() && ! equal(termval(), "emacs")) { 10850 CHECKSTRSPACE(3, out); /* permit 3 calls to USTPUTC */
10139 attyline();
10140 if (syntax == BASESYNTAX)
10141 return readtoken();
10142 c = pgetc();
10143 goto loop;
10144 }
10145#endif
10146 CHECKEND(); /* set c to PEOF if at end of here document */
10147 for (;;) { /* until end of line or end of word */
10148 CHECKSTRSPACE(3, out); /* permit 3 calls to USTPUTC */
10149 switch(syntax[c]) { 10851 switch(syntax[c]) {
10150 case CNL: /* '\n' */ 10852 case CNL: /* '\n' */
10151 if (syntax == BASESYNTAX) 10853 if (syntax == BASESYNTAX)
10152 goto endword; /* exit outer loop */ 10854 goto endword; /* exit outer loop */
10153 USTPUTC(c, out); 10855 USTPUTC(c, out);
10154 plinno++; 10856 plinno++;
10155 if (doprompt) 10857 if (doprompt)
@@ -10157,7 +10859,7 @@ readtoken1(firstc, syntax, eofmark, striptabs)
10157 else 10859 else
10158 setprompt(0); 10860 setprompt(0);
10159 c = pgetc(); 10861 c = pgetc();
10160 goto loop; /* continue outer loop */ 10862 goto loop; /* continue outer loop */
10161 case CWORD: 10863 case CWORD:
10162 USTPUTC(c, out); 10864 USTPUTC(c, out);
10163 break; 10865 break;
@@ -10167,7 +10869,7 @@ readtoken1(firstc, syntax, eofmark, striptabs)
10167 USTPUTC(CTLESC, out); 10869 USTPUTC(CTLESC, out);
10168 USTPUTC(c, out); 10870 USTPUTC(c, out);
10169 break; 10871 break;
10170 case CBACK: /* backslash */ 10872 case CBACK: /* backslash */
10171 c = pgetc2(); 10873 c = pgetc2();
10172 if (c == PEOF) { 10874 if (c == PEOF) {
10173 USTPUTC('\\', out); 10875 USTPUTC('\\', out);
@@ -10216,10 +10918,10 @@ readtoken1(firstc, syntax, eofmark, striptabs)
10216 quotef++; 10918 quotef++;
10217 } 10919 }
10218 break; 10920 break;
10219 case CVAR: /* '$' */ 10921 case CVAR: /* '$' */
10220 PARSESUB(); /* parse substitution */ 10922 PARSESUB(); /* parse substitution */
10221 break; 10923 break;
10222 case CENDVAR: /* '}' */ 10924 case CENDVAR: /* '}' */
10223 if (varnest > 0) { 10925 if (varnest > 0) {
10224 varnest--; 10926 varnest--;
10225 if (dqvarnest > 0) { 10927 if (dqvarnest > 0) {
@@ -10231,11 +10933,11 @@ readtoken1(firstc, syntax, eofmark, striptabs)
10231 } 10933 }
10232 break; 10934 break;
10233#ifdef ASH_MATH_SUPPORT 10935#ifdef ASH_MATH_SUPPORT
10234 case CLP: /* '(' in arithmetic */ 10936 case CLP: /* '(' in arithmetic */
10235 parenlevel++; 10937 parenlevel++;
10236 USTPUTC(c, out); 10938 USTPUTC(c, out);
10237 break; 10939 break;
10238 case CRP: /* ')' in arithmetic */ 10940 case CRP: /* ')' in arithmetic */
10239 if (parenlevel > 0) { 10941 if (parenlevel > 0) {
10240 USTPUTC(c, out); 10942 USTPUTC(c, out);
10241 --parenlevel; 10943 --parenlevel;
@@ -10261,16 +10963,16 @@ readtoken1(firstc, syntax, eofmark, striptabs)
10261 } 10963 }
10262 break; 10964 break;
10263#endif 10965#endif
10264 case CBQUOTE: /* '`' */ 10966 case CBQUOTE: /* '`' */
10265 PARSEBACKQOLD(); 10967 PARSEBACKQOLD();
10266 break; 10968 break;
10267 case CEOF: 10969 case CENDFILE:
10268 goto endword; /* exit outer loop */ 10970 goto endword; /* exit outer loop */
10269 case CIGN: 10971 case CIGN:
10270 break; 10972 break;
10271 default: 10973 default:
10272 if (varnest == 0) 10974 if (varnest == 0)
10273 goto endword; /* exit outer loop */ 10975 goto endword; /* exit outer loop */
10274 if (c != PEOA) { 10976 if (c != PEOA) {
10275 USTPUTC(c, out); 10977 USTPUTC(c, out);
10276 } 10978 }
@@ -10318,9 +11020,11 @@ endword:
10318 11020
10319checkend: { 11021checkend: {
10320 if (eofmark) { 11022 if (eofmark) {
11023#ifdef ASH_ALIAS
10321 if (c == PEOA) { 11024 if (c == PEOA) {
10322 c = pgetc2(); 11025 c = pgetc2();
10323 } 11026 }
11027#endif
10324 if (striptabs) { 11028 if (striptabs) {
10325 while (c == '\t') { 11029 while (c == '\t') {
10326 c = pgetc2(); 11030 c = pgetc2();
@@ -10370,7 +11074,7 @@ parseredir: {
10370 np->type = NTO; 11074 np->type = NTO;
10371 pungetc(); 11075 pungetc();
10372 } 11076 }
10373 } else { /* c == '<' */ 11077 } else { /* c == '<' */
10374 np->nfile.fd = 0; 11078 np->nfile.fd = 0;
10375 switch (c = pgetc()) { 11079 switch (c = pgetc()) {
10376 case '<': 11080 case '<':
@@ -10429,7 +11133,7 @@ parsesub: {
10429 ) { 11133 ) {
10430 USTPUTC('$', out); 11134 USTPUTC('$', out);
10431 pungetc(); 11135 pungetc();
10432 } else if (c == '(') { /* $(command) or $((arith)) */ 11136 } else if (c == '(') { /* $(command) or $((arith)) */
10433 if (pgetc() == '(') { 11137 if (pgetc() == '(') {
10434 PARSEARITH(); 11138 PARSEARITH();
10435 } else { 11139 } else {
@@ -10468,7 +11172,7 @@ parsesub: {
10468 c = pgetc(); 11172 c = pgetc();
10469 } 11173 }
10470 else 11174 else
10471badsub: synerror("Bad substitution"); 11175badsub: synerror("Bad substitution");
10472 11176
10473 STPUTC('=', out); 11177 STPUTC('=', out);
10474 flags = 0; 11178 flags = 0;
@@ -10553,17 +11257,17 @@ parsebackq: {
10553 savehandler = handler; 11257 savehandler = handler;
10554 handler = &jmploc; 11258 handler = &jmploc;
10555 INTON; 11259 INTON;
10556 if (oldstyle) { 11260 if (oldstyle) {
10557 /* We must read until the closing backquote, giving special 11261 /* We must read until the closing backquote, giving special
10558 treatment to some slashes, and then push the string and 11262 treatment to some slashes, and then push the string and
10559 reread it as input, interpreting it normally. */ 11263 reread it as input, interpreting it normally. */
10560 char *pout; 11264 char *pout;
10561 int pc; 11265 int pc;
10562 int psavelen; 11266 int psavelen;
10563 char *pstr; 11267 char *pstr;
10564 11268
10565 11269
10566 STARTSTACKSTR(pout); 11270 STARTSTACKSTR(pout);
10567 for (;;) { 11271 for (;;) {
10568 if (needprompt) { 11272 if (needprompt) {
10569 setprompt(2); 11273 setprompt(2);
@@ -10574,7 +11278,7 @@ parsebackq: {
10574 goto done; 11278 goto done;
10575 11279
10576 case '\\': 11280 case '\\':
10577 if ((pc = pgetc()) == '\n') { 11281 if ((pc = pgetc()) == '\n') {
10578 plinno++; 11282 plinno++;
10579 if (doprompt) 11283 if (doprompt)
10580 setprompt(2); 11284 setprompt(2);
@@ -10588,17 +11292,19 @@ parsebackq: {
10588 */ 11292 */
10589 continue; 11293 continue;
10590 } 11294 }
10591 if (pc != '\\' && pc != '`' && pc != '$' 11295 if (pc != '\\' && pc != '`' && pc != '$'
10592 && (!dblquote || pc != '"')) 11296 && (!dblquote || pc != '"'))
10593 STPUTC('\\', pout); 11297 STPUTC('\\', pout);
10594 if (pc > PEOA) { 11298 if (pc > PEOA) {
10595 break; 11299 break;
10596 } 11300 }
10597 /* fall through */ 11301 /* fall through */
10598 11302
10599 case PEOF: 11303 case PEOF:
11304#ifdef ASH_ALIAS
10600 case PEOA: 11305 case PEOA:
10601 startlinno = plinno; 11306#endif
11307 startlinno = plinno;
10602 synerror("EOF in backquote substitution"); 11308 synerror("EOF in backquote substitution");
10603 11309
10604 case '\n': 11310 case '\n':
@@ -10610,15 +11316,15 @@ parsebackq: {
10610 break; 11316 break;
10611 } 11317 }
10612 STPUTC(pc, pout); 11318 STPUTC(pc, pout);
10613 } 11319 }
10614done: 11320done:
10615 STPUTC('\0', pout); 11321 STPUTC('\0', pout);
10616 psavelen = pout - stackblock(); 11322 psavelen = pout - stackblock();
10617 if (psavelen > 0) { 11323 if (psavelen > 0) {
10618 pstr = grabstackstr(pout); 11324 pstr = grabstackstr(pout);
10619 setinputstring(pstr); 11325 setinputstring(pstr);
10620 } 11326 }
10621 } 11327 }
10622 nlpp = &bqlist; 11328 nlpp = &bqlist;
10623 while (*nlpp) 11329 while (*nlpp)
10624 nlpp = &(*nlpp)->next; 11330 nlpp = &(*nlpp)->next;
@@ -10641,12 +11347,12 @@ done:
10641 } 11347 }
10642 11348
10643 (*nlpp)->n = n; 11349 (*nlpp)->n = n;
10644 if (oldstyle) { 11350 if (oldstyle) {
10645 /* 11351 /*
10646 * Start reading from old file again, ignoring any pushed back 11352 * Start reading from old file again, ignoring any pushed back
10647 * tokens left from the backquote parsing 11353 * tokens left from the backquote parsing
10648 */ 11354 */
10649 popfile(); 11355 popfile();
10650 tokpushback = 0; 11356 tokpushback = 0;
10651 } 11357 }
10652 while (stackblocksize() <= savelen) 11358 while (stackblocksize() <= savelen)
@@ -10698,16 +11404,6 @@ parsearith: {
10698} /* end of readtoken */ 11404} /* end of readtoken */
10699 11405
10700 11406
10701
10702#ifdef mkinit
10703INCLUDE "parser.h"
10704RESET {
10705 tokpushback = 0;
10706 checkkwd = 0;
10707 checkalias = 0;
10708}
10709#endif
10710
10711/* 11407/*
10712 * Returns true if the text contains nothing to expand (no dollar signs 11408 * Returns true if the text contains nothing to expand (no dollar signs
10713 * or backquotes). 11409 * or backquotes).
@@ -10739,9 +11435,9 @@ noexpand(text)
10739 */ 11435 */
10740 11436
10741static int 11437static int
10742goodname(char *name) 11438goodname(const char *name)
10743 { 11439{
10744 char *p; 11440 const char *p;
10745 11441
10746 p = name; 11442 p = name;
10747 if (! is_name(*p)) 11443 if (! is_name(*p))
@@ -10778,9 +11474,8 @@ synexpect(token)
10778 11474
10779 11475
10780static void 11476static void
10781synerror(msg) 11477synerror(const char *msg)
10782 const char *msg; 11478{
10783 {
10784 if (commandname) 11479 if (commandname)
10785 outfmt(&errout, "%s: %d: ", commandname, startlinno); 11480 outfmt(&errout, "%s: %d: ", commandname, startlinno);
10786 outfmt(&errout, "Syntax error: %s\n", msg); 11481 outfmt(&errout, "Syntax error: %s\n", msg);
@@ -10788,12 +11483,6 @@ synerror(msg)
10788 /* NOTREACHED */ 11483 /* NOTREACHED */
10789} 11484}
10790 11485
10791static void
10792setprompt(int which)
10793{
10794 whichprompt = which;
10795 putprompt(getprompt(NULL));
10796}
10797 11486
10798/* 11487/*
10799 * called by editline -- any expansions to the prompt 11488 * called by editline -- any expansions to the prompt
@@ -10801,7 +11490,7 @@ setprompt(int which)
10801 */ 11490 */
10802static const char * 11491static const char *
10803getprompt(void *unused) 11492getprompt(void *unused)
10804 { 11493{
10805 switch (whichprompt) { 11494 switch (whichprompt) {
10806 case 0: 11495 case 0:
10807 return ""; 11496 return "";
@@ -10814,56 +11503,26 @@ getprompt(void *unused)
10814 } 11503 }
10815} 11504}
10816 11505
10817static int 11506static void
10818isassignment(const char *word) { 11507setprompt(int which)
10819 if (!is_name(*word)) { 11508{
10820 return 0; 11509 whichprompt = which;
10821 } 11510 putprompt(getprompt(NULL));
10822 do {
10823 word++;
10824 } while (is_in_name(*word));
10825 return *word == '=';
10826} 11511}
10827 11512
10828static const char *const *
10829findkwd(const char *s) {
10830 return findstring(
10831 s, parsekwd, sizeof(parsekwd) / sizeof(const char *)
10832 );
10833}
10834/* $NetBSD: redir.c,v 1.22 2000/05/22 10:18:47 elric Exp $ */
10835 11513
10836/* 11514/*
10837 * Code for dealing with input/output redirection. 11515 * Code for dealing with input/output redirection.
10838 */ 11516 */
10839 11517
10840#define EMPTY -2 /* marks an unused slot in redirtab */ 11518#define EMPTY -2 /* marks an unused slot in redirtab */
10841#ifndef PIPE_BUF 11519#ifndef PIPE_BUF
10842# define PIPESIZE 4096 /* amount of buffering in a pipe */ 11520# define PIPESIZE 4096 /* amount of buffering in a pipe */
10843#else 11521#else
10844# define PIPESIZE PIPE_BUF 11522# define PIPESIZE PIPE_BUF
10845#endif 11523#endif
10846 11524
10847 11525
10848struct redirtab *redirlist;
10849
10850/*
10851 * We keep track of whether or not fd0 has been redirected. This is for
10852 * background commands, where we want to redirect fd0 to /dev/null only
10853 * if it hasn't already been redirected.
10854*/
10855static int fd0_redirected = 0;
10856
10857/*
10858 * We also keep track of where fileno2 goes.
10859 */
10860static int fileno2 = 2;
10861
10862static int openredirect __P((union node *));
10863static void dupredirect __P((union node *, int, char[10 ]));
10864static int openhere __P((union node *));
10865static int noclobberopen __P((const char *));
10866
10867 11526
10868/* 11527/*
10869 * Process a list of redirection commands. If the REDIR_PUSH flag is set, 11528 * Process a list of redirection commands. If the REDIR_PUSH flag is set,
@@ -10884,7 +11543,7 @@ redirect(redir, flags)
10884 int fd; 11543 int fd;
10885 int newfd; 11544 int newfd;
10886 int try; 11545 int try;
10887 char memory[10]; /* file descriptors to write to memory */ 11546 char memory[10]; /* file descriptors to write to memory */
10888 11547
10889 for (i = 10 ; --i >= 0 ; ) 11548 for (i = 10 ; --i >= 0 ; )
10890 memory[i] = 0; 11549 memory[i] = 0;
@@ -10923,7 +11582,7 @@ redirect(redir, flags)
10923 close(newfd); 11582 close(newfd);
10924 } 11583 }
10925 INTON; 11584 INTON;
10926 error("%d: %s", fd, strerror(errno)); 11585 error("%d: %m", fd);
10927 /* NOTREACHED */ 11586 /* NOTREACHED */
10928 } 11587 }
10929 } 11588 }
@@ -10939,8 +11598,8 @@ redirect(redir, flags)
10939 } else if (fd != newfd) { 11598 } else if (fd != newfd) {
10940 close(fd); 11599 close(fd);
10941 } 11600 }
10942 if (fd == 0) 11601 if (fd == 0)
10943 fd0_redirected++; 11602 fd0_redirected++;
10944 if (!try) 11603 if (!try)
10945 dupredirect(n, newfd, memory); 11604 dupredirect(n, newfd, memory);
10946 INTON; 11605 INTON;
@@ -11024,16 +11683,13 @@ eopen:
11024 11683
11025 11684
11026static void 11685static void
11027dupredirect(redir, f, memory) 11686dupredirect(union node *redir, int f, char memory[10])
11028 union node *redir; 11687{
11029 int f;
11030 char memory[10];
11031 {
11032 int fd = redir->nfile.fd; 11688 int fd = redir->nfile.fd;
11033 11689
11034 memory[fd] = 0; 11690 memory[fd] = 0;
11035 if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) { 11691 if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
11036 if (redir->ndup.dupfd >= 0) { /* if not ">&-" */ 11692 if (redir->ndup.dupfd >= 0) { /* if not ">&-" */
11037 if (memory[redir->ndup.dupfd]) 11693 if (memory[redir->ndup.dupfd])
11038 memory[fd] = 1; 11694 memory[fd] = 1;
11039 else 11695 else
@@ -11093,21 +11749,21 @@ out:
11093} 11749}
11094 11750
11095 11751
11096
11097/* 11752/*
11098 * Undo the effects of the last redirection. 11753 * Undo the effects of the last redirection.
11099 */ 11754 */
11100 11755
11101static void 11756static void
11102popredir() { 11757popredir(void)
11758{
11103 struct redirtab *rp = redirlist; 11759 struct redirtab *rp = redirlist;
11104 int i; 11760 int i;
11105 11761
11106 INTOFF; 11762 INTOFF;
11107 for (i = 0 ; i < 10 ; i++) { 11763 for (i = 0 ; i < 10 ; i++) {
11108 if (rp->renamed[i] != EMPTY) { 11764 if (rp->renamed[i] != EMPTY) {
11109 if (i == 0) 11765 if (i == 0)
11110 fd0_redirected--; 11766 fd0_redirected--;
11111 close(i); 11767 close(i);
11112 if (rp->renamed[i] >= 0) { 11768 if (rp->renamed[i] >= 0) {
11113 dup_as_newfd(rp->renamed[i], i); 11769 dup_as_newfd(rp->renamed[i], i);
@@ -11124,36 +11780,11 @@ popredir() {
11124} 11780}
11125 11781
11126/* 11782/*
11127 * Undo all redirections. Called on error or interrupt.
11128 */
11129
11130#ifdef mkinit
11131
11132INCLUDE "redir.h"
11133
11134RESET {
11135 while (redirlist)
11136 popredir();
11137}
11138
11139SHELLPROC {
11140 clearredir();
11141}
11142
11143#endif
11144
11145/* Return true if fd 0 has already been redirected at least once. */
11146static int
11147fd0_redirected_p () {
11148 return fd0_redirected != 0;
11149}
11150
11151/*
11152 * Discard all saved file descriptors. 11783 * Discard all saved file descriptors.
11153 */ 11784 */
11154 11785
11155static void 11786static void
11156clearredir() { 11787clearredir(void) {
11157 struct redirtab *rp; 11788 struct redirtab *rp;
11158 int i; 11789 int i;
11159 11790
@@ -11175,7 +11806,6 @@ clearredir() {
11175} 11806}
11176 11807
11177 11808
11178
11179/* 11809/*
11180 * Copy a file descriptor to be >= to. Returns -1 11810 * Copy a file descriptor to be >= to. Returns -1
11181 * if the source file descriptor is closed, EMPTY if there are no unused 11811 * if the source file descriptor is closed, EMPTY if there are no unused
@@ -11194,7 +11824,7 @@ dup_as_newfd(from, to)
11194 if (errno == EMFILE) 11824 if (errno == EMFILE)
11195 return EMPTY; 11825 return EMPTY;
11196 else 11826 else
11197 error("%d: %s", from, strerror(errno)); 11827 error("%d: %m", from);
11198 } 11828 }
11199 return newfd; 11829 return newfd;
11200} 11830}
@@ -11204,8 +11834,7 @@ dup_as_newfd(from, to)
11204 * The code was copied from bash. 11834 * The code was copied from bash.
11205 */ 11835 */
11206static int 11836static int
11207noclobberopen(fname) 11837noclobberopen(const char *fname)
11208 const char *fname;
11209{ 11838{
11210 int r, fd; 11839 int r, fd;
11211 struct stat finfo, finfo2; 11840 struct stat finfo, finfo2;
@@ -11250,43 +11879,41 @@ noclobberopen(fname)
11250 */ 11879 */
11251 if (fstat(fd, &finfo2) == 0 && !S_ISREG(finfo2.st_mode) && 11880 if (fstat(fd, &finfo2) == 0 && !S_ISREG(finfo2.st_mode) &&
11252 finfo.st_dev == finfo2.st_dev && finfo.st_ino == finfo2.st_ino) 11881 finfo.st_dev == finfo2.st_dev && finfo.st_ino == finfo2.st_ino)
11253 return fd; 11882 return fd;
11254 11883
11255 /* The file has been replaced. badness. */ 11884 /* The file has been replaced. badness. */
11256 close(fd); 11885 close(fd);
11257 errno = EEXIST; 11886 errno = EEXIST;
11258 return -1; 11887 return -1;
11259} 11888}
11260/* $NetBSD: setmode.c,v 1.28 2000/01/25 15:43:43 enami Exp $ */ 11889/*#ifdef __weak_alias
11261
11262#ifdef __weak_alias
11263__weak_alias(getmode,_getmode) 11890__weak_alias(getmode,_getmode)
11264__weak_alias(setmode,_setmode) 11891__weak_alias(setmode,_setmode)
11265#endif 11892#endif*/
11266 11893
11267#ifdef __GLIBC__ 11894#ifdef __GLIBC__
11268#define S_ISTXT __S_ISVTX 11895#define S_ISTXT __S_ISVTX
11269#endif 11896#endif
11270 11897
11271#define SET_LEN 6 /* initial # of bitcmd struct to malloc */ 11898#define SET_LEN 6 /* initial # of bitcmd struct to malloc */
11272#define SET_LEN_INCR 4 /* # of bitcmd structs to add as needed */ 11899#define SET_LEN_INCR 4 /* # of bitcmd structs to add as needed */
11273 11900
11274typedef struct bitcmd { 11901typedef struct bitcmd {
11275 char cmd; 11902 char cmd;
11276 char cmd2; 11903 char cmd2;
11277 mode_t bits; 11904 mode_t bits;
11278} BITCMD; 11905} BITCMD;
11279 11906
11280#define CMD2_CLR 0x01 11907#define CMD2_CLR 0x01
11281#define CMD2_SET 0x02 11908#define CMD2_SET 0x02
11282#define CMD2_GBITS 0x04 11909#define CMD2_GBITS 0x04
11283#define CMD2_OBITS 0x08 11910#define CMD2_OBITS 0x08
11284#define CMD2_UBITS 0x10 11911#define CMD2_UBITS 0x10
11285 11912
11286static BITCMD *addcmd __P((BITCMD *, int, int, int, u_int)); 11913static BITCMD *addcmd (BITCMD *, int, int, int, u_int);
11287static void compress_mode __P((BITCMD *)); 11914static void compress_mode (BITCMD *);
11288#ifdef SETMODE_DEBUG 11915#ifdef SETMODE_DEBUG
11289static void dumpmode __P((BITCMD *)); 11916static void dumpmode (BITCMD *);
11290#endif 11917#endif
11291 11918
11292/* 11919/*
@@ -11295,7 +11922,7 @@ static void dumpmode __P((BITCMD *));
11295 * Note that there is no '=' command; a strict assignment is just a '-' (clear 11922 * Note that there is no '=' command; a strict assignment is just a '-' (clear
11296 * bits) followed by a '+' (set bits). 11923 * bits) followed by a '+' (set bits).
11297 */ 11924 */
11298mode_t 11925static mode_t
11299getmode(bbox, omode) 11926getmode(bbox, omode)
11300 const void *bbox; 11927 const void *bbox;
11301 mode_t omode; 11928 mode_t omode;
@@ -11325,7 +11952,7 @@ getmode(bbox, omode)
11325 11952
11326 case 'o': 11953 case 'o':
11327 value = newmode & S_IRWXO; 11954 value = newmode & S_IRWXO;
11328common: if (set->cmd2 & CMD2_CLR) { 11955common: if (set->cmd2 & CMD2_CLR) {
11329 clrval = 11956 clrval =
11330 (set->cmd2 & CMD2_SET) ? S_IRWXO : value; 11957 (set->cmd2 & CMD2_SET) ? S_IRWXO : value;
11331 if (set->cmd2 & CMD2_UBITS) 11958 if (set->cmd2 & CMD2_UBITS)
@@ -11367,23 +11994,23 @@ common: if (set->cmd2 & CMD2_CLR) {
11367 } 11994 }
11368} 11995}
11369 11996
11370#define ADDCMD(a, b, c, d) do { \ 11997#define ADDCMD(a, b, c, d) do { \
11371 if (set >= endset) { \ 11998 if (set >= endset) { \
11372 BITCMD *newset; \ 11999 BITCMD *newset; \
11373 setlen += SET_LEN_INCR; \ 12000 setlen += SET_LEN_INCR; \
11374 newset = realloc(saveset, sizeof(BITCMD) * setlen); \ 12001 newset = realloc(saveset, sizeof(BITCMD) * setlen); \
11375 if (newset == NULL) { \ 12002 if (newset == NULL) { \
11376 free(saveset); \ 12003 free(saveset); \
11377 return (NULL); \ 12004 return (NULL); \
11378 } \ 12005 } \
11379 set = newset + (set - saveset); \ 12006 set = newset + (set - saveset); \
11380 saveset = newset; \ 12007 saveset = newset; \
11381 endset = newset + (setlen - 2); \ 12008 endset = newset + (setlen - 2); \
11382 } \ 12009 } \
11383 set = addcmd(set, (a), (b), (c), (d)); \ 12010 set = addcmd(set, (a), (b), (c), (d)); \
11384} while (/*CONSTCOND*/0) 12011} while (/*CONSTCOND*/0)
11385 12012
11386#define STANDARD_BITS (S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO) 12013#define STANDARD_BITS (S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO)
11387 12014
11388static void * 12015static void *
11389setmode(p) 12016setmode(p)
@@ -11394,7 +12021,7 @@ setmode(p)
11394 BITCMD *set, *saveset, *endset; 12021 BITCMD *set, *saveset, *endset;
11395 sigset_t mysigset, sigoset; 12022 sigset_t mysigset, sigoset;
11396 mode_t mask; 12023 mode_t mask;
11397 int equalopdone = 0; /* pacify gcc */ 12024 int equalopdone = 0; /* pacify gcc */
11398 int permXbits, setlen; 12025 int permXbits, setlen;
11399 12026
11400 if (!*p) 12027 if (!*p)
@@ -11413,7 +12040,7 @@ setmode(p)
11413 (void)sigprocmask(SIG_SETMASK, &sigoset, NULL); 12040 (void)sigprocmask(SIG_SETMASK, &sigoset, NULL);
11414 12041
11415 setlen = SET_LEN + 2; 12042 setlen = SET_LEN + 2;
11416 12043
11417 if ((set = malloc((u_int)(sizeof(BITCMD) * setlen))) == NULL) 12044 if ((set = malloc((u_int)(sizeof(BITCMD) * setlen))) == NULL)
11418 return (NULL); 12045 return (NULL);
11419 saveset = set; 12046 saveset = set;
@@ -11459,7 +12086,7 @@ setmode(p)
11459 } 12086 }
11460 } 12087 }
11461 12088
11462getop: if ((op = *p++) != '+' && op != '-' && op != '=') { 12089getop: if ((op = *p++) != '+' && op != '-' && op != '=') {
11463 free(saveset); 12090 free(saveset);
11464 return (NULL); 12091 return (NULL);
11465 } 12092 }
@@ -11474,16 +12101,16 @@ getop: if ((op = *p++) != '+' && op != '-' && op != '=') {
11474 break; 12101 break;
11475 case 's': 12102 case 's':
11476 /* 12103 /*
11477 * If specific bits where requested and 12104 * If specific bits where requested and
11478 * only "other" bits ignore set-id. 12105 * only "other" bits ignore set-id.
11479 */ 12106 */
11480 if (who == 0 || (who & ~S_IRWXO)) 12107 if (who == 0 || (who & ~S_IRWXO))
11481 perm |= S_ISUID|S_ISGID; 12108 perm |= S_ISUID|S_ISGID;
11482 break; 12109 break;
11483 case 't': 12110 case 't':
11484 /* 12111 /*
11485 * If specific bits where requested and 12112 * If specific bits where requested and
11486 * only "other" bits ignore set-id. 12113 * only "other" bits ignore set-id.
11487 */ 12114 */
11488 if (who == 0 || (who & ~S_IRWXO)) { 12115 if (who == 0 || (who & ~S_IRWXO)) {
11489 who |= S_ISTXT; 12116 who |= S_ISTXT;
@@ -11539,7 +12166,7 @@ getop: if ((op = *p++) != '+' && op != '-' && op != '=') {
11539 } 12166 }
11540 } 12167 }
11541 12168
11542apply: if (!*p) 12169apply: if (!*p)
11543 break; 12170 break;
11544 if (*p != ',') 12171 if (*p != ',')
11545 goto getop; 12172 goto getop;
@@ -11596,7 +12223,7 @@ addcmd(set, op, who, oparg, mask)
11596 set->cmd2 = CMD2_UBITS | CMD2_GBITS | CMD2_OBITS; 12223 set->cmd2 = CMD2_UBITS | CMD2_GBITS | CMD2_OBITS;
11597 set->bits = mask; 12224 set->bits = mask;
11598 } 12225 }
11599 12226
11600 if (oparg == '+') 12227 if (oparg == '+')
11601 set->cmd2 |= CMD2_SET; 12228 set->cmd2 |= CMD2_SET;
11602 else if (oparg == '-') 12229 else if (oparg == '-')
@@ -11630,7 +12257,7 @@ dumpmode(set)
11630/* 12257/*
11631 * Given an array of bitcmd structures, compress by compacting consecutive 12258 * Given an array of bitcmd structures, compress by compacting consecutive
11632 * '+', '-' and 'X' commands into at most 3 commands, one of each. The 'u', 12259 * '+', '-' and 'X' commands into at most 3 commands, one of each. The 'u',
11633 * 'g' and 'o' commands continue to be separate. They could probably be 12260 * 'g' and 'o' commands continue to be separate. They could probably be
11634 * compacted, but it's not worth the effort. 12261 * compacted, but it's not worth the effort.
11635 */ 12262 */
11636static void 12263static void
@@ -11684,15 +12311,12 @@ compress_mode(set)
11684 } 12311 }
11685 } 12312 }
11686} 12313}
11687/* $NetBSD: show.c,v 1.18 1999/10/08 21:10:44 pk Exp $ */
11688
11689
11690#ifdef DEBUG 12314#ifdef DEBUG
11691static void shtree __P((union node *, int, char *, FILE*)); 12315static void shtree (union node *, int, char *, FILE*);
11692static void shcmd __P((union node *, FILE *)); 12316static void shcmd (union node *, FILE *);
11693static void sharg __P((union node *, FILE *)); 12317static void sharg (union node *, FILE *);
11694static void indent __P((int, char *, FILE *)); 12318static void indent (int, char *, FILE *);
11695static void trstring __P((char *)); 12319static void trstring (char *);
11696 12320
11697 12321
11698static void 12322static void
@@ -11780,14 +12404,14 @@ shcmd(cmd, fp)
11780 if (! first) 12404 if (! first)
11781 putchar(' '); 12405 putchar(' ');
11782 switch (np->nfile.type) { 12406 switch (np->nfile.type) {
11783 case NTO: s = ">"; dftfd = 1; break; 12407 case NTO: s = ">"; dftfd = 1; break;
11784 case NAPPEND: s = ">>"; dftfd = 1; break; 12408 case NAPPEND: s = ">>"; dftfd = 1; break;
11785 case NTOFD: s = ">&"; dftfd = 1; break; 12409 case NTOFD: s = ">&"; dftfd = 1; break;
11786 case NTOOV: s = ">|"; dftfd = 1; break; 12410 case NTOOV: s = ">|"; dftfd = 1; break;
11787 case NFROM: s = "<"; dftfd = 0; break; 12411 case NFROM: s = "<"; dftfd = 0; break;
11788 case NFROMFD: s = "<&"; dftfd = 0; break; 12412 case NFROMFD: s = "<&"; dftfd = 0; break;
11789 case NFROMTO: s = "<>"; dftfd = 0; break; 12413 case NFROMTO: s = "<>"; dftfd = 0; break;
11790 default: s = "*error*"; dftfd = 0; break; 12414 default: s = "*error*"; dftfd = 0; break;
11791 } 12415 }
11792 if (np->nfile.fd != dftfd) 12416 if (np->nfile.fd != dftfd)
11793 fprintf(fp, "%d", np->nfile.fd); 12417 fprintf(fp, "%d", np->nfile.fd);
@@ -11988,7 +12612,7 @@ trstring(s)
11988 case CTLVAR+CTLQUOTE: c = 'V'; goto backslash; 12612 case CTLVAR+CTLQUOTE: c = 'V'; goto backslash;
11989 case CTLBACKQ: c = 'q'; goto backslash; 12613 case CTLBACKQ: c = 'q'; goto backslash;
11990 case CTLBACKQ+CTLQUOTE: c = 'Q'; goto backslash; 12614 case CTLBACKQ+CTLQUOTE: c = 'Q'; goto backslash;
11991backslash: putc('\\', tracefile); 12615backslash: putc('\\', tracefile);
11992 putc(c, tracefile); 12616 putc(c, tracefile);
11993 break; 12617 break;
11994 default: 12618 default:
@@ -12042,11 +12666,11 @@ opentrace() {
12042 else 12666 else
12043 p = "/tmp"; 12667 p = "/tmp";
12044 } 12668 }
12045 scopy(p, s); 12669 strcpy(s, p);
12046 strcat(s, "/trace"); 12670 strcat(s, "/trace");
12047 } 12671 }
12048#else 12672#else
12049 scopy("./trace", s); 12673 strcpy(s, "./trace");
12050#endif /* not_this_way */ 12674#endif /* not_this_way */
12051 if ((tracefile = fopen(s, "a")) == NULL) { 12675 if ((tracefile = fopen(s, "a")) == NULL) {
12052 fprintf(stderr, "Can't open %s\n", s); 12676 fprintf(stderr, "Can't open %s\n", s);
@@ -12063,356 +12687,6 @@ opentrace() {
12063 12687
12064 12688
12065/* 12689/*
12066 * This file was generated by the mksyntax program.
12067 */
12068
12069/* syntax table used when not in quotes */
12070static const char basesyntax[257] = {
12071 CEOF, CSPCL, CWORD, CCTL,
12072 CCTL, CCTL, CCTL, CCTL,
12073 CCTL, CCTL, CCTL, CWORD,
12074 CWORD, CWORD, CWORD, CWORD,
12075 CWORD, CWORD, CWORD, CWORD,
12076 CWORD, CWORD, CWORD, CWORD,
12077 CWORD, CWORD, CWORD, CWORD,
12078 CWORD, CWORD, CWORD, CWORD,
12079 CWORD, CWORD, CWORD, CWORD,
12080 CWORD, CWORD, CWORD, CWORD,
12081 CWORD, CWORD, CWORD, CWORD,
12082 CWORD, CWORD, CWORD, CWORD,
12083 CWORD, CWORD, CWORD, CWORD,
12084 CWORD, CWORD, CWORD, CWORD,
12085 CWORD, CWORD, CWORD, CWORD,
12086 CWORD, CWORD, CWORD, CWORD,
12087 CWORD, CWORD, CWORD, CWORD,
12088 CWORD, CWORD, CWORD, CWORD,
12089 CWORD, CWORD, CWORD, CWORD,
12090 CWORD, CWORD, CWORD, CWORD,
12091 CWORD, CWORD, CWORD, CWORD,
12092 CWORD, CWORD, CWORD, CWORD,
12093 CWORD, CWORD, CWORD, CWORD,
12094 CWORD, CWORD, CWORD, CWORD,
12095 CWORD, CWORD, CWORD, CWORD,
12096 CWORD, CWORD, CWORD, CWORD,
12097 CWORD, CWORD, CWORD, CWORD,
12098 CWORD, CWORD, CWORD, CWORD,
12099 CWORD, CWORD, CWORD, CWORD,
12100 CWORD, CWORD, CWORD, CWORD,
12101 CWORD, CWORD, CWORD, CWORD,
12102 CWORD, CWORD, CWORD, CWORD,
12103 CWORD, CWORD, CWORD, CWORD,
12104 CWORD, CWORD, CWORD, CWORD,
12105 CWORD, CWORD, CWORD, CSPCL,
12106 CNL, CWORD, CWORD, CWORD,
12107 CWORD, CWORD, CWORD, CWORD,
12108 CWORD, CWORD, CWORD, CWORD,
12109 CWORD, CWORD, CWORD, CWORD,
12110 CWORD, CWORD, CWORD, CWORD,
12111 CWORD, CWORD, CSPCL, CWORD,
12112 CDQUOTE, CWORD, CVAR, CWORD,
12113 CSPCL, CSQUOTE, CSPCL, CSPCL,
12114 CWORD, CWORD, CWORD, CWORD,
12115 CWORD, CWORD, CWORD, CWORD,
12116 CWORD, CWORD, CWORD, CWORD,
12117 CWORD, CWORD, CWORD, CWORD,
12118 CWORD, CSPCL, CSPCL, CWORD,
12119 CSPCL, CWORD, CWORD, CWORD,
12120 CWORD, CWORD, CWORD, CWORD,
12121 CWORD, CWORD, CWORD, CWORD,
12122 CWORD, CWORD, CWORD, CWORD,
12123 CWORD, CWORD, CWORD, CWORD,
12124 CWORD, CWORD, CWORD, CWORD,
12125 CWORD, CWORD, CWORD, CWORD,
12126 CWORD, CWORD, CBACK, CWORD,
12127 CWORD, CWORD, CBQUOTE, CWORD,
12128 CWORD, CWORD, CWORD, CWORD,
12129 CWORD, CWORD, CWORD, CWORD,
12130 CWORD, CWORD, CWORD, CWORD,
12131 CWORD, CWORD, CWORD, CWORD,
12132 CWORD, CWORD, CWORD, CWORD,
12133 CWORD, CWORD, CWORD, CWORD,
12134 CWORD, CWORD, CSPCL, CENDVAR,
12135 CWORD
12136};
12137
12138/* syntax table used when in double quotes */
12139static const char dqsyntax[257] = {
12140 CEOF, CIGN, CWORD, CCTL,
12141 CCTL, CCTL, CCTL, CCTL,
12142 CCTL, CCTL, CCTL, CWORD,
12143 CWORD, CWORD, CWORD, CWORD,
12144 CWORD, CWORD, CWORD, CWORD,
12145 CWORD, CWORD, CWORD, CWORD,
12146 CWORD, CWORD, CWORD, CWORD,
12147 CWORD, CWORD, CWORD, CWORD,
12148 CWORD, CWORD, CWORD, CWORD,
12149 CWORD, CWORD, CWORD, CWORD,
12150 CWORD, CWORD, CWORD, CWORD,
12151 CWORD, CWORD, CWORD, CWORD,
12152 CWORD, CWORD, CWORD, CWORD,
12153 CWORD, CWORD, CWORD, CWORD,
12154 CWORD, CWORD, CWORD, CWORD,
12155 CWORD, CWORD, CWORD, CWORD,
12156 CWORD, CWORD, CWORD, CWORD,
12157 CWORD, CWORD, CWORD, CWORD,
12158 CWORD, CWORD, CWORD, CWORD,
12159 CWORD, CWORD, CWORD, CWORD,
12160 CWORD, CWORD, CWORD, CWORD,
12161 CWORD, CWORD, CWORD, CWORD,
12162 CWORD, CWORD, CWORD, CWORD,
12163 CWORD, CWORD, CWORD, CWORD,
12164 CWORD, CWORD, CWORD, CWORD,
12165 CWORD, CWORD, CWORD, CWORD,
12166 CWORD, CWORD, CWORD, CWORD,
12167 CWORD, CWORD, CWORD, CWORD,
12168 CWORD, CWORD, CWORD, CWORD,
12169 CWORD, CWORD, CWORD, CWORD,
12170 CWORD, CWORD, CWORD, CWORD,
12171 CWORD, CWORD, CWORD, CWORD,
12172 CWORD, CWORD, CWORD, CWORD,
12173 CWORD, CWORD, CWORD, CWORD,
12174 CWORD, CWORD, CWORD, CWORD,
12175 CNL, CWORD, CWORD, CWORD,
12176 CWORD, CWORD, CWORD, CWORD,
12177 CWORD, CWORD, CWORD, CWORD,
12178 CWORD, CWORD, CWORD, CWORD,
12179 CWORD, CWORD, CWORD, CWORD,
12180 CWORD, CWORD, CWORD, CCTL,
12181 CENDQUOTE,CWORD, CVAR, CWORD,
12182 CWORD, CWORD, CWORD, CWORD,
12183 CCTL, CWORD, CWORD, CCTL,
12184 CWORD, CCTL, CWORD, CWORD,
12185 CWORD, CWORD, CWORD, CWORD,
12186 CWORD, CWORD, CWORD, CWORD,
12187 CCTL, CWORD, CWORD, CCTL,
12188 CWORD, CCTL, CWORD, CWORD,
12189 CWORD, CWORD, CWORD, CWORD,
12190 CWORD, CWORD, CWORD, CWORD,
12191 CWORD, CWORD, CWORD, CWORD,
12192 CWORD, CWORD, CWORD, CWORD,
12193 CWORD, CWORD, CWORD, CWORD,
12194 CWORD, CWORD, CWORD, CWORD,
12195 CWORD, CCTL, CBACK, CCTL,
12196 CWORD, CWORD, CBQUOTE, CWORD,
12197 CWORD, CWORD, CWORD, CWORD,
12198 CWORD, CWORD, CWORD, CWORD,
12199 CWORD, CWORD, CWORD, CWORD,
12200 CWORD, CWORD, CWORD, CWORD,
12201 CWORD, CWORD, CWORD, CWORD,
12202 CWORD, CWORD, CWORD, CWORD,
12203 CWORD, CWORD, CWORD, CENDVAR,
12204 CCTL
12205};
12206
12207/* syntax table used when in single quotes */
12208static const char sqsyntax[257] = {
12209 CEOF, CIGN, CWORD, CCTL,
12210 CCTL, CCTL, CCTL, CCTL,
12211 CCTL, CCTL, CCTL, CWORD,
12212 CWORD, CWORD, CWORD, CWORD,
12213 CWORD, CWORD, CWORD, CWORD,
12214 CWORD, CWORD, CWORD, CWORD,
12215 CWORD, CWORD, CWORD, CWORD,
12216 CWORD, CWORD, CWORD, CWORD,
12217 CWORD, CWORD, CWORD, CWORD,
12218 CWORD, CWORD, CWORD, CWORD,
12219 CWORD, CWORD, CWORD, CWORD,
12220 CWORD, CWORD, CWORD, CWORD,
12221 CWORD, CWORD, CWORD, CWORD,
12222 CWORD, CWORD, CWORD, CWORD,
12223 CWORD, CWORD, CWORD, CWORD,
12224 CWORD, CWORD, CWORD, CWORD,
12225 CWORD, CWORD, CWORD, CWORD,
12226 CWORD, CWORD, CWORD, CWORD,
12227 CWORD, CWORD, CWORD, CWORD,
12228 CWORD, CWORD, CWORD, CWORD,
12229 CWORD, CWORD, CWORD, CWORD,
12230 CWORD, CWORD, CWORD, CWORD,
12231 CWORD, CWORD, CWORD, CWORD,
12232 CWORD, CWORD, CWORD, CWORD,
12233 CWORD, CWORD, CWORD, CWORD,
12234 CWORD, CWORD, CWORD, CWORD,
12235 CWORD, CWORD, CWORD, CWORD,
12236 CWORD, CWORD, CWORD, CWORD,
12237 CWORD, CWORD, CWORD, CWORD,
12238 CWORD, CWORD, CWORD, CWORD,
12239 CWORD, CWORD, CWORD, CWORD,
12240 CWORD, CWORD, CWORD, CWORD,
12241 CWORD, CWORD, CWORD, CWORD,
12242 CWORD, CWORD, CWORD, CWORD,
12243 CWORD, CWORD, CWORD, CWORD,
12244 CNL, CWORD, CWORD, CWORD,
12245 CWORD, CWORD, CWORD, CWORD,
12246 CWORD, CWORD, CWORD, CWORD,
12247 CWORD, CWORD, CWORD, CWORD,
12248 CWORD, CWORD, CWORD, CWORD,
12249 CWORD, CWORD, CWORD, CCTL,
12250 CWORD, CWORD, CWORD, CWORD,
12251 CWORD, CENDQUOTE,CWORD, CWORD,
12252 CCTL, CWORD, CWORD, CCTL,
12253 CWORD, CCTL, CWORD, CWORD,
12254 CWORD, CWORD, CWORD, CWORD,
12255 CWORD, CWORD, CWORD, CWORD,
12256 CCTL, CWORD, CWORD, CCTL,
12257 CWORD, CCTL, CWORD, CWORD,
12258 CWORD, CWORD, CWORD, CWORD,
12259 CWORD, CWORD, CWORD, CWORD,
12260 CWORD, CWORD, CWORD, CWORD,
12261 CWORD, CWORD, CWORD, CWORD,
12262 CWORD, CWORD, CWORD, CWORD,
12263 CWORD, CWORD, CWORD, CWORD,
12264 CWORD, CCTL, CCTL, CCTL,
12265 CWORD, CWORD, CWORD, CWORD,
12266 CWORD, CWORD, CWORD, CWORD,
12267 CWORD, CWORD, CWORD, CWORD,
12268 CWORD, CWORD, CWORD, CWORD,
12269 CWORD, CWORD, CWORD, CWORD,
12270 CWORD, CWORD, CWORD, CWORD,
12271 CWORD, CWORD, CWORD, CWORD,
12272 CWORD, CWORD, CWORD, CWORD,
12273 CCTL
12274};
12275
12276/* syntax table used when in arithmetic */
12277static const char arisyntax[257] = {
12278 CEOF, CIGN, CWORD, CCTL,
12279 CCTL, CCTL, CCTL, CCTL,
12280 CCTL, CCTL, CCTL, CWORD,
12281 CWORD, CWORD, CWORD, CWORD,
12282 CWORD, CWORD, CWORD, CWORD,
12283 CWORD, CWORD, CWORD, CWORD,
12284 CWORD, CWORD, CWORD, CWORD,
12285 CWORD, CWORD, CWORD, CWORD,
12286 CWORD, CWORD, CWORD, CWORD,
12287 CWORD, CWORD, CWORD, CWORD,
12288 CWORD, CWORD, CWORD, CWORD,
12289 CWORD, CWORD, CWORD, CWORD,
12290 CWORD, CWORD, CWORD, CWORD,
12291 CWORD, CWORD, CWORD, CWORD,
12292 CWORD, CWORD, CWORD, CWORD,
12293 CWORD, CWORD, CWORD, CWORD,
12294 CWORD, CWORD, CWORD, CWORD,
12295 CWORD, CWORD, CWORD, CWORD,
12296 CWORD, CWORD, CWORD, CWORD,
12297 CWORD, CWORD, CWORD, CWORD,
12298 CWORD, CWORD, CWORD, CWORD,
12299 CWORD, CWORD, CWORD, CWORD,
12300 CWORD, CWORD, CWORD, CWORD,
12301 CWORD, CWORD, CWORD, CWORD,
12302 CWORD, CWORD, CWORD, CWORD,
12303 CWORD, CWORD, CWORD, CWORD,
12304 CWORD, CWORD, CWORD, CWORD,
12305 CWORD, CWORD, CWORD, CWORD,
12306 CWORD, CWORD, CWORD, CWORD,
12307 CWORD, CWORD, CWORD, CWORD,
12308 CWORD, CWORD, CWORD, CWORD,
12309 CWORD, CWORD, CWORD, CWORD,
12310 CWORD, CWORD, CWORD, CWORD,
12311 CWORD, CWORD, CWORD, CWORD,
12312 CWORD, CWORD, CWORD, CWORD,
12313 CNL, CWORD, CWORD, CWORD,
12314 CWORD, CWORD, CWORD, CWORD,
12315 CWORD, CWORD, CWORD, CWORD,
12316 CWORD, CWORD, CWORD, CWORD,
12317 CWORD, CWORD, CWORD, CWORD,
12318 CWORD, CWORD, CWORD, CWORD,
12319 CDQUOTE, CWORD, CVAR, CWORD,
12320 CWORD, CSQUOTE, CLP, CRP,
12321 CWORD, CWORD, CWORD, CWORD,
12322 CWORD, CWORD, CWORD, CWORD,
12323 CWORD, CWORD, CWORD, CWORD,
12324 CWORD, CWORD, CWORD, CWORD,
12325 CWORD, CWORD, CWORD, CWORD,
12326 CWORD, CWORD, CWORD, CWORD,
12327 CWORD, CWORD, CWORD, CWORD,
12328 CWORD, CWORD, CWORD, CWORD,
12329 CWORD, CWORD, CWORD, CWORD,
12330 CWORD, CWORD, CWORD, CWORD,
12331 CWORD, CWORD, CWORD, CWORD,
12332 CWORD, CWORD, CWORD, CWORD,
12333 CWORD, CWORD, CBACK, CWORD,
12334 CWORD, CWORD, CBQUOTE, CWORD,
12335 CWORD, CWORD, CWORD, CWORD,
12336 CWORD, CWORD, CWORD, CWORD,
12337 CWORD, CWORD, CWORD, CWORD,
12338 CWORD, CWORD, CWORD, CWORD,
12339 CWORD, CWORD, CWORD, CWORD,
12340 CWORD, CWORD, CWORD, CWORD,
12341 CWORD, CWORD, CWORD, CENDVAR,
12342 CWORD
12343};
12344
12345/* character classification table */
12346static const char is_type[257] = {
12347 0, 0, 0, 0,
12348 0, 0, 0, 0,
12349 0, 0, 0, 0,
12350 0, 0, 0, 0,
12351 0, 0, 0, 0,
12352 0, 0, 0, 0,
12353 0, 0, 0, 0,
12354 0, 0, 0, 0,
12355 0, 0, 0, 0,
12356 0, 0, 0, 0,
12357 0, 0, 0, 0,
12358 0, 0, 0, 0,
12359 0, 0, 0, 0,
12360 0, 0, 0, 0,
12361 0, 0, 0, 0,
12362 0, 0, 0, 0,
12363 0, 0, 0, 0,
12364 0, 0, 0, 0,
12365 0, 0, 0, 0,
12366 0, 0, 0, 0,
12367 0, 0, 0, 0,
12368 0, 0, 0, 0,
12369 0, 0, 0, 0,
12370 0, 0, 0, 0,
12371 0, 0, 0, 0,
12372 0, 0, 0, 0,
12373 0, 0, 0, 0,
12374 0, 0, 0, 0,
12375 0, 0, 0, 0,
12376 0, 0, 0, 0,
12377 0, 0, 0, 0,
12378 0, 0, 0, 0,
12379 0, 0, 0, 0,
12380 0, 0, 0, 0,
12381 0, 0, 0, 0,
12382 0, 0, 0, 0,
12383 0, 0, 0, 0,
12384 0, 0, 0, 0,
12385 0, 0, 0, 0,
12386 0, 0, 0, 0,
12387 0, 0, 0, ISSPECL,
12388 0, ISSPECL, ISSPECL, 0,
12389 0, 0, 0, 0,
12390 ISSPECL, 0, 0, ISSPECL,
12391 0, 0, ISDIGIT, ISDIGIT,
12392 ISDIGIT, ISDIGIT, ISDIGIT, ISDIGIT,
12393 ISDIGIT, ISDIGIT, ISDIGIT, ISDIGIT,
12394 0, 0, 0, 0,
12395 0, ISSPECL, ISSPECL, ISUPPER,
12396 ISUPPER, ISUPPER, ISUPPER, ISUPPER,
12397 ISUPPER, ISUPPER, ISUPPER, ISUPPER,
12398 ISUPPER, ISUPPER, ISUPPER, ISUPPER,
12399 ISUPPER, ISUPPER, ISUPPER, ISUPPER,
12400 ISUPPER, ISUPPER, ISUPPER, ISUPPER,
12401 ISUPPER, ISUPPER, ISUPPER, ISUPPER,
12402 ISUPPER, 0, 0, 0,
12403 0, ISUNDER, 0, ISLOWER,
12404 ISLOWER, ISLOWER, ISLOWER, ISLOWER,
12405 ISLOWER, ISLOWER, ISLOWER, ISLOWER,
12406 ISLOWER, ISLOWER, ISLOWER, ISLOWER,
12407 ISLOWER, ISLOWER, ISLOWER, ISLOWER,
12408 ISLOWER, ISLOWER, ISLOWER, ISLOWER,
12409 ISLOWER, ISLOWER, ISLOWER, ISLOWER,
12410 ISLOWER, 0, 0, 0,
12411 0
12412};
12413/* $NetBSD: trap.c,v 1.25 2001/02/04 19:52:07 christos Exp $ */
12414
12415/*
12416 * The trap builtin. 12690 * The trap builtin.
12417 */ 12691 */
12418 12692
@@ -12467,25 +12741,6 @@ trapcmd(argc, argv)
12467 12741
12468 12742
12469 12743
12470/*
12471 * Clear traps on a fork.
12472 */
12473
12474static void
12475clear_traps() {
12476 char **tp;
12477
12478 for (tp = trap ; tp < &trap[NSIG] ; tp++) {
12479 if (*tp && **tp) { /* trap not NULL or SIG_IGN */
12480 INTOFF;
12481 ckfree(*tp);
12482 *tp = NULL;
12483 if (tp != &trap[0])
12484 setsignal(tp - trap);
12485 INTON;
12486 }
12487 }
12488}
12489 12744
12490 12745
12491 12746
@@ -12495,8 +12750,7 @@ clear_traps() {
12495 */ 12750 */
12496 12751
12497static void 12752static void
12498setsignal(signo) 12753setsignal(int signo)
12499 int signo;
12500{ 12754{
12501 int action; 12755 int action;
12502 char *t; 12756 char *t;
@@ -12517,7 +12771,6 @@ setsignal(signo)
12517 case SIGQUIT: 12771 case SIGQUIT:
12518#ifdef DEBUG 12772#ifdef DEBUG
12519 { 12773 {
12520 extern int debug;
12521 12774
12522 if (debug) 12775 if (debug)
12523 break; 12776 break;
@@ -12528,7 +12781,7 @@ setsignal(signo)
12528 if (iflag) 12781 if (iflag)
12529 action = S_IGN; 12782 action = S_IGN;
12530 break; 12783 break;
12531#if JOBS 12784#ifdef JOBS
12532 case SIGTSTP: 12785 case SIGTSTP:
12533 case SIGTTOU: 12786 case SIGTTOU:
12534 if (mflag) 12787 if (mflag)
@@ -12554,11 +12807,11 @@ setsignal(signo)
12554 if (act.sa_handler == SIG_IGN) { 12807 if (act.sa_handler == SIG_IGN) {
12555 if (mflag && (signo == SIGTSTP || 12808 if (mflag && (signo == SIGTSTP ||
12556 signo == SIGTTIN || signo == SIGTTOU)) { 12809 signo == SIGTTIN || signo == SIGTTOU)) {
12557 *t = S_IGN; /* don't hard ignore these */ 12810 *t = S_IGN; /* don't hard ignore these */
12558 } else 12811 } else
12559 *t = S_HARD_IGN; 12812 *t = S_HARD_IGN;
12560 } else { 12813 } else {
12561 *t = S_RESET; /* force to be set */ 12814 *t = S_RESET; /* force to be set */
12562 } 12815 }
12563 } 12816 }
12564 if (*t == S_HARD_IGN || *t == action) 12817 if (*t == S_HARD_IGN || *t == action)
@@ -12594,30 +12847,12 @@ ignoresig(signo)
12594} 12847}
12595 12848
12596 12849
12597#ifdef mkinit
12598INCLUDE <signal.h>
12599INCLUDE "trap.h"
12600
12601SHELLPROC {
12602 char *sm;
12603
12604 clear_traps();
12605 for (sm = sigmode ; sm < sigmode + NSIG - 1; sm++) {
12606 if (*sm == S_IGN)
12607 *sm = S_HARD_IGN;
12608 }
12609}
12610#endif
12611
12612
12613
12614/* 12850/*
12615 * Signal handler. 12851 * Signal handler.
12616 */ 12852 */
12617 12853
12618static void 12854static void
12619onsig(signo) 12855onsig(int signo)
12620 int signo;
12621{ 12856{
12622 if (signo == SIGINT && trap[SIGINT] == NULL) { 12857 if (signo == SIGINT && trap[SIGINT] == NULL) {
12623 onint(); 12858 onint();
@@ -12628,14 +12863,14 @@ onsig(signo)
12628} 12863}
12629 12864
12630 12865
12631
12632/* 12866/*
12633 * Called to execute a trap. Perhaps we should avoid entering new trap 12867 * Called to execute a trap. Perhaps we should avoid entering new trap
12634 * handlers while we are executing a trap handler. 12868 * handlers while we are executing a trap handler.
12635 */ 12869 */
12636 12870
12637static void 12871static void
12638dotrap() { 12872dotrap(void)
12873{
12639 int i; 12874 int i;
12640 int savestatus; 12875 int savestatus;
12641 12876
@@ -12655,37 +12890,12 @@ done:
12655 pendingsigs = 0; 12890 pendingsigs = 0;
12656} 12891}
12657 12892
12658
12659
12660/*
12661 * Controls whether the shell is interactive or not.
12662 */
12663
12664
12665static void
12666setinteractive(on)
12667 int on;
12668{
12669 static int is_interactive;
12670
12671 if (on == is_interactive)
12672 return;
12673 setsignal(SIGINT);
12674 setsignal(SIGQUIT);
12675 setsignal(SIGTERM);
12676 chkmail(1);
12677 is_interactive = on;
12678}
12679
12680
12681
12682/* 12893/*
12683 * Called to exit the shell. 12894 * Called to exit the shell.
12684 */ 12895 */
12685 12896
12686static void 12897static void
12687exitshell(status) 12898exitshell(int status)
12688 int status;
12689{ 12899{
12690 struct jmploc loc1, loc2; 12900 struct jmploc loc1, loc2;
12691 char *p; 12901 char *p;
@@ -12702,9 +12912,9 @@ exitshell(status)
12702 trap[0] = NULL; 12912 trap[0] = NULL;
12703 evalstring(p, 0); 12913 evalstring(p, 0);
12704 } 12914 }
12705l1: handler = &loc2; /* probably unnecessary */ 12915l1: handler = &loc2; /* probably unnecessary */
12706 flushall(); 12916 flushall();
12707#if JOBS 12917#ifdef JOBS
12708 setjobctl(0); 12918 setjobctl(0);
12709#endif 12919#endif
12710l2: _exit(status); 12920l2: _exit(status);
@@ -12715,8 +12925,7 @@ static int decode_signal(const char *string, int minsig)
12715{ 12925{
12716 int signo; 12926 int signo;
12717 12927
12718 if (is_number(string)) { 12928 if (is_number(string, &signo)) {
12719 signo = atoi(string);
12720 if (signo >= NSIG) { 12929 if (signo >= NSIG) {
12721 return -1; 12930 return -1;
12722 } 12931 }
@@ -12739,100 +12948,14 @@ zero:
12739 12948
12740 return -1; 12949 return -1;
12741} 12950}
12742/* $NetBSD: var.c,v 1.27 2001/02/04 19:52:07 christos Exp $ */ 12951static struct var **hashvar (const char *);
12743 12952static void showvars (const char *, int, int);
12744#define VTABSIZE 39 12953static struct var **findvar (struct var **, const char *);
12745
12746
12747struct varinit {
12748 struct var *var;
12749 int flags;
12750 const char *text;
12751 void (*func) __P((const char *));
12752};
12753
12754struct localvar *localvars;
12755
12756#if ATTY
12757struct var vatty;
12758#endif
12759struct var vifs;
12760struct var vmail;
12761struct var vmpath;
12762struct var vpath;
12763struct var vps1;
12764struct var vps2;
12765struct var vvers;
12766struct var voptind;
12767
12768static const char defpathvar[] =
12769 "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin";
12770#ifdef IFS_BROKEN
12771static const char defifsvar[] = "IFS= \t\n";
12772#else
12773static const char defifs[] = " \t\n";
12774#endif
12775
12776static const struct varinit varinit[] = {
12777#if ATTY
12778 { &vatty, VSTRFIXED|VTEXTFIXED|VUNSET, "ATTY=",
12779 NULL },
12780#endif
12781#ifdef IFS_BROKEN
12782 { &vifs, VSTRFIXED|VTEXTFIXED, defifsvar,
12783#else
12784 { &vifs, VSTRFIXED|VTEXTFIXED|VUNSET, "IFS=",
12785#endif
12786 NULL },
12787 { &vmail, VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL=",
12788 NULL },
12789 { &vmpath, VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH=",
12790 NULL },
12791 { &vpath, VSTRFIXED|VTEXTFIXED, defpathvar,
12792 changepath },
12793 /*
12794 * vps1 depends on uid
12795 */
12796 { &vps2, VSTRFIXED|VTEXTFIXED, "PS2=> ",
12797 NULL },
12798 { &voptind, VSTRFIXED|VTEXTFIXED, "OPTIND=1",
12799 getoptsreset },
12800 { NULL, 0, NULL,
12801 NULL }
12802};
12803
12804struct var *vartab[VTABSIZE];
12805
12806static struct var **hashvar __P((const char *));
12807static void showvars __P((const char *, int, int));
12808static struct var **findvar __P((struct var **, const char *));
12809 12954
12810/* 12955/*
12811 * Initialize the varable symbol tables and import the environment 12956 * Initialize the varable symbol tables and import the environment
12812 */ 12957 */
12813 12958
12814#ifdef mkinit
12815INCLUDE <unistd.h>
12816INCLUDE "output.h"
12817INCLUDE "var.h"
12818static char **environ;
12819INIT {
12820 char **envp;
12821 char ppid[32];
12822
12823 initvar();
12824 for (envp = environ ; *envp ; envp++) {
12825 if (strchr(*envp, '=')) {
12826 setvareq(*envp, VEXPORT|VTEXTFIXED);
12827 }
12828 }
12829
12830 fmtstr(ppid, sizeof(ppid), "%d", (int) getppid());
12831 setvar("PPID", ppid, 0);
12832}
12833#endif
12834
12835
12836/* 12959/*
12837 * This routine initializes the builtin variables. It is called when the 12960 * This routine initializes the builtin variables. It is called when the
12838 * shell is initialized and again when a shell procedure is spawned. 12961 * shell is initialized and again when a shell procedure is spawned.
@@ -12899,7 +13022,7 @@ setvar(name, val, flags)
12899 namelen = p - name; 13022 namelen = p - name;
12900 if (isbad) 13023 if (isbad)
12901 error("%.*s: bad variable name", namelen, name); 13024 error("%.*s: bad variable name", namelen, name);
12902 len = namelen + 2; /* 2 is space for '=' and '\0' */ 13025 len = namelen + 2; /* 2 is space for '=' and '\0' */
12903 if (val == NULL) { 13026 if (val == NULL) {
12904 flags |= VUNSET; 13027 flags |= VUNSET;
12905 } else { 13028 } else {
@@ -13065,16 +13188,8 @@ environment() {
13065 * VSTACK set since these are currently allocated on the stack. 13188 * VSTACK set since these are currently allocated on the stack.
13066 */ 13189 */
13067 13190
13068#ifdef mkinit
13069static void shprocvar __P((void));
13070
13071SHELLPROC {
13072 shprocvar();
13073}
13074#endif
13075
13076static void 13191static void
13077shprocvar() { 13192shprocvar(void) {
13078 struct var **vpp; 13193 struct var **vpp;
13079 struct var *vp, **prev; 13194 struct var *vp, **prev;
13080 13195
@@ -13158,6 +13273,8 @@ found:;
13158 * The "local" command. 13273 * The "local" command.
13159 */ 13274 */
13160 13275
13276/* funcnest nonzero if we are currently evaluating a function */
13277
13161static int 13278static int
13162localcmd(argc, argv) 13279localcmd(argc, argv)
13163 int argc; 13280 int argc;
@@ -13165,7 +13282,7 @@ localcmd(argc, argv)
13165{ 13282{
13166 char *name; 13283 char *name;
13167 13284
13168 if (! in_function()) 13285 if (! funcnest)
13169 error("Not in a function"); 13286 error("Not in a function");
13170 while ((name = *argptr++) != NULL) { 13287 while ((name = *argptr++) != NULL) {
13171 mklocal(name); 13288 mklocal(name);
@@ -13193,8 +13310,8 @@ mklocal(name)
13193 lvp = ckmalloc(sizeof (struct localvar)); 13310 lvp = ckmalloc(sizeof (struct localvar));
13194 if (name[0] == '-' && name[1] == '\0') { 13311 if (name[0] == '-' && name[1] == '\0') {
13195 char *p; 13312 char *p;
13196 p = ckmalloc(sizeof optlist); 13313 p = ckmalloc(sizeof optet_vals);
13197 lvp->text = memcpy(p, optlist, sizeof optlist); 13314 lvp->text = memcpy(p, optet_vals, sizeof optet_vals);
13198 vp = NULL; 13315 vp = NULL;
13199 } else { 13316 } else {
13200 vpp = hashvar(name); 13317 vpp = hashvar(name);
@@ -13204,7 +13321,7 @@ mklocal(name)
13204 setvareq(savestr(name), VSTRFIXED); 13321 setvareq(savestr(name), VSTRFIXED);
13205 else 13322 else
13206 setvar(name, NULL, VSTRFIXED); 13323 setvar(name, NULL, VSTRFIXED);
13207 vp = *vpp; /* the new variable */ 13324 vp = *vpp; /* the new variable */
13208 lvp->text = NULL; 13325 lvp->text = NULL;
13209 lvp->flags = VUNSET; 13326 lvp->flags = VUNSET;
13210 } else { 13327 } else {
@@ -13234,8 +13351,8 @@ poplocalvars() {
13234 while ((lvp = localvars) != NULL) { 13351 while ((lvp = localvars) != NULL) {
13235 localvars = lvp->next; 13352 localvars = lvp->next;
13236 vp = lvp->vp; 13353 vp = lvp->vp;
13237 if (vp == NULL) { /* $- saved */ 13354 if (vp == NULL) { /* $- saved */
13238 memcpy(optlist, lvp->text, sizeof optlist); 13355 memcpy(optet_vals, lvp->text, sizeof optet_vals);
13239 ckfree(lvp->text); 13356 ckfree(lvp->text);
13240 } else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) { 13357 } else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
13241 (void)unsetvar(vp->text); 13358 (void)unsetvar(vp->text);
@@ -13415,7 +13532,7 @@ findvar(struct var **vpp, const char *name)
13415/* 13532/*
13416 * Copyright (c) 1999 Herbert Xu <herbert@debian.org> 13533 * Copyright (c) 1999 Herbert Xu <herbert@debian.org>
13417 * This file contains code for the times builtin. 13534 * This file contains code for the times builtin.
13418 * $Id: ash.c,v 1.3 2001/06/28 16:43:57 andersen Exp $ 13535 * $Id: ash.c,v 1.4 2001/07/02 17:27:21 andersen Exp $
13419 */ 13536 */
13420static int timescmd (int argc, char **argv) 13537static int timescmd (int argc, char **argv)
13421{ 13538{
@@ -13438,7 +13555,7 @@ static int timescmd (int argc, char **argv)
13438 13555
13439/*- 13556/*-
13440 * Copyright (c) 1989, 1991, 1993, 1994 13557 * Copyright (c) 1989, 1991, 1993, 1994
13441 * The Regents of the University of California. All rights reserved. 13558 * The Regents of the University of California. All rights reserved.
13442 * 13559 *
13443 * This code is derived from software contributed to Berkeley by 13560 * This code is derived from software contributed to Berkeley by
13444 * Kenneth Almquist. 13561 * Kenneth Almquist.
@@ -13452,8 +13569,8 @@ static int timescmd (int argc, char **argv)
13452 * notice, this list of conditions and the following disclaimer in the 13569 * notice, this list of conditions and the following disclaimer in the
13453 * documentation and/or other materials provided with the distribution. 13570 * documentation and/or other materials provided with the distribution.
13454 * 13571 *
13455 * 3. <BSD Advertising Clause omitted per the July 22, 1999 licensing change 13572 * 3. <BSD Advertising Clause omitted per the July 22, 1999 licensing change
13456 * ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change> 13573 * ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change>
13457 * 13574 *
13458 * 4. Neither the name of the University nor the names of its contributors 13575 * 4. Neither the name of the University nor the names of its contributors
13459 * may be used to endorse or promote products derived from this software 13576 * may be used to endorse or promote products derived from this software
diff --git a/ash.h b/ash.h
deleted file mode 100644
index ac25ddb1c..000000000
--- a/ash.h
+++ /dev/null
@@ -1,1225 +0,0 @@
1/*-
2 * Copyright (c) 1993
3 * The Regents of the University of California. All rights reserved.
4 *
5 * This code is derived from software contributed to Berkeley by
6 * Kenneth Almquist.
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
37/* $NetBSD: alias.h,v 1.4 1995/05/11 21:28:42 christos Exp $ */
38
39#define ALIASINUSE 1
40#define ALIASDEAD 2
41
42struct alias {
43 struct alias *next;
44 char *name;
45 char *val;
46 int flag;
47};
48
49struct alias *lookupalias __P((const char *, int));
50static int aliascmd __P((int, char **));
51static int unaliascmd __P((int, char **));
52static void rmaliases __P((void));
53static int unalias __P((char *));
54static void printalias __P((const struct alias *));
55#define ARITH_NUM 257
56#define ARITH_LPAREN 258
57#define ARITH_RPAREN 259
58#define ARITH_OR 260
59#define ARITH_AND 261
60#define ARITH_BOR 262
61#define ARITH_BXOR 263
62#define ARITH_BAND 264
63#define ARITH_EQ 265
64#define ARITH_NE 266
65#define ARITH_LT 267
66#define ARITH_GT 268
67#define ARITH_GE 269
68#define ARITH_LE 270
69#define ARITH_LSHIFT 271
70#define ARITH_RSHIFT 272
71#define ARITH_ADD 273
72#define ARITH_SUB 274
73#define ARITH_MUL 275
74#define ARITH_DIV 276
75#define ARITH_REM 277
76#define ARITH_UNARYMINUS 278
77#define ARITH_UNARYPLUS 279
78#define ARITH_NOT 280
79#define ARITH_BNOT 281
80
81/*
82 * This file was generated by the mkbuiltins program.
83 */
84
85
86#define BUILTIN_SPECIAL 0x1
87#define BUILTIN_REGULAR 0x2
88#define BUILTIN_ASSIGN 0x4
89
90struct builtincmd {
91 const char *name;
92 int (*const builtinfunc) __P((int, char **));
93 unsigned flags;
94};
95
96extern const struct builtincmd builtincmds[];
97
98
99
100/* $NetBSD: cd.h,v 1.2 1997/07/04 21:01:52 christos Exp $ */
101static int cdcmd __P((int, char **));
102static int pwdcmd __P((int, char **));
103static void setpwd __P((const char *, int));
104
105
106/* $NetBSD: error.h,v 1.14 2001/02/04 19:52:06 christos Exp $ */
107
108/*
109 * Types of operations (passed to the errmsg routine).
110 */
111
112#define E_OPEN 01 /* opening a file */
113#define E_CREAT 02 /* creating a file */
114#define E_EXEC 04 /* executing a program */
115
116
117/*
118 * We enclose jmp_buf in a structure so that we can declare pointers to
119 * jump locations. The global variable handler contains the location to
120 * jump to when an exception occurs, and the global variable exception
121 * contains a code identifying the exeception. To implement nested
122 * exception handlers, the user should save the value of handler on entry
123 * to an inner scope, set handler to point to a jmploc structure for the
124 * inner scope, and restore handler on exit from the scope.
125 */
126
127struct jmploc {
128 jmp_buf loc;
129};
130
131extern struct jmploc *handler;
132extern int exception;
133
134/* exceptions */
135#define EXINT 0 /* SIGINT received */
136#define EXERROR 1 /* a generic error */
137#define EXSHELLPROC 2 /* execute a shell procedure */
138#define EXEXEC 3 /* command execution failed */
139
140
141/*
142 * These macros allow the user to suspend the handling of interrupt signals
143 * over a period of time. This is similar to SIGHOLD to or sigblock, but
144 * much more efficient and portable. (But hacking the kernel is so much
145 * more fun than worrying about efficiency and portability. :-))
146 */
147
148extern int suppressint;
149extern volatile int intpending;
150
151#define INTOFF suppressint++
152#ifdef REALLY_SMALL
153static void __inton __P((void));
154#define INTON __inton()
155#else
156#define INTON { if (--suppressint == 0 && intpending) onint(); }
157#endif
158#define FORCEINTON {suppressint = 0; if (intpending) onint();}
159#define CLEAR_PENDING_INT intpending = 0
160#define int_pending() intpending
161
162static void exraise __P((int)) __attribute__((__noreturn__));
163static void onint __P((void));
164static void error __P((const char *, ...)) __attribute__((__noreturn__));
165static void exerror __P((int, const char *, ...)) __attribute__((__noreturn__));
166static const char *errmsg __P((int, int));
167
168
169/*
170 * BSD setjmp saves the signal mask, which violates ANSI C and takes time,
171 * so we use _setjmp instead.
172 */
173
174#if defined(BSD) && !defined(__SVR4) && !defined(__GLIBC__)
175#define setjmp(jmploc) _setjmp(jmploc)
176#define longjmp(jmploc, val) _longjmp(jmploc, val)
177#endif
178
179
180
181/* $NetBSD: shell.h,v 1.13 2000/05/22 10:18:47 elric Exp $ */
182
183/*
184 * The follow should be set to reflect the type of system you have:
185 * JOBS -> 1 if you have Berkeley job control, 0 otherwise.
186 * SHORTNAMES -> 1 if your linker cannot handle long names.
187 * define BSD if you are running 4.2 BSD or later.
188 * define SYSV if you are running under System V.
189 * define DEBUG=1 to compile in debugging (set global "debug" to turn on)
190 * define DEBUG=2 to compile in and turn on debugging.
191 *
192 * When debugging is on, debugging info will be written to $HOME/trace and
193 * a quit signal will generate a core dump.
194 */
195
196
197#define JOBS 1
198#ifndef BSD
199#define BSD 1
200#endif
201
202#ifdef __STDC__
203typedef void *pointer;
204#ifndef NULL
205#define NULL (void *)0
206#endif
207#else /* not __STDC__ */
208typedef char *pointer;
209#ifndef NULL
210#define NULL 0
211#endif
212#endif /* not __STDC__ */
213
214extern char nullstr[1]; /* null string */
215
216
217#ifdef DEBUG
218#define TRACE(param) trace param
219#else
220#define TRACE(param)
221#endif
222
223
224
225
226/*
227 * This file was generated by the mknodes program.
228 */
229
230#define NSEMI 0
231#define NCMD 1
232#define NPIPE 2
233#define NREDIR 3
234#define NBACKGND 4
235#define NSUBSHELL 5
236#define NAND 6
237#define NOR 7
238#define NIF 8
239#define NWHILE 9
240#define NUNTIL 10
241#define NFOR 11
242#define NCASE 12
243#define NCLIST 13
244#define NDEFUN 14
245#define NARG 15
246#define NTO 16
247#define NFROM 17
248#define NFROMTO 18
249#define NAPPEND 19
250#define NTOOV 20
251#define NTOFD 21
252#define NFROMFD 22
253#define NHERE 23
254#define NXHERE 24
255#define NNOT 25
256
257
258
259struct nbinary {
260 int type;
261 union node *ch1;
262 union node *ch2;
263};
264
265
266struct ncmd {
267 int type;
268 int backgnd;
269 union node *assign;
270 union node *args;
271 union node *redirect;
272};
273
274
275struct npipe {
276 int type;
277 int backgnd;
278 struct nodelist *cmdlist;
279};
280
281
282struct nredir {
283 int type;
284 union node *n;
285 union node *redirect;
286};
287
288
289struct nif {
290 int type;
291 union node *test;
292 union node *ifpart;
293 union node *elsepart;
294};
295
296
297struct nfor {
298 int type;
299 union node *args;
300 union node *body;
301 char *var;
302};
303
304
305struct ncase {
306 int type;
307 union node *expr;
308 union node *cases;
309};
310
311
312struct nclist {
313 int type;
314 union node *next;
315 union node *pattern;
316 union node *body;
317};
318
319
320struct narg {
321 int type;
322 union node *next;
323 char *text;
324 struct nodelist *backquote;
325};
326
327
328struct nfile {
329 int type;
330 union node *next;
331 int fd;
332 union node *fname;
333 char *expfname;
334};
335
336
337struct ndup {
338 int type;
339 union node *next;
340 int fd;
341 int dupfd;
342 union node *vname;
343};
344
345
346struct nhere {
347 int type;
348 union node *next;
349 int fd;
350 union node *doc;
351};
352
353
354struct nnot {
355 int type;
356 union node *com;
357};
358
359
360union node {
361 int type;
362 struct nbinary nbinary;
363 struct ncmd ncmd;
364 struct npipe npipe;
365 struct nredir nredir;
366 struct nif nif;
367 struct nfor nfor;
368 struct ncase ncase;
369 struct nclist nclist;
370 struct narg narg;
371 struct nfile nfile;
372 struct ndup ndup;
373 struct nhere nhere;
374 struct nnot nnot;
375};
376
377
378struct nodelist {
379 struct nodelist *next;
380 union node *n;
381};
382
383
384#ifdef __STDC__
385union node *copyfunc(union node *);
386static void freefunc(union node *);
387#else
388union node *copyfunc();
389static void freefunc();
390#endif
391
392
393
394/* $NetBSD: eval.h,v 1.10 2000/01/27 23:39:40 christos Exp $ */
395extern char *commandname; /* currently executing command */
396extern int exitstatus; /* exit status of last command */
397extern struct strlist *cmdenviron; /* environment for builtin command */
398
399
400struct backcmd { /* result of evalbackcmd */
401 int fd; /* file descriptor to read from */
402 char *buf; /* buffer */
403 int nleft; /* number of chars in buffer */
404 struct job *jp; /* job structure for command */
405};
406
407static int evalcmd __P((int, char **));
408static void evalstring __P((char *, int));
409static void evaltree __P((union node *, int));
410static void evalbackcmd __P((union node *, struct backcmd *));
411static int bltincmd __P((int, char **));
412static int breakcmd __P((int, char **));
413static int returncmd __P((int, char **));
414static int execcmd __P((int, char **));
415
416/* in_function returns nonzero if we are currently evaluating a function */
417#define in_function() funcnest
418extern int funcnest;
419extern int evalskip;
420
421/* reasons for skipping commands (see comment on breakcmd routine) */
422#define SKIPBREAK 1
423#define SKIPCONT 2
424#define SKIPFUNC 3
425#define SKIPFILE 4
426
427
428
429
430/* $NetBSD: exec.h,v 1.17 2000/05/22 10:18:47 elric Exp $ */
431
432/* values of cmdtype */
433#define CMDUNKNOWN -1 /* no entry in table for command */
434#define CMDNORMAL 0 /* command is an executable program */
435#define CMDBUILTIN 1 /* command is a shell builtin */
436#define CMDFUNCTION 2 /* command is a shell function */
437
438
439struct cmdentry {
440 int cmdtype;
441 union param {
442 int index;
443 union node *func;
444 const struct builtincmd *cmd;
445 } u;
446};
447
448
449#define DO_ERR 1 /* find_command prints errors */
450#define DO_ABS 2 /* find_command checks absolute paths */
451#define DO_NOFUN 4 /* find_command ignores functions */
452#define DO_BRUTE 8 /* find_command ignores hash table */
453
454extern const char *pathopt; /* set by padvance */
455extern int exerrno; /* last exec error */
456
457static void shellexec __P((char **, char **, const char *, int))
458 __attribute__((noreturn));
459static char *padvance __P((const char **, const char *));
460static int hashcmd __P((int, char **));
461static void find_command __P((char *, struct cmdentry *, int, const char *));
462struct builtincmd *find_builtin __P((char *));
463static void hashcd __P((void));
464static void changepath __P((const char *));
465static void deletefuncs __P((void));
466#ifdef notdef
467static void getcmdentry __P((char *, struct cmdentry *));
468#endif
469static void addcmdentry __P((char *, struct cmdentry *));
470static void defun __P((char *, union node *));
471static void unsetfunc __P((char *));
472#ifdef ASH_TYPE
473static int typecmd __P((int, char **));
474#endif
475static int commandcmd __P((int, char **));
476
477
478
479/* $NetBSD: expand.h,v 1.12 1999/07/09 03:05:50 christos Exp $ */
480struct strlist {
481 struct strlist *next;
482 char *text;
483};
484
485
486struct arglist {
487 struct strlist *list;
488 struct strlist **lastp;
489};
490
491/*
492 * expandarg() flags
493 */
494#define EXP_FULL 0x1 /* perform word splitting & file globbing */
495#define EXP_TILDE 0x2 /* do normal tilde expansion */
496#define EXP_VARTILDE 0x4 /* expand tildes in an assignment */
497#define EXP_REDIR 0x8 /* file glob for a redirection (1 match only) */
498#define EXP_CASE 0x10 /* keeps quotes around for CASE pattern */
499#define EXP_RECORD 0x20 /* need to record arguments for ifs breakup */
500
501
502static void expandhere __P((union node *, int));
503static void expandarg __P((union node *, struct arglist *, int));
504#ifdef ASH_MATH_SUPPORT
505static void expari __P((int));
506#endif
507#if !(defined(__GLIBC__) && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN))
508static int patmatch __P((char *, char *, int));
509#endif
510#if defined(__GLIBC__) && !defined(FNMATCH_BROKEN)
511#define rmescapes(p) _rmescapes((p), 0)
512static char *_rmescapes __P((char *, int));
513#else
514static void rmescapes __P((char *));
515#endif
516static int casematch __P((union node *, char *));
517
518
519#ifdef ASH_MATH_SUPPORT
520/* From arith.y */
521static int arith __P((const char *));
522static int expcmd __P((int , char **));
523static void arith_lex_reset __P((void));
524static int yylex __P((void));
525#endif
526
527
528
529
530/* $NetBSD: init.h,v 1.8 1995/05/11 21:29:14 christos Exp $ */
531static void init __P((void));
532static void reset __P((void));
533static void initshellproc __P((void));
534
535
536
537/* $NetBSD: input.h,v 1.12 2000/05/22 10:18:47 elric Exp $ */
538
539/* PEOF (the end of file marker) is defined in syntax.h */
540/*
541 * The input line number. Input.c just defines this variable, and saves
542 * and restores it when files are pushed and popped. The user of this
543 * package must set its value.
544 */
545extern int plinno;
546extern int parsenleft; /* number of characters left in input buffer */
547extern char *parsenextc; /* next character in input buffer */
548
549static char *pfgets __P((char *, int));
550static int pgetc __P((void));
551static int pgetc2 __P((void));
552static int preadbuffer __P((void));
553static void pungetc __P((void));
554static void pushstring __P((char *, int, void *));
555static void popstring __P((void));
556static void setinputfile __P((const char *, int));
557static void setinputfd __P((int, int));
558static void setinputstring __P((char *));
559static void popfile __P((void));
560static void popallfiles __P((void));
561static void closescript __P((void));
562
563#define pgetc_macro() (--parsenleft >= 0? *parsenextc++ : preadbuffer())
564
565
566
567/* $NetBSD: jobs.h,v 1.12 2000/05/22 10:18:47 elric Exp $ */
568
569/* Mode argument to forkshell. Don't change FORK_FG or FORK_BG. */
570#define FORK_FG 0
571#define FORK_BG 1
572#define FORK_NOJOB 2
573
574
575/*
576 * A job structure contains information about a job. A job is either a
577 * single process or a set of processes contained in a pipeline. In the
578 * latter case, pidlist will be non-NULL, and will point to a -1 terminated
579 * array of pids.
580 */
581
582struct procstat {
583 pid_t pid; /* process id */
584 int status; /* status flags (defined above) */
585 char *cmd; /* text of command being run */
586};
587
588
589/* states */
590#define JOBSTOPPED 1 /* all procs are stopped */
591#define JOBDONE 2 /* all procs are completed */
592
593
594struct job {
595 struct procstat ps0; /* status of process */
596 struct procstat *ps; /* status or processes when more than one */
597 short nprocs; /* number of processes */
598 short pgrp; /* process group of this job */
599 char state; /* true if job is finished */
600 char used; /* true if this entry is in used */
601 char changed; /* true if status has changed */
602#if JOBS
603 char jobctl; /* job running under job control */
604#endif
605};
606
607extern short backgndpid; /* pid of last background process */
608extern int job_warning; /* user was warned about stopped jobs */
609
610static void setjobctl __P((int));
611static int killcmd __P((int, char **));
612static int fgcmd __P((int, char **));
613static int bgcmd __P((int, char **));
614static int jobscmd __P((int, char **));
615static void showjobs __P((int));
616static int waitcmd __P((int, char **));
617struct job *makejob __P((union node *, int));
618static int forkshell __P((struct job *, union node *, int));
619static int waitforjob __P((struct job *));
620static int stoppedjobs __P((void));
621static char *commandtext __P((union node *));
622
623#if ! JOBS
624#define setjobctl(on) /* do nothing */
625#endif
626
627
628
629/* $NetBSD: machdep.h,v 1.8 1995/05/11 21:29:21 christos Exp $ */
630
631/*
632 * Most machines require the value returned from malloc to be aligned
633 * in some way. The following macro will get this right on many machines.
634 */
635
636#ifndef ALIGN
637union align {
638 int i;
639 char *cp;
640};
641
642#define ALIGN(nbytes) (((nbytes) + sizeof(union align) - 1) & ~(sizeof(union align) - 1))
643#endif
644
645
646
647/* $NetBSD: mail.h,v 1.8 1995/05/11 21:29:23 christos Exp $ */
648
649static void chkmail __P((int));
650
651
652
653/* $NetBSD: main.h,v 1.8 1995/05/11 21:29:27 christos Exp $ */
654extern int rootpid; /* pid of main shell */
655extern int rootshell; /* true if we aren't a child of the main shell */
656
657static void readcmdfile __P((char *));
658static void cmdloop __P((int));
659static int dotcmd __P((int, char **));
660static int exitcmd __P((int, char **));
661
662
663
664/* $NetBSD: memalloc.h,v 1.11 2000/11/01 19:56:01 christos Exp $ */
665struct stackmark {
666 struct stack_block *stackp;
667 char *stacknxt;
668 int stacknleft;
669 struct stackmark *marknext;
670};
671
672
673extern char *stacknxt;
674extern int stacknleft;
675extern int sstrnleft;
676extern int herefd;
677
678static inline pointer ckmalloc (int sz) { return xmalloc(sz); }
679static inline pointer ckrealloc(void *p, int sz) { return xrealloc(p, sz); }
680static inline char * savestr (const char *s) { return xstrdup(s); }
681
682pointer stalloc __P((int));
683static void stunalloc __P((pointer));
684static void setstackmark __P((struct stackmark *));
685static void popstackmark __P((struct stackmark *));
686static void growstackblock __P((void));
687static void grabstackblock __P((int));
688static char *growstackstr __P((void));
689static char *makestrspace __P((size_t));
690static void ungrabstackstr __P((char *, char *));
691
692
693
694#define stackblock() stacknxt
695#define stackblocksize() stacknleft
696#define STARTSTACKSTR(p) p = stackblock(), sstrnleft = stackblocksize()
697#define STPUTC(c, p) (--sstrnleft >= 0? (*p++ = (c)) : (p = growstackstr(), *p++ = (c)))
698#define CHECKSTRSPACE(n, p) { if (sstrnleft < n) p = makestrspace(n); }
699#define USTPUTC(c, p) (--sstrnleft, *p++ = (c))
700#define STACKSTRNUL(p) (sstrnleft == 0? (p = growstackstr(), *p = '\0') : (*p = '\0'))
701#define STUNPUTC(p) (++sstrnleft, --p)
702#define STTOPC(p) p[-1]
703#define STADJUST(amount, p) (p += (amount), sstrnleft -= (amount))
704#define grabstackstr(p) stalloc(stackblocksize() - sstrnleft)
705
706#define ckfree(p) free((pointer)(p))
707
708
709
710/* $NetBSD: miscbltin.h,v 1.1 1997/07/04 21:02:10 christos Exp $ */
711static int readcmd __P((int, char **));
712static int umaskcmd __P((int, char **));
713static int ulimitcmd __P((int, char **));
714
715
716
717/* $NetBSD: mystring.h,v 1.9 1995/05/11 21:29:42 christos Exp $ */
718
719extern const char snlfmt[];
720extern const char spcstr[];
721
722#if 0
723static void scopyn __P((const char *, char *, int));
724#endif
725static int prefix __P((const char *, const char *));
726static int number __P((const char *));
727static int is_number __P((const char *));
728static char *single_quote __P((const char *));
729static char *sstrdup __P((const char *));
730static int pstrcmp __P((const void *, const void *));
731static const char *const *findstring __P((const char *, const char *const *, size_t));
732
733#define equal(s1, s2) (strcmp(s1, s2) == 0)
734#define scopy(s1, s2) ((void)strcpy(s2, s1))
735
736
737/* $NetBSD: options.h,v 1.14 2001/02/04 19:52:06 christos Exp $ */
738
739struct shparam {
740 int nparam; /* # of positional parameters (without $0) */
741 unsigned char malloc; /* if parameter list dynamically allocated */
742 char **p; /* parameter list */
743 int optind; /* next parameter to be processed by getopts */
744 int optoff; /* used by getopts */
745};
746
747
748
749#define eflag optlist[0].val
750#define fflag optlist[1].val
751#define Iflag optlist[2].val
752#define iflag optlist[3].val
753#define mflag optlist[4].val
754#define nflag optlist[5].val
755#define sflag optlist[6].val
756#define xflag optlist[7].val
757#define vflag optlist[8].val
758#define Vflag optlist[9].val
759#define Eflag optlist[10].val
760#define Cflag optlist[11].val
761#define aflag optlist[12].val
762#define bflag optlist[13].val
763#define uflag optlist[14].val
764#define qflag optlist[15].val
765
766#define NOPTS 16
767
768struct optent {
769 const char *name;
770 const char letter;
771 char val;
772};
773
774extern struct optent optlist[NOPTS];
775
776
777extern char *minusc; /* argument to -c option */
778extern char *arg0; /* $0 */
779extern struct shparam shellparam; /* $@ */
780extern char **argptr; /* argument list for builtin commands */
781extern char *optionarg; /* set by nextopt */
782extern char *optptr; /* used by nextopt */
783
784static void procargs __P((int, char **));
785static void optschanged __P((void));
786static void setparam __P((char **));
787static void freeparam __P((volatile struct shparam *));
788static int shiftcmd __P((int, char **));
789static int setcmd __P((int, char **));
790#ifdef ASH_GETOPTS
791static int getoptscmd __P((int, char **));
792static int setvarsafe __P((const char *, const char *, int));
793#endif
794static int nextopt __P((const char *));
795static void getoptsreset __P((const char *));
796
797
798
799/* $NetBSD: output.h,v 1.14 1998/01/31 12:37:55 christos Exp $ */
800struct output {
801#ifdef USE_GLIBC_STDIO
802 FILE *stream;
803#endif
804 char *nextc;
805 int nleft;
806 char *buf;
807 int bufsize;
808 int fd;
809 short flags;
810};
811
812extern struct output output;
813extern struct output errout;
814extern struct output memout;
815extern struct output *out1;
816extern struct output *out2;
817
818static void outstr __P((const char *, struct output *));
819#ifndef USE_GLIBC_STDIO
820static void outcslow __P((char, struct output *));
821#endif
822static void flushall __P((void));
823static void flushout __P((struct output *));
824static void freestdout __P((void));
825static void outfmt __P((struct output *, const char *, ...))
826 __attribute__((__format__(__printf__,2,3)));
827static void out1fmt __P((const char *, ...))
828 __attribute__((__format__(__printf__,1,2)));
829static void fmtstr __P((char *, size_t, const char *, ...))
830 __attribute__((__format__(__printf__,3,4)));
831#ifndef USE_GLIBC_STDIO
832static void doformat __P((struct output *, const char *, va_list));
833#endif
834static int xwrite __P((int, const char *, int));
835#ifdef USE_GLIBC_STDIO
836static void initstreams __P((void));
837static void openmemout __P((void));
838static int __closememout __P((void));
839#endif
840
841#define OUTPUT_ERR 01 /* error occurred on output */
842
843#ifdef USE_GLIBC_STDIO
844#define outc(c, o) putc((c), (o)->stream)
845#define doformat(d, f, a) vfprintf((d)->stream, (f), (a))
846#else
847#define outc(c, file) (--(file)->nleft < 0? outcslow((c), (file)) : (*(file)->nextc = (c), (file)->nextc++))
848#endif
849#define out1c(c) outc((c), out1)
850#define out2c(c) outc((c), out2)
851#define out1str(s) outstr((s), out1)
852#define out2str(s) outstr((s), out2)
853#define outerr(f) ((f)->flags & OUTPUT_ERR)
854
855
856
857/* $NetBSD: parser.h,v 1.14 2000/07/27 04:09:28 cgd Exp $ */
858/* control characters in argument strings */
859#define CTLESC '\201'
860#define CTLVAR '\202'
861#define CTLENDVAR '\203'
862#define CTLBACKQ '\204'
863#define CTLQUOTE 01 /* ored with CTLBACKQ code if in quotes */
864/* CTLBACKQ | CTLQUOTE == '\205' */
865#define CTLARI '\206'
866#define CTLENDARI '\207'
867#define CTLQUOTEMARK '\210'
868
869/* variable substitution byte (follows CTLVAR) */
870#define VSTYPE 0x0f /* type of variable substitution */
871#define VSNUL 0x10 /* colon--treat the empty string as unset */
872#define VSQUOTE 0x80 /* inside double quotes--suppress splitting */
873
874/* values of VSTYPE field */
875#define VSNORMAL 0x1 /* normal variable: $var or ${var} */
876#define VSMINUS 0x2 /* ${var-text} */
877#define VSPLUS 0x3 /* ${var+text} */
878#define VSQUESTION 0x4 /* ${var?message} */
879#define VSASSIGN 0x5 /* ${var=text} */
880#define VSTRIMLEFT 0x6 /* ${var#pattern} */
881#define VSTRIMLEFTMAX 0x7 /* ${var##pattern} */
882#define VSTRIMRIGHT 0x8 /* ${var%pattern} */
883#define VSTRIMRIGHTMAX 0x9 /* ${var%%pattern} */
884#define VSLENGTH 0xa /* ${#var} */
885
886
887/*
888 * NEOF is returned by parsecmd when it encounters an end of file. It
889 * must be distinct from NULL, so we use the address of a variable that
890 * happens to be handy.
891 */
892extern int tokpushback;
893#define NEOF ((union node *)&tokpushback)
894extern int whichprompt; /* 1 == PS1, 2 == PS2 */
895extern int checkalias;
896
897
898union node *parsecmd(int);
899static void fixredir(union node *, const char *, int);
900static int goodname(char *);
901static const char *getprompt(void *);
902static int isassignment __P((const char *));
903static const char *const *findkwd __P((const char *));
904
905
906/* $NetBSD: redir.h,v 1.12 2000/05/22 10:18:47 elric Exp $ */
907/* flags passed to redirect */
908#define REDIR_PUSH 01 /* save previous values of file descriptors */
909#define REDIR_BACKQ 02 /* save the command output in memory */
910
911extern int fileno2;
912
913static void redirect __P((union node *, int));
914static void popredir __P((void));
915static int fd0_redirected_p __P((void));
916static void clearredir __P((void));
917static int dup_as_newfd __P((int, int));
918
919
920
921
922/* $NetBSD: show.h,v 1.4 1999/10/08 21:10:44 pk Exp $ */
923#ifdef DEBUG
924static void trace __P((const char *, ...));
925static void trargs __P((char **));
926static void showtree __P((union node *));
927static void trputc __P((int));
928static void trputs __P((const char *));
929static void opentrace __P((void));
930#endif
931/*
932 * This file was generated by the mksyntax program.
933 */
934
935#ifdef CEOF
936#undef CEOF
937#endif
938
939/* Syntax classes */
940#define CWORD 0 /* character is nothing special */
941#define CNL 1 /* newline character */
942#define CBACK 2 /* a backslash character */
943#define CSQUOTE 3 /* single quote */
944#define CDQUOTE 4 /* double quote */
945#define CENDQUOTE 5 /* a terminating quote */
946#define CBQUOTE 6 /* backwards single quote */
947#define CVAR 7 /* a dollar sign */
948#define CENDVAR 8 /* a '}' character */
949#define CLP 9 /* a left paren in arithmetic */
950#define CRP 10 /* a right paren in arithmetic */
951#define CEOF 11 /* end of file */
952#define CCTL 12 /* like CWORD, except it must be escaped */
953#define CSPCL 13 /* these terminate a word */
954#define CIGN 14 /* character should be ignored */
955
956/* Syntax classes for is_ functions */
957#define ISDIGIT 01 /* a digit */
958#define ISUPPER 02 /* an upper case letter */
959#define ISLOWER 04 /* a lower case letter */
960#define ISUNDER 010 /* an underscore */
961#define ISSPECL 020 /* the name of a special parameter */
962
963#define SYNBASE 130
964#define PEOF -130
965
966#define PEOA -129
967
968
969#define BASESYNTAX (basesyntax + SYNBASE)
970#define DQSYNTAX (dqsyntax + SYNBASE)
971#define SQSYNTAX (sqsyntax + SYNBASE)
972#define ARISYNTAX (arisyntax + SYNBASE)
973
974#define is_digit(c) ((unsigned)((c) - '0') <= 9)
975#define is_alpha(c) (((c) < CTLESC || (c) > CTLENDARI) && isalpha((unsigned char) (c)))
976#define is_name(c) (((c) < CTLESC || (c) > CTLENDARI) && ((c) == '_' || isalpha((unsigned char) (c))))
977#define is_in_name(c) (((c) < CTLESC || (c) > CTLENDARI) && ((c) == '_' || isalnum((unsigned char) (c))))
978#define is_special(c) ((is_type+SYNBASE)[c] & (ISSPECL|ISDIGIT))
979#define digit_val(c) ((c) - '0')
980
981extern const char basesyntax[];
982extern const char dqsyntax[];
983extern const char sqsyntax[];
984extern const char arisyntax[];
985extern const char is_type[];
986#define TEOF 0
987#define TNL 1
988#define TSEMI 2
989#define TBACKGND 3
990#define TAND 4
991#define TOR 5
992#define TPIPE 6
993#define TLP 7
994#define TRP 8
995#define TENDCASE 9
996#define TENDBQUOTE 10
997#define TREDIR 11
998#define TWORD 12
999#define TASSIGN 13
1000#define TNOT 14
1001#define TCASE 15
1002#define TDO 16
1003#define TDONE 17
1004#define TELIF 18
1005#define TELSE 19
1006#define TESAC 20
1007#define TFI 21
1008#define TFOR 22
1009#define TIF 23
1010#define TIN 24
1011#define TTHEN 25
1012#define TUNTIL 26
1013#define TWHILE 27
1014#define TBEGIN 28
1015#define TEND 29
1016
1017/* Array indicating which tokens mark the end of a list */
1018static const char tokendlist[] = {
1019 1,
1020 0,
1021 0,
1022 0,
1023 0,
1024 0,
1025 0,
1026 0,
1027 1,
1028 1,
1029 1,
1030 0,
1031 0,
1032 0,
1033 0,
1034 0,
1035 1,
1036 1,
1037 1,
1038 1,
1039 1,
1040 1,
1041 0,
1042 0,
1043 0,
1044 1,
1045 0,
1046 0,
1047 0,
1048 1,
1049};
1050
1051static const char *const tokname[] = {
1052 "end of file",
1053 "newline",
1054 "\";\"",
1055 "\"&\"",
1056 "\"&&\"",
1057 "\"||\"",
1058 "\"|\"",
1059 "\"(\"",
1060 "\")\"",
1061 "\";;\"",
1062 "\"`\"",
1063 "redirection",
1064 "word",
1065 "assignment",
1066 "\"!\"",
1067 "\"case\"",
1068 "\"do\"",
1069 "\"done\"",
1070 "\"elif\"",
1071 "\"else\"",
1072 "\"esac\"",
1073 "\"fi\"",
1074 "\"for\"",
1075 "\"if\"",
1076 "\"in\"",
1077 "\"then\"",
1078 "\"until\"",
1079 "\"while\"",
1080 "\"{\"",
1081 "\"}\"",
1082};
1083
1084#define KWDOFFSET 14
1085
1086static const char *const parsekwd[] = {
1087 "!",
1088 "case",
1089 "do",
1090 "done",
1091 "elif",
1092 "else",
1093 "esac",
1094 "fi",
1095 "for",
1096 "if",
1097 "in",
1098 "then",
1099 "until",
1100 "while",
1101 "{",
1102 "}"
1103};
1104
1105
1106
1107
1108/* $NetBSD: trap.h,v 1.14 2000/05/22 10:18:47 elric Exp $ */
1109extern int pendingsigs;
1110
1111static int trapcmd __P((int, char **));
1112static void clear_traps __P((void));
1113static void setsignal __P((int));
1114static void ignoresig __P((int));
1115static void onsig __P((int));
1116static void dotrap __P((void));
1117static void setinteractive __P((int));
1118static void exitshell __P((int)) __attribute__((noreturn));
1119static int decode_signal __P((const char *, int));
1120
1121
1122
1123/* $NetBSD: var.h,v 1.18 2000/05/22 10:18:47 elric Exp $ */
1124
1125/*
1126 * Shell variables.
1127 */
1128
1129/* flags */
1130#define VEXPORT 0x01 /* variable is exported */
1131#define VREADONLY 0x02 /* variable cannot be modified */
1132#define VSTRFIXED 0x04 /* variable struct is staticly allocated */
1133#define VTEXTFIXED 0x08 /* text is staticly allocated */
1134#define VSTACK 0x10 /* text is allocated on the stack */
1135#define VUNSET 0x20 /* the variable is not set */
1136#define VNOFUNC 0x40 /* don't call the callback function */
1137
1138
1139struct var {
1140 struct var *next; /* next entry in hash list */
1141 int flags; /* flags are defined above */
1142 char *text; /* name=value */
1143 void (*func) __P((const char *));
1144 /* function to be called when */
1145 /* the variable gets set/unset */
1146};
1147
1148
1149struct localvar {
1150 struct localvar *next; /* next local variable in list */
1151 struct var *vp; /* the variable that was made local */
1152 int flags; /* saved flags */
1153 char *text; /* saved text */
1154};
1155
1156
1157extern struct localvar *localvars;
1158
1159#if ATTY
1160extern struct var vatty;
1161#endif
1162extern struct var vifs;
1163extern struct var vmail;
1164extern struct var vmpath;
1165extern struct var vpath;
1166extern struct var vps1;
1167extern struct var vps2;
1168#ifndef SMALL
1169extern struct var vterm;
1170extern struct var vtermcap;
1171extern struct var vhistsize;
1172#endif
1173
1174#ifdef IFS_BROKEN
1175extern const char defifsvar[];
1176#define defifs (defifsvar + 4)
1177#else
1178extern const char defifs[];
1179#endif
1180extern const char defpathvar[];
1181#define defpath (defpathvar + 5)
1182
1183/*
1184 * The following macros access the values of the above variables.
1185 * They have to skip over the name. They return the null string
1186 * for unset variables.
1187 */
1188
1189#define ifsval() (vifs.text + 4)
1190#define ifsset() ((vifs.flags & VUNSET) == 0)
1191#define mailval() (vmail.text + 5)
1192#define mpathval() (vmpath.text + 9)
1193#define pathval() (vpath.text + 5)
1194#define ps1val() (vps1.text + 4)
1195#define ps2val() (vps2.text + 4)
1196#define optindval() (voptind.text + 7)
1197#ifndef SMALL
1198#define histsizeval() (vhistsize.text + 9)
1199#define termval() (vterm.text + 5)
1200#endif
1201
1202#if ATTY
1203#define attyset() ((vatty.flags & VUNSET) == 0)
1204#endif
1205#define mpathset() ((vmpath.flags & VUNSET) == 0)
1206
1207static void initvar __P((void));
1208static void setvar __P((const char *, const char *, int));
1209static void setvareq __P((char *, int));
1210struct strlist;
1211static void listsetvar __P((struct strlist *));
1212static char *lookupvar __P((const char *));
1213static char *bltinlookup __P((const char *));
1214static char **environment __P((void));
1215static void shprocvar __P((void));
1216static int showvarscmd __P((int, char **));
1217static int exportcmd __P((int, char **));
1218static int localcmd __P((int, char **));
1219static void mklocal __P((char *));
1220static void poplocalvars __P((void));
1221static int setvarcmd __P((int, char **));
1222static int unsetcmd __P((int, char **));
1223static int unsetvar __P((const char *));
1224static int varequal __P((const char *, const char *));
1225
diff --git a/shell/ash.c b/shell/ash.c
index 7d394b617..489ccaa95 100644
--- a/shell/ash.c
+++ b/shell/ash.c
@@ -3,7 +3,7 @@
3 * ash shell port for busybox 3 * ash shell port for busybox
4 * 4 *
5 * Copyright (c) 1989, 1991, 1993, 1994 5 * Copyright (c) 1989, 1991, 1993, 1994
6 * The Regents of the University of California. All rights reserved. 6 * The Regents of the University of California. All rights reserved.
7 * 7 *
8 * This code is derived from software contributed to Berkeley by 8 * This code is derived from software contributed to Berkeley by
9 * Kenneth Almquist. 9 * Kenneth Almquist.
@@ -22,20 +22,74 @@
22 * along with this program; if not, write to the Free Software 22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 * 24 *
25 * This version of ash is adapted from the source in Debian's ash 0.3.8-5 25 * This version of ash is adapted from the source in Debian's ash 0.3.8-5
26 * package. 26 * package.
27 *
28 * Modified by Erik Andersen <andersee@debian.org> and
29 * Vladimir Oleynik <vodz@usa.net> to be used in busybox
27 * 30 *
28 * Modified by Erik Andersen <andersee@debian.org> to be used in busybox.
29 * 31 *
30 * Original copyright notice is retained at the end of this file. 32 * Original copyright notice is retained at the end of this file.
31 */ 33 */
32 34
33#undef _GNU_SOURCE 35
36/* These defines allow you to adjust the feature set to be compiled
37 * into the ash shell. As a rule, enabling these options will make
38 * ash get bigger... With all of these options off, ash adds about
39 * 62k to busybox on an x86 system.*/
40
41
42
43/* Enable job control. This allows you to run jobs in the background,
44 * which is great when ash is being used as an interactive shell, but
45 * it completely useless for is all you are doing is running scripts.
46 * This adds about 2.5k on an x86 system. */
47#define JOBS
48
49/* This enables alias support in ash. If you want to support things
50 * like "alias ls='ls -l'" with ash, enable this. This is only useful
51 * when ash is used as an intractive shell. This adds about 1.5k */
52#define ASH_ALIAS
53
54/* If you need ash to act as a full Posix shell, with full math
55 * support, enable this. This option needs some work, since it
56 * doesn't compile right now... */
57#undef ASH_MATH_SUPPORT
58
59/* This shell builtin is used to indicate how the shell would interpret
60 * what you give it. This command is only useful when debugging, and
61 * is obsolete anyways. Adds about 670 bytes... You probably want to
62 * leave this disabled. */
34#undef ASH_TYPE 63#undef ASH_TYPE
64
65/* Getopts is used by shell procedures to parse positional parameters.
66 * You probably want to leave this disabled, and use the busybox getopt
67 * applet if you want to do this sort of thing. There are some scripts
68 * out there that use it, so it you need it, enable. Most people will
69 * leave this disabled. This adds 1k on an x86 system. */
35#undef ASH_GETOPTS 70#undef ASH_GETOPTS
36#undef ASH_MATH_SUPPORT 71
72/* This allows you to override shell builtins and use whatever is on
73 * the filesystem. This is most useful when ash is acting as a
74 * standalone shell. Adds about 320 bytes. */
75#undef ASH_CMDCMD
76
77/* This makes a few common apps that are usually part of busybox
78 * anyways to be used as builtins. This may cause these builtins to be
79 * a little bit faster, but leaving this disabled will save you 2k. */
80#undef ASH_BBAPPS_AS_BUILTINS
81
82/* Enable this to compile in extra debugging noise. When debugging is
83 * on, debugging info will be written to $HOME/trace and a quit signal
84 * will generate a core dump. */
85#undef DEBUG
86
87
88
89/* These are here to work with glibc -- Don't change these... */
37#undef FNMATCH_BROKEN 90#undef FNMATCH_BROKEN
38#undef GLOB_BROKEN 91#undef GLOB_BROKEN
92#undef _GNU_SOURCE
39 93
40#include <assert.h> 94#include <assert.h>
41#include <ctype.h> 95#include <ctype.h>
@@ -72,39 +126,1282 @@
72#include <glob.h> 126#include <glob.h>
73#endif 127#endif
74 128
75#if JOBS 129#ifdef JOBS
76#include <termios.h> 130#include <termios.h>
77#undef CEOF /* syntax.h redefines this */
78#endif 131#endif
79 132
80#include "cmdedit.h"
81#include "busybox.h" 133#include "busybox.h"
82#include "ash.h" 134#include "cmdedit.h"
135
136/* if BB_PWD is defined, then disable ASH_PWD to save space */
137#ifdef BB_PWD
138#undef ASH_PWD
139#endif
140
141
142/*
143 * This file was generated by the mksyntax program.
144 */
145
146/* Syntax classes */
147#define CWORD 0 /* character is nothing special */
148#define CNL 1 /* newline character */
149#define CBACK 2 /* a backslash character */
150#define CSQUOTE 3 /* single quote */
151#define CDQUOTE 4 /* double quote */
152#define CENDQUOTE 5 /* a terminating quote */
153#define CBQUOTE 6 /* backwards single quote */
154#define CVAR 7 /* a dollar sign */
155#define CENDVAR 8 /* a '}' character */
156#define CLP 9 /* a left paren in arithmetic */
157#define CRP 10 /* a right paren in arithmetic */
158#define CENDFILE 11 /* end of file */
159#define CCTL 12 /* like CWORD, except it must be escaped */
160#define CSPCL 13 /* these terminate a word */
161#define CIGN 14 /* character should be ignored */
162
163/* Syntax classes for is_ functions */
164#define ISDIGIT 01 /* a digit */
165#define ISUPPER 02 /* an upper case letter */
166#define ISLOWER 04 /* a lower case letter */
167#define ISUNDER 010 /* an underscore */
168#define ISSPECL 020 /* the name of a special parameter */
169
170#define SYNBASE 130
171#define PEOF -130
172
173#define PEOA -129
174
175#define TEOF 0
176#define TNL 1
177#define TSEMI 2
178#define TBACKGND 3
179#define TAND 4
180#define TOR 5
181#define TPIPE 6
182#define TLP 7
183#define TRP 8
184#define TENDCASE 9
185#define TENDBQUOTE 10
186#define TREDIR 11
187#define TWORD 12
188#define TASSIGN 13
189#define TNOT 14
190#define TCASE 15
191#define TDO 16
192#define TDONE 17
193#define TELIF 18
194#define TELSE 19
195#define TESAC 20
196#define TFI 21
197#define TFOR 22
198#define TIF 23
199#define TIN 24
200#define TTHEN 25
201#define TUNTIL 26
202#define TWHILE 27
203#define TBEGIN 28
204#define TEND 29
205
206
207#define BASESYNTAX (basesyntax + SYNBASE)
208#define DQSYNTAX (dqsyntax + SYNBASE)
209#define SQSYNTAX (sqsyntax + SYNBASE)
210#define ARISYNTAX (arisyntax + SYNBASE)
211
212/* control characters in argument strings */
213#define CTLESC '\201'
214#define CTLVAR '\202'
215#define CTLENDVAR '\203'
216#define CTLBACKQ '\204'
217#define CTLQUOTE 01 /* ored with CTLBACKQ code if in quotes */
218/* CTLBACKQ | CTLQUOTE == '\205' */
219#define CTLARI '\206'
220#define CTLENDARI '\207'
221#define CTLQUOTEMARK '\210'
222
223#define is_digit(c) ((((unsigned char)(c)) - '0') <= 9)
224#define is_alpha(c) (((c) < CTLESC || (c) > CTLENDARI) && isalpha((unsigned char) (c)))
225#define is_name(c) (((c) < CTLESC || (c) > CTLENDARI) && ((c) == '_' || isalpha((unsigned char) (c))))
226#define is_in_name(c) (((c) < CTLESC || (c) > CTLENDARI) && ((c) == '_' || isalnum((unsigned char) (c))))
227#define is_special(c) ((is_type+SYNBASE)[c] & (ISSPECL|ISDIGIT))
228#define digit_val(c) ((c) - '0')
83 229
84 230
85#define _DIAGASSERT(x) 231#define _DIAGASSERT(x)
86 232
87#define ATABSIZE 39 233#define ATABSIZE 39
88 234
89#define S_DFL 1 /* default signal handling (SIG_DFL) */ 235#define S_DFL 1 /* default signal handling (SIG_DFL) */
90#define S_CATCH 2 /* signal is caught */ 236#define S_CATCH 2 /* signal is caught */
91#define S_IGN 3 /* signal is ignored (SIG_IGN) */ 237#define S_IGN 3 /* signal is ignored (SIG_IGN) */
92#define S_HARD_IGN 4 /* signal is ignored permenantly */ 238#define S_HARD_IGN 4 /* signal is ignored permenantly */
93#define S_RESET 5 /* temporary - to reset a hard ignored sig */ 239#define S_RESET 5 /* temporary - to reset a hard ignored sig */
240
241
242/* variable substitution byte (follows CTLVAR) */
243#define VSTYPE 0x0f /* type of variable substitution */
244#define VSNUL 0x10 /* colon--treat the empty string as unset */
245#define VSQUOTE 0x80 /* inside double quotes--suppress splitting */
246
247/* values of VSTYPE field */
248#define VSNORMAL 0x1 /* normal variable: $var or ${var} */
249#define VSMINUS 0x2 /* ${var-text} */
250#define VSPLUS 0x3 /* ${var+text} */
251#define VSQUESTION 0x4 /* ${var?message} */
252#define VSASSIGN 0x5 /* ${var=text} */
253#define VSTRIMLEFT 0x6 /* ${var#pattern} */
254#define VSTRIMLEFTMAX 0x7 /* ${var##pattern} */
255#define VSTRIMRIGHT 0x8 /* ${var%pattern} */
256#define VSTRIMRIGHTMAX 0x9 /* ${var%%pattern} */
257#define VSLENGTH 0xa /* ${#var} */
258
259/* flags passed to redirect */
260#define REDIR_PUSH 01 /* save previous values of file descriptors */
261#define REDIR_BACKQ 02 /* save the command output in memory */
262
263/*
264 * BSD setjmp saves the signal mask, which violates ANSI C and takes time,
265 * so we use _setjmp instead.
266 */
267
268#if !defined(__GLIBC__)
269#define setjmp(jmploc) _setjmp(jmploc)
270#define longjmp(jmploc, val) _longjmp(jmploc, val)
271#endif
272
273/*
274 * Most machines require the value returned from malloc to be aligned
275 * in some way. The following macro will get this right on many machines.
276 */
277
278#ifndef ALIGN
279union align {
280 int i;
281 char *cp;
282};
283
284#define ALIGN(nbytes) (((nbytes) + sizeof(union align) - 1) & ~(sizeof(union align) - 1))
285#endif
286
287#ifdef BB_LOCALE_SUPPORT
288#include <locale.h>
289static void change_lc_all(const char *value);
290static void change_lc_ctype(const char *value);
291#endif
292
293/*
294 * These macros allow the user to suspend the handling of interrupt signals
295 * over a period of time. This is similar to SIGHOLD to or sigblock, but
296 * much more efficient and portable. (But hacking the kernel is so much
297 * more fun than worrying about efficiency and portability. :-))
298 */
299
300static void onint (void);
301static volatile int suppressint;
302static volatile int intpending;
303
304#define INTOFF suppressint++
305#ifdef ASH_BBAPPS_AS_BUILTINS
306#define INTON { if (--suppressint == 0 && intpending) onint(); }
307#else
308static void __inton (void);
309#define INTON __inton()
310#endif
311#define FORCEINTON {suppressint = 0; if (intpending) onint();}
312#define CLEAR_PENDING_INT intpending = 0
313#define int_pending() intpending
314
315
316typedef void *pointer;
317#ifndef NULL
318#define NULL (void *)0
319#endif
320
321static inline pointer ckmalloc (int sz) { return xmalloc(sz); }
322static inline pointer ckrealloc(void *p, int sz) { return xrealloc(p, sz); }
323static inline char * savestr (const char *s) { return xstrdup(s); }
324
325static pointer stalloc (int);
326static void stunalloc (pointer);
327static void ungrabstackstr (char *, char *);
328static char * growstackstr(void);
329static char *sstrdup (const char *);
330
331/*
332 * Parse trees for commands are allocated in lifo order, so we use a stack
333 * to make this more efficient, and also to avoid all sorts of exception
334 * handling code to handle interrupts in the middle of a parse.
335 *
336 * The size 504 was chosen because the Ultrix malloc handles that size
337 * well.
338 */
339
340#define MINSIZE 504 /* minimum size of a block */
341
342
343struct stack_block {
344 struct stack_block *prev;
345 char space[MINSIZE];
346};
347
348static struct stack_block stackbase;
349static struct stack_block *stackp = &stackbase;
350static struct stackmark *markp;
351static char *stacknxt = stackbase.space;
352static int stacknleft = MINSIZE;
353
354
355#define equal(s1, s2) (strcmp(s1, s2) == 0)
356
357#define stackblock() stacknxt
358#define stackblocksize() stacknleft
359#define STARTSTACKSTR(p) p = stackblock(), sstrnleft = stackblocksize()
360#define STPUTC(c, p) (--sstrnleft >= 0? (*p++ = (c)) : (p = growstackstr(), *p++ = (c)))
361#define CHECKSTRSPACE(n, p) { if (sstrnleft < n) p = makestrspace(n); }
362#define USTPUTC(c, p) (--sstrnleft, *p++ = (c))
363#define STACKSTRNUL(p) (sstrnleft == 0? (p = growstackstr(), *p = '\0') : (*p = '\0'))
364#define STUNPUTC(p) (++sstrnleft, --p)
365#define STTOPC(p) p[-1]
366#define STADJUST(amount, p) (p += (amount), sstrnleft -= (amount))
367#define grabstackstr(p) stalloc(stackblocksize() - sstrnleft)
368
369#define ckfree(p) free((pointer)(p))
370
371static char * makestrspace(size_t newlen);
372
373#ifdef DEBUG
374#define TRACE(param) trace param
375static void trace (const char *, ...);
376static void trargs (char **);
377static void showtree (union node *);
378static void trputc (int);
379static void trputs (const char *);
380static void opentrace (void);
381#else
382#define TRACE(param)
383#endif
384
385#define NSEMI 0
386#define NCMD 1
387#define NPIPE 2
388#define NREDIR 3
389#define NBACKGND 4
390#define NSUBSHELL 5
391#define NAND 6
392#define NOR 7
393#define NIF 8
394#define NWHILE 9
395#define NUNTIL 10
396#define NFOR 11
397#define NCASE 12
398#define NCLIST 13
399#define NDEFUN 14
400#define NARG 15
401#define NTO 16
402#define NFROM 17
403#define NFROMTO 18
404#define NAPPEND 19
405#define NTOOV 20
406#define NTOFD 21
407#define NFROMFD 22
408#define NHERE 23
409#define NXHERE 24
410#define NNOT 25
411
412/*
413 * expandarg() flags
414 */
415#define EXP_FULL 0x1 /* perform word splitting & file globbing */
416#define EXP_TILDE 0x2 /* do normal tilde expansion */
417#define EXP_VARTILDE 0x4 /* expand tildes in an assignment */
418#define EXP_REDIR 0x8 /* file glob for a redirection (1 match only) */
419#define EXP_CASE 0x10 /* keeps quotes around for CASE pattern */
420#define EXP_RECORD 0x20 /* need to record arguments for ifs breakup */
421
422
423#define NOPTS 16
424
425static char optet_vals[NOPTS];
426
427static const char * const optlist[NOPTS] = {
428 "e" "errexit",
429 "f" "noglob",
430 "I" "ignoreeof",
431 "i" "interactive",
432 "m" "monitor",
433 "n" "noexec",
434 "s" "stdin",
435 "x" "xtrace",
436 "v" "verbose",
437 "V" "vi",
438 "E" "emacs",
439 "C" "noclobber",
440 "a" "allexport",
441 "b" "notify",
442 "u" "nounset",
443 "q" "quietprofile"
444};
445
446#define optent_name(optent) (optent+1)
447#define optent_letter(optent) optent[0]
448#define optent_val(optent) optet_vals[optent]
449
450#define eflag optent_val(0)
451#define fflag optent_val(1)
452#define Iflag optent_val(2)
453#define iflag optent_val(3)
454#define mflag optent_val(4)
455#define nflag optent_val(5)
456#define sflag optent_val(6)
457#define xflag optent_val(7)
458#define vflag optent_val(8)
459#define Vflag optent_val(9)
460#define Eflag optent_val(10)
461#define Cflag optent_val(11)
462#define aflag optent_val(12)
463#define bflag optent_val(13)
464#define uflag optent_val(14)
465#define qflag optent_val(15)
466
467
468/* Mode argument to forkshell. Don't change FORK_FG or FORK_BG. */
469#define FORK_FG 0
470#define FORK_BG 1
471#define FORK_NOJOB 2
472
473
474struct nbinary {
475 int type;
476 union node *ch1;
477 union node *ch2;
478};
479
480
481struct ncmd {
482 int type;
483 int backgnd;
484 union node *assign;
485 union node *args;
486 union node *redirect;
487};
488
489
490struct npipe {
491 int type;
492 int backgnd;
493 struct nodelist *cmdlist;
494};
495
496
497struct nredir {
498 int type;
499 union node *n;
500 union node *redirect;
501};
502
503
504struct nif {
505 int type;
506 union node *test;
507 union node *ifpart;
508 union node *elsepart;
509};
510
511
512struct nfor {
513 int type;
514 union node *args;
515 union node *body;
516 char *var;
517};
518
519
520struct ncase {
521 int type;
522 union node *expr;
523 union node *cases;
524};
525
526
527struct nclist {
528 int type;
529 union node *next;
530 union node *pattern;
531 union node *body;
532};
533
534
535struct narg {
536 int type;
537 union node *next;
538 char *text;
539 struct nodelist *backquote;
540};
541
542
543struct nfile {
544 int type;
545 union node *next;
546 int fd;
547 union node *fname;
548 char *expfname;
549};
550
551
552struct ndup {
553 int type;
554 union node *next;
555 int fd;
556 int dupfd;
557 union node *vname;
558};
559
560
561struct nhere {
562 int type;
563 union node *next;
564 int fd;
565 union node *doc;
566};
567
568
569struct nnot {
570 int type;
571 union node *com;
572};
573
574
575union node {
576 int type;
577 struct nbinary nbinary;
578 struct ncmd ncmd;
579 struct npipe npipe;
580 struct nredir nredir;
581 struct nif nif;
582 struct nfor nfor;
583 struct ncase ncase;
584 struct nclist nclist;
585 struct narg narg;
586 struct nfile nfile;
587 struct ndup ndup;
588 struct nhere nhere;
589 struct nnot nnot;
590};
591
592
593struct nodelist {
594 struct nodelist *next;
595 union node *n;
596};
597
598struct backcmd { /* result of evalbackcmd */
599 int fd; /* file descriptor to read from */
600 char *buf; /* buffer */
601 int nleft; /* number of chars in buffer */
602 struct job *jp; /* job structure for command */
603};
604
605struct cmdentry {
606 int cmdtype;
607 union param {
608 int index;
609 union node *func;
610 const struct builtincmd *cmd;
611 } u;
612};
613
614struct strlist {
615 struct strlist *next;
616 char *text;
617};
618
619
620struct arglist {
621 struct strlist *list;
622 struct strlist **lastp;
623};
624
625struct strpush {
626 struct strpush *prev; /* preceding string on stack */
627 char *prevstring;
628 int prevnleft;
629#ifdef ASH_ALIAS
630 struct alias *ap; /* if push was associated with an alias */
631#endif
632 char *string; /* remember the string since it may change */
633};
634
635struct parsefile {
636 struct parsefile *prev; /* preceding file on stack */
637 int linno; /* current line */
638 int fd; /* file descriptor (or -1 if string) */
639 int nleft; /* number of chars left in this line */
640 int lleft; /* number of chars left in this buffer */
641 char *nextc; /* next char in buffer */
642 char *buf; /* input buffer */
643 struct strpush *strpush; /* for pushing strings at this level */
644 struct strpush basestrpush; /* so pushing one is fast */
645};
646
647struct stackmark {
648 struct stack_block *stackp;
649 char *stacknxt;
650 int stacknleft;
651 struct stackmark *marknext;
652};
653
654struct shparam {
655 int nparam; /* # of positional parameters (without $0) */
656 unsigned char malloc; /* if parameter list dynamically allocated */
657 char **p; /* parameter list */
658 int optind; /* next parameter to be processed by getopts */
659 int optoff; /* used by getopts */
660};
661
662struct output {
663#ifdef USE_GLIBC_STDIO
664 FILE *stream;
665#endif
666 char *nextc;
667 int nleft;
668 char *buf;
669 int bufsize;
670 int fd;
671 short flags;
672};
673
674#define OUTBUFSIZ BUFSIZ
675#define MEM_OUT -3 /* output to dynamically allocated memory */
676
677
678#ifdef USE_GLIBC_STDIO
679static struct output output = {NULL, NULL, 0, NULL, 0, 1, 0};
680static struct output errout = {NULL, NULL, 0, NULL, 0, 2, 0};
681static struct output memout = {NULL, NULL, 0, NULL, 0, MEM_OUT, 0};
682#else
683static struct output output = {NULL, 0, NULL, OUTBUFSIZ, 1, 0};
684static struct output errout = {NULL, 0, NULL, 0, 2, 0};
685static struct output memout = {NULL, 0, NULL, 0, MEM_OUT, 0};
686#endif
687static struct output *out1 = &output;
688static struct output *out2 = &errout;
689
690#ifndef USE_GLIBC_STDIO
691static void outcslow (char, struct output *);
692#endif
693static void flushall (void);
694static void flushout (struct output *);
695static void freestdout (void);
696static void outfmt (struct output *, const char *, ...)
697 __attribute__((__format__(__printf__,2,3)));
698static void out1fmt (const char *, ...)
699 __attribute__((__format__(__printf__,1,2)));
700static void fmtstr (char *, size_t, const char *, ...)
701 __attribute__((__format__(__printf__,3,4)));
702#ifndef USE_GLIBC_STDIO
703static void doformat (struct output *, const char *, va_list);
704#endif
705static int xwrite (int, const char *, int);
706#ifdef USE_GLIBC_STDIO
707static void initstreams (void);
708static void openmemout (void);
709static int __closememout (void);
710#endif
711
712static void outstr(const char *p, struct output *file);
713
714#define OUTPUT_ERR 01 /* error occurred on output */
715
716#ifdef USE_GLIBC_STDIO
717#define outc(c, o) putc((c), (o)->stream)
718#define doformat(d, f, a) vfprintf((d)->stream, (f), (a))
719#else
720#define outc(c, file) (--(file)->nleft < 0? outcslow((c), (file)) : (*(file)->nextc = (c), (file)->nextc++))
721#endif
722#define out1c(c) outc((c), out1)
723#define out2c(c) outc((c), out2)
724#define out1str(s) outstr((s), out1)
725#define out2str(s) outstr((s), out2)
726#define outerr(f) ((f)->flags & OUTPUT_ERR)
727
728/* syntax table used when not in quotes */
729static const char basesyntax[257] = {
730 CENDFILE, CSPCL, CWORD, CCTL,
731 CCTL, CCTL, CCTL, CCTL,
732 CCTL, CCTL, CCTL, CWORD,
733 CWORD, CWORD, CWORD, CWORD,
734 CWORD, CWORD, CWORD, CWORD,
735 CWORD, CWORD, CWORD, CWORD,
736 CWORD, CWORD, CWORD, CWORD,
737 CWORD, CWORD, CWORD, CWORD,
738 CWORD, CWORD, CWORD, CWORD,
739 CWORD, CWORD, CWORD, CWORD,
740 CWORD, CWORD, CWORD, CWORD,
741 CWORD, CWORD, CWORD, CWORD,
742 CWORD, CWORD, CWORD, CWORD,
743 CWORD, CWORD, CWORD, CWORD,
744 CWORD, CWORD, CWORD, CWORD,
745 CWORD, CWORD, CWORD, CWORD,
746 CWORD, CWORD, CWORD, CWORD,
747 CWORD, CWORD, CWORD, CWORD,
748 CWORD, CWORD, CWORD, CWORD,
749 CWORD, CWORD, CWORD, CWORD,
750 CWORD, CWORD, CWORD, CWORD,
751 CWORD, CWORD, CWORD, CWORD,
752 CWORD, CWORD, CWORD, CWORD,
753 CWORD, CWORD, CWORD, CWORD,
754 CWORD, CWORD, CWORD, CWORD,
755 CWORD, CWORD, CWORD, CWORD,
756 CWORD, CWORD, CWORD, CWORD,
757 CWORD, CWORD, CWORD, CWORD,
758 CWORD, CWORD, CWORD, CWORD,
759 CWORD, CWORD, CWORD, CWORD,
760 CWORD, CWORD, CWORD, CWORD,
761 CWORD, CWORD, CWORD, CWORD,
762 CWORD, CWORD, CWORD, CWORD,
763 CWORD, CWORD, CWORD, CWORD,
764 CWORD, CWORD, CWORD, CSPCL,
765 CNL, CWORD, CWORD, CWORD,
766 CWORD, CWORD, CWORD, CWORD,
767 CWORD, CWORD, CWORD, CWORD,
768 CWORD, CWORD, CWORD, CWORD,
769 CWORD, CWORD, CWORD, CWORD,
770 CWORD, CWORD, CSPCL, CWORD,
771 CDQUOTE, CWORD, CVAR, CWORD,
772 CSPCL, CSQUOTE, CSPCL, CSPCL,
773 CWORD, CWORD, CWORD, CWORD,
774 CWORD, CWORD, CWORD, CWORD,
775 CWORD, CWORD, CWORD, CWORD,
776 CWORD, CWORD, CWORD, CWORD,
777 CWORD, CSPCL, CSPCL, CWORD,
778 CSPCL, CWORD, CWORD, CWORD,
779 CWORD, CWORD, CWORD, CWORD,
780 CWORD, CWORD, CWORD, CWORD,
781 CWORD, CWORD, CWORD, CWORD,
782 CWORD, CWORD, CWORD, CWORD,
783 CWORD, CWORD, CWORD, CWORD,
784 CWORD, CWORD, CWORD, CWORD,
785 CWORD, CWORD, CBACK, CWORD,
786 CWORD, CWORD, CBQUOTE, CWORD,
787 CWORD, CWORD, CWORD, CWORD,
788 CWORD, CWORD, CWORD, CWORD,
789 CWORD, CWORD, CWORD, CWORD,
790 CWORD, CWORD, CWORD, CWORD,
791 CWORD, CWORD, CWORD, CWORD,
792 CWORD, CWORD, CWORD, CWORD,
793 CWORD, CWORD, CSPCL, CENDVAR,
794 CWORD
795};
796
797/* syntax table used when in double quotes */
798static const char dqsyntax[257] = {
799 CENDFILE, CIGN, CWORD, CCTL,
800 CCTL, CCTL, CCTL, CCTL,
801 CCTL, CCTL, CCTL, CWORD,
802 CWORD, CWORD, CWORD, CWORD,
803 CWORD, CWORD, CWORD, CWORD,
804 CWORD, CWORD, CWORD, CWORD,
805 CWORD, CWORD, CWORD, CWORD,
806 CWORD, CWORD, CWORD, CWORD,
807 CWORD, CWORD, CWORD, CWORD,
808 CWORD, CWORD, CWORD, CWORD,
809 CWORD, CWORD, CWORD, CWORD,
810 CWORD, CWORD, CWORD, CWORD,
811 CWORD, CWORD, CWORD, CWORD,
812 CWORD, CWORD, CWORD, CWORD,
813 CWORD, CWORD, CWORD, CWORD,
814 CWORD, CWORD, CWORD, CWORD,
815 CWORD, CWORD, CWORD, CWORD,
816 CWORD, CWORD, CWORD, CWORD,
817 CWORD, CWORD, CWORD, CWORD,
818 CWORD, CWORD, CWORD, CWORD,
819 CWORD, CWORD, CWORD, CWORD,
820 CWORD, CWORD, CWORD, CWORD,
821 CWORD, CWORD, CWORD, CWORD,
822 CWORD, CWORD, CWORD, CWORD,
823 CWORD, CWORD, CWORD, CWORD,
824 CWORD, CWORD, CWORD, CWORD,
825 CWORD, CWORD, CWORD, CWORD,
826 CWORD, CWORD, CWORD, CWORD,
827 CWORD, CWORD, CWORD, CWORD,
828 CWORD, CWORD, CWORD, CWORD,
829 CWORD, CWORD, CWORD, CWORD,
830 CWORD, CWORD, CWORD, CWORD,
831 CWORD, CWORD, CWORD, CWORD,
832 CWORD, CWORD, CWORD, CWORD,
833 CWORD, CWORD, CWORD, CWORD,
834 CNL, CWORD, CWORD, CWORD,
835 CWORD, CWORD, CWORD, CWORD,
836 CWORD, CWORD, CWORD, CWORD,
837 CWORD, CWORD, CWORD, CWORD,
838 CWORD, CWORD, CWORD, CWORD,
839 CWORD, CWORD, CWORD, CCTL,
840 CENDQUOTE,CWORD, CVAR, CWORD,
841 CWORD, CWORD, CWORD, CWORD,
842 CCTL, CWORD, CWORD, CCTL,
843 CWORD, CCTL, CWORD, CWORD,
844 CWORD, CWORD, CWORD, CWORD,
845 CWORD, CWORD, CWORD, CWORD,
846 CCTL, CWORD, CWORD, CCTL,
847 CWORD, CCTL, CWORD, CWORD,
848 CWORD, CWORD, CWORD, CWORD,
849 CWORD, CWORD, CWORD, CWORD,
850 CWORD, CWORD, CWORD, CWORD,
851 CWORD, CWORD, CWORD, CWORD,
852 CWORD, CWORD, CWORD, CWORD,
853 CWORD, CWORD, CWORD, CWORD,
854 CWORD, CCTL, CBACK, CCTL,
855 CWORD, CWORD, CBQUOTE, CWORD,
856 CWORD, CWORD, CWORD, CWORD,
857 CWORD, CWORD, CWORD, CWORD,
858 CWORD, CWORD, CWORD, CWORD,
859 CWORD, CWORD, CWORD, CWORD,
860 CWORD, CWORD, CWORD, CWORD,
861 CWORD, CWORD, CWORD, CWORD,
862 CWORD, CWORD, CWORD, CENDVAR,
863 CCTL
864};
865
866/* syntax table used when in single quotes */
867static const char sqsyntax[257] = {
868 CENDFILE, CIGN, CWORD, CCTL,
869 CCTL, CCTL, CCTL, CCTL,
870 CCTL, CCTL, CCTL, CWORD,
871 CWORD, CWORD, CWORD, CWORD,
872 CWORD, CWORD, CWORD, CWORD,
873 CWORD, CWORD, CWORD, CWORD,
874 CWORD, CWORD, CWORD, CWORD,
875 CWORD, CWORD, CWORD, CWORD,
876 CWORD, CWORD, CWORD, CWORD,
877 CWORD, CWORD, CWORD, CWORD,
878 CWORD, CWORD, CWORD, CWORD,
879 CWORD, CWORD, CWORD, CWORD,
880 CWORD, CWORD, CWORD, CWORD,
881 CWORD, CWORD, CWORD, CWORD,
882 CWORD, CWORD, CWORD, CWORD,
883 CWORD, CWORD, CWORD, CWORD,
884 CWORD, CWORD, CWORD, CWORD,
885 CWORD, CWORD, CWORD, CWORD,
886 CWORD, CWORD, CWORD, CWORD,
887 CWORD, CWORD, CWORD, CWORD,
888 CWORD, CWORD, CWORD, CWORD,
889 CWORD, CWORD, CWORD, CWORD,
890 CWORD, CWORD, CWORD, CWORD,
891 CWORD, CWORD, CWORD, CWORD,
892 CWORD, CWORD, CWORD, CWORD,
893 CWORD, CWORD, CWORD, CWORD,
894 CWORD, CWORD, CWORD, CWORD,
895 CWORD, CWORD, CWORD, CWORD,
896 CWORD, CWORD, CWORD, CWORD,
897 CWORD, CWORD, CWORD, CWORD,
898 CWORD, CWORD, CWORD, CWORD,
899 CWORD, CWORD, CWORD, CWORD,
900 CWORD, CWORD, CWORD, CWORD,
901 CWORD, CWORD, CWORD, CWORD,
902 CWORD, CWORD, CWORD, CWORD,
903 CNL, CWORD, CWORD, CWORD,
904 CWORD, CWORD, CWORD, CWORD,
905 CWORD, CWORD, CWORD, CWORD,
906 CWORD, CWORD, CWORD, CWORD,
907 CWORD, CWORD, CWORD, CWORD,
908 CWORD, CWORD, CWORD, CCTL,
909 CWORD, CWORD, CWORD, CWORD,
910 CWORD, CENDQUOTE,CWORD, CWORD,
911 CCTL, CWORD, CWORD, CCTL,
912 CWORD, CCTL, CWORD, CWORD,
913 CWORD, CWORD, CWORD, CWORD,
914 CWORD, CWORD, CWORD, CWORD,
915 CCTL, CWORD, CWORD, CCTL,
916 CWORD, CCTL, CWORD, CWORD,
917 CWORD, CWORD, CWORD, CWORD,
918 CWORD, CWORD, CWORD, CWORD,
919 CWORD, CWORD, CWORD, CWORD,
920 CWORD, CWORD, CWORD, CWORD,
921 CWORD, CWORD, CWORD, CWORD,
922 CWORD, CWORD, CWORD, CWORD,
923 CWORD, CCTL, CCTL, CCTL,
924 CWORD, CWORD, CWORD, CWORD,
925 CWORD, CWORD, CWORD, CWORD,
926 CWORD, CWORD, CWORD, CWORD,
927 CWORD, CWORD, CWORD, CWORD,
928 CWORD, CWORD, CWORD, CWORD,
929 CWORD, CWORD, CWORD, CWORD,
930 CWORD, CWORD, CWORD, CWORD,
931 CWORD, CWORD, CWORD, CWORD,
932 CCTL
933};
94 934
935/* syntax table used when in arithmetic */
936static const char arisyntax[257] = {
937 CENDFILE, CIGN, CWORD, CCTL,
938 CCTL, CCTL, CCTL, CCTL,
939 CCTL, CCTL, CCTL, CWORD,
940 CWORD, CWORD, CWORD, CWORD,
941 CWORD, CWORD, CWORD, CWORD,
942 CWORD, CWORD, CWORD, CWORD,
943 CWORD, CWORD, CWORD, CWORD,
944 CWORD, CWORD, CWORD, CWORD,
945 CWORD, CWORD, CWORD, CWORD,
946 CWORD, CWORD, CWORD, CWORD,
947 CWORD, CWORD, CWORD, CWORD,
948 CWORD, CWORD, CWORD, CWORD,
949 CWORD, CWORD, CWORD, CWORD,
950 CWORD, CWORD, CWORD, CWORD,
951 CWORD, CWORD, CWORD, CWORD,
952 CWORD, CWORD, CWORD, CWORD,
953 CWORD, CWORD, CWORD, CWORD,
954 CWORD, CWORD, CWORD, CWORD,
955 CWORD, CWORD, CWORD, CWORD,
956 CWORD, CWORD, CWORD, CWORD,
957 CWORD, CWORD, CWORD, CWORD,
958 CWORD, CWORD, CWORD, CWORD,
959 CWORD, CWORD, CWORD, CWORD,
960 CWORD, CWORD, CWORD, CWORD,
961 CWORD, CWORD, CWORD, CWORD,
962 CWORD, CWORD, CWORD, CWORD,
963 CWORD, CWORD, CWORD, CWORD,
964 CWORD, CWORD, CWORD, CWORD,
965 CWORD, CWORD, CWORD, CWORD,
966 CWORD, CWORD, CWORD, CWORD,
967 CWORD, CWORD, CWORD, CWORD,
968 CWORD, CWORD, CWORD, CWORD,
969 CWORD, CWORD, CWORD, CWORD,
970 CWORD, CWORD, CWORD, CWORD,
971 CWORD, CWORD, CWORD, CWORD,
972 CNL, CWORD, CWORD, CWORD,
973 CWORD, CWORD, CWORD, CWORD,
974 CWORD, CWORD, CWORD, CWORD,
975 CWORD, CWORD, CWORD, CWORD,
976 CWORD, CWORD, CWORD, CWORD,
977 CWORD, CWORD, CWORD, CWORD,
978 CDQUOTE, CWORD, CVAR, CWORD,
979 CWORD, CSQUOTE, CLP, CRP,
980 CWORD, CWORD, CWORD, CWORD,
981 CWORD, CWORD, CWORD, CWORD,
982 CWORD, CWORD, CWORD, CWORD,
983 CWORD, CWORD, CWORD, CWORD,
984 CWORD, CWORD, CWORD, CWORD,
985 CWORD, CWORD, CWORD, CWORD,
986 CWORD, CWORD, CWORD, CWORD,
987 CWORD, CWORD, CWORD, CWORD,
988 CWORD, CWORD, CWORD, CWORD,
989 CWORD, CWORD, CWORD, CWORD,
990 CWORD, CWORD, CWORD, CWORD,
991 CWORD, CWORD, CWORD, CWORD,
992 CWORD, CWORD, CBACK, CWORD,
993 CWORD, CWORD, CBQUOTE, CWORD,
994 CWORD, CWORD, CWORD, CWORD,
995 CWORD, CWORD, CWORD, CWORD,
996 CWORD, CWORD, CWORD, CWORD,
997 CWORD, CWORD, CWORD, CWORD,
998 CWORD, CWORD, CWORD, CWORD,
999 CWORD, CWORD, CWORD, CWORD,
1000 CWORD, CWORD, CWORD, CENDVAR,
1001 CWORD
1002};
95 1003
1004/* character classification table */
1005static const char is_type[257] = {
1006 0, 0, 0, 0,
1007 0, 0, 0, 0,
1008 0, 0, 0, 0,
1009 0, 0, 0, 0,
1010 0, 0, 0, 0,
1011 0, 0, 0, 0,
1012 0, 0, 0, 0,
1013 0, 0, 0, 0,
1014 0, 0, 0, 0,
1015 0, 0, 0, 0,
1016 0, 0, 0, 0,
1017 0, 0, 0, 0,
1018 0, 0, 0, 0,
1019 0, 0, 0, 0,
1020 0, 0, 0, 0,
1021 0, 0, 0, 0,
1022 0, 0, 0, 0,
1023 0, 0, 0, 0,
1024 0, 0, 0, 0,
1025 0, 0, 0, 0,
1026 0, 0, 0, 0,
1027 0, 0, 0, 0,
1028 0, 0, 0, 0,
1029 0, 0, 0, 0,
1030 0, 0, 0, 0,
1031 0, 0, 0, 0,
1032 0, 0, 0, 0,
1033 0, 0, 0, 0,
1034 0, 0, 0, 0,
1035 0, 0, 0, 0,
1036 0, 0, 0, 0,
1037 0, 0, 0, 0,
1038 0, 0, 0, 0,
1039 0, 0, 0, 0,
1040 0, 0, 0, 0,
1041 0, 0, 0, 0,
1042 0, 0, 0, 0,
1043 0, 0, 0, 0,
1044 0, 0, 0, 0,
1045 0, 0, 0, 0,
1046 0, 0, 0, ISSPECL,
1047 0, ISSPECL, ISSPECL, 0,
1048 0, 0, 0, 0,
1049 ISSPECL, 0, 0, ISSPECL,
1050 0, 0, ISDIGIT, ISDIGIT,
1051 ISDIGIT, ISDIGIT, ISDIGIT, ISDIGIT,
1052 ISDIGIT, ISDIGIT, ISDIGIT, ISDIGIT,
1053 0, 0, 0, 0,
1054 0, ISSPECL, ISSPECL, ISUPPER,
1055 ISUPPER, ISUPPER, ISUPPER, ISUPPER,
1056 ISUPPER, ISUPPER, ISUPPER, ISUPPER,
1057 ISUPPER, ISUPPER, ISUPPER, ISUPPER,
1058 ISUPPER, ISUPPER, ISUPPER, ISUPPER,
1059 ISUPPER, ISUPPER, ISUPPER, ISUPPER,
1060 ISUPPER, ISUPPER, ISUPPER, ISUPPER,
1061 ISUPPER, 0, 0, 0,
1062 0, ISUNDER, 0, ISLOWER,
1063 ISLOWER, ISLOWER, ISLOWER, ISLOWER,
1064 ISLOWER, ISLOWER, ISLOWER, ISLOWER,
1065 ISLOWER, ISLOWER, ISLOWER, ISLOWER,
1066 ISLOWER, ISLOWER, ISLOWER, ISLOWER,
1067 ISLOWER, ISLOWER, ISLOWER, ISLOWER,
1068 ISLOWER, ISLOWER, ISLOWER, ISLOWER,
1069 ISLOWER, 0, 0, 0,
1070 0
1071};
96 1072
97struct alias *atab[ATABSIZE]; 1073/* Array indicating which tokens mark the end of a list */
1074static const char tokendlist[] = {
1075 1,
1076 0,
1077 0,
1078 0,
1079 0,
1080 0,
1081 0,
1082 0,
1083 1,
1084 1,
1085 1,
1086 0,
1087 0,
1088 0,
1089 0,
1090 0,
1091 1,
1092 1,
1093 1,
1094 1,
1095 1,
1096 1,
1097 0,
1098 0,
1099 0,
1100 1,
1101 0,
1102 0,
1103 0,
1104 1,
1105};
98 1106
99static void setalias __P((char *, char *)); 1107static const char *const tokname[] = {
100static struct alias **hashalias __P((const char *)); 1108 "end of file",
101static struct alias *freealias __P((struct alias *)); 1109 "newline",
102static struct alias **__lookupalias __P((const char *)); 1110 "\";\"",
103static char *trap[NSIG]; /* trap handler commands */ 1111 "\"&\"",
104static char sigmode[NSIG - 1]; /* current value of signal */ 1112 "\"&&\"",
105static char gotsig[NSIG - 1]; /* indicates specified signal received */ 1113 "\"||\"",
106static int pendingsigs; /* indicates some signal received */ 1114 "\"|\"",
1115 "\"(\"",
1116 "\")\"",
1117 "\";;\"",
1118 "\"`\"",
1119 "redirection",
1120 "word",
1121 "assignment",
1122 "\"!\"",
1123 "\"case\"",
1124 "\"do\"",
1125 "\"done\"",
1126 "\"elif\"",
1127 "\"else\"",
1128 "\"esac\"",
1129 "\"fi\"",
1130 "\"for\"",
1131 "\"if\"",
1132 "\"in\"",
1133 "\"then\"",
1134 "\"until\"",
1135 "\"while\"",
1136 "\"{\"",
1137 "\"}\"",
1138};
107 1139
1140#define KWDOFFSET 14
1141
1142static const char *const parsekwd[] = {
1143 "!",
1144 "case",
1145 "do",
1146 "done",
1147 "elif",
1148 "else",
1149 "esac",
1150 "fi",
1151 "for",
1152 "if",
1153 "in",
1154 "then",
1155 "until",
1156 "while",
1157 "{",
1158 "}"
1159};
1160
1161
1162static int plinno = 1; /* input line number */
1163
1164static int parselleft; /* copy of parsefile->lleft */
1165
1166static struct parsefile basepf; /* top level input file */
1167static char basebuf[BUFSIZ]; /* buffer for top level input file */
1168static struct parsefile *parsefile = &basepf; /* current input file */
1169
1170/*
1171 * NEOF is returned by parsecmd when it encounters an end of file. It
1172 * must be distinct from NULL, so we use the address of a variable that
1173 * happens to be handy.
1174 */
1175
1176static int tokpushback; /* last token pushed back */
1177#define NEOF ((union node *)&tokpushback)
1178static int checkkwd; /* 1 == check for kwds, 2 == also eat newlines */
1179
1180
1181static void error (const char *, ...) __attribute__((__noreturn__));
1182static void exerror (int, const char *, ...) __attribute__((__noreturn__));
1183static void shellexec (char **, char **, const char *, int)
1184 __attribute__((noreturn));
1185static void exitshell (int) __attribute__((noreturn));
1186
1187static int goodname(const char *);
1188static void ignoresig (int);
1189static void onsig (int);
1190static void dotrap (void);
1191static int decode_signal (const char *, int);
1192
1193static void shprocvar(void);
1194static void deletefuncs(void);
1195static void setparam (char **);
1196static void freeparam (volatile struct shparam *);
1197
1198/* reasons for skipping commands (see comment on breakcmd routine) */
1199#define SKIPBREAK 1
1200#define SKIPCONT 2
1201#define SKIPFUNC 3
1202#define SKIPFILE 4
1203
1204/* values of cmdtype */
1205#define CMDUNKNOWN -1 /* no entry in table for command */
1206#define CMDNORMAL 0 /* command is an executable program */
1207#define CMDBUILTIN 1 /* command is a shell builtin */
1208#define CMDFUNCTION 2 /* command is a shell function */
1209
1210#define DO_ERR 1 /* find_command prints errors */
1211#define DO_ABS 2 /* find_command checks absolute paths */
1212#define DO_NOFUN 4 /* find_command ignores functions */
1213#define DO_BRUTE 8 /* find_command ignores hash table */
1214
1215/*
1216 * Shell variables.
1217 */
1218
1219/* flags */
1220#define VEXPORT 0x01 /* variable is exported */
1221#define VREADONLY 0x02 /* variable cannot be modified */
1222#define VSTRFIXED 0x04 /* variable struct is staticly allocated */
1223#define VTEXTFIXED 0x08 /* text is staticly allocated */
1224#define VSTACK 0x10 /* text is allocated on the stack */
1225#define VUNSET 0x20 /* the variable is not set */
1226#define VNOFUNC 0x40 /* don't call the callback function */
1227
1228
1229struct var {
1230 struct var *next; /* next entry in hash list */
1231 int flags; /* flags are defined above */
1232 char *text; /* name=value */
1233 void (*func) (const char *);
1234 /* function to be called when */
1235 /* the variable gets set/unset */
1236};
1237
1238struct localvar {
1239 struct localvar *next; /* next local variable in list */
1240 struct var *vp; /* the variable that was made local */
1241 int flags; /* saved flags */
1242 char *text; /* saved text */
1243};
1244
1245
1246#if defined(__GLIBC__) && !defined(FNMATCH_BROKEN)
1247#define rmescapes(p) _rmescapes((p), 0)
1248static char *_rmescapes (char *, int);
1249#else
1250static void rmescapes (char *);
1251#endif
1252
1253static int casematch (union node *, const char *);
1254static void clearredir(void);
1255static void popstring(void);
1256static void readcmdfile (const char *);
1257
1258static int number (const char *);
1259static int is_number (const char *, int *num);
1260static char *single_quote (const char *);
1261static int nextopt (const char *);
1262
1263static void redirect (union node *, int);
1264static void popredir (void);
1265static int dup_as_newfd (int, int);
1266
1267static void changepath(const char *newval);
1268static void getoptsreset(const char *value);
1269
1270
1271static int parsenleft; /* copy of parsefile->nleft */
1272static char *parsenextc; /* copy of parsefile->nextc */
1273static int rootpid; /* pid of main shell */
1274static int rootshell; /* true if we aren't a child of the main shell */
1275
1276static const char spcstr[] = " ";
1277static const char snlfmt[] = "%s\n";
1278
1279static int sstrnleft;
1280static int herefd = -1;
1281
1282static struct localvar *localvars;
1283
1284static struct var vifs;
1285static struct var vmail;
1286static struct var vmpath;
1287static struct var vpath;
1288static struct var vps1;
1289static struct var vps2;
1290static struct var voptind;
1291#ifdef BB_LOCALE_SUPPORT
1292static struct var vlc_all;
1293static struct var vlc_ctype;
1294#endif
1295
1296struct varinit {
1297 struct var *var;
1298 int flags;
1299 const char *text;
1300 void (*func) (const char *);
1301};
1302
1303static const char defpathvar[] =
1304 "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin";
1305#define defpath (defpathvar + 5)
1306
1307#ifdef IFS_BROKEN
1308static const char defifsvar[] = "IFS= \t\n";
1309#define defifs (defifsvar + 4)
1310#else
1311static const char defifs[] = " \t\n";
1312#endif
1313
1314static const struct varinit varinit[] = {
1315#ifdef IFS_BROKEN
1316 { &vifs, VSTRFIXED|VTEXTFIXED, defifsvar,
1317#else
1318 { &vifs, VSTRFIXED|VTEXTFIXED|VUNSET, "IFS=",
1319#endif
1320 NULL },
1321 { &vmail, VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL=",
1322 NULL },
1323 { &vmpath, VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH=",
1324 NULL },
1325 { &vpath, VSTRFIXED|VTEXTFIXED, defpathvar,
1326 changepath },
1327 /*
1328 * vps1 depends on uid
1329 */
1330 { &vps2, VSTRFIXED|VTEXTFIXED, "PS2=> ",
1331 NULL },
1332 { &voptind, VSTRFIXED|VTEXTFIXED, "OPTIND=1",
1333 getoptsreset },
1334#ifdef BB_LOCALE_SUPPORT
1335 { &vlc_all, VSTRFIXED|VTEXTFIXED|VUNSET, "LC_ALL=",
1336 change_lc_all },
1337 { &vlc_ctype, VSTRFIXED|VTEXTFIXED|VUNSET, "LC_CTYPE=",
1338 change_lc_ctype },
1339#endif
1340 { NULL, 0, NULL,
1341 NULL }
1342};
1343
1344#define VTABSIZE 39
1345
1346static struct var *vartab[VTABSIZE];
1347
1348/*
1349 * The following macros access the values of the above variables.
1350 * They have to skip over the name. They return the null string
1351 * for unset variables.
1352 */
1353
1354#define ifsval() (vifs.text + 4)
1355#define ifsset() ((vifs.flags & VUNSET) == 0)
1356#define mailval() (vmail.text + 5)
1357#define mpathval() (vmpath.text + 9)
1358#define pathval() (vpath.text + 5)
1359#define ps1val() (vps1.text + 4)
1360#define ps2val() (vps2.text + 4)
1361#define optindval() (voptind.text + 7)
1362
1363#define mpathset() ((vmpath.flags & VUNSET) == 0)
1364
1365static void initvar (void);
1366static void setvar (const char *, const char *, int);
1367static void setvareq (char *, int);
1368static void listsetvar (struct strlist *);
1369static char *lookupvar (const char *);
1370static char *bltinlookup (const char *);
1371static char **environment (void);
1372static int showvarscmd (int, char **);
1373static void mklocal (char *);
1374static void poplocalvars (void);
1375static int unsetvar (const char *);
1376static int varequal (const char *, const char *);
1377
1378
1379static char *arg0; /* value of $0 */
1380static struct shparam shellparam; /* current positional parameters */
1381static char **argptr; /* argument list for builtin commands */
1382static char *optionarg; /* set by nextopt (like getopt) */
1383static char *optptr; /* used by nextopt */
1384static char *minusc; /* argument to -c option */
1385
1386
1387#ifdef ASH_ALIAS
1388
1389#define ALIASINUSE 1
1390#define ALIASDEAD 2
1391
1392struct alias {
1393 struct alias *next;
1394 char *name;
1395 char *val;
1396 int flag;
1397};
1398
1399static struct alias *atab[ATABSIZE];
1400
1401static void setalias (char *, char *);
1402static struct alias **hashalias (const char *);
1403static struct alias *freealias (struct alias *);
1404static struct alias **__lookupalias (const char *);
108 1405
109static void 1406static void
110setalias(name, val) 1407setalias(name, val)
@@ -119,7 +1416,7 @@ setalias(name, val)
119 if (!(ap->flag & ALIASINUSE)) { 1416 if (!(ap->flag & ALIASINUSE)) {
120 ckfree(ap->val); 1417 ckfree(ap->val);
121 } 1418 }
122 ap->val = savestr(val); 1419 ap->val = savestr(val);
123 ap->flag &= ~ALIASDEAD; 1420 ap->flag &= ~ALIASDEAD;
124 } else { 1421 } else {
125 /* not found */ 1422 /* not found */
@@ -134,9 +1431,8 @@ setalias(name, val)
134} 1431}
135 1432
136static int 1433static int
137unalias(name) 1434unalias(char *name)
138 char *name; 1435{
139 {
140 struct alias **app; 1436 struct alias **app;
141 1437
142 app = __lookupalias(name); 1438 app = __lookupalias(name);
@@ -151,16 +1447,9 @@ unalias(name)
151 return (1); 1447 return (1);
152} 1448}
153 1449
154#ifdef mkinit
155static void rmaliases __P((void));
156
157SHELLPROC {
158 rmaliases();
159}
160#endif
161
162static void 1450static void
163rmaliases() { 1451rmaliases(void)
1452{
164 struct alias *ap, **app; 1453 struct alias *ap, **app;
165 int i; 1454 int i;
166 1455
@@ -177,10 +1466,8 @@ rmaliases() {
177 INTON; 1466 INTON;
178} 1467}
179 1468
180struct alias * 1469static struct alias *
181lookupalias(name, check) 1470lookupalias(const char *name, int check)
182 const char *name;
183 int check;
184{ 1471{
185 struct alias *ap = *__lookupalias(name); 1472 struct alias *ap = *__lookupalias(name);
186 1473
@@ -189,14 +1476,21 @@ lookupalias(name, check)
189 return (ap); 1476 return (ap);
190} 1477}
191 1478
1479static void
1480printalias(const struct alias *ap) {
1481 char *p;
1482
1483 p = single_quote(ap->val);
1484 out1fmt("alias %s=%s\n", ap->name, p);
1485 stunalloc(p);
1486}
1487
192 1488
193/* 1489/*
194 * TODO - sort output 1490 * TODO - sort output
195 */ 1491 */
196static int 1492static int
197aliascmd(argc, argv) 1493aliascmd(int argc, char **argv)
198 int argc;
199 char **argv;
200{ 1494{
201 char *n, *v; 1495 char *n, *v;
202 int ret = 0; 1496 int ret = 0;
@@ -229,9 +1523,7 @@ aliascmd(argc, argv)
229} 1523}
230 1524
231static int 1525static int
232unaliascmd(argc, argv) 1526unaliascmd(int argc, char **argv)
233 int argc;
234 char **argv;
235{ 1527{
236 int i; 1528 int i;
237 1529
@@ -279,14 +1571,6 @@ freealias(struct alias *ap) {
279 return next; 1571 return next;
280} 1572}
281 1573
282static void
283printalias(const struct alias *ap) {
284 char *p;
285
286 p = single_quote(ap->val);
287 out1fmt("alias %s=%s\n", ap->name, p);
288 stunalloc(p);
289}
290 1574
291static struct alias ** 1575static struct alias **
292__lookupalias(const char *name) { 1576__lookupalias(const char *name) {
@@ -300,64 +1584,132 @@ __lookupalias(const char *name) {
300 1584
301 return app; 1585 return app;
302} 1586}
1587#endif
303 1588
304#ifdef ASH_MATH_SUPPORT 1589#ifdef ASH_MATH_SUPPORT
305/* The generated file arith.c has been snipped. If you want this 1590/* The generated file arith.c has been snipped. If you want this
306 * stuff back in, feel free to add it to your own copy. */ 1591 * stuff back in, feel free to add it to your own copy. */
307#endif 1592#define ARITH_NUM 257
1593#define ARITH_LPAREN 258
1594#define ARITH_RPAREN 259
1595#define ARITH_OR 260
1596#define ARITH_AND 261
1597#define ARITH_BOR 262
1598#define ARITH_BXOR 263
1599#define ARITH_BAND 264
1600#define ARITH_EQ 265
1601#define ARITH_NE 266
1602#define ARITH_LT 267
1603#define ARITH_GT 268
1604#define ARITH_GE 269
1605#define ARITH_LE 270
1606#define ARITH_LSHIFT 271
1607#define ARITH_RSHIFT 272
1608#define ARITH_ADD 273
1609#define ARITH_SUB 274
1610#define ARITH_MUL 275
1611#define ARITH_DIV 276
1612#define ARITH_REM 277
1613#define ARITH_UNARYMINUS 278
1614#define ARITH_UNARYPLUS 279
1615#define ARITH_NOT 280
1616#define ARITH_BNOT 281
1617
1618static void expari (int);
1619/* From arith.y */
1620static int arith (const char *);
1621static int expcmd (int , char **);
1622static void arith_lex_reset (void);
1623static int yylex (void);
1624
1625#endif
1626
1627static char *trap[NSIG]; /* trap handler commands */
1628static char sigmode[NSIG - 1]; /* current value of signal */
1629static char gotsig[NSIG - 1]; /* indicates specified signal received */
1630static int pendingsigs; /* indicates some signal received */
308 1631
309/* 1632/*
310 * This file was generated by the mkbuiltins program. 1633 * This file was generated by the mkbuiltins program.
311 */ 1634 */
312 1635
313static int bgcmd __P((int, char **)); 1636#ifdef JOBS
314static int breakcmd __P((int, char **)); 1637static int bgcmd (int, char **);
315static int cdcmd __P((int, char **)); 1638static int fgcmd (int, char **);
316static int commandcmd __P((int, char **)); 1639static int killcmd (int, char **);
317static int dotcmd __P((int, char **)); 1640#endif
318static int evalcmd __P((int, char **)); 1641#ifdef ASH_BBAPPS_AS_BUILTINS
319static int execcmd __P((int, char **)); 1642static int bltincmd (int, char **);
320static int exitcmd __P((int, char **)); 1643#endif
321static int exportcmd __P((int, char **)); 1644static int cdcmd (int, char **);
322static int histcmd __P((int, char **)); 1645static int breakcmd (int, char **);
323static int fgcmd __P((int, char **)); 1646#ifdef ASH_CMDCMD
324static int hashcmd __P((int, char **)); 1647static int commandcmd (int, char **);
325static int jobscmd __P((int, char **)); 1648#endif
326static int killcmd __P((int, char **)); 1649static int dotcmd (int, char **);
327static int localcmd __P((int, char **)); 1650static int evalcmd (int, char **);
328static int pwdcmd __P((int, char **)); 1651static int execcmd (int, char **);
329static int readcmd __P((int, char **)); 1652static int exitcmd (int, char **);
330static int returncmd __P((int, char **)); 1653static int exportcmd (int, char **);
331static int setcmd __P((int, char **)); 1654static int histcmd (int, char **);
332static int setvarcmd __P((int, char **)); 1655static int hashcmd (int, char **);
333static int shiftcmd __P((int, char **)); 1656static int jobscmd (int, char **);
334static int trapcmd __P((int, char **)); 1657static int localcmd (int, char **);
335static int umaskcmd __P((int, char **)); 1658#ifdef ASH_PWD
336static int unaliascmd __P((int, char **)); 1659static int pwdcmd (int, char **);
337static int unsetcmd __P((int, char **)); 1660#endif
338static int waitcmd __P((int, char **)); 1661static int readcmd (int, char **);
339static int aliascmd __P((int, char **)); 1662static int returncmd (int, char **);
340static int ulimitcmd __P((int, char **)); 1663static int setcmd (int, char **);
341static int timescmd __P((int, char **)); 1664static int setvarcmd (int, char **);
1665static int shiftcmd (int, char **);
1666static int trapcmd (int, char **);
1667static int umaskcmd (int, char **);
1668#ifdef ASH_ALIAS
1669static int aliascmd (int, char **);
1670static int unaliascmd (int, char **);
1671#endif
1672static int unsetcmd (int, char **);
1673static int waitcmd (int, char **);
1674static int ulimitcmd (int, char **);
1675static int timescmd (int, char **);
342#ifdef ASH_MATH_SUPPORT 1676#ifdef ASH_MATH_SUPPORT
343static int expcmd __P((int, char **)); 1677static int expcmd (int, char **);
344#endif 1678#endif
345#ifdef ASH_TYPE 1679#ifdef ASH_TYPE
346static int typecmd __P((int, char **)); 1680static int typecmd (int, char **);
347#endif 1681#endif
348#ifdef ASH_GETOPTS 1682#ifdef ASH_GETOPTS
349static int getoptscmd __P((int, char **)); 1683static int getoptscmd (int, char **);
350#endif 1684#endif
1685
351#ifndef BB_TRUE_FALSE 1686#ifndef BB_TRUE_FALSE
352static int true_main __P((int, char **)); 1687# ifdef ASH_BBAPPS_AS_BUILTINS
353static int false_main __P((int, char **)); 1688static int true_main (int, char **);
1689static int false_main (int, char **);
1690# endif
354#endif 1691#endif
355 1692
356static struct builtincmd *DOTCMD; 1693static void setpwd (const char *, int);
357static struct builtincmd *BLTINCMD; 1694
358static struct builtincmd *COMMANDCMD; 1695
359static struct builtincmd *EXECCMD; 1696#define BUILTIN_NOSPEC "0"
360static struct builtincmd *EVALCMD; 1697#define BUILTIN_SPECIAL "1"
1698#define BUILTIN_REGULAR "2"
1699#define BUILTIN_ASSIGN "4"
1700#define BUILTIN_SPEC_ASSG "5"
1701#define BUILTIN_REG_ASSG "6"
1702
1703#define IS_BUILTIN_SPECIAL(builtincmd) ((builtincmd)->name[0] & 1)
1704#define IS_BUILTIN_REGULAR(builtincmd) ((builtincmd)->name[0] & 2)
1705#define IS_BUILTIN_ASSIGN(builtincmd) ((builtincmd)->name[0] & 4)
1706
1707struct builtincmd {
1708 const char *name;
1709 int (*const builtinfunc) (int, char **);
1710 //unsigned flags;
1711};
1712
361 1713
362/* It is CRUCIAL that this listing be kept in ascii order, otherwise 1714/* It is CRUCIAL that this listing be kept in ascii order, otherwise
363 * the binary search in find_builtin() will stop working. If you value 1715 * the binary search in find_builtin() will stop working. If you value
@@ -366,75 +1718,149 @@ static struct builtincmd *EVALCMD;
366 * have been warned. 1718 * have been warned.
367 */ 1719 */
368static const struct builtincmd builtincmds[] = { 1720static const struct builtincmd builtincmds[] = {
369 { ".", dotcmd, 1 }, 1721 { BUILTIN_SPECIAL ".", dotcmd },
370 { ":", true_main, 1 }, 1722 { BUILTIN_SPECIAL ":", true_main },
371 { "alias", aliascmd, 6 }, 1723#ifdef ASH_ALIAS
372 { "bg", bgcmd, 2 }, 1724 { BUILTIN_REG_ASSG "alias", aliascmd },
373 { "break", breakcmd, 1 }, 1725#endif
374 { "builtin", bltincmd, 1 }, 1726#ifdef JOBS
375 { "cd", cdcmd, 2 }, 1727 { BUILTIN_REGULAR "bg", bgcmd },
376 { "chdir", cdcmd, 0 }, 1728#endif
377 { "command", commandcmd, 2 }, 1729 { BUILTIN_SPECIAL "break", breakcmd },
378 { "continue", breakcmd, 1 }, 1730#ifdef ASH_BBAPPS_AS_BUILTINS
379 { "eval", evalcmd, 1 }, 1731 { BUILTIN_SPECIAL "builtin", bltincmd },
380 { "exec", execcmd, 1 }, 1732#endif
381 { "exit", exitcmd, 1 }, 1733 { BUILTIN_REGULAR "cd", cdcmd },
1734#ifdef ASH_BBAPPS_AS_BUILTINS
1735 { BUILTIN_NOSPEC "chdir", cdcmd },
1736#endif
1737#ifdef ASH_CMDCMD
1738 { BUILTIN_REGULAR "command", commandcmd },
1739#endif
1740 { BUILTIN_SPECIAL "continue", breakcmd },
1741 { BUILTIN_SPECIAL "eval", evalcmd },
1742 { BUILTIN_SPECIAL "exec", execcmd },
1743 { BUILTIN_SPECIAL "exit", exitcmd },
382#ifdef ASH_MATH_SUPPORT 1744#ifdef ASH_MATH_SUPPORT
383 { "exp", expcmd, 0 }, 1745 { BUILTIN_NOSPEC "exp", expcmd },
1746#endif
1747 { BUILTIN_SPEC_ASSG "export", exportcmd },
1748#ifdef ASH_BBAPPS_AS_BUILTINS
1749 { BUILTIN_REGULAR "false", false_main },
1750#endif
1751 { BUILTIN_REGULAR "fc", histcmd },
1752#ifdef JOBS
1753 { BUILTIN_REGULAR "fg", fgcmd },
384#endif 1754#endif
385 { "export", exportcmd, 5 },
386 { "false", false_main, 2 },
387 { "fc", histcmd, 2 },
388 { "fg", fgcmd, 2 },
389#ifdef ASH_GETOPTS 1755#ifdef ASH_GETOPTS
390 { "getopts", getoptscmd, 2 }, 1756 { BUILTIN_REGULAR "getopts", getoptscmd },
391#endif 1757#endif
392 { "hash", hashcmd, 0 }, 1758 { BUILTIN_NOSPEC "hash", hashcmd },
393 { "jobs", jobscmd, 2 }, 1759 { BUILTIN_REGULAR "jobs", jobscmd },
394 { "kill", killcmd, 2 }, 1760#ifdef JOBS
1761 { BUILTIN_REGULAR "kill", killcmd },
1762#endif
395#ifdef ASH_MATH_SUPPORT 1763#ifdef ASH_MATH_SUPPORT
396 { "let", expcmd, 0 }, 1764 { BUILTIN_NOSPEC "let", expcmd },
397#endif 1765#endif
398 { "local", localcmd, 4 }, 1766 { BUILTIN_ASSIGN "local", localcmd },
399 { "pwd", pwdcmd, 0 }, 1767#ifdef ASH_PWD
400 { "read", readcmd, 2 }, 1768 { BUILTIN_NOSPEC "pwd", pwdcmd },
401 { "readonly", exportcmd, 5 }, 1769#endif
402 { "return", returncmd, 1 }, 1770 { BUILTIN_REGULAR "read", readcmd },
403 { "set", setcmd, 1 }, 1771 { BUILTIN_SPEC_ASSG "readonly", exportcmd },
404 { "setvar", setvarcmd, 0 }, 1772 { BUILTIN_SPECIAL "return", returncmd },
405 { "shift", shiftcmd, 1 }, 1773 { BUILTIN_SPECIAL "set", setcmd },
406 { "times", timescmd, 1 }, 1774 { BUILTIN_NOSPEC "setvar", setvarcmd },
407 { "trap", trapcmd, 1 }, 1775 { BUILTIN_SPECIAL "shift", shiftcmd },
408 { "true", true_main, 2 }, 1776 { BUILTIN_SPECIAL "times", timescmd },
1777 { BUILTIN_SPECIAL "trap", trapcmd },
1778#ifdef ASH_BBAPPS_AS_BUILTINS
1779 { BUILTIN_REGULAR "true", true_main },
1780#endif
409#ifdef ASH_TYPE 1781#ifdef ASH_TYPE
410 { "type", typecmd, 0 }, 1782 { BUILTIN_NOSPEC "type", typecmd },
411#endif 1783#endif
412 { "ulimit", ulimitcmd, 0 }, 1784 { BUILTIN_NOSPEC "ulimit", ulimitcmd },
413 { "umask", umaskcmd, 2 }, 1785 { BUILTIN_REGULAR "umask", umaskcmd },
414 { "unalias", unaliascmd, 2 }, 1786#ifdef ASH_ALIAS
415 { "unset", unsetcmd, 1 }, 1787 { BUILTIN_REGULAR "unalias", unaliascmd },
416 { "wait", waitcmd, 2 }, 1788#endif
1789 { BUILTIN_SPECIAL "unset", unsetcmd },
1790 { BUILTIN_REGULAR "wait", waitcmd },
417}; 1791};
418#define NUMBUILTINS (sizeof (builtincmds) / sizeof (struct builtincmd) ) 1792#define NUMBUILTINS (sizeof (builtincmds) / sizeof (struct builtincmd) )
419 1793
1794static const struct builtincmd *DOTCMD = &builtincmds[0];
1795static struct builtincmd *BLTINCMD;
1796static struct builtincmd *EXECCMD;
1797static struct builtincmd *EVALCMD;
1798
1799/* states */
1800#define JOBSTOPPED 1 /* all procs are stopped */
1801#define JOBDONE 2 /* all procs are completed */
1802
1803/*
1804 * A job structure contains information about a job. A job is either a
1805 * single process or a set of processes contained in a pipeline. In the
1806 * latter case, pidlist will be non-NULL, and will point to a -1 terminated
1807 * array of pids.
1808 */
420 1809
421/* $NetBSD: cd.c,v 1.27 1999/07/09 03:05:49 christos Exp $ */ 1810struct procstat {
1811 pid_t pid; /* process id */
1812 int status; /* status flags (defined above) */
1813 char *cmd; /* text of command being run */
1814};
422 1815
423static int docd __P((char *, int));
424static char *getcomponent __P((void));
425static void updatepwd __P((char *));
426static void getpwd __P((void));
427 1816
428static char *curdir = nullstr; /* current working directory */ 1817static int job_warning; /* user was warned about stopped jobs */
429static char *cdcomppath;
430 1818
431#ifdef mkinit 1819#ifdef JOBS
432INCLUDE "cd.h" 1820static void setjobctl(int enable);
433INIT { 1821#else
434 setpwd(0, 0); 1822#define setjobctl(on) /* do nothing */
435}
436#endif 1823#endif
437 1824
1825
1826struct job {
1827 struct procstat ps0; /* status of process */
1828 struct procstat *ps; /* status or processes when more than one */
1829 short nprocs; /* number of processes */
1830 short pgrp; /* process group of this job */
1831 char state; /* true if job is finished */
1832 char used; /* true if this entry is in used */
1833 char changed; /* true if status has changed */
1834#ifdef JOBS
1835 char jobctl; /* job running under job control */
1836#endif
1837};
1838
1839static struct job *jobtab; /* array of jobs */
1840static int njobs; /* size of array */
1841static int backgndpid = -1; /* pid of last background process */
1842#ifdef JOBS
1843static int initialpgrp; /* pgrp of shell on invocation */
1844static int curjob; /* current job */
1845static int jobctl;
1846#endif
1847static int intreceived;
1848
1849static struct job *makejob (union node *, int);
1850static int forkshell (struct job *, union node *, int);
1851static int waitforjob (struct job *);
1852
1853static int docd (char *, int);
1854static char *getcomponent (void);
1855static void updatepwd (const char *);
1856static void getpwd (void);
1857
1858static char *padvance (const char **, const char *);
1859
1860static char nullstr[1]; /* zero length string */
1861static char *curdir = nullstr; /* current working directory */
1862static char *cdcomppath;
1863
438static int 1864static int
439cdcmd(argc, argv) 1865cdcmd(argc, argv)
440 int argc; 1866 int argc;
@@ -450,7 +1876,7 @@ cdcmd(argc, argv)
450 if ((dest = *argptr) == NULL && (dest = bltinlookup("HOME")) == NULL) 1876 if ((dest = *argptr) == NULL && (dest = bltinlookup("HOME")) == NULL)
451 error("HOME not set"); 1877 error("HOME not set");
452 if (*dest == '\0') 1878 if (*dest == '\0')
453 dest = "."; 1879 dest = ".";
454 if (dest[0] == '-' && dest[1] == '\0') { 1880 if (dest[0] == '-' && dest[1] == '\0') {
455 dest = bltinlookup("OLDPWD"); 1881 dest = bltinlookup("OLDPWD");
456 if (!dest || !*dest) { 1882 if (!dest || !*dest) {
@@ -458,9 +1884,9 @@ cdcmd(argc, argv)
458 } 1884 }
459 print = 1; 1885 print = 1;
460 if (dest) 1886 if (dest)
461 print = 1; 1887 print = 1;
462 else 1888 else
463 dest = "."; 1889 dest = ".";
464 } 1890 }
465 if (*dest == '/' || (path = bltinlookup("CDPATH")) == NULL) 1891 if (*dest == '/' || (path = bltinlookup("CDPATH")) == NULL)
466 path = nullstr; 1892 path = nullstr;
@@ -581,15 +2007,16 @@ getcomponent() {
581 * that the current directory has changed. 2007 * that the current directory has changed.
582 */ 2008 */
583 2009
2010static void hashcd (void);
2011
584static void 2012static void
585updatepwd(dir) 2013updatepwd(const char *dir)
586 char *dir; 2014{
587 {
588 char *new; 2015 char *new;
589 char *p; 2016 char *p;
590 size_t len; 2017 size_t len;
591 2018
592 hashcd(); /* update command hash table */ 2019 hashcd(); /* update command hash table */
593 2020
594 /* 2021 /*
595 * If our argument is NULL, we don't know the current directory 2022 * If our argument is NULL, we don't know the current directory
@@ -626,7 +2053,7 @@ updatepwd(dir)
626} 2053}
627 2054
628 2055
629 2056#ifdef ASH_PWD
630static int 2057static int
631pwdcmd(argc, argv) 2058pwdcmd(argc, argv)
632 int argc; 2059 int argc;
@@ -635,89 +2062,18 @@ pwdcmd(argc, argv)
635 out1fmt(snlfmt, curdir); 2062 out1fmt(snlfmt, curdir);
636 return 0; 2063 return 0;
637} 2064}
638 2065#endif
639
640
641
642#define MAXPWD 256
643 2066
644/* 2067/*
645 * Find out what the current directory is. If we already know the current 2068 * Find out what the current directory is. If we already know the current
646 * directory, this routine returns immediately. 2069 * directory, this routine returns immediately.
647 */ 2070 */
648static void 2071static void
649getpwd() 2072getpwd(void)
650{ 2073{
651 char buf[MAXPWD]; 2074 curdir = xgetcwd(0);
652 2075 if(curdir==0)
653 /* 2076 curdir = nullstr;
654 * Things are a bit complicated here; we could have just used
655 * getcwd, but traditionally getcwd is implemented using popen
656 * to /bin/pwd. This creates a problem for us, since we cannot
657 * keep track of the job if it is being ran behind our backs.
658 * So we re-implement getcwd(), and we suppress interrupts
659 * throughout the process. This is not completely safe, since
660 * the user can still break out of it by killing the pwd program.
661 * We still try to use getcwd for systems that we know have a
662 * c implementation of getcwd, that does not open a pipe to
663 * /bin/pwd.
664 */
665#if defined(__NetBSD__) || defined(__SVR4) || defined(__GLIBC__)
666
667 if (getcwd(buf, sizeof(buf)) == NULL) {
668 char *pwd = getenv("PWD");
669 struct stat stdot, stpwd;
670
671 if (pwd && *pwd == '/' && stat(".", &stdot) != -1 &&
672 stat(pwd, &stpwd) != -1 &&
673 stdot.st_dev == stpwd.st_dev &&
674 stdot.st_ino == stpwd.st_ino) {
675 curdir = savestr(pwd);
676 return;
677 }
678 error("getcwd() failed: %s", strerror(errno));
679 }
680 curdir = savestr(buf);
681#else
682 {
683 char *p;
684 int i;
685 int status;
686 struct job *jp;
687 int pip[2];
688
689 if (pipe(pip) < 0)
690 error("Pipe call failed");
691 jp = makejob((union node *)NULL, 1);
692 if (forkshell(jp, (union node *)NULL, FORK_NOJOB) == 0) {
693 (void) close(pip[0]);
694 if (pip[1] != 1) {
695 close(1);
696 dup_as_newfd(pip[1], 1);
697 close(pip[1]);
698 }
699 (void) execl("/bin/pwd", "pwd", (char *)0);
700 error("Cannot exec /bin/pwd");
701 }
702 (void) close(pip[1]);
703 pip[1] = -1;
704 p = buf;
705 while ((i = read(pip[0], p, buf + MAXPWD - p)) > 0
706 || (i == -1 && errno == EINTR)) {
707 if (i > 0)
708 p += i;
709 }
710 (void) close(pip[0]);
711 pip[0] = -1;
712 status = waitforjob(jp);
713 if (status != 0)
714 error((char *)0);
715 if (i < 0 || p == buf || p[-1] != '\n')
716 error("pwd command failed");
717 p[-1] = '\0';
718 }
719 curdir = savestr(buf);
720#endif
721} 2077}
722 2078
723static void 2079static void
@@ -740,8 +2096,6 @@ setpwd(const char *val, int setold)
740 setvar("PWD", curdir, VEXPORT); 2096 setvar("PWD", curdir, VEXPORT);
741} 2097}
742 2098
743/* $NetBSD: error.c,v 1.23 2000/07/03 03:26:19 matt Exp $ */
744
745/* 2099/*
746 * Errors and exceptions. 2100 * Errors and exceptions.
747 */ 2101 */
@@ -750,13 +2104,30 @@ setpwd(const char *val, int setold)
750 * Code to handle exceptions in C. 2104 * Code to handle exceptions in C.
751 */ 2105 */
752 2106
753struct jmploc *handler; 2107/*
754static int exception; 2108 * We enclose jmp_buf in a structure so that we can declare pointers to
755volatile int suppressint; 2109 * jump locations. The global variable handler contains the location to
756volatile int intpending; 2110 * jump to when an exception occurs, and the global variable exception
2111 * contains a code identifying the exeception. To implement nested
2112 * exception handlers, the user should save the value of handler on entry
2113 * to an inner scope, set handler to point to a jmploc structure for the
2114 * inner scope, and restore handler on exit from the scope.
2115 */
2116
2117struct jmploc {
2118 jmp_buf loc;
2119};
757 2120
2121/* exceptions */
2122#define EXINT 0 /* SIGINT received */
2123#define EXERROR 1 /* a generic error */
2124#define EXSHELLPROC 2 /* execute a shell procedure */
2125#define EXEXEC 3 /* command execution failed */
2126
2127static struct jmploc *handler;
2128static int exception;
758 2129
759static void exverror __P((int, const char *, va_list)) 2130static void exverror (int, const char *, va_list)
760 __attribute__((__noreturn__)); 2131 __attribute__((__noreturn__));
761 2132
762/* 2133/*
@@ -765,9 +2136,10 @@ static void exverror __P((int, const char *, va_list))
765 * stored in the global variable "exception". 2136 * stored in the global variable "exception".
766 */ 2137 */
767 2138
2139static void exraise (int) __attribute__((__noreturn__));
2140
768static void 2141static void
769exraise(e) 2142exraise(int e)
770 int e;
771{ 2143{
772#ifdef DEBUG 2144#ifdef DEBUG
773 if (handler == NULL) 2145 if (handler == NULL)
@@ -789,7 +2161,7 @@ exraise(e)
789 */ 2161 */
790 2162
791static void 2163static void
792onint() { 2164onint(void) {
793 sigset_t mysigset; 2165 sigset_t mysigset;
794 2166
795 if (suppressint) { 2167 if (suppressint) {
@@ -809,16 +2181,15 @@ onint() {
809} 2181}
810 2182
811 2183
2184static char *commandname; /* currently executing command */
2185
812/* 2186/*
813 * Exverror is called to raise the error exception. If the first argument 2187 * Exverror is called to raise the error exception. If the first argument
814 * is not NULL then error prints an error message using printf style 2188 * is not NULL then error prints an error message using printf style
815 * formatting. It then raises the error exception. 2189 * formatting. It then raises the error exception.
816 */ 2190 */
817static void 2191static void
818exverror(cond, msg, ap) 2192exverror(int cond, const char *msg, va_list ap)
819 int cond;
820 const char *msg;
821 va_list ap;
822{ 2193{
823 CLEAR_PENDING_INT; 2194 CLEAR_PENDING_INT;
824 INTOFF; 2195 INTOFF;
@@ -903,69 +2274,75 @@ exerror(va_alist)
903 */ 2274 */
904 2275
905struct errname { 2276struct errname {
906 short errcode; /* error number */ 2277 short errcode; /* error number */
907 short action; /* operation which encountered the error */ 2278 short action; /* operation which encountered the error */
908 const char *msg; /* text describing the error */
909}; 2279};
910 2280
2281/*
2282 * Types of operations (passed to the errmsg routine).
2283 */
2284
2285#define E_OPEN 01 /* opening a file */
2286#define E_CREAT 02 /* creating a file */
2287#define E_EXEC 04 /* executing a program */
911 2288
912#define ALL (E_OPEN|E_CREAT|E_EXEC) 2289#define ALL (E_OPEN|E_CREAT|E_EXEC)
913 2290
914static const struct errname errormsg[] = { 2291static const struct errname errormsg[] = {
915 { EINTR, ALL, "interrupted" }, 2292 { EINTR, ALL },
916 { EACCES, ALL, "permission denied" }, 2293 { EACCES, ALL },
917 { EIO, ALL, "I/O error" }, 2294 { EIO, ALL },
918 { ENOENT, E_OPEN, "no such file" }, 2295 { ENOENT, E_OPEN },
919 { ENOENT, E_CREAT,"directory nonexistent" }, 2296 { ENOENT, E_CREAT },
920 { ENOENT, E_EXEC, "not found" }, 2297 { ENOENT, E_EXEC },
921 { ENOTDIR, E_OPEN, "no such file" }, 2298 { ENOTDIR, E_OPEN },
922 { ENOTDIR, E_CREAT,"directory nonexistent" }, 2299 { ENOTDIR, E_CREAT },
923 { ENOTDIR, E_EXEC, "not found" }, 2300 { ENOTDIR, E_EXEC },
924 { EISDIR, ALL, "is a directory" }, 2301 { EISDIR, ALL },
925 { EEXIST, E_CREAT,"file exists" }, 2302 { EEXIST, E_CREAT },
926#ifdef notdef 2303#ifdef EMFILE
927 { EMFILE, ALL, "too many open files" }, 2304 { EMFILE, ALL },
928#endif 2305#endif
929 { ENFILE, ALL, "file table overflow" }, 2306 { ENFILE, ALL },
930 { ENOSPC, ALL, "file system full" }, 2307 { ENOSPC, ALL },
931#ifdef EDQUOT 2308#ifdef EDQUOT
932 { EDQUOT, ALL, "disk quota exceeded" }, 2309 { EDQUOT, ALL },
933#endif 2310#endif
934#ifdef ENOSR 2311#ifdef ENOSR
935 { ENOSR, ALL, "no streams resources" }, 2312 { ENOSR, ALL },
936#endif 2313#endif
937 { ENXIO, ALL, "no such device or address" }, 2314 { ENXIO, ALL },
938 { EROFS, ALL, "read-only file system" }, 2315 { EROFS, ALL },
939 { ETXTBSY, ALL, "text busy" }, 2316 { ETXTBSY, ALL },
940#ifdef SYSV 2317#ifdef EAGAIN
941 { EAGAIN, E_EXEC, "not enough memory" }, 2318 { EAGAIN, E_EXEC },
942#endif 2319#endif
943 { ENOMEM, ALL, "not enough memory" }, 2320 { ENOMEM, ALL },
944#ifdef ENOLINK 2321#ifdef ENOLINK
945 { ENOLINK, ALL, "remote access failed" }, 2322 { ENOLINK, ALL },
946#endif 2323#endif
947#ifdef EMULTIHOP 2324#ifdef EMULTIHOP
948 { EMULTIHOP, ALL, "remote access failed" }, 2325 { EMULTIHOP, ALL },
949#endif 2326#endif
950#ifdef ECOMM 2327#ifdef ECOMM
951 { ECOMM, ALL, "remote access failed" }, 2328 { ECOMM, ALL },
952#endif 2329#endif
953#ifdef ESTALE 2330#ifdef ESTALE
954 { ESTALE, ALL, "remote access failed" }, 2331 { ESTALE, ALL },
955#endif 2332#endif
956#ifdef ETIMEDOUT 2333#ifdef ETIMEDOUT
957 { ETIMEDOUT, ALL, "remote access failed" }, 2334 { ETIMEDOUT, ALL },
958#endif 2335#endif
959#ifdef ELOOP 2336#ifdef ELOOP
960 { ELOOP, ALL, "symbolic link loop" }, 2337 { ELOOP, ALL },
961#endif 2338#endif
962 { E2BIG, E_EXEC, "argument list too long" }, 2339 { E2BIG, E_EXEC },
963#ifdef ELIBACC 2340#ifdef ELIBACC
964 { ELIBACC, E_EXEC, "shared library missing" }, 2341 { ELIBACC, E_EXEC },
965#endif 2342#endif
966 { 0, 0, NULL },
967}; 2343};
968 2344
2345#define ERRNAME_SIZE (sizeof(errormsg)/sizeof(struct errname))
969 2346
970/* 2347/*
971 * Return a string describing an error. The returned string may be a 2348 * Return a string describing an error. The returned string may be a
@@ -974,23 +2351,22 @@ static const struct errname errormsg[] = {
974 */ 2351 */
975 2352
976static const char * 2353static const char *
977errmsg(e, action) 2354errmsg(int e, int action)
978 int e;
979 int action;
980{ 2355{
981 struct errname const *ep; 2356 struct errname const *ep;
982 static char buf[12]; 2357 static char buf[12];
983 2358
984 for (ep = errormsg ; ep->errcode ; ep++) { 2359 for (ep = errormsg ; ep < errormsg+ERRNAME_SIZE; ep++) {
985 if (ep->errcode == e && (ep->action & action) != 0) 2360 if (ep->errcode == e && (ep->action & action) != 0)
986 return ep->msg; 2361 return strerror(e);
987 } 2362 }
2363
988 fmtstr(buf, sizeof buf, "error %d", e); 2364 fmtstr(buf, sizeof buf, "error %d", e);
989 return buf; 2365 return buf;
990} 2366}
991 2367
992 2368
993#ifdef REALLY_SMALL 2369#ifndef ASH_BBAPPS_AS_BUILTINS
994static void 2370static void
995__inton() { 2371__inton() {
996 if (--suppressint == 0 && intpending) { 2372 if (--suppressint == 0 && intpending) {
@@ -998,104 +2374,91 @@ __inton() {
998 } 2374 }
999} 2375}
1000#endif 2376#endif
1001/* $NetBSD: eval.c,v 1.57 2001/02/04 19:52:06 christos Exp $ */
1002
1003 2377
1004/* flags in argument to evaltree */ 2378/* flags in argument to evaltree */
1005#define EV_EXIT 01 /* exit after evaluating tree */ 2379#define EV_EXIT 01 /* exit after evaluating tree */
1006#define EV_TESTED 02 /* exit status is checked; ignore -e flag */ 2380#define EV_TESTED 02 /* exit status is checked; ignore -e flag */
1007#define EV_BACKCMD 04 /* command executing within back quotes */ 2381#define EV_BACKCMD 04 /* command executing within back quotes */
2382
2383static int evalskip; /* set if we are skipping commands */
2384static int skipcount; /* number of levels to skip */
2385static int loopnest; /* current loop nesting level */
2386static int funcnest; /* depth of function calls */
1008 2387
1009static int evalskip; /* set if we are skipping commands */
1010static int skipcount; /* number of levels to skip */
1011static int loopnest; /* current loop nesting level */
1012static int funcnest; /* depth of function calls */
1013 2388
1014 2389
1015static char *commandname; 2390static struct strlist *cmdenviron; /* environment for builtin command */
1016struct strlist *cmdenviron; 2391static int exitstatus; /* exit status of last command */
1017static int exitstatus; /* exit status of last command */ 2392static int oexitstatus; /* saved exit status */
1018static int oexitstatus; /* saved exit status */
1019 2393
1020 2394
1021static void evalloop __P((union node *, int)); 2395static void evalloop (union node *, int);
1022static void evalfor __P((union node *, int)); 2396static void evalfor (union node *, int);
1023static void evalcase __P((union node *, int)); 2397static void evalcase (union node *, int);
1024static void evalsubshell __P((union node *, int)); 2398static void evalsubshell (union node *, int);
1025static void expredir __P((union node *)); 2399static void expredir (union node *);
1026static void evalpipe __P((union node *)); 2400static void evalpipe (union node *);
1027#ifdef notyet 2401#ifdef notyet
1028static void evalcommand __P((union node *, int, struct backcmd *)); 2402static void evalcommand (union node *, int, struct backcmd *);
1029#else 2403#else
1030static void evalcommand __P((union node *, int)); 2404static void evalcommand (union node *, int);
1031#endif 2405#endif
1032static void prehash __P((union node *)); 2406static void prehash (union node *);
1033static void eprintlist __P((struct strlist *)); 2407static void eprintlist (struct strlist *);
1034
1035 2408
2409static union node *parsecmd(int);
1036/* 2410/*
1037 * Called to reset things after an exception. 2411 * Called to reset things after an exception.
1038 */ 2412 */
1039 2413
1040#ifdef mkinit
1041INCLUDE "eval.h"
1042
1043RESET {
1044 evalskip = 0;
1045 loopnest = 0;
1046 funcnest = 0;
1047}
1048
1049SHELLPROC {
1050 exitstatus = 0;
1051}
1052#endif
1053
1054
1055
1056/* 2414/*
1057 * The eval commmand. 2415 * The eval commmand.
1058 */ 2416 */
2417static void evalstring (char *, int);
1059 2418
1060static int 2419static int
1061evalcmd(argc, argv) 2420evalcmd(argc, argv)
1062 int argc; 2421 int argc;
1063 char **argv; 2422 char **argv;
1064{ 2423{
1065 char *p; 2424 char *p;
1066 char *concat; 2425 char *concat;
1067 char **ap; 2426 char **ap;
1068 2427
1069 if (argc > 1) { 2428 if (argc > 1) {
1070 p = argv[1]; 2429 p = argv[1];
1071 if (argc > 2) { 2430 if (argc > 2) {
1072 STARTSTACKSTR(concat); 2431 STARTSTACKSTR(concat);
1073 ap = argv + 2; 2432 ap = argv + 2;
1074 for (;;) { 2433 for (;;) {
1075 while (*p) 2434 while (*p)
1076 STPUTC(*p++, concat); 2435 STPUTC(*p++, concat);
1077 if ((p = *ap++) == NULL) 2436 if ((p = *ap++) == NULL)
1078 break; 2437 break;
1079 STPUTC(' ', concat); 2438 STPUTC(' ', concat);
1080 } 2439 }
1081 STPUTC('\0', concat); 2440 STPUTC('\0', concat);
1082 p = grabstackstr(concat); 2441 p = grabstackstr(concat);
1083 } 2442 }
1084 evalstring(p, EV_TESTED); 2443 evalstring(p, EV_TESTED);
1085 } 2444 }
1086 return exitstatus; 2445 return exitstatus;
1087} 2446}
1088 2447
1089
1090/* 2448/*
1091 * Execute a command or commands contained in a string. 2449 * Execute a command or commands contained in a string.
1092 */ 2450 */
1093 2451
2452static void evaltree (union node *, int);
2453static void setinputstring (char *);
2454static void popfile (void);
2455static void setstackmark(struct stackmark *mark);
2456static void popstackmark(struct stackmark *mark);
2457
2458
1094static void 2459static void
1095evalstring(s, flag) 2460evalstring(char *s, int flag)
1096 char *s; 2461{
1097 int flag;
1098 {
1099 union node *n; 2462 union node *n;
1100 struct stackmark smark; 2463 struct stackmark smark;
1101 2464
@@ -1109,12 +2472,12 @@ evalstring(s, flag)
1109 popstackmark(&smark); 2472 popstackmark(&smark);
1110} 2473}
1111 2474
1112
1113
1114/* 2475/*
1115 * Evaluate a parse tree. The value is left in the global variable 2476 * Evaluate a parse tree. The value is left in the global variable
1116 * exitstatus. 2477 * exitstatus.
1117 */ 2478 */
2479static struct builtincmd *find_builtin (const char *);
2480static void defun (char *, union node *);
1118 2481
1119static void 2482static void
1120evaltree(n, flags) 2483evaltree(n, flags)
@@ -1184,7 +2547,7 @@ evaltree(n, flags)
1184 struct builtincmd *bcmd; 2547 struct builtincmd *bcmd;
1185 if ( 2548 if (
1186 (bcmd = find_builtin(n->narg.text)) && 2549 (bcmd = find_builtin(n->narg.text)) &&
1187 bcmd->flags & BUILTIN_SPECIAL 2550 IS_BUILTIN_SPECIAL(bcmd)
1188 ) { 2551 ) {
1189 outfmt(out2, "%s is a special built-in\n", n->narg.text); 2552 outfmt(out2, "%s is a special built-in\n", n->narg.text);
1190 exitstatus = 1; 2553 exitstatus = 1;
@@ -1243,7 +2606,7 @@ evalloop(n, flags)
1243 for (;;) { 2606 for (;;) {
1244 evaltree(n->nbinary.ch1, EV_TESTED); 2607 evaltree(n->nbinary.ch1, EV_TESTED);
1245 if (evalskip) { 2608 if (evalskip) {
1246skipping: if (evalskip == SKIPCONT && --skipcount <= 0) { 2609skipping: if (evalskip == SKIPCONT && --skipcount <= 0) {
1247 evalskip = 0; 2610 evalskip = 0;
1248 continue; 2611 continue;
1249 } 2612 }
@@ -1267,7 +2630,8 @@ skipping: if (evalskip == SKIPCONT && --skipcount <= 0) {
1267 exitstatus = status; 2630 exitstatus = status;
1268} 2631}
1269 2632
1270 2633static void expandarg (union node *, struct arglist *, int);
2634static void fixredir(union node *n, const char *text, int err);
1271 2635
1272static void 2636static void
1273evalfor(n, flags) 2637evalfor(n, flags)
@@ -1310,7 +2674,6 @@ out:
1310} 2674}
1311 2675
1312 2676
1313
1314static void 2677static void
1315evalcase(n, flags) 2678evalcase(n, flags)
1316 union node *n; 2679 union node *n;
@@ -1339,8 +2702,6 @@ out:
1339 popstackmark(&smark); 2702 popstackmark(&smark);
1340} 2703}
1341 2704
1342
1343
1344/* 2705/*
1345 * Kick off a subshell to evaluate a tree. 2706 * Kick off a subshell to evaluate a tree.
1346 */ 2707 */
@@ -1359,7 +2720,7 @@ evalsubshell(n, flags)
1359 if (backgnd) 2720 if (backgnd)
1360 flags &=~ EV_TESTED; 2721 flags &=~ EV_TESTED;
1361 redirect(n->nredir.redirect, 0); 2722 redirect(n->nredir.redirect, 0);
1362 evaltree(n->nredir.n, flags | EV_EXIT); /* never returns */ 2723 evaltree(n->nredir.n, flags | EV_EXIT); /* never returns */
1363 } 2724 }
1364 if (! backgnd) { 2725 if (! backgnd) {
1365 INTOFF; 2726 INTOFF;
@@ -1404,8 +2765,6 @@ expredir(n)
1404 } 2765 }
1405} 2766}
1406 2767
1407
1408
1409/* 2768/*
1410 * Evaluate a pipeline. All the processes in the pipeline are children 2769 * Evaluate a pipeline. All the processes in the pipeline are children
1411 * of the process creating the pipeline. (This differs from some versions 2770 * of the process creating the pipeline. (This differs from some versions
@@ -1485,13 +2844,11 @@ evalpipe(n)
1485 */ 2844 */
1486 2845
1487static void 2846static void
1488evalbackcmd(n, result) 2847evalbackcmd(union node *n, struct backcmd *result)
1489 union node *n;
1490 struct backcmd *result;
1491{ 2848{
1492 int pip[2]; 2849 int pip[2];
1493 struct job *jp; 2850 struct job *jp;
1494 struct stackmark smark; /* unnecessary */ 2851 struct stackmark smark; /* unnecessary */
1495 2852
1496 setstackmark(&smark); 2853 setstackmark(&smark);
1497 result->fd = -1; 2854 result->fd = -1;
@@ -1546,6 +2903,19 @@ out:
1546 * Execute a simple command. 2903 * Execute a simple command.
1547 */ 2904 */
1548 2905
2906static void find_command (const char *, struct cmdentry *, int, const char *);
2907
2908static int
2909isassignment(const char *word) {
2910 if (!is_name(*word)) {
2911 return 0;
2912 }
2913 do {
2914 word++;
2915 } while (is_in_name(*word));
2916 return *word == '=';
2917}
2918
1549static void 2919static void
1550#ifdef notyet 2920#ifdef notyet
1551evalcommand(cmd, flags, backcmd) 2921evalcommand(cmd, flags, backcmd)
@@ -1611,7 +2981,7 @@ evalcommand(cmd, flags)
1611 struct builtincmd *bcmd; 2981 struct builtincmd *bcmd;
1612 bool pseudovarflag; 2982 bool pseudovarflag;
1613 bcmd = find_builtin(arglist.list->text); 2983 bcmd = find_builtin(arglist.list->text);
1614 pseudovarflag = bcmd && bcmd->flags & BUILTIN_ASSIGN; 2984 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
1615 for (; argp; argp = argp->narg.next) { 2985 for (; argp; argp = argp->narg.next) {
1616 if (pseudovarflag && isassignment(argp->narg.text)) { 2986 if (pseudovarflag && isassignment(argp->narg.text)) {
1617 expandarg(argp, &arglist, EXP_VARTILDE); 2987 expandarg(argp, &arglist, EXP_VARTILDE);
@@ -1678,7 +3048,7 @@ evalcommand(cmd, flags)
1678 firstbltin = 0; 3048 firstbltin = 0;
1679 for(;;) { 3049 for(;;) {
1680 find_command(argv[0], &cmdentry, findflag, path); 3050 find_command(argv[0], &cmdentry, findflag, path);
1681 if (cmdentry.cmdtype == CMDUNKNOWN) { /* command not found */ 3051 if (cmdentry.cmdtype == CMDUNKNOWN) { /* command not found */
1682 exitstatus = 127; 3052 exitstatus = 127;
1683#ifdef FLUSHERR 3053#ifdef FLUSHERR
1684 flushout(&errout); 3054 flushout(&errout);
@@ -1712,7 +3082,7 @@ evalcommand(cmd, flags)
1712 break; 3082 break;
1713 } 3083 }
1714 } 3084 }
1715 if (cmdentry.u.cmd == COMMANDCMD) { 3085 if (cmdentry.u.cmd == find_builtin("command")) {
1716 argv++; 3086 argv++;
1717 if (--argc == 0) { 3087 if (--argc == 0) {
1718 goto found; 3088 goto found;
@@ -1761,7 +3131,7 @@ found:
1761 } 3131 }
1762#endif 3132#endif
1763 if (forkshell(jp, cmd, mode) != 0) 3133 if (forkshell(jp, cmd, mode) != 0)
1764 goto parent; /* at end of routine */ 3134 goto parent; /* at end of routine */
1765#ifdef notyet 3135#ifdef notyet
1766 if (flags & EV_BACKCMD) { 3136 if (flags & EV_BACKCMD) {
1767 FORCEINTON; 3137 FORCEINTON;
@@ -1849,7 +3219,7 @@ found:
1849#endif 3219#endif
1850 redirect(cmd->ncmd.redirect, mode); 3220 redirect(cmd->ncmd.redirect, mode);
1851 savecmdname = commandname; 3221 savecmdname = commandname;
1852 if (firstbltin->flags & BUILTIN_SPECIAL) { 3222 if (IS_BUILTIN_SPECIAL(firstbltin)) {
1853 listsetvar(varlist.list); 3223 listsetvar(varlist.list);
1854 } else { 3224 } else {
1855 cmdenviron = varlist.list; 3225 cmdenviron = varlist.list;
@@ -1864,7 +3234,7 @@ found:
1864 handler = &jmploc; 3234 handler = &jmploc;
1865 commandname = argv[0]; 3235 commandname = argv[0];
1866 argptr = argv + 1; 3236 argptr = argv + 1;
1867 optptr = NULL; /* initialize nextopt */ 3237 optptr = NULL; /* initialize nextopt */
1868 exitstatus = (*cmdentry.u.cmd->builtinfunc)(argc, argv); 3238 exitstatus = (*cmdentry.u.cmd->builtinfunc)(argc, argv);
1869 flushall(); 3239 flushall();
1870cmddone: 3240cmddone:
@@ -1894,12 +3264,8 @@ cmddone:
1894 if (flags == EV_BACKCMD) { 3264 if (flags == EV_BACKCMD) {
1895 INTOFF; 3265 INTOFF;
1896#ifdef USE_GLIBC_STDIO 3266#ifdef USE_GLIBC_STDIO
1897 if (__closememout()) { 3267 if (__closememout())
1898 error( 3268 error("__closememout() failed: %m");
1899 "__closememout() failed: %s",
1900 strerror(errno)
1901 );
1902 }
1903#endif 3269#endif
1904 backcmd->buf = memout.buf; 3270 backcmd->buf = memout.buf;
1905#ifdef USE_GLIBC_STDIO 3271#ifdef USE_GLIBC_STDIO
@@ -1924,8 +3290,8 @@ cmddone:
1924 } 3290 }
1925 goto out; 3291 goto out;
1926 3292
1927parent: /* parent process gets here (if we forked) */ 3293parent: /* parent process gets here (if we forked) */
1928 if (mode == 0) { /* argument to fork */ 3294 if (mode == 0) { /* argument to fork */
1929 INTOFF; 3295 INTOFF;
1930 exitstatus = waitforjob(jp); 3296 exitstatus = waitforjob(jp);
1931 INTON; 3297 INTON;
@@ -2043,6 +3409,7 @@ returncmd(argc, argv)
2043 3409
2044 3410
2045#ifndef BB_TRUE_FALSE 3411#ifndef BB_TRUE_FALSE
3412#ifdef ASH_BBAPPS_AS_BUILTINS
2046static int 3413static int
2047false_main(argc, argv) 3414false_main(argc, argv)
2048 int argc; 3415 int argc;
@@ -2060,6 +3427,37 @@ true_main(argc, argv)
2060 return 0; 3427 return 0;
2061} 3428}
2062#endif 3429#endif
3430#endif
3431
3432/*
3433 * Controls whether the shell is interactive or not.
3434 */
3435
3436static void setsignal(int signo);
3437static void chkmail(int silent);
3438
3439
3440static void
3441setinteractive(int on)
3442{
3443 static int is_interactive;
3444
3445 if (on == is_interactive)
3446 return;
3447 setsignal(SIGINT);
3448 setsignal(SIGQUIT);
3449 setsignal(SIGTERM);
3450 chkmail(1);
3451 is_interactive = on;
3452}
3453
3454static void
3455optschanged(void)
3456{
3457 setinteractive(iflag);
3458 setjobctl(mflag);
3459}
3460
2063 3461
2064static int 3462static int
2065execcmd(argc, argv) 3463execcmd(argc, argv)
@@ -2069,7 +3467,7 @@ execcmd(argc, argv)
2069 if (argc > 1) { 3467 if (argc > 1) {
2070 struct strlist *sp; 3468 struct strlist *sp;
2071 3469
2072 iflag = 0; /* exit on error */ 3470 iflag = 0; /* exit on error */
2073 mflag = 0; 3471 mflag = 0;
2074 optschanged(); 3472 optschanged();
2075 for (sp = cmdenviron; sp ; sp = sp->next) 3473 for (sp = cmdenviron; sp ; sp = sp->next)
@@ -2086,8 +3484,6 @@ eprintlist(struct strlist *sp)
2086 outfmt(&errout, " %s",sp->text); 3484 outfmt(&errout, " %s",sp->text);
2087 } 3485 }
2088} 3486}
2089/* $NetBSD: exec.c,v 1.32 2001/02/04 19:52:06 christos Exp $ */
2090
2091/* 3487/*
2092 * When commands are first encountered, they are entered in a hash table. 3488 * When commands are first encountered, they are entered in a hash table.
2093 * This ensures that a full path search will not have to be done for them 3489 * This ensures that a full path search will not have to be done for them
@@ -2096,37 +3492,34 @@ eprintlist(struct strlist *sp)
2096 * We should investigate converting to a linear search, even though that 3492 * We should investigate converting to a linear search, even though that
2097 * would make the command name "hash" a misnomer. 3493 * would make the command name "hash" a misnomer.
2098 */ 3494 */
2099#define CMDTABLESIZE 31 /* should be prime */ 3495#define CMDTABLESIZE 31 /* should be prime */
2100#define ARB 1 /* actual size determined at run time */ 3496#define ARB 1 /* actual size determined at run time */
2101 3497
2102 3498
2103 3499
2104struct tblentry { 3500struct tblentry {
2105 struct tblentry *next; /* next entry in hash chain */ 3501 struct tblentry *next; /* next entry in hash chain */
2106 union param param; /* definition of builtin function */ 3502 union param param; /* definition of builtin function */
2107 short cmdtype; /* index identifying command */ 3503 short cmdtype; /* index identifying command */
2108 char rehash; /* if set, cd done since entry created */ 3504 char rehash; /* if set, cd done since entry created */
2109 char cmdname[ARB]; /* name of command */ 3505 char cmdname[ARB]; /* name of command */
2110}; 3506};
2111 3507
2112 3508
2113static struct tblentry *cmdtable[CMDTABLESIZE]; 3509static struct tblentry *cmdtable[CMDTABLESIZE];
2114static int builtinloc = -1; /* index in path of %builtin, or -1 */ 3510static int builtinloc = -1; /* index in path of %builtin, or -1 */
2115static int exerrno = 0; /* Last exec error */ 3511static int exerrno = 0; /* Last exec error */
2116 3512
2117 3513
2118static void tryexec __P((char *, char **, char **)); 3514static void tryexec (char *, char **, char **);
2119#if !defined(BSD) && !defined(linux) 3515static void printentry (struct tblentry *, int);
2120static void execinterp __P((char **, char **)); 3516static void clearcmdentry (int);
2121#endif 3517static struct tblentry *cmdlookup (const char *, int);
2122static void printentry __P((struct tblentry *, int)); 3518static void delete_cmd_entry (void);
2123static void clearcmdentry __P((int));
2124static struct tblentry *cmdlookup __P((char *, int));
2125static void delete_cmd_entry __P((void));
2126#ifdef ASH_TYPE 3519#ifdef ASH_TYPE
2127static int describe_command __P((char *, int)); 3520static int describe_command (char *, int);
2128#endif 3521#endif
2129static int path_change __P((const char *, int *)); 3522static int path_change (const char *, int *);
2130 3523
2131 3524
2132/* 3525/*
@@ -2134,6 +3527,8 @@ static int path_change __P((const char *, int *));
2134 * have to change the find_command routine as well. 3527 * have to change the find_command routine as well.
2135 */ 3528 */
2136 3529
3530static const char *pathopt; /* set by padvance */
3531
2137static void 3532static void
2138shellexec(argv, envp, path, idx) 3533shellexec(argv, envp, path, idx)
2139 char **argv, **envp; 3534 char **argv, **envp;
@@ -2174,6 +3569,225 @@ shellexec(argv, envp, path, idx)
2174 /* NOTREACHED */ 3569 /* NOTREACHED */
2175} 3570}
2176 3571
3572/*
3573 * Clear traps on a fork.
3574 */
3575static void
3576clear_traps(void) {
3577 char **tp;
3578
3579 for (tp = trap ; tp < &trap[NSIG] ; tp++) {
3580 if (*tp && **tp) { /* trap not NULL or SIG_IGN */
3581 INTOFF;
3582 ckfree(*tp);
3583 *tp = NULL;
3584 if (tp != &trap[0])
3585 setsignal(tp - trap);
3586 INTON;
3587 }
3588 }
3589}
3590
3591
3592static void
3593initshellproc(void) {
3594
3595#ifdef ASH_ALIAS
3596 /* from alias.c: */
3597 {
3598 rmaliases();
3599 }
3600#endif
3601 /* from eval.c: */
3602 {
3603 exitstatus = 0;
3604 }
3605
3606 /* from exec.c: */
3607 {
3608 deletefuncs();
3609 }
3610
3611 /* from jobs.c: */
3612 {
3613 backgndpid = -1;
3614#ifdef JOBS
3615 jobctl = 0;
3616#endif
3617 }
3618
3619 /* from options.c: */
3620 {
3621 int i;
3622
3623 for (i = 0; i < NOPTS; i++)
3624 optent_val(i) = 0;
3625 optschanged();
3626
3627 }
3628
3629 /* from redir.c: */
3630 {
3631 clearredir();
3632 }
3633
3634 /* from trap.c: */
3635 {
3636 char *sm;
3637
3638 clear_traps();
3639 for (sm = sigmode ; sm < sigmode + NSIG - 1; sm++) {
3640 if (*sm == S_IGN)
3641 *sm = S_HARD_IGN;
3642 }
3643 }
3644
3645 /* from var.c: */
3646 {
3647 shprocvar();
3648 }
3649}
3650
3651static int preadbuffer(void);
3652static void pushfile (void);
3653static int preadfd (void);
3654
3655/*
3656 * Read a character from the script, returning PEOF on end of file.
3657 * Nul characters in the input are silently discarded.
3658 */
3659
3660#ifdef ASH_BBAPPS_AS_BUILTINS
3661#define pgetc_macro() (--parsenleft >= 0? *parsenextc++ : preadbuffer())
3662static int
3663pgetc(void)
3664{
3665 return pgetc_macro();
3666}
3667#else
3668static int
3669pgetc_macro(void)
3670{
3671 return --parsenleft >= 0? *parsenextc++ : preadbuffer();
3672}
3673
3674static inline int
3675pgetc(void)
3676{
3677 return pgetc_macro();
3678}
3679#endif
3680
3681
3682/*
3683 * Undo the last call to pgetc. Only one character may be pushed back.
3684 * PEOF may be pushed back.
3685 */
3686
3687static void
3688pungetc() {
3689 parsenleft++;
3690 parsenextc--;
3691}
3692
3693
3694static void
3695popfile(void) {
3696 struct parsefile *pf = parsefile;
3697
3698 INTOFF;
3699 if (pf->fd >= 0)
3700 close(pf->fd);
3701 if (pf->buf)
3702 ckfree(pf->buf);
3703 while (pf->strpush)
3704 popstring();
3705 parsefile = pf->prev;
3706 ckfree(pf);
3707 parsenleft = parsefile->nleft;
3708 parselleft = parsefile->lleft;
3709 parsenextc = parsefile->nextc;
3710 plinno = parsefile->linno;
3711 INTON;
3712}
3713
3714
3715/*
3716 * Return to top level.
3717 */
3718
3719static void
3720popallfiles(void) {
3721 while (parsefile != &basepf)
3722 popfile();
3723}
3724
3725/*
3726 * Close the file(s) that the shell is reading commands from. Called
3727 * after a fork is done.
3728 */
3729
3730static void
3731closescript() {
3732 popallfiles();
3733 if (parsefile->fd > 0) {
3734 close(parsefile->fd);
3735 parsefile->fd = 0;
3736 }
3737}
3738
3739
3740/*
3741 * Like setinputfile, but takes an open file descriptor. Call this with
3742 * interrupts off.
3743 */
3744
3745static void
3746setinputfd(fd, push)
3747 int fd, push;
3748{
3749 (void) fcntl(fd, F_SETFD, FD_CLOEXEC);
3750 if (push) {
3751 pushfile();
3752 parsefile->buf = 0;
3753 } else {
3754 closescript();
3755 while (parsefile->strpush)
3756 popstring();
3757 }
3758 parsefile->fd = fd;
3759 if (parsefile->buf == NULL)
3760 parsefile->buf = ckmalloc(BUFSIZ);
3761 parselleft = parsenleft = 0;
3762 plinno = 1;
3763}
3764
3765
3766/*
3767 * Set the input to take input from a file. If push is set, push the
3768 * old input onto the stack first.
3769 */
3770
3771static void
3772setinputfile(const char *fname, int push)
3773{
3774 int fd;
3775 int myfileno2;
3776
3777 INTOFF;
3778 if ((fd = open(fname, O_RDONLY)) < 0)
3779 error("Can't open %s", fname);
3780 if (fd < 10) {
3781 myfileno2 = dup_as_newfd(fd, 10);
3782 close(fd);
3783 if (myfileno2 < 0)
3784 error("Out of file descriptors");
3785 fd = myfileno2;
3786 }
3787 setinputfd(fd, push);
3788 INTON;
3789}
3790
2177 3791
2178static void 3792static void
2179tryexec(cmd, argv, envp) 3793tryexec(cmd, argv, envp)
@@ -2182,119 +3796,21 @@ tryexec(cmd, argv, envp)
2182 char **envp; 3796 char **envp;
2183 { 3797 {
2184 int e; 3798 int e;
2185#if !defined(BSD) && !defined(linux)
2186 char *p;
2187#endif
2188 3799
2189#ifdef SYSV
2190 do {
2191 execve(cmd, argv, envp);
2192 } while (errno == EINTR);
2193#else
2194 execve(cmd, argv, envp); 3800 execve(cmd, argv, envp);
2195#endif
2196 e = errno; 3801 e = errno;
2197 if (e == ENOEXEC) { 3802 if (e == ENOEXEC) {
2198 INTOFF; 3803 INTOFF;
2199 initshellproc(); 3804 initshellproc();
2200 setinputfile(cmd, 0); 3805 setinputfile(cmd, 0);
2201 commandname = arg0 = savestr(argv[0]); 3806 commandname = arg0 = savestr(argv[0]);
2202#if !defined(BSD) && !defined(linux)
2203 INTON;
2204 pgetc(); pungetc(); /* fill up input buffer */
2205 p = parsenextc;
2206 if (parsenleft > 2 && p[0] == '#' && p[1] == '!') {
2207 argv[0] = cmd;
2208 execinterp(argv, envp);
2209 }
2210 INTOFF;
2211#endif
2212 setparam(argv + 1); 3807 setparam(argv + 1);
2213 exraise(EXSHELLPROC); 3808 exraise(EXSHELLPROC);
2214 } 3809 }
2215 errno = e; 3810 errno = e;
2216} 3811}
2217 3812
2218 3813static char *commandtext (const union node *);
2219#if !defined(BSD) && !defined(linux)
2220/*
2221 * Execute an interpreter introduced by "#!", for systems where this
2222 * feature has not been built into the kernel. If the interpreter is
2223 * the shell, return (effectively ignoring the "#!"). If the execution
2224 * of the interpreter fails, exit.
2225 *
2226 * This code peeks inside the input buffer in order to avoid actually
2227 * reading any input. It would benefit from a rewrite.
2228 */
2229
2230#define NEWARGS 5
2231
2232static void
2233execinterp(argv, envp)
2234 char **argv, **envp;
2235 {
2236 int n;
2237 char *inp;
2238 char *outp;
2239 char c;
2240 char *p;
2241 char **ap;
2242 char *newargs[NEWARGS];
2243 int i;
2244 char **ap2;
2245 char **new;
2246
2247 n = parsenleft - 2;
2248 inp = parsenextc + 2;
2249 ap = newargs;
2250 for (;;) {
2251 while (--n >= 0 && (*inp == ' ' || *inp == '\t'))
2252 inp++;
2253 if (n < 0)
2254 goto bad;
2255 if ((c = *inp++) == '\n')
2256 break;
2257 if (ap == &newargs[NEWARGS])
2258bad: error("Bad #! line");
2259 STARTSTACKSTR(outp);
2260 do {
2261 STPUTC(c, outp);
2262 } while (--n >= 0 && (c = *inp++) != ' ' && c != '\t' && c != '\n');
2263 STPUTC('\0', outp);
2264 n++, inp--;
2265 *ap++ = grabstackstr(outp);
2266 }
2267 if (ap == newargs + 1) { /* if no args, maybe no exec is needed */
2268 p = newargs[0];
2269 for (;;) {
2270 if (equal(p, "sh") || equal(p, "ash")) {
2271 return;
2272 }
2273 while (*p != '/') {
2274 if (*p == '\0')
2275 goto break2;
2276 p++;
2277 }
2278 p++;
2279 }
2280break2:;
2281 }
2282 i = (char *)ap - (char *)newargs; /* size in bytes */
2283 if (i == 0)
2284 error("Bad #! line");
2285 for (ap2 = argv ; *ap2++ != NULL ; );
2286 new = ckmalloc(i + ((char *)ap2 - (char *)argv));
2287 ap = newargs, ap2 = new;
2288 while ((i -= sizeof (char **)) >= 0)
2289 *ap2++ = *ap++;
2290 ap = argv;
2291 while (*ap2++ = *ap++);
2292 shellexec(new, envp, pathval(), 0);
2293 /* NOTREACHED */
2294}
2295#endif
2296
2297
2298 3814
2299/* 3815/*
2300 * Do a path search. The variable path (passed by reference) should be 3816 * Do a path search. The variable path (passed by reference) should be
@@ -2308,11 +3824,12 @@ break2:;
2308 3824
2309static const char *pathopt; 3825static const char *pathopt;
2310 3826
3827static void growstackblock(void);
3828
3829
2311static char * 3830static char *
2312padvance(path, name) 3831padvance(const char **path, const char *name)
2313 const char **path; 3832{
2314 const char *name;
2315 {
2316 const char *p; 3833 const char *p;
2317 char *q; 3834 char *q;
2318 const char *start; 3835 const char *start;
@@ -2322,7 +3839,7 @@ padvance(path, name)
2322 return NULL; 3839 return NULL;
2323 start = *path; 3840 start = *path;
2324 for (p = start ; *p && *p != ':' && *p != '%' ; p++); 3841 for (p = start ; *p && *p != ':' && *p != '%' ; p++);
2325 len = p - start + strlen(name) + 2; /* "2" is for '/' and '\0' */ 3842 len = p - start + strlen(name) + 2; /* "2" is for '/' and '\0' */
2326 while (stackblocksize() < len) 3843 while (stackblocksize() < len)
2327 growstackblock(); 3844 growstackblock();
2328 q = stackblock(); 3845 q = stackblock();
@@ -2442,12 +3959,10 @@ printentry(cmdp, verbose)
2442 * change the shellexec routine as well. 3959 * change the shellexec routine as well.
2443 */ 3960 */
2444 3961
3962static int prefix (const char *, const char *);
3963
2445static void 3964static void
2446find_command(name, entry, act, path) 3965find_command(const char *name, struct cmdentry *entry, int act, const char *path)
2447 char *name;
2448 struct cmdentry *entry;
2449 int act;
2450 const char *path;
2451{ 3966{
2452 struct tblentry *cmdp; 3967 struct tblentry *cmdp;
2453 int idx; 3968 int idx;
@@ -2465,10 +3980,6 @@ find_command(name, entry, act, path)
2465 if (strchr(name, '/') != NULL) { 3980 if (strchr(name, '/') != NULL) {
2466 if (act & DO_ABS) { 3981 if (act & DO_ABS) {
2467 while (stat(name, &statb) < 0) { 3982 while (stat(name, &statb) < 0) {
2468 #ifdef SYSV
2469 if (errno == EINTR)
2470 continue;
2471 #endif
2472 if (errno != ENOENT && errno != ENOTDIR) 3983 if (errno != ENOENT && errno != ENOTDIR)
2473 e = errno; 3984 e = errno;
2474 entry->cmdtype = CMDUNKNOWN; 3985 entry->cmdtype = CMDUNKNOWN;
@@ -2516,11 +4027,11 @@ find_command(name, entry, act, path)
2516 } 4027 }
2517 4028
2518 bcmd = find_builtin(name); 4029 bcmd = find_builtin(name);
2519 regular = bcmd && bcmd->flags & BUILTIN_REGULAR; 4030 regular = bcmd && IS_BUILTIN_REGULAR(bcmd);
2520 4031
2521 if (regular) { 4032 if (regular) {
2522 if (cmdp && (cmdp->cmdtype == CMDBUILTIN)) { 4033 if (cmdp && (cmdp->cmdtype == CMDBUILTIN)) {
2523 goto success; 4034 goto success;
2524 } 4035 }
2525 } else if (act & DO_BRUTE) { 4036 } else if (act & DO_BRUTE) {
2526 if (firstchange == 0) { 4037 if (firstchange == 0) {
@@ -2545,8 +4056,8 @@ builtin:
2545 } 4056 }
2546 4057
2547 /* We have to search path. */ 4058 /* We have to search path. */
2548 prev = -1; /* where to start */ 4059 prev = -1; /* where to start */
2549 if (cmdp && cmdp->rehash) { /* doing a rehash */ 4060 if (cmdp && cmdp->rehash) { /* doing a rehash */
2550 if (cmdp->cmdtype == CMDBUILTIN) 4061 if (cmdp->cmdtype == CMDBUILTIN)
2551 prev = builtinloc; 4062 prev = builtinloc;
2552 else 4063 else
@@ -2572,7 +4083,7 @@ loop:
2572 prefix("func", pathopt)) { 4083 prefix("func", pathopt)) {
2573 /* handled below */ 4084 /* handled below */
2574 } else { 4085 } else {
2575 continue; /* ignore unimplemented options */ 4086 continue; /* ignore unimplemented options */
2576 } 4087 }
2577 } 4088 }
2578 /* if rehash, don't redo absolute path names */ 4089 /* if rehash, don't redo absolute path names */
@@ -2584,18 +4095,14 @@ loop:
2584 goto success; 4095 goto success;
2585 } 4096 }
2586 while (stat(fullname, &statb) < 0) { 4097 while (stat(fullname, &statb) < 0) {
2587#ifdef SYSV
2588 if (errno == EINTR)
2589 continue;
2590#endif
2591 if (errno != ENOENT && errno != ENOTDIR) 4098 if (errno != ENOENT && errno != ENOTDIR)
2592 e = errno; 4099 e = errno;
2593 goto loop; 4100 goto loop;
2594 } 4101 }
2595 e = EACCES; /* if we fail, this will be the error */ 4102 e = EACCES; /* if we fail, this will be the error */
2596 if (!S_ISREG(statb.st_mode)) 4103 if (!S_ISREG(statb.st_mode))
2597 continue; 4104 continue;
2598 if (pathopt) { /* this is a %func directory */ 4105 if (pathopt) { /* this is a %func directory */
2599 stalloc(strlen(fullname) + 1); 4106 stalloc(strlen(fullname) + 1);
2600 readcmdfile(fullname); 4107 readcmdfile(fullname);
2601 if ((cmdp = cmdlookup(name, 0)) == NULL || cmdp->cmdtype != CMDFUNCTION) 4108 if ((cmdp = cmdlookup(name, 0)) == NULL || cmdp->cmdtype != CMDFUNCTION)
@@ -2603,18 +4110,6 @@ loop:
2603 stunalloc(fullname); 4110 stunalloc(fullname);
2604 goto success; 4111 goto success;
2605 } 4112 }
2606#ifdef notdef
2607 if (statb.st_uid == geteuid()) {
2608 if ((statb.st_mode & 0100) == 0)
2609 goto loop;
2610 } else if (statb.st_gid == getegid()) {
2611 if ((statb.st_mode & 010) == 0)
2612 goto loop;
2613 } else {
2614 if ((statb.st_mode & 01) == 0)
2615 goto loop;
2616 }
2617#endif
2618 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname)); 4113 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
2619 /* If we aren't called with DO_BRUTE and cmdp is set, it must 4114 /* If we aren't called with DO_BRUTE and cmdp is set, it must
2620 be a function and we're being called with DO_NOFUN */ 4115 be a function and we're being called with DO_NOFUN */
@@ -2651,14 +4146,19 @@ success:
2651 * Search the table of builtin commands. 4146 * Search the table of builtin commands.
2652 */ 4147 */
2653 4148
2654struct builtincmd * 4149static int
2655find_builtin(name) 4150bstrcmp(const void *name, const void *b)
2656 char *name; 4151{
4152 return strcmp((const char *)name, (*(const char *const *) b)+1);
4153}
4154
4155static struct builtincmd *
4156find_builtin(const char *name)
2657{ 4157{
2658 struct builtincmd *bp; 4158 struct builtincmd *bp;
2659 4159
2660 bp = bsearch( &name, builtincmds, NUMBUILTINS, sizeof(struct builtincmd), 4160 bp = bsearch(name, builtincmds, NUMBUILTINS, sizeof(struct builtincmd),
2661 pstrcmp 4161 bstrcmp
2662 ); 4162 );
2663 return bp; 4163 return bp;
2664} 4164}
@@ -2670,7 +4170,7 @@ find_builtin(name)
2670 */ 4170 */
2671 4171
2672static void 4172static void
2673hashcd() { 4173hashcd(void) {
2674 struct tblentry **pp; 4174 struct tblentry **pp;
2675 struct tblentry *cmdp; 4175 struct tblentry *cmdp;
2676 4176
@@ -2692,15 +4192,14 @@ hashcd() {
2692 */ 4192 */
2693 4193
2694static void 4194static void
2695changepath(newval) 4195changepath(const char *newval)
2696 const char *newval;
2697{ 4196{
2698 int firstchange; 4197 int firstchange;
2699 int bltin; 4198 int bltin;
2700 4199
2701 firstchange = path_change(newval, &bltin); 4200 firstchange = path_change(newval, &bltin);
2702 if (builtinloc < 0 && bltin >= 0) 4201 if (builtinloc < 0 && bltin >= 0)
2703 builtinloc = bltin; /* zap builtins */ 4202 builtinloc = bltin; /* zap builtins */
2704 clearcmdentry(firstchange); 4203 clearcmdentry(firstchange);
2705 builtinloc = bltin; 4204 builtinloc = bltin;
2706} 4205}
@@ -2737,21 +4236,24 @@ clearcmdentry(firstchange)
2737 INTON; 4236 INTON;
2738} 4237}
2739 4238
2740
2741/* 4239/*
2742 * Delete all functions. 4240 * Free a parse tree.
2743 */ 4241 */
2744 4242
2745#ifdef mkinit 4243static void
2746static void deletefuncs __P((void)); 4244freefunc(union node *n)
2747 4245{
2748SHELLPROC { 4246 if (n)
2749 deletefuncs(); 4247 ckfree(n);
2750} 4248}
2751#endif 4249
4250
4251/*
4252 * Delete all functions.
4253 */
2752 4254
2753static void 4255static void
2754deletefuncs() { 4256deletefuncs(void) {
2755 struct tblentry **tblp; 4257 struct tblentry **tblp;
2756 struct tblentry **pp; 4258 struct tblentry **pp;
2757 struct tblentry *cmdp; 4259 struct tblentry *cmdp;
@@ -2782,16 +4284,13 @@ deletefuncs() {
2782 * entry. 4284 * entry.
2783 */ 4285 */
2784 4286
2785struct tblentry **lastcmdentry; 4287static struct tblentry **lastcmdentry;
2786
2787 4288
2788static struct tblentry * 4289static struct tblentry *
2789cmdlookup(name, add) 4290cmdlookup(const char *name, int add)
2790 char *name;
2791 int add;
2792{ 4291{
2793 int hashval; 4292 int hashval;
2794 char *p; 4293 const char *p;
2795 struct tblentry *cmdp; 4294 struct tblentry *cmdp;
2796 struct tblentry **pp; 4295 struct tblentry **pp;
2797 4296
@@ -2837,35 +4336,14 @@ delete_cmd_entry() {
2837 4336
2838 4337
2839 4338
2840#ifdef notdef
2841static void
2842getcmdentry(name, entry)
2843 char *name;
2844 struct cmdentry *entry;
2845 {
2846 struct tblentry *cmdp = cmdlookup(name, 0);
2847
2848 if (cmdp) {
2849 entry->u = cmdp->param;
2850 entry->cmdtype = cmdp->cmdtype;
2851 } else {
2852 entry->cmdtype = CMDUNKNOWN;
2853 entry->u.index = 0;
2854 }
2855}
2856#endif
2857
2858
2859/* 4339/*
2860 * Add a new command entry, replacing any existing command entry for 4340 * Add a new command entry, replacing any existing command entry for
2861 * the same name. 4341 * the same name.
2862 */ 4342 */
2863 4343
2864static void 4344static void
2865addcmdentry(name, entry) 4345addcmdentry(char *name, struct cmdentry *entry)
2866 char *name; 4346{
2867 struct cmdentry *entry;
2868 {
2869 struct tblentry *cmdp; 4347 struct tblentry *cmdp;
2870 4348
2871 INTOFF; 4349 INTOFF;
@@ -2883,11 +4361,11 @@ addcmdentry(name, entry)
2883 * Define a shell function. 4361 * Define a shell function.
2884 */ 4362 */
2885 4363
4364static union node *copyfunc(union node *);
4365
2886static void 4366static void
2887defun(name, func) 4367defun(char *name, union node *func)
2888 char *name; 4368{
2889 union node *func;
2890 {
2891 struct cmdentry entry; 4369 struct cmdentry entry;
2892 4370
2893 entry.cmdtype = CMDFUNCTION; 4371 entry.cmdtype = CMDFUNCTION;
@@ -2901,9 +4379,8 @@ defun(name, func)
2901 */ 4379 */
2902 4380
2903static void 4381static void
2904unsetfunc(name) 4382unsetfunc(char *name)
2905 char *name; 4383{
2906 {
2907 struct tblentry *cmdp; 4384 struct tblentry *cmdp;
2908 4385
2909 if ((cmdp = cmdlookup(name, 0)) != NULL && cmdp->cmdtype == CMDFUNCTION) { 4386 if ((cmdp = cmdlookup(name, 0)) != NULL && cmdp->cmdtype == CMDFUNCTION) {
@@ -2912,6 +4389,26 @@ unsetfunc(name)
2912 } 4389 }
2913} 4390}
2914 4391
4392/*
4393 * Wrapper around strcmp for qsort/bsearch/...
4394 */
4395static int
4396pstrcmp(const void *a, const void *b)
4397{
4398 return strcmp((const char *) a, *(const char *const *) b);
4399}
4400
4401/*
4402 * Find a keyword is in a sorted array.
4403 */
4404
4405static const char *const *
4406findkwd(const char *s)
4407{
4408 return bsearch(s, parsekwd, sizeof(parsekwd) / sizeof(const char *),
4409 sizeof(const char *), pstrcmp);
4410}
4411
2915#ifdef ASH_TYPE 4412#ifdef ASH_TYPE
2916/* 4413/*
2917 * Locate and print what a word is... 4414 * Locate and print what a word is...
@@ -2932,13 +4429,13 @@ typecmd(argc, argv)
2932} 4429}
2933 4430
2934static int 4431static int
2935describe_command(command, verbose) 4432describe_command(char *command, int verbose)
2936 char *command;
2937 int verbose;
2938{ 4433{
2939 struct cmdentry entry; 4434 struct cmdentry entry;
2940 struct tblentry *cmdp; 4435 struct tblentry *cmdp;
4436#ifdef ASH_ALIAS
2941 const struct alias *ap; 4437 const struct alias *ap;
4438#endif
2942 const char *path = pathval(); 4439 const char *path = pathval();
2943 4440
2944 if (verbose) { 4441 if (verbose) {
@@ -2951,6 +4448,7 @@ describe_command(command, verbose)
2951 goto out; 4448 goto out;
2952 } 4449 }
2953 4450
4451#ifdef ASH_ALIAS
2954 /* Then look at the aliases */ 4452 /* Then look at the aliases */
2955 if ((ap = lookupalias(command, 0)) != NULL) { 4453 if ((ap = lookupalias(command, 0)) != NULL) {
2956 if (verbose) { 4454 if (verbose) {
@@ -2960,7 +4458,7 @@ describe_command(command, verbose)
2960 } 4458 }
2961 goto out; 4459 goto out;
2962 } 4460 }
2963 4461#endif
2964 /* Then check if it is a tracked alias */ 4462 /* Then check if it is a tracked alias */
2965 if ((cmdp = cmdlookup(command, 0)) != NULL) { 4463 if ((cmdp = cmdlookup(command, 0)) != NULL) {
2966 entry.cmdtype = cmdp->cmdtype; 4464 entry.cmdtype = cmdp->cmdtype;
@@ -3005,7 +4503,7 @@ describe_command(command, verbose)
3005 if (verbose) { 4503 if (verbose) {
3006 out1fmt( 4504 out1fmt(
3007 " is a %sshell builtin", 4505 " is a %sshell builtin",
3008 entry.u.cmd->flags & BUILTIN_SPECIAL ? 4506 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
3009 "special " : nullstr 4507 "special " : nullstr
3010 ); 4508 );
3011 } else { 4509 } else {
@@ -3024,8 +4522,9 @@ out:
3024 out1c('\n'); 4522 out1c('\n');
3025 return 0; 4523 return 0;
3026} 4524}
3027#endif 4525#endif
3028 4526
4527#ifdef ASH_CMDCMD
3029static int 4528static int
3030commandcmd(argc, argv) 4529commandcmd(argc, argv)
3031 int argc; 4530 int argc;
@@ -3066,10 +4565,11 @@ commandcmd(argc, argv)
3066 if (verify_only || verbose_verify_only) { 4565 if (verify_only || verbose_verify_only) {
3067 return describe_command(*argptr, verbose_verify_only); 4566 return describe_command(*argptr, verbose_verify_only);
3068 } 4567 }
3069#endif 4568#endif
3070 4569
3071 return 0; 4570 return 0;
3072} 4571}
4572#endif
3073 4573
3074static int 4574static int
3075path_change(newval, bltin) 4575path_change(newval, bltin)
@@ -3082,7 +4582,7 @@ path_change(newval, bltin)
3082 4582
3083 old = pathval(); 4583 old = pathval();
3084 new = newval; 4584 new = newval;
3085 firstchange = 9999; /* assume no change */ 4585 firstchange = 9999; /* assume no change */
3086 idx = 0; 4586 idx = 0;
3087 *bltin = -1; 4587 *bltin = -1;
3088 for (;;) { 4588 for (;;) {
@@ -3091,7 +4591,7 @@ path_change(newval, bltin)
3091 if ((*old == '\0' && *new == ':') 4591 if ((*old == '\0' && *new == ':')
3092 || (*old == ':' && *new == '\0')) 4592 || (*old == ':' && *new == '\0'))
3093 firstchange++; 4593 firstchange++;
3094 old = new; /* ignore subsequent differences */ 4594 old = new; /* ignore subsequent differences */
3095 } 4595 }
3096 if (*new == '\0') 4596 if (*new == '\0')
3097 break; 4597 break;
@@ -3106,8 +4606,6 @@ path_change(newval, bltin)
3106 firstchange = 0; 4606 firstchange = 0;
3107 return firstchange; 4607 return firstchange;
3108} 4608}
3109/* $NetBSD: expand.c,v 1.50 2001/02/04 19:52:06 christos Exp $ */
3110
3111/* 4609/*
3112 * Routines to expand arguments to commands. We have to deal with 4610 * Routines to expand arguments to commands. We have to deal with
3113 * backquotes, shell variables, and file metacharacters. 4611 * backquotes, shell variables, and file metacharacters.
@@ -3115,8 +4613,8 @@ path_change(newval, bltin)
3115/* 4613/*
3116 * _rmescape() flags 4614 * _rmescape() flags
3117 */ 4615 */
3118#define RMESCAPE_ALLOC 0x1 /* Allocate a new string */ 4616#define RMESCAPE_ALLOC 0x1 /* Allocate a new string */
3119#define RMESCAPE_GLOB 0x2 /* Add backslashes for glob */ 4617#define RMESCAPE_GLOB 0x2 /* Add backslashes for glob */
3120 4618
3121/* 4619/*
3122 * Structure specifying which parts of the string should be searched 4620 * Structure specifying which parts of the string should be searched
@@ -3124,66 +4622,62 @@ path_change(newval, bltin)
3124 */ 4622 */
3125 4623
3126struct ifsregion { 4624struct ifsregion {
3127 struct ifsregion *next; /* next region in list */ 4625 struct ifsregion *next; /* next region in list */
3128 int begoff; /* offset of start of region */ 4626 int begoff; /* offset of start of region */
3129 int endoff; /* offset of end of region */ 4627 int endoff; /* offset of end of region */
3130 int nulonly; /* search for nul bytes only */ 4628 int nulonly; /* search for nul bytes only */
3131}; 4629};
3132 4630
3133 4631
3134static char *expdest; /* output of current string */ 4632static char *expdest; /* output of current string */
3135struct nodelist *argbackq; /* list of back quote expressions */ 4633static struct nodelist *argbackq; /* list of back quote expressions */
3136struct ifsregion ifsfirst; /* first struct in list of ifs regions */ 4634static struct ifsregion ifsfirst; /* first struct in list of ifs regions */
3137struct ifsregion *ifslastp; /* last struct in list */ 4635static struct ifsregion *ifslastp; /* last struct in list */
3138struct arglist exparg; /* holds expanded arg list */ 4636static struct arglist exparg; /* holds expanded arg list */
3139 4637
3140static void argstr __P((char *, int)); 4638static void argstr (char *, int);
3141static char *exptilde __P((char *, int)); 4639static char *exptilde (char *, int);
3142static void expbackq __P((union node *, int, int)); 4640static void expbackq (union node *, int, int);
3143static int subevalvar __P((char *, char *, int, int, int, int, int)); 4641static int subevalvar (char *, char *, int, int, int, int, int);
3144static char *evalvar __P((char *, int)); 4642static char *evalvar (char *, int);
3145static int varisset __P((char *, int)); 4643static int varisset (char *, int);
3146static void strtodest __P((const char *, const char *, int)); 4644static void strtodest (const char *, const char *, int);
3147static void varvalue __P((char *, int, int)); 4645static void varvalue (char *, int, int);
3148static void recordregion __P((int, int, int)); 4646static void recordregion (int, int, int);
3149static void removerecordregions __P((int)); 4647static void removerecordregions (int);
3150static void ifsbreakup __P((char *, struct arglist *)); 4648static void ifsbreakup (char *, struct arglist *);
3151static void ifsfree __P((void)); 4649static void ifsfree (void);
3152static void expandmeta __P((struct strlist *, int)); 4650static void expandmeta (struct strlist *, int);
3153#if defined(__GLIBC__) && !defined(FNMATCH_BROKEN) 4651#if defined(__GLIBC__) && !defined(FNMATCH_BROKEN)
3154#define preglob(p) _rmescapes((p), RMESCAPE_ALLOC | RMESCAPE_GLOB) 4652#define preglob(p) _rmescapes((p), RMESCAPE_ALLOC | RMESCAPE_GLOB)
3155#if !defined(GLOB_BROKEN) 4653#if !defined(GLOB_BROKEN)
3156static void addglob __P((const glob_t *)); 4654static void addglob (const glob_t *);
3157#endif 4655#endif
3158#endif 4656#endif
3159#if !(defined(__GLIBC__) && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN)) 4657#if !(defined(__GLIBC__) && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN))
3160static void expmeta __P((char *, char *)); 4658static void expmeta (char *, char *);
3161#endif 4659#endif
3162static void addfname __P((char *));
3163#if !(defined(__GLIBC__) && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN)) 4660#if !(defined(__GLIBC__) && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN))
3164static struct strlist *expsort __P((struct strlist *)); 4661static struct strlist *expsort (struct strlist *);
3165static struct strlist *msort __P((struct strlist *, int)); 4662static struct strlist *msort (struct strlist *, int);
3166#endif 4663#endif
3167#if defined(__GLIBC__) && !defined(FNMATCH_BROKEN) 4664#if defined(__GLIBC__) && !defined(FNMATCH_BROKEN)
3168static int patmatch __P((char *, char *, int)); 4665static int patmatch (char *, char *, int);
3169static int patmatch2 __P((char *, char *, int)); 4666static int patmatch2 (char *, char *, int);
3170#else 4667#else
3171static int pmatch __P((char *, char *, int)); 4668static int pmatch (char *, char *, int);
3172#define patmatch2 patmatch 4669#define patmatch2 patmatch
3173#endif 4670#endif
3174static char *cvtnum __P((int, char *)); 4671static char *cvtnum (int, char *);
3175
3176extern int oexitstatus;
3177 4672
3178/* 4673/*
3179 * Expand shell variables and backquotes inside a here document. 4674 * Expand shell variables and backquotes inside a here document.
3180 */ 4675 */
3181 4676
4677/* arg: the document, fd: where to write the expanded version */
3182static void 4678static void
3183expandhere(arg, fd) 4679expandhere(union node *arg, int fd)
3184 union node *arg; /* the document */ 4680{
3185 int fd; /* where to write the expanded version */
3186 {
3187 herefd = fd; 4681 herefd = fd;
3188 expandarg(arg, (struct arglist *)NULL, 0); 4682 expandarg(arg, (struct arglist *)NULL, 0);
3189 xwrite(fd, stackblock(), expdest - stackblock()); 4683 xwrite(fd, stackblock(), expdest - stackblock());
@@ -3212,7 +4706,7 @@ expandarg(arg, arglist, flag)
3212 ifslastp = NULL; 4706 ifslastp = NULL;
3213 argstr(arg->narg.text, flag); 4707 argstr(arg->narg.text, flag);
3214 if (arglist == NULL) { 4708 if (arglist == NULL) {
3215 return; /* here document expanded */ 4709 return; /* here document expanded */
3216 } 4710 }
3217 STPUTC('\0', expdest); 4711 STPUTC('\0', expdest);
3218 p = grabstackstr(expdest); 4712 p = grabstackstr(expdest);
@@ -3255,7 +4749,7 @@ argstr(p, flag)
3255 int flag; 4749 int flag;
3256{ 4750{
3257 char c; 4751 char c;
3258 int quotes = flag & (EXP_FULL | EXP_CASE); /* do CTLESC */ 4752 int quotes = flag & (EXP_FULL | EXP_CASE); /* do CTLESC */
3259 int firsteq = 1; 4753 int firsteq = 1;
3260 4754
3261 if (*p == '~' && (flag & (EXP_TILDE | EXP_VARTILDE))) 4755 if (*p == '~' && (flag & (EXP_TILDE | EXP_VARTILDE)))
@@ -3290,7 +4784,7 @@ argstr(p, flag)
3290 case CTLENDARI: 4784 case CTLENDARI:
3291 expari(flag); 4785 expari(flag);
3292 break; 4786 break;
3293#endif 4787#endif
3294 case ':': 4788 case ':':
3295 case '=': 4789 case '=':
3296 /* 4790 /*
@@ -3362,9 +4856,8 @@ lose:
3362} 4856}
3363 4857
3364 4858
3365static void 4859static void
3366removerecordregions(endoff) 4860removerecordregions(int endoff)
3367 int endoff;
3368{ 4861{
3369 if (ifslastp == NULL) 4862 if (ifslastp == NULL)
3370 return; 4863 return;
@@ -3386,7 +4879,7 @@ removerecordregions(endoff)
3386 } 4879 }
3387 return; 4880 return;
3388 } 4881 }
3389 4882
3390 ifslastp = &ifsfirst; 4883 ifslastp = &ifsfirst;
3391 while (ifslastp->next && ifslastp->next->begoff < endoff) 4884 while (ifslastp->next && ifslastp->next->begoff < endoff)
3392 ifslastp=ifslastp->next; 4885 ifslastp=ifslastp->next;
@@ -3409,8 +4902,7 @@ removerecordregions(endoff)
3409 * evaluate, place result in (backed up) result, adjust string position. 4902 * evaluate, place result in (backed up) result, adjust string position.
3410 */ 4903 */
3411static void 4904static void
3412expari(flag) 4905expari(int flag)
3413 int flag;
3414{ 4906{
3415 char *p, *start; 4907 char *p, *start;
3416 int result; 4908 int result;
@@ -3418,7 +4910,7 @@ expari(flag)
3418 int quotes = flag & (EXP_FULL | EXP_CASE); 4910 int quotes = flag & (EXP_FULL | EXP_CASE);
3419 int quoted; 4911 int quoted;
3420 4912
3421 /* ifsfree(); */ 4913 /* ifsfree(); */
3422 4914
3423 /* 4915 /*
3424 * This routine is slightly over-complicated for 4916 * This routine is slightly over-complicated for
@@ -3462,8 +4954,7 @@ expari(flag)
3462 result = expdest - p + 1; 4954 result = expdest - p + 1;
3463 STADJUST(-result, expdest); 4955 STADJUST(-result, expdest);
3464} 4956}
3465#endif 4957#endif
3466
3467 4958
3468/* 4959/*
3469 * Expand stuff in backwards quotes. 4960 * Expand stuff in backwards quotes.
@@ -3573,8 +5064,6 @@ err2:
3573 INTON; 5064 INTON;
3574} 5065}
3575 5066
3576
3577
3578static int 5067static int
3579subevalvar(p, str, strloc, subtype, startloc, varflags, quotes) 5068subevalvar(p, str, strloc, subtype, startloc, varflags, quotes)
3580 char *p; 5069 char *p;
@@ -3630,7 +5119,7 @@ subevalvar(p, str, strloc, subtype, startloc, varflags, quotes)
3630 goto recordleft; 5119 goto recordleft;
3631 *loc = c; 5120 *loc = c;
3632 if (quotes && *loc == CTLESC) 5121 if (quotes && *loc == CTLESC)
3633 loc++; 5122 loc++;
3634 } 5123 }
3635 return 0; 5124 return 0;
3636 5125
@@ -3653,11 +5142,11 @@ subevalvar(p, str, strloc, subtype, startloc, varflags, quotes)
3653 return 0; 5142 return 0;
3654 5143
3655 case VSTRIMRIGHT: 5144 case VSTRIMRIGHT:
3656 for (loc = str - 1; loc >= startp;) { 5145 for (loc = str - 1; loc >= startp;) {
3657 if (patmatch2(str, loc, quotes)) 5146 if (patmatch2(str, loc, quotes))
3658 goto recordright; 5147 goto recordright;
3659 loc--; 5148 loc--;
3660 if (quotes && loc > startp && *(loc - 1) == CTLESC) { 5149 if (quotes && loc > startp && *(loc - 1) == CTLESC) {
3661 for (q = startp; q < loc; q++) 5150 for (q = startp; q < loc; q++)
3662 if (*q == CTLESC) 5151 if (*q == CTLESC)
3663 q++; 5152 q++;
@@ -3672,7 +5161,7 @@ subevalvar(p, str, strloc, subtype, startloc, varflags, quotes)
3672 if (patmatch2(str, loc, quotes)) 5161 if (patmatch2(str, loc, quotes))
3673 goto recordright; 5162 goto recordright;
3674 if (quotes && *loc == CTLESC) 5163 if (quotes && *loc == CTLESC)
3675 loc++; 5164 loc++;
3676 } 5165 }
3677 return 0; 5166 return 0;
3678 5167
@@ -3788,7 +5277,7 @@ record:
3788 case VSPLUS: 5277 case VSPLUS:
3789 case VSMINUS: 5278 case VSMINUS:
3790 if (!set) { 5279 if (!set) {
3791 argstr(p, flag); 5280 argstr(p, flag);
3792 break; 5281 break;
3793 } 5282 }
3794 if (easy) 5283 if (easy)
@@ -3822,9 +5311,9 @@ record:
3822 if (subevalvar(p, var, 0, subtype, startloc, 5311 if (subevalvar(p, var, 0, subtype, startloc,
3823 varflags, quotes)) { 5312 varflags, quotes)) {
3824 varflags &= ~VSNUL; 5313 varflags &= ~VSNUL;
3825 /* 5314 /*
3826 * Remove any recorded regions beyond 5315 * Remove any recorded regions beyond
3827 * start of variable 5316 * start of variable
3828 */ 5317 */
3829 removerecordregions(startloc); 5318 removerecordregions(startloc);
3830 goto again; 5319 goto again;
@@ -3841,7 +5330,7 @@ record:
3841#endif 5330#endif
3842 } 5331 }
3843 5332
3844 if (subtype != VSNORMAL) { /* skip to end of alternative */ 5333 if (subtype != VSNORMAL) { /* skip to end of alternative */
3845 int nesting = 1; 5334 int nesting = 1;
3846 for (;;) { 5335 for (;;) {
3847 if ((c = *p++) == CTLESC) 5336 if ((c = *p++) == CTLESC)
@@ -3861,8 +5350,6 @@ record:
3861 return p; 5350 return p;
3862} 5351}
3863 5352
3864
3865
3866/* 5353/*
3867 * Test whether a specialized variable is set. 5354 * Test whether a specialized variable is set.
3868 */ 5355 */
@@ -3904,8 +5391,6 @@ varisset(name, nulok)
3904 return 1; 5391 return 1;
3905} 5392}
3906 5393
3907
3908
3909/* 5394/*
3910 * Put a string on the stack. 5395 * Put a string on the stack.
3911 */ 5396 */
@@ -3923,8 +5408,6 @@ strtodest(p, syntax, quotes)
3923 } 5408 }
3924} 5409}
3925 5410
3926
3927
3928/* 5411/*
3929 * Add the value of a specialized variable to the stack string. 5412 * Add the value of a specialized variable to the stack string.
3930 */ 5413 */
@@ -3963,8 +5446,8 @@ numvar:
3963 break; 5446 break;
3964 case '-': 5447 case '-':
3965 for (i = 0 ; i < NOPTS ; i++) { 5448 for (i = 0 ; i < NOPTS ; i++) {
3966 if (optlist[i].val) 5449 if (optent_val(i))
3967 STPUTC(optlist[i].letter, expdest); 5450 STPUTC(optent_letter(optlist[i]), expdest);
3968 } 5451 }
3969 break; 5452 break;
3970 case '@': 5453 case '@':
@@ -4001,7 +5484,6 @@ param:
4001} 5484}
4002 5485
4003 5486
4004
4005/* 5487/*
4006 * Record the fact that we have to scan this region of the 5488 * Record the fact that we have to scan this region of the
4007 * string for IFS characters. 5489 * string for IFS characters.
@@ -4136,7 +5618,22 @@ ifsfree()
4136 ifsfirst.next = NULL; 5618 ifsfirst.next = NULL;
4137} 5619}
4138 5620
5621/*
5622 * Add a file name to the list.
5623 */
5624
5625static void
5626addfname(const char *name)
5627{
5628 char *p;
5629 struct strlist *sp;
4139 5630
5631 p = sstrdup(name);
5632 sp = (struct strlist *)stalloc(sizeof *sp);
5633 sp->text = p;
5634 *exparg.lastp = sp;
5635 exparg.lastp = &sp->next;
5636}
4140 5637
4141/* 5638/*
4142 * Expand shell metacharacters. At this point, the only control characters 5639 * Expand shell metacharacters. At this point, the only control characters
@@ -4175,7 +5672,7 @@ nometa:
4175 rmescapes(str->text); 5672 rmescapes(str->text);
4176 exparg.lastp = &str->next; 5673 exparg.lastp = &str->next;
4177 break; 5674 break;
4178 default: /* GLOB_NOSPACE */ 5675 default: /* GLOB_NOSPACE */
4179 error("Out of space"); 5676 error("Out of space");
4180 } 5677 }
4181 str = str->next; 5678 str = str->next;
@@ -4199,7 +5696,7 @@ addglob(pglob)
4199} 5696}
4200 5697
4201 5698
4202#else /* defined(__GLIBC__) && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN) */ 5699#else /* defined(__GLIBC__) && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN) */
4203static char *expdir; 5700static char *expdir;
4204 5701
4205 5702
@@ -4218,7 +5715,7 @@ expandmeta(str, flag)
4218 if (fflag) 5715 if (fflag)
4219 goto nometa; 5716 goto nometa;
4220 p = str->text; 5717 p = str->text;
4221 for (;;) { /* fast check for meta chars */ 5718 for (;;) { /* fast check for meta chars */
4222 if ((c = *p++) == '\0') 5719 if ((c = *p++) == '\0')
4223 goto nometa; 5720 goto nometa;
4224 if (c == '*' || c == '?' || c == '[' || c == '!') 5721 if (c == '*' || c == '?' || c == '[' || c == '!')
@@ -4297,7 +5794,7 @@ expmeta(enddir, name)
4297 break; 5794 break;
4298 } 5795 }
4299 } 5796 }
4300 } else if (*p == '!' && p[1] == '!' && (p == name || p[-1] == '/')) { 5797 } else if (*p == '!' && p[1] == '!' && (p == name || p[-1] == '/')) {
4301 metaflag = 1; 5798 metaflag = 1;
4302 } else if (*p == '\0') 5799 } else if (*p == '\0')
4303 break; 5800 break;
@@ -4311,7 +5808,7 @@ expmeta(enddir, name)
4311 start = p + 1; 5808 start = p + 1;
4312 } 5809 }
4313 } 5810 }
4314 if (metaflag == 0) { /* we've reached the end of the file name */ 5811 if (metaflag == 0) { /* we've reached the end of the file name */
4315 if (enddir != expdir) 5812 if (enddir != expdir)
4316 metaflag++; 5813 metaflag++;
4317 for (p = name ; ; p++) { 5814 for (p = name ; ; p++) {
@@ -4369,7 +5866,7 @@ expmeta(enddir, name)
4369 continue; 5866 continue;
4370 if (patmatch(start, dp->d_name, 0)) { 5867 if (patmatch(start, dp->d_name, 0)) {
4371 if (atend) { 5868 if (atend) {
4372 scopy(dp->d_name, enddir); 5869 strcpy(enddir, dp->d_name);
4373 addfname(expdir); 5870 addfname(expdir);
4374 } else { 5871 } else {
4375 for (p = enddir, cp = dp->d_name; 5872 for (p = enddir, cp = dp->d_name;
@@ -4384,27 +5881,9 @@ expmeta(enddir, name)
4384 if (! atend) 5881 if (! atend)
4385 endname[-1] = '/'; 5882 endname[-1] = '/';
4386} 5883}
4387#endif /* defined(__GLIBC__) && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN) */ 5884#endif /* defined(__GLIBC__) && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN) */
4388 5885
4389 5886
4390/*
4391 * Add a file name to the list.
4392 */
4393
4394static void
4395addfname(name)
4396 char *name;
4397 {
4398 char *p;
4399 struct strlist *sp;
4400
4401 p = sstrdup(name);
4402 sp = (struct strlist *)stalloc(sizeof *sp);
4403 sp->text = p;
4404 *exparg.lastp = sp;
4405 exparg.lastp = &sp->next;
4406}
4407
4408 5887
4409#if !(defined(__GLIBC__) && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN)) 5888#if !(defined(__GLIBC__) && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN))
4410/* 5889/*
@@ -4445,9 +5924,9 @@ msort(list, len)
4445 q = p; 5924 q = p;
4446 p = p->next; 5925 p = p->next;
4447 } 5926 }
4448 q->next = NULL; /* terminate first half of list */ 5927 q->next = NULL; /* terminate first half of list */
4449 q = msort(list, half); /* sort first half of list */ 5928 q = msort(list, half); /* sort first half of list */
4450 p = msort(p, len - half); /* sort second half */ 5929 p = msort(p, len - half); /* sort second half */
4451 lpp = &list; 5930 lpp = &list;
4452 for (;;) { 5931 for (;;) {
4453 if (strcmp(p->text, q->text) < 0) { 5932 if (strcmp(p->text, q->text) < 0) {
@@ -4477,12 +5956,10 @@ msort(list, len)
4477 */ 5956 */
4478 5957
4479#if defined(__GLIBC__) && !defined(FNMATCH_BROKEN) 5958#if defined(__GLIBC__) && !defined(FNMATCH_BROKEN)
5959/* squoted: string might have quote chars */
4480static int 5960static int
4481patmatch(pattern, string, squoted) 5961patmatch(char *pattern, char *string, int squoted)
4482 char *pattern; 5962{
4483 char *string;
4484 int squoted; /* string might have quote chars */
4485 {
4486 const char *p; 5963 const char *p;
4487 char *q; 5964 char *q;
4488 5965
@@ -4494,11 +5971,8 @@ patmatch(pattern, string, squoted)
4494 5971
4495 5972
4496static int 5973static int
4497patmatch2(pattern, string, squoted) 5974patmatch2(char *pattern, char *string, int squoted)
4498 char *pattern; 5975{
4499 char *string;
4500 int squoted; /* string might have quote chars */
4501 {
4502 char *p; 5976 char *p;
4503 int res; 5977 int res;
4504 5978
@@ -4510,26 +5984,14 @@ patmatch2(pattern, string, squoted)
4510} 5984}
4511#else 5985#else
4512static int 5986static int
4513patmatch(pattern, string, squoted) 5987patmatch(char *pattern, char *string, int squoted) {
4514 char *pattern; 5988 return pmatch(pattern, string, squoted);
4515 char *string;
4516 int squoted; /* string might have quote chars */
4517 {
4518#ifdef notdef
4519 if (pattern[0] == '!' && pattern[1] == '!')
4520 return 1 - pmatch(pattern + 2, string);
4521 else
4522#endif
4523 return pmatch(pattern, string, squoted);
4524} 5989}
4525 5990
4526 5991
4527static int 5992static int
4528pmatch(pattern, string, squoted) 5993pmatch(char *pattern, char *string, int squoted)
4529 char *pattern; 5994{
4530 char *string;
4531 int squoted;
4532 {
4533 char *p, *q; 5995 char *p, *q;
4534 char c; 5996 char c;
4535 5997
@@ -4589,7 +6051,7 @@ pmatch(pattern, string, squoted)
4589 while (*endp == CTLQUOTEMARK) 6051 while (*endp == CTLQUOTEMARK)
4590 endp++; 6052 endp++;
4591 if (*endp == '\0') 6053 if (*endp == '\0')
4592 goto dft; /* no matching ] */ 6054 goto dft; /* no matching ] */
4593 if (*endp == CTLESC) 6055 if (*endp == CTLESC)
4594 endp++; 6056 endp++;
4595 if (*++endp == ']') 6057 if (*++endp == ']')
@@ -4630,7 +6092,7 @@ pmatch(pattern, string, squoted)
4630 return 0; 6092 return 0;
4631 break; 6093 break;
4632 } 6094 }
4633dft: default: 6095dft: default:
4634 if (squoted && *q == CTLESC) 6096 if (squoted && *q == CTLESC)
4635 q++; 6097 q++;
4636 if (*q++ != c) 6098 if (*q++ != c)
@@ -4653,9 +6115,7 @@ breakloop:
4653 6115
4654#if defined(__GLIBC__) && !defined(FNMATCH_BROKEN) 6116#if defined(__GLIBC__) && !defined(FNMATCH_BROKEN)
4655static char * 6117static char *
4656_rmescapes(str, flag) 6118_rmescapes(char *str, int flag)
4657 char *str;
4658 int flag;
4659{ 6119{
4660 char *p, *q, *r; 6120 char *p, *q, *r;
4661 static const char qchars[] = { CTLESC, CTLQUOTEMARK, 0 }; 6121 static const char qchars[] = { CTLESC, CTLQUOTEMARK, 0 };
@@ -4727,10 +6187,8 @@ rmescapes(str)
4727 */ 6187 */
4728 6188
4729static int 6189static int
4730casematch(pattern, val) 6190casematch(union node *pattern, const char *val)
4731 union node *pattern; 6191{
4732 char *val;
4733 {
4734 struct stackmark smark; 6192 struct stackmark smark;
4735 int result; 6193 int result;
4736 char *p; 6194 char *p;
@@ -4742,7 +6200,7 @@ casematch(pattern, val)
4742 argstr(pattern->narg.text, EXP_TILDE | EXP_CASE); 6200 argstr(pattern->narg.text, EXP_TILDE | EXP_CASE);
4743 STPUTC('\0', expdest); 6201 STPUTC('\0', expdest);
4744 p = grabstackstr(expdest); 6202 p = grabstackstr(expdest);
4745 result = patmatch(p, val, 0); 6203 result = patmatch(p, (char *)val, 0);
4746 popstackmark(&smark); 6204 popstackmark(&smark);
4747 return result; 6205 return result;
4748} 6206}
@@ -4763,8 +6221,6 @@ cvtnum(num, buf)
4763 STADJUST(len, buf); 6221 STADJUST(len, buf);
4764 return buf; 6222 return buf;
4765} 6223}
4766/* $NetBSD: histedit.c,v 1.25 2001/02/04 19:52:06 christos Exp $ */
4767
4768/* 6224/*
4769 * Editline and history functions (and glue). 6225 * Editline and history functions (and glue).
4770 */ 6226 */
@@ -4777,54 +6233,15 @@ static int histcmd(argc, argv)
4777} 6233}
4778 6234
4779 6235
4780/* 6236static int whichprompt; /* 1 == PS1, 2 == PS2 */
4781 * This file was generated by the mkinit program.
4782 */
4783
4784extern void rmaliases __P((void));
4785
4786extern int loopnest; /* current loop nesting level */
4787
4788extern void deletefuncs __P((void));
4789 6237
4790struct strpush {
4791 struct strpush *prev; /* preceding string on stack */
4792 char *prevstring;
4793 int prevnleft;
4794 struct alias *ap; /* if push was associated with an alias */
4795 char *string; /* remember the string since it may change */
4796};
4797
4798struct parsefile {
4799 struct parsefile *prev; /* preceding file on stack */
4800 int linno; /* current line */
4801 int fd; /* file descriptor (or -1 if string) */
4802 int nleft; /* number of chars left in this line */
4803 int lleft; /* number of chars left in this buffer */
4804 char *nextc; /* next char in buffer */
4805 char *buf; /* input buffer */
4806 struct strpush *strpush; /* for pushing strings at this level */
4807 struct strpush basestrpush; /* so pushing one is fast */
4808};
4809
4810extern int parselleft; /* copy of parsefile->lleft */
4811extern struct parsefile basepf; /* top level input file */
4812extern char basebuf[BUFSIZ]; /* buffer for top level input file */
4813
4814extern short backgndpid; /* pid of last background process */
4815extern int jobctl;
4816
4817extern int tokpushback; /* last token pushed back */
4818extern int checkkwd; /* 1 == check for kwds, 2 == also eat newlines */
4819 6238
4820struct redirtab { 6239struct redirtab {
4821 struct redirtab *next; 6240 struct redirtab *next;
4822 short renamed[10]; 6241 short renamed[10];
4823}; 6242};
4824 6243
4825extern struct redirtab *redirlist; 6244static struct redirtab *redirlist;
4826
4827extern char sigmode[NSIG - 1]; /* current value of signal */
4828 6245
4829extern char **environ; 6246extern char **environ;
4830 6247
@@ -4835,7 +6252,7 @@ extern char **environ;
4835 */ 6252 */
4836 6253
4837static void 6254static void
4838init() { 6255init(void) {
4839 6256
4840 /* from cd.c: */ 6257 /* from cd.c: */
4841 { 6258 {
@@ -4878,8 +6295,13 @@ init() {
4878 * interactive shell and control is returned to the main command loop. 6295 * interactive shell and control is returned to the main command loop.
4879 */ 6296 */
4880 6297
6298#ifdef ASH_ALIAS
6299/* 1 == check for aliases, 2 == also check for assignments */
6300static int checkalias;
6301#endif
6302
4881static void 6303static void
4882reset() { 6304reset(void) {
4883 6305
4884 /* from eval.c: */ 6306 /* from eval.c: */
4885 { 6307 {
@@ -4891,7 +6313,7 @@ reset() {
4891 /* from input.c: */ 6313 /* from input.c: */
4892 { 6314 {
4893 if (exception != EXSHELLPROC) 6315 if (exception != EXSHELLPROC)
4894 parselleft = parsenleft = 0; /* clear input buffer */ 6316 parselleft = parsenleft = 0; /* clear input buffer */
4895 popallfiles(); 6317 popallfiles();
4896 } 6318 }
4897 6319
@@ -4899,7 +6321,9 @@ reset() {
4899 { 6321 {
4900 tokpushback = 0; 6322 tokpushback = 0;
4901 checkkwd = 0; 6323 checkkwd = 0;
6324#ifdef ASH_ALIAS
4902 checkalias = 0; 6325 checkalias = 0;
6326#endif
4903 } 6327 }
4904 6328
4905 /* from redir.c: */ 6329 /* from redir.c: */
@@ -4926,69 +6350,6 @@ reset() {
4926 6350
4927 6351
4928/* 6352/*
4929 * This routine is called to initialize the shell to run a shell procedure.
4930 */
4931
4932static void
4933initshellproc() {
4934
4935 /* from alias.c: */
4936 {
4937 rmaliases();
4938 }
4939
4940 /* from eval.c: */
4941 {
4942 exitstatus = 0;
4943 }
4944
4945 /* from exec.c: */
4946 {
4947 deletefuncs();
4948 }
4949
4950 /* from jobs.c: */
4951 {
4952 backgndpid = -1;
4953#if JOBS
4954 jobctl = 0;
4955#endif
4956 }
4957
4958 /* from options.c: */
4959 {
4960 int i;
4961
4962 for (i = 0; i < NOPTS; i++)
4963 optlist[i].val = 0;
4964 optschanged();
4965
4966 }
4967
4968 /* from redir.c: */
4969 {
4970 clearredir();
4971 }
4972
4973 /* from trap.c: */
4974 {
4975 char *sm;
4976
4977 clear_traps();
4978 for (sm = sigmode ; sm < sigmode + NSIG - 1; sm++) {
4979 if (*sm == S_IGN)
4980 *sm = S_HARD_IGN;
4981 }
4982 }
4983
4984 /* from var.c: */
4985 {
4986 shprocvar();
4987 }
4988}
4989/* $NetBSD: input.c,v 1.35 2001/02/04 19:52:06 christos Exp $ */
4990
4991/*
4992 * This file implements the input routines used by the parser. 6353 * This file implements the input routines used by the parser.
4993 */ 6354 */
4994 6355
@@ -5004,45 +6365,34 @@ static inline void putprompt(const char *s) {
5004} 6365}
5005#endif 6366#endif
5006 6367
5007#define EOF_NLEFT -99 /* value of parsenleft when EOF pushed back */ 6368#define EOF_NLEFT -99 /* value of parsenleft when EOF pushed back */
5008
5009static int plinno = 1; /* input line number */
5010static int parsenleft; /* copy of parsefile->nleft */
5011static int parselleft; /* copy of parsefile->lleft */
5012static char *parsenextc; /* copy of parsefile->nextc */
5013struct parsefile basepf; /* top level input file */
5014static char basebuf[BUFSIZ]; /* buffer for top level input file */
5015struct parsefile *parsefile = &basepf; /* current input file */
5016static int whichprompt; /* 1 == PS1, 2 == PS2 */
5017 6369
5018static void pushfile __P((void));
5019static int preadfd __P((void));
5020 6370
5021#ifdef mkinit
5022INCLUDE <stdio.h>
5023INCLUDE "input.h"
5024INCLUDE "error.h"
5025 6371
5026INIT { 6372/*
5027 basepf.nextc = basepf.buf = basebuf; 6373 * Same as pgetc(), but ignores PEOA.
5028} 6374 */
5029 6375
5030RESET { 6376#ifdef ASH_ALIAS
5031 if (exception != EXSHELLPROC) 6377static int
5032 parselleft = parsenleft = 0; /* clear input buffer */ 6378pgetc2()
5033 popallfiles(); 6379{
6380 int c;
6381 do {
6382 c = pgetc_macro();
6383 } while (c == PEOA);
6384 return c;
5034} 6385}
6386#else
6387static inline int pgetc2() { return pgetc_macro(); }
5035#endif 6388#endif
5036 6389
5037
5038/* 6390/*
5039 * Read a line from the script. 6391 * Read a line from the script.
5040 */ 6392 */
5041 6393
5042static char * 6394static char *
5043pfgets(line, len) 6395pfgets(char *line, int len)
5044 char *line;
5045 int len;
5046{ 6396{
5047 char *p = line; 6397 char *p = line;
5048 int nleft = len; 6398 int nleft = len;
@@ -5063,36 +6413,8 @@ pfgets(line, len)
5063 return line; 6413 return line;
5064} 6414}
5065 6415
5066
5067/*
5068 * Read a character from the script, returning PEOF on end of file.
5069 * Nul characters in the input are silently discarded.
5070 */
5071
5072static int
5073pgetc()
5074{
5075 return pgetc_macro();
5076}
5077
5078
5079/*
5080 * Same as pgetc(), but ignores PEOA.
5081 */
5082
5083static int 6416static int
5084pgetc2() 6417preadfd(void)
5085{
5086 int c;
5087 do {
5088 c = pgetc_macro();
5089 } while (c == PEOA);
5090 return c;
5091}
5092
5093
5094static int
5095preadfd()
5096{ 6418{
5097 int nr; 6419 int nr;
5098 char *buf = parsefile->buf; 6420 char *buf = parsefile->buf;
@@ -5103,7 +6425,7 @@ retry:
5103 { 6425 {
5104 if (parsefile->fd) 6426 if (parsefile->fd)
5105 nr = read(parsefile->fd, buf, BUFSIZ - 1); 6427 nr = read(parsefile->fd, buf, BUFSIZ - 1);
5106 else { 6428 else {
5107 do { 6429 do {
5108 cmdedit_read_input((char*)cmdedit_prompt, buf); 6430 cmdedit_read_input((char*)cmdedit_prompt, buf);
5109 nr = strlen(buf); 6431 nr = strlen(buf);
@@ -5132,6 +6454,39 @@ retry:
5132 return nr; 6454 return nr;
5133} 6455}
5134 6456
6457static void
6458popstring(void)
6459{
6460 struct strpush *sp = parsefile->strpush;
6461
6462 INTOFF;
6463#ifdef ASH_ALIAS
6464 if (sp->ap) {
6465 if (parsenextc[-1] == ' ' || parsenextc[-1] == '\t') {
6466 if (!checkalias) {
6467 checkalias = 1;
6468 }
6469 }
6470 if (sp->string != sp->ap->val) {
6471 ckfree(sp->string);
6472 }
6473
6474 sp->ap->flag &= ~ALIASINUSE;
6475 if (sp->ap->flag & ALIASDEAD) {
6476 unalias(sp->ap->name);
6477 }
6478 }
6479#endif
6480 parsenextc = sp->prevstring;
6481 parsenleft = sp->prevnleft;
6482/*dprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/
6483 parsefile->strpush = sp->prev;
6484 if (sp != &(parsefile->basestrpush))
6485 ckfree(sp);
6486 INTON;
6487}
6488
6489
5135/* 6490/*
5136 * Refill the input buffer and return the next input character: 6491 * Refill the input buffer and return the next input character:
5137 * 6492 *
@@ -5143,19 +6498,19 @@ retry:
5143 */ 6498 */
5144 6499
5145static int 6500static int
5146preadbuffer() 6501preadbuffer(void)
5147{ 6502{
5148 char *p, *q; 6503 char *p, *q;
5149 int more; 6504 int more;
5150 char savec; 6505 char savec;
5151 6506
5152 while (parsefile->strpush) { 6507 while (parsefile->strpush) {
5153 if ( 6508#ifdef ASH_ALIAS
5154 parsenleft == -1 && parsefile->strpush->ap && 6509 if (parsenleft == -1 && parsefile->strpush->ap &&
5155 parsenextc[-1] != ' ' && parsenextc[-1] != '\t' 6510 parsenextc[-1] != ' ' && parsenextc[-1] != '\t') {
5156 ) {
5157 return PEOA; 6511 return PEOA;
5158 } 6512 }
6513#endif
5159 popstring(); 6514 popstring();
5160 if (--parsenleft >= 0) 6515 if (--parsenleft >= 0)
5161 return (*parsenextc++); 6516 return (*parsenextc++);
@@ -5181,7 +6536,7 @@ again:
5181 for (more = 1; more;) { 6536 for (more = 1; more;) {
5182 switch (*p) { 6537 switch (*p) {
5183 case '\0': 6538 case '\0':
5184 p++; /* Skip nul */ 6539 p++; /* Skip nul */
5185 goto check; 6540 goto check;
5186 6541
5187 6542
@@ -5216,27 +6571,14 @@ check:
5216 return *parsenextc++; 6571 return *parsenextc++;
5217} 6572}
5218 6573
5219/*
5220 * Undo the last call to pgetc. Only one character may be pushed back.
5221 * PEOF may be pushed back.
5222 */
5223
5224static void
5225pungetc() {
5226 parsenleft++;
5227 parsenextc--;
5228}
5229 6574
5230/* 6575/*
5231 * Push a string back onto the input at this current parsefile level. 6576 * Push a string back onto the input at this current parsefile level.
5232 * We handle aliases this way. 6577 * We handle aliases this way.
5233 */ 6578 */
5234static void 6579static void
5235pushstring(s, len, ap) 6580pushstring(char *s, int len, void *ap)
5236 char *s; 6581{
5237 int len;
5238 void *ap;
5239 {
5240 struct strpush *sp; 6582 struct strpush *sp;
5241 6583
5242 INTOFF; 6584 INTOFF;
@@ -5249,97 +6591,19 @@ pushstring(s, len, ap)
5249 sp = parsefile->strpush = &(parsefile->basestrpush); 6591 sp = parsefile->strpush = &(parsefile->basestrpush);
5250 sp->prevstring = parsenextc; 6592 sp->prevstring = parsenextc;
5251 sp->prevnleft = parsenleft; 6593 sp->prevnleft = parsenleft;
6594#ifdef ASH_ALIAS
5252 sp->ap = (struct alias *)ap; 6595 sp->ap = (struct alias *)ap;
5253 if (ap) { 6596 if (ap) {
5254 ((struct alias *)ap)->flag |= ALIASINUSE; 6597 ((struct alias *)ap)->flag |= ALIASINUSE;
5255 sp->string = s; 6598 sp->string = s;
5256 } 6599 }
6600#endif
5257 parsenextc = s; 6601 parsenextc = s;
5258 parsenleft = len; 6602 parsenleft = len;
5259 INTON; 6603 INTON;
5260} 6604}
5261 6605
5262static void
5263popstring()
5264{
5265 struct strpush *sp = parsefile->strpush;
5266 6606
5267 INTOFF;
5268 if (sp->ap) {
5269 if (parsenextc[-1] == ' ' || parsenextc[-1] == '\t') {
5270 if (!checkalias) {
5271 checkalias = 1;
5272 }
5273 }
5274 if (sp->string != sp->ap->val) {
5275 ckfree(sp->string);
5276 }
5277 sp->ap->flag &= ~ALIASINUSE;
5278 if (sp->ap->flag & ALIASDEAD) {
5279 unalias(sp->ap->name);
5280 }
5281 }
5282 parsenextc = sp->prevstring;
5283 parsenleft = sp->prevnleft;
5284/*dprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/
5285 parsefile->strpush = sp->prev;
5286 if (sp != &(parsefile->basestrpush))
5287 ckfree(sp);
5288 INTON;
5289}
5290
5291/*
5292 * Set the input to take input from a file. If push is set, push the
5293 * old input onto the stack first.
5294 */
5295
5296static void
5297setinputfile(fname, push)
5298 const char *fname;
5299 int push;
5300{
5301 int fd;
5302 int myfileno2;
5303
5304 INTOFF;
5305 if ((fd = open(fname, O_RDONLY)) < 0)
5306 error("Can't open %s", fname);
5307 if (fd < 10) {
5308 myfileno2 = dup_as_newfd(fd, 10);
5309 close(fd);
5310 if (myfileno2 < 0)
5311 error("Out of file descriptors");
5312 fd = myfileno2;
5313 }
5314 setinputfd(fd, push);
5315 INTON;
5316}
5317
5318
5319/*
5320 * Like setinputfile, but takes an open file descriptor. Call this with
5321 * interrupts off.
5322 */
5323
5324static void
5325setinputfd(fd, push)
5326 int fd, push;
5327{
5328 (void) fcntl(fd, F_SETFD, FD_CLOEXEC);
5329 if (push) {
5330 pushfile();
5331 parsefile->buf = 0;
5332 } else {
5333 closescript();
5334 while (parsefile->strpush)
5335 popstring();
5336 }
5337 parsefile->fd = fd;
5338 if (parsefile->buf == NULL)
5339 parsefile->buf = ckmalloc(BUFSIZ);
5340 parselleft = parsenleft = 0;
5341 plinno = 1;
5342}
5343 6607
5344 6608
5345/* 6609/*
@@ -5367,7 +6631,7 @@ setinputstring(string)
5367 */ 6631 */
5368 6632
5369static void 6633static void
5370pushfile() { 6634pushfile(void) {
5371 struct parsefile *pf; 6635 struct parsefile *pf;
5372 6636
5373 parsefile->nleft = parsenleft; 6637 parsefile->nleft = parsenleft;
@@ -5382,79 +6646,42 @@ pushfile() {
5382 parsefile = pf; 6646 parsefile = pf;
5383} 6647}
5384 6648
5385 6649#ifdef JOBS
5386static void 6650static void restartjob (struct job *);
5387popfile() { 6651#endif
5388 struct parsefile *pf = parsefile; 6652static void freejob (struct job *);
5389 6653static struct job *getjob (const char *);
5390 INTOFF; 6654static int dowait (int, struct job *);
5391 if (pf->fd >= 0) 6655static int waitproc (int, int *);
5392 close(pf->fd); 6656static void waitonint(int);
5393 if (pf->buf)
5394 ckfree(pf->buf);
5395 while (pf->strpush)
5396 popstring();
5397 parsefile = pf->prev;
5398 ckfree(pf);
5399 parsenleft = parsefile->nleft;
5400 parselleft = parsefile->lleft;
5401 parsenextc = parsefile->nextc;
5402 plinno = parsefile->linno;
5403 INTON;
5404}
5405 6657
5406 6658
5407/* 6659/*
5408 * Return to top level. 6660 * We keep track of whether or not fd0 has been redirected. This is for
5409 */ 6661 * background commands, where we want to redirect fd0 to /dev/null only
6662 * if it hasn't already been redirected.
6663*/
6664static int fd0_redirected = 0;
5410 6665
5411static void 6666/* Return true if fd 0 has already been redirected at least once. */
5412popallfiles() { 6667static inline int
5413 while (parsefile != &basepf) 6668fd0_redirected_p () {
5414 popfile(); 6669 return fd0_redirected != 0;
5415} 6670}
5416 6671
5417
5418
5419/* 6672/*
5420 * Close the file(s) that the shell is reading commands from. Called 6673 * We also keep track of where fileno2 goes.
5421 * after a fork is done.
5422 */ 6674 */
6675static int fileno2 = 2;
5423 6676
5424static void 6677static int openredirect (union node *);
5425closescript() { 6678static void dupredirect (union node *, int, char[10 ]);
5426 popallfiles(); 6679static int openhere (union node *);
5427 if (parsefile->fd > 0) { 6680static int noclobberopen (const char *);
5428 close(parsefile->fd);
5429 parsefile->fd = 0;
5430 }
5431}
5432/* $NetBSD: jobs.c,v 1.36 2000/05/22 10:18:47 elric Exp $ */
5433
5434
5435struct job *jobtab; /* array of jobs */
5436static int njobs; /* size of array */
5437short backgndpid = -1; /* pid of last background process */
5438#if JOBS
5439static int initialpgrp; /* pgrp of shell on invocation */
5440short curjob; /* current job */
5441#endif
5442static int intreceived;
5443 6681
5444static void restartjob __P((struct job *));
5445static void freejob __P((struct job *));
5446static struct job *getjob __P((char *));
5447static int dowait __P((int, struct job *));
5448#ifdef SYSV
5449static int onsigchild __P((void));
5450#endif
5451static int waitproc __P((int, int *));
5452static void cmdtxt __P((union node *));
5453static void cmdputs __P((const char *));
5454static void waitonint(int);
5455 6682
5456 6683
5457#if JOBS 6684#ifdef JOBS
5458/* 6685/*
5459 * Turn job control on and off. 6686 * Turn job control on and off.
5460 * 6687 *
@@ -5463,7 +6690,7 @@ static void waitonint(int);
5463 * System V doesn't have job control yet, this isn't a problem now. 6690 * System V doesn't have job control yet, this isn't a problem now.
5464 */ 6691 */
5465 6692
5466static int jobctl; 6693
5467 6694
5468static void setjobctl(int enable) 6695static void setjobctl(int enable)
5469{ 6696{
@@ -5524,22 +6751,6 @@ static void setjobctl(int enable)
5524#endif 6751#endif
5525 6752
5526 6753
5527#ifdef mkinit
5528INCLUDE <stdlib.h>
5529
5530SHELLPROC {
5531 backgndpid = -1;
5532#if JOBS
5533 jobctl = 0;
5534#endif
5535}
5536
5537#endif
5538
5539
5540/* This file was automatically created by ./mksignames.
5541 Do not edit. Edit support/mksignames.c instead. */
5542
5543/* A translation list so we can be polite to our users. */ 6754/* A translation list so we can be polite to our users. */
5544static char *signal_names[NSIG + 2] = { 6755static char *signal_names[NSIG + 2] = {
5545 "EXIT", 6756 "EXIT",
@@ -5612,7 +6823,7 @@ static char *signal_names[NSIG + 2] = {
5612 6823
5613 6824
5614 6825
5615#if JOBS 6826#ifdef JOBS
5616static int 6827static int
5617killcmd(argc, argv) 6828killcmd(argc, argv)
5618 int argc; 6829 int argc;
@@ -5650,7 +6861,7 @@ usage:
5650 optionarg 6861 optionarg
5651 ); 6862 );
5652 } 6863 }
5653 break; 6864 break;
5654#ifdef DEBUG 6865#ifdef DEBUG
5655 default: 6866 default:
5656 error( 6867 error(
@@ -5697,7 +6908,7 @@ usage:
5697 } else 6908 } else
5698 pid = atoi(*argptr); 6909 pid = atoi(*argptr);
5699 if (kill(pid, signo) != 0) 6910 if (kill(pid, signo) != 0)
5700 error("%s: %s", *argptr, strerror(errno)); 6911 error("%s: %m", *argptr);
5701 } while (*++argptr); 6912 } while (*++argptr);
5702 6913
5703 return 0; 6914 return 0;
@@ -5767,6 +6978,8 @@ restartjob(jp)
5767} 6978}
5768#endif 6979#endif
5769 6980
6981static void showjobs(int change);
6982
5770 6983
5771static int 6984static int
5772jobscmd(argc, argv) 6985jobscmd(argc, argv)
@@ -5811,12 +7024,12 @@ showjobs(change)
5811 if (change && ! jp->changed) 7024 if (change && ! jp->changed)
5812 continue; 7025 continue;
5813 procno = jp->nprocs; 7026 procno = jp->nprocs;
5814 for (ps = jp->ps ; ; ps++) { /* for each process */ 7027 for (ps = jp->ps ; ; ps++) { /* for each process */
5815 if (ps == jp->ps) 7028 if (ps == jp->ps)
5816 fmtstr(s, 64, "[%d] %ld ", jobno, 7029 fmtstr(s, 64, "[%d] %ld ", jobno,
5817 (long)ps->pid); 7030 (long)ps->pid);
5818 else 7031 else
5819 fmtstr(s, 64, " %ld ", 7032 fmtstr(s, 64, " %ld ",
5820 (long)ps->pid); 7033 (long)ps->pid);
5821 out1str(s); 7034 out1str(s);
5822 col = strlen(s); 7035 col = strlen(s);
@@ -5824,17 +7037,17 @@ showjobs(change)
5824 if (ps->status == -1) { 7037 if (ps->status == -1) {
5825 /* don't print anything */ 7038 /* don't print anything */
5826 } else if (WIFEXITED(ps->status)) { 7039 } else if (WIFEXITED(ps->status)) {
5827 fmtstr(s, 64, "Exit %d", 7040 fmtstr(s, 64, "Exit %d",
5828 WEXITSTATUS(ps->status)); 7041 WEXITSTATUS(ps->status));
5829 } else { 7042 } else {
5830#if JOBS 7043#ifdef JOBS
5831 if (WIFSTOPPED(ps->status)) 7044 if (WIFSTOPPED(ps->status))
5832 i = WSTOPSIG(ps->status); 7045 i = WSTOPSIG(ps->status);
5833 else /* WIFSIGNALED(ps->status) */ 7046 else /* WIFSIGNALED(ps->status) */
5834#endif 7047#endif
5835 i = WTERMSIG(ps->status); 7048 i = WTERMSIG(ps->status);
5836 if ((i & 0x7F) < NSIG && sys_siglist[i & 0x7F]) 7049 if ((i & 0x7F) < NSIG && sys_siglist[i & 0x7F])
5837 scopy(sys_siglist[i & 0x7F], s); 7050 strcpy(s, sys_siglist[i & 0x7F]);
5838 else 7051 else
5839 fmtstr(s, 64, "Signal %d", i & 0x7F); 7052 fmtstr(s, 64, "Signal %d", i & 0x7F);
5840 if (WCOREDUMP(ps->status)) 7053 if (WCOREDUMP(ps->status))
@@ -5876,7 +7089,7 @@ freejob(jp)
5876 if (jp->ps != &jp->ps0) 7089 if (jp->ps != &jp->ps0)
5877 ckfree(jp->ps); 7090 ckfree(jp->ps);
5878 jp->used = 0; 7091 jp->used = 0;
5879#if JOBS 7092#ifdef JOBS
5880 if (curjob == jp - jobtab + 1) 7093 if (curjob == jp - jobtab + 1)
5881 curjob = 0; 7094 curjob = 0;
5882#endif 7095#endif
@@ -5900,7 +7113,7 @@ start:
5900 } else { 7113 } else {
5901 job = NULL; 7114 job = NULL;
5902 } 7115 }
5903 for (;;) { /* loop until process terminated or stopped */ 7116 for (;;) { /* loop until process terminated or stopped */
5904 if (job != NULL) { 7117 if (job != NULL) {
5905 if (job->state) { 7118 if (job->state) {
5906 status = job->ps[job->nprocs - 1].status; 7119 status = job->ps[job->nprocs - 1].status;
@@ -5911,7 +7124,7 @@ start:
5911 } 7124 }
5912 if (WIFEXITED(status)) 7125 if (WIFEXITED(status))
5913 retval = WEXITSTATUS(status); 7126 retval = WEXITSTATUS(status);
5914#if JOBS 7127#ifdef JOBS
5915 else if (WIFSTOPPED(status)) 7128 else if (WIFSTOPPED(status))
5916 retval = WSTOPSIG(status) + 128; 7129 retval = WSTOPSIG(status) + 128;
5917#endif 7130#endif
@@ -5923,7 +7136,7 @@ start:
5923 } 7136 }
5924 } else { 7137 } else {
5925 for (jp = jobtab ; ; jp++) { 7138 for (jp = jobtab ; ; jp++) {
5926 if (jp >= jobtab + njobs) { /* no running procs */ 7139 if (jp >= jobtab + njobs) { /* no running procs */
5927 return 0; 7140 return 0;
5928 } 7141 }
5929 if (jp->used && jp->state == 0) 7142 if (jp->used && jp->state == 0)
@@ -5943,16 +7156,15 @@ start:
5943 */ 7156 */
5944 7157
5945static struct job * 7158static struct job *
5946getjob(name) 7159getjob(const char *name)
5947 char *name; 7160{
5948 {
5949 int jobno; 7161 int jobno;
5950 struct job *jp; 7162 struct job *jp;
5951 int pid; 7163 int pid;
5952 int i; 7164 int i;
5953 7165
5954 if (name == NULL) { 7166 if (name == NULL) {
5955#if JOBS 7167#ifdef JOBS
5956currentjob: 7168currentjob:
5957 if ((jobno = curjob) == 0 || jobtab[jobno - 1].used == 0) 7169 if ((jobno = curjob) == 0 || jobtab[jobno - 1].used == 0)
5958 error("No current job"); 7170 error("No current job");
@@ -5966,7 +7178,7 @@ currentjob:
5966 if (jobno > 0 && jobno <= njobs 7178 if (jobno > 0 && jobno <= njobs
5967 && jobtab[jobno - 1].used != 0) 7179 && jobtab[jobno - 1].used != 0)
5968 return &jobtab[jobno - 1]; 7180 return &jobtab[jobno - 1];
5969#if JOBS 7181#ifdef JOBS
5970 } else if (name[1] == '%' && name[2] == '\0') { 7182 } else if (name[1] == '%' && name[2] == '\0') {
5971 goto currentjob; 7183 goto currentjob;
5972#endif 7184#endif
@@ -5983,8 +7195,7 @@ currentjob:
5983 if (found) 7195 if (found)
5984 return found; 7196 return found;
5985 } 7197 }
5986 } else if (is_number(name)) { 7198 } else if (is_number(name, &pid)) {
5987 pid = number(name);
5988 for (jp = jobtab, i = njobs ; --i >= 0 ; jp++) { 7199 for (jp = jobtab, i = njobs ; --i >= 0 ; jp++) {
5989 if (jp->used && jp->nprocs > 0 7200 if (jp->used && jp->nprocs > 0
5990 && jp->ps[jp->nprocs - 1].pid == pid) 7201 && jp->ps[jp->nprocs - 1].pid == pid)
@@ -6001,7 +7212,7 @@ currentjob:
6001 * Return a new job structure, 7212 * Return a new job structure,
6002 */ 7213 */
6003 7214
6004struct job * 7215static struct job *
6005makejob(node, nprocs) 7216makejob(node, nprocs)
6006 union node *node; 7217 union node *node;
6007 int nprocs; 7218 int nprocs;
@@ -6037,7 +7248,7 @@ makejob(node, nprocs)
6037 jp->used = 1; 7248 jp->used = 1;
6038 jp->changed = 0; 7249 jp->changed = 0;
6039 jp->nprocs = 0; 7250 jp->nprocs = 0;
6040#if JOBS 7251#ifdef JOBS
6041 jp->jobctl = jobctl; 7252 jp->jobctl = jobctl;
6042#endif 7253#endif
6043 if (nprocs > 1) { 7254 if (nprocs > 1) {
@@ -6057,21 +7268,20 @@ makejob(node, nprocs)
6057 * own process group. Jp is a job structure that the job is to be added to. 7268 * own process group. Jp is a job structure that the job is to be added to.
6058 * N is the command that will be evaluated by the child. Both jp and n may 7269 * N is the command that will be evaluated by the child. Both jp and n may
6059 * be NULL. The mode parameter can be one of the following: 7270 * be NULL. The mode parameter can be one of the following:
6060 * FORK_FG - Fork off a foreground process. 7271 * FORK_FG - Fork off a foreground process.
6061 * FORK_BG - Fork off a background process. 7272 * FORK_BG - Fork off a background process.
6062 * FORK_NOJOB - Like FORK_FG, but don't give the process its own 7273 * FORK_NOJOB - Like FORK_FG, but don't give the process its own
6063 * process group even if job control is on. 7274 * process group even if job control is on.
6064 * 7275 *
6065 * When job control is turned off, background processes have their standard 7276 * When job control is turned off, background processes have their standard
6066 * input redirected to /dev/null (except for the second and later processes 7277 * input redirected to /dev/null (except for the second and later processes
6067 * in a pipeline). 7278 * in a pipeline).
6068 */ 7279 */
6069 7280
7281
7282
6070static int 7283static int
6071forkshell(jp, n, mode) 7284forkshell(struct job *jp, union node *n, int mode)
6072 union node *n;
6073 struct job *jp;
6074 int mode;
6075{ 7285{
6076 int pid; 7286 int pid;
6077 int pgrp; 7287 int pgrp;
@@ -6098,8 +7308,8 @@ forkshell(jp, n, mode)
6098 closescript(); 7308 closescript();
6099 INTON; 7309 INTON;
6100 clear_traps(); 7310 clear_traps();
6101#if JOBS 7311#ifdef JOBS
6102 jobctl = 0; /* do job control only in root shell */ 7312 jobctl = 0; /* do job control only in root shell */
6103 if (wasroot && mode != FORK_NOJOB && mflag) { 7313 if (wasroot && mode != FORK_NOJOB && mflag) {
6104 if (jp == NULL || jp->nprocs == 0) 7314 if (jp == NULL || jp->nprocs == 0)
6105 pgrp = getpid(); 7315 pgrp = getpid();
@@ -6158,7 +7368,7 @@ forkshell(jp, n, mode)
6158 setpgid(pid, pgrp); 7368 setpgid(pid, pgrp);
6159 } 7369 }
6160 if (mode == FORK_BG) 7370 if (mode == FORK_BG)
6161 backgndpid = pid; /* set $! */ 7371 backgndpid = pid; /* set $! */
6162 if (jp) { 7372 if (jp) {
6163 struct procstat *ps = &jp->ps[jp->nprocs++]; 7373 struct procstat *ps = &jp->ps[jp->nprocs++];
6164 ps->pid = pid; 7374 ps->pid = pid;
@@ -6197,7 +7407,7 @@ static int
6197waitforjob(jp) 7407waitforjob(jp)
6198 struct job *jp; 7408 struct job *jp;
6199 { 7409 {
6200#if JOBS 7410#ifdef JOBS
6201 int mypgrp = getpgrp(); 7411 int mypgrp = getpgrp();
6202#endif 7412#endif
6203 int status; 7413 int status;
@@ -6206,7 +7416,7 @@ waitforjob(jp)
6206 7416
6207 INTOFF; 7417 INTOFF;
6208 intreceived = 0; 7418 intreceived = 0;
6209#if JOBS 7419#ifdef JOBS
6210 if (!jobctl) { 7420 if (!jobctl) {
6211#else 7421#else
6212 if (!iflag) { 7422 if (!iflag) {
@@ -6219,7 +7429,7 @@ waitforjob(jp)
6219 while (jp->state == 0) { 7429 while (jp->state == 0) {
6220 dowait(1, jp); 7430 dowait(1, jp);
6221 } 7431 }
6222#if JOBS 7432#ifdef JOBS
6223 if (!jobctl) { 7433 if (!jobctl) {
6224#else 7434#else
6225 if (!iflag) { 7435 if (!iflag) {
@@ -6227,7 +7437,7 @@ waitforjob(jp)
6227 sigaction(SIGINT, &oact, 0); 7437 sigaction(SIGINT, &oact, 0);
6228 if (intreceived && trap[SIGINT]) kill(getpid(), SIGINT); 7438 if (intreceived && trap[SIGINT]) kill(getpid(), SIGINT);
6229 } 7439 }
6230#if JOBS 7440#ifdef JOBS
6231 if (jp->jobctl) { 7441 if (jp->jobctl) {
6232#ifdef OLD_TTY_DRIVER 7442#ifdef OLD_TTY_DRIVER
6233 if (ioctl(fileno2, TIOCSPGRP, (char *)&mypgrp) < 0) 7443 if (ioctl(fileno2, TIOCSPGRP, (char *)&mypgrp) < 0)
@@ -6244,13 +7454,13 @@ waitforjob(jp)
6244 /* convert to 8 bits */ 7454 /* convert to 8 bits */
6245 if (WIFEXITED(status)) 7455 if (WIFEXITED(status))
6246 st = WEXITSTATUS(status); 7456 st = WEXITSTATUS(status);
6247#if JOBS 7457#ifdef JOBS
6248 else if (WIFSTOPPED(status)) 7458 else if (WIFSTOPPED(status))
6249 st = WSTOPSIG(status) + 128; 7459 st = WSTOPSIG(status) + 128;
6250#endif 7460#endif
6251 else 7461 else
6252 st = WTERMSIG(status) + 128; 7462 st = WTERMSIG(status) + 128;
6253#if JOBS 7463#ifdef JOBS
6254 if (jp->jobctl) { 7464 if (jp->jobctl) {
6255 /* 7465 /*
6256 * This is truly gross. 7466 * This is truly gross.
@@ -6263,8 +7473,9 @@ waitforjob(jp)
6263 if (WIFSIGNALED(status) && WTERMSIG(status) == SIGINT) 7473 if (WIFSIGNALED(status) && WTERMSIG(status) == SIGINT)
6264 raise(SIGINT); 7474 raise(SIGINT);
6265 } 7475 }
7476 if (jp->state == JOBDONE)
7477
6266#endif 7478#endif
6267 if (! JOBS || jp->state == JOBDONE)
6268 freejob(jp); 7479 freejob(jp);
6269 INTON; 7480 INTON;
6270 return st; 7481 return st;
@@ -6317,14 +7528,14 @@ dowait(block, job)
6317 else if (WIFSTOPPED(sp->status)) 7528 else if (WIFSTOPPED(sp->status))
6318 done = 0; 7529 done = 0;
6319 } 7530 }
6320 if (stopped) { /* stopped or done */ 7531 if (stopped) { /* stopped or done */
6321 int state = done? JOBDONE : JOBSTOPPED; 7532 int state = done? JOBDONE : JOBSTOPPED;
6322 if (jp->state != state) { 7533 if (jp->state != state) {
6323 TRACE(("Job %d: changing state from %d to %d\n", jp - jobtab + 1, jp->state, state)); 7534 TRACE(("Job %d: changing state from %d to %d\n", jp - jobtab + 1, jp->state, state));
6324 jp->state = state; 7535 jp->state = state;
6325#if JOBS 7536#ifdef JOBS
6326 if (done && curjob == jp - jobtab + 1) 7537 if (done && curjob == jp - jobtab + 1)
6327 curjob = 0; /* no current job */ 7538 curjob = 0; /* no current job */
6328#endif 7539#endif
6329 } 7540 }
6330 } 7541 }
@@ -6333,7 +7544,7 @@ dowait(block, job)
6333 INTON; 7544 INTON;
6334 if (! rootshell || ! iflag || (job && thisjob == job)) { 7545 if (! rootshell || ! iflag || (job && thisjob == job)) {
6335 core = WCOREDUMP(status); 7546 core = WCOREDUMP(status);
6336#if JOBS 7547#ifdef JOBS
6337 if (WIFSTOPPED(status)) sig = WSTOPSIG(status); 7548 if (WIFSTOPPED(status)) sig = WSTOPSIG(status);
6338 else 7549 else
6339#endif 7550#endif
@@ -6343,7 +7554,7 @@ dowait(block, job)
6343 if (sig != 0 && sig != SIGINT && sig != SIGPIPE) { 7554 if (sig != 0 && sig != SIGINT && sig != SIGPIPE) {
6344 if (thisjob != job) 7555 if (thisjob != job)
6345 outfmt(out2, "%d: ", pid); 7556 outfmt(out2, "%d: ", pid);
6346#if JOBS 7557#ifdef JOBS
6347 if (sig == SIGTSTP && rootshell && iflag) 7558 if (sig == SIGTSTP && rootshell && iflag)
6348 outfmt(out2, "%%%ld ", 7559 outfmt(out2, "%%%ld ",
6349 (long)(job - jobtab + 1)); 7560 (long)(job - jobtab + 1));
@@ -6359,7 +7570,7 @@ dowait(block, job)
6359 flushout(&errout); 7570 flushout(&errout);
6360#endif 7571#endif
6361 } else { 7572 } else {
6362 TRACE(("Not printing status: status=%d, sig=%d\n", 7573 TRACE(("Not printing status: status=%d, sig=%d\n",
6363 status, sig)); 7574 status, sig));
6364 } 7575 }
6365 } else { 7576 } else {
@@ -6394,64 +7605,30 @@ dowait(block, job)
6394 * then checking to see whether it was called. If there are any 7605 * then checking to see whether it was called. If there are any
6395 * children to be waited for, it will be. 7606 * children to be waited for, it will be.
6396 * 7607 *
6397 * If neither SYSV nor BSD is defined, we don't implement nonblocking
6398 * waits at all. In this case, the user will not be informed when
6399 * a background process until the next time she runs a real program
6400 * (as opposed to running a builtin command or just typing return),
6401 * and the jobs command may give out of date information.
6402 */ 7608 */
6403 7609
6404#ifdef SYSV
6405static int gotsigchild;
6406
6407static int onsigchild() {
6408 gotsigchild = 1;
6409}
6410#endif
6411
6412
6413static int 7610static int
6414waitproc(block, status) 7611waitproc(block, status)
6415 int block; 7612 int block;
6416 int *status; 7613 int *status;
6417{ 7614{
6418#ifdef BSD
6419 int flags; 7615 int flags;
6420 7616
6421 flags = 0; 7617 flags = 0;
6422#if JOBS 7618#ifdef JOBS
6423 if (jobctl) 7619 if (jobctl)
6424 flags |= WUNTRACED; 7620 flags |= WUNTRACED;
6425#endif 7621#endif
6426 if (block == 0) 7622 if (block == 0)
6427 flags |= WNOHANG; 7623 flags |= WNOHANG;
6428 return wait3(status, flags, (struct rusage *)NULL); 7624 return wait3(status, flags, (struct rusage *)NULL);
6429#else
6430#ifdef SYSV
6431 int (*save)();
6432
6433 if (block == 0) {
6434 gotsigchild = 0;
6435 save = signal(SIGCLD, onsigchild);
6436 signal(SIGCLD, save);
6437 if (gotsigchild == 0)
6438 return 0;
6439 }
6440 return wait(status);
6441#else
6442 if (block == 0)
6443 return 0;
6444 return wait(status);
6445#endif
6446#endif
6447} 7625}
6448 7626
6449/* 7627/*
6450 * return 1 if there are stopped jobs, otherwise 0 7628 * return 1 if there are stopped jobs, otherwise 0
6451 */ 7629 */
6452static int job_warning = 0;
6453static int 7630static int
6454stoppedjobs() 7631stoppedjobs(void)
6455{ 7632{
6456 int jobno; 7633 int jobno;
6457 struct job *jp; 7634 struct job *jp;
@@ -6478,26 +7655,51 @@ stoppedjobs()
6478 7655
6479static char *cmdnextc; 7656static char *cmdnextc;
6480static int cmdnleft; 7657static int cmdnleft;
6481#define MAXCMDTEXT 200 7658#define MAXCMDTEXT 200
6482 7659
6483static char * 7660static void
6484commandtext(n) 7661cmdputs(const char *s)
6485 union node *n; 7662{
6486 { 7663 const char *p;
6487 char *name; 7664 char *q;
7665 char c;
7666 int subtype = 0;
6488 7667
6489 cmdnextc = name = ckmalloc(MAXCMDTEXT); 7668 if (cmdnleft <= 0)
6490 cmdnleft = MAXCMDTEXT - 4; 7669 return;
6491 cmdtxt(n); 7670 p = s;
6492 *cmdnextc = '\0'; 7671 q = cmdnextc;
6493 return name; 7672 while ((c = *p++) != '\0') {
7673 if (c == CTLESC)
7674 *q++ = *p++;
7675 else if (c == CTLVAR) {
7676 *q++ = '$';
7677 if (--cmdnleft > 0)
7678 *q++ = '{';
7679 subtype = *p++;
7680 } else if (c == '=' && subtype != 0) {
7681 *q++ = "}-+?="[(subtype & VSTYPE) - VSNORMAL];
7682 subtype = 0;
7683 } else if (c == CTLENDVAR) {
7684 *q++ = '}';
7685 } else if (c == CTLBACKQ || c == CTLBACKQ+CTLQUOTE)
7686 cmdnleft++; /* ignore it */
7687 else
7688 *q++ = c;
7689 if (--cmdnleft <= 0) {
7690 *q++ = '.';
7691 *q++ = '.';
7692 *q++ = '.';
7693 break;
7694 }
7695 }
7696 cmdnextc = q;
6494} 7697}
6495 7698
6496 7699
6497static void 7700static void
6498cmdtxt(n) 7701cmdtxt(const union node *n)
6499 union node *n; 7702{
6500 {
6501 union node *np; 7703 union node *np;
6502 struct nodelist *lp; 7704 struct nodelist *lp;
6503 const char *p; 7705 const char *p;
@@ -6624,53 +7826,23 @@ redir:
6624} 7826}
6625 7827
6626 7828
7829static char *
7830commandtext(const union node *n)
7831{
7832 char *name;
6627 7833
6628static void 7834 cmdnextc = name = ckmalloc(MAXCMDTEXT);
6629cmdputs(s) 7835 cmdnleft = MAXCMDTEXT - 4;
6630 const char *s; 7836 cmdtxt(n);
6631 { 7837 *cmdnextc = '\0';
6632 const char *p; 7838 return name;
6633 char *q;
6634 char c;
6635 int subtype = 0;
6636
6637 if (cmdnleft <= 0)
6638 return;
6639 p = s;
6640 q = cmdnextc;
6641 while ((c = *p++) != '\0') {
6642 if (c == CTLESC)
6643 *q++ = *p++;
6644 else if (c == CTLVAR) {
6645 *q++ = '$';
6646 if (--cmdnleft > 0)
6647 *q++ = '{';
6648 subtype = *p++;
6649 } else if (c == '=' && subtype != 0) {
6650 *q++ = "}-+?="[(subtype & VSTYPE) - VSNORMAL];
6651 subtype = 0;
6652 } else if (c == CTLENDVAR) {
6653 *q++ = '}';
6654 } else if (c == CTLBACKQ || c == CTLBACKQ+CTLQUOTE)
6655 cmdnleft++; /* ignore it */
6656 else
6657 *q++ = c;
6658 if (--cmdnleft <= 0) {
6659 *q++ = '.';
6660 *q++ = '.';
6661 *q++ = '.';
6662 break;
6663 }
6664 }
6665 cmdnextc = q;
6666} 7839}
6667 7840
7841
6668static void waitonint(int sig) { 7842static void waitonint(int sig) {
6669 intreceived = 1; 7843 intreceived = 1;
6670 return; 7844 return;
6671} 7845}
6672/* $NetBSD: mail.c,v 1.14 2000/07/03 03:26:19 matt Exp $ */
6673
6674/* 7846/*
6675 * Routines to check for mail. (Perhaps make part of main.c?) 7847 * Routines to check for mail. (Perhaps make part of main.c?)
6676 */ 7848 */
@@ -6679,8 +7851,8 @@ static void waitonint(int sig) {
6679#define MAXMBOXES 10 7851#define MAXMBOXES 10
6680 7852
6681 7853
6682static int nmboxes; /* number of mailboxes */ 7854static int nmboxes; /* number of mailboxes */
6683static time_t mailtime[MAXMBOXES]; /* times of mailboxes */ 7855static time_t mailtime[MAXMBOXES]; /* times of mailboxes */
6684 7856
6685 7857
6686 7858
@@ -6691,8 +7863,7 @@ static time_t mailtime[MAXMBOXES]; /* times of mailboxes */
6691 */ 7863 */
6692 7864
6693static void 7865static void
6694chkmail(silent) 7866chkmail(int silent)
6695 int silent;
6696{ 7867{
6697 int i; 7868 int i;
6698 const char *mpath; 7869 const char *mpath;
@@ -6718,18 +7889,7 @@ chkmail(silent)
6718 if (q[-1] != '/') 7889 if (q[-1] != '/')
6719 abort(); 7890 abort();
6720#endif 7891#endif
6721 q[-1] = '\0'; /* delete trailing '/' */ 7892 q[-1] = '\0'; /* delete trailing '/' */
6722#ifdef notdef /* this is what the System V shell claims to do (it lies) */
6723 if (stat(p, &statb) < 0)
6724 statb.st_mtime = 0;
6725 if (statb.st_mtime > mailtime[i] && ! silent) {
6726 outfmt(
6727 &errout, snlfmt,
6728 pathopt? pathopt : "you have mail"
6729 );
6730 }
6731 mailtime[i] = statb.st_mtime;
6732#else /* this is what it should do */
6733 if (stat(p, &statb) < 0) 7893 if (stat(p, &statb) < 0)
6734 statb.st_size = 0; 7894 statb.st_size = 0;
6735 if (statb.st_size > mailtime[i] && ! silent) { 7895 if (statb.st_size > mailtime[i] && ! silent) {
@@ -6739,28 +7899,27 @@ chkmail(silent)
6739 ); 7899 );
6740 } 7900 }
6741 mailtime[i] = statb.st_size; 7901 mailtime[i] = statb.st_size;
6742#endif
6743 } 7902 }
6744 nmboxes = i; 7903 nmboxes = i;
6745 popstackmark(&smark); 7904 popstackmark(&smark);
6746} 7905}
6747/* $NetBSD: main.c,v 1.40 2001/02/04 19:52:06 christos Exp $ */
6748
6749 7906
6750#define PROFILE 0 7907#define PROFILE 0
6751 7908
6752static int rootpid;
6753static int rootshell;
6754#if PROFILE 7909#if PROFILE
6755short profile_buf[16384]; 7910static short profile_buf[16384];
6756extern int etext(); 7911extern int etext();
6757#endif 7912#endif
6758 7913
6759static void read_profile __P((const char *)); 7914static void read_profile (const char *);
6760static char *find_dot_file __P((char *)); 7915static char *find_dot_file (char *);
6761int shell_main __P((int, char **)); 7916static void cmdloop (int);
7917static void options (int);
7918static void minus_o (char *, int);
7919static void setoption (int, int);
7920static void procargs (int, char **);
7921
6762 7922
6763extern int oexitstatus;
6764/* 7923/*
6765 * Main routine. We initialize things, parse the arguments, execute 7924 * Main routine. We initialize things, parse the arguments, execute
6766 * profiles if we're a login shell, and then call cmdloop to execute 7925 * profiles if we're a login shell, and then call cmdloop to execute
@@ -6781,7 +7940,6 @@ shell_main(argc, argv)
6781 7940
6782 DOTCMD = find_builtin("."); 7941 DOTCMD = find_builtin(".");
6783 BLTINCMD = find_builtin("builtin"); 7942 BLTINCMD = find_builtin("builtin");
6784 COMMANDCMD = find_builtin("command");
6785 EXECCMD = find_builtin("exec"); 7943 EXECCMD = find_builtin("exec");
6786 EVALCMD = find_builtin("eval"); 7944 EVALCMD = find_builtin("eval");
6787 7945
@@ -6824,18 +7982,14 @@ shell_main(argc, argv)
6824 exitshell(exitstatus); 7982 exitshell(exitstatus);
6825 } 7983 }
6826 reset(); 7984 reset();
6827 if (exception == EXINT 7985 if (exception == EXINT) {
6828#if ATTY
6829 && (! attyset() || equal(termval(), "emacs"))
6830#endif
6831 ) {
6832 out2c('\n'); 7986 out2c('\n');
6833#ifdef FLUSHERR 7987#ifdef FLUSHERR
6834 flushout(out2); 7988 flushout(out2);
6835#endif 7989#endif
6836 } 7990 }
6837 popstackmark(&smark); 7991 popstackmark(&smark);
6838 FORCEINTON; /* enable interrupts */ 7992 FORCEINTON; /* enable interrupts */
6839 if (state == 1) 7993 if (state == 1)
6840 goto state1; 7994 goto state1;
6841 else if (state == 2) 7995 else if (state == 2)
@@ -6878,7 +8032,7 @@ state3:
6878 state = 4; 8032 state = 4;
6879 if (sflag == 0 || minusc) { 8033 if (sflag == 0 || minusc) {
6880 static int sigs[] = { 8034 static int sigs[] = {
6881 SIGINT, SIGQUIT, SIGHUP, 8035 SIGINT, SIGQUIT, SIGHUP,
6882#ifdef SIGTSTP 8036#ifdef SIGTSTP
6883 SIGTSTP, 8037 SIGTSTP,
6884#endif 8038#endif
@@ -6895,7 +8049,7 @@ state3:
6895 evalstring(minusc, 0); 8049 evalstring(minusc, 0);
6896 8050
6897 if (sflag || minusc == NULL) { 8051 if (sflag || minusc == NULL) {
6898state4: /* XXX ??? - why isn't this before the "if" statement */ 8052state4: /* XXX ??? - why isn't this before the "if" statement */
6899 cmdloop(1); 8053 cmdloop(1);
6900 } 8054 }
6901#if PROFILE 8055#if PROFILE
@@ -6912,8 +8066,7 @@ state4: /* XXX ??? - why isn't this before the "if" statement */
6912 */ 8066 */
6913 8067
6914static void 8068static void
6915cmdloop(top) 8069cmdloop(int top)
6916 int top;
6917{ 8070{
6918 union node *n; 8071 union node *n;
6919 struct stackmark smark; 8072 struct stackmark smark;
@@ -7002,8 +8155,7 @@ read_profile(name)
7002 */ 8155 */
7003 8156
7004static void 8157static void
7005readcmdfile(name) 8158readcmdfile(const char *name)
7006 char *name;
7007{ 8159{
7008 int fd; 8160 int fd;
7009 8161
@@ -7064,7 +8216,7 @@ dotcmd(argc, argv)
7064 for (sp = cmdenviron; sp ; sp = sp->next) 8216 for (sp = cmdenviron; sp ; sp = sp->next)
7065 setvareq(savestr(sp->text), VSTRFIXED|VTEXTFIXED); 8217 setvareq(savestr(sp->text), VSTRFIXED|VTEXTFIXED);
7066 8218
7067 if (argc >= 2) { /* That's what SVR2 does */ 8219 if (argc >= 2) { /* That's what SVR2 does */
7068 char *fullname; 8220 char *fullname;
7069 struct stackmark smark; 8221 struct stackmark smark;
7070 8222
@@ -7094,38 +8246,8 @@ exitcmd(argc, argv)
7094 exitshell(exitstatus); 8246 exitshell(exitstatus);
7095 /* NOTREACHED */ 8247 /* NOTREACHED */
7096} 8248}
7097/* $NetBSD: memalloc.c,v 1.23 2000/11/01 19:56:01 christos Exp $ */ 8249static pointer
7098 8250stalloc(int nbytes)
7099/*
7100 * Parse trees for commands are allocated in lifo order, so we use a stack
7101 * to make this more efficient, and also to avoid all sorts of exception
7102 * handling code to handle interrupts in the middle of a parse.
7103 *
7104 * The size 504 was chosen because the Ultrix malloc handles that size
7105 * well.
7106 */
7107
7108#define MINSIZE 504 /* minimum size of a block */
7109
7110
7111struct stack_block {
7112 struct stack_block *prev;
7113 char space[MINSIZE];
7114};
7115
7116struct stack_block stackbase;
7117struct stack_block *stackp = &stackbase;
7118struct stackmark *markp;
7119static char *stacknxt = stackbase.space;
7120static int stacknleft = MINSIZE;
7121static int sstrnleft;
7122static int herefd = -1;
7123
7124
7125
7126pointer
7127stalloc(nbytes)
7128 int nbytes;
7129{ 8251{
7130 char *p; 8252 char *p;
7131 8253
@@ -7153,11 +8275,10 @@ stalloc(nbytes)
7153 8275
7154 8276
7155static void 8277static void
7156stunalloc(p) 8278stunalloc(pointer p)
7157 pointer p; 8279{
7158 {
7159#ifdef DEBUG 8280#ifdef DEBUG
7160 if (p == NULL) { /*DEBUG */ 8281 if (p == NULL) { /*DEBUG */
7161 write(2, "stunalloc\n", 10); 8282 write(2, "stunalloc\n", 10);
7162 abort(); 8283 abort();
7163 } 8284 }
@@ -7170,11 +8291,9 @@ stunalloc(p)
7170} 8291}
7171 8292
7172 8293
7173
7174static void 8294static void
7175setstackmark(mark) 8295setstackmark(struct stackmark *mark)
7176 struct stackmark *mark; 8296{
7177 {
7178 mark->stackp = stackp; 8297 mark->stackp = stackp;
7179 mark->stacknxt = stacknxt; 8298 mark->stacknxt = stacknxt;
7180 mark->stacknleft = stacknleft; 8299 mark->stacknleft = stacknleft;
@@ -7184,9 +8303,8 @@ setstackmark(mark)
7184 8303
7185 8304
7186static void 8305static void
7187popstackmark(mark) 8306popstackmark(struct stackmark *mark)
7188 struct stackmark *mark; 8307{
7189 {
7190 struct stack_block *sp; 8308 struct stack_block *sp;
7191 8309
7192 INTOFF; 8310 INTOFF;
@@ -7213,7 +8331,7 @@ popstackmark(mark)
7213 */ 8331 */
7214 8332
7215static void 8333static void
7216growstackblock() { 8334growstackblock(void) {
7217 char *p; 8335 char *p;
7218 int newlen = ALIGN(stacknleft * 2 + 100); 8336 int newlen = ALIGN(stacknleft * 2 + 100);
7219 char *oldspace = stacknxt; 8337 char *oldspace = stacknxt;
@@ -7233,7 +8351,7 @@ growstackblock() {
7233 stacknleft = newlen; 8351 stacknleft = newlen;
7234 { 8352 {
7235 /* Stack marks pointing to the start of the old block 8353 /* Stack marks pointing to the start of the old block
7236 * must be relocated to point to the new block 8354 * must be relocated to point to the new block
7237 */ 8355 */
7238 struct stackmark *xmark; 8356 struct stackmark *xmark;
7239 xmark = markp; 8357 xmark = markp;
@@ -7248,16 +8366,15 @@ growstackblock() {
7248 } else { 8366 } else {
7249 p = stalloc(newlen); 8367 p = stalloc(newlen);
7250 memcpy(p, oldspace, oldlen); 8368 memcpy(p, oldspace, oldlen);
7251 stacknxt = p; /* free the space */ 8369 stacknxt = p; /* free the space */
7252 stacknleft += newlen; /* we just allocated */ 8370 stacknleft += newlen; /* we just allocated */
7253 } 8371 }
7254} 8372}
7255 8373
7256 8374
7257 8375
7258static void 8376static inline void
7259grabstackblock(len) 8377grabstackblock(int len)
7260 int len;
7261{ 8378{
7262 len = ALIGN(len); 8379 len = ALIGN(len);
7263 stacknxt += len; 8380 stacknxt += len;
@@ -7286,7 +8403,7 @@ grabstackblock(len)
7286 8403
7287 8404
7288static char * 8405static char *
7289growstackstr() { 8406growstackstr(void) {
7290 int len = stackblocksize(); 8407 int len = stackblocksize();
7291 if (herefd >= 0 && len >= 1024) { 8408 if (herefd >= 0 && len >= 1024) {
7292 xwrite(herefd, stackblock(), len); 8409 xwrite(herefd, stackblock(), len);
@@ -7316,16 +8433,12 @@ makestrspace(size_t newlen) {
7316 8433
7317 8434
7318static void 8435static void
7319ungrabstackstr(s, p) 8436ungrabstackstr(char *s, char *p)
7320 char *s; 8437{
7321 char *p;
7322 {
7323 stacknleft += stacknxt - s; 8438 stacknleft += stacknxt - s;
7324 stacknxt = s; 8439 stacknxt = s;
7325 sstrnleft = stacknleft - (p - s); 8440 sstrnleft = stacknleft - (p - s);
7326} 8441}
7327/* $NetBSD: miscbltin.c,v 1.30 2001/02/04 19:52:06 christos Exp $ */
7328
7329/* 8442/*
7330 * Miscelaneous builtins. 8443 * Miscelaneous builtins.
7331 */ 8444 */
@@ -7334,7 +8447,7 @@ ungrabstackstr(s, p)
7334#undef rflag 8447#undef rflag
7335 8448
7336#ifdef __GLIBC__ 8449#ifdef __GLIBC__
7337mode_t getmode(const void *, mode_t); 8450static mode_t getmode(const void *, mode_t);
7338static void *setmode(const char *); 8451static void *setmode(const char *);
7339 8452
7340#if !defined(__GLIBC__) || __GLIBC__ == 2 && __GLIBC_MINOR__ < 1 8453#if !defined(__GLIBC__) || __GLIBC__ == 2 && __GLIBC_MINOR__ < 1
@@ -7531,46 +8644,46 @@ umaskcmd(argc, argv)
7531 8644
7532struct limits { 8645struct limits {
7533 const char *name; 8646 const char *name;
7534 int cmd; 8647 int cmd;
7535 int factor; /* multiply by to get rlim_{cur,max} values */ 8648 int factor; /* multiply by to get rlim_{cur,max} values */
7536 char option; 8649 char option;
7537}; 8650};
7538 8651
7539static const struct limits limits[] = { 8652static const struct limits limits[] = {
7540#ifdef RLIMIT_CPU 8653#ifdef RLIMIT_CPU
7541 { "time(seconds)", RLIMIT_CPU, 1, 't' }, 8654 { "time(seconds)", RLIMIT_CPU, 1, 't' },
7542#endif 8655#endif
7543#ifdef RLIMIT_FSIZE 8656#ifdef RLIMIT_FSIZE
7544 { "file(blocks)", RLIMIT_FSIZE, 512, 'f' }, 8657 { "file(blocks)", RLIMIT_FSIZE, 512, 'f' },
7545#endif 8658#endif
7546#ifdef RLIMIT_DATA 8659#ifdef RLIMIT_DATA
7547 { "data(kbytes)", RLIMIT_DATA, 1024, 'd' }, 8660 { "data(kbytes)", RLIMIT_DATA, 1024, 'd' },
7548#endif 8661#endif
7549#ifdef RLIMIT_STACK 8662#ifdef RLIMIT_STACK
7550 { "stack(kbytes)", RLIMIT_STACK, 1024, 's' }, 8663 { "stack(kbytes)", RLIMIT_STACK, 1024, 's' },
7551#endif 8664#endif
7552#ifdef RLIMIT_CORE 8665#ifdef RLIMIT_CORE
7553 { "coredump(blocks)", RLIMIT_CORE, 512, 'c' }, 8666 { "coredump(blocks)", RLIMIT_CORE, 512, 'c' },
7554#endif 8667#endif
7555#ifdef RLIMIT_RSS 8668#ifdef RLIMIT_RSS
7556 { "memory(kbytes)", RLIMIT_RSS, 1024, 'm' }, 8669 { "memory(kbytes)", RLIMIT_RSS, 1024, 'm' },
7557#endif 8670#endif
7558#ifdef RLIMIT_MEMLOCK 8671#ifdef RLIMIT_MEMLOCK
7559 { "locked memory(kbytes)", RLIMIT_MEMLOCK, 1024, 'l' }, 8672 { "locked memory(kbytes)", RLIMIT_MEMLOCK, 1024, 'l' },
7560#endif 8673#endif
7561#ifdef RLIMIT_NPROC 8674#ifdef RLIMIT_NPROC
7562 { "process(processes)", RLIMIT_NPROC, 1, 'p' }, 8675 { "process(processes)", RLIMIT_NPROC, 1, 'p' },
7563#endif 8676#endif
7564#ifdef RLIMIT_NOFILE 8677#ifdef RLIMIT_NOFILE
7565 { "nofiles(descriptors)", RLIMIT_NOFILE, 1, 'n' }, 8678 { "nofiles(descriptors)", RLIMIT_NOFILE, 1, 'n' },
7566#endif 8679#endif
7567#ifdef RLIMIT_VMEM 8680#ifdef RLIMIT_VMEM
7568 { "vmemory(kbytes)", RLIMIT_VMEM, 1024, 'v' }, 8681 { "vmemory(kbytes)", RLIMIT_VMEM, 1024, 'v' },
7569#endif 8682#endif
7570#ifdef RLIMIT_SWAP 8683#ifdef RLIMIT_SWAP
7571 { "swap(kbytes)", RLIMIT_SWAP, 1024, 'w' }, 8684 { "swap(kbytes)", RLIMIT_SWAP, 1024, 'w' },
7572#endif 8685#endif
7573 { (char *) 0, 0, 0, '\0' } 8686 { (char *) 0, 0, 0, '\0' }
7574}; 8687};
7575 8688
7576static int 8689static int
@@ -7578,14 +8691,14 @@ ulimitcmd(argc, argv)
7578 int argc; 8691 int argc;
7579 char **argv; 8692 char **argv;
7580{ 8693{
7581 int c; 8694 int c;
7582 rlim_t val = 0; 8695 rlim_t val = 0;
7583 enum { SOFT = 0x1, HARD = 0x2 } 8696 enum { SOFT = 0x1, HARD = 0x2 }
7584 how = SOFT | HARD; 8697 how = SOFT | HARD;
7585 const struct limits *l; 8698 const struct limits *l;
7586 int set, all = 0; 8699 int set, all = 0;
7587 int optc, what; 8700 int optc, what;
7588 struct rlimit limit; 8701 struct rlimit limit;
7589 8702
7590 what = 'f'; 8703 what = 'f';
7591 while ((optc = nextopt("HSatfdsmcnpl")) != '\0') 8704 while ((optc = nextopt("HSatfdsmcnpl")) != '\0')
@@ -7644,11 +8757,7 @@ ulimitcmd(argc, argv)
7644 else 8757 else
7645 { 8758 {
7646 val /= l->factor; 8759 val /= l->factor;
7647#ifdef BSD4_4
7648 out1fmt("%lld\n", (long long) val); 8760 out1fmt("%lld\n", (long long) val);
7649#else
7650 out1fmt("%ld\n", (long) val);
7651#endif
7652 } 8761 }
7653 } 8762 }
7654 return 0; 8763 return 0;
@@ -7661,7 +8770,7 @@ ulimitcmd(argc, argv)
7661 if (how & SOFT) 8770 if (how & SOFT)
7662 limit.rlim_cur = val; 8771 limit.rlim_cur = val;
7663 if (setrlimit(l->cmd, &limit) < 0) 8772 if (setrlimit(l->cmd, &limit) < 0)
7664 error("error setting limit (%s)", strerror(errno)); 8773 error("error setting limit (%m)");
7665 } else { 8774 } else {
7666 if (how & SOFT) 8775 if (how & SOFT)
7667 val = limit.rlim_cur; 8776 val = limit.rlim_cur;
@@ -7673,63 +8782,11 @@ ulimitcmd(argc, argv)
7673 else 8782 else
7674 { 8783 {
7675 val /= l->factor; 8784 val /= l->factor;
7676#ifdef BSD4_4
7677 out1fmt("%lld\n", (long long) val); 8785 out1fmt("%lld\n", (long long) val);
7678#else
7679 out1fmt("%ld\n", (long) val);
7680#endif
7681 } 8786 }
7682 } 8787 }
7683 return 0; 8788 return 0;
7684} 8789}
7685/* $NetBSD: mystring.c,v 1.14 1999/07/09 03:05:50 christos Exp $ */
7686
7687/*
7688 * String functions.
7689 *
7690 * equal(s1, s2) Return true if strings are equal.
7691 * scopy(from, to) Copy a string.
7692 * scopyn(from, to, n) Like scopy, but checks for overflow.
7693 * number(s) Convert a string of digits to an integer.
7694 * is_number(s) Return true if s is a string of digits.
7695 */
7696
7697static char nullstr[1]; /* zero length string */
7698static const char spcstr[] = " ";
7699static const char snlfmt[] = "%s\n";
7700
7701/*
7702 * equal - #defined in mystring.h
7703 */
7704
7705/*
7706 * scopy - #defined in mystring.h
7707 */
7708
7709
7710#if 0
7711/*
7712 * scopyn - copy a string from "from" to "to", truncating the string
7713 * if necessary. "To" is always nul terminated, even if
7714 * truncation is performed. "Size" is the size of "to".
7715 */
7716
7717static void
7718scopyn(from, to, size)
7719 char const *from;
7720 char *to;
7721 int size;
7722 {
7723
7724 while (--size > 0) {
7725 if ((*to++ = *from++) == '\0')
7726 return;
7727 }
7728 *to = '\0';
7729}
7730#endif
7731
7732
7733/* 8790/*
7734 * prefix -- see if pfx is a prefix of string. 8791 * prefix -- see if pfx is a prefix of string.
7735 */ 8792 */
@@ -7746,40 +8803,42 @@ prefix(pfx, string)
7746 return 1; 8803 return 1;
7747} 8804}
7748 8805
7749
7750/* 8806/*
7751 * Convert a string of digits to an integer, printing an error message on 8807 * Return true if s is a string of digits, and save munber in intptr
7752 * failure. 8808 * nagative is bad
7753 */ 8809 */
7754 8810
7755static int 8811static int
7756number(s) 8812is_number(const char *p, int *intptr)
7757 const char *s; 8813{
7758 { 8814 int ret = 0;
7759
7760 if (! is_number(s))
7761 error("Illegal number: %s", s);
7762 return atoi(s);
7763}
7764 8815
8816 do {
8817 if (! is_digit(*p))
8818 return 0;
8819 ret *= 10;
8820 ret += digit_val(*p);
8821 p++;
8822 } while (*p != '\0');
7765 8823
8824 *intptr = ret;
8825 return 1;
8826}
7766 8827
7767/* 8828/*
7768 * Check for a valid number. This should be elsewhere. 8829 * Convert a string of digits to an integer, printing an error message on
8830 * failure.
7769 */ 8831 */
7770 8832
7771static int 8833static int
7772is_number(p) 8834number(const char *s)
7773 const char *p; 8835{
7774 { 8836 int i;
7775 do { 8837 if (! is_number(s, &i))
7776 if (! is_digit(*p)) 8838 error("Illegal number: %s", s);
7777 return 0; 8839 return i;
7778 } while (*++p != '\0');
7779 return 1;
7780} 8840}
7781 8841
7782
7783/* 8842/*
7784 * Produce a possibly single quoted string suitable as input to the shell. 8843 * Produce a possibly single quoted string suitable as input to the shell.
7785 * The return string is allocated on the stack. 8844 * The return string is allocated on the stack.
@@ -7863,38 +8922,20 @@ sstrdup(const char *p)
7863 return memcpy(stalloc(len), p, len); 8922 return memcpy(stalloc(len), p, len);
7864} 8923}
7865 8924
7866/*
7867 * Wrapper around strcmp for qsort/bsearch/...
7868 */
7869static int
7870pstrcmp(const void *a, const void *b)
7871{
7872 return strcmp(*(const char *const *) a, *(const char *const *) b);
7873}
7874 8925
7875/* 8926/*
7876 * Find a string is in a sorted array.
7877 */
7878static const char *const *
7879findstring(const char *s, const char *const *array, size_t nmemb)
7880{
7881 return bsearch(&s, array, nmemb, sizeof(const char *), pstrcmp);
7882}
7883/*
7884 * This file was generated by the mknodes program. 8927 * This file was generated by the mknodes program.
7885 */ 8928 */
7886 8929
7887/* $NetBSD: nodes.c.pat,v 1.8 1997/04/11 23:03:09 christos Exp $ */
7888
7889/* 8930/*
7890 * Routine for dealing with parsed shell commands. 8931 * Routine for dealing with parsed shell commands.
7891 */ 8932 */
7892 8933
7893 8934
7894static int funcblocksize; /* size of structures in function */ 8935static int funcblocksize; /* size of structures in function */
7895static int funcstringsize; /* size of strings in node */ 8936static int funcstringsize; /* size of strings in node */
7896pointer funcblock; /* block to allocate function from */ 8937static pointer funcblock; /* block to allocate function from */
7897static char *funcstring; /* block to allocate strings from */ 8938static char *funcstring; /* block to allocate strings from */
7898 8939
7899static const short nodesize[26] = { 8940static const short nodesize[26] = {
7900 ALIGN(sizeof (struct nbinary)), 8941 ALIGN(sizeof (struct nbinary)),
@@ -7926,11 +8967,11 @@ static const short nodesize[26] = {
7926}; 8967};
7927 8968
7928 8969
7929static void calcsize __P((union node *)); 8970static void calcsize (union node *);
7930static void sizenodelist __P((struct nodelist *)); 8971static void sizenodelist (struct nodelist *);
7931static union node *copynode __P((union node *)); 8972static union node *copynode (union node *);
7932static struct nodelist *copynodelist __P((struct nodelist *)); 8973static struct nodelist *copynodelist (struct nodelist *);
7933static char *nodesavestr __P((char *)); 8974static char *nodesavestr (char *);
7934 8975
7935 8976
7936 8977
@@ -7938,9 +8979,8 @@ static char *nodesavestr __P((char *));
7938 * Make a copy of a parse tree. 8979 * Make a copy of a parse tree.
7939 */ 8980 */
7940 8981
7941union node * 8982static union node *
7942copyfunc(n) 8983copyfunc(union node *n)
7943 union node *n;
7944{ 8984{
7945 if (n == NULL) 8985 if (n == NULL)
7946 return NULL; 8986 return NULL;
@@ -8181,54 +9221,8 @@ nodesavestr(s)
8181#endif 9221#endif
8182} 9222}
8183 9223
8184
8185
8186/*
8187 * Free a parse tree.
8188 */
8189
8190static void
8191freefunc(n)
8192 union node *n;
8193{
8194 if (n)
8195 ckfree(n);
8196}
8197/* $NetBSD: options.c,v 1.31 2001/02/26 13:06:43 wiz Exp $ */
8198
8199
8200struct optent optlist[NOPTS] = {
8201 { "errexit", 'e', 0 },
8202 { "noglob", 'f', 0 },
8203 { "ignoreeof", 'I', 0 },
8204 { "interactive",'i', 0 },
8205 { "monitor", 'm', 0 },
8206 { "noexec", 'n', 0 },
8207 { "stdin", 's', 0 },
8208 { "xtrace", 'x', 0 },
8209 { "verbose", 'v', 0 },
8210 { "vi", 'V', 0 },
8211 { "emacs", 'E', 0 },
8212 { "noclobber", 'C', 0 },
8213 { "allexport", 'a', 0 },
8214 { "notify", 'b', 0 },
8215 { "nounset", 'u', 0 },
8216 { "quietprofile", 'q', 0 },
8217};
8218static char *arg0; /* value of $0 */
8219struct shparam shellparam; /* current positional parameters */
8220static char **argptr; /* argument list for builtin commands */
8221static char *optionarg; /* set by nextopt (like getopt) */
8222static char *optptr; /* used by nextopt */
8223
8224static char *minusc; /* argument to -c option */
8225
8226
8227static void options __P((int));
8228static void minus_o __P((char *, int));
8229static void setoption __P((int, int));
8230#ifdef ASH_GETOPTS 9224#ifdef ASH_GETOPTS
8231static int getopts __P((char *, char *, char **, int *, int *)); 9225static int getopts (char *, char *, char **, int *, int *);
8232#endif 9226#endif
8233 9227
8234 9228
@@ -8247,7 +9241,7 @@ procargs(argc, argv)
8247 if (argc > 0) 9241 if (argc > 0)
8248 argptr++; 9242 argptr++;
8249 for (i = 0; i < NOPTS; i++) 9243 for (i = 0; i < NOPTS; i++)
8250 optlist[i].val = 2; 9244 optent_val(i) = 2;
8251 options(1); 9245 options(1);
8252 if (*argptr == NULL && minusc == NULL) 9246 if (*argptr == NULL && minusc == NULL)
8253 sflag = 1; 9247 sflag = 1;
@@ -8256,8 +9250,8 @@ procargs(argc, argv)
8256 if (mflag == 2) 9250 if (mflag == 2)
8257 mflag = iflag; 9251 mflag = iflag;
8258 for (i = 0; i < NOPTS; i++) 9252 for (i = 0; i < NOPTS; i++)
8259 if (optlist[i].val == 2) 9253 if (optent_val(i) == 2)
8260 optlist[i].val = 0; 9254 optent_val(i) = 0;
8261 arg0 = argv[0]; 9255 arg0 = argv[0];
8262 if (sflag == 0 && minusc == NULL) { 9256 if (sflag == 0 && minusc == NULL) {
8263 commandname = argv[0]; 9257 commandname = argv[0];
@@ -8267,7 +9261,7 @@ procargs(argc, argv)
8267 } 9261 }
8268 /* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */ 9262 /* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
8269 if (argptr && minusc && *argptr) 9263 if (argptr && minusc && *argptr)
8270 arg0 = *argptr++; 9264 arg0 = *argptr++;
8271 9265
8272 shellparam.p = argptr; 9266 shellparam.p = argptr;
8273 shellparam.optind = 1; 9267 shellparam.optind = 1;
@@ -8281,12 +9275,6 @@ procargs(argc, argv)
8281} 9275}
8282 9276
8283 9277
8284static void
8285optschanged()
8286{
8287 setinteractive(iflag);
8288 setjobctl(mflag);
8289}
8290 9278
8291/* 9279/*
8292 * Process shell options. The global variable argptr contains a pointer 9280 * Process shell options. The global variable argptr contains a pointer
@@ -8307,16 +9295,16 @@ options(cmdline)
8307 argptr++; 9295 argptr++;
8308 if ((c = *p++) == '-') { 9296 if ((c = *p++) == '-') {
8309 val = 1; 9297 val = 1;
8310 if (p[0] == '\0' || (p[0] == '-' && p[1] == '\0')) { 9298 if (p[0] == '\0' || (p[0] == '-' && p[1] == '\0')) {
8311 if (!cmdline) { 9299 if (!cmdline) {
8312 /* "-" means turn off -x and -v */ 9300 /* "-" means turn off -x and -v */
8313 if (p[0] == '\0') 9301 if (p[0] == '\0')
8314 xflag = vflag = 0; 9302 xflag = vflag = 0;
8315 /* "--" means reset params */ 9303 /* "--" means reset params */
8316 else if (*argptr == NULL) 9304 else if (*argptr == NULL)
8317 setparam(argptr); 9305 setparam(argptr);
8318 } 9306 }
8319 break; /* "-" or "--" terminates options */ 9307 break; /* "-" or "--" terminates options */
8320 } 9308 }
8321 } else if (c == '+') { 9309 } else if (c == '+') {
8322 val = 0; 9310 val = 0;
@@ -8327,7 +9315,7 @@ options(cmdline)
8327 while ((c = *p++) != '\0') { 9315 while ((c = *p++) != '\0') {
8328 if (c == 'c' && cmdline) { 9316 if (c == 'c' && cmdline) {
8329 char *q; 9317 char *q;
8330#ifdef NOHACK /* removing this code allows sh -ce 'foo' for compat */ 9318#ifdef NOHACK /* removing this code allows sh -ce 'foo' for compat */
8331 if (*p == '\0') 9319 if (*p == '\0')
8332#endif 9320#endif
8333 q = *argptr++; 9321 q = *argptr++;
@@ -8358,12 +9346,12 @@ minus_o(name, val)
8358 if (name == NULL) { 9346 if (name == NULL) {
8359 out1str("Current option settings\n"); 9347 out1str("Current option settings\n");
8360 for (i = 0; i < NOPTS; i++) 9348 for (i = 0; i < NOPTS; i++)
8361 out1fmt("%-16s%s\n", optlist[i].name, 9349 out1fmt("%-16s%s\n", optent_name(optlist[i]),
8362 optlist[i].val ? "on" : "off"); 9350 optent_val(i) ? "on" : "off");
8363 } else { 9351 } else {
8364 for (i = 0; i < NOPTS; i++) 9352 for (i = 0; i < NOPTS; i++)
8365 if (equal(name, optlist[i].name)) { 9353 if (equal(name, optent_name(optlist[i]))) {
8366 setoption(optlist[i].letter, val); 9354 setoption(optent_letter(optlist[i]), val);
8367 return; 9355 return;
8368 } 9356 }
8369 error("Illegal option -o %s", name); 9357 error("Illegal option -o %s", name);
@@ -8372,15 +9360,13 @@ minus_o(name, val)
8372 9360
8373 9361
8374static void 9362static void
8375setoption(flag, val) 9363setoption(int flag, int val)
8376 char flag; 9364{
8377 int val;
8378 {
8379 int i; 9365 int i;
8380 9366
8381 for (i = 0; i < NOPTS; i++) 9367 for (i = 0; i < NOPTS; i++)
8382 if (optlist[i].letter == flag) { 9368 if (optent_letter(optlist[i]) == flag) {
8383 optlist[i].val = val; 9369 optent_val(i) = val;
8384 if (val) { 9370 if (val) {
8385 /* #%$ hack for ksh semantics */ 9371 /* #%$ hack for ksh semantics */
8386 if (flag == 'V') 9372 if (flag == 'V')
@@ -8396,26 +9382,13 @@ setoption(flag, val)
8396 9382
8397 9383
8398 9384
8399#ifdef mkinit
8400SHELLPROC {
8401 int i;
8402
8403 for (i = 0; i < NOPTS; i++)
8404 optlist[i].val = 0;
8405 optschanged();
8406
8407}
8408#endif
8409
8410
8411/* 9385/*
8412 * Set the shell parameters. 9386 * Set the shell parameters.
8413 */ 9387 */
8414 9388
8415static void 9389static void
8416setparam(argv) 9390setparam(char **argv)
8417 char **argv; 9391{
8418 {
8419 char **newparam; 9392 char **newparam;
8420 char **ap; 9393 char **ap;
8421 int nparam; 9394 int nparam;
@@ -8440,9 +9413,8 @@ setparam(argv)
8440 */ 9413 */
8441 9414
8442static void 9415static void
8443freeparam(param) 9416freeparam(volatile struct shparam *param)
8444 volatile struct shparam *param; 9417{
8445 {
8446 char **ap; 9418 char **ap;
8447 9419
8448 if (param->malloc) { 9420 if (param->malloc) {
@@ -8510,13 +9482,27 @@ setcmd(argc, argv)
8510 9482
8511 9483
8512static void 9484static void
8513getoptsreset(value) 9485getoptsreset(const char *value)
8514 const char *value;
8515{ 9486{
8516 shellparam.optind = number(value); 9487 shellparam.optind = number(value);
8517 shellparam.optoff = -1; 9488 shellparam.optoff = -1;
8518} 9489}
8519 9490
9491#ifdef BB_LOCALE_SUPPORT
9492static void change_lc_all(const char *value)
9493{
9494 if(value != 0 && *value != 0)
9495 setlocale(LC_ALL, value);
9496}
9497
9498static void change_lc_ctype(const char *value)
9499{
9500 if(value != 0 && *value != 0)
9501 setlocale(LC_CTYPE, value);
9502}
9503
9504#endif
9505
8520#ifdef ASH_GETOPTS 9506#ifdef ASH_GETOPTS
8521/* 9507/*
8522 * The getopts builtin. Shellparam.optnext points to the next argument 9508 * The getopts builtin. Shellparam.optnext points to the next argument
@@ -8612,7 +9598,7 @@ atend:
8612 goto out; 9598 goto out;
8613 } 9599 }
8614 optnext++; 9600 optnext++;
8615 if (p[0] == '-' && p[1] == '\0') /* check for "--" */ 9601 if (p[0] == '-' && p[1] == '\0') /* check for "--" */
8616 goto atend; 9602 goto atend;
8617 } 9603 }
8618 9604
@@ -8679,7 +9665,7 @@ out:
8679 } 9665 }
8680 return done; 9666 return done;
8681} 9667}
8682#endif 9668#endif
8683 9669
8684/* 9670/*
8685 * XXX - should get rid of. have all builtins use getopt(3). the 9671 * XXX - should get rid of. have all builtins use getopt(3). the
@@ -8705,7 +9691,7 @@ nextopt(optstring)
8705 if (p == NULL || *p != '-' || *++p == '\0') 9691 if (p == NULL || *p != '-' || *++p == '\0')
8706 return '\0'; 9692 return '\0';
8707 argptr++; 9693 argptr++;
8708 if (p[0] == '-' && p[1] == '\0') /* check for "--" */ 9694 if (p[0] == '-' && p[1] == '\0') /* check for "--" */
8709 return '\0'; 9695 return '\0';
8710 } 9696 }
8711 c = *p++; 9697 c = *p++;
@@ -8726,66 +9712,21 @@ nextopt(optstring)
8726} 9712}
8727 9713
8728 9714
8729/* $NetBSD: output.c,v 1.23 2001/01/07 23:39:07 lukem Exp $ */
8730
8731/* 9715/*
8732 * Shell output routines. We use our own output routines because: 9716 * Shell output routines. We use our own output routines because:
8733 * When a builtin command is interrupted we have to discard 9717 * When a builtin command is interrupted we have to discard
8734 * any pending output. 9718 * any pending output.
8735 * When a builtin command appears in back quotes, we want to 9719 * When a builtin command appears in back quotes, we want to
8736 * save the output of the command in a region obtained 9720 * save the output of the command in a region obtained
8737 * via malloc, rather than doing a fork and reading the 9721 * via malloc, rather than doing a fork and reading the
8738 * output of the command via a pipe. 9722 * output of the command via a pipe.
8739 * Our output routines may be smaller than the stdio routines. 9723 * Our output routines may be smaller than the stdio routines.
8740 */ 9724 */
8741 9725
8742 9726
8743#define OUTBUFSIZ BUFSIZ
8744#define MEM_OUT -3 /* output to dynamically allocated memory */
8745
8746
8747#ifdef USE_GLIBC_STDIO
8748struct output output = {NULL, NULL, 0, NULL, 0, 1, 0};
8749struct output errout = {NULL, NULL, 0, NULL, 0, 2, 0};
8750struct output memout = {NULL, NULL, 0, NULL, 0, MEM_OUT, 0};
8751#else
8752struct output output = {NULL, 0, NULL, OUTBUFSIZ, 1, 0};
8753struct output errout = {NULL, 0, NULL, 0, 2, 0};
8754struct output memout = {NULL, 0, NULL, 0, MEM_OUT, 0};
8755#endif
8756struct output *out1 = &output;
8757struct output *out2 = &errout;
8758
8759 9727
8760#ifndef USE_GLIBC_STDIO 9728#ifndef USE_GLIBC_STDIO
8761static void __outstr __P((const char *, size_t, struct output*)); 9729static void __outstr (const char *, size_t, struct output*);
8762#endif
8763
8764
8765#ifdef mkinit
8766
8767INCLUDE "output.h"
8768INCLUDE "memalloc.h"
8769
8770INIT {
8771#ifdef USE_GLIBC_STDIO
8772 initstreams();
8773#endif
8774}
8775
8776RESET {
8777 out1 = &output;
8778 out2 = &errout;
8779#ifdef USE_GLIBC_STDIO
8780 if (memout.stream != NULL)
8781 __closememout();
8782#endif
8783 if (memout.buf != NULL) {
8784 ckfree(memout.buf);
8785 memout.buf = NULL;
8786 }
8787}
8788
8789#endif 9730#endif
8790 9731
8791 9732
@@ -8835,10 +9776,8 @@ __outstr(const char *p, size_t len, struct output *dest) {
8835 9776
8836 9777
8837static void 9778static void
8838outstr(p, file) 9779outstr(const char *p, struct output *file)
8839 const char *p; 9780{
8840 struct output *file;
8841 {
8842#ifdef USE_GLIBC_STDIO 9781#ifdef USE_GLIBC_STDIO
8843 INTOFF; 9782 INTOFF;
8844 fputs(p, file->stream); 9783 fputs(p, file->stream);
@@ -8990,232 +9929,26 @@ fmtstr(va_alist)
8990} 9929}
8991 9930
8992#ifndef USE_GLIBC_STDIO 9931#ifndef USE_GLIBC_STDIO
8993/*
8994 * Formatted output. This routine handles a subset of the printf formats:
8995 * - Formats supported: d, u, o, p, X, s, and c.
8996 * - The x format is also accepted but is treated like X.
8997 * - The l, ll and q modifiers are accepted.
8998 * - The - and # flags are accepted; # only works with the o format.
8999 * - Width and precision may be specified with any format except c.
9000 * - An * may be given for the width or precision.
9001 * - The obsolete practice of preceding the width with a zero to get
9002 * zero padding is not supported; use the precision field.
9003 * - A % may be printed by writing %% in the format string.
9004 */
9005
9006#define TEMPSIZE 24
9007
9008#ifdef BSD4_4
9009#define HAVE_VASPRINTF 1
9010#endif
9011
9012#if !HAVE_VASPRINTF
9013static const char digit[] = "0123456789ABCDEF";
9014#endif
9015
9016 9932
9017static void 9933static void
9018doformat(dest, f, ap) 9934doformat(struct output *dest, const char *f, va_list ap)
9019 struct output *dest;
9020 const char *f; /* format string */
9021 va_list ap;
9022{ 9935{
9023#if HAVE_VASPRINTF 9936 char *pm;
9024 char *s, *t; 9937 int size = BUFSIZ;
9025 int len;
9026 9938
9027 INTOFF; 9939 while(size) {
9028 len = vasprintf(&t, f, ap); 9940 int nchars;
9029 if (len < 0) {
9030 return;
9031 }
9032 s = stalloc(++len);
9033 memcpy(s, t, len);
9034 free(t);
9035 INTON;
9036 outstr(s, dest);
9037 stunalloc(s);
9038#else /* !HAVE_VASPRINTF */
9039 char c;
9040 char temp[TEMPSIZE];
9041 int flushleft;
9042 int sharp;
9043 int width;
9044 int prec;
9045 int islong;
9046 int isquad;
9047 char *p;
9048 int sign;
9049#ifdef BSD4_4
9050 quad_t l;
9051 u_quad_t num;
9052#else
9053 long l;
9054 u_long num;
9055#endif
9056 unsigned base;
9057 int len;
9058 int size;
9059 int pad;
9060 9941
9061 while ((c = *f++) != '\0') { 9942 pm = xmalloc(size);
9062 if (c != '%') { 9943 nchars = vsnprintf(pm, size, f, ap);
9063 outc(c, dest); 9944 if(nchars > -1) {
9064 continue; 9945 outstr(pm, dest);
9065 } 9946 size = 0;
9066 flushleft = 0;
9067 sharp = 0;
9068 width = 0;
9069 prec = -1;
9070 islong = 0;
9071 isquad = 0;
9072 for (;;) {
9073 if (*f == '-')
9074 flushleft++;
9075 else if (*f == '#')
9076 sharp++;
9077 else
9078 break;
9079 f++;
9080 }
9081 if (*f == '*') {
9082 width = va_arg(ap, int);
9083 f++;
9084 } else {
9085 while (is_digit(*f)) {
9086 width = 10 * width + digit_val(*f++);
9087 }
9088 }
9089 if (*f == '.') {
9090 if (*++f == '*') {
9091 prec = va_arg(ap, int);
9092 f++;
9093 } else {
9094 prec = 0;
9095 while (is_digit(*f)) {
9096 prec = 10 * prec + digit_val(*f++);
9097 }
9098 } 9947 }
9099 } 9948 else
9100 if (*f == 'l') { 9949 size *= 2;
9101 f++; 9950 free(pm);
9102 if (*f == 'l') {
9103 isquad++;
9104 f++;
9105 } else
9106 islong++;
9107 } else if (*f == 'q') {
9108 isquad++;
9109 f++;
9110 }
9111 switch (*f) {
9112 case 'd':
9113#ifdef BSD4_4
9114 if (isquad)
9115 l = va_arg(ap, quad_t);
9116 else
9117#endif
9118 if (islong)
9119 l = va_arg(ap, long);
9120 else
9121 l = va_arg(ap, int);
9122 sign = 0;
9123 num = l;
9124 if (l < 0) {
9125 num = -l;
9126 sign = 1;
9127 }
9128 base = 10;
9129 goto number;
9130 case 'u':
9131 base = 10;
9132 goto uns_number;
9133 case 'o':
9134 base = 8;
9135 goto uns_number;
9136 case 'p':
9137 outc('0', dest);
9138 outc('x', dest);
9139 /*FALLTHROUGH*/
9140 case 'x':
9141 /* we don't implement 'x'; treat like 'X' */
9142 case 'X':
9143 base = 16;
9144uns_number: /* an unsigned number */
9145 sign = 0;
9146#ifdef BSD4_4
9147 if (isquad)
9148 num = va_arg(ap, u_quad_t);
9149 else
9150#endif
9151 if (islong)
9152 num = va_arg(ap, unsigned long);
9153 else
9154 num = va_arg(ap, unsigned int);
9155number: /* process a number */
9156 p = temp + TEMPSIZE - 1;
9157 *p = '\0';
9158 while (num) {
9159 *--p = digit[num % base];
9160 num /= base;
9161 }
9162 len = (temp + TEMPSIZE - 1) - p;
9163 if (prec < 0)
9164 prec = 1;
9165 if (sharp && *f == 'o' && prec <= len)
9166 prec = len + 1;
9167 pad = 0;
9168 if (width) {
9169 size = len;
9170 if (size < prec)
9171 size = prec;
9172 size += sign;
9173 pad = width - size;
9174 if (flushleft == 0) {
9175 while (--pad >= 0)
9176 outc(' ', dest);
9177 }
9178 }
9179 if (sign)
9180 outc('-', dest);
9181 prec -= len;
9182 while (--prec >= 0)
9183 outc('0', dest);
9184 while (*p)
9185 outc(*p++, dest);
9186 while (--pad >= 0)
9187 outc(' ', dest);
9188 break;
9189 case 's':
9190 p = va_arg(ap, char *);
9191 pad = 0;
9192 if (width) {
9193 len = strlen(p);
9194 if (prec >= 0 && len > prec)
9195 len = prec;
9196 pad = width - len;
9197 if (flushleft == 0) {
9198 while (--pad >= 0)
9199 outc(' ', dest);
9200 }
9201 }
9202 prec++;
9203 while (--prec != 0 && *p)
9204 outc(*p++, dest);
9205 while (--pad >= 0)
9206 outc(' ', dest);
9207 break;
9208 case 'c':
9209 c = va_arg(ap, int);
9210 outc(c, dest);
9211 break;
9212 default:
9213 outc(*f, dest);
9214 break;
9215 }
9216 f++;
9217 } 9951 }
9218#endif /* !HAVE_VASPRINTF */
9219} 9952}
9220#endif 9953#endif
9221 9954
@@ -9226,11 +9959,8 @@ number: /* process a number */
9226 */ 9959 */
9227 9960
9228static int 9961static int
9229xwrite(fd, buf, nbytes) 9962xwrite(int fd, const char *buf, int nbytes)
9230 int fd; 9963{
9231 const char *buf;
9232 int nbytes;
9233 {
9234 int ntry; 9964 int ntry;
9235 int i; 9965 int i;
9236 int n; 9966 int n;
@@ -9254,26 +9984,6 @@ xwrite(fd, buf, nbytes)
9254} 9984}
9255 9985
9256 9986
9257#ifdef notdef
9258/*
9259 * Version of ioctl that retries after a signal is caught.
9260 * XXX unused function
9261 */
9262
9263static int
9264xioctl(fd, request, arg)
9265 int fd;
9266 unsigned long request;
9267 char * arg;
9268{
9269 int i;
9270
9271 while ((i = ioctl(fd, request, arg)) == -1 && errno == EINTR);
9272 return i;
9273}
9274#endif
9275
9276
9277#ifdef USE_GLIBC_STDIO 9987#ifdef USE_GLIBC_STDIO
9278static void initstreams() { 9988static void initstreams() {
9279 output.stream = stdout; 9989 output.stream = stdout;
@@ -9297,8 +10007,6 @@ __closememout() {
9297 return error; 10007 return error;
9298} 10008}
9299#endif 10009#endif
9300/* $NetBSD: parser.c,v 1.46 2001/02/04 19:52:06 christos Exp $ */
9301
9302/* 10010/*
9303 * Shell command parser. 10011 * Shell command parser.
9304 */ 10012 */
@@ -9308,47 +10016,42 @@ __closememout() {
9308 10016
9309 10017
9310struct heredoc { 10018struct heredoc {
9311 struct heredoc *next; /* next here document in list */ 10019 struct heredoc *next; /* next here document in list */
9312 union node *here; /* redirection node */ 10020 union node *here; /* redirection node */
9313 char *eofmark; /* string indicating end of input */ 10021 char *eofmark; /* string indicating end of input */
9314 int striptabs; /* if set, strip leading tabs */ 10022 int striptabs; /* if set, strip leading tabs */
9315}; 10023};
9316 10024
10025static struct heredoc *heredoclist; /* list of here documents to read */
10026static int parsebackquote; /* nonzero if we are inside backquotes */
10027static int doprompt; /* if set, prompt the user */
10028static int needprompt; /* true if interactive and at start of line */
10029static int lasttoken; /* last token read */
9317 10030
10031static char *wordtext; /* text of last word returned by readtoken */
9318 10032
9319struct heredoc *heredoclist; /* list of here documents to read */ 10033static struct nodelist *backquotelist;
9320static int parsebackquote; /* nonzero if we are inside backquotes */ 10034static union node *redirnode;
9321static int doprompt; /* if set, prompt the user */
9322static int needprompt; /* true if interactive and at start of line */
9323static int lasttoken; /* last token read */
9324static int tokpushback; /* last token pushed back */
9325static char *wordtext; /* text of last word returned by readtoken */
9326static int checkkwd; /* 1 == check for kwds, 2 == also eat newlines */
9327/* 1 == check for aliases, 2 == also check for assignments */
9328static int checkalias;
9329struct nodelist *backquotelist;
9330union node *redirnode;
9331struct heredoc *heredoc; 10035struct heredoc *heredoc;
9332static int quoteflag; /* set if (part of) last token was quoted */ 10036static int quoteflag; /* set if (part of) last token was quoted */
9333static int startlinno; /* line # where last token started */ 10037static int startlinno; /* line # where last token started */
9334 10038
9335 10039
9336static union node *list __P((int)); 10040static union node *list (int);
9337static union node *andor __P((void)); 10041static union node *andor (void);
9338static union node *pipeline __P((void)); 10042static union node *pipeline (void);
9339static union node *command __P((void)); 10043static union node *command (void);
9340static union node *simplecmd __P((void)); 10044static union node *simplecmd (void);
9341static union node *makename __P((void)); 10045static void parsefname (void);
9342static void parsefname __P((void)); 10046static void parseheredoc (void);
9343static void parseheredoc __P((void)); 10047static int peektoken (void);
9344static int peektoken __P((void)); 10048static int readtoken (void);
9345static int readtoken __P((void)); 10049static int xxreadtoken (void);
9346static int xxreadtoken __P((void)); 10050static int readtoken1 (int, char const *, char *, int);
9347static int readtoken1 __P((int, char const *, char *, int)); 10051static int noexpand (char *);
9348static int noexpand __P((char *)); 10052static void synexpect (int) __attribute__((noreturn));
9349static void synexpect __P((int)) __attribute__((noreturn)); 10053static void synerror (const char *) __attribute__((noreturn));
9350static void synerror __P((const char *)) __attribute__((noreturn)); 10054static void setprompt (int);
9351static void setprompt __P((int));
9352 10055
9353 10056
9354/* 10057/*
@@ -9356,7 +10059,7 @@ static void setprompt __P((int));
9356 * valid parse tree indicating a blank line.) 10059 * valid parse tree indicating a blank line.)
9357 */ 10060 */
9358 10061
9359union node * 10062static union node *
9360parsecmd(int interact) 10063parsecmd(int interact)
9361{ 10064{
9362 int t; 10065 int t;
@@ -9436,7 +10139,7 @@ list(nlflag)
9436 if (heredoclist) 10139 if (heredoclist)
9437 parseheredoc(); 10140 parseheredoc();
9438 else 10141 else
9439 pungetc(); /* push back EOF on input */ 10142 pungetc(); /* push back EOF on input */
9440 return n1; 10143 return n1;
9441 default: 10144 default:
9442 if (nlflag) 10145 if (nlflag)
@@ -9746,7 +10449,9 @@ simplecmd() {
9746 redir = NULL; 10449 redir = NULL;
9747 rpp = &redir; 10450 rpp = &redir;
9748 10451
10452#ifdef ASH_ALIAS
9749 checkalias = 2; 10453 checkalias = 2;
10454#endif
9750 for (;;) { 10455 for (;;) {
9751 switch (readtoken()) { 10456 switch (readtoken()) {
9752 case TWORD: 10457 case TWORD:
@@ -9766,7 +10471,7 @@ simplecmd() {
9766 case TREDIR: 10471 case TREDIR:
9767 *rpp = n = redirnode; 10472 *rpp = n = redirnode;
9768 rpp = &n->nfile.next; 10473 rpp = &n->nfile.next;
9769 parsefname(); /* read name of redirection file */ 10474 parsefname(); /* read name of redirection file */
9770 break; 10475 break;
9771 case TLP: 10476 case TLP:
9772 if ( 10477 if (
@@ -9776,10 +10481,6 @@ simplecmd() {
9776 /* We have a function */ 10481 /* We have a function */
9777 if (readtoken() != TRP) 10482 if (readtoken() != TRP)
9778 synexpect(TRP); 10483 synexpect(TRP);
9779#ifdef notdef
9780 if (! goodname(n->narg.text))
9781 synerror("Bad function name");
9782#endif
9783 n->type = NDEFUN; 10484 n->type = NDEFUN;
9784 checkkwd = 2; 10485 checkkwd = 2;
9785 n->narg.next = command(); 10486 n->narg.next = command();
@@ -9805,7 +10506,7 @@ out:
9805} 10506}
9806 10507
9807static union node * 10508static union node *
9808makename() { 10509makename(void) {
9809 union node *n; 10510 union node *n;
9810 10511
9811 n = (union node *)stalloc(sizeof (struct narg)); 10512 n = (union node *)stalloc(sizeof (struct narg));
@@ -9817,7 +10518,7 @@ makename() {
9817} 10518}
9818 10519
9819static void fixredir(union node *n, const char *text, int err) 10520static void fixredir(union node *n, const char *text, int err)
9820 { 10521{
9821 TRACE(("Fix redir %s %d\n", text, err)); 10522 TRACE(("Fix redir %s %d\n", text, err));
9822 if (!err) 10523 if (!err)
9823 n->ndup.vname = NULL; 10524 n->ndup.vname = NULL;
@@ -9837,7 +10538,7 @@ static void fixredir(union node *n, const char *text, int err)
9837 10538
9838 10539
9839static void 10540static void
9840parsefname() { 10541parsefname(void) {
9841 union node *n = redirnode; 10542 union node *n = redirnode;
9842 10543
9843 if (readtoken() != TWORD) 10544 if (readtoken() != TWORD)
@@ -9912,16 +10613,25 @@ peektoken() {
9912static int 10613static int
9913readtoken() { 10614readtoken() {
9914 int t; 10615 int t;
10616#ifdef ASH_ALIAS
9915 int savecheckkwd = checkkwd; 10617 int savecheckkwd = checkkwd;
9916 int savecheckalias = checkalias; 10618 int savecheckalias = checkalias;
9917 struct alias *ap; 10619 struct alias *ap;
10620#endif
10621
9918#ifdef DEBUG 10622#ifdef DEBUG
9919 int alreadyseen = tokpushback; 10623 int alreadyseen = tokpushback;
9920#endif 10624#endif
9921 10625
10626#ifdef ASH_ALIAS
9922top: 10627top:
10628#endif
10629
9923 t = xxreadtoken(); 10630 t = xxreadtoken();
10631
10632#ifdef ASH_ALIAS
9924 checkalias = savecheckalias; 10633 checkalias = savecheckalias;
10634#endif
9925 10635
9926 if (checkkwd) { 10636 if (checkkwd) {
9927 /* 10637 /*
@@ -9950,6 +10660,7 @@ top:
9950 } 10660 }
9951 } 10661 }
9952 10662
10663#ifdef ASH_ALIAS
9953 if (t != TWORD) { 10664 if (t != TWORD) {
9954 if (t != TREDIR) { 10665 if (t != TREDIR) {
9955 checkalias = 0; 10666 checkalias = 0;
@@ -9966,6 +10677,7 @@ top:
9966 } 10677 }
9967 checkalias = 0; 10678 checkalias = 0;
9968 } 10679 }
10680#endif
9969out: 10681out:
9970#ifdef DEBUG 10682#ifdef DEBUG
9971 if (!alreadyseen) 10683 if (!alreadyseen)
@@ -9980,12 +10692,12 @@ out:
9980/* 10692/*
9981 * Read the next input token. 10693 * Read the next input token.
9982 * If the token is a word, we set backquotelist to the list of cmds in 10694 * If the token is a word, we set backquotelist to the list of cmds in
9983 * backquotes. We set quoteflag to true if any part of the word was 10695 * backquotes. We set quoteflag to true if any part of the word was
9984 * quoted. 10696 * quoted.
9985 * If the token is TREDIR, then we set redirnode to a structure containing 10697 * If the token is TREDIR, then we set redirnode to a structure containing
9986 * the redirection. 10698 * the redirection.
9987 * In all cases, the variable startlinno is set to the number of the line 10699 * In all cases, the variable startlinno is set to the number of the line
9988 * on which the token starts. 10700 * on which the token starts.
9989 * 10701 *
9990 * [Change comment: here documents and internal procedures] 10702 * [Change comment: here documents and internal procedures]
9991 * [Readtoken shouldn't have any arguments. Perhaps we should make the 10703 * [Readtoken shouldn't have any arguments. Perhaps we should make the
@@ -9995,7 +10707,7 @@ out:
9995 * have parseword (readtoken1?) handle both words and redirection.] 10707 * have parseword (readtoken1?) handle both words and redirection.]
9996 */ 10708 */
9997 10709
9998#define RETURN(token) return lasttoken = token 10710#define RETURN(token) return lasttoken = token
9999 10711
10000static int 10712static int
10001xxreadtoken() { 10713xxreadtoken() {
@@ -10010,7 +10722,7 @@ xxreadtoken() {
10010 needprompt = 0; 10722 needprompt = 0;
10011 } 10723 }
10012 startlinno = plinno; 10724 startlinno = plinno;
10013 for (;;) { /* until token or start of word found */ 10725 for (;;) { /* until token or start of word found */
10014 c = pgetc_macro(); 10726 c = pgetc_macro();
10015 switch (c) { 10727 switch (c) {
10016 case ' ': case '\t': 10728 case ' ': case '\t':
@@ -10079,12 +10791,12 @@ breakloop:
10079 * will run code that appears at the end of readtoken1. 10791 * will run code that appears at the end of readtoken1.
10080 */ 10792 */
10081 10793
10082#define CHECKEND() {goto checkend; checkend_return:;} 10794#define CHECKEND() {goto checkend; checkend_return:;}
10083#define PARSEREDIR() {goto parseredir; parseredir_return:;} 10795#define PARSEREDIR() {goto parseredir; parseredir_return:;}
10084#define PARSESUB() {goto parsesub; parsesub_return:;} 10796#define PARSESUB() {goto parsesub; parsesub_return:;}
10085#define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;} 10797#define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
10086#define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;} 10798#define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
10087#define PARSEARITH() {goto parsearith; parsearith_return:;} 10799#define PARSEARITH() {goto parsearith; parsearith_return:;}
10088 10800
10089static int 10801static int
10090readtoken1(firstc, syntax, eofmark, striptabs) 10802readtoken1(firstc, syntax, eofmark, striptabs)
@@ -10100,12 +10812,12 @@ readtoken1(firstc, syntax, eofmark, striptabs)
10100 struct nodelist *bqlist; 10812 struct nodelist *bqlist;
10101 int quotef; 10813 int quotef;
10102 int dblquote; 10814 int dblquote;
10103 int varnest; /* levels of variables expansion */ 10815 int varnest; /* levels of variables expansion */
10104 int arinest; /* levels of arithmetic expansion */ 10816 int arinest; /* levels of arithmetic expansion */
10105 int parenlevel; /* levels of parens in arithmetic */ 10817 int parenlevel; /* levels of parens in arithmetic */
10106 int dqvarnest; /* levels of variables expansion within double quotes */ 10818 int dqvarnest; /* levels of variables expansion within double quotes */
10107 int oldstyle; 10819 int oldstyle;
10108 char const *prevsyntax; /* syntax before arithmetic */ 10820 char const *prevsyntax; /* syntax before arithmetic */
10109#if __GNUC__ 10821#if __GNUC__
10110 /* Avoid longjmp clobbering */ 10822 /* Avoid longjmp clobbering */
10111 (void) &out; 10823 (void) &out;
@@ -10132,24 +10844,14 @@ readtoken1(firstc, syntax, eofmark, striptabs)
10132 dqvarnest = 0; 10844 dqvarnest = 0;
10133 10845
10134 STARTSTACKSTR(out); 10846 STARTSTACKSTR(out);
10135 loop: { /* for each line, until end of word */ 10847 loop: { /* for each line, until end of word */
10136#if ATTY 10848 CHECKEND(); /* set c to PEOF if at end of here document */
10137 if (c == '\034' && doprompt 10849 for (;;) { /* until end of line or end of word */
10138 && attyset() && ! equal(termval(), "emacs")) { 10850 CHECKSTRSPACE(3, out); /* permit 3 calls to USTPUTC */
10139 attyline();
10140 if (syntax == BASESYNTAX)
10141 return readtoken();
10142 c = pgetc();
10143 goto loop;
10144 }
10145#endif
10146 CHECKEND(); /* set c to PEOF if at end of here document */
10147 for (;;) { /* until end of line or end of word */
10148 CHECKSTRSPACE(3, out); /* permit 3 calls to USTPUTC */
10149 switch(syntax[c]) { 10851 switch(syntax[c]) {
10150 case CNL: /* '\n' */ 10852 case CNL: /* '\n' */
10151 if (syntax == BASESYNTAX) 10853 if (syntax == BASESYNTAX)
10152 goto endword; /* exit outer loop */ 10854 goto endword; /* exit outer loop */
10153 USTPUTC(c, out); 10855 USTPUTC(c, out);
10154 plinno++; 10856 plinno++;
10155 if (doprompt) 10857 if (doprompt)
@@ -10157,7 +10859,7 @@ readtoken1(firstc, syntax, eofmark, striptabs)
10157 else 10859 else
10158 setprompt(0); 10860 setprompt(0);
10159 c = pgetc(); 10861 c = pgetc();
10160 goto loop; /* continue outer loop */ 10862 goto loop; /* continue outer loop */
10161 case CWORD: 10863 case CWORD:
10162 USTPUTC(c, out); 10864 USTPUTC(c, out);
10163 break; 10865 break;
@@ -10167,7 +10869,7 @@ readtoken1(firstc, syntax, eofmark, striptabs)
10167 USTPUTC(CTLESC, out); 10869 USTPUTC(CTLESC, out);
10168 USTPUTC(c, out); 10870 USTPUTC(c, out);
10169 break; 10871 break;
10170 case CBACK: /* backslash */ 10872 case CBACK: /* backslash */
10171 c = pgetc2(); 10873 c = pgetc2();
10172 if (c == PEOF) { 10874 if (c == PEOF) {
10173 USTPUTC('\\', out); 10875 USTPUTC('\\', out);
@@ -10216,10 +10918,10 @@ readtoken1(firstc, syntax, eofmark, striptabs)
10216 quotef++; 10918 quotef++;
10217 } 10919 }
10218 break; 10920 break;
10219 case CVAR: /* '$' */ 10921 case CVAR: /* '$' */
10220 PARSESUB(); /* parse substitution */ 10922 PARSESUB(); /* parse substitution */
10221 break; 10923 break;
10222 case CENDVAR: /* '}' */ 10924 case CENDVAR: /* '}' */
10223 if (varnest > 0) { 10925 if (varnest > 0) {
10224 varnest--; 10926 varnest--;
10225 if (dqvarnest > 0) { 10927 if (dqvarnest > 0) {
@@ -10231,11 +10933,11 @@ readtoken1(firstc, syntax, eofmark, striptabs)
10231 } 10933 }
10232 break; 10934 break;
10233#ifdef ASH_MATH_SUPPORT 10935#ifdef ASH_MATH_SUPPORT
10234 case CLP: /* '(' in arithmetic */ 10936 case CLP: /* '(' in arithmetic */
10235 parenlevel++; 10937 parenlevel++;
10236 USTPUTC(c, out); 10938 USTPUTC(c, out);
10237 break; 10939 break;
10238 case CRP: /* ')' in arithmetic */ 10940 case CRP: /* ')' in arithmetic */
10239 if (parenlevel > 0) { 10941 if (parenlevel > 0) {
10240 USTPUTC(c, out); 10942 USTPUTC(c, out);
10241 --parenlevel; 10943 --parenlevel;
@@ -10261,16 +10963,16 @@ readtoken1(firstc, syntax, eofmark, striptabs)
10261 } 10963 }
10262 break; 10964 break;
10263#endif 10965#endif
10264 case CBQUOTE: /* '`' */ 10966 case CBQUOTE: /* '`' */
10265 PARSEBACKQOLD(); 10967 PARSEBACKQOLD();
10266 break; 10968 break;
10267 case CEOF: 10969 case CENDFILE:
10268 goto endword; /* exit outer loop */ 10970 goto endword; /* exit outer loop */
10269 case CIGN: 10971 case CIGN:
10270 break; 10972 break;
10271 default: 10973 default:
10272 if (varnest == 0) 10974 if (varnest == 0)
10273 goto endword; /* exit outer loop */ 10975 goto endword; /* exit outer loop */
10274 if (c != PEOA) { 10976 if (c != PEOA) {
10275 USTPUTC(c, out); 10977 USTPUTC(c, out);
10276 } 10978 }
@@ -10318,9 +11020,11 @@ endword:
10318 11020
10319checkend: { 11021checkend: {
10320 if (eofmark) { 11022 if (eofmark) {
11023#ifdef ASH_ALIAS
10321 if (c == PEOA) { 11024 if (c == PEOA) {
10322 c = pgetc2(); 11025 c = pgetc2();
10323 } 11026 }
11027#endif
10324 if (striptabs) { 11028 if (striptabs) {
10325 while (c == '\t') { 11029 while (c == '\t') {
10326 c = pgetc2(); 11030 c = pgetc2();
@@ -10370,7 +11074,7 @@ parseredir: {
10370 np->type = NTO; 11074 np->type = NTO;
10371 pungetc(); 11075 pungetc();
10372 } 11076 }
10373 } else { /* c == '<' */ 11077 } else { /* c == '<' */
10374 np->nfile.fd = 0; 11078 np->nfile.fd = 0;
10375 switch (c = pgetc()) { 11079 switch (c = pgetc()) {
10376 case '<': 11080 case '<':
@@ -10429,7 +11133,7 @@ parsesub: {
10429 ) { 11133 ) {
10430 USTPUTC('$', out); 11134 USTPUTC('$', out);
10431 pungetc(); 11135 pungetc();
10432 } else if (c == '(') { /* $(command) or $((arith)) */ 11136 } else if (c == '(') { /* $(command) or $((arith)) */
10433 if (pgetc() == '(') { 11137 if (pgetc() == '(') {
10434 PARSEARITH(); 11138 PARSEARITH();
10435 } else { 11139 } else {
@@ -10468,7 +11172,7 @@ parsesub: {
10468 c = pgetc(); 11172 c = pgetc();
10469 } 11173 }
10470 else 11174 else
10471badsub: synerror("Bad substitution"); 11175badsub: synerror("Bad substitution");
10472 11176
10473 STPUTC('=', out); 11177 STPUTC('=', out);
10474 flags = 0; 11178 flags = 0;
@@ -10553,17 +11257,17 @@ parsebackq: {
10553 savehandler = handler; 11257 savehandler = handler;
10554 handler = &jmploc; 11258 handler = &jmploc;
10555 INTON; 11259 INTON;
10556 if (oldstyle) { 11260 if (oldstyle) {
10557 /* We must read until the closing backquote, giving special 11261 /* We must read until the closing backquote, giving special
10558 treatment to some slashes, and then push the string and 11262 treatment to some slashes, and then push the string and
10559 reread it as input, interpreting it normally. */ 11263 reread it as input, interpreting it normally. */
10560 char *pout; 11264 char *pout;
10561 int pc; 11265 int pc;
10562 int psavelen; 11266 int psavelen;
10563 char *pstr; 11267 char *pstr;
10564 11268
10565 11269
10566 STARTSTACKSTR(pout); 11270 STARTSTACKSTR(pout);
10567 for (;;) { 11271 for (;;) {
10568 if (needprompt) { 11272 if (needprompt) {
10569 setprompt(2); 11273 setprompt(2);
@@ -10574,7 +11278,7 @@ parsebackq: {
10574 goto done; 11278 goto done;
10575 11279
10576 case '\\': 11280 case '\\':
10577 if ((pc = pgetc()) == '\n') { 11281 if ((pc = pgetc()) == '\n') {
10578 plinno++; 11282 plinno++;
10579 if (doprompt) 11283 if (doprompt)
10580 setprompt(2); 11284 setprompt(2);
@@ -10588,17 +11292,19 @@ parsebackq: {
10588 */ 11292 */
10589 continue; 11293 continue;
10590 } 11294 }
10591 if (pc != '\\' && pc != '`' && pc != '$' 11295 if (pc != '\\' && pc != '`' && pc != '$'
10592 && (!dblquote || pc != '"')) 11296 && (!dblquote || pc != '"'))
10593 STPUTC('\\', pout); 11297 STPUTC('\\', pout);
10594 if (pc > PEOA) { 11298 if (pc > PEOA) {
10595 break; 11299 break;
10596 } 11300 }
10597 /* fall through */ 11301 /* fall through */
10598 11302
10599 case PEOF: 11303 case PEOF:
11304#ifdef ASH_ALIAS
10600 case PEOA: 11305 case PEOA:
10601 startlinno = plinno; 11306#endif
11307 startlinno = plinno;
10602 synerror("EOF in backquote substitution"); 11308 synerror("EOF in backquote substitution");
10603 11309
10604 case '\n': 11310 case '\n':
@@ -10610,15 +11316,15 @@ parsebackq: {
10610 break; 11316 break;
10611 } 11317 }
10612 STPUTC(pc, pout); 11318 STPUTC(pc, pout);
10613 } 11319 }
10614done: 11320done:
10615 STPUTC('\0', pout); 11321 STPUTC('\0', pout);
10616 psavelen = pout - stackblock(); 11322 psavelen = pout - stackblock();
10617 if (psavelen > 0) { 11323 if (psavelen > 0) {
10618 pstr = grabstackstr(pout); 11324 pstr = grabstackstr(pout);
10619 setinputstring(pstr); 11325 setinputstring(pstr);
10620 } 11326 }
10621 } 11327 }
10622 nlpp = &bqlist; 11328 nlpp = &bqlist;
10623 while (*nlpp) 11329 while (*nlpp)
10624 nlpp = &(*nlpp)->next; 11330 nlpp = &(*nlpp)->next;
@@ -10641,12 +11347,12 @@ done:
10641 } 11347 }
10642 11348
10643 (*nlpp)->n = n; 11349 (*nlpp)->n = n;
10644 if (oldstyle) { 11350 if (oldstyle) {
10645 /* 11351 /*
10646 * Start reading from old file again, ignoring any pushed back 11352 * Start reading from old file again, ignoring any pushed back
10647 * tokens left from the backquote parsing 11353 * tokens left from the backquote parsing
10648 */ 11354 */
10649 popfile(); 11355 popfile();
10650 tokpushback = 0; 11356 tokpushback = 0;
10651 } 11357 }
10652 while (stackblocksize() <= savelen) 11358 while (stackblocksize() <= savelen)
@@ -10698,16 +11404,6 @@ parsearith: {
10698} /* end of readtoken */ 11404} /* end of readtoken */
10699 11405
10700 11406
10701
10702#ifdef mkinit
10703INCLUDE "parser.h"
10704RESET {
10705 tokpushback = 0;
10706 checkkwd = 0;
10707 checkalias = 0;
10708}
10709#endif
10710
10711/* 11407/*
10712 * Returns true if the text contains nothing to expand (no dollar signs 11408 * Returns true if the text contains nothing to expand (no dollar signs
10713 * or backquotes). 11409 * or backquotes).
@@ -10739,9 +11435,9 @@ noexpand(text)
10739 */ 11435 */
10740 11436
10741static int 11437static int
10742goodname(char *name) 11438goodname(const char *name)
10743 { 11439{
10744 char *p; 11440 const char *p;
10745 11441
10746 p = name; 11442 p = name;
10747 if (! is_name(*p)) 11443 if (! is_name(*p))
@@ -10778,9 +11474,8 @@ synexpect(token)
10778 11474
10779 11475
10780static void 11476static void
10781synerror(msg) 11477synerror(const char *msg)
10782 const char *msg; 11478{
10783 {
10784 if (commandname) 11479 if (commandname)
10785 outfmt(&errout, "%s: %d: ", commandname, startlinno); 11480 outfmt(&errout, "%s: %d: ", commandname, startlinno);
10786 outfmt(&errout, "Syntax error: %s\n", msg); 11481 outfmt(&errout, "Syntax error: %s\n", msg);
@@ -10788,12 +11483,6 @@ synerror(msg)
10788 /* NOTREACHED */ 11483 /* NOTREACHED */
10789} 11484}
10790 11485
10791static void
10792setprompt(int which)
10793{
10794 whichprompt = which;
10795 putprompt(getprompt(NULL));
10796}
10797 11486
10798/* 11487/*
10799 * called by editline -- any expansions to the prompt 11488 * called by editline -- any expansions to the prompt
@@ -10801,7 +11490,7 @@ setprompt(int which)
10801 */ 11490 */
10802static const char * 11491static const char *
10803getprompt(void *unused) 11492getprompt(void *unused)
10804 { 11493{
10805 switch (whichprompt) { 11494 switch (whichprompt) {
10806 case 0: 11495 case 0:
10807 return ""; 11496 return "";
@@ -10814,56 +11503,26 @@ getprompt(void *unused)
10814 } 11503 }
10815} 11504}
10816 11505
10817static int 11506static void
10818isassignment(const char *word) { 11507setprompt(int which)
10819 if (!is_name(*word)) { 11508{
10820 return 0; 11509 whichprompt = which;
10821 } 11510 putprompt(getprompt(NULL));
10822 do {
10823 word++;
10824 } while (is_in_name(*word));
10825 return *word == '=';
10826} 11511}
10827 11512
10828static const char *const *
10829findkwd(const char *s) {
10830 return findstring(
10831 s, parsekwd, sizeof(parsekwd) / sizeof(const char *)
10832 );
10833}
10834/* $NetBSD: redir.c,v 1.22 2000/05/22 10:18:47 elric Exp $ */
10835 11513
10836/* 11514/*
10837 * Code for dealing with input/output redirection. 11515 * Code for dealing with input/output redirection.
10838 */ 11516 */
10839 11517
10840#define EMPTY -2 /* marks an unused slot in redirtab */ 11518#define EMPTY -2 /* marks an unused slot in redirtab */
10841#ifndef PIPE_BUF 11519#ifndef PIPE_BUF
10842# define PIPESIZE 4096 /* amount of buffering in a pipe */ 11520# define PIPESIZE 4096 /* amount of buffering in a pipe */
10843#else 11521#else
10844# define PIPESIZE PIPE_BUF 11522# define PIPESIZE PIPE_BUF
10845#endif 11523#endif
10846 11524
10847 11525
10848struct redirtab *redirlist;
10849
10850/*
10851 * We keep track of whether or not fd0 has been redirected. This is for
10852 * background commands, where we want to redirect fd0 to /dev/null only
10853 * if it hasn't already been redirected.
10854*/
10855static int fd0_redirected = 0;
10856
10857/*
10858 * We also keep track of where fileno2 goes.
10859 */
10860static int fileno2 = 2;
10861
10862static int openredirect __P((union node *));
10863static void dupredirect __P((union node *, int, char[10 ]));
10864static int openhere __P((union node *));
10865static int noclobberopen __P((const char *));
10866
10867 11526
10868/* 11527/*
10869 * Process a list of redirection commands. If the REDIR_PUSH flag is set, 11528 * Process a list of redirection commands. If the REDIR_PUSH flag is set,
@@ -10884,7 +11543,7 @@ redirect(redir, flags)
10884 int fd; 11543 int fd;
10885 int newfd; 11544 int newfd;
10886 int try; 11545 int try;
10887 char memory[10]; /* file descriptors to write to memory */ 11546 char memory[10]; /* file descriptors to write to memory */
10888 11547
10889 for (i = 10 ; --i >= 0 ; ) 11548 for (i = 10 ; --i >= 0 ; )
10890 memory[i] = 0; 11549 memory[i] = 0;
@@ -10923,7 +11582,7 @@ redirect(redir, flags)
10923 close(newfd); 11582 close(newfd);
10924 } 11583 }
10925 INTON; 11584 INTON;
10926 error("%d: %s", fd, strerror(errno)); 11585 error("%d: %m", fd);
10927 /* NOTREACHED */ 11586 /* NOTREACHED */
10928 } 11587 }
10929 } 11588 }
@@ -10939,8 +11598,8 @@ redirect(redir, flags)
10939 } else if (fd != newfd) { 11598 } else if (fd != newfd) {
10940 close(fd); 11599 close(fd);
10941 } 11600 }
10942 if (fd == 0) 11601 if (fd == 0)
10943 fd0_redirected++; 11602 fd0_redirected++;
10944 if (!try) 11603 if (!try)
10945 dupredirect(n, newfd, memory); 11604 dupredirect(n, newfd, memory);
10946 INTON; 11605 INTON;
@@ -11024,16 +11683,13 @@ eopen:
11024 11683
11025 11684
11026static void 11685static void
11027dupredirect(redir, f, memory) 11686dupredirect(union node *redir, int f, char memory[10])
11028 union node *redir; 11687{
11029 int f;
11030 char memory[10];
11031 {
11032 int fd = redir->nfile.fd; 11688 int fd = redir->nfile.fd;
11033 11689
11034 memory[fd] = 0; 11690 memory[fd] = 0;
11035 if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) { 11691 if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
11036 if (redir->ndup.dupfd >= 0) { /* if not ">&-" */ 11692 if (redir->ndup.dupfd >= 0) { /* if not ">&-" */
11037 if (memory[redir->ndup.dupfd]) 11693 if (memory[redir->ndup.dupfd])
11038 memory[fd] = 1; 11694 memory[fd] = 1;
11039 else 11695 else
@@ -11093,21 +11749,21 @@ out:
11093} 11749}
11094 11750
11095 11751
11096
11097/* 11752/*
11098 * Undo the effects of the last redirection. 11753 * Undo the effects of the last redirection.
11099 */ 11754 */
11100 11755
11101static void 11756static void
11102popredir() { 11757popredir(void)
11758{
11103 struct redirtab *rp = redirlist; 11759 struct redirtab *rp = redirlist;
11104 int i; 11760 int i;
11105 11761
11106 INTOFF; 11762 INTOFF;
11107 for (i = 0 ; i < 10 ; i++) { 11763 for (i = 0 ; i < 10 ; i++) {
11108 if (rp->renamed[i] != EMPTY) { 11764 if (rp->renamed[i] != EMPTY) {
11109 if (i == 0) 11765 if (i == 0)
11110 fd0_redirected--; 11766 fd0_redirected--;
11111 close(i); 11767 close(i);
11112 if (rp->renamed[i] >= 0) { 11768 if (rp->renamed[i] >= 0) {
11113 dup_as_newfd(rp->renamed[i], i); 11769 dup_as_newfd(rp->renamed[i], i);
@@ -11124,36 +11780,11 @@ popredir() {
11124} 11780}
11125 11781
11126/* 11782/*
11127 * Undo all redirections. Called on error or interrupt.
11128 */
11129
11130#ifdef mkinit
11131
11132INCLUDE "redir.h"
11133
11134RESET {
11135 while (redirlist)
11136 popredir();
11137}
11138
11139SHELLPROC {
11140 clearredir();
11141}
11142
11143#endif
11144
11145/* Return true if fd 0 has already been redirected at least once. */
11146static int
11147fd0_redirected_p () {
11148 return fd0_redirected != 0;
11149}
11150
11151/*
11152 * Discard all saved file descriptors. 11783 * Discard all saved file descriptors.
11153 */ 11784 */
11154 11785
11155static void 11786static void
11156clearredir() { 11787clearredir(void) {
11157 struct redirtab *rp; 11788 struct redirtab *rp;
11158 int i; 11789 int i;
11159 11790
@@ -11175,7 +11806,6 @@ clearredir() {
11175} 11806}
11176 11807
11177 11808
11178
11179/* 11809/*
11180 * Copy a file descriptor to be >= to. Returns -1 11810 * Copy a file descriptor to be >= to. Returns -1
11181 * if the source file descriptor is closed, EMPTY if there are no unused 11811 * if the source file descriptor is closed, EMPTY if there are no unused
@@ -11194,7 +11824,7 @@ dup_as_newfd(from, to)
11194 if (errno == EMFILE) 11824 if (errno == EMFILE)
11195 return EMPTY; 11825 return EMPTY;
11196 else 11826 else
11197 error("%d: %s", from, strerror(errno)); 11827 error("%d: %m", from);
11198 } 11828 }
11199 return newfd; 11829 return newfd;
11200} 11830}
@@ -11204,8 +11834,7 @@ dup_as_newfd(from, to)
11204 * The code was copied from bash. 11834 * The code was copied from bash.
11205 */ 11835 */
11206static int 11836static int
11207noclobberopen(fname) 11837noclobberopen(const char *fname)
11208 const char *fname;
11209{ 11838{
11210 int r, fd; 11839 int r, fd;
11211 struct stat finfo, finfo2; 11840 struct stat finfo, finfo2;
@@ -11250,43 +11879,41 @@ noclobberopen(fname)
11250 */ 11879 */
11251 if (fstat(fd, &finfo2) == 0 && !S_ISREG(finfo2.st_mode) && 11880 if (fstat(fd, &finfo2) == 0 && !S_ISREG(finfo2.st_mode) &&
11252 finfo.st_dev == finfo2.st_dev && finfo.st_ino == finfo2.st_ino) 11881 finfo.st_dev == finfo2.st_dev && finfo.st_ino == finfo2.st_ino)
11253 return fd; 11882 return fd;
11254 11883
11255 /* The file has been replaced. badness. */ 11884 /* The file has been replaced. badness. */
11256 close(fd); 11885 close(fd);
11257 errno = EEXIST; 11886 errno = EEXIST;
11258 return -1; 11887 return -1;
11259} 11888}
11260/* $NetBSD: setmode.c,v 1.28 2000/01/25 15:43:43 enami Exp $ */ 11889/*#ifdef __weak_alias
11261
11262#ifdef __weak_alias
11263__weak_alias(getmode,_getmode) 11890__weak_alias(getmode,_getmode)
11264__weak_alias(setmode,_setmode) 11891__weak_alias(setmode,_setmode)
11265#endif 11892#endif*/
11266 11893
11267#ifdef __GLIBC__ 11894#ifdef __GLIBC__
11268#define S_ISTXT __S_ISVTX 11895#define S_ISTXT __S_ISVTX
11269#endif 11896#endif
11270 11897
11271#define SET_LEN 6 /* initial # of bitcmd struct to malloc */ 11898#define SET_LEN 6 /* initial # of bitcmd struct to malloc */
11272#define SET_LEN_INCR 4 /* # of bitcmd structs to add as needed */ 11899#define SET_LEN_INCR 4 /* # of bitcmd structs to add as needed */
11273 11900
11274typedef struct bitcmd { 11901typedef struct bitcmd {
11275 char cmd; 11902 char cmd;
11276 char cmd2; 11903 char cmd2;
11277 mode_t bits; 11904 mode_t bits;
11278} BITCMD; 11905} BITCMD;
11279 11906
11280#define CMD2_CLR 0x01 11907#define CMD2_CLR 0x01
11281#define CMD2_SET 0x02 11908#define CMD2_SET 0x02
11282#define CMD2_GBITS 0x04 11909#define CMD2_GBITS 0x04
11283#define CMD2_OBITS 0x08 11910#define CMD2_OBITS 0x08
11284#define CMD2_UBITS 0x10 11911#define CMD2_UBITS 0x10
11285 11912
11286static BITCMD *addcmd __P((BITCMD *, int, int, int, u_int)); 11913static BITCMD *addcmd (BITCMD *, int, int, int, u_int);
11287static void compress_mode __P((BITCMD *)); 11914static void compress_mode (BITCMD *);
11288#ifdef SETMODE_DEBUG 11915#ifdef SETMODE_DEBUG
11289static void dumpmode __P((BITCMD *)); 11916static void dumpmode (BITCMD *);
11290#endif 11917#endif
11291 11918
11292/* 11919/*
@@ -11295,7 +11922,7 @@ static void dumpmode __P((BITCMD *));
11295 * Note that there is no '=' command; a strict assignment is just a '-' (clear 11922 * Note that there is no '=' command; a strict assignment is just a '-' (clear
11296 * bits) followed by a '+' (set bits). 11923 * bits) followed by a '+' (set bits).
11297 */ 11924 */
11298mode_t 11925static mode_t
11299getmode(bbox, omode) 11926getmode(bbox, omode)
11300 const void *bbox; 11927 const void *bbox;
11301 mode_t omode; 11928 mode_t omode;
@@ -11325,7 +11952,7 @@ getmode(bbox, omode)
11325 11952
11326 case 'o': 11953 case 'o':
11327 value = newmode & S_IRWXO; 11954 value = newmode & S_IRWXO;
11328common: if (set->cmd2 & CMD2_CLR) { 11955common: if (set->cmd2 & CMD2_CLR) {
11329 clrval = 11956 clrval =
11330 (set->cmd2 & CMD2_SET) ? S_IRWXO : value; 11957 (set->cmd2 & CMD2_SET) ? S_IRWXO : value;
11331 if (set->cmd2 & CMD2_UBITS) 11958 if (set->cmd2 & CMD2_UBITS)
@@ -11367,23 +11994,23 @@ common: if (set->cmd2 & CMD2_CLR) {
11367 } 11994 }
11368} 11995}
11369 11996
11370#define ADDCMD(a, b, c, d) do { \ 11997#define ADDCMD(a, b, c, d) do { \
11371 if (set >= endset) { \ 11998 if (set >= endset) { \
11372 BITCMD *newset; \ 11999 BITCMD *newset; \
11373 setlen += SET_LEN_INCR; \ 12000 setlen += SET_LEN_INCR; \
11374 newset = realloc(saveset, sizeof(BITCMD) * setlen); \ 12001 newset = realloc(saveset, sizeof(BITCMD) * setlen); \
11375 if (newset == NULL) { \ 12002 if (newset == NULL) { \
11376 free(saveset); \ 12003 free(saveset); \
11377 return (NULL); \ 12004 return (NULL); \
11378 } \ 12005 } \
11379 set = newset + (set - saveset); \ 12006 set = newset + (set - saveset); \
11380 saveset = newset; \ 12007 saveset = newset; \
11381 endset = newset + (setlen - 2); \ 12008 endset = newset + (setlen - 2); \
11382 } \ 12009 } \
11383 set = addcmd(set, (a), (b), (c), (d)); \ 12010 set = addcmd(set, (a), (b), (c), (d)); \
11384} while (/*CONSTCOND*/0) 12011} while (/*CONSTCOND*/0)
11385 12012
11386#define STANDARD_BITS (S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO) 12013#define STANDARD_BITS (S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO)
11387 12014
11388static void * 12015static void *
11389setmode(p) 12016setmode(p)
@@ -11394,7 +12021,7 @@ setmode(p)
11394 BITCMD *set, *saveset, *endset; 12021 BITCMD *set, *saveset, *endset;
11395 sigset_t mysigset, sigoset; 12022 sigset_t mysigset, sigoset;
11396 mode_t mask; 12023 mode_t mask;
11397 int equalopdone = 0; /* pacify gcc */ 12024 int equalopdone = 0; /* pacify gcc */
11398 int permXbits, setlen; 12025 int permXbits, setlen;
11399 12026
11400 if (!*p) 12027 if (!*p)
@@ -11413,7 +12040,7 @@ setmode(p)
11413 (void)sigprocmask(SIG_SETMASK, &sigoset, NULL); 12040 (void)sigprocmask(SIG_SETMASK, &sigoset, NULL);
11414 12041
11415 setlen = SET_LEN + 2; 12042 setlen = SET_LEN + 2;
11416 12043
11417 if ((set = malloc((u_int)(sizeof(BITCMD) * setlen))) == NULL) 12044 if ((set = malloc((u_int)(sizeof(BITCMD) * setlen))) == NULL)
11418 return (NULL); 12045 return (NULL);
11419 saveset = set; 12046 saveset = set;
@@ -11459,7 +12086,7 @@ setmode(p)
11459 } 12086 }
11460 } 12087 }
11461 12088
11462getop: if ((op = *p++) != '+' && op != '-' && op != '=') { 12089getop: if ((op = *p++) != '+' && op != '-' && op != '=') {
11463 free(saveset); 12090 free(saveset);
11464 return (NULL); 12091 return (NULL);
11465 } 12092 }
@@ -11474,16 +12101,16 @@ getop: if ((op = *p++) != '+' && op != '-' && op != '=') {
11474 break; 12101 break;
11475 case 's': 12102 case 's':
11476 /* 12103 /*
11477 * If specific bits where requested and 12104 * If specific bits where requested and
11478 * only "other" bits ignore set-id. 12105 * only "other" bits ignore set-id.
11479 */ 12106 */
11480 if (who == 0 || (who & ~S_IRWXO)) 12107 if (who == 0 || (who & ~S_IRWXO))
11481 perm |= S_ISUID|S_ISGID; 12108 perm |= S_ISUID|S_ISGID;
11482 break; 12109 break;
11483 case 't': 12110 case 't':
11484 /* 12111 /*
11485 * If specific bits where requested and 12112 * If specific bits where requested and
11486 * only "other" bits ignore set-id. 12113 * only "other" bits ignore set-id.
11487 */ 12114 */
11488 if (who == 0 || (who & ~S_IRWXO)) { 12115 if (who == 0 || (who & ~S_IRWXO)) {
11489 who |= S_ISTXT; 12116 who |= S_ISTXT;
@@ -11539,7 +12166,7 @@ getop: if ((op = *p++) != '+' && op != '-' && op != '=') {
11539 } 12166 }
11540 } 12167 }
11541 12168
11542apply: if (!*p) 12169apply: if (!*p)
11543 break; 12170 break;
11544 if (*p != ',') 12171 if (*p != ',')
11545 goto getop; 12172 goto getop;
@@ -11596,7 +12223,7 @@ addcmd(set, op, who, oparg, mask)
11596 set->cmd2 = CMD2_UBITS | CMD2_GBITS | CMD2_OBITS; 12223 set->cmd2 = CMD2_UBITS | CMD2_GBITS | CMD2_OBITS;
11597 set->bits = mask; 12224 set->bits = mask;
11598 } 12225 }
11599 12226
11600 if (oparg == '+') 12227 if (oparg == '+')
11601 set->cmd2 |= CMD2_SET; 12228 set->cmd2 |= CMD2_SET;
11602 else if (oparg == '-') 12229 else if (oparg == '-')
@@ -11630,7 +12257,7 @@ dumpmode(set)
11630/* 12257/*
11631 * Given an array of bitcmd structures, compress by compacting consecutive 12258 * Given an array of bitcmd structures, compress by compacting consecutive
11632 * '+', '-' and 'X' commands into at most 3 commands, one of each. The 'u', 12259 * '+', '-' and 'X' commands into at most 3 commands, one of each. The 'u',
11633 * 'g' and 'o' commands continue to be separate. They could probably be 12260 * 'g' and 'o' commands continue to be separate. They could probably be
11634 * compacted, but it's not worth the effort. 12261 * compacted, but it's not worth the effort.
11635 */ 12262 */
11636static void 12263static void
@@ -11684,15 +12311,12 @@ compress_mode(set)
11684 } 12311 }
11685 } 12312 }
11686} 12313}
11687/* $NetBSD: show.c,v 1.18 1999/10/08 21:10:44 pk Exp $ */
11688
11689
11690#ifdef DEBUG 12314#ifdef DEBUG
11691static void shtree __P((union node *, int, char *, FILE*)); 12315static void shtree (union node *, int, char *, FILE*);
11692static void shcmd __P((union node *, FILE *)); 12316static void shcmd (union node *, FILE *);
11693static void sharg __P((union node *, FILE *)); 12317static void sharg (union node *, FILE *);
11694static void indent __P((int, char *, FILE *)); 12318static void indent (int, char *, FILE *);
11695static void trstring __P((char *)); 12319static void trstring (char *);
11696 12320
11697 12321
11698static void 12322static void
@@ -11780,14 +12404,14 @@ shcmd(cmd, fp)
11780 if (! first) 12404 if (! first)
11781 putchar(' '); 12405 putchar(' ');
11782 switch (np->nfile.type) { 12406 switch (np->nfile.type) {
11783 case NTO: s = ">"; dftfd = 1; break; 12407 case NTO: s = ">"; dftfd = 1; break;
11784 case NAPPEND: s = ">>"; dftfd = 1; break; 12408 case NAPPEND: s = ">>"; dftfd = 1; break;
11785 case NTOFD: s = ">&"; dftfd = 1; break; 12409 case NTOFD: s = ">&"; dftfd = 1; break;
11786 case NTOOV: s = ">|"; dftfd = 1; break; 12410 case NTOOV: s = ">|"; dftfd = 1; break;
11787 case NFROM: s = "<"; dftfd = 0; break; 12411 case NFROM: s = "<"; dftfd = 0; break;
11788 case NFROMFD: s = "<&"; dftfd = 0; break; 12412 case NFROMFD: s = "<&"; dftfd = 0; break;
11789 case NFROMTO: s = "<>"; dftfd = 0; break; 12413 case NFROMTO: s = "<>"; dftfd = 0; break;
11790 default: s = "*error*"; dftfd = 0; break; 12414 default: s = "*error*"; dftfd = 0; break;
11791 } 12415 }
11792 if (np->nfile.fd != dftfd) 12416 if (np->nfile.fd != dftfd)
11793 fprintf(fp, "%d", np->nfile.fd); 12417 fprintf(fp, "%d", np->nfile.fd);
@@ -11988,7 +12612,7 @@ trstring(s)
11988 case CTLVAR+CTLQUOTE: c = 'V'; goto backslash; 12612 case CTLVAR+CTLQUOTE: c = 'V'; goto backslash;
11989 case CTLBACKQ: c = 'q'; goto backslash; 12613 case CTLBACKQ: c = 'q'; goto backslash;
11990 case CTLBACKQ+CTLQUOTE: c = 'Q'; goto backslash; 12614 case CTLBACKQ+CTLQUOTE: c = 'Q'; goto backslash;
11991backslash: putc('\\', tracefile); 12615backslash: putc('\\', tracefile);
11992 putc(c, tracefile); 12616 putc(c, tracefile);
11993 break; 12617 break;
11994 default: 12618 default:
@@ -12042,11 +12666,11 @@ opentrace() {
12042 else 12666 else
12043 p = "/tmp"; 12667 p = "/tmp";
12044 } 12668 }
12045 scopy(p, s); 12669 strcpy(s, p);
12046 strcat(s, "/trace"); 12670 strcat(s, "/trace");
12047 } 12671 }
12048#else 12672#else
12049 scopy("./trace", s); 12673 strcpy(s, "./trace");
12050#endif /* not_this_way */ 12674#endif /* not_this_way */
12051 if ((tracefile = fopen(s, "a")) == NULL) { 12675 if ((tracefile = fopen(s, "a")) == NULL) {
12052 fprintf(stderr, "Can't open %s\n", s); 12676 fprintf(stderr, "Can't open %s\n", s);
@@ -12063,356 +12687,6 @@ opentrace() {
12063 12687
12064 12688
12065/* 12689/*
12066 * This file was generated by the mksyntax program.
12067 */
12068
12069/* syntax table used when not in quotes */
12070static const char basesyntax[257] = {
12071 CEOF, CSPCL, CWORD, CCTL,
12072 CCTL, CCTL, CCTL, CCTL,
12073 CCTL, CCTL, CCTL, CWORD,
12074 CWORD, CWORD, CWORD, CWORD,
12075 CWORD, CWORD, CWORD, CWORD,
12076 CWORD, CWORD, CWORD, CWORD,
12077 CWORD, CWORD, CWORD, CWORD,
12078 CWORD, CWORD, CWORD, CWORD,
12079 CWORD, CWORD, CWORD, CWORD,
12080 CWORD, CWORD, CWORD, CWORD,
12081 CWORD, CWORD, CWORD, CWORD,
12082 CWORD, CWORD, CWORD, CWORD,
12083 CWORD, CWORD, CWORD, CWORD,
12084 CWORD, CWORD, CWORD, CWORD,
12085 CWORD, CWORD, CWORD, CWORD,
12086 CWORD, CWORD, CWORD, CWORD,
12087 CWORD, CWORD, CWORD, CWORD,
12088 CWORD, CWORD, CWORD, CWORD,
12089 CWORD, CWORD, CWORD, CWORD,
12090 CWORD, CWORD, CWORD, CWORD,
12091 CWORD, CWORD, CWORD, CWORD,
12092 CWORD, CWORD, CWORD, CWORD,
12093 CWORD, CWORD, CWORD, CWORD,
12094 CWORD, CWORD, CWORD, CWORD,
12095 CWORD, CWORD, CWORD, CWORD,
12096 CWORD, CWORD, CWORD, CWORD,
12097 CWORD, CWORD, CWORD, CWORD,
12098 CWORD, CWORD, CWORD, CWORD,
12099 CWORD, CWORD, CWORD, CWORD,
12100 CWORD, CWORD, CWORD, CWORD,
12101 CWORD, CWORD, CWORD, CWORD,
12102 CWORD, CWORD, CWORD, CWORD,
12103 CWORD, CWORD, CWORD, CWORD,
12104 CWORD, CWORD, CWORD, CWORD,
12105 CWORD, CWORD, CWORD, CSPCL,
12106 CNL, CWORD, CWORD, CWORD,
12107 CWORD, CWORD, CWORD, CWORD,
12108 CWORD, CWORD, CWORD, CWORD,
12109 CWORD, CWORD, CWORD, CWORD,
12110 CWORD, CWORD, CWORD, CWORD,
12111 CWORD, CWORD, CSPCL, CWORD,
12112 CDQUOTE, CWORD, CVAR, CWORD,
12113 CSPCL, CSQUOTE, CSPCL, CSPCL,
12114 CWORD, CWORD, CWORD, CWORD,
12115 CWORD, CWORD, CWORD, CWORD,
12116 CWORD, CWORD, CWORD, CWORD,
12117 CWORD, CWORD, CWORD, CWORD,
12118 CWORD, CSPCL, CSPCL, CWORD,
12119 CSPCL, CWORD, CWORD, CWORD,
12120 CWORD, CWORD, CWORD, CWORD,
12121 CWORD, CWORD, CWORD, CWORD,
12122 CWORD, CWORD, CWORD, CWORD,
12123 CWORD, CWORD, CWORD, CWORD,
12124 CWORD, CWORD, CWORD, CWORD,
12125 CWORD, CWORD, CWORD, CWORD,
12126 CWORD, CWORD, CBACK, CWORD,
12127 CWORD, CWORD, CBQUOTE, CWORD,
12128 CWORD, CWORD, CWORD, CWORD,
12129 CWORD, CWORD, CWORD, CWORD,
12130 CWORD, CWORD, CWORD, CWORD,
12131 CWORD, CWORD, CWORD, CWORD,
12132 CWORD, CWORD, CWORD, CWORD,
12133 CWORD, CWORD, CWORD, CWORD,
12134 CWORD, CWORD, CSPCL, CENDVAR,
12135 CWORD
12136};
12137
12138/* syntax table used when in double quotes */
12139static const char dqsyntax[257] = {
12140 CEOF, CIGN, CWORD, CCTL,
12141 CCTL, CCTL, CCTL, CCTL,
12142 CCTL, CCTL, CCTL, CWORD,
12143 CWORD, CWORD, CWORD, CWORD,
12144 CWORD, CWORD, CWORD, CWORD,
12145 CWORD, CWORD, CWORD, CWORD,
12146 CWORD, CWORD, CWORD, CWORD,
12147 CWORD, CWORD, CWORD, CWORD,
12148 CWORD, CWORD, CWORD, CWORD,
12149 CWORD, CWORD, CWORD, CWORD,
12150 CWORD, CWORD, CWORD, CWORD,
12151 CWORD, CWORD, CWORD, CWORD,
12152 CWORD, CWORD, CWORD, CWORD,
12153 CWORD, CWORD, CWORD, CWORD,
12154 CWORD, CWORD, CWORD, CWORD,
12155 CWORD, CWORD, CWORD, CWORD,
12156 CWORD, CWORD, CWORD, CWORD,
12157 CWORD, CWORD, CWORD, CWORD,
12158 CWORD, CWORD, CWORD, CWORD,
12159 CWORD, CWORD, CWORD, CWORD,
12160 CWORD, CWORD, CWORD, CWORD,
12161 CWORD, CWORD, CWORD, CWORD,
12162 CWORD, CWORD, CWORD, CWORD,
12163 CWORD, CWORD, CWORD, CWORD,
12164 CWORD, CWORD, CWORD, CWORD,
12165 CWORD, CWORD, CWORD, CWORD,
12166 CWORD, CWORD, CWORD, CWORD,
12167 CWORD, CWORD, CWORD, CWORD,
12168 CWORD, CWORD, CWORD, CWORD,
12169 CWORD, CWORD, CWORD, CWORD,
12170 CWORD, CWORD, CWORD, CWORD,
12171 CWORD, CWORD, CWORD, CWORD,
12172 CWORD, CWORD, CWORD, CWORD,
12173 CWORD, CWORD, CWORD, CWORD,
12174 CWORD, CWORD, CWORD, CWORD,
12175 CNL, CWORD, CWORD, CWORD,
12176 CWORD, CWORD, CWORD, CWORD,
12177 CWORD, CWORD, CWORD, CWORD,
12178 CWORD, CWORD, CWORD, CWORD,
12179 CWORD, CWORD, CWORD, CWORD,
12180 CWORD, CWORD, CWORD, CCTL,
12181 CENDQUOTE,CWORD, CVAR, CWORD,
12182 CWORD, CWORD, CWORD, CWORD,
12183 CCTL, CWORD, CWORD, CCTL,
12184 CWORD, CCTL, CWORD, CWORD,
12185 CWORD, CWORD, CWORD, CWORD,
12186 CWORD, CWORD, CWORD, CWORD,
12187 CCTL, CWORD, CWORD, CCTL,
12188 CWORD, CCTL, CWORD, CWORD,
12189 CWORD, CWORD, CWORD, CWORD,
12190 CWORD, CWORD, CWORD, CWORD,
12191 CWORD, CWORD, CWORD, CWORD,
12192 CWORD, CWORD, CWORD, CWORD,
12193 CWORD, CWORD, CWORD, CWORD,
12194 CWORD, CWORD, CWORD, CWORD,
12195 CWORD, CCTL, CBACK, CCTL,
12196 CWORD, CWORD, CBQUOTE, CWORD,
12197 CWORD, CWORD, CWORD, CWORD,
12198 CWORD, CWORD, CWORD, CWORD,
12199 CWORD, CWORD, CWORD, CWORD,
12200 CWORD, CWORD, CWORD, CWORD,
12201 CWORD, CWORD, CWORD, CWORD,
12202 CWORD, CWORD, CWORD, CWORD,
12203 CWORD, CWORD, CWORD, CENDVAR,
12204 CCTL
12205};
12206
12207/* syntax table used when in single quotes */
12208static const char sqsyntax[257] = {
12209 CEOF, CIGN, CWORD, CCTL,
12210 CCTL, CCTL, CCTL, CCTL,
12211 CCTL, CCTL, CCTL, CWORD,
12212 CWORD, CWORD, CWORD, CWORD,
12213 CWORD, CWORD, CWORD, CWORD,
12214 CWORD, CWORD, CWORD, CWORD,
12215 CWORD, CWORD, CWORD, CWORD,
12216 CWORD, CWORD, CWORD, CWORD,
12217 CWORD, CWORD, CWORD, CWORD,
12218 CWORD, CWORD, CWORD, CWORD,
12219 CWORD, CWORD, CWORD, CWORD,
12220 CWORD, CWORD, CWORD, CWORD,
12221 CWORD, CWORD, CWORD, CWORD,
12222 CWORD, CWORD, CWORD, CWORD,
12223 CWORD, CWORD, CWORD, CWORD,
12224 CWORD, CWORD, CWORD, CWORD,
12225 CWORD, CWORD, CWORD, CWORD,
12226 CWORD, CWORD, CWORD, CWORD,
12227 CWORD, CWORD, CWORD, CWORD,
12228 CWORD, CWORD, CWORD, CWORD,
12229 CWORD, CWORD, CWORD, CWORD,
12230 CWORD, CWORD, CWORD, CWORD,
12231 CWORD, CWORD, CWORD, CWORD,
12232 CWORD, CWORD, CWORD, CWORD,
12233 CWORD, CWORD, CWORD, CWORD,
12234 CWORD, CWORD, CWORD, CWORD,
12235 CWORD, CWORD, CWORD, CWORD,
12236 CWORD, CWORD, CWORD, CWORD,
12237 CWORD, CWORD, CWORD, CWORD,
12238 CWORD, CWORD, CWORD, CWORD,
12239 CWORD, CWORD, CWORD, CWORD,
12240 CWORD, CWORD, CWORD, CWORD,
12241 CWORD, CWORD, CWORD, CWORD,
12242 CWORD, CWORD, CWORD, CWORD,
12243 CWORD, CWORD, CWORD, CWORD,
12244 CNL, CWORD, CWORD, CWORD,
12245 CWORD, CWORD, CWORD, CWORD,
12246 CWORD, CWORD, CWORD, CWORD,
12247 CWORD, CWORD, CWORD, CWORD,
12248 CWORD, CWORD, CWORD, CWORD,
12249 CWORD, CWORD, CWORD, CCTL,
12250 CWORD, CWORD, CWORD, CWORD,
12251 CWORD, CENDQUOTE,CWORD, CWORD,
12252 CCTL, CWORD, CWORD, CCTL,
12253 CWORD, CCTL, CWORD, CWORD,
12254 CWORD, CWORD, CWORD, CWORD,
12255 CWORD, CWORD, CWORD, CWORD,
12256 CCTL, CWORD, CWORD, CCTL,
12257 CWORD, CCTL, CWORD, CWORD,
12258 CWORD, CWORD, CWORD, CWORD,
12259 CWORD, CWORD, CWORD, CWORD,
12260 CWORD, CWORD, CWORD, CWORD,
12261 CWORD, CWORD, CWORD, CWORD,
12262 CWORD, CWORD, CWORD, CWORD,
12263 CWORD, CWORD, CWORD, CWORD,
12264 CWORD, CCTL, CCTL, CCTL,
12265 CWORD, CWORD, CWORD, CWORD,
12266 CWORD, CWORD, CWORD, CWORD,
12267 CWORD, CWORD, CWORD, CWORD,
12268 CWORD, CWORD, CWORD, CWORD,
12269 CWORD, CWORD, CWORD, CWORD,
12270 CWORD, CWORD, CWORD, CWORD,
12271 CWORD, CWORD, CWORD, CWORD,
12272 CWORD, CWORD, CWORD, CWORD,
12273 CCTL
12274};
12275
12276/* syntax table used when in arithmetic */
12277static const char arisyntax[257] = {
12278 CEOF, CIGN, CWORD, CCTL,
12279 CCTL, CCTL, CCTL, CCTL,
12280 CCTL, CCTL, CCTL, CWORD,
12281 CWORD, CWORD, CWORD, CWORD,
12282 CWORD, CWORD, CWORD, CWORD,
12283 CWORD, CWORD, CWORD, CWORD,
12284 CWORD, CWORD, CWORD, CWORD,
12285 CWORD, CWORD, CWORD, CWORD,
12286 CWORD, CWORD, CWORD, CWORD,
12287 CWORD, CWORD, CWORD, CWORD,
12288 CWORD, CWORD, CWORD, CWORD,
12289 CWORD, CWORD, CWORD, CWORD,
12290 CWORD, CWORD, CWORD, CWORD,
12291 CWORD, CWORD, CWORD, CWORD,
12292 CWORD, CWORD, CWORD, CWORD,
12293 CWORD, CWORD, CWORD, CWORD,
12294 CWORD, CWORD, CWORD, CWORD,
12295 CWORD, CWORD, CWORD, CWORD,
12296 CWORD, CWORD, CWORD, CWORD,
12297 CWORD, CWORD, CWORD, CWORD,
12298 CWORD, CWORD, CWORD, CWORD,
12299 CWORD, CWORD, CWORD, CWORD,
12300 CWORD, CWORD, CWORD, CWORD,
12301 CWORD, CWORD, CWORD, CWORD,
12302 CWORD, CWORD, CWORD, CWORD,
12303 CWORD, CWORD, CWORD, CWORD,
12304 CWORD, CWORD, CWORD, CWORD,
12305 CWORD, CWORD, CWORD, CWORD,
12306 CWORD, CWORD, CWORD, CWORD,
12307 CWORD, CWORD, CWORD, CWORD,
12308 CWORD, CWORD, CWORD, CWORD,
12309 CWORD, CWORD, CWORD, CWORD,
12310 CWORD, CWORD, CWORD, CWORD,
12311 CWORD, CWORD, CWORD, CWORD,
12312 CWORD, CWORD, CWORD, CWORD,
12313 CNL, CWORD, CWORD, CWORD,
12314 CWORD, CWORD, CWORD, CWORD,
12315 CWORD, CWORD, CWORD, CWORD,
12316 CWORD, CWORD, CWORD, CWORD,
12317 CWORD, CWORD, CWORD, CWORD,
12318 CWORD, CWORD, CWORD, CWORD,
12319 CDQUOTE, CWORD, CVAR, CWORD,
12320 CWORD, CSQUOTE, CLP, CRP,
12321 CWORD, CWORD, CWORD, CWORD,
12322 CWORD, CWORD, CWORD, CWORD,
12323 CWORD, CWORD, CWORD, CWORD,
12324 CWORD, CWORD, CWORD, CWORD,
12325 CWORD, CWORD, CWORD, CWORD,
12326 CWORD, CWORD, CWORD, CWORD,
12327 CWORD, CWORD, CWORD, CWORD,
12328 CWORD, CWORD, CWORD, CWORD,
12329 CWORD, CWORD, CWORD, CWORD,
12330 CWORD, CWORD, CWORD, CWORD,
12331 CWORD, CWORD, CWORD, CWORD,
12332 CWORD, CWORD, CWORD, CWORD,
12333 CWORD, CWORD, CBACK, CWORD,
12334 CWORD, CWORD, CBQUOTE, CWORD,
12335 CWORD, CWORD, CWORD, CWORD,
12336 CWORD, CWORD, CWORD, CWORD,
12337 CWORD, CWORD, CWORD, CWORD,
12338 CWORD, CWORD, CWORD, CWORD,
12339 CWORD, CWORD, CWORD, CWORD,
12340 CWORD, CWORD, CWORD, CWORD,
12341 CWORD, CWORD, CWORD, CENDVAR,
12342 CWORD
12343};
12344
12345/* character classification table */
12346static const char is_type[257] = {
12347 0, 0, 0, 0,
12348 0, 0, 0, 0,
12349 0, 0, 0, 0,
12350 0, 0, 0, 0,
12351 0, 0, 0, 0,
12352 0, 0, 0, 0,
12353 0, 0, 0, 0,
12354 0, 0, 0, 0,
12355 0, 0, 0, 0,
12356 0, 0, 0, 0,
12357 0, 0, 0, 0,
12358 0, 0, 0, 0,
12359 0, 0, 0, 0,
12360 0, 0, 0, 0,
12361 0, 0, 0, 0,
12362 0, 0, 0, 0,
12363 0, 0, 0, 0,
12364 0, 0, 0, 0,
12365 0, 0, 0, 0,
12366 0, 0, 0, 0,
12367 0, 0, 0, 0,
12368 0, 0, 0, 0,
12369 0, 0, 0, 0,
12370 0, 0, 0, 0,
12371 0, 0, 0, 0,
12372 0, 0, 0, 0,
12373 0, 0, 0, 0,
12374 0, 0, 0, 0,
12375 0, 0, 0, 0,
12376 0, 0, 0, 0,
12377 0, 0, 0, 0,
12378 0, 0, 0, 0,
12379 0, 0, 0, 0,
12380 0, 0, 0, 0,
12381 0, 0, 0, 0,
12382 0, 0, 0, 0,
12383 0, 0, 0, 0,
12384 0, 0, 0, 0,
12385 0, 0, 0, 0,
12386 0, 0, 0, 0,
12387 0, 0, 0, ISSPECL,
12388 0, ISSPECL, ISSPECL, 0,
12389 0, 0, 0, 0,
12390 ISSPECL, 0, 0, ISSPECL,
12391 0, 0, ISDIGIT, ISDIGIT,
12392 ISDIGIT, ISDIGIT, ISDIGIT, ISDIGIT,
12393 ISDIGIT, ISDIGIT, ISDIGIT, ISDIGIT,
12394 0, 0, 0, 0,
12395 0, ISSPECL, ISSPECL, ISUPPER,
12396 ISUPPER, ISUPPER, ISUPPER, ISUPPER,
12397 ISUPPER, ISUPPER, ISUPPER, ISUPPER,
12398 ISUPPER, ISUPPER, ISUPPER, ISUPPER,
12399 ISUPPER, ISUPPER, ISUPPER, ISUPPER,
12400 ISUPPER, ISUPPER, ISUPPER, ISUPPER,
12401 ISUPPER, ISUPPER, ISUPPER, ISUPPER,
12402 ISUPPER, 0, 0, 0,
12403 0, ISUNDER, 0, ISLOWER,
12404 ISLOWER, ISLOWER, ISLOWER, ISLOWER,
12405 ISLOWER, ISLOWER, ISLOWER, ISLOWER,
12406 ISLOWER, ISLOWER, ISLOWER, ISLOWER,
12407 ISLOWER, ISLOWER, ISLOWER, ISLOWER,
12408 ISLOWER, ISLOWER, ISLOWER, ISLOWER,
12409 ISLOWER, ISLOWER, ISLOWER, ISLOWER,
12410 ISLOWER, 0, 0, 0,
12411 0
12412};
12413/* $NetBSD: trap.c,v 1.25 2001/02/04 19:52:07 christos Exp $ */
12414
12415/*
12416 * The trap builtin. 12690 * The trap builtin.
12417 */ 12691 */
12418 12692
@@ -12467,25 +12741,6 @@ trapcmd(argc, argv)
12467 12741
12468 12742
12469 12743
12470/*
12471 * Clear traps on a fork.
12472 */
12473
12474static void
12475clear_traps() {
12476 char **tp;
12477
12478 for (tp = trap ; tp < &trap[NSIG] ; tp++) {
12479 if (*tp && **tp) { /* trap not NULL or SIG_IGN */
12480 INTOFF;
12481 ckfree(*tp);
12482 *tp = NULL;
12483 if (tp != &trap[0])
12484 setsignal(tp - trap);
12485 INTON;
12486 }
12487 }
12488}
12489 12744
12490 12745
12491 12746
@@ -12495,8 +12750,7 @@ clear_traps() {
12495 */ 12750 */
12496 12751
12497static void 12752static void
12498setsignal(signo) 12753setsignal(int signo)
12499 int signo;
12500{ 12754{
12501 int action; 12755 int action;
12502 char *t; 12756 char *t;
@@ -12517,7 +12771,6 @@ setsignal(signo)
12517 case SIGQUIT: 12771 case SIGQUIT:
12518#ifdef DEBUG 12772#ifdef DEBUG
12519 { 12773 {
12520 extern int debug;
12521 12774
12522 if (debug) 12775 if (debug)
12523 break; 12776 break;
@@ -12528,7 +12781,7 @@ setsignal(signo)
12528 if (iflag) 12781 if (iflag)
12529 action = S_IGN; 12782 action = S_IGN;
12530 break; 12783 break;
12531#if JOBS 12784#ifdef JOBS
12532 case SIGTSTP: 12785 case SIGTSTP:
12533 case SIGTTOU: 12786 case SIGTTOU:
12534 if (mflag) 12787 if (mflag)
@@ -12554,11 +12807,11 @@ setsignal(signo)
12554 if (act.sa_handler == SIG_IGN) { 12807 if (act.sa_handler == SIG_IGN) {
12555 if (mflag && (signo == SIGTSTP || 12808 if (mflag && (signo == SIGTSTP ||
12556 signo == SIGTTIN || signo == SIGTTOU)) { 12809 signo == SIGTTIN || signo == SIGTTOU)) {
12557 *t = S_IGN; /* don't hard ignore these */ 12810 *t = S_IGN; /* don't hard ignore these */
12558 } else 12811 } else
12559 *t = S_HARD_IGN; 12812 *t = S_HARD_IGN;
12560 } else { 12813 } else {
12561 *t = S_RESET; /* force to be set */ 12814 *t = S_RESET; /* force to be set */
12562 } 12815 }
12563 } 12816 }
12564 if (*t == S_HARD_IGN || *t == action) 12817 if (*t == S_HARD_IGN || *t == action)
@@ -12594,30 +12847,12 @@ ignoresig(signo)
12594} 12847}
12595 12848
12596 12849
12597#ifdef mkinit
12598INCLUDE <signal.h>
12599INCLUDE "trap.h"
12600
12601SHELLPROC {
12602 char *sm;
12603
12604 clear_traps();
12605 for (sm = sigmode ; sm < sigmode + NSIG - 1; sm++) {
12606 if (*sm == S_IGN)
12607 *sm = S_HARD_IGN;
12608 }
12609}
12610#endif
12611
12612
12613
12614/* 12850/*
12615 * Signal handler. 12851 * Signal handler.
12616 */ 12852 */
12617 12853
12618static void 12854static void
12619onsig(signo) 12855onsig(int signo)
12620 int signo;
12621{ 12856{
12622 if (signo == SIGINT && trap[SIGINT] == NULL) { 12857 if (signo == SIGINT && trap[SIGINT] == NULL) {
12623 onint(); 12858 onint();
@@ -12628,14 +12863,14 @@ onsig(signo)
12628} 12863}
12629 12864
12630 12865
12631
12632/* 12866/*
12633 * Called to execute a trap. Perhaps we should avoid entering new trap 12867 * Called to execute a trap. Perhaps we should avoid entering new trap
12634 * handlers while we are executing a trap handler. 12868 * handlers while we are executing a trap handler.
12635 */ 12869 */
12636 12870
12637static void 12871static void
12638dotrap() { 12872dotrap(void)
12873{
12639 int i; 12874 int i;
12640 int savestatus; 12875 int savestatus;
12641 12876
@@ -12655,37 +12890,12 @@ done:
12655 pendingsigs = 0; 12890 pendingsigs = 0;
12656} 12891}
12657 12892
12658
12659
12660/*
12661 * Controls whether the shell is interactive or not.
12662 */
12663
12664
12665static void
12666setinteractive(on)
12667 int on;
12668{
12669 static int is_interactive;
12670
12671 if (on == is_interactive)
12672 return;
12673 setsignal(SIGINT);
12674 setsignal(SIGQUIT);
12675 setsignal(SIGTERM);
12676 chkmail(1);
12677 is_interactive = on;
12678}
12679
12680
12681
12682/* 12893/*
12683 * Called to exit the shell. 12894 * Called to exit the shell.
12684 */ 12895 */
12685 12896
12686static void 12897static void
12687exitshell(status) 12898exitshell(int status)
12688 int status;
12689{ 12899{
12690 struct jmploc loc1, loc2; 12900 struct jmploc loc1, loc2;
12691 char *p; 12901 char *p;
@@ -12702,9 +12912,9 @@ exitshell(status)
12702 trap[0] = NULL; 12912 trap[0] = NULL;
12703 evalstring(p, 0); 12913 evalstring(p, 0);
12704 } 12914 }
12705l1: handler = &loc2; /* probably unnecessary */ 12915l1: handler = &loc2; /* probably unnecessary */
12706 flushall(); 12916 flushall();
12707#if JOBS 12917#ifdef JOBS
12708 setjobctl(0); 12918 setjobctl(0);
12709#endif 12919#endif
12710l2: _exit(status); 12920l2: _exit(status);
@@ -12715,8 +12925,7 @@ static int decode_signal(const char *string, int minsig)
12715{ 12925{
12716 int signo; 12926 int signo;
12717 12927
12718 if (is_number(string)) { 12928 if (is_number(string, &signo)) {
12719 signo = atoi(string);
12720 if (signo >= NSIG) { 12929 if (signo >= NSIG) {
12721 return -1; 12930 return -1;
12722 } 12931 }
@@ -12739,100 +12948,14 @@ zero:
12739 12948
12740 return -1; 12949 return -1;
12741} 12950}
12742/* $NetBSD: var.c,v 1.27 2001/02/04 19:52:07 christos Exp $ */ 12951static struct var **hashvar (const char *);
12743 12952static void showvars (const char *, int, int);
12744#define VTABSIZE 39 12953static struct var **findvar (struct var **, const char *);
12745
12746
12747struct varinit {
12748 struct var *var;
12749 int flags;
12750 const char *text;
12751 void (*func) __P((const char *));
12752};
12753
12754struct localvar *localvars;
12755
12756#if ATTY
12757struct var vatty;
12758#endif
12759struct var vifs;
12760struct var vmail;
12761struct var vmpath;
12762struct var vpath;
12763struct var vps1;
12764struct var vps2;
12765struct var vvers;
12766struct var voptind;
12767
12768static const char defpathvar[] =
12769 "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin";
12770#ifdef IFS_BROKEN
12771static const char defifsvar[] = "IFS= \t\n";
12772#else
12773static const char defifs[] = " \t\n";
12774#endif
12775
12776static const struct varinit varinit[] = {
12777#if ATTY
12778 { &vatty, VSTRFIXED|VTEXTFIXED|VUNSET, "ATTY=",
12779 NULL },
12780#endif
12781#ifdef IFS_BROKEN
12782 { &vifs, VSTRFIXED|VTEXTFIXED, defifsvar,
12783#else
12784 { &vifs, VSTRFIXED|VTEXTFIXED|VUNSET, "IFS=",
12785#endif
12786 NULL },
12787 { &vmail, VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL=",
12788 NULL },
12789 { &vmpath, VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH=",
12790 NULL },
12791 { &vpath, VSTRFIXED|VTEXTFIXED, defpathvar,
12792 changepath },
12793 /*
12794 * vps1 depends on uid
12795 */
12796 { &vps2, VSTRFIXED|VTEXTFIXED, "PS2=> ",
12797 NULL },
12798 { &voptind, VSTRFIXED|VTEXTFIXED, "OPTIND=1",
12799 getoptsreset },
12800 { NULL, 0, NULL,
12801 NULL }
12802};
12803
12804struct var *vartab[VTABSIZE];
12805
12806static struct var **hashvar __P((const char *));
12807static void showvars __P((const char *, int, int));
12808static struct var **findvar __P((struct var **, const char *));
12809 12954
12810/* 12955/*
12811 * Initialize the varable symbol tables and import the environment 12956 * Initialize the varable symbol tables and import the environment
12812 */ 12957 */
12813 12958
12814#ifdef mkinit
12815INCLUDE <unistd.h>
12816INCLUDE "output.h"
12817INCLUDE "var.h"
12818static char **environ;
12819INIT {
12820 char **envp;
12821 char ppid[32];
12822
12823 initvar();
12824 for (envp = environ ; *envp ; envp++) {
12825 if (strchr(*envp, '=')) {
12826 setvareq(*envp, VEXPORT|VTEXTFIXED);
12827 }
12828 }
12829
12830 fmtstr(ppid, sizeof(ppid), "%d", (int) getppid());
12831 setvar("PPID", ppid, 0);
12832}
12833#endif
12834
12835
12836/* 12959/*
12837 * This routine initializes the builtin variables. It is called when the 12960 * This routine initializes the builtin variables. It is called when the
12838 * shell is initialized and again when a shell procedure is spawned. 12961 * shell is initialized and again when a shell procedure is spawned.
@@ -12899,7 +13022,7 @@ setvar(name, val, flags)
12899 namelen = p - name; 13022 namelen = p - name;
12900 if (isbad) 13023 if (isbad)
12901 error("%.*s: bad variable name", namelen, name); 13024 error("%.*s: bad variable name", namelen, name);
12902 len = namelen + 2; /* 2 is space for '=' and '\0' */ 13025 len = namelen + 2; /* 2 is space for '=' and '\0' */
12903 if (val == NULL) { 13026 if (val == NULL) {
12904 flags |= VUNSET; 13027 flags |= VUNSET;
12905 } else { 13028 } else {
@@ -13065,16 +13188,8 @@ environment() {
13065 * VSTACK set since these are currently allocated on the stack. 13188 * VSTACK set since these are currently allocated on the stack.
13066 */ 13189 */
13067 13190
13068#ifdef mkinit
13069static void shprocvar __P((void));
13070
13071SHELLPROC {
13072 shprocvar();
13073}
13074#endif
13075
13076static void 13191static void
13077shprocvar() { 13192shprocvar(void) {
13078 struct var **vpp; 13193 struct var **vpp;
13079 struct var *vp, **prev; 13194 struct var *vp, **prev;
13080 13195
@@ -13158,6 +13273,8 @@ found:;
13158 * The "local" command. 13273 * The "local" command.
13159 */ 13274 */
13160 13275
13276/* funcnest nonzero if we are currently evaluating a function */
13277
13161static int 13278static int
13162localcmd(argc, argv) 13279localcmd(argc, argv)
13163 int argc; 13280 int argc;
@@ -13165,7 +13282,7 @@ localcmd(argc, argv)
13165{ 13282{
13166 char *name; 13283 char *name;
13167 13284
13168 if (! in_function()) 13285 if (! funcnest)
13169 error("Not in a function"); 13286 error("Not in a function");
13170 while ((name = *argptr++) != NULL) { 13287 while ((name = *argptr++) != NULL) {
13171 mklocal(name); 13288 mklocal(name);
@@ -13193,8 +13310,8 @@ mklocal(name)
13193 lvp = ckmalloc(sizeof (struct localvar)); 13310 lvp = ckmalloc(sizeof (struct localvar));
13194 if (name[0] == '-' && name[1] == '\0') { 13311 if (name[0] == '-' && name[1] == '\0') {
13195 char *p; 13312 char *p;
13196 p = ckmalloc(sizeof optlist); 13313 p = ckmalloc(sizeof optet_vals);
13197 lvp->text = memcpy(p, optlist, sizeof optlist); 13314 lvp->text = memcpy(p, optet_vals, sizeof optet_vals);
13198 vp = NULL; 13315 vp = NULL;
13199 } else { 13316 } else {
13200 vpp = hashvar(name); 13317 vpp = hashvar(name);
@@ -13204,7 +13321,7 @@ mklocal(name)
13204 setvareq(savestr(name), VSTRFIXED); 13321 setvareq(savestr(name), VSTRFIXED);
13205 else 13322 else
13206 setvar(name, NULL, VSTRFIXED); 13323 setvar(name, NULL, VSTRFIXED);
13207 vp = *vpp; /* the new variable */ 13324 vp = *vpp; /* the new variable */
13208 lvp->text = NULL; 13325 lvp->text = NULL;
13209 lvp->flags = VUNSET; 13326 lvp->flags = VUNSET;
13210 } else { 13327 } else {
@@ -13234,8 +13351,8 @@ poplocalvars() {
13234 while ((lvp = localvars) != NULL) { 13351 while ((lvp = localvars) != NULL) {
13235 localvars = lvp->next; 13352 localvars = lvp->next;
13236 vp = lvp->vp; 13353 vp = lvp->vp;
13237 if (vp == NULL) { /* $- saved */ 13354 if (vp == NULL) { /* $- saved */
13238 memcpy(optlist, lvp->text, sizeof optlist); 13355 memcpy(optet_vals, lvp->text, sizeof optet_vals);
13239 ckfree(lvp->text); 13356 ckfree(lvp->text);
13240 } else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) { 13357 } else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
13241 (void)unsetvar(vp->text); 13358 (void)unsetvar(vp->text);
@@ -13415,7 +13532,7 @@ findvar(struct var **vpp, const char *name)
13415/* 13532/*
13416 * Copyright (c) 1999 Herbert Xu <herbert@debian.org> 13533 * Copyright (c) 1999 Herbert Xu <herbert@debian.org>
13417 * This file contains code for the times builtin. 13534 * This file contains code for the times builtin.
13418 * $Id: ash.c,v 1.3 2001/06/28 16:43:57 andersen Exp $ 13535 * $Id: ash.c,v 1.4 2001/07/02 17:27:21 andersen Exp $
13419 */ 13536 */
13420static int timescmd (int argc, char **argv) 13537static int timescmd (int argc, char **argv)
13421{ 13538{
@@ -13438,7 +13555,7 @@ static int timescmd (int argc, char **argv)
13438 13555
13439/*- 13556/*-
13440 * Copyright (c) 1989, 1991, 1993, 1994 13557 * Copyright (c) 1989, 1991, 1993, 1994
13441 * The Regents of the University of California. All rights reserved. 13558 * The Regents of the University of California. All rights reserved.
13442 * 13559 *
13443 * This code is derived from software contributed to Berkeley by 13560 * This code is derived from software contributed to Berkeley by
13444 * Kenneth Almquist. 13561 * Kenneth Almquist.
@@ -13452,8 +13569,8 @@ static int timescmd (int argc, char **argv)
13452 * notice, this list of conditions and the following disclaimer in the 13569 * notice, this list of conditions and the following disclaimer in the
13453 * documentation and/or other materials provided with the distribution. 13570 * documentation and/or other materials provided with the distribution.
13454 * 13571 *
13455 * 3. <BSD Advertising Clause omitted per the July 22, 1999 licensing change 13572 * 3. <BSD Advertising Clause omitted per the July 22, 1999 licensing change
13456 * ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change> 13573 * ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change>
13457 * 13574 *
13458 * 4. Neither the name of the University nor the names of its contributors 13575 * 4. Neither the name of the University nor the names of its contributors
13459 * may be used to endorse or promote products derived from this software 13576 * may be used to endorse or promote products derived from this software