deffe28c56351de755abe67777e6460e81bef3f9
[oweals/busybox.git] / shell / ash.c
1 /* vi: set sw=4 ts=4: */
2 /*
3  * ash shell port for busybox
4  *
5  * Copyright (c) 1989, 1991, 1993, 1994
6  *      The Regents of the University of California.  All rights reserved.
7  *
8  * Copyright (c) 1997-2003 Herbert Xu <herbert@debian.org>
9  * was re-ported from NetBSD and debianized.
10  *
11  *
12  * This code is derived from software contributed to Berkeley by
13  * Kenneth Almquist.
14  *
15  * This program is free software; you can redistribute it and/or modify
16  * it under the terms of the GNU General Public License as published by
17  * the Free Software Foundation; either version 2 of the License, or
18  * (at your option) any later version.
19  *
20  * This program is distributed in the hope that it will be useful,
21  * but WITHOUT ANY WARRANTY; without even the implied warranty of
22  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23  * General Public License for more details.
24  *
25  * You should have received a copy of the GNU General Public License
26  * along with this program; if not, write to the Free Software
27  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
28  *
29  * Original BSD copyright notice is retained at the end of this file.
30  */
31
32 /*
33  * rewrite arith.y to micro stack based cryptic algorithm by
34  * Copyright (c) 2001 Aaron Lehmann <aaronl@vitelus.com>
35  *
36  * Modified by Vladimir Oleynik <dzo@simtreas.ru> (c) 2001-2003 to be
37  * used in busybox and size optimizations,
38  * support locale, rewrited arith (see notes to this)
39  *
40  */
41
42
43 /*
44  * The follow should be set to reflect the type of system you have:
45  *      JOBS -> 1 if you have Berkeley job control, 0 otherwise.
46  *      define SYSV if you are running under System V.
47  *      define DEBUG=1 to compile in debugging ('set -o debug' to turn on)
48  *      define DEBUG=2 to compile in and turn on debugging.
49  *
50  * When debugging is on, debugging info will be written to ./trace and
51  * a quit signal will generate a core dump.
52  */
53
54
55
56 #define IFS_BROKEN
57
58 #define PROFILE 0
59
60 #ifdef DEBUG
61 #define _GNU_SOURCE
62 #endif
63
64 #include <sys/types.h>
65 #include <sys/cdefs.h>
66 #include <sys/ioctl.h>
67 #include <sys/param.h>
68 #include <sys/resource.h>
69 #include <sys/stat.h>
70 #include <sys/time.h>
71 #include <sys/wait.h>
72
73 #include <stdio.h>
74 #include <stdlib.h>
75 #include <string.h>
76 #include <unistd.h>
77
78 #include <stdarg.h>
79 #include <stddef.h>
80 #include <assert.h>
81 #include <ctype.h>
82 #include <dirent.h>
83 #include <errno.h>
84 #include <fcntl.h>
85 #include <limits.h>
86 #include <paths.h>
87 #include <setjmp.h>
88 #include <signal.h>
89 #include <stdint.h>
90 #include <sysexits.h>
91
92 #include <fnmatch.h>
93
94
95 #include "busybox.h"
96 #include "pwd_.h"
97
98 #ifdef CONFIG_ASH_JOB_CONTROL
99 #define JOBS 1
100 #else
101 #undef JOBS
102 #endif
103
104 #if JOBS
105 #include <termios.h>
106 #endif
107
108 #include "cmdedit.h"
109
110 #ifdef __GLIBC__
111 /* glibc sucks */
112 static int *dash_errno;
113 #undef errno
114 #define errno (*dash_errno)
115 #endif
116
117 #if defined(__uClinux__)
118 #error "Do not even bother, ash will not run on uClinux"
119 #endif
120
121 #ifdef DEBUG
122 #define _DIAGASSERT(assert_expr) assert(assert_expr)
123 #else
124 #define _DIAGASSERT(assert_expr)
125 #endif
126
127
128 #ifdef CONFIG_ASH_ALIAS
129 /*      $NetBSD: alias.h,v 1.5 2002/11/24 22:35:38 christos Exp $       */
130
131 #define ALIASINUSE      1
132 #define ALIASDEAD       2
133
134 struct alias {
135         struct alias *next;
136         char *name;
137         char *val;
138         int flag;
139 };
140
141 static struct alias *lookupalias(const char *, int);
142 static int aliascmd(int, char **);
143 static int unaliascmd(int, char **);
144 static void rmaliases(void);
145 static int unalias(const char *);
146 static void printalias(const struct alias *);
147 #endif
148
149 /*      $NetBSD: cd.h,v 1.3 2002/11/24 22:35:39 christos Exp $  */
150
151
152 static void    setpwd(const char *, int);
153
154 /*      $NetBSD: error.h,v 1.15 2002/11/24 22:35:39 christos Exp $      */
155
156
157 /*
158  * Types of operations (passed to the errmsg routine).
159  */
160
161
162 static const char not_found_msg[] = "%s: not found";
163
164
165 #define E_OPEN  "No such file"          /* opening a file */
166 #define E_CREAT "Directory nonexistent" /* creating a file */
167 #define E_EXEC  not_found_msg+4         /* executing a program */
168
169 /*
170  * We enclose jmp_buf in a structure so that we can declare pointers to
171  * jump locations.  The global variable handler contains the location to
172  * jump to when an exception occurs, and the global variable exception
173  * contains a code identifying the exeception.  To implement nested
174  * exception handlers, the user should save the value of handler on entry
175  * to an inner scope, set handler to point to a jmploc structure for the
176  * inner scope, and restore handler on exit from the scope.
177  */
178
179 struct jmploc {
180         jmp_buf loc;
181 };
182
183 static struct jmploc *handler;
184 static int exception;
185 static volatile int suppressint;
186 static volatile sig_atomic_t intpending;
187
188 static int exerrno;            /* Last exec error, error for EXEXEC */
189
190 /* exceptions */
191 #define EXINT 0         /* SIGINT received */
192 #define EXERROR 1       /* a generic error */
193 #define EXSHELLPROC 2   /* execute a shell procedure */
194 #define EXEXEC 3        /* command execution failed */
195 #define EXEXIT 4        /* exit the shell */
196 #define EXSIG 5         /* trapped signal in wait(1) */
197
198
199 /* do we generate EXSIG events */
200 static int exsig;
201 /* last pending signal */
202 static volatile sig_atomic_t pendingsigs;
203
204 /*
205  * These macros allow the user to suspend the handling of interrupt signals
206  * over a period of time.  This is similar to SIGHOLD to or sigblock, but
207  * much more efficient and portable.  (But hacking the kernel is so much
208  * more fun than worrying about efficiency and portability. :-))
209  */
210
211 #define barrier() ({ __asm__ __volatile__ ("": : :"memory"); })
212 #define INTOFF \
213         ({ \
214                 suppressint++; \
215                 barrier(); \
216                 0; \
217         })
218 #define SAVEINT(v) ((v) = suppressint)
219 #define RESTOREINT(v) \
220         ({ \
221                 barrier(); \
222                 if ((suppressint = (v)) == 0 && intpending) onint(); \
223                 0; \
224         })
225 #define EXSIGON() \
226         ({ \
227                 exsig++; \
228                 barrier(); \
229                 if (pendingsigs) \
230                         exraise(EXSIG); \
231                 0; \
232         })
233 /* EXSIG is turned off by evalbltin(). */
234
235
236 static void exraise(int) __attribute__((__noreturn__));
237 static void onint(void) __attribute__((__noreturn__));
238
239 static void error(const char *, ...) __attribute__((__noreturn__));
240 static void exerror(int, const char *, ...) __attribute__((__noreturn__));
241
242 static void sh_warnx(const char *, ...);
243
244 #ifdef CONFIG_ASH_OPTIMIZE_FOR_SIZE
245 static void
246 inton(void) {
247         if (--suppressint == 0 && intpending) {
248                 onint();
249         }
250 }
251 #define INTON inton()
252 static void forceinton(void)
253 {
254         suppressint = 0;
255         if (intpending)
256                 onint();
257 }
258 #define FORCEINTON forceinton()
259 #else
260 #define INTON \
261         ({ \
262                 barrier(); \
263                 if (--suppressint == 0 && intpending) onint(); \
264                 0; \
265         })
266 #define FORCEINTON \
267         ({ \
268                 barrier(); \
269                 suppressint = 0; \
270                 if (intpending) onint(); \
271                 0; \
272         })
273 #endif /* CONFIG_ASH_OPTIMIZE_FOR_SIZE */
274
275 /*
276  * BSD setjmp saves the signal mask, which violates ANSI C and takes time,
277  * so we use _setjmp instead.
278  */
279
280 #if defined(BSD) && !defined(__SVR4) && !defined(__GLIBC__)
281 #define setjmp(jmploc)  _setjmp(jmploc)
282 #define longjmp(jmploc, val)    _longjmp(jmploc, val)
283 #endif
284
285 /*      $NetBSD: expand.h,v 1.13 2002/11/24 22:35:40 christos Exp $     */
286
287 struct strlist {
288         struct strlist *next;
289         char *text;
290 };
291
292
293 struct arglist {
294         struct strlist *list;
295         struct strlist **lastp;
296 };
297
298 /*
299  * expandarg() flags
300  */
301 #define EXP_FULL        0x1     /* perform word splitting & file globbing */
302 #define EXP_TILDE       0x2     /* do normal tilde expansion */
303 #define EXP_VARTILDE    0x4     /* expand tildes in an assignment */
304 #define EXP_REDIR       0x8     /* file glob for a redirection (1 match only) */
305 #define EXP_CASE        0x10    /* keeps quotes around for CASE pattern */
306 #define EXP_RECORD      0x20    /* need to record arguments for ifs breakup */
307 #define EXP_VARTILDE2   0x40    /* expand tildes after colons only */
308 #define EXP_WORD        0x80    /* expand word in parameter expansion */
309 #define EXP_QWORD       0x100   /* expand word in quoted parameter expansion */
310
311
312 union node;
313 static void expandarg(union node *, struct arglist *, int);
314 #define rmescapes(p) _rmescapes((p), 0)
315 static char *_rmescapes(char *, int);
316 static int casematch(union node *, char *);
317
318 #ifdef CONFIG_ASH_MATH_SUPPORT
319 static void expari(int);
320 #endif
321
322 /*      $NetBSD: eval.h,v 1.13 2002/11/24 22:35:39 christos Exp $       */
323
324 static char *commandname;              /* currently executing command */
325 static struct strlist *cmdenviron;     /* environment for builtin command */
326 static int exitstatus;                 /* exit status of last command */
327 static int back_exitstatus;            /* exit status of backquoted command */
328
329
330 struct backcmd {                /* result of evalbackcmd */
331         int fd;                 /* file descriptor to read from */
332         char *buf;              /* buffer */
333         int nleft;              /* number of chars in buffer */
334         struct job *jp;         /* job structure for command */
335 };
336
337 /*
338  * This file was generated by the mknodes program.
339  */
340
341 #define NCMD 0
342 #define NPIPE 1
343 #define NREDIR 2
344 #define NBACKGND 3
345 #define NSUBSHELL 4
346 #define NAND 5
347 #define NOR 6
348 #define NSEMI 7
349 #define NIF 8
350 #define NWHILE 9
351 #define NUNTIL 10
352 #define NFOR 11
353 #define NCASE 12
354 #define NCLIST 13
355 #define NDEFUN 14
356 #define NARG 15
357 #define NTO 16
358 #define NCLOBBER 17
359 #define NFROM 18
360 #define NFROMTO 19
361 #define NAPPEND 20
362 #define NTOFD 21
363 #define NFROMFD 22
364 #define NHERE 23
365 #define NXHERE 24
366 #define NNOT 25
367
368
369
370 struct ncmd {
371       int type;
372       union node *assign;
373       union node *args;
374       union node *redirect;
375 };
376
377
378 struct npipe {
379       int type;
380       int backgnd;
381       struct nodelist *cmdlist;
382 };
383
384
385 struct nredir {
386       int type;
387       union node *n;
388       union node *redirect;
389 };
390
391
392 struct nbinary {
393       int type;
394       union node *ch1;
395       union node *ch2;
396 };
397
398
399 struct nif {
400       int type;
401       union node *test;
402       union node *ifpart;
403       union node *elsepart;
404 };
405
406
407 struct nfor {
408       int type;
409       union node *args;
410       union node *body;
411       char *var;
412 };
413
414
415 struct ncase {
416       int type;
417       union node *expr;
418       union node *cases;
419 };
420
421
422 struct nclist {
423       int type;
424       union node *next;
425       union node *pattern;
426       union node *body;
427 };
428
429
430 struct narg {
431       int type;
432       union node *next;
433       char *text;
434       struct nodelist *backquote;
435 };
436
437
438 struct nfile {
439       int type;
440       union node *next;
441       int fd;
442       union node *fname;
443       char *expfname;
444 };
445
446
447 struct ndup {
448       int type;
449       union node *next;
450       int fd;
451       int dupfd;
452       union node *vname;
453 };
454
455
456 struct nhere {
457       int type;
458       union node *next;
459       int fd;
460       union node *doc;
461 };
462
463
464 struct nnot {
465       int type;
466       union node *com;
467 };
468
469
470 union node {
471       int type;
472       struct ncmd ncmd;
473       struct npipe npipe;
474       struct nredir nredir;
475       struct nbinary nbinary;
476       struct nif nif;
477       struct nfor nfor;
478       struct ncase ncase;
479       struct nclist nclist;
480       struct narg narg;
481       struct nfile nfile;
482       struct ndup ndup;
483       struct nhere nhere;
484       struct nnot nnot;
485 };
486
487
488 struct nodelist {
489         struct nodelist *next;
490         union node *n;
491 };
492
493
494 struct funcnode {
495         int count;
496         union node n;
497 };
498
499
500 static void freefunc(struct funcnode *);
501 /*      $NetBSD: parser.h,v 1.15 2002/11/24 22:35:42 christos Exp $     */
502
503 /* control characters in argument strings */
504 #define CTL_FIRST '\201'        /* first 'special' character */
505 #define CTLESC '\201'           /* escape next character */
506 #define CTLVAR '\202'           /* variable defn */
507 #define CTLENDVAR '\203'
508 #define CTLBACKQ '\204'
509 #define CTLQUOTE 01             /* ored with CTLBACKQ code if in quotes */
510 /*      CTLBACKQ | CTLQUOTE == '\205' */
511 #define CTLARI  '\206'          /* arithmetic expression */
512 #define CTLENDARI '\207'
513 #define CTLQUOTEMARK '\210'
514 #define CTL_LAST '\210'         /* last 'special' character */
515
516 /* variable substitution byte (follows CTLVAR) */
517 #define VSTYPE  0x0f            /* type of variable substitution */
518 #define VSNUL   0x10            /* colon--treat the empty string as unset */
519 #define VSQUOTE 0x80            /* inside double quotes--suppress splitting */
520
521 /* values of VSTYPE field */
522 #define VSNORMAL        0x1             /* normal variable:  $var or ${var} */
523 #define VSMINUS         0x2             /* ${var-text} */
524 #define VSPLUS          0x3             /* ${var+text} */
525 #define VSQUESTION      0x4             /* ${var?message} */
526 #define VSASSIGN        0x5             /* ${var=text} */
527 #define VSTRIMRIGHT     0x6             /* ${var%pattern} */
528 #define VSTRIMRIGHTMAX  0x7             /* ${var%%pattern} */
529 #define VSTRIMLEFT      0x8             /* ${var#pattern} */
530 #define VSTRIMLEFTMAX   0x9             /* ${var##pattern} */
531 #define VSLENGTH        0xa             /* ${#var} */
532
533 /* values of checkkwd variable */
534 #define CHKALIAS        0x1
535 #define CHKKWD          0x2
536 #define CHKNL           0x4
537
538 #define IBUFSIZ (BUFSIZ + 1)
539
540 /*
541  * NEOF is returned by parsecmd when it encounters an end of file.  It
542  * must be distinct from NULL, so we use the address of a variable that
543  * happens to be handy.
544  */
545 static int plinno = 1;                  /* input line number */
546
547 /* number of characters left in input buffer */
548 static int parsenleft;                  /* copy of parsefile->nleft */
549 static int parselleft;                  /* copy of parsefile->lleft */
550
551 /* next character in input buffer */
552 static char *parsenextc;                /* copy of parsefile->nextc */
553
554 struct strpush {
555         struct strpush *prev;   /* preceding string on stack */
556         char *prevstring;
557         int prevnleft;
558 #ifdef CONFIG_ASH_ALIAS
559         struct alias *ap;       /* if push was associated with an alias */
560 #endif
561         char *string;           /* remember the string since it may change */
562 };
563
564 struct parsefile {
565         struct parsefile *prev; /* preceding file on stack */
566         int linno;              /* current line */
567         int fd;                 /* file descriptor (or -1 if string) */
568         int nleft;              /* number of chars left in this line */
569         int lleft;              /* number of chars left in this buffer */
570         char *nextc;            /* next char in buffer */
571         char *buf;              /* input buffer */
572         struct strpush *strpush; /* for pushing strings at this level */
573         struct strpush basestrpush; /* so pushing one is fast */
574 };
575
576 static struct parsefile basepf;         /* top level input file */
577 static char basebuf[IBUFSIZ];           /* buffer for top level input file */
578 static struct parsefile *parsefile = &basepf;  /* current input file */
579
580
581 static int tokpushback;                 /* last token pushed back */
582 #define NEOF ((union node *)&tokpushback)
583 static int parsebackquote;             /* nonzero if we are inside backquotes */
584 static int doprompt;                   /* if set, prompt the user */
585 static int needprompt;                 /* true if interactive and at start of line */
586 static int lasttoken;                  /* last token read */
587 static char *wordtext;                 /* text of last word returned by readtoken */
588 static int checkkwd;
589 static struct nodelist *backquotelist;
590 static union node *redirnode;
591 static struct heredoc *heredoc;
592 static int quoteflag;                  /* set if (part of) last token was quoted */
593 static int startlinno;                 /* line # where last token started */
594
595 static union node *parsecmd(int);
596 static void fixredir(union node *, const char *, int);
597 static const char *const *findkwd(const char *);
598 static char *endofname(const char *);
599
600 /*      $NetBSD: shell.h,v 1.16 2003/01/22 20:36:04 dsl Exp $   */
601
602 typedef void *pointer;
603
604 static char nullstr[1];                /* zero length string */
605 static const char spcstr[] = " ";
606 static const char snlfmt[] = "%s\n";
607 static const char dolatstr[] = { CTLVAR, VSNORMAL|VSQUOTE, '@', '=', '\0' };
608 static const char illnum[] = "Illegal number: %s";
609 static const char homestr[] = "HOME";
610
611 #ifdef DEBUG
612 #define TRACE(param)    trace param
613 #define TRACEV(param)   tracev param
614 #else
615 #define TRACE(param)
616 #define TRACEV(param)
617 #endif
618
619 #if !defined(__GNUC__) || (__GNUC__ == 2 && __GNUC_MINOR__ < 96)
620 #define __builtin_expect(x, expected_value) (x)
621 #endif
622
623 #define likely(x)       __builtin_expect((x),1)
624
625
626 #define TEOF 0
627 #define TNL 1
628 #define TREDIR 2
629 #define TWORD 3
630 #define TSEMI 4
631 #define TBACKGND 5
632 #define TAND 6
633 #define TOR 7
634 #define TPIPE 8
635 #define TLP 9
636 #define TRP 10
637 #define TENDCASE 11
638 #define TENDBQUOTE 12
639 #define TNOT 13
640 #define TCASE 14
641 #define TDO 15
642 #define TDONE 16
643 #define TELIF 17
644 #define TELSE 18
645 #define TESAC 19
646 #define TFI 20
647 #define TFOR 21
648 #define TIF 22
649 #define TIN 23
650 #define TTHEN 24
651 #define TUNTIL 25
652 #define TWHILE 26
653 #define TBEGIN 27
654 #define TEND 28
655
656 /* first char is indicating which tokens mark the end of a list */
657 static const char *const tokname_array[] = {
658         "\1end of file",
659         "\0newline",
660         "\0redirection",
661         "\0word",
662         "\0;",
663         "\0&",
664         "\0&&",
665         "\0||",
666         "\0|",
667         "\0(",
668         "\1)",
669         "\1;;",
670         "\1`",
671 #define KWDOFFSET 13
672         /* the following are keywords */
673         "\0!",
674         "\0case",
675         "\1do",
676         "\1done",
677         "\1elif",
678         "\1else",
679         "\1esac",
680         "\1fi",
681         "\0for",
682         "\0if",
683         "\0in",
684         "\1then",
685         "\0until",
686         "\0while",
687         "\0{",
688         "\1}",
689 };
690
691 static const char *tokname(int tok)
692 {
693         static char buf[16];
694
695         if (tok >= TSEMI)
696                 buf[0] = '"';
697         sprintf(buf + (tok >= TSEMI), "%s%c",
698                         tokname_array[tok] + 1, (tok >= TSEMI ? '"' : 0));
699         return buf;
700 }
701
702 /*      $NetBSD: machdep.h,v 1.10 2002/10/07 14:26:08 christos Exp $    */
703
704 /*
705  * Most machines require the value returned from malloc to be aligned
706  * in some way.  The following macro will get this right on many machines.
707  */
708
709 #define SHELL_SIZE (sizeof(union {int i; char *cp; double d; }) - 1)
710 /*
711  * It appears that grabstackstr() will barf with such alignments
712  * because stalloc() will return a string allocated in a new stackblock.
713  */
714 #define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE)
715
716 /*
717  * This file was generated by the mksyntax program.
718  */
719
720
721 /* Syntax classes */
722 #define CWORD 0                 /* character is nothing special */
723 #define CNL 1                   /* newline character */
724 #define CBACK 2                 /* a backslash character */
725 #define CSQUOTE 3               /* single quote */
726 #define CDQUOTE 4               /* double quote */
727 #define CENDQUOTE 5             /* a terminating quote */
728 #define CBQUOTE 6               /* backwards single quote */
729 #define CVAR 7                  /* a dollar sign */
730 #define CENDVAR 8               /* a '}' character */
731 #define CLP 9                   /* a left paren in arithmetic */
732 #define CRP 10                  /* a right paren in arithmetic */
733 #define CENDFILE 11             /* end of file */
734 #define CCTL 12                 /* like CWORD, except it must be escaped */
735 #define CSPCL 13                /* these terminate a word */
736 #define CIGN 14                 /* character should be ignored */
737
738 #ifdef CONFIG_ASH_ALIAS
739 #define SYNBASE 130
740 #define PEOF -130
741 #define PEOA -129
742 #define PEOA_OR_PEOF PEOA
743 #else
744 #define SYNBASE 129
745 #define PEOF -129
746 #define PEOA_OR_PEOF PEOF
747 #endif
748
749 #define is_digit(c)     ((unsigned)((c) - '0') <= 9)
750 #define is_name(c)      ((c) == '_' || isalpha((unsigned char)(c)))
751 #define is_in_name(c)   ((c) == '_' || isalnum((unsigned char)(c)))
752
753 /*
754  * is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
755  * (assuming ascii char codes, as the original implementation did)
756  */
757 #define is_special(c) \
758     ( (((unsigned int)c) - 33 < 32) \
759                          && ((0xc1ff920dUL >> (((unsigned int)c) - 33)) & 1))
760
761 #define digit_val(c)    ((c) - '0')
762
763 /*
764  * This file was generated by the mksyntax program.
765  */
766
767 #ifdef CONFIG_ASH_OPTIMIZE_FOR_SIZE
768 #define USE_SIT_FUNCTION
769 #endif
770
771 /* number syntax index */
772 #define  BASESYNTAX  0  /* not in quotes */
773 #define  DQSYNTAX    1  /* in double quotes */
774 #define  SQSYNTAX    2  /* in single quotes */
775 #define  ARISYNTAX   3  /* in arithmetic */
776
777 #ifdef CONFIG_ASH_MATH_SUPPORT
778 static const char S_I_T[][4] = {
779 #ifdef CONFIG_ASH_ALIAS
780         {CSPCL, CIGN, CIGN, CIGN},              /* 0, PEOA */
781 #endif
782         {CSPCL, CWORD, CWORD, CWORD},           /* 1, ' ' */
783         {CNL, CNL, CNL, CNL},                   /* 2, \n */
784         {CWORD, CCTL, CCTL, CWORD},             /* 3, !*-/:=?[]~ */
785         {CDQUOTE, CENDQUOTE, CWORD, CWORD},     /* 4, '"' */
786         {CVAR, CVAR, CWORD, CVAR},              /* 5, $ */
787         {CSQUOTE, CWORD, CENDQUOTE, CWORD},     /* 6, "'" */
788         {CSPCL, CWORD, CWORD, CLP},             /* 7, ( */
789         {CSPCL, CWORD, CWORD, CRP},             /* 8, ) */
790         {CBACK, CBACK, CCTL, CBACK},            /* 9, \ */
791         {CBQUOTE, CBQUOTE, CWORD, CBQUOTE},     /* 10, ` */
792         {CENDVAR, CENDVAR, CWORD, CENDVAR},     /* 11, } */
793 #ifndef USE_SIT_FUNCTION
794         {CENDFILE, CENDFILE, CENDFILE, CENDFILE},       /* 12, PEOF */
795         {CWORD, CWORD, CWORD, CWORD},           /* 13, 0-9A-Za-z */
796         {CCTL, CCTL, CCTL, CCTL}                /* 14, CTLESC ... */
797 #endif
798 };
799 #else
800 static const char S_I_T[][3] = {
801 #ifdef CONFIG_ASH_ALIAS
802         {CSPCL, CIGN, CIGN},                    /* 0, PEOA */
803 #endif
804         {CSPCL, CWORD, CWORD},                  /* 1, ' ' */
805         {CNL, CNL, CNL},                        /* 2, \n */
806         {CWORD, CCTL, CCTL},                    /* 3, !*-/:=?[]~ */
807         {CDQUOTE, CENDQUOTE, CWORD},            /* 4, '"' */
808         {CVAR, CVAR, CWORD},                    /* 5, $ */
809         {CSQUOTE, CWORD, CENDQUOTE},            /* 6, "'" */
810         {CSPCL, CWORD, CWORD},                  /* 7, ( */
811         {CSPCL, CWORD, CWORD},                  /* 8, ) */
812         {CBACK, CBACK, CCTL},                   /* 9, \ */
813         {CBQUOTE, CBQUOTE, CWORD},              /* 10, ` */
814         {CENDVAR, CENDVAR, CWORD},              /* 11, } */
815 #ifndef USE_SIT_FUNCTION
816         {CENDFILE, CENDFILE, CENDFILE},         /* 12, PEOF */
817         {CWORD, CWORD, CWORD},                  /* 13, 0-9A-Za-z */
818         {CCTL, CCTL, CCTL}                      /* 14, CTLESC ... */
819 #endif
820 };
821 #endif /* CONFIG_ASH_MATH_SUPPORT */
822
823 #ifdef USE_SIT_FUNCTION
824
825 #define U_C(c) ((unsigned char)(c))
826
827 static int SIT(int c, int syntax)
828 {
829         static const char spec_symbls[] = "\t\n !\"$&'()*-/:;<=>?[\\]`|}~";
830 #ifdef CONFIG_ASH_ALIAS
831         static const char syntax_index_table[] = {
832                 1, 2, 1, 3, 4, 5, 1, 6,         /* "\t\n !\"$&'" */
833                 7, 8, 3, 3, 3, 3, 1, 1,         /* "()*-/:;<" */
834                 3, 1, 3, 3, 9, 3, 10, 1,        /* "=>?[\\]`|" */
835                 11, 3                           /* "}~" */
836         };
837 #else
838         static const char syntax_index_table[] = {
839                 0, 1, 0, 2, 3, 4, 0, 5,         /* "\t\n !\"$&'" */
840                 6, 7, 2, 2, 2, 2, 0, 0,         /* "()*-/:;<" */
841                 2, 0, 2, 2, 8, 2, 9, 0,         /* "=>?[\\]`|" */
842                 10, 2                           /* "}~" */
843         };
844 #endif
845         const char *s;
846         int indx;
847
848         if (c == PEOF)          /* 2^8+2 */
849                 return CENDFILE;
850 #ifdef CONFIG_ASH_ALIAS
851         if (c == PEOA)          /* 2^8+1 */
852                 indx = 0;
853         else
854 #endif
855                 if (U_C(c) >= U_C(CTLESC) && U_C(c) <= U_C(CTLQUOTEMARK))
856                         return CCTL;
857         else {
858                 s = strchr(spec_symbls, c);
859                 if (s == 0 || *s == 0)
860                         return CWORD;
861                 indx = syntax_index_table[(s - spec_symbls)];
862         }
863         return S_I_T[indx][syntax];
864 }
865
866 #else                                                   /* USE_SIT_FUNCTION */
867
868 #define SIT(c, syntax) S_I_T[(int)syntax_index_table[((int)c)+SYNBASE]][syntax]
869
870 #ifdef CONFIG_ASH_ALIAS
871 #define CSPCL_CIGN_CIGN_CIGN                           0
872 #define CSPCL_CWORD_CWORD_CWORD                        1
873 #define CNL_CNL_CNL_CNL                                2
874 #define CWORD_CCTL_CCTL_CWORD                          3
875 #define CDQUOTE_CENDQUOTE_CWORD_CWORD                  4
876 #define CVAR_CVAR_CWORD_CVAR                           5
877 #define CSQUOTE_CWORD_CENDQUOTE_CWORD                  6
878 #define CSPCL_CWORD_CWORD_CLP                          7
879 #define CSPCL_CWORD_CWORD_CRP                          8
880 #define CBACK_CBACK_CCTL_CBACK                         9
881 #define CBQUOTE_CBQUOTE_CWORD_CBQUOTE                 10
882 #define CENDVAR_CENDVAR_CWORD_CENDVAR                 11
883 #define CENDFILE_CENDFILE_CENDFILE_CENDFILE           12
884 #define CWORD_CWORD_CWORD_CWORD                       13
885 #define CCTL_CCTL_CCTL_CCTL                           14
886 #else
887 #define CSPCL_CWORD_CWORD_CWORD                        0
888 #define CNL_CNL_CNL_CNL                                1
889 #define CWORD_CCTL_CCTL_CWORD                          2
890 #define CDQUOTE_CENDQUOTE_CWORD_CWORD                  3
891 #define CVAR_CVAR_CWORD_CVAR                           4
892 #define CSQUOTE_CWORD_CENDQUOTE_CWORD                  5
893 #define CSPCL_CWORD_CWORD_CLP                          6
894 #define CSPCL_CWORD_CWORD_CRP                          7
895 #define CBACK_CBACK_CCTL_CBACK                         8
896 #define CBQUOTE_CBQUOTE_CWORD_CBQUOTE                  9
897 #define CENDVAR_CENDVAR_CWORD_CENDVAR                 10
898 #define CENDFILE_CENDFILE_CENDFILE_CENDFILE           11
899 #define CWORD_CWORD_CWORD_CWORD                       12
900 #define CCTL_CCTL_CCTL_CCTL                           13
901 #endif
902
903 static const char syntax_index_table[258] = {
904         /* BASESYNTAX_DQSYNTAX_SQSYNTAX_ARISYNTAX */
905         /*   0  PEOF */      CENDFILE_CENDFILE_CENDFILE_CENDFILE,
906 #ifdef CONFIG_ASH_ALIAS
907         /*   1  PEOA */      CSPCL_CIGN_CIGN_CIGN,
908 #endif
909         /*   2  -128 0x80 */ CWORD_CWORD_CWORD_CWORD,
910         /*   3  -127 CTLESC       */ CCTL_CCTL_CCTL_CCTL,
911         /*   4  -126 CTLVAR       */ CCTL_CCTL_CCTL_CCTL,
912         /*   5  -125 CTLENDVAR    */ CCTL_CCTL_CCTL_CCTL,
913         /*   6  -124 CTLBACKQ     */ CCTL_CCTL_CCTL_CCTL,
914         /*   7  -123 CTLQUOTE     */ CCTL_CCTL_CCTL_CCTL,
915         /*   8  -122 CTLARI       */ CCTL_CCTL_CCTL_CCTL,
916         /*   9  -121 CTLENDARI    */ CCTL_CCTL_CCTL_CCTL,
917         /*  10  -120 CTLQUOTEMARK */ CCTL_CCTL_CCTL_CCTL,
918         /*  11  -119      */ CWORD_CWORD_CWORD_CWORD,
919         /*  12  -118      */ CWORD_CWORD_CWORD_CWORD,
920         /*  13  -117      */ CWORD_CWORD_CWORD_CWORD,
921         /*  14  -116      */ CWORD_CWORD_CWORD_CWORD,
922         /*  15  -115      */ CWORD_CWORD_CWORD_CWORD,
923         /*  16  -114      */ CWORD_CWORD_CWORD_CWORD,
924         /*  17  -113      */ CWORD_CWORD_CWORD_CWORD,
925         /*  18  -112      */ CWORD_CWORD_CWORD_CWORD,
926         /*  19  -111      */ CWORD_CWORD_CWORD_CWORD,
927         /*  20  -110      */ CWORD_CWORD_CWORD_CWORD,
928         /*  21  -109      */ CWORD_CWORD_CWORD_CWORD,
929         /*  22  -108      */ CWORD_CWORD_CWORD_CWORD,
930         /*  23  -107      */ CWORD_CWORD_CWORD_CWORD,
931         /*  24  -106      */ CWORD_CWORD_CWORD_CWORD,
932         /*  25  -105      */ CWORD_CWORD_CWORD_CWORD,
933         /*  26  -104      */ CWORD_CWORD_CWORD_CWORD,
934         /*  27  -103      */ CWORD_CWORD_CWORD_CWORD,
935         /*  28  -102      */ CWORD_CWORD_CWORD_CWORD,
936         /*  29  -101      */ CWORD_CWORD_CWORD_CWORD,
937         /*  30  -100      */ CWORD_CWORD_CWORD_CWORD,
938         /*  31   -99      */ CWORD_CWORD_CWORD_CWORD,
939         /*  32   -98      */ CWORD_CWORD_CWORD_CWORD,
940         /*  33   -97      */ CWORD_CWORD_CWORD_CWORD,
941         /*  34   -96      */ CWORD_CWORD_CWORD_CWORD,
942         /*  35   -95      */ CWORD_CWORD_CWORD_CWORD,
943         /*  36   -94      */ CWORD_CWORD_CWORD_CWORD,
944         /*  37   -93      */ CWORD_CWORD_CWORD_CWORD,
945         /*  38   -92      */ CWORD_CWORD_CWORD_CWORD,
946         /*  39   -91      */ CWORD_CWORD_CWORD_CWORD,
947         /*  40   -90      */ CWORD_CWORD_CWORD_CWORD,
948         /*  41   -89      */ CWORD_CWORD_CWORD_CWORD,
949         /*  42   -88      */ CWORD_CWORD_CWORD_CWORD,
950         /*  43   -87      */ CWORD_CWORD_CWORD_CWORD,
951         /*  44   -86      */ CWORD_CWORD_CWORD_CWORD,
952         /*  45   -85      */ CWORD_CWORD_CWORD_CWORD,
953         /*  46   -84      */ CWORD_CWORD_CWORD_CWORD,
954         /*  47   -83      */ CWORD_CWORD_CWORD_CWORD,
955         /*  48   -82      */ CWORD_CWORD_CWORD_CWORD,
956         /*  49   -81      */ CWORD_CWORD_CWORD_CWORD,
957         /*  50   -80      */ CWORD_CWORD_CWORD_CWORD,
958         /*  51   -79      */ CWORD_CWORD_CWORD_CWORD,
959         /*  52   -78      */ CWORD_CWORD_CWORD_CWORD,
960         /*  53   -77      */ CWORD_CWORD_CWORD_CWORD,
961         /*  54   -76      */ CWORD_CWORD_CWORD_CWORD,
962         /*  55   -75      */ CWORD_CWORD_CWORD_CWORD,
963         /*  56   -74      */ CWORD_CWORD_CWORD_CWORD,
964         /*  57   -73      */ CWORD_CWORD_CWORD_CWORD,
965         /*  58   -72      */ CWORD_CWORD_CWORD_CWORD,
966         /*  59   -71      */ CWORD_CWORD_CWORD_CWORD,
967         /*  60   -70      */ CWORD_CWORD_CWORD_CWORD,
968         /*  61   -69      */ CWORD_CWORD_CWORD_CWORD,
969         /*  62   -68      */ CWORD_CWORD_CWORD_CWORD,
970         /*  63   -67      */ CWORD_CWORD_CWORD_CWORD,
971         /*  64   -66      */ CWORD_CWORD_CWORD_CWORD,
972         /*  65   -65      */ CWORD_CWORD_CWORD_CWORD,
973         /*  66   -64      */ CWORD_CWORD_CWORD_CWORD,
974         /*  67   -63      */ CWORD_CWORD_CWORD_CWORD,
975         /*  68   -62      */ CWORD_CWORD_CWORD_CWORD,
976         /*  69   -61      */ CWORD_CWORD_CWORD_CWORD,
977         /*  70   -60      */ CWORD_CWORD_CWORD_CWORD,
978         /*  71   -59      */ CWORD_CWORD_CWORD_CWORD,
979         /*  72   -58      */ CWORD_CWORD_CWORD_CWORD,
980         /*  73   -57      */ CWORD_CWORD_CWORD_CWORD,
981         /*  74   -56      */ CWORD_CWORD_CWORD_CWORD,
982         /*  75   -55      */ CWORD_CWORD_CWORD_CWORD,
983         /*  76   -54      */ CWORD_CWORD_CWORD_CWORD,
984         /*  77   -53      */ CWORD_CWORD_CWORD_CWORD,
985         /*  78   -52      */ CWORD_CWORD_CWORD_CWORD,
986         /*  79   -51      */ CWORD_CWORD_CWORD_CWORD,
987         /*  80   -50      */ CWORD_CWORD_CWORD_CWORD,
988         /*  81   -49      */ CWORD_CWORD_CWORD_CWORD,
989         /*  82   -48      */ CWORD_CWORD_CWORD_CWORD,
990         /*  83   -47      */ CWORD_CWORD_CWORD_CWORD,
991         /*  84   -46      */ CWORD_CWORD_CWORD_CWORD,
992         /*  85   -45      */ CWORD_CWORD_CWORD_CWORD,
993         /*  86   -44      */ CWORD_CWORD_CWORD_CWORD,
994         /*  87   -43      */ CWORD_CWORD_CWORD_CWORD,
995         /*  88   -42      */ CWORD_CWORD_CWORD_CWORD,
996         /*  89   -41      */ CWORD_CWORD_CWORD_CWORD,
997         /*  90   -40      */ CWORD_CWORD_CWORD_CWORD,
998         /*  91   -39      */ CWORD_CWORD_CWORD_CWORD,
999         /*  92   -38      */ CWORD_CWORD_CWORD_CWORD,
1000         /*  93   -37      */ CWORD_CWORD_CWORD_CWORD,
1001         /*  94   -36      */ CWORD_CWORD_CWORD_CWORD,
1002         /*  95   -35      */ CWORD_CWORD_CWORD_CWORD,
1003         /*  96   -34      */ CWORD_CWORD_CWORD_CWORD,
1004         /*  97   -33      */ CWORD_CWORD_CWORD_CWORD,
1005         /*  98   -32      */ CWORD_CWORD_CWORD_CWORD,
1006         /*  99   -31      */ CWORD_CWORD_CWORD_CWORD,
1007         /* 100   -30      */ CWORD_CWORD_CWORD_CWORD,
1008         /* 101   -29      */ CWORD_CWORD_CWORD_CWORD,
1009         /* 102   -28      */ CWORD_CWORD_CWORD_CWORD,
1010         /* 103   -27      */ CWORD_CWORD_CWORD_CWORD,
1011         /* 104   -26      */ CWORD_CWORD_CWORD_CWORD,
1012         /* 105   -25      */ CWORD_CWORD_CWORD_CWORD,
1013         /* 106   -24      */ CWORD_CWORD_CWORD_CWORD,
1014         /* 107   -23      */ CWORD_CWORD_CWORD_CWORD,
1015         /* 108   -22      */ CWORD_CWORD_CWORD_CWORD,
1016         /* 109   -21      */ CWORD_CWORD_CWORD_CWORD,
1017         /* 110   -20      */ CWORD_CWORD_CWORD_CWORD,
1018         /* 111   -19      */ CWORD_CWORD_CWORD_CWORD,
1019         /* 112   -18      */ CWORD_CWORD_CWORD_CWORD,
1020         /* 113   -17      */ CWORD_CWORD_CWORD_CWORD,
1021         /* 114   -16      */ CWORD_CWORD_CWORD_CWORD,
1022         /* 115   -15      */ CWORD_CWORD_CWORD_CWORD,
1023         /* 116   -14      */ CWORD_CWORD_CWORD_CWORD,
1024         /* 117   -13      */ CWORD_CWORD_CWORD_CWORD,
1025         /* 118   -12      */ CWORD_CWORD_CWORD_CWORD,
1026         /* 119   -11      */ CWORD_CWORD_CWORD_CWORD,
1027         /* 120   -10      */ CWORD_CWORD_CWORD_CWORD,
1028         /* 121    -9      */ CWORD_CWORD_CWORD_CWORD,
1029         /* 122    -8      */ CWORD_CWORD_CWORD_CWORD,
1030         /* 123    -7      */ CWORD_CWORD_CWORD_CWORD,
1031         /* 124    -6      */ CWORD_CWORD_CWORD_CWORD,
1032         /* 125    -5      */ CWORD_CWORD_CWORD_CWORD,
1033         /* 126    -4      */ CWORD_CWORD_CWORD_CWORD,
1034         /* 127    -3      */ CWORD_CWORD_CWORD_CWORD,
1035         /* 128    -2      */ CWORD_CWORD_CWORD_CWORD,
1036         /* 129    -1      */ CWORD_CWORD_CWORD_CWORD,
1037         /* 130     0      */ CWORD_CWORD_CWORD_CWORD,
1038         /* 131     1      */ CWORD_CWORD_CWORD_CWORD,
1039         /* 132     2      */ CWORD_CWORD_CWORD_CWORD,
1040         /* 133     3      */ CWORD_CWORD_CWORD_CWORD,
1041         /* 134     4      */ CWORD_CWORD_CWORD_CWORD,
1042         /* 135     5      */ CWORD_CWORD_CWORD_CWORD,
1043         /* 136     6      */ CWORD_CWORD_CWORD_CWORD,
1044         /* 137     7      */ CWORD_CWORD_CWORD_CWORD,
1045         /* 138     8      */ CWORD_CWORD_CWORD_CWORD,
1046         /* 139     9 "\t" */ CSPCL_CWORD_CWORD_CWORD,
1047         /* 140    10 "\n" */ CNL_CNL_CNL_CNL,
1048         /* 141    11      */ CWORD_CWORD_CWORD_CWORD,
1049         /* 142    12      */ CWORD_CWORD_CWORD_CWORD,
1050         /* 143    13      */ CWORD_CWORD_CWORD_CWORD,
1051         /* 144    14      */ CWORD_CWORD_CWORD_CWORD,
1052         /* 145    15      */ CWORD_CWORD_CWORD_CWORD,
1053         /* 146    16      */ CWORD_CWORD_CWORD_CWORD,
1054         /* 147    17      */ CWORD_CWORD_CWORD_CWORD,
1055         /* 148    18      */ CWORD_CWORD_CWORD_CWORD,
1056         /* 149    19      */ CWORD_CWORD_CWORD_CWORD,
1057         /* 150    20      */ CWORD_CWORD_CWORD_CWORD,
1058         /* 151    21      */ CWORD_CWORD_CWORD_CWORD,
1059         /* 152    22      */ CWORD_CWORD_CWORD_CWORD,
1060         /* 153    23      */ CWORD_CWORD_CWORD_CWORD,
1061         /* 154    24      */ CWORD_CWORD_CWORD_CWORD,
1062         /* 155    25      */ CWORD_CWORD_CWORD_CWORD,
1063         /* 156    26      */ CWORD_CWORD_CWORD_CWORD,
1064         /* 157    27      */ CWORD_CWORD_CWORD_CWORD,
1065         /* 158    28      */ CWORD_CWORD_CWORD_CWORD,
1066         /* 159    29      */ CWORD_CWORD_CWORD_CWORD,
1067         /* 160    30      */ CWORD_CWORD_CWORD_CWORD,
1068         /* 161    31      */ CWORD_CWORD_CWORD_CWORD,
1069         /* 162    32  " " */ CSPCL_CWORD_CWORD_CWORD,
1070         /* 163    33  "!" */ CWORD_CCTL_CCTL_CWORD,
1071         /* 164    34  """ */ CDQUOTE_CENDQUOTE_CWORD_CWORD,
1072         /* 165    35  "#" */ CWORD_CWORD_CWORD_CWORD,
1073         /* 166    36  "$" */ CVAR_CVAR_CWORD_CVAR,
1074         /* 167    37  "%" */ CWORD_CWORD_CWORD_CWORD,
1075         /* 168    38  "&" */ CSPCL_CWORD_CWORD_CWORD,
1076         /* 169    39  "'" */ CSQUOTE_CWORD_CENDQUOTE_CWORD,
1077         /* 170    40  "(" */ CSPCL_CWORD_CWORD_CLP,
1078         /* 171    41  ")" */ CSPCL_CWORD_CWORD_CRP,
1079         /* 172    42  "*" */ CWORD_CCTL_CCTL_CWORD,
1080         /* 173    43  "+" */ CWORD_CWORD_CWORD_CWORD,
1081         /* 174    44  "," */ CWORD_CWORD_CWORD_CWORD,
1082         /* 175    45  "-" */ CWORD_CCTL_CCTL_CWORD,
1083         /* 176    46  "." */ CWORD_CWORD_CWORD_CWORD,
1084         /* 177    47  "/" */ CWORD_CCTL_CCTL_CWORD,
1085         /* 178    48  "0" */ CWORD_CWORD_CWORD_CWORD,
1086         /* 179    49  "1" */ CWORD_CWORD_CWORD_CWORD,
1087         /* 180    50  "2" */ CWORD_CWORD_CWORD_CWORD,
1088         /* 181    51  "3" */ CWORD_CWORD_CWORD_CWORD,
1089         /* 182    52  "4" */ CWORD_CWORD_CWORD_CWORD,
1090         /* 183    53  "5" */ CWORD_CWORD_CWORD_CWORD,
1091         /* 184    54  "6" */ CWORD_CWORD_CWORD_CWORD,
1092         /* 185    55  "7" */ CWORD_CWORD_CWORD_CWORD,
1093         /* 186    56  "8" */ CWORD_CWORD_CWORD_CWORD,
1094         /* 187    57  "9" */ CWORD_CWORD_CWORD_CWORD,
1095         /* 188    58  ":" */ CWORD_CCTL_CCTL_CWORD,
1096         /* 189    59  ";" */ CSPCL_CWORD_CWORD_CWORD,
1097         /* 190    60  "<" */ CSPCL_CWORD_CWORD_CWORD,
1098         /* 191    61  "=" */ CWORD_CCTL_CCTL_CWORD,
1099         /* 192    62  ">" */ CSPCL_CWORD_CWORD_CWORD,
1100         /* 193    63  "?" */ CWORD_CCTL_CCTL_CWORD,
1101         /* 194    64  "@" */ CWORD_CWORD_CWORD_CWORD,
1102         /* 195    65  "A" */ CWORD_CWORD_CWORD_CWORD,
1103         /* 196    66  "B" */ CWORD_CWORD_CWORD_CWORD,
1104         /* 197    67  "C" */ CWORD_CWORD_CWORD_CWORD,
1105         /* 198    68  "D" */ CWORD_CWORD_CWORD_CWORD,
1106         /* 199    69  "E" */ CWORD_CWORD_CWORD_CWORD,
1107         /* 200    70  "F" */ CWORD_CWORD_CWORD_CWORD,
1108         /* 201    71  "G" */ CWORD_CWORD_CWORD_CWORD,
1109         /* 202    72  "H" */ CWORD_CWORD_CWORD_CWORD,
1110         /* 203    73  "I" */ CWORD_CWORD_CWORD_CWORD,
1111         /* 204    74  "J" */ CWORD_CWORD_CWORD_CWORD,
1112         /* 205    75  "K" */ CWORD_CWORD_CWORD_CWORD,
1113         /* 206    76  "L" */ CWORD_CWORD_CWORD_CWORD,
1114         /* 207    77  "M" */ CWORD_CWORD_CWORD_CWORD,
1115         /* 208    78  "N" */ CWORD_CWORD_CWORD_CWORD,
1116         /* 209    79  "O" */ CWORD_CWORD_CWORD_CWORD,
1117         /* 210    80  "P" */ CWORD_CWORD_CWORD_CWORD,
1118         /* 211    81  "Q" */ CWORD_CWORD_CWORD_CWORD,
1119         /* 212    82  "R" */ CWORD_CWORD_CWORD_CWORD,
1120         /* 213    83  "S" */ CWORD_CWORD_CWORD_CWORD,
1121         /* 214    84  "T" */ CWORD_CWORD_CWORD_CWORD,
1122         /* 215    85  "U" */ CWORD_CWORD_CWORD_CWORD,
1123         /* 216    86  "V" */ CWORD_CWORD_CWORD_CWORD,
1124         /* 217    87  "W" */ CWORD_CWORD_CWORD_CWORD,
1125         /* 218    88  "X" */ CWORD_CWORD_CWORD_CWORD,
1126         /* 219    89  "Y" */ CWORD_CWORD_CWORD_CWORD,
1127         /* 220    90  "Z" */ CWORD_CWORD_CWORD_CWORD,
1128         /* 221    91  "[" */ CWORD_CCTL_CCTL_CWORD,
1129         /* 222    92  "\" */ CBACK_CBACK_CCTL_CBACK,
1130         /* 223    93  "]" */ CWORD_CCTL_CCTL_CWORD,
1131         /* 224    94  "^" */ CWORD_CWORD_CWORD_CWORD,
1132         /* 225    95  "_" */ CWORD_CWORD_CWORD_CWORD,
1133         /* 226    96  "`" */ CBQUOTE_CBQUOTE_CWORD_CBQUOTE,
1134         /* 227    97  "a" */ CWORD_CWORD_CWORD_CWORD,
1135         /* 228    98  "b" */ CWORD_CWORD_CWORD_CWORD,
1136         /* 229    99  "c" */ CWORD_CWORD_CWORD_CWORD,
1137         /* 230   100  "d" */ CWORD_CWORD_CWORD_CWORD,
1138         /* 231   101  "e" */ CWORD_CWORD_CWORD_CWORD,
1139         /* 232   102  "f" */ CWORD_CWORD_CWORD_CWORD,
1140         /* 233   103  "g" */ CWORD_CWORD_CWORD_CWORD,
1141         /* 234   104  "h" */ CWORD_CWORD_CWORD_CWORD,
1142         /* 235   105  "i" */ CWORD_CWORD_CWORD_CWORD,
1143         /* 236   106  "j" */ CWORD_CWORD_CWORD_CWORD,
1144         /* 237   107  "k" */ CWORD_CWORD_CWORD_CWORD,
1145         /* 238   108  "l" */ CWORD_CWORD_CWORD_CWORD,
1146         /* 239   109  "m" */ CWORD_CWORD_CWORD_CWORD,
1147         /* 240   110  "n" */ CWORD_CWORD_CWORD_CWORD,
1148         /* 241   111  "o" */ CWORD_CWORD_CWORD_CWORD,
1149         /* 242   112  "p" */ CWORD_CWORD_CWORD_CWORD,
1150         /* 243   113  "q" */ CWORD_CWORD_CWORD_CWORD,
1151         /* 244   114  "r" */ CWORD_CWORD_CWORD_CWORD,
1152         /* 245   115  "s" */ CWORD_CWORD_CWORD_CWORD,
1153         /* 246   116  "t" */ CWORD_CWORD_CWORD_CWORD,
1154         /* 247   117  "u" */ CWORD_CWORD_CWORD_CWORD,
1155         /* 248   118  "v" */ CWORD_CWORD_CWORD_CWORD,
1156         /* 249   119  "w" */ CWORD_CWORD_CWORD_CWORD,
1157         /* 250   120  "x" */ CWORD_CWORD_CWORD_CWORD,
1158         /* 251   121  "y" */ CWORD_CWORD_CWORD_CWORD,
1159         /* 252   122  "z" */ CWORD_CWORD_CWORD_CWORD,
1160         /* 253   123  "{" */ CWORD_CWORD_CWORD_CWORD,
1161         /* 254   124  "|" */ CSPCL_CWORD_CWORD_CWORD,
1162         /* 255   125  "}" */ CENDVAR_CENDVAR_CWORD_CENDVAR,
1163         /* 256   126  "~" */ CWORD_CCTL_CCTL_CWORD,
1164         /* 257   127      */ CWORD_CWORD_CWORD_CWORD,
1165 };
1166
1167 #endif                                                  /* USE_SIT_FUNCTION */
1168
1169 /*      $NetBSD: alias.c,v 1.11 2002/11/24 22:35:38 christos Exp $      */
1170
1171
1172 #define ATABSIZE 39
1173
1174 static int     funcblocksize;          /* size of structures in function */
1175 static int     funcstringsize;         /* size of strings in node */
1176 static pointer funcblock;              /* block to allocate function from */
1177 static char   *funcstring;             /* block to allocate strings from */
1178
1179 static const short nodesize[26] = {
1180       SHELL_ALIGN(sizeof (struct ncmd)),
1181       SHELL_ALIGN(sizeof (struct npipe)),
1182       SHELL_ALIGN(sizeof (struct nredir)),
1183       SHELL_ALIGN(sizeof (struct nredir)),
1184       SHELL_ALIGN(sizeof (struct nredir)),
1185       SHELL_ALIGN(sizeof (struct nbinary)),
1186       SHELL_ALIGN(sizeof (struct nbinary)),
1187       SHELL_ALIGN(sizeof (struct nbinary)),
1188       SHELL_ALIGN(sizeof (struct nif)),
1189       SHELL_ALIGN(sizeof (struct nbinary)),
1190       SHELL_ALIGN(sizeof (struct nbinary)),
1191       SHELL_ALIGN(sizeof (struct nfor)),
1192       SHELL_ALIGN(sizeof (struct ncase)),
1193       SHELL_ALIGN(sizeof (struct nclist)),
1194       SHELL_ALIGN(sizeof (struct narg)),
1195       SHELL_ALIGN(sizeof (struct narg)),
1196       SHELL_ALIGN(sizeof (struct nfile)),
1197       SHELL_ALIGN(sizeof (struct nfile)),
1198       SHELL_ALIGN(sizeof (struct nfile)),
1199       SHELL_ALIGN(sizeof (struct nfile)),
1200       SHELL_ALIGN(sizeof (struct nfile)),
1201       SHELL_ALIGN(sizeof (struct ndup)),
1202       SHELL_ALIGN(sizeof (struct ndup)),
1203       SHELL_ALIGN(sizeof (struct nhere)),
1204       SHELL_ALIGN(sizeof (struct nhere)),
1205       SHELL_ALIGN(sizeof (struct nnot)),
1206 };
1207
1208
1209 static void calcsize(union node *);
1210 static void sizenodelist(struct nodelist *);
1211 static union node *copynode(union node *);
1212 static struct nodelist *copynodelist(struct nodelist *);
1213 static char *nodesavestr(char *);
1214
1215
1216
1217 static void evalstring(char *, int);
1218 union node;     /* BLETCH for ansi C */
1219 static void evaltree(union node *, int);
1220 static void evalbackcmd(union node *, struct backcmd *);
1221
1222 /* in_function returns nonzero if we are currently evaluating a function */
1223 #define in_function()   funcnest
1224 static int evalskip;                   /* set if we are skipping commands */
1225 static int skipcount;           /* number of levels to skip */
1226 static int funcnest;                   /* depth of function calls */
1227
1228 /* reasons for skipping commands (see comment on breakcmd routine) */
1229 #define SKIPBREAK       1
1230 #define SKIPCONT        2
1231 #define SKIPFUNC        3
1232 #define SKIPFILE        4
1233
1234 /*
1235  * This file was generated by the mkbuiltins program.
1236  */
1237
1238 #ifdef JOBS
1239 static int bgcmd(int, char **);
1240 #endif
1241 static int breakcmd(int, char **);
1242 static int cdcmd(int, char **);
1243 #ifdef CONFIG_ASH_CMDCMD
1244 static int commandcmd(int, char **);
1245 #endif
1246 static int dotcmd(int, char **);
1247 static int evalcmd(int, char **);
1248 static int execcmd(int, char **);
1249 static int exitcmd(int, char **);
1250 static int exportcmd(int, char **);
1251 static int falsecmd(int, char **);
1252 #ifdef JOBS
1253 static int fgcmd(int, char **);
1254 #endif
1255 #ifdef CONFIG_ASH_GETOPTS
1256 static int getoptscmd(int, char **);
1257 #endif
1258 static int hashcmd(int, char **);
1259 #ifndef CONFIG_FEATURE_SH_EXTRA_QUIET
1260 static int helpcmd(int argc, char **argv);
1261 #endif
1262 #ifdef JOBS
1263 static int jobscmd(int, char **);
1264 #endif
1265 #ifdef CONFIG_ASH_MATH_SUPPORT
1266 static int letcmd(int, char **);
1267 #endif
1268 static int localcmd(int, char **);
1269 static int pwdcmd(int, char **);
1270 static int readcmd(int, char **);
1271 static int returncmd(int, char **);
1272 static int setcmd(int, char **);
1273 static int shiftcmd(int, char **);
1274 static int timescmd(int, char **);
1275 static int trapcmd(int, char **);
1276 static int truecmd(int, char **);
1277 static int typecmd(int, char **);
1278 static int umaskcmd(int, char **);
1279 static int unsetcmd(int, char **);
1280 static int waitcmd(int, char **);
1281 static int ulimitcmd(int, char **);
1282 #ifdef JOBS
1283 static int killcmd(int, char **);
1284 #endif
1285
1286 /*      $NetBSD: mail.h,v 1.9 2002/11/24 22:35:40 christos Exp $        */
1287
1288 #ifdef CONFIG_ASH_MAIL
1289 static void chkmail(void);
1290 static void changemail(const char *);
1291 #endif
1292
1293 /*      $NetBSD: exec.h,v 1.20 2003/01/22 20:36:04 dsl Exp $    */
1294
1295 /* values of cmdtype */
1296 #define CMDUNKNOWN      -1      /* no entry in table for command */
1297 #define CMDNORMAL       0       /* command is an executable program */
1298 #define CMDFUNCTION     1       /* command is a shell function */
1299 #define CMDBUILTIN      2       /* command is a shell builtin */
1300
1301 struct builtincmd {
1302         const char *name;
1303         int (*builtin)(int, char **);
1304         /* unsigned flags; */
1305 };
1306
1307 #ifdef CONFIG_ASH_CMDCMD
1308 # ifdef JOBS
1309 #  ifdef CONFIG_ASH_ALIAS
1310 #    define COMMANDCMD (builtincmd + 7)
1311 #    define EXECCMD (builtincmd + 10)
1312 #  else
1313 #    define COMMANDCMD (builtincmd + 6)
1314 #    define EXECCMD (builtincmd + 9)
1315 #  endif
1316 # else /* ! JOBS */
1317 #  ifdef CONFIG_ASH_ALIAS
1318 #    define COMMANDCMD (builtincmd + 6)
1319 #    define EXECCMD (builtincmd + 9)
1320 #  else
1321 #    define COMMANDCMD (builtincmd + 5)
1322 #    define EXECCMD (builtincmd + 8)
1323 #  endif
1324 # endif /* JOBS */
1325 #else   /* ! CONFIG_ASH_CMDCMD */
1326 # ifdef JOBS
1327 #  ifdef CONFIG_ASH_ALIAS
1328 #    define EXECCMD (builtincmd + 9)
1329 #  else
1330 #    define EXECCMD (builtincmd + 8)
1331 #  endif
1332 # else /* ! JOBS */
1333 #  ifdef CONFIG_ASH_ALIAS
1334 #    define EXECCMD (builtincmd + 8)
1335 #  else
1336 #    define EXECCMD (builtincmd + 7)
1337 #  endif
1338 # endif /* JOBS */
1339 #endif /* CONFIG_ASH_CMDCMD */
1340
1341 #define BUILTIN_NOSPEC  "0"
1342 #define BUILTIN_SPECIAL "1"
1343 #define BUILTIN_REGULAR "2"
1344 #define BUILTIN_SPEC_REG "3"
1345 #define BUILTIN_ASSIGN  "4"
1346 #define BUILTIN_SPEC_ASSG  "5"
1347 #define BUILTIN_REG_ASSG   "6"
1348 #define BUILTIN_SPEC_REG_ASSG   "7"
1349
1350 #define IS_BUILTIN_SPECIAL(builtincmd) ((builtincmd)->name[0] & 1)
1351 #define IS_BUILTIN_REGULAR(builtincmd) ((builtincmd)->name[0] & 2)
1352
1353 static const struct builtincmd builtincmd[] = {
1354         { BUILTIN_SPEC_REG      ".", dotcmd },
1355         { BUILTIN_SPEC_REG      ":", truecmd },
1356 #ifdef CONFIG_ASH_ALIAS
1357         { BUILTIN_REG_ASSG      "alias", aliascmd },
1358 #endif
1359 #ifdef JOBS
1360         { BUILTIN_REGULAR       "bg", bgcmd },
1361 #endif
1362         { BUILTIN_SPEC_REG      "break", breakcmd },
1363         { BUILTIN_REGULAR       "cd", cdcmd },
1364         { BUILTIN_NOSPEC        "chdir", cdcmd },
1365 #ifdef CONFIG_ASH_CMDCMD
1366         { BUILTIN_REGULAR       "command", commandcmd },
1367 #endif
1368         { BUILTIN_SPEC_REG      "continue", breakcmd },
1369         { BUILTIN_SPEC_REG      "eval", evalcmd },
1370         { BUILTIN_SPEC_REG      "exec", execcmd },
1371         { BUILTIN_SPEC_REG      "exit", exitcmd },
1372         { BUILTIN_SPEC_REG_ASSG "export", exportcmd },
1373         { BUILTIN_REGULAR       "false", falsecmd },
1374 #ifdef JOBS
1375         { BUILTIN_REGULAR       "fg", fgcmd },
1376 #endif
1377 #ifdef CONFIG_ASH_GETOPTS
1378         { BUILTIN_REGULAR       "getopts", getoptscmd },
1379 #endif
1380         { BUILTIN_NOSPEC        "hash", hashcmd },
1381 #ifndef CONFIG_FEATURE_SH_EXTRA_QUIET
1382         { BUILTIN_NOSPEC        "help", helpcmd },
1383 #endif
1384 #ifdef JOBS
1385         { BUILTIN_REGULAR       "jobs", jobscmd },
1386         { BUILTIN_REGULAR       "kill", killcmd },
1387 #endif
1388 #ifdef CONFIG_ASH_MATH_SUPPORT
1389         { BUILTIN_NOSPEC        "let", letcmd },
1390 #endif
1391         { BUILTIN_ASSIGN        "local", localcmd },
1392         { BUILTIN_NOSPEC        "pwd", pwdcmd },
1393         { BUILTIN_REGULAR       "read", readcmd },
1394         { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd },
1395         { BUILTIN_SPEC_REG      "return", returncmd },
1396         { BUILTIN_SPEC_REG      "set", setcmd },
1397         { BUILTIN_SPEC_REG      "shift", shiftcmd },
1398         { BUILTIN_SPEC_REG      "times", timescmd },
1399         { BUILTIN_SPEC_REG      "trap", trapcmd },
1400         { BUILTIN_REGULAR       "true", truecmd },
1401         { BUILTIN_NOSPEC        "type", typecmd },
1402         { BUILTIN_NOSPEC        "ulimit", ulimitcmd },
1403         { BUILTIN_REGULAR       "umask", umaskcmd },
1404 #ifdef CONFIG_ASH_ALIAS
1405         { BUILTIN_REGULAR       "unalias", unaliascmd },
1406 #endif
1407         { BUILTIN_SPEC_REG      "unset", unsetcmd },
1408         { BUILTIN_REGULAR       "wait", waitcmd },
1409 };
1410
1411 #define NUMBUILTINS  (sizeof (builtincmd) / sizeof (struct builtincmd) )
1412
1413
1414
1415 struct cmdentry {
1416         int cmdtype;
1417         union param {
1418                 int index;
1419                 const struct builtincmd *cmd;
1420                 struct funcnode *func;
1421         } u;
1422 };
1423
1424
1425 /* action to find_command() */
1426 #define DO_ERR          0x01    /* prints errors */
1427 #define DO_ABS          0x02    /* checks absolute paths */
1428 #define DO_NOFUNC       0x04    /* don't return shell functions, for command */
1429 #define DO_ALTPATH      0x08    /* using alternate path */
1430 #define DO_ALTBLTIN     0x20    /* %builtin in alt. path */
1431
1432 static const char *pathopt;     /* set by padvance */
1433
1434 static void shellexec(char **, const char *, int)
1435     __attribute__((__noreturn__));
1436 static char *padvance(const char **, const char *);
1437 static void find_command(char *, struct cmdentry *, int, const char *);
1438 static struct builtincmd *find_builtin(const char *);
1439 static void hashcd(void);
1440 static void changepath(const char *);
1441 static void defun(char *, union node *);
1442 static void unsetfunc(const char *);
1443
1444 #ifdef CONFIG_ASH_MATH_SUPPORT
1445 static int dash_arith(const char *);
1446 #endif
1447
1448 /*      $NetBSD: init.h,v 1.9 2002/11/24 22:35:40 christos Exp $        */
1449
1450 static void reset(void);
1451
1452 /*      $NetBSD: var.h,v 1.21 2003/01/22 20:36:04 dsl Exp $     */
1453
1454 /*
1455  * Shell variables.
1456  */
1457
1458 /* flags */
1459 #define VEXPORT         0x01    /* variable is exported */
1460 #define VREADONLY       0x02    /* variable cannot be modified */
1461 #define VSTRFIXED       0x04    /* variable struct is statically allocated */
1462 #define VTEXTFIXED      0x08    /* text is statically allocated */
1463 #define VSTACK          0x10    /* text is allocated on the stack */
1464 #define VUNSET          0x20    /* the variable is not set */
1465 #define VNOFUNC         0x40    /* don't call the callback function */
1466 #define VNOSET          0x80    /* do not set variable - just readonly test */
1467 #define VNOSAVE         0x100   /* when text is on the heap before setvareq */
1468
1469
1470 struct var {
1471         struct var *next;               /* next entry in hash list */
1472         int flags;                      /* flags are defined above */
1473         const char *text;               /* name=value */
1474         void (*func)(const char *);
1475                                         /* function to be called when  */
1476                                         /* the variable gets set/unset */
1477 };
1478
1479 struct localvar {
1480         struct localvar *next;          /* next local variable in list */
1481         struct var *vp;                 /* the variable that was made local */
1482         int flags;                      /* saved flags */
1483         const char *text;               /* saved text */
1484 };
1485
1486
1487 static struct localvar *localvars;
1488
1489 /*
1490  * Shell variables.
1491  */
1492
1493 #ifdef CONFIG_ASH_GETOPTS
1494 static void getoptsreset(const char *);
1495 #endif
1496
1497 #ifdef CONFIG_LOCALE_SUPPORT
1498 #include <locale.h>
1499 static void change_lc_all(const char *value);
1500 static void change_lc_ctype(const char *value);
1501 #endif
1502
1503 #define VTABSIZE 39
1504
1505 static const char defpathvar[] = "PATH=/usr/local/bin:/usr/bin:/sbin:/bin";
1506 #ifdef IFS_BROKEN
1507 static const char defifsvar[] = "IFS= \t\n";
1508 #define defifs (defifsvar + 4)
1509 #else
1510 static const char defifs[] = " \t\n";
1511 #endif
1512
1513
1514 static struct var varinit[] = {
1515 #ifdef IFS_BROKEN
1516         { 0,    VSTRFIXED|VTEXTFIXED,           defifsvar,      0 },
1517 #else
1518         { 0,    VSTRFIXED|VTEXTFIXED|VUNSET,    "IFS\0",        0 },
1519 #endif
1520
1521 #ifdef CONFIG_ASH_MAIL
1522         { 0,    VSTRFIXED|VTEXTFIXED|VUNSET,    "MAIL\0",       changemail },
1523         { 0,    VSTRFIXED|VTEXTFIXED|VUNSET,    "MAILPATH\0",   changemail },
1524 #endif
1525
1526         { 0,    VSTRFIXED|VTEXTFIXED,           defpathvar,     changepath },
1527         { 0,    VSTRFIXED|VTEXTFIXED,           "PS1=$ ",       0 },
1528         { 0,    VSTRFIXED|VTEXTFIXED,           "PS2=> ",       0 },
1529         { 0,    VSTRFIXED|VTEXTFIXED,           "PS4=+ ",       0 },
1530 #ifdef CONFIG_ASH_GETOPTS
1531         { 0,    VSTRFIXED|VTEXTFIXED,           "OPTIND=1",     getoptsreset },
1532 #endif
1533 #ifdef CONFIG_LOCALE_SUPPORT
1534         {0, VSTRFIXED | VTEXTFIXED | VUNSET, "LC_ALL=", change_lc_all},
1535         {0, VSTRFIXED | VTEXTFIXED | VUNSET, "LC_CTYPE=", change_lc_ctype},
1536 #endif
1537 #ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
1538         {0, VSTRFIXED | VTEXTFIXED | VUNSET, "HISTFILE=", NULL},
1539 #endif
1540 };
1541
1542 #define vifs varinit[0]
1543 #ifdef CONFIG_ASH_MAIL
1544 #define vmail (&vifs)[1]
1545 #define vmpath (&vmail)[1]
1546 #else
1547 #define vmpath vifs
1548 #endif
1549 #define vpath (&vmpath)[1]
1550 #define vps1 (&vpath)[1]
1551 #define vps2 (&vps1)[1]
1552 #define vps4 (&vps2)[1]
1553 #define voptind (&vps4)[1]
1554
1555 #define defpath (defpathvar + 5)
1556
1557 /*
1558  * The following macros access the values of the above variables.
1559  * They have to skip over the name.  They return the null string
1560  * for unset variables.
1561  */
1562
1563 #define ifsval()        (vifs.text + 4)
1564 #define ifsset()        ((vifs.flags & VUNSET) == 0)
1565 #define mailval()       (vmail.text + 5)
1566 #define mpathval()      (vmpath.text + 9)
1567 #define pathval()       (vpath.text + 5)
1568 #define ps1val()        (vps1.text + 4)
1569 #define ps2val()        (vps2.text + 4)
1570 #define ps4val()        (vps4.text + 4)
1571 #define optindval()     (voptind.text + 7)
1572
1573 #define mpathset()      ((vmpath.flags & VUNSET) == 0)
1574
1575 static void setvar(const char *, const char *, int);
1576 static void setvareq(char *, int);
1577 static void listsetvar(struct strlist *, int);
1578 static char *lookupvar(const char *);
1579 static char *bltinlookup(const char *);
1580 static char **listvars(int, int, char ***);
1581 #define environment() listvars(VEXPORT, VUNSET, 0)
1582 static int showvars(const char *, int, int);
1583 static void poplocalvars(void);
1584 static int unsetvar(const char *);
1585 #ifdef CONFIG_ASH_GETOPTS
1586 static int setvarsafe(const char *, const char *, int);
1587 #endif
1588 static int varcmp(const char *, const char *);
1589 static struct var **hashvar(const char *);
1590
1591
1592 static inline int varequal(const char *a, const char *b) {
1593         return !varcmp(a, b);
1594 }
1595
1596
1597 static int loopnest;            /* current loop nesting level */
1598
1599 /*
1600  * The parsefile structure pointed to by the global variable parsefile
1601  * contains information about the current file being read.
1602  */
1603
1604
1605 struct redirtab {
1606         struct redirtab *next;
1607         int renamed[10];
1608         int nullredirs;
1609 };
1610
1611 static struct redirtab *redirlist;
1612 static int nullredirs;
1613
1614 extern char **environ;
1615
1616 /*      $NetBSD: output.h,v 1.16 2002/11/24 22:35:42 christos Exp $     */
1617
1618
1619 static void outstr(const char *, FILE *);
1620 static void outcslow(int, FILE *);
1621 static void flushall(void);
1622 static void flushout(FILE *);
1623 static int  out1fmt(const char *, ...)
1624     __attribute__((__format__(__printf__,1,2)));
1625 static int fmtstr(char *, size_t, const char *, ...)
1626     __attribute__((__format__(__printf__,3,4)));
1627 static void xwrite(int, const void *, size_t);
1628
1629 static int preverrout_fd;   /* save fd2 before print debug if xflag is set. */
1630
1631
1632 static void out1str(const char *p)
1633 {
1634         outstr(p, stdout);
1635 }
1636
1637 static void out2str(const char *p)
1638 {
1639         outstr(p, stderr);
1640         flushout(stderr);
1641 }
1642
1643 /*
1644  * Initialization code.
1645  */
1646
1647 /*
1648  * This routine initializes the builtin variables.
1649  */
1650
1651 static inline void
1652 initvar(void)
1653 {
1654         struct var *vp;
1655         struct var *end;
1656         struct var **vpp;
1657
1658         /*
1659          * PS1 depends on uid
1660          */
1661 #if defined(CONFIG_FEATURE_COMMAND_EDITING) && defined(CONFIG_FEATURE_SH_FANCY_PROMPT)
1662         vps1.text = "PS1=\\w \\$ ";
1663 #else
1664         if (!geteuid())
1665                 vps1.text = "PS1=# ";
1666 #endif
1667         vp = varinit;
1668         end = vp + sizeof(varinit) / sizeof(varinit[0]);
1669         do {
1670                 vpp = hashvar(vp->text);
1671                 vp->next = *vpp;
1672                 *vpp = vp;
1673         } while (++vp < end);
1674 }
1675
1676 static inline void
1677 init(void)
1678 {
1679
1680       /* from input.c: */
1681       {
1682               basepf.nextc = basepf.buf = basebuf;
1683       }
1684
1685       /* from trap.c: */
1686       {
1687               signal(SIGCHLD, SIG_DFL);
1688       }
1689
1690       /* from var.c: */
1691       {
1692               char **envp;
1693               char ppid[32];
1694
1695               initvar();
1696               for (envp = environ ; *envp ; envp++) {
1697                       if (strchr(*envp, '=')) {
1698                               setvareq(*envp, VEXPORT|VTEXTFIXED);
1699                       }
1700               }
1701
1702               snprintf(ppid, sizeof(ppid), "%d", (int) getppid());
1703               setvar("PPID", ppid, 0);
1704               setpwd(0, 0);
1705       }
1706 }
1707
1708 /* PEOF (the end of file marker) */
1709
1710 /*
1711  * The input line number.  Input.c just defines this variable, and saves
1712  * and restores it when files are pushed and popped.  The user of this
1713  * package must set its value.
1714  */
1715
1716 static int pgetc(void);
1717 static int pgetc2(void);
1718 static int preadbuffer(void);
1719 static void pungetc(void);
1720 static void pushstring(char *, void *);
1721 static void popstring(void);
1722 static void setinputfile(const char *, int);
1723 static void setinputfd(int, int);
1724 static void setinputstring(char *);
1725 static void popfile(void);
1726 static void popallfiles(void);
1727 static void closescript(void);
1728
1729
1730 /*      $NetBSD: jobs.h,v 1.17 2003/01/22 20:36:04 dsl Exp $    */
1731
1732
1733 /* Mode argument to forkshell.  Don't change FORK_FG or FORK_BG. */
1734 #define FORK_FG 0
1735 #define FORK_BG 1
1736 #define FORK_NOJOB 2
1737
1738 /* mode flags for showjob(s) */
1739 #define SHOW_PGID       0x01    /* only show pgid - for jobs -p */
1740 #define SHOW_PID        0x04    /* include process pid */
1741 #define SHOW_CHANGED    0x08    /* only jobs whose state has changed */
1742
1743
1744 /*
1745  * A job structure contains information about a job.  A job is either a
1746  * single process or a set of processes contained in a pipeline.  In the
1747  * latter case, pidlist will be non-NULL, and will point to a -1 terminated
1748  * array of pids.
1749  */
1750
1751 struct procstat {
1752         pid_t   pid;            /* process id */
1753         int     status;         /* last process status from wait() */
1754         char    *cmd;           /* text of command being run */
1755 };
1756
1757 struct job {
1758         struct procstat ps0;    /* status of process */
1759         struct procstat *ps;    /* status or processes when more than one */
1760 #if JOBS
1761         int stopstatus;         /* status of a stopped job */
1762 #endif
1763         uint32_t
1764                 nprocs: 16,     /* number of processes */
1765                 state: 8,
1766 #define JOBRUNNING      0       /* at least one proc running */
1767 #define JOBSTOPPED      1       /* all procs are stopped */
1768 #define JOBDONE         2       /* all procs are completed */
1769 #if JOBS
1770                 sigint: 1,      /* job was killed by SIGINT */
1771                 jobctl: 1,      /* job running under job control */
1772 #endif
1773                 waited: 1,      /* true if this entry has been waited for */
1774                 used: 1,        /* true if this entry is in used */
1775                 changed: 1;     /* true if status has changed */
1776         struct job *prev_job;   /* previous job */
1777 };
1778
1779 static pid_t backgndpid;        /* pid of last background process */
1780 static int job_warning;         /* user was warned about stopped jobs */
1781 #if JOBS
1782 static int jobctl;              /* true if doing job control */
1783 #endif
1784
1785 static struct job *makejob(union node *, int);
1786 static int forkshell(struct job *, union node *, int);
1787 static int waitforjob(struct job *);
1788 static int stoppedjobs(void);
1789
1790 #if ! JOBS
1791 #define setjobctl(on)   /* do nothing */
1792 #else
1793 static void setjobctl(int);
1794 static void showjobs(FILE *, int);
1795 #endif
1796
1797 /*      $NetBSD: main.h,v 1.9 2002/11/24 22:35:41 christos Exp $        */
1798
1799
1800 /* pid of main shell */
1801 static int rootpid;
1802 /* true if we aren't a child of the main shell */
1803 static int rootshell;
1804
1805 static void readcmdfile(char *);
1806 static void cmdloop(int);
1807
1808 /*      $NetBSD: memalloc.h,v 1.13 2003/01/22 20:36:04 dsl Exp $        */
1809
1810
1811 struct stackmark {
1812         struct stack_block *stackp;
1813         char *stacknxt;
1814         size_t stacknleft;
1815         struct stackmark *marknext;
1816 };
1817
1818 /* minimum size of a block */
1819 #define MINSIZE SHELL_ALIGN(504)
1820
1821 struct stack_block {
1822         struct stack_block *prev;
1823         char space[MINSIZE];
1824 };
1825
1826 static struct stack_block stackbase;
1827 static struct stack_block *stackp = &stackbase;
1828 static struct stackmark *markp;
1829 static char *stacknxt = stackbase.space;
1830 static size_t stacknleft = MINSIZE;
1831 static char *sstrend = stackbase.space + MINSIZE;
1832 static int herefd = -1;
1833
1834
1835 static pointer ckmalloc(size_t);
1836 static pointer ckrealloc(pointer, size_t);
1837 static char *savestr(const char *);
1838 static pointer stalloc(size_t);
1839 static void stunalloc(pointer);
1840 static void setstackmark(struct stackmark *);
1841 static void popstackmark(struct stackmark *);
1842 static void growstackblock(void);
1843 static void *growstackstr(void);
1844 static char *makestrspace(size_t, char *);
1845 static char *stnputs(const char *, size_t, char *);
1846 static char *stputs(const char *, char *);
1847
1848
1849 static inline char *_STPUTC(char c, char *p) {
1850         if (p == sstrend)
1851                 p = growstackstr();
1852         *p++ = c;
1853         return p;
1854 }
1855
1856 #define stackblock() ((void *)stacknxt)
1857 #define stackblocksize() stacknleft
1858 #define STARTSTACKSTR(p) ((p) = stackblock())
1859 #define STPUTC(c, p) ((p) = _STPUTC((c), (p)))
1860 #define CHECKSTRSPACE(n, p) \
1861         ({ \
1862                 char *q = (p); \
1863                 size_t l = (n); \
1864                 size_t m = sstrend - q; \
1865                 if (l > m) \
1866                         (p) = makestrspace(l, q); \
1867                 0; \
1868         })
1869 #define USTPUTC(c, p)   (*p++ = (c))
1870 #define STACKSTRNUL(p)  ((p) == sstrend? (p = growstackstr(), *p = '\0') : (*p = '\0'))
1871 #define STUNPUTC(p)     (--p)
1872 #define STTOPC(p)       p[-1]
1873 #define STADJUST(amount, p)     (p += (amount))
1874
1875 #define grabstackstr(p) stalloc((char *)(p) - (char *)stackblock())
1876 #define ungrabstackstr(s, p) stunalloc((s))
1877 #define stackstrend() ((void *)sstrend)
1878
1879 #define ckfree(p)       free((pointer)(p))
1880
1881 /*      $NetBSD: mystring.h,v 1.10 2002/11/24 22:35:42 christos Exp $   */
1882
1883
1884 #define DOLATSTRLEN 4
1885
1886 static char *prefix(const char *, const char *);
1887 static int number(const char *);
1888 static int is_number(const char *);
1889 static char *single_quote(const char *);
1890 static char *sstrdup(const char *);
1891
1892 #define equal(s1, s2)   (strcmp(s1, s2) == 0)
1893 #define scopy(s1, s2)   ((void)strcpy(s2, s1))
1894
1895 /*      $NetBSD: options.h,v 1.16 2003/01/22 20:36:04 dsl Exp $ */
1896
1897 struct shparam {
1898         int nparam;             /* # of positional parameters (without $0) */
1899         unsigned char malloc;   /* if parameter list dynamically allocated */
1900         char **p;               /* parameter list */
1901 #ifdef CONFIG_ASH_GETOPTS
1902         int optind;             /* next parameter to be processed by getopts */
1903         int optoff;             /* used by getopts */
1904 #endif
1905 };
1906
1907
1908 #define eflag optlist[0]
1909 #define fflag optlist[1]
1910 #define Iflag optlist[2]
1911 #define iflag optlist[3]
1912 #define mflag optlist[4]
1913 #define nflag optlist[5]
1914 #define sflag optlist[6]
1915 #define xflag optlist[7]
1916 #define vflag optlist[8]
1917 #define Cflag optlist[9]
1918 #define aflag optlist[10]
1919 #define bflag optlist[11]
1920 #define uflag optlist[12]
1921 #define qflag optlist[13]
1922
1923 #ifdef DEBUG
1924 #define nolog optlist[14]
1925 #define debug optlist[15]
1926 #define NOPTS   16
1927 #else
1928 #define NOPTS   14
1929 #endif
1930
1931 /*      $NetBSD: options.c,v 1.33 2003/01/22 20:36:04 dsl Exp $ */
1932
1933
1934 static const char *const optletters_optnames[NOPTS] = {
1935         "e"   "errexit",
1936         "f"   "noglob",
1937         "I"   "ignoreeof",
1938         "i"   "interactive",
1939         "m"   "monitor",
1940         "n"   "noexec",
1941         "s"   "stdin",
1942         "x"   "xtrace",
1943         "v"   "verbose",
1944         "C"   "noclobber",
1945         "a"   "allexport",
1946         "b"   "notify",
1947         "u"   "nounset",
1948         "q"   "quietprofile",
1949 #ifdef DEBUG
1950         "\0"  "nolog",
1951         "\0"  "debug",
1952 #endif
1953 };
1954
1955 #define optletters(n) optletters_optnames[(n)][0]
1956 #define optnames(n) (&optletters_optnames[(n)][1])
1957
1958
1959 static char optlist[NOPTS];
1960
1961
1962 static char *arg0;                     /* value of $0 */
1963 static struct shparam shellparam;      /* $@ current positional parameters */
1964 static char **argptr;                  /* argument list for builtin commands */
1965 static char *optionarg;                /* set by nextopt (like getopt) */
1966 static char *optptr;                   /* used by nextopt */
1967
1968 static char *minusc;                   /* argument to -c option */
1969
1970
1971 static void procargs(int, char **);
1972 static void optschanged(void);
1973 static void setparam(char **);
1974 static void freeparam(volatile struct shparam *);
1975 static int shiftcmd(int, char **);
1976 static int setcmd(int, char **);
1977 static int nextopt(const char *);
1978
1979 /*      $NetBSD: redir.h,v 1.14 2002/11/24 22:35:43 christos Exp $      */
1980
1981 /* flags passed to redirect */
1982 #define REDIR_PUSH 01           /* save previous values of file descriptors */
1983 #define REDIR_SAVEFD2 03       /* set preverrout */
1984
1985 union node;
1986 static void redirect(union node *, int);
1987 static void popredir(int);
1988 static void clearredir(int);
1989 static int copyfd(int, int);
1990 static int redirectsafe(union node *, int);
1991
1992 /*      $NetBSD: show.h,v 1.6 2003/01/22 20:36:04 dsl Exp $     */
1993
1994
1995 #ifdef DEBUG
1996 static void showtree(union node *);
1997 static void trace(const char *, ...);
1998 static void tracev(const char *, va_list);
1999 static void trargs(char **);
2000 static void trputc(int);
2001 static void trputs(const char *);
2002 static void opentrace(void);
2003 #endif
2004
2005 /*      $NetBSD: trap.h,v 1.16 2002/11/24 22:35:43 christos Exp $       */
2006
2007
2008 /* trap handler commands */
2009 static char *trap[NSIG];
2010 /* current value of signal */
2011 static char sigmode[NSIG - 1];
2012 /* indicates specified signal received */
2013 static char gotsig[NSIG - 1];
2014
2015 static void clear_traps(void);
2016 static void setsignal(int);
2017 static void ignoresig(int);
2018 static void onsig(int);
2019 static void dotrap(void);
2020 static void setinteractive(int);
2021 static void exitshell(void) __attribute__((__noreturn__));
2022 static int decode_signal(const char *, int);
2023
2024 /*
2025  * This routine is called when an error or an interrupt occurs in an
2026  * interactive shell and control is returned to the main command loop.
2027  */
2028
2029 static void
2030 reset(void)
2031 {
2032       /* from eval.c: */
2033       {
2034               evalskip = 0;
2035               loopnest = 0;
2036               funcnest = 0;
2037       }
2038
2039       /* from input.c: */
2040       {
2041               parselleft = parsenleft = 0;      /* clear input buffer */
2042               popallfiles();
2043       }
2044
2045       /* from parser.c: */
2046       {
2047               tokpushback = 0;
2048               checkkwd = 0;
2049       }
2050
2051       /* from redir.c: */
2052       {
2053               clearredir(0);
2054       }
2055
2056 }
2057
2058 #ifdef CONFIG_ASH_ALIAS
2059 static struct alias *atab[ATABSIZE];
2060
2061 static void setalias(const char *, const char *);
2062 static struct alias *freealias(struct alias *);
2063 static struct alias **__lookupalias(const char *);
2064
2065 static void
2066 setalias(const char *name, const char *val)
2067 {
2068         struct alias *ap, **app;
2069
2070         app = __lookupalias(name);
2071         ap = *app;
2072         INTOFF;
2073         if (ap) {
2074                 if (!(ap->flag & ALIASINUSE)) {
2075                         ckfree(ap->val);
2076                 }
2077                 ap->val = savestr(val);
2078                 ap->flag &= ~ALIASDEAD;
2079         } else {
2080                 /* not found */
2081                 ap = ckmalloc(sizeof (struct alias));
2082                 ap->name = savestr(name);
2083                 ap->val = savestr(val);
2084                 ap->flag = 0;
2085                 ap->next = 0;
2086                 *app = ap;
2087         }
2088         INTON;
2089 }
2090
2091 static int
2092 unalias(const char *name)
2093 {
2094         struct alias **app;
2095
2096         app = __lookupalias(name);
2097
2098         if (*app) {
2099                 INTOFF;
2100                 *app = freealias(*app);
2101                 INTON;
2102                 return (0);
2103         }
2104
2105         return (1);
2106 }
2107
2108 static void
2109 rmaliases(void)
2110 {
2111         struct alias *ap, **app;
2112         int i;
2113
2114         INTOFF;
2115         for (i = 0; i < ATABSIZE; i++) {
2116                 app = &atab[i];
2117                 for (ap = *app; ap; ap = *app) {
2118                         *app = freealias(*app);
2119                         if (ap == *app) {
2120                                 app = &ap->next;
2121                         }
2122                 }
2123         }
2124         INTON;
2125 }
2126
2127 static struct alias *
2128 lookupalias(const char *name, int check)
2129 {
2130         struct alias *ap = *__lookupalias(name);
2131
2132         if (check && ap && (ap->flag & ALIASINUSE))
2133                 return (NULL);
2134         return (ap);
2135 }
2136
2137 /*
2138  * TODO - sort output
2139  */
2140 static int
2141 aliascmd(int argc, char **argv)
2142 {
2143         char *n, *v;
2144         int ret = 0;
2145         struct alias *ap;
2146
2147         if (argc == 1) {
2148                 int i;
2149
2150                 for (i = 0; i < ATABSIZE; i++)
2151                         for (ap = atab[i]; ap; ap = ap->next) {
2152                                 printalias(ap);
2153                         }
2154                 return (0);
2155         }
2156         while ((n = *++argv) != NULL) {
2157                 if ((v = strchr(n+1, '=')) == NULL) { /* n+1: funny ksh stuff */
2158                         if ((ap = *__lookupalias(n)) == NULL) {
2159                                 fprintf(stderr, "%s: %s not found\n", "alias", n);
2160                                 ret = 1;
2161                         } else
2162                                 printalias(ap);
2163                 } else {
2164                         *v++ = '\0';
2165                         setalias(n, v);
2166                 }
2167         }
2168
2169         return (ret);
2170 }
2171
2172 static int
2173 unaliascmd(int argc, char **argv)
2174 {
2175         int i;
2176
2177         while ((i = nextopt("a")) != '\0') {
2178                 if (i == 'a') {
2179                         rmaliases();
2180                         return (0);
2181                 }
2182         }
2183         for (i = 0; *argptr; argptr++) {
2184                 if (unalias(*argptr)) {
2185                         fprintf(stderr, "%s: %s not found\n", "unalias", *argptr);
2186                         i = 1;
2187                 }
2188         }
2189
2190         return (i);
2191 }
2192
2193 static struct alias *
2194 freealias(struct alias *ap) {
2195         struct alias *next;
2196
2197         if (ap->flag & ALIASINUSE) {
2198                 ap->flag |= ALIASDEAD;
2199                 return ap;
2200         }
2201
2202         next = ap->next;
2203         ckfree(ap->name);
2204         ckfree(ap->val);
2205         ckfree(ap);
2206         return next;
2207 }
2208
2209 static void
2210 printalias(const struct alias *ap) {
2211         out1fmt("%s=%s\n", ap->name, single_quote(ap->val));
2212 }
2213
2214 static struct alias **
2215 __lookupalias(const char *name) {
2216         unsigned int hashval;
2217         struct alias **app;
2218         const char *p;
2219         unsigned int ch;
2220
2221         p = name;
2222
2223         ch = (unsigned char)*p;
2224         hashval = ch << 4;
2225         while (ch) {
2226                 hashval += ch;
2227                 ch = (unsigned char)*++p;
2228         }
2229         app = &atab[hashval % ATABSIZE];
2230
2231         for (; *app; app = &(*app)->next) {
2232                 if (equal(name, (*app)->name)) {
2233                         break;
2234                 }
2235         }
2236
2237         return app;
2238 }
2239 #endif /* CONFIG_ASH_ALIAS */
2240
2241
2242 /*      $NetBSD: cd.c,v 1.30 2003/01/22 20:36:03 dsl Exp $      */
2243
2244 /*
2245  * The cd and pwd commands.
2246  */
2247
2248 #define CD_PHYSICAL 1
2249 #define CD_PRINT 2
2250
2251 static int docd(const char *, int);
2252 static int cdopt(void);
2253
2254 static char *curdir = nullstr;          /* current working directory */
2255 static char *physdir = nullstr;         /* physical working directory */
2256
2257 static int
2258 cdopt(void)
2259 {
2260         int flags = 0;
2261         int i, j;
2262
2263         j = 'L';
2264         while ((i = nextopt("LP"))) {
2265                 if (i != j) {
2266                         flags ^= CD_PHYSICAL;
2267                         j = i;
2268                 }
2269         }
2270
2271         return flags;
2272 }
2273
2274 static int
2275 cdcmd(int argc, char **argv)
2276 {
2277         const char *dest;
2278         const char *path;
2279         const char *p;
2280         char c;
2281         struct stat statb;
2282         int flags;
2283
2284         flags = cdopt();
2285         dest = *argptr;
2286         if (!dest)
2287                 dest = bltinlookup(homestr);
2288         else if (dest[0] == '-' && dest[1] == '\0') {
2289                 dest = bltinlookup("OLDPWD");
2290                 flags |= CD_PRINT;
2291                 goto step7;
2292         }
2293         if (!dest)
2294                 dest = nullstr;
2295         if (*dest == '/')
2296                 goto step7;
2297         if (*dest == '.') {
2298                 c = dest[1];
2299 dotdot:
2300                 switch (c) {
2301                 case '\0':
2302                 case '/':
2303                         goto step6;
2304                 case '.':
2305                         c = dest[2];
2306                         if (c != '.')
2307                                 goto dotdot;
2308                 }
2309         }
2310         if (!*dest)
2311                 dest = ".";
2312         if (!(path = bltinlookup("CDPATH"))) {
2313 step6:
2314 step7:
2315                 p = dest;
2316                 goto docd;
2317         }
2318         do {
2319                 c = *path;
2320                 p = padvance(&path, dest);
2321                 if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
2322                         if (c && c != ':')
2323                                 flags |= CD_PRINT;
2324 docd:
2325                         if (!docd(p, flags))
2326                                 goto out;
2327                         break;
2328                 }
2329         } while (path);
2330         error("can't cd to %s", dest);
2331         /* NOTREACHED */
2332 out:
2333         if (flags & CD_PRINT)
2334                 out1fmt(snlfmt, curdir);
2335         return 0;
2336 }
2337
2338
2339 /*
2340  * Update curdir (the name of the current directory) in response to a
2341  * cd command.
2342  */
2343
2344 static inline const char *
2345 updatepwd(const char *dir)
2346 {
2347         char *new;
2348         char *p;
2349         char *cdcomppath;
2350         const char *lim;
2351
2352         cdcomppath = sstrdup(dir);
2353         STARTSTACKSTR(new);
2354         if (*dir != '/') {
2355                 if (curdir == nullstr)
2356                         return 0;
2357                 new = stputs(curdir, new);
2358         }
2359         new = makestrspace(strlen(dir) + 2, new);
2360         lim = stackblock() + 1;
2361         if (*dir != '/') {
2362                 if (new[-1] != '/')
2363                         USTPUTC('/', new);
2364                 if (new > lim && *lim == '/')
2365                         lim++;
2366         } else {
2367                 USTPUTC('/', new);
2368                 cdcomppath++;
2369                 if (dir[1] == '/' && dir[2] != '/') {
2370                         USTPUTC('/', new);
2371                         cdcomppath++;
2372                         lim++;
2373                 }
2374         }
2375         p = strtok(cdcomppath, "/");
2376         while (p) {
2377                 switch(*p) {
2378                 case '.':
2379                         if (p[1] == '.' && p[2] == '\0') {
2380                                 while (new > lim) {
2381                                         STUNPUTC(new);
2382                                         if (new[-1] == '/')
2383                                                 break;
2384                                 }
2385                                 break;
2386                         } else if (p[1] == '\0')
2387                                 break;
2388                         /* fall through */
2389                 default:
2390                         new = stputs(p, new);
2391                         USTPUTC('/', new);
2392                 }
2393                 p = strtok(0, "/");
2394         }
2395         if (new > lim)
2396                 STUNPUTC(new);
2397         *new = 0;
2398         return stackblock();
2399 }
2400
2401 /*
2402  * Actually do the chdir.  We also call hashcd to let the routines in exec.c
2403  * know that the current directory has changed.
2404  */
2405
2406 static int
2407 docd(const char *dest, int flags)
2408 {
2409         const char *dir = 0;
2410         int err;
2411
2412         TRACE(("docd(\"%s\", %d) called\n", dest, flags));
2413
2414         INTOFF;
2415         if (!(flags & CD_PHYSICAL)) {
2416                 dir = updatepwd(dest);
2417                 if (dir)
2418                         dest = dir;
2419         }
2420         err = chdir(dest);
2421         if (err)
2422                 goto out;
2423         setpwd(dir, 1);
2424         hashcd();
2425 out:
2426         INTON;
2427         return err;
2428 }
2429
2430 /*
2431  * Find out what the current directory is. If we already know the current
2432  * directory, this routine returns immediately.
2433  */
2434 static inline char *
2435 getpwd(void)
2436 {
2437         char *dir = getcwd(0, 0);
2438         return dir ? dir : nullstr;
2439 }
2440
2441 static int
2442 pwdcmd(int argc, char **argv)
2443 {
2444         int flags;
2445         const char *dir = curdir;
2446
2447         flags = cdopt();
2448         if (flags) {
2449                 if (physdir == nullstr)
2450                         setpwd(dir, 0);
2451                 dir = physdir;
2452         }
2453         out1fmt(snlfmt, dir);
2454         return 0;
2455 }
2456
2457 static void
2458 setpwd(const char *val, int setold)
2459 {
2460         char *oldcur, *dir;
2461
2462         oldcur = dir = curdir;
2463
2464         if (setold) {
2465                 setvar("OLDPWD", oldcur, VEXPORT);
2466         }
2467         INTOFF;
2468         if (physdir != nullstr) {
2469                 if (physdir != oldcur)
2470                         free(physdir);
2471                 physdir = nullstr;
2472         }
2473         if (oldcur == val || !val) {
2474                 char *s = getpwd();
2475                 physdir = s;
2476                 if (!val)
2477                         dir = s;
2478         } else
2479                 dir = savestr(val);
2480         if (oldcur != dir && oldcur != nullstr) {
2481                 free(oldcur);
2482         }
2483         curdir = dir;
2484         INTON;
2485         setvar("PWD", dir, VEXPORT);
2486 }
2487
2488 /*      $NetBSD: error.c,v 1.30 2003/01/22 20:36:03 dsl Exp $   */
2489
2490 /*
2491  * Errors and exceptions.
2492  */
2493
2494 /*
2495  * Code to handle exceptions in C.
2496  */
2497
2498
2499
2500 static void exverror(int, const char *, va_list)
2501     __attribute__((__noreturn__));
2502
2503 /*
2504  * Called to raise an exception.  Since C doesn't include exceptions, we
2505  * just do a longjmp to the exception handler.  The type of exception is
2506  * stored in the global variable "exception".
2507  */
2508
2509 static void
2510 exraise(int e)
2511 {
2512 #ifdef DEBUG
2513         if (handler == NULL)
2514                 abort();
2515 #endif
2516         INTOFF;
2517
2518         exception = e;
2519         longjmp(handler->loc, 1);
2520 }
2521
2522
2523 /*
2524  * Called from trap.c when a SIGINT is received.  (If the user specifies
2525  * that SIGINT is to be trapped or ignored using the trap builtin, then
2526  * this routine is not called.)  Suppressint is nonzero when interrupts
2527  * are held using the INTOFF macro.  (The test for iflag is just
2528  * defensive programming.)
2529  */
2530
2531 static void
2532 onint(void) {
2533         int i;
2534
2535         intpending = 0;
2536         sigsetmask(0);
2537         i = EXSIG;
2538         if (gotsig[SIGINT - 1] && !trap[SIGINT]) {
2539                 if (!(rootshell && iflag)) {
2540                         signal(SIGINT, SIG_DFL);
2541                         raise(SIGINT);
2542                 }
2543                 i = EXINT;
2544         }
2545         exraise(i);
2546         /* NOTREACHED */
2547 }
2548
2549 static void
2550 exvwarning(const char *msg, va_list ap)
2551 {
2552         FILE *errs;
2553         const char *name;
2554         const char *fmt;
2555
2556         errs = stderr;
2557         name = arg0;
2558         fmt = "%s: ";
2559         if (commandname) {
2560                 name = commandname;
2561                 fmt = "%s: %d: ";
2562         }
2563         fprintf(errs, fmt, name, startlinno);
2564         vfprintf(errs, msg, ap);
2565         outcslow('\n', errs);
2566 }
2567
2568 /*
2569  * Exverror is called to raise the error exception.  If the second argument
2570  * is not NULL then error prints an error message using printf style
2571  * formatting.  It then raises the error exception.
2572  */
2573 static void
2574 exverror(int cond, const char *msg, va_list ap)
2575 {
2576 #ifdef DEBUG
2577         if (msg) {
2578                 TRACE(("exverror(%d, \"", cond));
2579                 TRACEV((msg, ap));
2580                 TRACE(("\") pid=%d\n", getpid()));
2581         } else
2582                 TRACE(("exverror(%d, NULL) pid=%d\n", cond, getpid()));
2583         if (msg)
2584 #endif
2585                 exvwarning(msg, ap);
2586
2587         flushall();
2588         exraise(cond);
2589         /* NOTREACHED */
2590 }
2591
2592
2593 static void
2594 error(const char *msg, ...)
2595 {
2596         va_list ap;
2597
2598         va_start(ap, msg);
2599         exverror(EXERROR, msg, ap);
2600         /* NOTREACHED */
2601         va_end(ap);
2602 }
2603
2604
2605 static void
2606 exerror(int cond, const char *msg, ...)
2607 {
2608         va_list ap;
2609
2610         va_start(ap, msg);
2611         exverror(cond, msg, ap);
2612         /* NOTREACHED */
2613         va_end(ap);
2614 }
2615
2616 /*
2617  * error/warning routines for external builtins
2618  */
2619
2620 static void
2621 sh_warnx(const char *fmt, ...)
2622 {
2623         va_list ap;
2624
2625         va_start(ap, fmt);
2626         exvwarning(fmt, ap);
2627         va_end(ap);
2628 }
2629
2630
2631 /*
2632  * Return a string describing an error.  The returned string may be a
2633  * pointer to a static buffer that will be overwritten on the next call.
2634  * Action describes the operation that got the error.
2635  */
2636
2637 static const char *
2638 errmsg(int e, const char *em)
2639 {
2640         if(e == ENOENT || e == ENOTDIR) {
2641
2642                 return em;
2643         }
2644         return strerror(e);
2645 }
2646
2647
2648 /*      $NetBSD: eval.c,v 1.71 2003/01/23 03:33:16 rafal Exp $  */
2649
2650 /*
2651  * Evaluate a command.
2652  */
2653
2654 /* flags in argument to evaltree */
2655 #define EV_EXIT 01              /* exit after evaluating tree */
2656 #define EV_TESTED 02            /* exit status is checked; ignore -e flag */
2657 #define EV_BACKCMD 04           /* command executing within back quotes */
2658
2659
2660 static void evalloop(union node *, int);
2661 static void evalfor(union node *, int);
2662 static void evalcase(union node *, int);
2663 static void evalsubshell(union node *, int);
2664 static void expredir(union node *);
2665 static void evalpipe(union node *, int);
2666 static void evalcommand(union node *, int);
2667 static int evalbltin(const struct builtincmd *, int, char **);
2668 static int evalfun(struct funcnode *, int, char **, int);
2669 static void prehash(union node *);
2670 static int bltincmd(int, char **);
2671
2672
2673 static const struct builtincmd bltin = {
2674         "\0\0", bltincmd
2675 };
2676
2677
2678 /*
2679  * Called to reset things after an exception.
2680  */
2681
2682 /*
2683  * The eval commmand.
2684  */
2685
2686 static int
2687 evalcmd(int argc, char **argv)
2688 {
2689         char *p;
2690         char *concat;
2691         char **ap;
2692
2693         if (argc > 1) {
2694                 p = argv[1];
2695                 if (argc > 2) {
2696                         STARTSTACKSTR(concat);
2697                         ap = argv + 2;
2698                         for (;;) {
2699                                 concat = stputs(p, concat);
2700                                 if ((p = *ap++) == NULL)
2701                                         break;
2702                                 STPUTC(' ', concat);
2703                         }
2704                         STPUTC('\0', concat);
2705                         p = grabstackstr(concat);
2706                 }
2707                 evalstring(p, EV_TESTED);
2708         }
2709         return exitstatus;
2710 }
2711
2712
2713 /*
2714  * Execute a command or commands contained in a string.
2715  */
2716
2717 static void
2718 evalstring(char *s, int flag)
2719 {
2720         union node *n;
2721         struct stackmark smark;
2722
2723         setstackmark(&smark);
2724         setinputstring(s);
2725
2726         while ((n = parsecmd(0)) != NEOF) {
2727                 evaltree(n, flag);
2728                 popstackmark(&smark);
2729                 if (evalskip)
2730                         break;
2731         }
2732         popfile();
2733         popstackmark(&smark);
2734 }
2735
2736
2737
2738 /*
2739  * Evaluate a parse tree.  The value is left in the global variable
2740  * exitstatus.
2741  */
2742
2743 static void
2744 evaltree(union node *n, int flags)
2745 {
2746         int checkexit = 0;
2747         void (*evalfn)(union node *, int);
2748         unsigned isor;
2749         int status;
2750         if (n == NULL) {
2751                 TRACE(("evaltree(NULL) called\n"));
2752                 goto out;
2753         }
2754         TRACE(("pid %d, evaltree(%p: %d, %d) called\n",
2755             getpid(), n, n->type, flags));
2756         switch (n->type) {
2757         default:
2758 #ifdef DEBUG
2759                 out1fmt("Node type = %d\n", n->type);
2760                 fflush(stdout);
2761                 break;
2762 #endif
2763         case NNOT:
2764                 evaltree(n->nnot.com, EV_TESTED);
2765                 status = !exitstatus;
2766                 goto setstatus;
2767         case NREDIR:
2768                 expredir(n->nredir.redirect);
2769                 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
2770                 if (!status) {
2771                         evaltree(n->nredir.n, flags & EV_TESTED);
2772                         status = exitstatus;
2773                 }
2774                 popredir(0);
2775                 goto setstatus;
2776         case NCMD:
2777                 evalfn = evalcommand;
2778 checkexit:
2779                 if (eflag && !(flags & EV_TESTED))
2780                         checkexit = ~0;
2781                 goto calleval;
2782         case NFOR:
2783                 evalfn = evalfor;
2784                 goto calleval;
2785         case NWHILE:
2786         case NUNTIL:
2787                 evalfn = evalloop;
2788                 goto calleval;
2789         case NSUBSHELL:
2790         case NBACKGND:
2791                 evalfn = evalsubshell;
2792                 goto calleval;
2793         case NPIPE:
2794                 evalfn = evalpipe;
2795                 goto checkexit;
2796         case NCASE:
2797                 evalfn = evalcase;
2798                 goto calleval;
2799         case NAND:
2800         case NOR:
2801         case NSEMI:
2802 #if NAND + 1 != NOR
2803 #error NAND + 1 != NOR
2804 #endif
2805 #if NOR + 1 != NSEMI
2806 #error NOR + 1 != NSEMI
2807 #endif
2808                 isor = n->type - NAND;
2809                 evaltree(
2810                         n->nbinary.ch1,
2811                         (flags | ((isor >> 1) - 1)) & EV_TESTED
2812                 );
2813                 if (!exitstatus == isor)
2814                         break;
2815                 if (!evalskip) {
2816                         n = n->nbinary.ch2;
2817 evaln:
2818                         evalfn = evaltree;
2819 calleval:
2820                         evalfn(n, flags);
2821                         break;
2822                 }
2823                 break;
2824         case NIF:
2825                 evaltree(n->nif.test, EV_TESTED);
2826                 if (evalskip)
2827                         break;
2828                 if (exitstatus == 0) {
2829                         n = n->nif.ifpart;
2830                         goto evaln;
2831                 } else if (n->nif.elsepart) {
2832                         n = n->nif.elsepart;
2833                         goto evaln;
2834                 }
2835                 goto success;
2836         case NDEFUN:
2837                 defun(n->narg.text, n->narg.next);
2838 success:
2839                 status = 0;
2840 setstatus:
2841                 exitstatus = status;
2842                 break;
2843         }
2844 out:
2845         if (pendingsigs)
2846                 dotrap();
2847         if (flags & EV_EXIT || checkexit & exitstatus)
2848                 exraise(EXEXIT);
2849 }
2850
2851
2852 #if !defined(__alpha__) || (defined(__GNUC__) && __GNUC__ >= 3)
2853 static
2854 #endif
2855 void evaltreenr(union node *, int) __attribute__ ((alias("evaltree"),__noreturn__));
2856
2857
2858 static void
2859 evalloop(union node *n, int flags)
2860 {
2861         int status;
2862
2863         loopnest++;
2864         status = 0;
2865         flags &= EV_TESTED;
2866         for (;;) {
2867                 int i;
2868
2869                 evaltree(n->nbinary.ch1, EV_TESTED);
2870                 if (evalskip) {
2871 skipping:         if (evalskip == SKIPCONT && --skipcount <= 0) {
2872                                 evalskip = 0;
2873                                 continue;
2874                         }
2875                         if (evalskip == SKIPBREAK && --skipcount <= 0)
2876                                 evalskip = 0;
2877                         break;
2878                 }
2879                 i = exitstatus;
2880                 if (n->type != NWHILE)
2881                         i = !i;
2882                 if (i != 0)
2883                         break;
2884                 evaltree(n->nbinary.ch2, flags);
2885                 status = exitstatus;
2886                 if (evalskip)
2887                         goto skipping;
2888         }
2889         loopnest--;
2890         exitstatus = status;
2891 }
2892
2893
2894
2895 static void
2896 evalfor(union node *n, int flags)
2897 {
2898         struct arglist arglist;
2899         union node *argp;
2900         struct strlist *sp;
2901         struct stackmark smark;
2902
2903         setstackmark(&smark);
2904         arglist.lastp = &arglist.list;
2905         for (argp = n->nfor.args ; argp ; argp = argp->narg.next) {
2906                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE | EXP_RECORD);
2907                 /* XXX */
2908                 if (evalskip)
2909                         goto out;
2910         }
2911         *arglist.lastp = NULL;
2912
2913         exitstatus = 0;
2914         loopnest++;
2915         flags &= EV_TESTED;
2916         for (sp = arglist.list ; sp ; sp = sp->next) {
2917                 setvar(n->nfor.var, sp->text, 0);
2918                 evaltree(n->nfor.body, flags);
2919                 if (evalskip) {
2920                         if (evalskip == SKIPCONT && --skipcount <= 0) {
2921                                 evalskip = 0;
2922                                 continue;
2923                         }
2924                         if (evalskip == SKIPBREAK && --skipcount <= 0)
2925                                 evalskip = 0;
2926                         break;
2927                 }
2928         }
2929         loopnest--;
2930 out:
2931         popstackmark(&smark);
2932 }
2933
2934
2935
2936 static void
2937 evalcase(union node *n, int flags)
2938 {
2939         union node *cp;
2940         union node *patp;
2941         struct arglist arglist;
2942         struct stackmark smark;
2943
2944         setstackmark(&smark);
2945         arglist.lastp = &arglist.list;
2946         expandarg(n->ncase.expr, &arglist, EXP_TILDE);
2947         exitstatus = 0;
2948         for (cp = n->ncase.cases ; cp && evalskip == 0 ; cp = cp->nclist.next) {
2949                 for (patp = cp->nclist.pattern ; patp ; patp = patp->narg.next) {
2950                         if (casematch(patp, arglist.list->text)) {
2951                                 if (evalskip == 0) {
2952                                         evaltree(cp->nclist.body, flags);
2953                                 }
2954                                 goto out;
2955                         }
2956                 }
2957         }
2958 out:
2959         popstackmark(&smark);
2960 }
2961
2962
2963
2964 /*
2965  * Kick off a subshell to evaluate a tree.
2966  */
2967
2968 static void
2969 evalsubshell(union node *n, int flags)
2970 {
2971         struct job *jp;
2972         int backgnd = (n->type == NBACKGND);
2973         int status;
2974
2975         expredir(n->nredir.redirect);
2976         if (!backgnd && flags & EV_EXIT && !trap[0])
2977                 goto nofork;
2978         INTOFF;
2979         jp = makejob(n, 1);
2980         if (forkshell(jp, n, backgnd) == 0) {
2981                 INTON;
2982                 flags |= EV_EXIT;
2983                 if (backgnd)
2984                         flags &=~ EV_TESTED;
2985 nofork:
2986                 redirect(n->nredir.redirect, 0);
2987                 evaltreenr(n->nredir.n, flags);
2988                 /* never returns */
2989         }
2990         status = 0;
2991         if (! backgnd)
2992                 status = waitforjob(jp);
2993         exitstatus = status;
2994         INTON;
2995 }
2996
2997
2998
2999 /*
3000  * Compute the names of the files in a redirection list.
3001  */
3002
3003 static void
3004 expredir(union node *n)
3005 {
3006         union node *redir;
3007
3008         for (redir = n ; redir ; redir = redir->nfile.next) {
3009                 struct arglist fn;
3010                 fn.lastp = &fn.list;
3011                 switch (redir->type) {
3012                 case NFROMTO:
3013                 case NFROM:
3014                 case NTO:
3015                 case NCLOBBER:
3016                 case NAPPEND:
3017                         expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
3018                         redir->nfile.expfname = fn.list->text;
3019                         break;
3020                 case NFROMFD:
3021                 case NTOFD:
3022                         if (redir->ndup.vname) {
3023                                 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
3024                                 fixredir(redir, fn.list->text, 1);
3025                         }
3026                         break;
3027                 }
3028         }
3029 }
3030
3031
3032
3033 /*
3034  * Evaluate a pipeline.  All the processes in the pipeline are children
3035  * of the process creating the pipeline.  (This differs from some versions
3036  * of the shell, which make the last process in a pipeline the parent
3037  * of all the rest.)
3038  */
3039
3040 static void
3041 evalpipe(union node *n, int flags)
3042 {
3043         struct job *jp;
3044         struct nodelist *lp;
3045         int pipelen;
3046         int prevfd;
3047         int pip[2];
3048
3049         TRACE(("evalpipe(0x%lx) called\n", (long)n));
3050         pipelen = 0;
3051         for (lp = n->npipe.cmdlist ; lp ; lp = lp->next)
3052                 pipelen++;
3053         flags |= EV_EXIT;
3054         INTOFF;
3055         jp = makejob(n, pipelen);
3056         prevfd = -1;
3057         for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
3058                 prehash(lp->n);
3059                 pip[1] = -1;
3060                 if (lp->next) {
3061                         if (pipe(pip) < 0) {
3062                                 close(prevfd);
3063                                 error("Pipe call failed");
3064                         }
3065                 }
3066                 if (forkshell(jp, lp->n, n->npipe.backgnd) == 0) {
3067                         INTON;
3068                         if (pip[1] >= 0) {
3069                                 close(pip[0]);
3070                         }
3071                         if (prevfd > 0) {
3072                                 dup2(prevfd, 0);
3073                                 close(prevfd);
3074                         }
3075                         if (pip[1] > 1) {
3076                                 dup2(pip[1], 1);
3077                                 close(pip[1]);
3078                         }
3079                         evaltreenr(lp->n, flags);
3080                         /* never returns */
3081                 }
3082                 if (prevfd >= 0)
3083                         close(prevfd);
3084                 prevfd = pip[0];
3085                 close(pip[1]);
3086         }
3087         if (n->npipe.backgnd == 0) {
3088                 exitstatus = waitforjob(jp);
3089                 TRACE(("evalpipe:  job done exit status %d\n", exitstatus));
3090         }
3091         INTON;
3092 }
3093
3094
3095
3096 /*
3097  * Execute a command inside back quotes.  If it's a builtin command, we
3098  * want to save its output in a block obtained from malloc.  Otherwise
3099  * we fork off a subprocess and get the output of the command via a pipe.
3100  * Should be called with interrupts off.
3101  */
3102
3103 static void
3104 evalbackcmd(union node *n, struct backcmd *result)
3105 {
3106         int saveherefd;
3107
3108         result->fd = -1;
3109         result->buf = NULL;
3110         result->nleft = 0;
3111         result->jp = NULL;
3112         if (n == NULL) {
3113                 goto out;
3114         }
3115
3116         saveherefd = herefd;
3117         herefd = -1;
3118
3119         {
3120                 int pip[2];
3121                 struct job *jp;
3122
3123                 if (pipe(pip) < 0)
3124                         error("Pipe call failed");
3125                 jp = makejob(n, 1);
3126                 if (forkshell(jp, n, FORK_NOJOB) == 0) {
3127                         FORCEINTON;
3128                         close(pip[0]);
3129                         if (pip[1] != 1) {
3130                                 close(1);
3131                                 copyfd(pip[1], 1);
3132                                 close(pip[1]);
3133                         }
3134                         eflag = 0;
3135                         evaltreenr(n, EV_EXIT);
3136                         /* NOTREACHED */
3137                 }
3138                 close(pip[1]);
3139                 result->fd = pip[0];
3140                 result->jp = jp;
3141         }
3142         herefd = saveherefd;
3143 out:
3144         TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
3145                 result->fd, result->buf, result->nleft, result->jp));
3146 }
3147
3148 #ifdef CONFIG_ASH_CMDCMD
3149 static inline char **
3150 parse_command_args(char **argv, const char **path)
3151 {
3152         char *cp, c;
3153
3154         for (;;) {
3155                 cp = *++argv;
3156                 if (!cp)
3157                         return 0;
3158                 if (*cp++ != '-')
3159                         break;
3160                 if (!(c = *cp++))
3161                         break;
3162                 if (c == '-' && !*cp) {
3163                         argv++;
3164                         break;
3165                 }
3166                 do {
3167                         switch (c) {
3168                         case 'p':
3169                                 *path = defpath;
3170                                 break;
3171                         default:
3172                                 /* run 'typecmd' for other options */
3173                                 return 0;
3174                         }
3175                 } while ((c = *cp++));
3176         }
3177         return argv;
3178 }
3179 #endif
3180
3181
3182
3183 /*
3184  * Execute a simple command.
3185  */
3186
3187 static void
3188 evalcommand(union node *cmd, int flags)
3189 {
3190         struct stackmark smark;
3191         union node *argp;
3192         struct arglist arglist;
3193         struct arglist varlist;
3194         char **argv;
3195         int argc;
3196         const struct strlist *sp;
3197         struct cmdentry cmdentry;
3198         struct job *jp;
3199         char *lastarg;
3200         const char *path;
3201         int spclbltin;
3202         int cmd_is_exec;
3203         int status;
3204         char **nargv;
3205
3206         /* First expand the arguments. */
3207         TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
3208         setstackmark(&smark);
3209         back_exitstatus = 0;
3210
3211         cmdentry.cmdtype = CMDBUILTIN;
3212         cmdentry.u.cmd = &bltin;
3213         varlist.lastp = &varlist.list;
3214         *varlist.lastp = NULL;
3215         arglist.lastp = &arglist.list;
3216         *arglist.lastp = NULL;
3217
3218         argc = 0;
3219         for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
3220                 struct strlist **spp;
3221
3222                 spp = arglist.lastp;
3223                 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
3224                 for (sp = *spp; sp; sp = sp->next)
3225                         argc++;
3226         }
3227
3228         argv = nargv = stalloc(sizeof (char *) * (argc + 1));
3229         for (sp = arglist.list ; sp ; sp = sp->next) {
3230                 TRACE(("evalcommand arg: %s\n", sp->text));
3231                 *nargv++ = sp->text;
3232         }
3233         *nargv = NULL;
3234
3235         lastarg = NULL;
3236         if (iflag && funcnest == 0 && argc > 0)
3237                 lastarg = nargv[-1];
3238
3239         preverrout_fd = 2;
3240         expredir(cmd->ncmd.redirect);
3241         status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH|REDIR_SAVEFD2);
3242
3243         path = vpath.text;
3244         for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
3245                 struct strlist **spp;
3246                 char *p;
3247
3248                 spp = varlist.lastp;
3249                 expandarg(argp, &varlist, EXP_VARTILDE);
3250
3251                 /*
3252                  * Modify the command lookup path, if a PATH= assignment
3253                  * is present
3254                  */
3255                 p = (*spp)->text;
3256                 if (varequal(p, path))
3257                         path = p;
3258         }
3259
3260         /* Print the command if xflag is set. */
3261         if (xflag) {
3262                 int n;
3263                 const char *p = " %s";
3264
3265                 p++;
3266                 dprintf(preverrout_fd, p, ps4val());
3267
3268                 sp = varlist.list;
3269                 for(n = 0; n < 2; n++) {
3270                         while (sp) {
3271                                 dprintf(preverrout_fd, p, sp->text);
3272                                 sp = sp->next;
3273                                 if(*p == '%') {
3274                                         p--;
3275                                 }
3276                         }
3277                         sp = arglist.list;
3278                 }
3279                 xwrite(preverrout_fd, "\n", 1);
3280         }
3281
3282         cmd_is_exec = 0;
3283         spclbltin = -1;
3284
3285         /* Now locate the command. */
3286         if (argc) {
3287                 const char *oldpath;
3288                 int cmd_flag = DO_ERR;
3289
3290                 path += 5;
3291                 oldpath = path;
3292                 for (;;) {
3293                         find_command(argv[0], &cmdentry, cmd_flag, path);
3294                         if (cmdentry.cmdtype == CMDUNKNOWN) {
3295                                 status = 127;
3296                                 flushout(stderr);
3297                                 goto bail;
3298                         }
3299
3300                         /* implement bltin and command here */
3301                         if (cmdentry.cmdtype != CMDBUILTIN)
3302                                 break;
3303                         if (spclbltin < 0)
3304                                 spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
3305                         if (cmdentry.u.cmd == EXECCMD)
3306                                 cmd_is_exec++;
3307 #ifdef CONFIG_ASH_CMDCMD
3308                         if (cmdentry.u.cmd == COMMANDCMD) {
3309
3310                                 path = oldpath;
3311                                 nargv = parse_command_args(argv, &path);
3312                                 if (!nargv)
3313                                         break;
3314                                 argc -= nargv - argv;
3315                                 argv = nargv;
3316                                 cmd_flag |= DO_NOFUNC;
3317                         } else
3318 #endif
3319                                 break;
3320                 }
3321         }
3322
3323         if (status) {
3324                 /* We have a redirection error. */
3325                 if (spclbltin > 0)
3326                         exraise(EXERROR);
3327 bail:
3328                 exitstatus = status;
3329                 goto out;
3330         }
3331
3332         /* Execute the command. */
3333         switch (cmdentry.cmdtype) {
3334         default:
3335                 /* Fork off a child process if necessary. */
3336                 if (!(flags & EV_EXIT) || trap[0]) {
3337                         INTOFF;
3338                         jp = makejob(cmd, 1);
3339                         if (forkshell(jp, cmd, FORK_FG) != 0) {
3340                                 exitstatus = waitforjob(jp);
3341                                 INTON;
3342                                 break;
3343                         }
3344                         FORCEINTON;
3345                 }
3346                 listsetvar(varlist.list, VEXPORT|VSTACK);
3347                 shellexec(argv, path, cmdentry.u.index);
3348                 /* NOTREACHED */
3349
3350         case CMDBUILTIN:
3351                 cmdenviron = varlist.list;
3352                 if (cmdenviron) {
3353                         struct strlist *list = cmdenviron;
3354                         int i = VNOSET;
3355                         if (spclbltin > 0 || argc == 0) {
3356                                 i = 0;
3357                                 if (cmd_is_exec && argc > 1)
3358                                         i = VEXPORT;
3359                         }
3360                         listsetvar(list, i);
3361                 }
3362                 if (evalbltin(cmdentry.u.cmd, argc, argv)) {
3363                         int exit_status;
3364                         int i, j;
3365
3366                         i = exception;
3367                         if (i == EXEXIT)
3368                                 goto raise;
3369
3370                         exit_status = 2;
3371                         j = 0;
3372                         if (i == EXINT)
3373                                 j = SIGINT;
3374                         if (i == EXSIG)
3375                                 j = pendingsigs;
3376                         if (j)
3377                                 exit_status = j + 128;
3378                         exitstatus = exit_status;
3379
3380                         if (i == EXINT || spclbltin > 0) {
3381 raise:
3382                                 longjmp(handler->loc, 1);
3383                         }
3384                         FORCEINTON;
3385                 }
3386                 break;
3387
3388         case CMDFUNCTION:
3389                 listsetvar(varlist.list, 0);
3390                 if (evalfun(cmdentry.u.func, argc, argv, flags))
3391                         goto raise;
3392                 break;
3393         }
3394
3395 out:
3396         popredir(cmd_is_exec);
3397         if (lastarg)
3398                 /* dsl: I think this is intended to be used to support
3399                  * '_' in 'vi' command mode during line editing...
3400                  * However I implemented that within libedit itself.
3401                  */
3402                 setvar("_", lastarg, 0);
3403         popstackmark(&smark);
3404 }
3405
3406 static int
3407 evalbltin(const struct builtincmd *cmd, int argc, char **argv) {
3408         char *volatile savecmdname;
3409         struct jmploc *volatile savehandler;
3410         struct jmploc jmploc;
3411         int i;
3412
3413         savecmdname = commandname;
3414         if ((i = setjmp(jmploc.loc)))
3415                 goto cmddone;
3416         savehandler = handler;
3417         handler = &jmploc;
3418         commandname = argv[0];
3419         argptr = argv + 1;
3420         optptr = NULL;                  /* initialize nextopt */
3421         exitstatus = (*cmd->builtin)(argc, argv);
3422         flushall();
3423 cmddone:
3424         exitstatus |= ferror(stdout);
3425         commandname = savecmdname;
3426         exsig = 0;
3427         handler = savehandler;
3428
3429         return i;
3430 }
3431
3432 static int
3433 evalfun(struct funcnode *func, int argc, char **argv, int flags)
3434 {
3435         volatile struct shparam saveparam;
3436         struct localvar *volatile savelocalvars;
3437         struct jmploc *volatile savehandler;
3438         struct jmploc jmploc;
3439         int e;
3440
3441         saveparam = shellparam;
3442         savelocalvars = localvars;
3443         if ((e = setjmp(jmploc.loc))) {
3444                 goto funcdone;
3445         }
3446         INTOFF;
3447         savehandler = handler;
3448         handler = &jmploc;
3449         localvars = NULL;
3450         shellparam.malloc = 0;
3451         func->count++;
3452         INTON;
3453         shellparam.nparam = argc - 1;
3454         shellparam.p = argv + 1;
3455 #ifdef CONFIG_ASH_GETOPTS
3456         shellparam.optind = 1;
3457         shellparam.optoff = -1;
3458 #endif
3459         funcnest++;
3460         evaltree(&func->n, flags & EV_TESTED);
3461         funcnest--;
3462 funcdone:
3463         INTOFF;
3464         freefunc(func);
3465         poplocalvars();
3466         localvars = savelocalvars;
3467         freeparam(&shellparam);
3468         shellparam = saveparam;
3469         handler = savehandler;
3470         INTON;
3471         if (evalskip == SKIPFUNC) {
3472                 evalskip = 0;
3473                 skipcount = 0;
3474         }
3475         return e;
3476 }
3477
3478
3479 /*
3480  * Search for a command.  This is called before we fork so that the
3481  * location of the command will be available in the parent as well as
3482  * the child.
3483  */
3484
3485 static void
3486 prehash(union node *n)
3487 {
3488         struct cmdentry entry;
3489
3490         if (n->type == NCMD && n->ncmd.args)
3491                 find_command(n->ncmd.args->narg.text, &entry, 0, pathval());
3492 }
3493
3494
3495
3496 /*
3497  * Builtin commands.  Builtin commands whose functions are closely
3498  * tied to evaluation are implemented here.
3499  */
3500
3501 /*
3502  * No command given.
3503  */
3504
3505 static int
3506 bltincmd(int argc, char **argv)
3507 {
3508         /*
3509          * Preserve exitstatus of a previous possible redirection
3510          * as POSIX mandates
3511          */
3512         return back_exitstatus;
3513 }
3514
3515
3516 /*
3517  * Handle break and continue commands.  Break, continue, and return are
3518  * all handled by setting the evalskip flag.  The evaluation routines
3519  * above all check this flag, and if it is set they start skipping
3520  * commands rather than executing them.  The variable skipcount is
3521  * the number of loops to break/continue, or the number of function
3522  * levels to return.  (The latter is always 1.)  It should probably
3523  * be an error to break out of more loops than exist, but it isn't
3524  * in the standard shell so we don't make it one here.
3525  */
3526
3527 static int
3528 breakcmd(int argc, char **argv)
3529 {
3530         int n = argc > 1 ? number(argv[1]) : 1;
3531
3532         if (n <= 0)
3533                 error(illnum, argv[1]);
3534         if (n > loopnest)
3535                 n = loopnest;
3536         if (n > 0) {
3537                 evalskip = (**argv == 'c')? SKIPCONT : SKIPBREAK;
3538                 skipcount = n;
3539         }
3540         return 0;
3541 }
3542
3543
3544 /*
3545  * The return command.
3546  */
3547
3548 static int
3549 returncmd(int argc, char **argv)
3550 {
3551         int ret = argc > 1 ? number(argv[1]) : exitstatus;
3552
3553         if (funcnest) {
3554                 evalskip = SKIPFUNC;
3555                 skipcount = 1;
3556                 return ret;
3557         }
3558         else {
3559                 /* Do what ksh does; skip the rest of the file */
3560                 evalskip = SKIPFILE;
3561                 skipcount = 1;
3562                 return ret;
3563         }
3564 }
3565
3566
3567 static int
3568 falsecmd(int argc, char **argv)
3569 {
3570         return 1;
3571 }
3572
3573
3574 static int
3575 truecmd(int argc, char **argv)
3576 {
3577         return 0;
3578 }
3579
3580
3581 static int
3582 execcmd(int argc, char **argv)
3583 {
3584         if (argc > 1) {
3585                 iflag = 0;              /* exit on error */
3586                 mflag = 0;
3587                 optschanged();
3588                 shellexec(argv + 1, pathval(), 0);
3589         }
3590         return 0;
3591 }
3592
3593
3594 /*      $NetBSD: exec.c,v 1.35 2003/01/22 20:36:04 dsl Exp $    */
3595
3596 /*
3597  * When commands are first encountered, they are entered in a hash table.
3598  * This ensures that a full path search will not have to be done for them
3599  * on each invocation.
3600  *
3601  * We should investigate converting to a linear search, even though that
3602  * would make the command name "hash" a misnomer.
3603  */
3604
3605 #define CMDTABLESIZE 31         /* should be prime */
3606 #define ARB 1                   /* actual size determined at run time */
3607
3608
3609
3610 struct tblentry {
3611         struct tblentry *next;  /* next entry in hash chain */
3612         union param param;      /* definition of builtin function */
3613         short cmdtype;          /* index identifying command */
3614         char rehash;            /* if set, cd done since entry created */
3615         char cmdname[ARB];      /* name of command */
3616 };
3617
3618
3619 static struct tblentry *cmdtable[CMDTABLESIZE];
3620 static int builtinloc = -1;             /* index in path of %builtin, or -1 */
3621
3622
3623 static void tryexec(char *, char **, char **);
3624 static void clearcmdentry(int);
3625 static struct tblentry *cmdlookup(const char *, int);
3626 static void delete_cmd_entry(void);
3627
3628
3629 /*
3630  * Exec a program.  Never returns.  If you change this routine, you may
3631  * have to change the find_command routine as well.
3632  */
3633
3634 static void
3635 shellexec(char **argv, const char *path, int idx)
3636 {
3637         char *cmdname;
3638         int e;
3639         char **envp;
3640
3641         clearredir(1);
3642         envp = environment();
3643         if (strchr(argv[0], '/') != NULL
3644 #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
3645                 || find_applet_by_name(argv[0])
3646 #endif
3647                                                 ) {
3648                 tryexec(argv[0], argv, envp);
3649                 e = errno;
3650         } else {
3651                 e = ENOENT;
3652                 while ((cmdname = padvance(&path, argv[0])) != NULL) {
3653                         if (--idx < 0 && pathopt == NULL) {
3654                                 tryexec(cmdname, argv, envp);
3655                                 if (errno != ENOENT && errno != ENOTDIR)
3656                                         e = errno;
3657                         }
3658                         stunalloc(cmdname);
3659                 }
3660         }
3661
3662         /* Map to POSIX errors */
3663         switch (e) {
3664         case EACCES:
3665                 exerrno = 126;
3666                 break;
3667         case ENOENT:
3668                 exerrno = 127;
3669                 break;
3670         default:
3671                 exerrno = 2;
3672                 break;
3673         }
3674         TRACE(("shellexec failed for %s, errno %d, suppressint %d\n",
3675                 argv[0], e, suppressint ));
3676         exerror(EXEXEC, "%s: %s", argv[0], errmsg(e, E_EXEC));
3677         /* NOTREACHED */
3678 }
3679
3680
3681 static void
3682 tryexec(char *cmd, char **argv, char **envp)
3683 {
3684         int repeated = 0;
3685 #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
3686         int flg_bb = 0;
3687         char *name = cmd;
3688
3689 #ifdef CONFIG_FEATURE_SH_APPLETS_ALWAYS_WIN
3690         name = bb_get_last_path_component(name);
3691         if(find_applet_by_name(name) != NULL)
3692                 flg_bb = 1;
3693 #else
3694         if(strchr(name, '/') == NULL && find_applet_by_name(name) != NULL) {
3695                 flg_bb = 1;
3696         }
3697 #endif
3698         if(flg_bb) {
3699                 char **ap;
3700                 char **new;
3701
3702                 *argv = name;
3703                 if(strcmp(name, "busybox")) {
3704                         for (ap = argv; *ap; ap++);
3705                         ap = new = xmalloc((ap - argv + 2) * sizeof(char *));
3706                         *ap++ = cmd = "/bin/busybox";
3707                         while ((*ap++ = *argv++));
3708                         argv = new;
3709                         repeated++;
3710                 } else {
3711                         cmd = "/bin/busybox";
3712                 }
3713         }
3714 #endif
3715
3716 repeat:
3717 #ifdef SYSV
3718         do {
3719                 execve(cmd, argv, envp);
3720         } while (errno == EINTR);
3721 #else
3722         execve(cmd, argv, envp);
3723 #endif
3724         if (repeated++) {
3725                 ckfree(argv);
3726         } else if (errno == ENOEXEC) {
3727                 char **ap;
3728                 char **new;
3729
3730                 for (ap = argv; *ap; ap++)
3731                         ;
3732                 ap = new = ckmalloc((ap - argv + 2) * sizeof(char *));
3733                 ap[1] = cmd;
3734                 *ap = cmd = (char *)DEFAULT_SHELL;
3735                 ap += 2;
3736                 argv++;
3737                 while ((*ap++ = *argv++))
3738                         ;
3739                 argv = new;
3740                 goto repeat;
3741         }
3742 }
3743
3744
3745
3746 /*
3747  * Do a path search.  The variable path (passed by reference) should be
3748  * set to the start of the path before the first call; padvance will update
3749  * this value as it proceeds.  Successive calls to padvance will return
3750  * the possible path expansions in sequence.  If an option (indicated by
3751  * a percent sign) appears in the path entry then the global variable
3752  * pathopt will be set to point to it; otherwise pathopt will be set to
3753  * NULL.
3754  */
3755
3756 static char *
3757 padvance(const char **path, const char *name)
3758 {
3759         const char *p;
3760         char *q;
3761         const char *start;
3762         size_t len;
3763
3764         if (*path == NULL)
3765                 return NULL;
3766         start = *path;
3767         for (p = start ; *p && *p != ':' && *p != '%' ; p++);
3768         len = p - start + strlen(name) + 2;     /* "2" is for '/' and '\0' */
3769         while (stackblocksize() < len)
3770                 growstackblock();
3771         q = stackblock();
3772         if (p != start) {
3773                 memcpy(q, start, p - start);
3774                 q += p - start;
3775                 *q++ = '/';
3776         }
3777         strcpy(q, name);
3778         pathopt = NULL;
3779         if (*p == '%') {
3780                 pathopt = ++p;
3781                 while (*p && *p != ':')  p++;
3782         }
3783         if (*p == ':')
3784                 *path = p + 1;
3785         else
3786                 *path = NULL;
3787         return stalloc(len);
3788 }
3789
3790
3791 /*** Command hashing code ***/
3792
3793 static void
3794 printentry(struct tblentry *cmdp)
3795 {
3796         int idx;
3797         const char *path;
3798         char *name;
3799
3800         idx = cmdp->param.index;
3801         path = pathval();
3802         do {
3803                 name = padvance(&path, cmdp->cmdname);
3804                 stunalloc(name);
3805         } while (--idx >= 0);
3806         out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
3807 }
3808
3809
3810 static int
3811 hashcmd(int argc, char **argv)
3812 {
3813         struct tblentry **pp;
3814         struct tblentry *cmdp;
3815         int c;
3816         struct cmdentry entry;
3817         char *name;
3818
3819         while ((c = nextopt("r")) != '\0') {
3820                 clearcmdentry(0);
3821                 return 0;
3822         }
3823         if (*argptr == NULL) {
3824                 for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
3825                         for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
3826                                 if (cmdp->cmdtype == CMDNORMAL)
3827                                         printentry(cmdp);
3828                         }
3829                 }
3830                 return 0;
3831         }
3832         c = 0;
3833         while ((name = *argptr) != NULL) {
3834                 if ((cmdp = cmdlookup(name, 0)) != NULL
3835                  && (cmdp->cmdtype == CMDNORMAL
3836                      || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0)))
3837                         delete_cmd_entry();
3838                 find_command(name, &entry, DO_ERR, pathval());
3839                 if (entry.cmdtype == CMDUNKNOWN)
3840                         c = 1;
3841                 argptr++;
3842         }
3843         return c;
3844 }
3845
3846
3847 /*
3848  * Resolve a command name.  If you change this routine, you may have to
3849  * change the shellexec routine as well.
3850  */
3851
3852 static void
3853 find_command(char *name, struct cmdentry *entry, int act, const char *path)
3854 {
3855         struct tblentry *cmdp;
3856         int idx;
3857         int prev;
3858         char *fullname;
3859         struct stat statb;
3860         int e;
3861         int updatetbl;
3862         struct builtincmd *bcmd;
3863
3864         /* If name contains a slash, don't use PATH or hash table */
3865         if (strchr(name, '/') != NULL) {
3866                 entry->u.index = -1;
3867                 if (act & DO_ABS) {
3868                         while (stat(name, &statb) < 0) {
3869 #ifdef SYSV
3870                                 if (errno == EINTR)
3871                                         continue;
3872 #endif
3873                                 entry->cmdtype = CMDUNKNOWN;
3874                                 return;
3875                         }
3876                 }
3877                 entry->cmdtype = CMDNORMAL;
3878                 return;
3879         }
3880
3881 #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
3882         if (find_applet_by_name(name)) {
3883                 entry->cmdtype = CMDNORMAL;
3884                 entry->u.index = -1;
3885                 return;
3886         }
3887 #endif
3888
3889         updatetbl = (path == pathval());
3890         if (!updatetbl) {
3891                 act |= DO_ALTPATH;
3892                 if (strstr(path, "%builtin") != NULL)
3893                         act |= DO_ALTBLTIN;
3894         }
3895
3896         /* If name is in the table, check answer will be ok */
3897         if ((cmdp = cmdlookup(name, 0)) != NULL) {
3898                 int bit;
3899
3900                 switch (cmdp->cmdtype) {
3901                 default:
3902 #if DEBUG
3903                         abort();
3904 #endif
3905                 case CMDNORMAL:
3906                         bit = DO_ALTPATH;
3907                         break;
3908                 case CMDFUNCTION:
3909                         bit = DO_NOFUNC;
3910                         break;
3911                 case CMDBUILTIN:
3912                         bit = DO_ALTBLTIN;
3913                         break;
3914                 }
3915                 if (act & bit) {
3916                         updatetbl = 0;
3917                         cmdp = NULL;
3918                 } else if (cmdp->rehash == 0)
3919                         /* if not invalidated by cd, we're done */
3920                         goto success;
3921         }
3922
3923         /* If %builtin not in path, check for builtin next */
3924         bcmd = find_builtin(name);
3925         if (bcmd && (IS_BUILTIN_REGULAR(bcmd) || (
3926                 act & DO_ALTPATH ? !(act & DO_ALTBLTIN) : builtinloc <= 0
3927         )))
3928                 goto builtin_success;
3929
3930         /* We have to search path. */
3931         prev = -1;              /* where to start */
3932         if (cmdp && cmdp->rehash) {     /* doing a rehash */
3933                 if (cmdp->cmdtype == CMDBUILTIN)
3934                         prev = builtinloc;
3935                 else
3936                         prev = cmdp->param.index;
3937         }
3938
3939         e = ENOENT;
3940         idx = -1;
3941 loop:
3942         while ((fullname = padvance(&path, name)) != NULL) {
3943                 stunalloc(fullname);
3944                 idx++;
3945                 if (pathopt) {
3946                         if (prefix(pathopt, "builtin")) {
3947                                 if (bcmd)
3948                                         goto builtin_success;
3949                                 continue;
3950                         } else if (!(act & DO_NOFUNC) &&
3951                                    prefix(pathopt, "func")) {
3952                                 /* handled below */
3953                         } else {
3954                                 /* ignore unimplemented options */
3955                                 continue;
3956                         }
3957                 }
3958                 /* if rehash, don't redo absolute path names */
3959                 if (fullname[0] == '/' && idx <= prev) {
3960                         if (idx < prev)
3961                                 continue;
3962                         TRACE(("searchexec \"%s\": no change\n", name));
3963                         goto success;
3964                 }
3965                 while (stat(fullname, &statb) < 0) {
3966 #ifdef SYSV
3967                         if (errno == EINTR)
3968                                 continue;
3969 #endif
3970                         if (errno != ENOENT && errno != ENOTDIR)
3971                                 e = errno;
3972                         goto loop;
3973                 }
3974                 e = EACCES;     /* if we fail, this will be the error */
3975                 if (!S_ISREG(statb.st_mode))
3976                         continue;
3977                 if (pathopt) {          /* this is a %func directory */
3978                         stalloc(strlen(fullname) + 1);
3979                         readcmdfile(fullname);
3980                         if ((cmdp = cmdlookup(name, 0)) == NULL ||
3981                             cmdp->cmdtype != CMDFUNCTION)
3982                                 error("%s not defined in %s", name, fullname);
3983                         stunalloc(fullname);
3984                         goto success;
3985                 }
3986                 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
3987                 if (!updatetbl) {
3988                         entry->cmdtype = CMDNORMAL;
3989                         entry->u.index = idx;
3990                         return;
3991                 }
3992                 INTOFF;
3993                 cmdp = cmdlookup(name, 1);
3994                 cmdp->cmdtype = CMDNORMAL;
3995                 cmdp->param.index = idx;
3996                 INTON;
3997                 goto success;
3998         }
3999
4000         /* We failed.  If there was an entry for this command, delete it */
4001         if (cmdp && updatetbl)
4002                 delete_cmd_entry();
4003         if (act & DO_ERR)
4004                 sh_warnx("%s: %s", name, errmsg(e, E_EXEC));
4005         entry->cmdtype = CMDUNKNOWN;
4006         return;
4007
4008 builtin_success:
4009         if (!updatetbl) {
4010                 entry->cmdtype = CMDBUILTIN;
4011                 entry->u.cmd = bcmd;
4012                 return;
4013         }
4014         INTOFF;
4015         cmdp = cmdlookup(name, 1);
4016         cmdp->cmdtype = CMDBUILTIN;
4017         cmdp->param.cmd = bcmd;
4018         INTON;
4019 success:
4020         cmdp->rehash = 0;
4021         entry->cmdtype = cmdp->cmdtype;
4022         entry->u = cmdp->param;
4023 }
4024
4025
4026 /*
4027  * Wrapper around strcmp for qsort/bsearch/...
4028  */
4029 static int pstrcmp(const void *a, const void *b)
4030 {
4031         return strcmp((const char *) a, (*(const char *const *) b) + 1);
4032 }
4033
4034 /*
4035  * Search the table of builtin commands.
4036  */
4037
4038 static struct builtincmd *
4039 find_builtin(const char *name)
4040 {
4041         struct builtincmd *bp;
4042
4043         bp = bsearch(
4044                 name, builtincmd, NUMBUILTINS, sizeof(struct builtincmd),
4045                 pstrcmp
4046         );
4047         return bp;
4048 }
4049
4050
4051
4052 /*
4053  * Called when a cd is done.  Marks all commands so the next time they
4054  * are executed they will be rehashed.
4055  */
4056
4057 static void
4058 hashcd(void)
4059 {
4060         struct tblentry **pp;
4061         struct tblentry *cmdp;
4062
4063         for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
4064                 for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
4065                         if (cmdp->cmdtype == CMDNORMAL || (
4066                                 cmdp->cmdtype == CMDBUILTIN &&
4067                                 !(IS_BUILTIN_REGULAR(cmdp->param.cmd)) &&
4068                                 builtinloc > 0
4069                         ))
4070                                 cmdp->rehash = 1;
4071                 }
4072         }
4073 }
4074
4075
4076
4077 /*
4078  * Fix command hash table when PATH changed.
4079  * Called before PATH is changed.  The argument is the new value of PATH;
4080  * pathval() still returns the old value at this point.
4081  * Called with interrupts off.
4082  */
4083
4084 static void
4085 changepath(const char *newval)
4086 {
4087         const char *old, *new;
4088         int idx;
4089         int firstchange;
4090         int idx_bltin;
4091
4092         old = pathval();
4093         new = newval;
4094         firstchange = 9999;     /* assume no change */
4095         idx = 0;
4096         idx_bltin = -1;
4097         for (;;) {
4098                 if (*old != *new) {
4099                         firstchange = idx;
4100                         if ((*old == '\0' && *new == ':')
4101                          || (*old == ':' && *new == '\0'))
4102                                 firstchange++;
4103                         old = new;      /* ignore subsequent differences */
4104                 }
4105                 if (*new == '\0')
4106                         break;
4107                 if (*new == '%' && idx_bltin < 0 && prefix(new + 1, "builtin"))
4108                         idx_bltin = idx;
4109                 if (*new == ':') {
4110                         idx++;
4111                 }
4112                 new++, old++;
4113         }
4114         if (builtinloc < 0 && idx_bltin >= 0)
4115                 builtinloc = idx_bltin;             /* zap builtins */
4116         if (builtinloc >= 0 && idx_bltin < 0)
4117                 firstchange = 0;
4118         clearcmdentry(firstchange);
4119         builtinloc = idx_bltin;
4120 }
4121
4122
4123 /*
4124  * Clear out command entries.  The argument specifies the first entry in
4125  * PATH which has changed.
4126  */
4127
4128 static void
4129 clearcmdentry(int firstchange)
4130 {
4131         struct tblentry **tblp;
4132         struct tblentry **pp;
4133         struct tblentry *cmdp;
4134
4135         INTOFF;
4136         for (tblp = cmdtable ; tblp < &cmdtable[CMDTABLESIZE] ; tblp++) {
4137                 pp = tblp;
4138                 while ((cmdp = *pp) != NULL) {
4139                         if ((cmdp->cmdtype == CMDNORMAL &&
4140                              cmdp->param.index >= firstchange)
4141                          || (cmdp->cmdtype == CMDBUILTIN &&
4142                              builtinloc >= firstchange)) {
4143                                 *pp = cmdp->next;
4144                                 ckfree(cmdp);
4145                         } else {
4146                                 pp = &cmdp->next;
4147                         }
4148                 }
4149         }
4150         INTON;
4151 }
4152
4153
4154
4155 /*
4156  * Locate a command in the command hash table.  If "add" is nonzero,
4157  * add the command to the table if it is not already present.  The
4158  * variable "lastcmdentry" is set to point to the address of the link
4159  * pointing to the entry, so that delete_cmd_entry can delete the
4160  * entry.
4161  *
4162  * Interrupts must be off if called with add != 0.
4163  */
4164
4165 static struct tblentry **lastcmdentry;
4166
4167
4168 static struct tblentry *
4169 cmdlookup(const char *name, int add)
4170 {
4171         unsigned int hashval;
4172         const char *p;
4173         struct tblentry *cmdp;
4174         struct tblentry **pp;
4175
4176         p = name;
4177         hashval = (unsigned char)*p << 4;
4178         while (*p)
4179                 hashval += (unsigned char)*p++;
4180         hashval &= 0x7FFF;
4181         pp = &cmdtable[hashval % CMDTABLESIZE];
4182         for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
4183                 if (equal(cmdp->cmdname, name))
4184                         break;
4185                 pp = &cmdp->next;
4186         }
4187         if (add && cmdp == NULL) {
4188                 cmdp = *pp = ckmalloc(sizeof (struct tblentry) - ARB
4189                                         + strlen(name) + 1);
4190                 cmdp->next = NULL;
4191                 cmdp->cmdtype = CMDUNKNOWN;
4192                 strcpy(cmdp->cmdname, name);
4193         }
4194         lastcmdentry = pp;
4195         return cmdp;
4196 }
4197
4198 /*
4199  * Delete the command entry returned on the last lookup.
4200  */
4201
4202 static void
4203 delete_cmd_entry(void)
4204 {
4205         struct tblentry *cmdp;
4206
4207         INTOFF;
4208         cmdp = *lastcmdentry;
4209         *lastcmdentry = cmdp->next;
4210         if (cmdp->cmdtype == CMDFUNCTION)
4211                 freefunc(cmdp->param.func);
4212         ckfree(cmdp);
4213         INTON;
4214 }
4215
4216
4217 /*
4218  * Add a new command entry, replacing any existing command entry for
4219  * the same name - except special builtins.
4220  */
4221
4222 static inline void
4223 addcmdentry(char *name, struct cmdentry *entry)
4224 {
4225         struct tblentry *cmdp;
4226
4227         cmdp = cmdlookup(name, 1);
4228         if (cmdp->cmdtype == CMDFUNCTION) {
4229                 freefunc(cmdp->param.func);
4230         }
4231         cmdp->cmdtype = entry->cmdtype;
4232         cmdp->param = entry->u;
4233         cmdp->rehash = 0;
4234 }
4235
4236 /*
4237  * Make a copy of a parse tree.
4238  */
4239
4240 static inline struct funcnode *
4241 copyfunc(union node *n)
4242 {
4243         struct funcnode *f;
4244         size_t blocksize;
4245
4246         funcblocksize = offsetof(struct funcnode, n);
4247         funcstringsize = 0;
4248         calcsize(n);
4249         blocksize = funcblocksize;
4250         f = ckmalloc(blocksize + funcstringsize);
4251         funcblock = (char *) f + offsetof(struct funcnode, n);
4252         funcstring = (char *) f + blocksize;
4253         copynode(n);
4254         f->count = 0;
4255         return f;
4256 }
4257
4258 /*
4259  * Define a shell function.
4260  */
4261
4262 static void
4263 defun(char *name, union node *func)
4264 {
4265         struct cmdentry entry;
4266
4267         INTOFF;
4268         entry.cmdtype = CMDFUNCTION;
4269         entry.u.func = copyfunc(func);
4270         addcmdentry(name, &entry);
4271         INTON;
4272 }
4273
4274
4275 /*
4276  * Delete a function if it exists.
4277  */
4278
4279 static void
4280 unsetfunc(const char *name)
4281 {
4282         struct tblentry *cmdp;
4283
4284         if ((cmdp = cmdlookup(name, 0)) != NULL &&
4285             cmdp->cmdtype == CMDFUNCTION)
4286                 delete_cmd_entry();
4287 }
4288
4289 /*
4290  * Locate and print what a word is...
4291  */
4292
4293
4294 #ifdef CONFIG_ASH_CMDCMD
4295 static int
4296 describe_command(char *command, int describe_command_verbose)
4297 #else
4298 #define describe_command_verbose 1
4299 static int
4300 describe_command(char *command)
4301 #endif
4302 {
4303         struct cmdentry entry;
4304         struct tblentry *cmdp;
4305 #ifdef CONFIG_ASH_ALIAS
4306         const struct alias *ap;
4307 #endif
4308         const char *path = pathval();
4309
4310         if (describe_command_verbose) {
4311                 out1str(command);
4312         }
4313
4314         /* First look at the keywords */
4315         if (findkwd(command)) {
4316                 out1str(describe_command_verbose ? " is a shell keyword" : command);
4317                 goto out;
4318         }
4319
4320 #ifdef CONFIG_ASH_ALIAS
4321         /* Then look at the aliases */
4322         if ((ap = lookupalias(command, 0)) != NULL) {
4323                 if (describe_command_verbose) {
4324                         out1fmt(" is an alias for %s", ap->val);
4325                 } else {
4326                         out1str("alias ");
4327                         printalias(ap);
4328                         return 0;
4329                 }
4330                 goto out;
4331         }
4332 #endif
4333         /* Then check if it is a tracked alias */
4334         if ((cmdp = cmdlookup(command, 0)) != NULL) {
4335                 entry.cmdtype = cmdp->cmdtype;
4336                 entry.u = cmdp->param;
4337         } else {
4338                 /* Finally use brute force */
4339                 find_command(command, &entry, DO_ABS, path);
4340         }
4341
4342         switch (entry.cmdtype) {
4343         case CMDNORMAL: {
4344                 int j = entry.u.index;
4345                 char *p;
4346                 if (j == -1) {
4347                         p = command;
4348                 } else {
4349                         do {
4350                                 p = padvance(&path, command);
4351                                 stunalloc(p);
4352                         } while (--j >= 0);
4353                 }
4354                 if (describe_command_verbose) {
4355                         out1fmt(" is%s %s",
4356                                 (cmdp ? " a tracked alias for" : nullstr), p
4357                         );
4358                 } else {
4359                         out1str(p);
4360                 }
4361                 break;
4362         }
4363
4364         case CMDFUNCTION:
4365                 if (describe_command_verbose) {
4366                         out1str(" is a shell function");
4367                 } else {
4368                         out1str(command);
4369                 }
4370                 break;
4371
4372         case CMDBUILTIN:
4373                 if (describe_command_verbose) {
4374                         out1fmt(" is a %sshell builtin",
4375                                 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
4376                                         "special " : nullstr
4377                         );
4378                 } else {
4379                         out1str(command);
4380                 }
4381                 break;
4382
4383         default:
4384                 if (describe_command_verbose) {
4385                         out1str(": not found\n");
4386                 }
4387                 return 127;
4388         }
4389
4390 out:
4391         outstr("\n", stdout);
4392         return 0;
4393 }
4394
4395 static int
4396 typecmd(int argc, char **argv)
4397 {
4398         int i;
4399         int err = 0;
4400
4401         for (i = 1; i < argc; i++) {
4402 #ifdef CONFIG_ASH_CMDCMD
4403                 err |= describe_command(argv[i], 1);
4404 #else
4405                 err |= describe_command(argv[i]);
4406 #endif
4407         }
4408         return err;
4409 }
4410
4411 #ifdef CONFIG_ASH_CMDCMD
4412 static int
4413 commandcmd(int argc, char **argv)
4414 {
4415         int c;
4416         int default_path = 0;
4417         int verify_only = 0;
4418         int verbose_verify_only = 0;
4419
4420         while ((c = nextopt("pvV")) != '\0')
4421                 switch (c) {
4422                 default:
4423 #ifdef DEBUG
4424                         fprintf(stderr,
4425 "command: nextopt returned character code 0%o\n", c);
4426                         return EX_SOFTWARE;
4427 #endif
4428                 case 'p':
4429                         default_path = 1;
4430                         break;
4431                 case 'v':
4432                         verify_only = 1;
4433                         break;
4434                 case 'V':
4435                         verbose_verify_only = 1;
4436                         break;
4437                 }
4438
4439         if (default_path + verify_only + verbose_verify_only > 1 ||
4440             !*argptr) {
4441                         fprintf(stderr,
4442                                 "command [-p] command [arg ...]\n"
4443                                 "command {-v|-V} command\n");
4444                         return EX_USAGE;
4445         }
4446
4447         if (verify_only || verbose_verify_only) {
4448                 return describe_command(*argptr, verbose_verify_only);
4449         }
4450
4451         return 0;
4452 }
4453 #endif
4454
4455 /*      $NetBSD: expand.c,v 1.56 2002/11/24 22:35:39 christos Exp $     */
4456
4457 /*
4458  * Routines to expand arguments to commands.  We have to deal with
4459  * backquotes, shell variables, and file metacharacters.
4460  */
4461
4462 /*
4463  * _rmescape() flags
4464  */
4465 #define RMESCAPE_ALLOC  0x1     /* Allocate a new string */
4466 #define RMESCAPE_GLOB   0x2     /* Add backslashes for glob */
4467 #define RMESCAPE_QUOTED 0x4     /* Remove CTLESC unless in quotes */
4468 #define RMESCAPE_GROW   0x8     /* Grow strings instead of stalloc */
4469 #define RMESCAPE_HEAP   0x10    /* Malloc strings instead of stalloc */
4470
4471 /*
4472  * Structure specifying which parts of the string should be searched
4473  * for IFS characters.
4474  */
4475
4476 struct ifsregion {
4477         struct ifsregion *next; /* next region in list */
4478         int begoff;             /* offset of start of region */
4479         int endoff;             /* offset of end of region */
4480         int nulonly;            /* search for nul bytes only */
4481 };
4482
4483 /* output of current string */
4484 static char *expdest;
4485 /* list of back quote expressions */
4486 static struct nodelist *argbackq;
4487 /* first struct in list of ifs regions */
4488 static struct ifsregion ifsfirst;
4489 /* last struct in list */
4490 static struct ifsregion *ifslastp;
4491 /* holds expanded arg list */
4492 static struct arglist exparg;
4493
4494 static void argstr(char *, int);
4495 static char *exptilde(char *, char *, int);
4496 static void expbackq(union node *, int, int);
4497 static const char *subevalvar(char *, char *, int, int, int, int, int);
4498 static char *evalvar(char *, int);
4499 static int varisset(char *, int);
4500 static void strtodest(const char *, int, int);
4501 static void memtodest(const char *p, size_t len, int syntax, int quotes);
4502 static void varvalue(char *, int, int);
4503 static void recordregion(int, int, int);
4504 static void removerecordregions(int);
4505 static void ifsbreakup(char *, struct arglist *);
4506 static void ifsfree(void);
4507 static void expandmeta(struct strlist *, int);
4508 static int patmatch(char *, const char *);
4509
4510 static int cvtnum(long);
4511 static size_t esclen(const char *, const char *);
4512 static char *scanleft(char *, char *, char *, char *, int, int);
4513 static char *scanright(char *, char *, char *, char *, int, int);
4514 static void varunset(const char *, const char *, const char *, int)
4515         __attribute__((__noreturn__));
4516
4517
4518 #define pmatch(a, b) !fnmatch((a), (b), 0)
4519 /*
4520  * Prepare a pattern for a expmeta (internal glob(3)) call.
4521  *
4522  * Returns an stalloced string.
4523  */
4524
4525 static inline char *
4526 preglob(const char *pattern, int quoted, int flag) {
4527         flag |= RMESCAPE_GLOB;
4528         if (quoted) {
4529                 flag |= RMESCAPE_QUOTED;
4530         }
4531         return _rmescapes((char *)pattern, flag);
4532 }
4533
4534
4535 static size_t
4536 esclen(const char *start, const char *p) {
4537         size_t esc = 0;
4538
4539         while (p > start && *--p == CTLESC) {
4540                 esc++;
4541         }
4542         return esc;
4543 }
4544
4545
4546 /*
4547  * Expand shell variables and backquotes inside a here document.
4548  */
4549
4550 static inline void
4551 expandhere(union node *arg, int fd)
4552 {
4553         herefd = fd;
4554         expandarg(arg, (struct arglist *)NULL, 0);
4555         xwrite(fd, stackblock(), expdest - (char *)stackblock());
4556 }
4557
4558
4559 /*
4560  * Perform variable substitution and command substitution on an argument,
4561  * placing the resulting list of arguments in arglist.  If EXP_FULL is true,
4562  * perform splitting and file name expansion.  When arglist is NULL, perform
4563  * here document expansion.
4564  */
4565
4566 void
4567 expandarg(union node *arg, struct arglist *arglist, int flag)
4568 {
4569         struct strlist *sp;
4570         char *p;
4571
4572         argbackq = arg->narg.backquote;
4573         STARTSTACKSTR(expdest);
4574         ifsfirst.next = NULL;
4575         ifslastp = NULL;
4576         argstr(arg->narg.text, flag);
4577         if (arglist == NULL) {
4578                 return;                 /* here document expanded */
4579         }
4580         STPUTC('\0', expdest);
4581         p = grabstackstr(expdest);
4582         exparg.lastp = &exparg.list;
4583         /*
4584          * TODO - EXP_REDIR
4585          */
4586         if (flag & EXP_FULL) {
4587                 ifsbreakup(p, &exparg);
4588                 *exparg.lastp = NULL;
4589                 exparg.lastp = &exparg.list;
4590                 expandmeta(exparg.list, flag);
4591         } else {
4592                 if (flag & EXP_REDIR) /*XXX - for now, just remove escapes */
4593                         rmescapes(p);
4594                 sp = (struct strlist *)stalloc(sizeof (struct strlist));
4595                 sp->text = p;
4596                 *exparg.lastp = sp;
4597                 exparg.lastp = &sp->next;
4598         }
4599         if (ifsfirst.next)
4600                 ifsfree();
4601         *exparg.lastp = NULL;
4602         if (exparg.list) {
4603                 *arglist->lastp = exparg.list;
4604                 arglist->lastp = exparg.lastp;
4605         }
4606 }
4607
4608
4609 /*
4610  * Perform variable and command substitution.  If EXP_FULL is set, output CTLESC
4611  * characters to allow for further processing.  Otherwise treat
4612  * $@ like $* since no splitting will be performed.
4613  */
4614
4615 static void
4616 argstr(char *p, int flag)
4617 {
4618         static const char spclchars[] = {
4619                 '=',
4620                 ':',
4621                 CTLQUOTEMARK,
4622                 CTLENDVAR,
4623                 CTLESC,
4624                 CTLVAR,
4625                 CTLBACKQ,
4626                 CTLBACKQ | CTLQUOTE,
4627 #ifdef CONFIG_ASH_MATH_SUPPORT
4628                 CTLENDARI,
4629 #endif
4630                 0
4631         };
4632         const char *reject = spclchars;
4633         int c;
4634         int quotes = flag & (EXP_FULL | EXP_CASE);      /* do CTLESC */
4635         int breakall = flag & EXP_WORD;
4636         int inquotes;
4637         size_t length;
4638         int startloc;
4639
4640         if (!(flag & EXP_VARTILDE)) {
4641                 reject += 2;
4642         } else if (flag & EXP_VARTILDE2) {
4643                 reject++;
4644         }
4645         inquotes = 0;
4646         length = 0;
4647         if (flag & EXP_TILDE) {
4648                 char *q;
4649
4650                 flag &= ~EXP_TILDE;
4651 tilde:
4652                 q = p;
4653                 if (*q == CTLESC && (flag & EXP_QWORD))
4654                         q++;
4655                 if (*q == '~')
4656                         p = exptilde(p, q, flag);
4657         }
4658 start:
4659         startloc = expdest - (char *)stackblock();
4660         for (;;) {
4661                 length += strcspn(p + length, reject);
4662                 c = p[length];
4663                 if (c && (!(c & 0x80)
4664 #ifdef CONFIG_ASH_MATH_SUPPORT
4665                                         || c == CTLENDARI
4666 #endif
4667                    )) {
4668                         /* c == '=' || c == ':' || c == CTLENDARI */
4669                         length++;
4670                 }
4671                 if (length > 0) {
4672                         int newloc;
4673                         expdest = stnputs(p, length, expdest);
4674                         newloc = expdest - (char *)stackblock();
4675                         if (breakall && !inquotes && newloc > startloc) {
4676                                 recordregion(startloc, newloc, 0);
4677                         }
4678                         startloc = newloc;
4679                 }
4680                 p += length + 1;
4681                 length = 0;
4682
4683                 switch (c) {
4684                 case '\0':
4685                         goto breakloop;
4686                 case '=':
4687                         if (flag & EXP_VARTILDE2) {
4688                                 p--;
4689                                 continue;
4690                         }
4691                         flag |= EXP_VARTILDE2;
4692                         reject++;
4693                         /* fall through */
4694                 case ':':
4695                         /*
4696                          * sort of a hack - expand tildes in variable
4697                          * assignments (after the first '=' and after ':'s).
4698                          */
4699                         if (*--p == '~') {
4700                                 goto tilde;
4701                         }
4702                         continue;
4703                 }
4704
4705                 switch (c) {
4706                 case CTLENDVAR: /* ??? */
4707                         goto breakloop;
4708                 case CTLQUOTEMARK:
4709                         /* "$@" syntax adherence hack */
4710                         if (
4711                                 !inquotes &&
4712                                 !memcmp(p, dolatstr, DOLATSTRLEN) &&
4713                                 (p[4] == CTLQUOTEMARK || (
4714                                         p[4] == CTLENDVAR &&
4715                                         p[5] == CTLQUOTEMARK
4716                                 ))
4717                         ) {
4718                                 p = evalvar(p + 1, flag) + 1;
4719                                 goto start;
4720                         }
4721                         inquotes = !inquotes;
4722 addquote:
4723                         if (quotes) {
4724                                 p--;
4725                                 length++;
4726                                 startloc++;
4727                         }
4728                         break;
4729                 case CTLESC:
4730                         startloc++;
4731                         length++;
4732                         goto addquote;
4733                 case CTLVAR:
4734                         p = evalvar(p, flag);
4735                         goto start;
4736                 case CTLBACKQ:
4737                         c = 0;
4738                 case CTLBACKQ|CTLQUOTE:
4739                         expbackq(argbackq->n, c, quotes);
4740                         argbackq = argbackq->next;
4741                         goto start;
4742 #ifdef CONFIG_ASH_MATH_SUPPORT
4743                 case CTLENDARI:
4744                         p--;
4745                         expari(quotes);
4746                         goto start;
4747 #endif
4748                 }
4749         }
4750 breakloop:
4751         ;
4752 }
4753
4754 static char *
4755 exptilde(char *startp, char *p, int flag)
4756 {
4757         char c;
4758         char *name;
4759         struct passwd *pw;
4760         const char *home;
4761         int quotes = flag & (EXP_FULL | EXP_CASE);
4762         int startloc;
4763
4764         name = p + 1;
4765
4766         while ((c = *++p) != '\0') {
4767                 switch(c) {
4768                 case CTLESC:
4769                         return (startp);
4770                 case CTLQUOTEMARK:
4771                         return (startp);
4772                 case ':':
4773                         if (flag & EXP_VARTILDE)
4774                                 goto done;
4775                         break;
4776                 case '/':
4777                 case CTLENDVAR:
4778                         goto done;
4779                 }
4780         }
4781 done:
4782         *p = '\0';
4783         if (*name == '\0') {
4784                 if ((home = lookupvar(homestr)) == NULL)
4785                         goto lose;
4786         } else {
4787                 if ((pw = getpwnam(name)) == NULL)
4788                         goto lose;
4789                 home = pw->pw_dir;
4790         }
4791         if (*home == '\0')
4792                 goto lose;
4793         *p = c;
4794         startloc = expdest - (char *)stackblock();
4795         strtodest(home, SQSYNTAX, quotes);
4796         recordregion(startloc, expdest - (char *)stackblock(), 0);
4797         return (p);
4798 lose:
4799         *p = c;
4800         return (startp);
4801 }
4802
4803
4804 static void
4805 removerecordregions(int endoff)
4806 {
4807         if (ifslastp == NULL)
4808                 return;
4809
4810         if (ifsfirst.endoff > endoff) {
4811                 while (ifsfirst.next != NULL) {
4812                         struct ifsregion *ifsp;
4813                         INTOFF;
4814                         ifsp = ifsfirst.next->next;
4815                         ckfree(ifsfirst.next);
4816                         ifsfirst.next = ifsp;
4817                         INTON;
4818                 }
4819                 if (ifsfirst.begoff > endoff)
4820                         ifslastp = NULL;
4821                 else {
4822                         ifslastp = &ifsfirst;
4823                         ifsfirst.endoff = endoff;
4824                 }
4825                 return;
4826         }
4827
4828         ifslastp = &ifsfirst;
4829         while (ifslastp->next && ifslastp->next->begoff < endoff)
4830                 ifslastp=ifslastp->next;
4831         while (ifslastp->next != NULL) {
4832                 struct ifsregion *ifsp;
4833                 INTOFF;
4834                 ifsp = ifslastp->next->next;
4835                 ckfree(ifslastp->next);
4836                 ifslastp->next = ifsp;
4837                 INTON;
4838         }
4839         if (ifslastp->endoff > endoff)
4840                 ifslastp->endoff = endoff;
4841 }
4842
4843
4844 #ifdef CONFIG_ASH_MATH_SUPPORT
4845 /*
4846  * Expand arithmetic expression.  Backup to start of expression,
4847  * evaluate, place result in (backed up) result, adjust string position.
4848  */
4849 void
4850 expari(int quotes)
4851 {
4852         char *p, *start;
4853         int begoff;
4854         int flag;
4855         int len;
4856
4857         /*      ifsfree(); */
4858
4859         /*
4860          * This routine is slightly over-complicated for
4861          * efficiency.  Next we scan backwards looking for the
4862          * start of arithmetic.
4863          */
4864         start = stackblock();
4865         p = expdest - 1;
4866         *p = '\0';
4867         p--;
4868         do {
4869                 int esc;
4870
4871                 while (*p != CTLARI) {
4872                         p--;
4873 #ifdef DEBUG
4874                         if (p < start) {
4875                                 error("missing CTLARI (shouldn't happen)");
4876                         }
4877 #endif
4878                 }
4879
4880                 esc = esclen(start, p);
4881                 if (!(esc % 2)) {
4882                         break;
4883                 }
4884
4885                 p -= esc + 1;
4886         } while (1);
4887
4888         begoff = p - start;
4889
4890         removerecordregions(begoff);
4891
4892         flag = p[1];
4893
4894         expdest = p;
4895
4896         if (quotes)
4897                 rmescapes(p + 2);
4898
4899         len = cvtnum(dash_arith(p + 2));
4900
4901         if (flag != '"')
4902                 recordregion(begoff, begoff + len, 0);
4903 }
4904 #endif
4905
4906 /*
4907  * Expand stuff in backwards quotes.
4908  */
4909
4910 static void
4911 expbackq(union node *cmd, int quoted, int quotes)
4912 {
4913         struct backcmd in;
4914         int i;
4915         char buf[128];
4916         char *p;
4917         char *dest;
4918         int startloc;
4919         int syntax = quoted? DQSYNTAX : BASESYNTAX;
4920         struct stackmark smark;
4921
4922         INTOFF;
4923         setstackmark(&smark);
4924         dest = expdest;
4925         startloc = dest - (char *)stackblock();
4926         grabstackstr(dest);
4927         evalbackcmd(cmd, (struct backcmd *) &in);
4928         popstackmark(&smark);
4929
4930         p = in.buf;
4931         i = in.nleft;
4932         if (i == 0)
4933                 goto read;
4934         for (;;) {
4935                 memtodest(p, i, syntax, quotes);
4936 read:
4937                 if (in.fd < 0)
4938                         break;
4939                 i = safe_read(in.fd, buf, sizeof buf);
4940                 TRACE(("expbackq: read returns %d\n", i));
4941                 if (i <= 0)
4942                         break;
4943                 p = buf;
4944         }
4945
4946         if (in.buf)
4947                 ckfree(in.buf);
4948         if (in.fd >= 0) {
4949                 close(in.fd);
4950                 back_exitstatus = waitforjob(in.jp);
4951         }
4952         INTON;
4953
4954         /* Eat all trailing newlines */
4955         dest = expdest;
4956         for (; dest > (char *)stackblock() && dest[-1] == '\n';)
4957                 STUNPUTC(dest);
4958         expdest = dest;
4959
4960         if (quoted == 0)
4961                 recordregion(startloc, dest - (char *)stackblock(), 0);
4962         TRACE(("evalbackq: size=%d: \"%.*s\"\n",
4963                 (dest - (char *)stackblock()) - startloc,
4964                 (dest - (char *)stackblock()) - startloc,
4965                 stackblock() + startloc));
4966 }
4967
4968
4969 static char *
4970 scanleft(char *startp, char *rmesc, char *rmescend, char *str, int quotes,
4971         int zero)
4972 {
4973         char *loc;
4974         char *loc2;
4975         char c;
4976
4977         loc = startp;
4978         loc2 = rmesc;
4979         do {
4980                 int match;
4981                 const char *s = loc2;
4982                 c = *loc2;
4983                 if (zero) {
4984                         *loc2 = '\0';
4985                         s = rmesc;
4986                 }
4987                 match = pmatch(str, s);
4988                 *loc2 = c;
4989                 if (match)
4990                         return loc;
4991                 if (quotes && *loc == CTLESC)
4992                         loc++;
4993                 loc++;
4994                 loc2++;
4995         } while (c);
4996         return 0;
4997 }
4998
4999
5000 static char *
5001 scanright(char *startp, char *rmesc, char *rmescend, char *str, int quotes,
5002         int zero)
5003 {
5004         int esc = 0;
5005         char *loc;
5006         char *loc2;
5007
5008         for (loc = str - 1, loc2 = rmescend; loc >= startp; loc2--) {
5009                 int match;
5010                 char c = *loc2;
5011                 const char *s = loc2;
5012                 if (zero) {
5013                         *loc2 = '\0';
5014                         s = rmesc;
5015                 }
5016                 match = pmatch(str, s);
5017                 *loc2 = c;
5018                 if (match)
5019                         return loc;
5020                 loc--;
5021                 if (quotes) {
5022                         if (--esc < 0) {
5023                                 esc = esclen(startp, loc);
5024                         }
5025                         if (esc % 2) {
5026                                 esc--;
5027                                 loc--;
5028                         }
5029                 }
5030         }
5031         return 0;
5032 }
5033
5034 static const char *
5035 subevalvar(char *p, char *str, int strloc, int subtype, int startloc, int varflags, int quotes)
5036 {
5037         char *startp;
5038         char *loc;
5039         int saveherefd = herefd;
5040         struct nodelist *saveargbackq = argbackq;
5041         int amount;
5042         char *rmesc, *rmescend;
5043         int zero;
5044         char *(*scan)(char *, char *, char *, char *, int , int);
5045
5046         herefd = -1;
5047         argstr(p, subtype != VSASSIGN && subtype != VSQUESTION ? EXP_CASE : 0);
5048         STPUTC('\0', expdest);
5049         herefd = saveherefd;
5050         argbackq = saveargbackq;
5051         startp = stackblock() + startloc;
5052
5053         switch (subtype) {
5054         case VSASSIGN:
5055                 setvar(str, startp, 0);
5056                 amount = startp - expdest;
5057                 STADJUST(amount, expdest);
5058                 return startp;
5059
5060         case VSQUESTION:
5061                 varunset(p, str, startp, varflags);
5062                 /* NOTREACHED */
5063         }
5064
5065         subtype -= VSTRIMRIGHT;
5066 #ifdef DEBUG
5067         if (subtype < 0 || subtype > 3)
5068                 abort();
5069 #endif
5070
5071         rmesc = startp;
5072         rmescend = stackblock() + strloc;
5073         if (quotes) {
5074                 rmesc = _rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW);
5075                 if (rmesc != startp) {
5076                         rmescend = expdest;
5077                         startp = stackblock() + startloc;
5078                 }
5079         }
5080         rmescend--;
5081         str = stackblock() + strloc;
5082         preglob(str, varflags & VSQUOTE, 0);
5083
5084         /* zero = subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX */
5085         zero = subtype >> 1;
5086         /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
5087         scan = (subtype & 1) ^ zero ? scanleft : scanright;
5088
5089         loc = scan(startp, rmesc, rmescend, str, quotes, zero);
5090         if (loc) {
5091                 if (zero) {
5092                         memmove(startp, loc, str - loc);
5093                         loc = startp + (str - loc) - 1;
5094                 }
5095                 *loc = '\0';
5096                 amount = loc - expdest;
5097                 STADJUST(amount, expdest);
5098         }
5099         return loc;
5100 }
5101
5102
5103 /*
5104  * Expand a variable, and return a pointer to the next character in the
5105  * input string.
5106  */
5107 static char *
5108 evalvar(char *p, int flag)
5109 {
5110         int subtype;
5111         int varflags;
5112         char *var;
5113         int patloc;
5114         int c;
5115         int set;
5116         int startloc;
5117         size_t varlen;
5118         int easy;
5119         int quotes;
5120         int quoted;
5121
5122         quotes = flag & (EXP_FULL | EXP_CASE);
5123         varflags = *p++;
5124         subtype = varflags & VSTYPE;
5125         quoted = varflags & VSQUOTE;
5126         var = p;
5127         easy = (!quoted || (*var == '@' && shellparam.nparam));
5128         varlen = 0;
5129         startloc = expdest - (char *)stackblock();
5130         p = strchr(p, '=') + 1;
5131
5132         if (!is_name(*var)) {
5133                 set = varisset(var, varflags & VSNUL);
5134                 set--;
5135                 if (subtype == VSPLUS)
5136                         goto vsplus;
5137                 if (++set) {
5138                         varvalue(var, quoted, flag);
5139                         if (subtype == VSLENGTH) {
5140                                 varlen =
5141                                         expdest - (char *)stackblock() -
5142                                         startloc;
5143                                 STADJUST(-varlen, expdest);
5144                                 goto vslen;
5145                         }
5146                 }
5147         } else {
5148                 const char *val;
5149 again:
5150                 /* jump here after setting a variable with ${var=text} */
5151                 val = lookupvar(var);
5152                 set = !val || ((varflags & VSNUL) && !*val);
5153                 if (subtype == VSPLUS)
5154                         goto vsplus;
5155                 if (--set) {
5156                         varlen = strlen(val);
5157                         if (subtype == VSLENGTH)
5158                                 goto vslen;
5159                         memtodest(
5160                                 val, varlen, quoted ? DQSYNTAX : BASESYNTAX,
5161                                 quotes
5162                         );
5163                 }
5164         }
5165
5166
5167         if (subtype == VSMINUS) {
5168 vsplus:
5169                 if (!set) {
5170                         argstr(
5171                                 p, flag | EXP_TILDE |
5172                                         (quoted ?  EXP_QWORD : EXP_WORD)
5173                         );
5174                         goto end;
5175                 }
5176                 if (easy)
5177                         goto record;
5178                 goto end;
5179         }
5180
5181         if (subtype == VSASSIGN || subtype == VSQUESTION) {
5182                 if (!set) {
5183                         if (subevalvar(p, var, 0, subtype, startloc,
5184                                        varflags, 0)) {
5185                                 varflags &= ~VSNUL;
5186                                 /*
5187                                  * Remove any recorded regions beyond
5188                                  * start of variable
5189                                  */
5190                                 removerecordregions(startloc);
5191                                 goto again;
5192                         }
5193                         goto end;
5194                 }
5195                 if (easy)
5196                         goto record;
5197                 goto end;
5198         }
5199
5200         if (!set && uflag)
5201                 varunset(p, var, 0, 0);
5202
5203         if (subtype == VSLENGTH) {
5204 vslen:
5205                 cvtnum(varlen);
5206                 goto record;
5207         }
5208
5209         if (subtype == VSNORMAL) {
5210                 if (!easy)
5211                         goto end;
5212 record:
5213                 recordregion(startloc, expdest - (char *)stackblock(), quoted);
5214                 goto end;
5215         }
5216
5217 #ifdef DEBUG
5218         switch (subtype) {
5219         case VSTRIMLEFT:
5220         case VSTRIMLEFTMAX:
5221         case VSTRIMRIGHT:
5222         case VSTRIMRIGHTMAX:
5223                 break;
5224         default:
5225                 abort();
5226         }
5227 #endif
5228
5229         if (set) {
5230                 /*
5231                  * Terminate the string and start recording the pattern
5232                  * right after it
5233                  */
5234                 STPUTC('\0', expdest);
5235                 patloc = expdest - (char *)stackblock();
5236                 if (subevalvar(p, NULL, patloc, subtype,
5237                                startloc, varflags, quotes) == 0) {
5238                         int amount = expdest - (
5239                                 (char *)stackblock() + patloc - 1
5240                         );
5241                         STADJUST(-amount, expdest);
5242                 }
5243                 /* Remove any recorded regions beyond start of variable */
5244                 removerecordregions(startloc);
5245                 goto record;
5246         }
5247
5248 end:
5249         if (subtype != VSNORMAL) {      /* skip to end of alternative */
5250                 int nesting = 1;
5251                 for (;;) {
5252                         if ((c = *p++) == CTLESC)
5253                                 p++;
5254                         else if (c == CTLBACKQ || c == (CTLBACKQ|CTLQUOTE)) {
5255                                 if (set)
5256                                         argbackq = argbackq->next;
5257                         } else if (c == CTLVAR) {
5258                                 if ((*p++ & VSTYPE) != VSNORMAL)
5259                                         nesting++;
5260                         } else if (c == CTLENDVAR) {
5261                                 if (--nesting == 0)
5262                                         break;
5263                         }
5264                 }
5265         }
5266         return p;
5267 }
5268
5269
5270
5271 /*
5272  * Test whether a specialized variable is set.
5273  */
5274
5275 static int
5276 varisset(char *name, int nulok)
5277 {
5278         if (*name == '!')
5279                 return backgndpid != 0;
5280         else if (*name == '@' || *name == '*') {
5281                 if (*shellparam.p == NULL)
5282                         return 0;
5283
5284                 if (nulok) {
5285                         char **av;
5286
5287                         for (av = shellparam.p; *av; av++)
5288                                 if (**av != '\0')
5289                                         return 1;
5290                         return 0;
5291                 }
5292         } else if (is_digit(*name)) {
5293                 char *ap;
5294                 int num = atoi(name);
5295
5296                 if (num > shellparam.nparam)
5297                         return 0;
5298
5299                 if (num == 0)
5300                         ap = arg0;
5301                 else
5302                         ap = shellparam.p[num - 1];
5303
5304                 if (nulok && (ap == NULL || *ap == '\0'))
5305                         return 0;
5306         }
5307         return 1;
5308 }
5309
5310
5311 /*
5312  * Put a string on the stack.
5313  */
5314
5315 static void
5316 memtodest(const char *p, size_t len, int syntax, int quotes) {
5317         char *q = expdest;
5318
5319         q = makestrspace(len * 2, q);
5320
5321         while (len--) {
5322                 int c = *p++;
5323                 if (!c)
5324                         continue;
5325                 if (quotes && (SIT(c, syntax) == CCTL || SIT(c, syntax) == CBACK))
5326                         USTPUTC(CTLESC, q);
5327                 USTPUTC(c, q);
5328         }
5329
5330         expdest = q;
5331 }
5332
5333
5334 static void
5335 strtodest(const char *p, int syntax, int quotes)
5336 {
5337         memtodest(p, strlen(p), syntax, quotes);
5338 }
5339
5340
5341 /*
5342  * Add the value of a specialized variable to the stack string.
5343  */
5344
5345 static void
5346 varvalue(char *name, int quoted, int flags)
5347 {
5348         int num;
5349         char *p;
5350         int i;
5351         int sep;
5352         int sepq = 0;
5353         char **ap;
5354         int syntax;
5355         int allow_split = flags & EXP_FULL;
5356         int quotes = flags & (EXP_FULL | EXP_CASE);
5357
5358         syntax = quoted ? DQSYNTAX : BASESYNTAX;
5359         switch (*name) {
5360         case '$':
5361                 num = rootpid;
5362                 goto numvar;
5363         case '?':
5364                 num = exitstatus;
5365                 goto numvar;
5366         case '#':
5367                 num = shellparam.nparam;
5368                 goto numvar;
5369         case '!':
5370                 num = backgndpid;
5371 numvar:
5372                 cvtnum(num);
5373                 break;
5374         case '-':
5375                 for (i = 0 ; i < NOPTS ; i++) {
5376                         if (optlist[i])
5377                                 STPUTC(optletters(i), expdest);
5378                 }
5379                 break;
5380         case '@':
5381                 if (allow_split && quoted) {
5382                         sep = 1 << CHAR_BIT;
5383                         goto param;
5384                 }
5385                 /* fall through */
5386         case '*':
5387                 sep = ifsset() ? ifsval()[0] : ' ';
5388                 if (quotes) {
5389                         sepq = (SIT(sep, syntax) == CCTL) || (SIT(sep, syntax) == CBACK);
5390                 }
5391 param:
5392                 for (ap = shellparam.p ; (p = *ap++) != NULL ; ) {
5393                         strtodest(p, syntax, quotes);
5394                         if (*ap && sep) {
5395                                 p = expdest;
5396                                 if (sepq)
5397                                         STPUTC(CTLESC, p);
5398                                 STPUTC(sep, p);
5399                                 expdest = p;
5400                         }
5401                 }
5402                 break;
5403         case '0':
5404                 strtodest(arg0, syntax, quotes);
5405                 break;
5406         default:
5407                 num = atoi(name);
5408                 if (num > 0 && num <= shellparam.nparam) {
5409                         strtodest(shellparam.p[num - 1], syntax, quotes);
5410                 }
5411                 break;
5412         }
5413 }
5414
5415
5416 /*
5417  * Record the fact that we have to scan this region of the
5418  * string for IFS characters.
5419  */
5420
5421 static void
5422 recordregion(int start, int end, int nulonly)
5423 {
5424         struct ifsregion *ifsp;
5425
5426         if (ifslastp == NULL) {
5427                 ifsp = &ifsfirst;
5428         } else {
5429                 INTOFF;
5430                 ifsp = (struct ifsregion *)ckmalloc(sizeof (struct ifsregion));
5431                 ifsp->next = NULL;
5432                 ifslastp->next = ifsp;
5433                 INTON;
5434         }
5435         ifslastp = ifsp;
5436         ifslastp->begoff = start;
5437         ifslastp->endoff = end;
5438         ifslastp->nulonly = nulonly;
5439 }
5440
5441
5442 /*
5443  * Break the argument string into pieces based upon IFS and add the
5444  * strings to the argument list.  The regions of the string to be
5445  * searched for IFS characters have been stored by recordregion.
5446  */
5447 static void
5448 ifsbreakup(char *string, struct arglist *arglist)
5449 {
5450         struct ifsregion *ifsp;
5451         struct strlist *sp;
5452         char *start;
5453         char *p;
5454         char *q;
5455         const char *ifs, *realifs;
5456         int ifsspc;
5457         int nulonly;
5458
5459
5460         start = string;
5461         if (ifslastp != NULL) {
5462                 ifsspc = 0;
5463                 nulonly = 0;
5464                 realifs = ifsset() ? ifsval() : defifs;
5465                 ifsp = &ifsfirst;
5466                 do {
5467                         p = string + ifsp->begoff;
5468                         nulonly = ifsp->nulonly;
5469                         ifs = nulonly ? nullstr : realifs;
5470                         ifsspc = 0;
5471                         while (p < string + ifsp->endoff) {
5472                                 q = p;
5473                                 if (*p == CTLESC)
5474                                         p++;
5475                                 if (strchr(ifs, *p)) {
5476                                         if (!nulonly)
5477                                                 ifsspc = (strchr(defifs, *p) != NULL);
5478                                         /* Ignore IFS whitespace at start */
5479                                         if (q == start && ifsspc) {
5480                                                 p++;
5481                                                 start = p;
5482                                                 continue;
5483                                         }
5484                                         *q = '\0';
5485                                         sp = (struct strlist *)stalloc(sizeof *sp);
5486                                         sp->text = start;
5487                                         *arglist->lastp = sp;
5488                                         arglist->lastp = &sp->next;
5489                                         p++;
5490                                         if (!nulonly) {
5491                                                 for (;;) {
5492                                                         if (p >= string + ifsp->endoff) {
5493                                                                 break;
5494                                                         }
5495                                                         q = p;
5496                                                         if (*p == CTLESC)
5497                                                                 p++;
5498                                                         if (strchr(ifs, *p) == NULL ) {
5499                                                                 p = q;
5500                                                                 break;
5501                                                         } else if (strchr(defifs, *p) == NULL) {
5502                                                                 if (ifsspc) {
5503                                                                         p++;
5504                                                                         ifsspc = 0;
5505                                                                 } else {
5506                                                                         p = q;
5507                                                                         break;
5508                                                                 }
5509                                                         } else
5510                                                                 p++;
5511                                                 }
5512                                         }
5513                                         start = p;
5514                                 } else
5515                                         p++;
5516                         }
5517                 } while ((ifsp = ifsp->next) != NULL);
5518                 if (nulonly)
5519                         goto add;
5520         }
5521
5522         if (!*start)
5523                 return;
5524
5525 add:
5526         sp = (struct strlist *)stalloc(sizeof *sp);
5527         sp->text = start;
5528         *arglist->lastp = sp;
5529         arglist->lastp = &sp->next;
5530 }
5531
5532 static void
5533 ifsfree(void)
5534 {
5535         struct ifsregion *p;
5536
5537         INTOFF;
5538         p = ifsfirst.next;
5539         do {
5540                 struct ifsregion *ifsp;
5541                 ifsp = p->next;
5542                 ckfree(p);
5543                 p = ifsp;
5544         } while (p);
5545         ifslastp = NULL;
5546         ifsfirst.next = NULL;
5547         INTON;
5548 }
5549
5550 static void expmeta(char *, char *);
5551 static struct strlist *expsort(struct strlist *);
5552 static struct strlist *msort(struct strlist *, int);
5553
5554 static char *expdir;
5555
5556
5557 static void
5558 expandmeta(struct strlist *str, int flag)
5559 {
5560         static const char metachars[] = {
5561                 '*', '?', '[', 0
5562         };
5563         /* TODO - EXP_REDIR */
5564
5565         while (str) {
5566                 struct strlist **savelastp;
5567                 struct strlist *sp;
5568                 char *p;
5569
5570                 if (fflag)
5571                         goto nometa;
5572                 if (!strpbrk(str->text, metachars))
5573                         goto nometa;
5574                 savelastp = exparg.lastp;
5575
5576                 INTOFF;
5577                 p = preglob(str->text, 0, RMESCAPE_ALLOC | RMESCAPE_HEAP);
5578                 {
5579                         int i = strlen(str->text);
5580                         expdir = ckmalloc(i < 2048 ? 2048 : i); /* XXX */
5581                 }
5582
5583                 expmeta(expdir, p);
5584                 ckfree(expdir);
5585                 if (p != str->text)
5586                         ckfree(p);
5587                 INTON;
5588                 if (exparg.lastp == savelastp) {
5589                         /*
5590                          * no matches
5591                          */
5592 nometa:
5593                         *exparg.lastp = str;
5594                         rmescapes(str->text);
5595                         exparg.lastp = &str->next;
5596                 } else {
5597                         *exparg.lastp = NULL;
5598                         *savelastp = sp = expsort(*savelastp);
5599                         while (sp->next != NULL)
5600                                 sp = sp->next;
5601                         exparg.lastp = &sp->next;
5602                 }
5603                 str = str->next;
5604         }
5605 }
5606
5607 /*
5608  * Add a file name to the list.
5609  */
5610
5611 static void
5612 addfname(const char *name)
5613 {
5614         struct strlist *sp;
5615
5616         sp = (struct strlist *)stalloc(sizeof *sp);
5617         sp->text = sstrdup(name);
5618         *exparg.lastp = sp;
5619         exparg.lastp = &sp->next;
5620 }
5621
5622
5623 /*
5624  * Do metacharacter (i.e. *, ?, [...]) expansion.
5625  */
5626
5627 static void
5628 expmeta(char *enddir, char *name)
5629 {
5630         char *p;
5631         const char *cp;
5632         char *start;
5633         char *endname;
5634         int metaflag;
5635         struct stat statb;
5636         DIR *dirp;
5637         struct dirent *dp;
5638         int atend;
5639         int matchdot;
5640
5641         metaflag = 0;
5642         start = name;
5643         for (p = name; *p; p++) {
5644                 if (*p == '*' || *p == '?')
5645                         metaflag = 1;
5646                 else if (*p == '[') {
5647                         char *q = p + 1;
5648                         if (*q == '!')
5649                                 q++;
5650                         for (;;) {
5651                                 if (*q == '\\')
5652                                         q++;
5653                                 if (*q == '/' || *q == '\0')
5654                                         break;
5655                                 if (*++q == ']') {
5656                                         metaflag = 1;
5657                                         break;
5658                                 }
5659                         }
5660                 } else if (*p == '\\')
5661                         p++;
5662                 else if (*p == '/') {
5663                         if (metaflag)
5664                                 goto out;
5665                         start = p + 1;
5666                 }
5667         }
5668 out:
5669         if (metaflag == 0) {    /* we've reached the end of the file name */
5670                 if (enddir != expdir)
5671                         metaflag++;
5672                 p = name;
5673                 do {
5674                         if (*p == '\\')
5675                                 p++;
5676                         *enddir++ = *p;
5677                 } while (*p++);
5678                 if (metaflag == 0 || lstat(expdir, &statb) >= 0)
5679                         addfname(expdir);
5680                 return;
5681         }
5682         endname = p;
5683         if (name < start) {
5684                 p = name;
5685                 do {
5686                         if (*p == '\\')
5687                                 p++;
5688                         *enddir++ = *p++;
5689                 } while (p < start);
5690         }
5691         if (enddir == expdir) {
5692                 cp = ".";
5693         } else if (enddir == expdir + 1 && *expdir == '/') {
5694                 cp = "/";
5695         } else {
5696                 cp = expdir;
5697                 enddir[-1] = '\0';
5698         }
5699         if ((dirp = opendir(cp)) == NULL)
5700                 return;
5701         if (enddir != expdir)
5702                 enddir[-1] = '/';
5703         if (*endname == 0) {
5704                 atend = 1;
5705         } else {
5706                 atend = 0;
5707                 *endname++ = '\0';
5708         }
5709         matchdot = 0;
5710         p = start;
5711         if (*p == '\\')
5712                 p++;
5713         if (*p == '.')
5714                 matchdot++;
5715         while (! intpending && (dp = readdir(dirp)) != NULL) {
5716                 if (dp->d_name[0] == '.' && ! matchdot)
5717                         continue;
5718                 if (pmatch(start, dp->d_name)) {
5719                         if (atend) {
5720                                 scopy(dp->d_name, enddir);
5721                                 addfname(expdir);
5722                         } else {
5723                                 for (p = enddir, cp = dp->d_name;
5724                                      (*p++ = *cp++) != '\0';)
5725                                         continue;
5726                                 p[-1] = '/';
5727                                 expmeta(p, endname);
5728                         }
5729                 }
5730         }
5731         closedir(dirp);
5732         if (! atend)
5733                 endname[-1] = '/';
5734 }
5735
5736 /*
5737  * Sort the results of file name expansion.  It calculates the number of
5738  * strings to sort and then calls msort (short for merge sort) to do the
5739  * work.
5740  */
5741
5742 static struct strlist *
5743 expsort(struct strlist *str)
5744 {
5745         int len;
5746         struct strlist *sp;
5747
5748         len = 0;
5749         for (sp = str ; sp ; sp = sp->next)
5750                 len++;
5751         return msort(str, len);
5752 }
5753
5754
5755 static struct strlist *
5756 msort(struct strlist *list, int len)
5757 {
5758         struct strlist *p, *q = NULL;
5759         struct strlist **lpp;
5760         int half;
5761         int n;
5762
5763         if (len <= 1)
5764                 return list;
5765         half = len >> 1;
5766         p = list;
5767         for (n = half ; --n >= 0 ; ) {
5768                 q = p;
5769                 p = p->next;
5770         }
5771         q->next = NULL;                 /* terminate first half of list */
5772         q = msort(list, half);          /* sort first half of list */
5773         p = msort(p, len - half);               /* sort second half */
5774         lpp = &list;
5775         for (;;) {
5776 #ifdef CONFIG_LOCALE_SUPPORT
5777                 if (strcoll(p->text, q->text) < 0)
5778 #else
5779                 if (strcmp(p->text, q->text) < 0)
5780 #endif
5781                                                 {
5782                         *lpp = p;
5783                         lpp = &p->next;
5784                         if ((p = *lpp) == NULL) {
5785                                 *lpp = q;
5786                                 break;
5787                         }
5788                 } else {
5789                         *lpp = q;
5790                         lpp = &q->next;
5791                         if ((q = *lpp) == NULL) {
5792                                 *lpp = p;
5793                                 break;
5794                         }
5795                 }
5796         }
5797         return list;
5798 }
5799
5800
5801 /*
5802  * Returns true if the pattern matches the string.
5803  */
5804
5805 static inline int
5806 patmatch(char *pattern, const char *string)
5807 {
5808         return pmatch(preglob(pattern, 0, 0), string);
5809 }
5810
5811
5812 /*
5813  * Remove any CTLESC characters from a string.
5814  */
5815
5816 static char *
5817 _rmescapes(char *str, int flag)
5818 {
5819         char *p, *q, *r;
5820         static const char qchars[] = { CTLESC, CTLQUOTEMARK, 0 };
5821         unsigned inquotes;
5822         int notescaped;
5823         int globbing;
5824
5825         p = strpbrk(str, qchars);
5826         if (!p) {
5827                 return str;
5828         }
5829         q = p;
5830         r = str;
5831         if (flag & RMESCAPE_ALLOC) {
5832                 size_t len = p - str;
5833                 size_t fulllen = len + strlen(p) + 1;
5834
5835                 if (flag & RMESCAPE_GROW) {
5836                         r = makestrspace(fulllen, expdest);
5837                 } else if (flag & RMESCAPE_HEAP) {
5838                         r = ckmalloc(fulllen);
5839                 } else {
5840                         r = stalloc(fulllen);
5841                 }
5842                 q = r;
5843                 if (len > 0) {
5844                         q = mempcpy(q, str, len);
5845                 }
5846         }
5847         inquotes = (flag & RMESCAPE_QUOTED) ^ RMESCAPE_QUOTED;
5848         globbing = flag & RMESCAPE_GLOB;
5849         notescaped = globbing;
5850         while (*p) {
5851                 if (*p == CTLQUOTEMARK) {
5852                         inquotes = ~inquotes;
5853                         p++;
5854                         notescaped = globbing;
5855                         continue;
5856                 }
5857                 if (*p == '\\') {
5858                         /* naked back slash */
5859                         notescaped = 0;
5860                         goto copy;
5861                 }
5862                 if (*p == CTLESC) {
5863                         p++;
5864                         if (notescaped && inquotes && *p != '/') {
5865                                 *q++ = '\\';
5866                         }
5867                 }
5868                 notescaped = globbing;
5869 copy:
5870                 *q++ = *p++;
5871         }
5872         *q = '\0';
5873         if (flag & RMESCAPE_GROW) {
5874                 expdest = r;
5875                 STADJUST(q - r + 1, expdest);
5876         }
5877         return r;
5878 }
5879
5880
5881 /*
5882  * See if a pattern matches in a case statement.
5883  */
5884
5885 int
5886 casematch(union node *pattern, char *val)
5887 {
5888         struct stackmark smark;
5889         int result;
5890
5891         setstackmark(&smark);
5892         argbackq = pattern->narg.backquote;
5893         STARTSTACKSTR(expdest);
5894         ifslastp = NULL;
5895         argstr(pattern->narg.text, EXP_TILDE | EXP_CASE);
5896         STACKSTRNUL(expdest);
5897         result = patmatch(stackblock(), val);
5898         popstackmark(&smark);
5899         return result;
5900 }
5901
5902 /*
5903  * Our own itoa().
5904  */
5905
5906 static int
5907 cvtnum(long num)
5908 {
5909         int len;
5910
5911         expdest = makestrspace(32, expdest);
5912         len = fmtstr(expdest, 32, "%ld", num);
5913         STADJUST(len, expdest);
5914         return len;
5915 }
5916
5917 static void
5918 varunset(const char *end, const char *var, const char *umsg, int varflags)
5919 {
5920         const char *msg;
5921         const char *tail;
5922
5923         tail = nullstr;
5924         msg = "parameter not set";
5925         if (umsg) {
5926                 if (*end == CTLENDVAR) {
5927                         if (varflags & VSNUL)
5928                                 tail = " or null";
5929                 } else
5930                         msg = umsg;
5931         }
5932         error("%.*s: %s%s", end - var - 1, var, msg, tail);
5933 }
5934
5935
5936 /*      $NetBSD: input.c,v 1.37 2002/11/24 22:35:40 christos Exp $      */
5937
5938 /*
5939  * This implements the input routines used by the parser.
5940  */
5941
5942 #define EOF_NLEFT -99           /* value of parsenleft when EOF pushed back */
5943 #define IBUFSIZ (BUFSIZ + 1)
5944
5945 static void pushfile(void);
5946
5947 /*
5948  * Read a line from the script.
5949  */
5950
5951 static inline char *
5952 pfgets(char *line, int len)
5953 {
5954         char *p = line;
5955         int nleft = len;
5956         int c;
5957
5958         while (--nleft > 0) {
5959                 c = pgetc2();
5960                 if (c == PEOF) {
5961                         if (p == line)
5962                                 return NULL;
5963                         break;
5964                 }
5965                 *p++ = c;
5966                 if (c == '\n')
5967                         break;
5968         }
5969         *p = '\0';
5970         return line;
5971 }
5972
5973
5974 /*
5975  * Read a character from the script, returning PEOF on end of file.
5976  * Nul characters in the input are silently discarded.
5977  */
5978
5979 #define pgetc_as_macro()   (--parsenleft >= 0? *parsenextc++ : preadbuffer())
5980
5981 #ifdef CONFIG_ASH_OPTIMIZE_FOR_SIZE
5982 #define pgetc_macro() pgetc()
5983 static int
5984 pgetc(void)
5985 {
5986         return pgetc_as_macro();
5987 }
5988 #else
5989 #define pgetc_macro()   pgetc_as_macro()
5990 static int
5991 pgetc(void)
5992 {
5993         return pgetc_macro();
5994 }
5995 #endif
5996
5997
5998 /*
5999  * Same as pgetc(), but ignores PEOA.
6000  */
6001 #ifdef CONFIG_ASH_ALIAS
6002 static int pgetc2(void)
6003 {
6004         int c;
6005
6006         do {
6007                 c = pgetc_macro();
6008         } while (c == PEOA);
6009         return c;
6010 }
6011 #else
6012 static inline int pgetc2(void)
6013 {
6014         return pgetc_macro();
6015 }
6016 #endif
6017
6018
6019 #ifdef CONFIG_FEATURE_COMMAND_EDITING
6020 static const char *cmdedit_prompt;
6021 static inline void putprompt(const char *s)
6022 {
6023         cmdedit_prompt = s;
6024 }
6025 #else
6026 static inline void putprompt(const char *s)
6027 {
6028         out2str(s);
6029 }
6030 #endif
6031
6032 static inline int
6033 preadfd(void)
6034 {
6035         int nr;
6036         char *buf =  parsefile->buf;
6037         parsenextc = buf;
6038
6039 retry:
6040 #ifdef CONFIG_FEATURE_COMMAND_EDITING
6041         if (!iflag || parsefile->fd)
6042                 nr = safe_read(parsefile->fd, buf, BUFSIZ - 1);
6043         else {
6044                 nr = cmdedit_read_input((char *) cmdedit_prompt, buf);
6045                 if(nr == 0) {
6046                         /* Ctrl+C presend */
6047                         raise(SIGINT);
6048                         goto retry;
6049                 }
6050                 if(nr < 0) {
6051                         /* Ctrl+D presend */
6052                         nr = 0;
6053                 }
6054         }
6055 #else
6056         nr = safe_read(parsefile->fd, buf, BUFSIZ - 1);
6057 #endif
6058
6059         if (nr < 0) {
6060                 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
6061                         int flags = fcntl(0, F_GETFL, 0);
6062                         if (flags >= 0 && flags & O_NONBLOCK) {
6063                                 flags &=~ O_NONBLOCK;
6064                                 if (fcntl(0, F_SETFL, flags) >= 0) {
6065                                         out2str("sh: turning off NDELAY mode\n");
6066                                         goto retry;
6067                                 }
6068                         }
6069                 }
6070         }
6071         return nr;
6072 }
6073
6074 /*
6075  * Refill the input buffer and return the next input character:
6076  *
6077  * 1) If a string was pushed back on the input, pop it;
6078  * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading
6079  *    from a string so we can't refill the buffer, return EOF.
6080  * 3) If the is more stuff in this buffer, use it else call read to fill it.
6081  * 4) Process input up to the next newline, deleting nul characters.
6082  */
6083
6084 int
6085 preadbuffer(void)
6086 {
6087         char *p, *q;
6088         int more;
6089         char savec;
6090
6091         while (parsefile->strpush) {
6092 #ifdef CONFIG_ASH_ALIAS
6093                 if (parsenleft == -1 && parsefile->strpush->ap &&
6094                         parsenextc[-1] != ' ' && parsenextc[-1] != '\t') {
6095                         return PEOA;
6096                 }
6097 #endif
6098                 popstring();
6099                 if (--parsenleft >= 0)
6100                         return (*parsenextc++);
6101         }
6102         if (parsenleft == EOF_NLEFT || parsefile->buf == NULL)
6103                 return PEOF;
6104         flushall();
6105
6106 again:
6107         if (parselleft <= 0) {
6108                 if ((parselleft = preadfd()) <= 0) {
6109                         parselleft = parsenleft = EOF_NLEFT;
6110                         return PEOF;
6111                 }
6112         }
6113
6114         q = p = parsenextc;
6115
6116         /* delete nul characters */
6117         for (more = 1; more;) {
6118                 switch (*p) {
6119                 case '\0':
6120                         p++;    /* Skip nul */
6121                         goto check;
6122
6123                 case '\n':
6124                         parsenleft = q - parsenextc;
6125                         more = 0; /* Stop processing here */
6126                         break;
6127
6128                 }
6129
6130                 *q++ = *p++;
6131 check:
6132                 if (--parselleft <= 0 && more) {
6133                         parsenleft = q - parsenextc - 1;
6134                         if (parsenleft < 0)
6135                                 goto again;
6136                         more = 0;
6137                 }
6138         }
6139
6140         savec = *q;
6141         *q = '\0';
6142
6143         if (vflag) {
6144                 out2str(parsenextc);
6145         }
6146
6147         *q = savec;
6148
6149         return *parsenextc++;
6150 }
6151
6152 /*
6153  * Undo the last call to pgetc.  Only one character may be pushed back.
6154  * PEOF may be pushed back.
6155  */
6156
6157 void
6158 pungetc(void)
6159 {
6160         parsenleft++;
6161         parsenextc--;
6162 }
6163
6164 /*
6165  * Push a string back onto the input at this current parsefile level.
6166  * We handle aliases this way.
6167  */
6168 void
6169 pushstring(char *s, void *ap)
6170 {
6171         struct strpush *sp;
6172         size_t len;
6173
6174         len = strlen(s);
6175         INTOFF;
6176 /*dprintf("*** calling pushstring: %s, %d\n", s, len);*/
6177         if (parsefile->strpush) {
6178                 sp = ckmalloc(sizeof (struct strpush));
6179                 sp->prev = parsefile->strpush;
6180                 parsefile->strpush = sp;
6181         } else
6182                 sp = parsefile->strpush = &(parsefile->basestrpush);
6183         sp->prevstring = parsenextc;
6184         sp->prevnleft = parsenleft;
6185 #ifdef CONFIG_ASH_ALIAS
6186         sp->ap = (struct alias *)ap;
6187         if (ap) {
6188                 ((struct alias *)ap)->flag |= ALIASINUSE;
6189                 sp->string = s;
6190         }
6191 #endif
6192         parsenextc = s;
6193         parsenleft = len;
6194         INTON;
6195 }
6196
6197 void
6198 popstring(void)
6199 {
6200         struct strpush *sp = parsefile->strpush;
6201
6202         INTOFF;
6203 #ifdef CONFIG_ASH_ALIAS
6204         if (sp->ap) {
6205                 if (parsenextc[-1] == ' ' || parsenextc[-1] == '\t') {
6206                         checkkwd |= CHKALIAS;
6207                 }
6208                 if (sp->string != sp->ap->val) {
6209                         ckfree(sp->string);
6210                 }
6211                 sp->ap->flag &= ~ALIASINUSE;
6212                 if (sp->ap->flag & ALIASDEAD) {
6213                         unalias(sp->ap->name);
6214                 }
6215         }
6216 #endif
6217         parsenextc = sp->prevstring;
6218         parsenleft = sp->prevnleft;
6219 /*dprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/
6220         parsefile->strpush = sp->prev;
6221         if (sp != &(parsefile->basestrpush))
6222                 ckfree(sp);
6223         INTON;
6224 }
6225
6226 /*
6227  * Set the input to take input from a file.  If push is set, push the
6228  * old input onto the stack first.
6229  */
6230
6231 void
6232 setinputfile(const char *fname, int push)
6233 {
6234         int fd;
6235         int fd2;
6236
6237         INTOFF;
6238         if ((fd = open(fname, O_RDONLY)) < 0)
6239                 error("Can't open %s", fname);
6240         if (fd < 10) {
6241                 fd2 = copyfd(fd, 10);
6242                 close(fd);
6243                 if (fd2 < 0)
6244                         error("Out of file descriptors");
6245                 fd = fd2;
6246         }
6247         setinputfd(fd, push);
6248         INTON;
6249 }
6250
6251
6252 /*
6253  * Like setinputfile, but takes an open file descriptor.  Call this with
6254  * interrupts off.
6255  */
6256
6257 static void
6258 setinputfd(int fd, int push)
6259 {
6260         (void) fcntl(fd, F_SETFD, FD_CLOEXEC);
6261         if (push) {
6262                 pushfile();
6263                 parsefile->buf = 0;
6264         }
6265         parsefile->fd = fd;
6266         if (parsefile->buf == NULL)
6267                 parsefile->buf = ckmalloc(IBUFSIZ);
6268         parselleft = parsenleft = 0;
6269         plinno = 1;
6270 }
6271
6272
6273 /*
6274  * Like setinputfile, but takes input from a string.
6275  */
6276
6277 static void
6278 setinputstring(char *string)
6279 {
6280         INTOFF;
6281         pushfile();
6282         parsenextc = string;
6283         parsenleft = strlen(string);
6284         parsefile->buf = NULL;
6285         plinno = 1;
6286         INTON;
6287 }
6288
6289
6290 /*
6291  * To handle the "." command, a stack of input files is used.  Pushfile
6292  * adds a new entry to the stack and popfile restores the previous level.
6293  */
6294
6295 static void
6296 pushfile(void)
6297 {
6298         struct parsefile *pf;
6299
6300         parsefile->nleft = parsenleft;
6301         parsefile->lleft = parselleft;
6302         parsefile->nextc = parsenextc;
6303         parsefile->linno = plinno;
6304         pf = (struct parsefile *)ckmalloc(sizeof (struct parsefile));
6305         pf->prev = parsefile;
6306         pf->fd = -1;
6307         pf->strpush = NULL;
6308         pf->basestrpush.prev = NULL;
6309         parsefile = pf;
6310 }
6311
6312
6313 static void
6314 popfile(void)
6315 {
6316         struct parsefile *pf = parsefile;
6317
6318         INTOFF;
6319         if (pf->fd >= 0)
6320                 close(pf->fd);
6321         if (pf->buf)
6322                 ckfree(pf->buf);
6323         while (pf->strpush)
6324                 popstring();
6325         parsefile = pf->prev;
6326         ckfree(pf);
6327         parsenleft = parsefile->nleft;
6328         parselleft = parsefile->lleft;
6329         parsenextc = parsefile->nextc;
6330         plinno = parsefile->linno;
6331         INTON;
6332 }
6333
6334
6335 /*
6336  * Return to top level.
6337  */
6338
6339 static void
6340 popallfiles(void)
6341 {
6342         while (parsefile != &basepf)
6343                 popfile();
6344 }
6345
6346
6347 /*
6348  * Close the file(s) that the shell is reading commands from.  Called
6349  * after a fork is done.
6350  */
6351
6352 static void
6353 closescript(void)
6354 {
6355         popallfiles();
6356         if (parsefile->fd > 0) {
6357                 close(parsefile->fd);
6358                 parsefile->fd = 0;
6359         }
6360 }
6361
6362 /*      $NetBSD: jobs.c,v 1.56 2002/11/25 12:13:03 agc Exp $    */
6363
6364 /* mode flags for set_curjob */
6365 #define CUR_DELETE 2
6366 #define CUR_RUNNING 1
6367 #define CUR_STOPPED 0
6368
6369 /* mode flags for dowait */
6370 #define DOWAIT_NORMAL 0
6371 #define DOWAIT_BLOCK 1
6372
6373 /* array of jobs */
6374 static struct job *jobtab;
6375 /* size of array */
6376 static unsigned njobs;
6377 #if JOBS
6378 /* pgrp of shell on invocation */
6379 static int initialpgrp;
6380 static int ttyfd = -1;
6381 #endif
6382 /* current job */
6383 static struct job *curjob;
6384 /* number of presumed living untracked jobs */
6385 static int jobless;
6386
6387 static void set_curjob(struct job *, unsigned);
6388 #if JOBS
6389 static int restartjob(struct job *, int);
6390 static void xtcsetpgrp(int, pid_t);
6391 static char *commandtext(union node *);
6392 static void cmdlist(union node *, int);
6393 static void cmdtxt(union node *);
6394 static void cmdputs(const char *);
6395 static void showpipe(struct job *, FILE *);
6396 #endif
6397 static int sprint_status(char *, int, int);
6398 static void freejob(struct job *);
6399 static struct job *getjob(const char *, int);
6400 static struct job *growjobtab(void);
6401 static void forkchild(struct job *, union node *, int);
6402 static void forkparent(struct job *, union node *, int, pid_t);
6403 static int dowait(int, struct job *);
6404 static int getstatus(struct job *);
6405
6406 static void
6407 set_curjob(struct job *jp, unsigned mode)
6408 {
6409         struct job *jp1;
6410         struct job **jpp, **curp;
6411
6412         /* first remove from list */
6413         jpp = curp = &curjob;
6414         do {
6415                 jp1 = *jpp;
6416                 if (jp1 == jp)
6417                         break;
6418                 jpp = &jp1->prev_job;
6419         } while (1);
6420         *jpp = jp1->prev_job;
6421
6422         /* Then re-insert in correct position */
6423         jpp = curp;
6424         switch (mode) {
6425         default:
6426 #ifdef DEBUG
6427                 abort();
6428 #endif
6429         case CUR_DELETE:
6430                 /* job being deleted */
6431                 break;
6432         case CUR_RUNNING:
6433                 /* newly created job or backgrounded job,
6434                    put after all stopped jobs. */
6435                 do {
6436                         jp1 = *jpp;
6437 #ifdef JOBS
6438                         if (!jp1 || jp1->state != JOBSTOPPED)
6439 #endif
6440                                 break;
6441                         jpp = &jp1->prev_job;
6442                 } while (1);
6443                 /* FALLTHROUGH */
6444 #ifdef JOBS
6445         case CUR_STOPPED:
6446 #endif
6447                 /* newly stopped job - becomes curjob */
6448                 jp->prev_job = *jpp;
6449                 *jpp = jp;
6450                 break;
6451         }
6452 }
6453
6454 #if JOBS
6455 /*
6456  * Turn job control on and off.
6457  *
6458  * Note:  This code assumes that the third arg to ioctl is a character
6459  * pointer, which is true on Berkeley systems but not System V.  Since
6460  * System V doesn't have job control yet, this isn't a problem now.
6461  *
6462  * Called with interrupts off.
6463  */
6464
6465 void
6466 setjobctl(int on)
6467 {
6468         int fd;
6469         int pgrp;
6470
6471         if (on == jobctl || rootshell == 0)
6472                 return;
6473         if (on) {
6474                 int ofd;
6475                 ofd = fd = open(_PATH_TTY, O_RDWR);
6476                 if (fd < 0) {
6477                         fd += 3;
6478                         while (!isatty(fd) && --fd >= 0)
6479                                 ;
6480                 }
6481                 fd = fcntl(fd, F_DUPFD, 10);
6482                 close(ofd);
6483                 if (fd < 0)
6484                         goto out;
6485                 fcntl(fd, F_SETFD, FD_CLOEXEC);
6486                 do { /* while we are in the background */
6487                         if ((pgrp = tcgetpgrp(fd)) < 0) {
6488 out:
6489                                 sh_warnx("can't access tty; job control turned off");
6490                                 mflag = on = 0;
6491                                 goto close;
6492                         }
6493                         if (pgrp == getpgrp())
6494                                 break;
6495                         killpg(0, SIGTTIN);
6496                 } while (1);
6497                 initialpgrp = pgrp;
6498
6499                 setsignal(SIGTSTP);
6500                 setsignal(SIGTTOU);
6501                 setsignal(SIGTTIN);
6502                 pgrp = rootpid;
6503                 setpgid(0, pgrp);
6504                 xtcsetpgrp(fd, pgrp);
6505         } else {
6506                 /* turning job control off */
6507                 fd = ttyfd;
6508                 pgrp = initialpgrp;
6509                 xtcsetpgrp(fd, pgrp);
6510                 setpgid(0, pgrp);
6511                 setsignal(SIGTSTP);
6512                 setsignal(SIGTTOU);
6513                 setsignal(SIGTTIN);
6514 close:
6515                 close(fd);
6516                 fd = -1;
6517         }
6518         ttyfd = fd;
6519         jobctl = on;
6520 }
6521
6522 static int
6523 killcmd(int argc, char **argv)
6524 {
6525         int signo = -1;
6526         int list = 0;
6527         int i;
6528         pid_t pid;
6529         struct job *jp;
6530
6531         if (argc <= 1) {
6532 usage:
6533                 error(
6534 "Usage: kill [-s sigspec | -signum | -sigspec] [pid | job]... or\n"
6535 "kill -l [exitstatus]"
6536                 );
6537         }
6538
6539         if (**++argv == '-') {
6540                 signo = decode_signal(*argv + 1, 1);
6541                 if (signo < 0) {
6542                         int c;
6543
6544                         while ((c = nextopt("ls:")) != '\0')
6545                                 switch (c) {
6546                                 default:
6547 #ifdef DEBUG
6548                                         abort();
6549 #endif
6550                                 case 'l':
6551                                         list = 1;
6552                                         break;
6553                                 case 's':
6554                                         signo = decode_signal(optionarg, 1);
6555                                         if (signo < 0) {
6556                                                 error(
6557                                                         "invalid signal number or name: %s",
6558                                                         optionarg
6559                                                 );
6560                                         }
6561                                         break;
6562                                 }
6563                         argv = argptr;
6564                 } else
6565                         argv++;
6566         }
6567
6568         if (!list && signo < 0)
6569                 signo = SIGTERM;
6570
6571         if ((signo < 0 || !*argv) ^ list) {
6572                 goto usage;
6573         }
6574
6575         if (list) {
6576                 const char *name;
6577
6578                 if (!*argv) {
6579                         for (i = 1; i < NSIG; i++) {
6580                                 name = u_signal_names(0, &i, 1);
6581                                 if (name)
6582                                         out1fmt(snlfmt, name);
6583                         }
6584                         return 0;
6585                 }
6586                 name = u_signal_names(*argptr, &signo, -1);
6587                 if (name)
6588                         out1fmt(snlfmt, name);
6589                 else
6590                         error("invalid signal number or exit status: %s", *argptr);
6591                 return 0;
6592         }
6593
6594         i = 0;
6595         do {
6596                 if (**argv == '%') {
6597                         jp = getjob(*argv, 0);
6598                         pid = -jp->ps[0].pid;
6599                 } else
6600                         pid = number(*argv);
6601                 if (kill(pid, signo) != 0) {
6602                         sh_warnx("%m\n");
6603                         i = 1;
6604                 }
6605         } while (*++argv);
6606
6607         return i;
6608 }
6609 #endif /* JOBS */
6610
6611 #if defined(JOBS) || defined(DEBUG)
6612 static int
6613 jobno(const struct job *jp)
6614 {
6615         return jp - jobtab + 1;
6616 }
6617 #endif
6618
6619 #ifdef JOBS
6620 static int
6621 fgcmd(int argc, char **argv)
6622 {
6623         struct job *jp;
6624         FILE *out;
6625         int mode;
6626         int retval;
6627
6628         mode = (**argv == 'f') ? FORK_FG : FORK_BG;
6629         nextopt(nullstr);
6630         argv = argptr;
6631         out = stdout;
6632         do {
6633                 jp = getjob(*argv, 1);
6634                 if (mode == FORK_BG) {
6635                         set_curjob(jp, CUR_RUNNING);
6636                         fprintf(out, "[%d] ", jobno(jp));
6637                 }
6638                 outstr(jp->ps->cmd, out);
6639                 showpipe(jp, out);
6640                 retval = restartjob(jp, mode);
6641         } while (*argv && *++argv);
6642         return retval;
6643 }
6644
6645 static int bgcmd(int, char **) __attribute__((__alias__("fgcmd")));
6646
6647
6648 static int
6649 restartjob(struct job *jp, int mode)
6650 {
6651         struct procstat *ps;
6652         int i;
6653         int status;
6654         pid_t pgid;
6655
6656         INTOFF;
6657         if (jp->state == JOBDONE)
6658                 goto out;
6659         jp->state = JOBRUNNING;
6660         pgid = jp->ps->pid;
6661         if (mode == FORK_FG)
6662                 xtcsetpgrp(ttyfd, pgid);
6663         killpg(pgid, SIGCONT);
6664         ps = jp->ps;
6665         i = jp->nprocs;
6666         do {
6667                 if (WIFSTOPPED(ps->status)) {
6668                         ps->status = -1;
6669                 }
6670         } while (ps++, --i);
6671 out:
6672         status = (mode == FORK_FG) ? waitforjob(jp) : 0;
6673         INTON;
6674         return status;
6675 }
6676 #endif
6677
6678 static int
6679 sprint_status(char *s, int status, int sigonly)
6680 {
6681         int col;
6682         int st;
6683
6684         col = 0;
6685         if (!WIFEXITED(status)) {
6686 #if JOBS
6687                 if (WIFSTOPPED(status))
6688                         st = WSTOPSIG(status);
6689                 else
6690 #endif
6691                         st = WTERMSIG(status);
6692                 if (sigonly) {
6693                         if(st == SIGPIPE) {
6694                                 col = fmtstr(s, 16, "Broken pipe");
6695                                 goto out;
6696                         }
6697                         if (st == SIGINT)
6698                                 goto out;
6699 #if JOBS
6700                         if (WIFSTOPPED(status))
6701                                 goto out;
6702 #endif
6703                 }
6704                 st &= 0x7f;
6705                 col = fmtstr(s, 32, u_signal_names(NULL, &st, 0));
6706                 if (WCOREDUMP(status)) {
6707                         col += fmtstr(s + col, 16, " (core dumped)");
6708                 }
6709         } else if (!sigonly) {
6710                 st = WEXITSTATUS(status);
6711                 if (st)
6712                         col = fmtstr(s, 16, "Done(%d)", st);
6713                 else
6714                         col = fmtstr(s, 16, "Done");
6715         }
6716
6717 out:
6718         return col;
6719 }
6720
6721 #if JOBS
6722 static void
6723 showjob(FILE *out, struct job *jp, int mode)
6724 {
6725         struct procstat *ps;
6726         struct procstat *psend;
6727         int col;
6728         int indent;
6729         char s[80];
6730
6731         ps = jp->ps;
6732
6733         if (mode & SHOW_PGID) {
6734                 /* just output process (group) id of pipeline */
6735                 fprintf(out, "%d\n", ps->pid);
6736                 return;
6737         }
6738
6739         col = fmtstr(s, 16, "[%d]   ", jobno(jp));
6740         indent = col;
6741
6742         if (jp == curjob)
6743                 s[col - 2] = '+';
6744         else if (curjob && jp == curjob->prev_job)
6745                 s[col - 2] = '-';
6746
6747         if (mode & SHOW_PID)
6748                 col += fmtstr(s + col, 16, "%d ", ps->pid);
6749
6750         psend = ps + jp->nprocs;
6751
6752         if (jp->state == JOBRUNNING) {
6753                 scopy("Running", s + col);
6754                 col += strlen("Running");
6755         } else {
6756                 int status = psend[-1].status;
6757 #if JOBS
6758                 if (jp->state == JOBSTOPPED)
6759                         status = jp->stopstatus;
6760 #endif
6761                 col += sprint_status(s + col, status, 0);
6762         }
6763
6764         goto start;
6765
6766         do {
6767                 /* for each process */
6768                 col = fmtstr(s, 48, " |\n%*c%d ", indent, ' ', ps->pid) - 3;
6769
6770 start:
6771                 fprintf(out, "%s%*c%s",
6772                         s, 33 - col >= 0 ? 33 - col : 0, ' ', ps->cmd
6773                 );
6774                 if (!(mode & SHOW_PID)) {
6775                         showpipe(jp, out);
6776                         break;
6777                 }
6778                 if (++ps == psend) {
6779                         outcslow('\n', out);
6780                         break;
6781                 }
6782         } while (1);
6783
6784         jp->changed = 0;
6785
6786         if (jp->state == JOBDONE) {
6787                 TRACE(("showjob: freeing job %d\n", jobno(jp)));
6788                 freejob(jp);
6789         }
6790 }
6791
6792
6793 static int
6794 jobscmd(int argc, char **argv)
6795 {
6796         int mode, m;
6797         FILE *out;
6798
6799         mode = 0;
6800         while ((m = nextopt("lp")))
6801                 if (m == 'l')
6802                         mode = SHOW_PID;
6803                 else
6804                         mode = SHOW_PGID;
6805
6806         out = stdout;
6807         argv = argptr;
6808         if (*argv)
6809                 do
6810                         showjob(out, getjob(*argv,0), mode);
6811                 while (*++argv);
6812         else
6813                 showjobs(out, mode);
6814
6815         return 0;
6816 }
6817
6818
6819 /*
6820  * Print a list of jobs.  If "change" is nonzero, only print jobs whose
6821  * statuses have changed since the last call to showjobs.
6822  */
6823
6824 static void
6825 showjobs(FILE *out, int mode)
6826 {
6827         struct job *jp;
6828
6829         TRACE(("showjobs(%x) called\n", mode));
6830
6831         /* If not even one one job changed, there is nothing to do */
6832         while (dowait(DOWAIT_NORMAL, NULL) > 0)
6833                 continue;
6834
6835         for (jp = curjob; jp; jp = jp->prev_job) {
6836                 if (!(mode & SHOW_CHANGED) || jp->changed)
6837                         showjob(out, jp, mode);
6838         }
6839 }
6840 #endif /* JOBS */
6841
6842 /*
6843  * Mark a job structure as unused.
6844  */
6845
6846 static void
6847 freejob(struct job *jp)
6848 {
6849         struct procstat *ps;
6850         int i;
6851
6852         INTOFF;
6853         for (i = jp->nprocs, ps = jp->ps ; --i >= 0 ; ps++) {
6854                 if (ps->cmd != nullstr)
6855                         ckfree(ps->cmd);
6856         }
6857         if (jp->ps != &jp->ps0)
6858                 ckfree(jp->ps);
6859         jp->used = 0;
6860         set_curjob(jp, CUR_DELETE);
6861         INTON;
6862 }
6863
6864
6865 static int
6866 waitcmd(int argc, char **argv)
6867 {
6868         struct job *job;
6869         int retval;
6870         struct job *jp;
6871
6872         EXSIGON();
6873
6874         nextopt(nullstr);
6875         retval = 0;
6876
6877         argv = argptr;
6878         if (!*argv) {
6879                 /* wait for all jobs */
6880                 for (;;) {
6881                         jp = curjob;
6882                         while (1) {
6883                                 if (!jp) {
6884                                         /* no running procs */
6885                                         goto out;
6886                                 }
6887                                 if (jp->state == JOBRUNNING)
6888                                         break;
6889                                 jp->waited = 1;
6890                                 jp = jp->prev_job;
6891                         }
6892                         dowait(DOWAIT_BLOCK, 0);
6893                 }
6894         }
6895
6896         retval = 127;
6897         do {
6898                 if (**argv != '%') {
6899                         pid_t pid = number(*argv);
6900                         job = curjob;
6901                         goto start;
6902                         do {
6903                                 if (job->ps[job->nprocs - 1].pid == pid)
6904                                         break;
6905                                 job = job->prev_job;
6906 start:
6907                                 if (!job)
6908                                         goto repeat;
6909                         } while (1);
6910                 } else
6911                         job = getjob(*argv, 0);
6912                 /* loop until process terminated or stopped */
6913                 while (job->state == JOBRUNNING)
6914                         dowait(DOWAIT_BLOCK, 0);
6915                 job->waited = 1;
6916                 retval = getstatus(job);
6917 repeat:
6918                 ;
6919         } while (*++argv);
6920
6921 out:
6922         return retval;
6923 }
6924
6925
6926 /*
6927  * Convert a job name to a job structure.
6928  */
6929
6930 static struct job *
6931 getjob(const char *name, int getctl)
6932 {
6933         struct job *jp;
6934         struct job *found;
6935         const char *err_msg = "No such job: %s";
6936         unsigned num;
6937         int c;
6938         const char *p;
6939         char *(*match)(const char *, const char *);
6940
6941         jp = curjob;
6942         p = name;
6943         if (!p)
6944                 goto currentjob;
6945
6946         if (*p != '%')
6947                 goto err;
6948
6949         c = *++p;
6950         if (!c)
6951                 goto currentjob;
6952
6953         if (!p[1]) {
6954                 if (c == '+' || c == '%') {
6955 currentjob:
6956                         err_msg = "No current job";
6957                         goto check;
6958                 } else if (c == '-') {
6959                         if (jp)
6960                                 jp = jp->prev_job;
6961                         err_msg = "No previous job";
6962 check:
6963                         if (!jp)
6964                                 goto err;
6965                         goto gotit;
6966                 }
6967         }
6968
6969         if (is_number(p)) {
6970                 num = atoi(p);
6971                 if (num < njobs) {
6972                         jp = jobtab + num - 1;
6973                         if (jp->used)
6974                                 goto gotit;
6975                         goto err;
6976                 }
6977         }
6978
6979         match = prefix;
6980         if (*p == '?') {
6981                 match = strstr;
6982                 p++;
6983         }
6984
6985         found = 0;
6986         while (1) {
6987                 if (!jp)
6988                         goto err;
6989                 if (match(jp->ps[0].cmd, p)) {
6990                         if (found)
6991                                 goto err;
6992                         found = jp;
6993                         err_msg = "%s: ambiguous";
6994                 }
6995                 jp = jp->prev_job;
6996         }
6997
6998 gotit:
6999 #if JOBS
7000         err_msg = "job %s not created under job control";
7001         if (getctl && jp->jobctl == 0)
7002                 goto err;
7003 #endif
7004         return jp;
7005 err:
7006         error(err_msg, name);
7007 }
7008
7009
7010 /*
7011  * Return a new job structure.
7012  * Called with interrupts off.
7013  */
7014
7015 static struct job *
7016 makejob(union node *node, int nprocs)
7017 {
7018         int i;
7019         struct job *jp;
7020
7021         for (i = njobs, jp = jobtab ; ; jp++) {
7022                 if (--i < 0) {
7023                         jp = growjobtab();
7024                         break;
7025                 }
7026                 if (jp->used == 0)
7027                         break;
7028                 if (jp->state != JOBDONE || !jp->waited)
7029                         continue;
7030 #if JOBS
7031                 if (jobctl)
7032                         continue;
7033 #endif
7034                 freejob(jp);
7035                 break;
7036         }
7037         memset(jp, 0, sizeof(*jp));
7038 #if JOBS
7039         if (jobctl)
7040                 jp->jobctl = 1;
7041 #endif
7042         jp->prev_job = curjob;
7043         curjob = jp;
7044         jp->used = 1;
7045         jp->ps = &jp->ps0;
7046         if (nprocs > 1) {
7047                 jp->ps = ckmalloc(nprocs * sizeof (struct procstat));
7048         }
7049         TRACE(("makejob(0x%lx, %d) returns %%%d\n", (long)node, nprocs,
7050             jobno(jp)));
7051         return jp;
7052 }
7053
7054 static struct job *
7055 growjobtab(void)
7056 {
7057         size_t len;
7058         ptrdiff_t offset;
7059         struct job *jp, *jq;
7060
7061         len = njobs * sizeof(*jp);
7062         jq = jobtab;
7063         jp = ckrealloc(jq, len + 4 * sizeof(*jp));
7064
7065         offset = (char *)jp - (char *)jq;
7066         if (offset) {
7067                 /* Relocate pointers */
7068                 size_t l = len;
7069
7070                 jq = (struct job *)((char *)jq + l);
7071                 while (l) {
7072                         l -= sizeof(*jp);
7073                         jq--;
7074 #define joff(p) ((struct job *)((char *)(p) + l))
7075 #define jmove(p) (p) = (void *)((char *)(p) + offset)
7076                         if (likely(joff(jp)->ps == &jq->ps0))
7077                                 jmove(joff(jp)->ps);
7078                         if (joff(jp)->prev_job)
7079                                 jmove(joff(jp)->prev_job);
7080                 }
7081                 if (curjob)
7082                         jmove(curjob);
7083 #undef joff
7084 #undef jmove
7085         }
7086
7087         njobs += 4;
7088         jobtab = jp;
7089         jp = (struct job *)((char *)jp + len);
7090         jq = jp + 3;
7091         do {
7092                 jq->used = 0;
7093         } while (--jq >= jp);
7094         return jp;
7095 }
7096
7097
7098 /*
7099  * Fork off a subshell.  If we are doing job control, give the subshell its
7100  * own process group.  Jp is a job structure that the job is to be added to.
7101  * N is the command that will be evaluated by the child.  Both jp and n may
7102  * be NULL.  The mode parameter can be one of the following:
7103  *      FORK_FG - Fork off a foreground process.
7104  *      FORK_BG - Fork off a background process.
7105  *      FORK_NOJOB - Like FORK_FG, but don't give the process its own
7106  *                   process group even if job control is on.
7107  *
7108  * When job control is turned off, background processes have their standard
7109  * input redirected to /dev/null (except for the second and later processes
7110  * in a pipeline).
7111  *
7112  * Called with interrupts off.
7113  */
7114
7115 static inline void
7116 forkchild(struct job *jp, union node *n, int mode)
7117 {
7118         int wasroot;
7119
7120         TRACE(("Child shell %d\n", getpid()));
7121         wasroot = rootshell;
7122         rootshell = 0;
7123
7124         closescript();
7125         clear_traps();
7126 #if JOBS
7127         /* do job control only in root shell */
7128         jobctl = 0;
7129         if (mode != FORK_NOJOB && jp->jobctl && wasroot) {
7130                 pid_t pgrp;
7131
7132                 if (jp->nprocs == 0)
7133                         pgrp = getpid();
7134                 else
7135                         pgrp = jp->ps[0].pid;
7136                 /* This can fail because we are doing it in the parent also */
7137                 (void)setpgid(0, pgrp);
7138                 if (mode == FORK_FG)
7139                         xtcsetpgrp(ttyfd, pgrp);
7140                 setsignal(SIGTSTP);
7141                 setsignal(SIGTTOU);
7142         } else
7143 #endif
7144         if (mode == FORK_BG) {
7145                 ignoresig(SIGINT);
7146                 ignoresig(SIGQUIT);
7147                 if (jp->nprocs == 0) {
7148                         close(0);
7149                         if (open(_PATH_DEVNULL, O_RDONLY) != 0)
7150                                 error("Can't open %s", _PATH_DEVNULL);
7151                 }
7152         }
7153         if (wasroot && iflag) {
7154                 setsignal(SIGINT);
7155                 setsignal(SIGQUIT);
7156                 setsignal(SIGTERM);
7157         }
7158         for (jp = curjob; jp; jp = jp->prev_job)
7159                 freejob(jp);
7160         jobless = 0;
7161 }
7162
7163 static inline void
7164 forkparent(struct job *jp, union node *n, int mode, pid_t pid)
7165 {
7166         TRACE(("In parent shell:  child = %d\n", pid));
7167         if (!jp) {
7168                 while (jobless && dowait(DOWAIT_NORMAL, 0) > 0);
7169                 jobless++;
7170                 return;
7171         }
7172 #if JOBS
7173         if (mode != FORK_NOJOB && jp->jobctl) {
7174                 int pgrp;
7175
7176                 if (jp->nprocs == 0)
7177                         pgrp = pid;
7178                 else
7179                         pgrp = jp->ps[0].pid;
7180                 /* This can fail because we are doing it in the child also */
7181                 (void)setpgid(pid, pgrp);
7182         }
7183 #endif
7184         if (mode == FORK_BG) {
7185                 backgndpid = pid;               /* set $! */
7186                 set_curjob(jp, CUR_RUNNING);
7187         }
7188         if (jp) {
7189                 struct procstat *ps = &jp->ps[jp->nprocs++];
7190                 ps->pid = pid;
7191                 ps->status = -1;
7192                 ps->cmd = nullstr;
7193 #if JOBS
7194                 if (jobctl && n)
7195                         ps->cmd = commandtext(n);
7196 #endif
7197         }
7198 }
7199
7200 static int
7201 forkshell(struct job *jp, union node *n, int mode)
7202 {
7203         int pid;
7204
7205         TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode));
7206         pid = fork();
7207         if (pid < 0) {
7208                 TRACE(("Fork failed, errno=%d", errno));
7209                 if (jp)
7210                         freejob(jp);
7211                 error("Cannot fork");
7212         }
7213         if (pid == 0)
7214                 forkchild(jp, n, mode);
7215         else
7216                 forkparent(jp, n, mode, pid);
7217         return pid;
7218 }
7219
7220 /*
7221  * Wait for job to finish.
7222  *
7223  * Under job control we have the problem that while a child process is
7224  * running interrupts generated by the user are sent to the child but not
7225  * to the shell.  This means that an infinite loop started by an inter-
7226  * active user may be hard to kill.  With job control turned off, an
7227  * interactive user may place an interactive program inside a loop.  If
7228  * the interactive program catches interrupts, the user doesn't want
7229  * these interrupts to also abort the loop.  The approach we take here
7230  * is to have the shell ignore interrupt signals while waiting for a
7231  * forground process to terminate, and then send itself an interrupt
7232  * signal if the child process was terminated by an interrupt signal.
7233  * Unfortunately, some programs want to do a bit of cleanup and then
7234  * exit on interrupt; unless these processes terminate themselves by
7235  * sending a signal to themselves (instead of calling exit) they will
7236  * confuse this approach.
7237  *
7238  * Called with interrupts off.
7239  */
7240
7241 int
7242 waitforjob(struct job *jp)
7243 {
7244         int st;
7245
7246         TRACE(("waitforjob(%%%d) called\n", jobno(jp)));
7247         while (jp->state == JOBRUNNING) {
7248                 dowait(DOWAIT_BLOCK, jp);
7249         }
7250         st = getstatus(jp);
7251 #if JOBS
7252         if (jp->jobctl) {
7253                 xtcsetpgrp(ttyfd, rootpid);
7254                 /*
7255                  * This is truly gross.
7256                  * If we're doing job control, then we did a TIOCSPGRP which
7257                  * caused us (the shell) to no longer be in the controlling
7258                  * session -- so we wouldn't have seen any ^C/SIGINT.  So, we
7259                  * intuit from the subprocess exit status whether a SIGINT
7260                  * occurred, and if so interrupt ourselves.  Yuck.  - mycroft
7261                  */
7262                 if (jp->sigint)
7263                         raise(SIGINT);
7264         }
7265         if (jp->state == JOBDONE)
7266 #endif
7267                 freejob(jp);
7268         return st;
7269 }
7270
7271
7272 /*
7273  * Do a wait system call.  If job control is compiled in, we accept
7274  * stopped processes.  If block is zero, we return a value of zero
7275  * rather than blocking.
7276  *
7277  * System V doesn't have a non-blocking wait system call.  It does
7278  * have a SIGCLD signal that is sent to a process when one of it's
7279  * children dies.  The obvious way to use SIGCLD would be to install
7280  * a handler for SIGCLD which simply bumped a counter when a SIGCLD
7281  * was received, and have waitproc bump another counter when it got
7282  * the status of a process.  Waitproc would then know that a wait
7283  * system call would not block if the two counters were different.
7284  * This approach doesn't work because if a process has children that
7285  * have not been waited for, System V will send it a SIGCLD when it
7286  * installs a signal handler for SIGCLD.  What this means is that when
7287  * a child exits, the shell will be sent SIGCLD signals continuously
7288  * until is runs out of stack space, unless it does a wait call before
7289  * restoring the signal handler.  The code below takes advantage of
7290  * this (mis)feature by installing a signal handler for SIGCLD and
7291  * then checking to see whether it was called.  If there are any
7292  * children to be waited for, it will be.
7293  *
7294  * If neither SYSV nor BSD is defined, we don't implement nonblocking
7295  * waits at all.  In this case, the user will not be informed when
7296  * a background process until the next time she runs a real program
7297  * (as opposed to running a builtin command or just typing return),
7298  * and the jobs command may give out of date information.
7299  */
7300
7301 static inline int
7302 waitproc(int block, int *status)
7303 {
7304         int flags = 0;
7305
7306 #if JOBS
7307         if (jobctl)
7308                 flags |= WUNTRACED;
7309 #endif
7310         if (block == 0)
7311                 flags |= WNOHANG;
7312         return wait3(status, flags, (struct rusage *)NULL);
7313 }
7314
7315 /*
7316  * Wait for a process to terminate.
7317  */
7318
7319 static int
7320 dowait(int block, struct job *job)
7321 {
7322         int pid;
7323         int status;
7324         struct job *jp;
7325         struct job *thisjob;
7326         int state;
7327
7328         TRACE(("dowait(%d) called\n", block));
7329         pid = waitproc(block, &status);
7330         TRACE(("wait returns pid %d, status=%d\n", pid, status));
7331         if (pid <= 0)
7332                 return pid;
7333         INTOFF;
7334         thisjob = NULL;
7335         for (jp = curjob; jp; jp = jp->prev_job) {
7336                 struct procstat *sp;
7337                 struct procstat *spend;
7338                 if (jp->state == JOBDONE)
7339                         continue;
7340                 state = JOBDONE;
7341                 spend = jp->ps + jp->nprocs;
7342                 sp = jp->ps;
7343                 do {
7344                         if (sp->pid == pid) {
7345                                 TRACE(("Job %d: changing status of proc %d from 0x%x to 0x%x\n", jobno(jp), pid, sp->status, status));
7346                                 sp->status = status;
7347                                 thisjob = jp;
7348                         }
7349                         if (sp->status == -1)
7350                                 state = JOBRUNNING;
7351 #ifdef JOBS
7352                         if (state == JOBRUNNING)
7353                                 continue;
7354                         if (WIFSTOPPED(sp->status)) {
7355                                 jp->stopstatus = sp->status;
7356                                 state = JOBSTOPPED;
7357                         }
7358 #endif
7359                 } while (++sp < spend);
7360                 if (thisjob)
7361                         goto gotjob;
7362         }
7363 #ifdef JOBS
7364         if (!WIFSTOPPED(status))
7365 #endif
7366
7367                 jobless--;
7368         goto out;
7369
7370 gotjob:
7371         if (state != JOBRUNNING) {
7372                 thisjob->changed = 1;
7373
7374                 if (thisjob->state != state) {
7375                         TRACE(("Job %d: changing state from %d to %d\n", jobno(thisjob), thisjob->state, state));
7376                         thisjob->state = state;
7377 #ifdef JOBS
7378                         if (state == JOBSTOPPED) {
7379                                 set_curjob(thisjob, CUR_STOPPED);
7380                         }
7381 #endif
7382                 }
7383         }
7384
7385 out:
7386         INTON;
7387
7388         if (thisjob && thisjob == job) {
7389                 char s[48 + 1];
7390                 int len;
7391
7392                 len = sprint_status(s, status, 1);
7393                 if (len) {
7394                         s[len] = '\n';
7395                         s[len + 1] = 0;
7396                         out2str(s);
7397                 }
7398         }
7399         return pid;
7400 }
7401
7402
7403 /*
7404  * return 1 if there are stopped jobs, otherwise 0
7405  */
7406
7407 int
7408 stoppedjobs(void)
7409 {
7410         struct job *jp;
7411         int retval;
7412
7413         retval = 0;
7414         if (job_warning)
7415                 goto out;
7416         jp = curjob;
7417         if (jp && jp->state == JOBSTOPPED) {
7418                 out2str("You have stopped jobs.\n");
7419                 job_warning = 2;
7420                 retval++;
7421         }
7422
7423 out:
7424         return retval;
7425 }
7426
7427 /*
7428  * Return a string identifying a command (to be printed by the
7429  * jobs command).
7430  */
7431
7432 #if JOBS
7433 static char *cmdnextc;
7434
7435 static char *
7436 commandtext(union node *n)
7437 {
7438         char *name;
7439
7440         STARTSTACKSTR(cmdnextc);
7441         cmdtxt(n);
7442         name = stackblock();
7443         TRACE(("commandtext: name %p, end %p\n\t\"%s\"\n",
7444                 name, cmdnextc, cmdnextc));
7445         return savestr(name);
7446 }
7447
7448 static void
7449 cmdtxt(union node *n)
7450 {
7451         union node *np;
7452         struct nodelist *lp;
7453         const char *p;
7454         char s[2];
7455
7456         switch (n->type) {
7457         default:
7458 #if DEBUG
7459                 abort();
7460 #endif
7461         case NPIPE:
7462                 lp = n->npipe.cmdlist;
7463                 for (;;) {
7464                         cmdtxt(lp->n);
7465                         lp = lp->next;
7466                         if (!lp)
7467                                 break;
7468                         cmdputs(" | ");
7469                 }
7470                 break;
7471         case NSEMI:
7472                 p = "; ";
7473                 goto binop;
7474         case NAND:
7475                 p = " && ";
7476                 goto binop;
7477         case NOR:
7478                 p = " || ";
7479 binop:
7480                 cmdtxt(n->nbinary.ch1);
7481                 cmdputs(p);
7482                 n = n->nbinary.ch2;
7483                 goto donode;
7484         case NREDIR:
7485         case NBACKGND:
7486                 n = n->nredir.n;
7487                 goto donode;
7488         case NNOT:
7489                 cmdputs("!");
7490                 n = n->nnot.com;
7491 donode:
7492                 cmdtxt(n);
7493                 break;
7494         case NIF:
7495                 cmdputs("if ");
7496                 cmdtxt(n->nif.test);
7497                 cmdputs("; then ");
7498                 n = n->nif.ifpart;
7499                 if (n->nif.elsepart) {
7500                         cmdtxt(n);
7501                         cmdputs("; else ");
7502                         n = n->nif.elsepart;
7503                 }
7504                 p = "; fi";
7505                 goto dotail;
7506         case NSUBSHELL:
7507                 cmdputs("(");
7508                 n = n->nredir.n;
7509                 p = ")";
7510                 goto dotail;
7511         case NWHILE:
7512                 p = "while ";
7513                 goto until;
7514         case NUNTIL:
7515                 p = "until ";
7516 until:
7517                 cmdputs(p);
7518                 cmdtxt(n->nbinary.ch1);
7519                 n = n->nbinary.ch2;
7520                 p = "; done";
7521 dodo:
7522                 cmdputs("; do ");
7523 dotail:
7524                 cmdtxt(n);
7525                 goto dotail2;
7526         case NFOR:
7527                 cmdputs("for ");
7528                 cmdputs(n->nfor.var);
7529                 cmdputs(" in ");
7530                 cmdlist(n->nfor.args, 1);
7531                 n = n->nfor.body;
7532                 p = "; done";
7533                 goto dodo;
7534         case NDEFUN:
7535                 cmdputs(n->narg.text);
7536                 p = "() { ... }";
7537                 goto dotail2;
7538         case NCMD:
7539                 cmdlist(n->ncmd.args, 1);
7540                 cmdlist(n->ncmd.redirect, 0);
7541                 break;
7542         case NARG:
7543                 p = n->narg.text;
7544 dotail2:
7545                 cmdputs(p);
7546                 break;
7547         case NHERE:
7548         case NXHERE:
7549                 p = "<<...";
7550                 goto dotail2;
7551         case NCASE:
7552                 cmdputs("case ");
7553                 cmdputs(n->ncase.expr->narg.text);
7554                 cmdputs(" in ");
7555                 for (np = n->ncase.cases; np; np = np->nclist.next) {
7556                         cmdtxt(np->nclist.pattern);
7557                         cmdputs(") ");
7558                         cmdtxt(np->nclist.body);
7559                         cmdputs(";; ");
7560                 }
7561                 p = "esac";
7562                 goto dotail2;
7563         case NTO:
7564                 p = ">";
7565                 goto redir;
7566         case NCLOBBER:
7567                 p = ">|";
7568                 goto redir;
7569         case NAPPEND:
7570                 p = ">>";
7571                 goto redir;
7572         case NTOFD:
7573                 p = ">&";
7574                 goto redir;
7575         case NFROM:
7576                 p = "<";
7577                 goto redir;
7578         case NFROMFD:
7579                 p = "<&";
7580                 goto redir;
7581         case NFROMTO:
7582                 p = "<>";
7583 redir:
7584                 s[0] = n->nfile.fd + '0';
7585                 s[1] = '\0';
7586                 cmdputs(s);
7587                 cmdputs(p);
7588                 if (n->type == NTOFD || n->type == NFROMFD) {
7589                         s[0] = n->ndup.dupfd + '0';
7590                         p = s;
7591                         goto dotail2;
7592                 } else {
7593                         n = n->nfile.fname;
7594                         goto donode;
7595                 }
7596         }
7597 }
7598
7599 static void
7600 cmdlist(union node *np, int sep)
7601 {
7602         for (; np; np = np->narg.next) {
7603                 if (!sep)
7604                         cmdputs(spcstr);
7605                 cmdtxt(np);
7606                 if (sep && np->narg.next)
7607                         cmdputs(spcstr);
7608         }
7609 }
7610
7611 static void
7612 cmdputs(const char *s)
7613 {
7614         const char *p, *str;
7615         char c, cc[2] = " ";
7616         char *nextc;
7617         int subtype = 0;
7618         int quoted = 0;
7619         static const char *const vstype[16] = {
7620                 nullstr, "}", "-", "+", "?", "=",
7621                 "#", "##", "%", "%%"
7622         };
7623
7624         nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc);
7625         p = s;
7626         while ((c = *p++) != 0) {
7627                 str = 0;
7628                 switch (c) {
7629                 case CTLESC:
7630                         c = *p++;
7631                         break;
7632                 case CTLVAR:
7633                         subtype = *p++;
7634                         if ((subtype & VSTYPE) == VSLENGTH)
7635                                 str = "${#";
7636                         else
7637                                 str = "${";
7638                         if (!(subtype & VSQUOTE) != !(quoted & 1)) {
7639                                 quoted ^= 1;
7640                                 c = '"';
7641                         } else
7642                                 goto dostr;
7643                         break;
7644                 case CTLENDVAR:
7645                         quoted >>= 1;
7646                         subtype = 0;
7647                         if (quoted & 1) {
7648                                 str = "\"}";
7649                                 goto dostr;
7650                         }
7651                         c = '}';
7652                         break;
7653                 case CTLBACKQ:
7654                         str = "$(...)";
7655                         goto dostr;
7656                 case CTLBACKQ+CTLQUOTE:
7657                         str = "\"$(...)\"";
7658                         goto dostr;
7659 #ifdef CONFIG_ASH_MATH_SUPPORT
7660                 case CTLARI:
7661                         str = "$((";
7662                         goto dostr;
7663                 case CTLENDARI:
7664                         str = "))";
7665                         goto dostr;
7666 #endif
7667                 case CTLQUOTEMARK:
7668                         quoted ^= 1;
7669                         c = '"';
7670                         break;
7671                 case '=':
7672                         if (subtype == 0)
7673                                 break;
7674                         str = vstype[subtype & VSTYPE];
7675                         if (subtype & VSNUL)
7676                                 c = ':';
7677                         else
7678                                 c = *str++;
7679                         if (c != '}')
7680                                 quoted <<= 1;
7681                         break;
7682                 case '\'':
7683                 case '\\':
7684                 case '"':
7685                 case '$':
7686                         /* These can only happen inside quotes */
7687                         cc[0] = c;
7688                         str = cc;
7689                         c = '\\';
7690                         break;
7691                 default:
7692                         break;
7693                 }
7694                 USTPUTC(c, nextc);
7695                 if (!str)
7696                         continue;
7697 dostr:
7698                 while ((c = *str++)) {
7699                         USTPUTC(c, nextc);
7700                 }
7701         }
7702         if (quoted & 1) {
7703                 USTPUTC('"', nextc);
7704         }
7705         *nextc = 0;
7706         cmdnextc = nextc;
7707 }
7708
7709
7710 static void
7711 showpipe(struct job *jp, FILE *out)
7712 {
7713         struct procstat *sp;
7714         struct procstat *spend;
7715
7716         spend = jp->ps + jp->nprocs;
7717         for (sp = jp->ps + 1; sp < spend; sp++)
7718                 fprintf(out, " | %s", sp->cmd);
7719         outcslow('\n', out);
7720         flushall();
7721 }
7722
7723 static void
7724 xtcsetpgrp(int fd, pid_t pgrp)
7725 {
7726         if (tcsetpgrp(fd, pgrp))
7727                 error("Cannot set tty process group (%m)");
7728 }
7729 #endif /* JOBS */
7730
7731 static int
7732 getstatus(struct job *job) {
7733         int status;
7734         int retval;
7735
7736         status = job->ps[job->nprocs - 1].status;
7737         retval = WEXITSTATUS(status);
7738         if (!WIFEXITED(status)) {
7739 #if JOBS
7740                 retval = WSTOPSIG(status);
7741                 if (!WIFSTOPPED(status))
7742 #endif
7743                 {
7744                         /* XXX: limits number of signals */
7745                         retval = WTERMSIG(status);
7746 #if JOBS
7747                         if (retval == SIGINT)
7748                                 job->sigint = 1;
7749 #endif
7750                 }
7751                 retval += 128;
7752         }
7753         TRACE(("getstatus: job %d, nproc %d, status %x, retval %x\n",
7754                 jobno(job), job->nprocs, status, retval));
7755         return retval;
7756 }
7757
7758 #ifdef CONFIG_ASH_MAIL
7759 /*      $NetBSD: mail.c,v 1.15 2002/11/24 22:35:40 christos Exp $       */
7760
7761 /*
7762  * Routines to check for mail.  (Perhaps make part of main.c?)
7763  */
7764
7765 #define MAXMBOXES 10
7766
7767 /* times of mailboxes */
7768 static time_t mailtime[MAXMBOXES];
7769 /* Set if MAIL or MAILPATH is changed. */
7770 static int mail_var_path_changed;
7771
7772
7773
7774 /*
7775  * Print appropriate message(s) if mail has arrived.
7776  * If mail_var_path_changed is set,
7777  * then the value of MAIL has mail_var_path_changed,
7778  * so we just update the values.
7779  */
7780
7781 static void
7782 chkmail(void)
7783 {
7784         const char *mpath;
7785         char *p;
7786         char *q;
7787         time_t *mtp;
7788         struct stackmark smark;
7789         struct stat statb;
7790
7791         setstackmark(&smark);
7792         mpath = mpathset() ? mpathval() : mailval();
7793         for (mtp = mailtime; mtp < mailtime + MAXMBOXES; mtp++) {
7794                 p = padvance(&mpath, nullstr);
7795                 if (p == NULL)
7796                         break;
7797                 if (*p == '\0')
7798                         continue;
7799                 for (q = p ; *q ; q++);
7800 #ifdef DEBUG
7801                 if (q[-1] != '/')
7802                         abort();
7803 #endif
7804                 q[-1] = '\0';                   /* delete trailing '/' */
7805                 if (stat(p, &statb) < 0) {
7806                         *mtp = 0;
7807                         continue;
7808                 }
7809                 if (!mail_var_path_changed && statb.st_mtime != *mtp) {
7810                         fprintf(
7811                                 stderr, snlfmt,
7812                                 pathopt ? pathopt : "you have mail"
7813                         );
7814                 }
7815                 *mtp = statb.st_mtime;
7816         }
7817         mail_var_path_changed = 0;
7818         popstackmark(&smark);
7819 }
7820
7821
7822 static void
7823 changemail(const char *val)
7824 {
7825         mail_var_path_changed++;
7826 }
7827
7828 #endif /* CONFIG_ASH_MAIL */
7829
7830 /*      $NetBSD: main.c,v 1.46 2002/12/11 19:12:18 christos Exp $       */
7831
7832
7833 #if PROFILE
7834 static short profile_buf[16384];
7835 extern int etext();
7836 #endif
7837
7838 static int isloginsh;
7839
7840 static void read_profile(const char *);
7841
7842 /*
7843  * Main routine.  We initialize things, parse the arguments, execute
7844  * profiles if we're a login shell, and then call cmdloop to execute
7845  * commands.  The setjmp call sets up the location to jump to when an
7846  * exception occurs.  When an exception occurs the variable "state"
7847  * is used to figure out how far we had gotten.
7848  */
7849
7850 int
7851 ash_main(int argc, char **argv)
7852 {
7853         char *shinit;
7854         volatile int state;
7855         struct jmploc jmploc;
7856         struct stackmark smark;
7857
7858 #ifdef __GLIBC__
7859         dash_errno = __errno_location();
7860 #endif
7861
7862 #if PROFILE
7863         monitor(4, etext, profile_buf, sizeof profile_buf, 50);
7864 #endif
7865         state = 0;
7866         if (setjmp(jmploc.loc)) {
7867                 int status;
7868                 int e;
7869
7870                 reset();
7871
7872                 e = exception;
7873                 switch (exception) {
7874                 case EXEXEC:
7875                         status = exerrno;
7876                         break;
7877
7878                 case EXERROR:
7879                         status = 2;
7880                         break;
7881
7882                 default:
7883                         status = exitstatus;
7884                         break;
7885                 }
7886                 exitstatus = status;
7887
7888                 if (e == EXEXIT || state == 0 || iflag == 0 || ! rootshell)
7889                         exitshell();
7890
7891                 if (e == EXINT) {
7892                         outcslow('\n', stderr);
7893                 }
7894                 popstackmark(&smark);
7895                 FORCEINTON;                             /* enable interrupts */
7896                 if (state == 1)
7897                         goto state1;
7898                 else if (state == 2)
7899                         goto state2;
7900                 else if (state == 3)
7901                         goto state3;
7902                 else
7903                         goto state4;
7904         }
7905         handler = &jmploc;
7906 #ifdef DEBUG
7907         opentrace();
7908         trputs("Shell args:  ");  trargs(argv);
7909 #endif
7910         rootpid = getpid();
7911         rootshell = 1;
7912         init();
7913         setstackmark(&smark);
7914         procargs(argc, argv);
7915 #ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
7916         if ( iflag ) {
7917                 const char *hp = lookupvar("HISTFILE");
7918
7919                 if(hp == NULL ) {
7920                         hp = lookupvar("HOME");
7921                         if(hp != NULL) {
7922                                 char *defhp = concat_path_file(hp, ".ash_history");
7923                                 setvar("HISTFILE", defhp, 0);
7924                                 free(defhp);
7925                         }
7926                 }
7927         }
7928 #endif
7929         if (argv[0] && argv[0][0] == '-')
7930                 isloginsh = 1;
7931         if (isloginsh) {
7932                 state = 1;
7933                 read_profile("/etc/profile");
7934 state1:
7935                 state = 2;
7936                 read_profile(".profile");
7937         }
7938 state2:
7939         state = 3;
7940         if (
7941 #ifndef linux
7942                 getuid() == geteuid() && getgid() == getegid() &&
7943 #endif
7944                 iflag
7945         ) {
7946                 if ((shinit = lookupvar("ENV")) != NULL && *shinit != '\0') {
7947                         read_profile(shinit);
7948                 }
7949         }
7950 state3:
7951         state = 4;
7952         if (minusc)
7953                 evalstring(minusc, 0);
7954
7955         if (sflag || minusc == NULL) {
7956 #ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
7957             if ( iflag ) {
7958                 const char *hp = lookupvar("HISTFILE");
7959
7960                 if(hp != NULL )
7961                         load_history ( hp );
7962             }
7963 #endif
7964 state4: /* XXX ??? - why isn't this before the "if" statement */
7965                 cmdloop(1);
7966         }
7967 #if PROFILE
7968         monitor(0);
7969 #endif
7970 #if GPROF
7971         {
7972                 extern void _mcleanup(void);
7973                 _mcleanup();
7974         }
7975 #endif
7976         exitshell();
7977         /* NOTREACHED */
7978 }
7979
7980
7981 /*
7982  * Read and execute commands.  "Top" is nonzero for the top level command
7983  * loop; it turns on prompting if the shell is interactive.
7984  */
7985
7986 static void
7987 cmdloop(int top)
7988 {
7989         union node *n;
7990         struct stackmark smark;
7991         int inter;
7992         int numeof = 0;
7993
7994         TRACE(("cmdloop(%d) called\n", top));
7995         setstackmark(&smark);
7996         for (;;) {
7997                 if (pendingsigs)
7998                         dotrap();
7999 #if JOBS
8000                 if (jobctl)
8001                         showjobs(stderr, SHOW_CHANGED);
8002 #endif
8003                 inter = 0;
8004                 if (iflag && top) {
8005                         inter++;
8006 #ifdef CONFIG_ASH_MAIL
8007                         chkmail();
8008 #endif
8009                 }
8010                 n = parsecmd(inter);
8011                 /* showtree(n); DEBUG */
8012                 if (n == NEOF) {
8013                         if (!top || numeof >= 50)
8014                                 break;
8015                         if (!stoppedjobs()) {
8016                                 if (!Iflag)
8017                                         break;
8018                                 out2str("\nUse \"exit\" to leave shell.\n");
8019                         }
8020                         numeof++;
8021                 } else if (n != NULL && nflag == 0) {
8022                         job_warning = (job_warning == 2) ? 1 : 0;
8023                         numeof = 0;
8024                         evaltree(n, 0);
8025                 }
8026                 popstackmark(&smark);
8027                 setstackmark(&smark);
8028                 if (evalskip == SKIPFILE) {
8029                         evalskip = 0;
8030                         break;
8031                 }
8032         }
8033         popstackmark(&smark);
8034 }
8035
8036
8037 /*
8038  * Read /etc/profile or .profile.  Return on error.
8039  */
8040
8041 static void
8042 read_profile(const char *name)
8043 {
8044         int fd;
8045         int xflag_set = 0;
8046         int vflag_set = 0;
8047
8048         INTOFF;
8049         if ((fd = open(name, O_RDONLY)) >= 0)
8050                 setinputfd(fd, 1);
8051         INTON;
8052         if (fd < 0)
8053                 return;
8054         /* -q turns off -x and -v just when executing init files */
8055         if (qflag)  {
8056             if (xflag)
8057                     xflag = 0, xflag_set = 1;
8058             if (vflag)
8059                     vflag = 0, vflag_set = 1;
8060         }
8061         cmdloop(0);
8062         if (qflag)  {
8063             if (xflag_set)
8064                     xflag = 1;
8065             if (vflag_set)
8066                     vflag = 1;
8067         }
8068         popfile();
8069 }
8070
8071
8072 /*
8073  * Read a file containing shell functions.
8074  */
8075
8076 static void
8077 readcmdfile(char *name)
8078 {
8079         int fd;
8080
8081         INTOFF;
8082         if ((fd = open(name, O_RDONLY)) >= 0)
8083                 setinputfd(fd, 1);
8084         else
8085                 error("Can't open %s", name);
8086         INTON;
8087         cmdloop(0);
8088         popfile();
8089 }
8090
8091
8092 /*
8093  * Take commands from a file.  To be compatible we should do a path
8094  * search for the file, which is necessary to find sub-commands.
8095  */
8096
8097 static inline char *
8098 find_dot_file(char *name)
8099 {
8100         char *fullname;
8101         const char *path = pathval();
8102         struct stat statb;
8103
8104         /* don't try this for absolute or relative paths */
8105         if (strchr(name, '/'))
8106                 return name;
8107
8108         while ((fullname = padvance(&path, name)) != NULL) {
8109                 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
8110                         /*
8111                          * Don't bother freeing here, since it will
8112                          * be freed by the caller.
8113                          */
8114                         return fullname;
8115                 }
8116                 stunalloc(fullname);
8117         }
8118
8119         /* not found in the PATH */
8120         error(not_found_msg, name);
8121         /* NOTREACHED */
8122 }
8123
8124 int
8125 dotcmd(int argc, char **argv)
8126 {
8127         exitstatus = 0;
8128
8129         if (argc >= 2) {                /* That's what SVR2 does */
8130                 char *fullname;
8131                 struct stackmark smark;
8132
8133                 setstackmark(&smark);
8134                 fullname = find_dot_file(argv[1]);
8135                 setinputfile(fullname, 1);
8136                 commandname = fullname;
8137                 cmdloop(0);
8138                 popfile();
8139                 popstackmark(&smark);
8140         }
8141         return exitstatus;
8142 }
8143
8144
8145 static int
8146 exitcmd(int argc, char **argv)
8147 {
8148         if (stoppedjobs())
8149                 return 0;
8150         if (argc > 1)
8151                 exitstatus = number(argv[1]);
8152         exraise(EXEXIT);
8153         /* NOTREACHED */
8154 }
8155
8156 /*      $NetBSD: memalloc.c,v 1.27 2003/01/22 20:36:04 dsl Exp $        */
8157
8158 /*
8159  * Same for malloc, realloc, but returns an error when out of space.
8160  */
8161
8162 static pointer
8163 ckrealloc(pointer p, size_t nbytes)
8164 {
8165         p = realloc(p, nbytes);
8166         if (p == NULL)
8167                 error(bb_msg_memory_exhausted);
8168         return p;
8169 }
8170
8171 static pointer
8172 ckmalloc(size_t nbytes)
8173 {
8174         return ckrealloc(NULL, nbytes);
8175 }
8176
8177 /*
8178  * Make a copy of a string in safe storage.
8179  */
8180
8181 static char *
8182 savestr(const char *s)
8183 {
8184         char *p = strdup(s);
8185         if (!p)
8186                 error(bb_msg_memory_exhausted);
8187         return p;
8188 }
8189
8190
8191 /*
8192  * Parse trees for commands are allocated in lifo order, so we use a stack
8193  * to make this more efficient, and also to avoid all sorts of exception
8194  * handling code to handle interrupts in the middle of a parse.
8195  *
8196  * The size 504 was chosen because the Ultrix malloc handles that size
8197  * well.
8198  */
8199
8200
8201 static pointer
8202 stalloc(size_t nbytes)
8203 {
8204         char *p;
8205         size_t aligned;
8206
8207         aligned = SHELL_ALIGN(nbytes);
8208         if (aligned > stacknleft) {
8209                 size_t len;
8210                 size_t blocksize;
8211                 struct stack_block *sp;
8212
8213                 blocksize = aligned;
8214                 if (blocksize < MINSIZE)
8215                         blocksize = MINSIZE;
8216                 len = sizeof(struct stack_block) - MINSIZE + blocksize;
8217                 if (len < blocksize)
8218                         error(bb_msg_memory_exhausted);
8219                 INTOFF;
8220                 sp = ckmalloc(len);
8221                 sp->prev = stackp;
8222                 stacknxt = sp->space;
8223                 stacknleft = blocksize;
8224                 sstrend = stacknxt + blocksize;
8225                 stackp = sp;
8226                 INTON;
8227         }
8228         p = stacknxt;
8229         stacknxt += aligned;
8230         stacknleft -= aligned;
8231         return p;
8232 }
8233
8234
8235 void
8236 stunalloc(pointer p)
8237 {
8238 #ifdef DEBUG
8239         if (!p || (stacknxt < (char *)p) || ((char *)p < stackp->space)) {
8240                 write(2, "stunalloc\n", 10);
8241                 abort();
8242         }
8243 #endif
8244         stacknleft += stacknxt - (char *)p;
8245         stacknxt = p;
8246 }
8247
8248
8249 void
8250 setstackmark(struct stackmark *mark)
8251 {
8252         mark->stackp = stackp;
8253         mark->stacknxt = stacknxt;
8254         mark->stacknleft = stacknleft;
8255         mark->marknext = markp;
8256         markp = mark;
8257 }
8258
8259
8260 void
8261 popstackmark(struct stackmark *mark)
8262 {
8263         struct stack_block *sp;
8264
8265         INTOFF;
8266         markp = mark->marknext;
8267         while (stackp != mark->stackp) {
8268                 sp = stackp;
8269                 stackp = sp->prev;
8270                 ckfree(sp);
8271         }
8272         stacknxt = mark->stacknxt;
8273         stacknleft = mark->stacknleft;
8274         sstrend = mark->stacknxt + mark->stacknleft;
8275         INTON;
8276 }
8277
8278
8279 /*
8280  * When the parser reads in a string, it wants to stick the string on the
8281  * stack and only adjust the stack pointer when it knows how big the
8282  * string is.  Stackblock (defined in stack.h) returns a pointer to a block
8283  * of space on top of the stack and stackblocklen returns the length of
8284  * this block.  Growstackblock will grow this space by at least one byte,
8285  * possibly moving it (like realloc).  Grabstackblock actually allocates the
8286  * part of the block that has been used.
8287  */
8288
8289 void
8290 growstackblock(void)
8291 {
8292         size_t newlen;
8293
8294         newlen = stacknleft * 2;
8295         if (newlen < stacknleft)
8296                 error(bb_msg_memory_exhausted);
8297         if (newlen < 128)
8298                 newlen += 128;
8299
8300         if (stacknxt == stackp->space && stackp != &stackbase) {
8301                 struct stack_block *oldstackp;
8302                 struct stackmark *xmark;
8303                 struct stack_block *sp;
8304                 struct stack_block *prevstackp;
8305                 size_t grosslen;
8306
8307                 INTOFF;
8308                 oldstackp = stackp;
8309                 sp = stackp;
8310                 prevstackp = sp->prev;
8311                 grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
8312                 sp = ckrealloc((pointer)sp, grosslen);
8313                 sp->prev = prevstackp;
8314                 stackp = sp;
8315                 stacknxt = sp->space;
8316                 stacknleft = newlen;
8317                 sstrend = sp->space + newlen;
8318
8319                 /*
8320                  * Stack marks pointing to the start of the old block
8321                  * must be relocated to point to the new block
8322                  */
8323                 xmark = markp;
8324                 while (xmark != NULL && xmark->stackp == oldstackp) {
8325                         xmark->stackp = stackp;
8326                         xmark->stacknxt = stacknxt;
8327                         xmark->stacknleft = stacknleft;
8328                         xmark = xmark->marknext;
8329                 }
8330                 INTON;
8331         } else {
8332                 char *oldspace = stacknxt;
8333                 int oldlen = stacknleft;
8334                 char *p = stalloc(newlen);
8335
8336                 /* free the space we just allocated */
8337                 stacknxt = memcpy(p, oldspace, oldlen);
8338                 stacknleft += newlen;
8339         }
8340 }
8341
8342 static inline void
8343 grabstackblock(size_t len)
8344 {
8345         len = SHELL_ALIGN(len);
8346         stacknxt += len;
8347         stacknleft -= len;
8348 }
8349
8350 /*
8351  * The following routines are somewhat easier to use than the above.
8352  * The user declares a variable of type STACKSTR, which may be declared
8353  * to be a register.  The macro STARTSTACKSTR initializes things.  Then
8354  * the user uses the macro STPUTC to add characters to the string.  In
8355  * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
8356  * grown as necessary.  When the user is done, she can just leave the
8357  * string there and refer to it using stackblock().  Or she can allocate
8358  * the space for it using grabstackstr().  If it is necessary to allow
8359  * someone else to use the stack temporarily and then continue to grow
8360  * the string, the user should use grabstack to allocate the space, and
8361  * then call ungrabstr(p) to return to the previous mode of operation.
8362  *
8363  * USTPUTC is like STPUTC except that it doesn't check for overflow.
8364  * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
8365  * is space for at least one character.
8366  */
8367
8368 void *
8369 growstackstr(void)
8370 {
8371         size_t len = stackblocksize();
8372         if (herefd >= 0 && len >= 1024) {
8373                 xwrite(herefd, stackblock(), len);
8374                 return stackblock();
8375         }
8376         growstackblock();
8377         return stackblock() + len;
8378 }
8379
8380 /*
8381  * Called from CHECKSTRSPACE.
8382  */
8383
8384 char *
8385 makestrspace(size_t newlen, char *p)
8386 {
8387         size_t len = p - stacknxt;
8388         size_t size = stackblocksize();
8389
8390         for (;;) {
8391                 size_t nleft;
8392
8393                 size = stackblocksize();
8394                 nleft = size - len;
8395                 if (nleft >= newlen)
8396                         break;
8397                 growstackblock();
8398         }
8399         return stackblock() + len;
8400 }
8401
8402 char *
8403 stnputs(const char *s, size_t n, char *p)
8404 {
8405         p = makestrspace(n, p);
8406         p = mempcpy(p, s, n);
8407         return p;
8408 }
8409
8410 char *
8411 stputs(const char *s, char *p)
8412 {
8413         return stnputs(s, strlen(s), p);
8414 }
8415
8416 /*      $NetBSD: mystring.c,v 1.15 2002/11/24 22:35:42 christos Exp $   */
8417
8418 /*
8419  * String functions.
8420  *
8421  *      number(s)               Convert a string of digits to an integer.
8422  *      is_number(s)            Return true if s is a string of digits.
8423  */
8424
8425 /*
8426  * prefix -- see if pfx is a prefix of string.
8427  */
8428
8429 char *
8430 prefix(const char *string, const char *pfx)
8431 {
8432         while (*pfx) {
8433                 if (*pfx++ != *string++)
8434                         return 0;
8435         }
8436         return (char *) string;
8437 }
8438
8439
8440 /*
8441  * Convert a string of digits to an integer, printing an error message on
8442  * failure.
8443  */
8444
8445 int
8446 number(const char *s)
8447 {
8448
8449         if (! is_number(s))
8450                 error(illnum, s);
8451         return atoi(s);
8452 }
8453
8454
8455 /*
8456  * Check for a valid number.  This should be elsewhere.
8457  */
8458
8459 int
8460 is_number(const char *p)
8461 {
8462         do {
8463                 if (! is_digit(*p))
8464                         return 0;
8465         } while (*++p != '\0');
8466         return 1;
8467 }
8468
8469
8470 /*
8471  * Produce a possibly single quoted string suitable as input to the shell.
8472  * The return string is allocated on the stack.
8473  */
8474
8475 char *
8476 single_quote(const char *s) {
8477         char *p;
8478
8479         STARTSTACKSTR(p);
8480
8481         do {
8482                 char *q;
8483                 size_t len;
8484
8485                 len = strchrnul(s, '\'') - s;
8486
8487                 q = p = makestrspace(len + 3, p);
8488
8489                 *q++ = '\'';
8490                 q = mempcpy(q, s, len);
8491                 *q++ = '\'';
8492                 s += len;
8493
8494                 STADJUST(q - p, p);
8495
8496                 len = strspn(s, "'");
8497                 if (!len)
8498                         break;
8499
8500                 q = p = makestrspace(len + 3, p);
8501
8502                 *q++ = '"';
8503                 q = mempcpy(q, s, len);
8504                 *q++ = '"';
8505                 s += len;
8506
8507                 STADJUST(q - p, p);
8508         } while (*s);
8509
8510         USTPUTC(0, p);
8511
8512         return stackblock();
8513 }
8514
8515 /*
8516  * Like strdup but works with the ash stack.
8517  */
8518
8519 char *
8520 sstrdup(const char *p)
8521 {
8522         size_t len = strlen(p) + 1;
8523         return memcpy(stalloc(len), p, len);
8524 }
8525
8526
8527 static void
8528 calcsize(union node *n)
8529 {
8530       if (n == NULL)
8531             return;
8532       funcblocksize += nodesize[n->type];
8533       switch (n->type) {
8534       case NCMD:
8535             calcsize(n->ncmd.redirect);
8536             calcsize(n->ncmd.args);
8537             calcsize(n->ncmd.assign);
8538             break;
8539       case NPIPE:
8540             sizenodelist(n->npipe.cmdlist);
8541             break;
8542       case NREDIR:
8543       case NBACKGND:
8544       case NSUBSHELL:
8545             calcsize(n->nredir.redirect);
8546             calcsize(n->nredir.n);
8547             break;
8548       case NAND:
8549       case NOR:
8550       case NSEMI:
8551       case NWHILE:
8552       case NUNTIL:
8553             calcsize(n->nbinary.ch2);
8554             calcsize(n->nbinary.ch1);
8555             break;
8556       case NIF:
8557             calcsize(n->nif.elsepart);
8558             calcsize(n->nif.ifpart);
8559             calcsize(n->nif.test);
8560             break;
8561       case NFOR:
8562             funcstringsize += strlen(n->nfor.var) + 1;
8563             calcsize(n->nfor.body);
8564             calcsize(n->nfor.args);
8565             break;
8566       case NCASE:
8567             calcsize(n->ncase.cases);
8568             calcsize(n->ncase.expr);
8569             break;
8570       case NCLIST:
8571             calcsize(n->nclist.body);
8572             calcsize(n->nclist.pattern);
8573             calcsize(n->nclist.next);
8574             break;
8575       case NDEFUN:
8576       case NARG:
8577             sizenodelist(n->narg.backquote);
8578             funcstringsize += strlen(n->narg.text) + 1;
8579             calcsize(n->narg.next);
8580             break;
8581       case NTO:
8582       case NCLOBBER:
8583       case NFROM:
8584       case NFROMTO:
8585       case NAPPEND:
8586             calcsize(n->nfile.fname);
8587             calcsize(n->nfile.next);
8588             break;
8589       case NTOFD:
8590       case NFROMFD:
8591             calcsize(n->ndup.vname);
8592             calcsize(n->ndup.next);
8593             break;
8594       case NHERE:
8595       case NXHERE:
8596             calcsize(n->nhere.doc);
8597             calcsize(n->nhere.next);
8598             break;
8599       case NNOT:
8600             calcsize(n->nnot.com);
8601             break;
8602       };
8603 }
8604
8605
8606 static void
8607 sizenodelist(struct nodelist *lp)
8608 {
8609         while (lp) {
8610                 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
8611                 calcsize(lp->n);
8612                 lp = lp->next;
8613         }
8614 }
8615
8616
8617 static union node *
8618 copynode(union node *n)
8619 {
8620       union node *new;
8621
8622       if (n == NULL)
8623             return NULL;
8624       new = funcblock;
8625       funcblock = (char *) funcblock + nodesize[n->type];
8626       switch (n->type) {
8627       case NCMD:
8628             new->ncmd.redirect = copynode(n->ncmd.redirect);
8629             new->ncmd.args = copynode(n->ncmd.args);
8630             new->ncmd.assign = copynode(n->ncmd.assign);
8631             break;
8632       case NPIPE:
8633             new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
8634             new->npipe.backgnd = n->npipe.backgnd;
8635             break;
8636       case NREDIR:
8637       case NBACKGND:
8638       case NSUBSHELL:
8639             new->nredir.redirect = copynode(n->nredir.redirect);
8640             new->nredir.n = copynode(n->nredir.n);
8641             break;
8642       case NAND:
8643       case NOR:
8644       case NSEMI:
8645       case NWHILE:
8646       case NUNTIL:
8647             new->nbinary.ch2 = copynode(n->nbinary.ch2);
8648             new->nbinary.ch1 = copynode(n->nbinary.ch1);
8649             break;
8650       case NIF:
8651             new->nif.elsepart = copynode(n->nif.elsepart);
8652             new->nif.ifpart = copynode(n->nif.ifpart);
8653             new->nif.test = copynode(n->nif.test);
8654             break;
8655       case NFOR:
8656             new->nfor.var = nodesavestr(n->nfor.var);
8657             new->nfor.body = copynode(n->nfor.body);
8658             new->nfor.args = copynode(n->nfor.args);
8659             break;
8660       case NCASE:
8661             new->ncase.cases = copynode(n->ncase.cases);
8662             new->ncase.expr = copynode(n->ncase.expr);
8663             break;
8664       case NCLIST:
8665             new->nclist.body = copynode(n->nclist.body);
8666             new->nclist.pattern = copynode(n->nclist.pattern);
8667             new->nclist.next = copynode(n->nclist.next);
8668             break;
8669       case NDEFUN:
8670       case NARG:
8671             new->narg.backquote = copynodelist(n->narg.backquote);
8672             new->narg.text = nodesavestr(n->narg.text);
8673             new->narg.next = copynode(n->narg.next);
8674             break;
8675       case NTO:
8676       case NCLOBBER:
8677       case NFROM:
8678       case NFROMTO:
8679       case NAPPEND:
8680             new->nfile.fname = copynode(n->nfile.fname);
8681             new->nfile.fd = n->nfile.fd;
8682             new->nfile.next = copynode(n->nfile.next);
8683             break;
8684       case NTOFD:
8685       case NFROMFD:
8686             new->ndup.vname = copynode(n->ndup.vname);
8687             new->ndup.dupfd = n->ndup.dupfd;
8688             new->ndup.fd = n->ndup.fd;
8689             new->ndup.next = copynode(n->ndup.next);
8690             break;
8691       case NHERE:
8692       case NXHERE:
8693             new->nhere.doc = copynode(n->nhere.doc);
8694             new->nhere.fd = n->nhere.fd;
8695             new->nhere.next = copynode(n->nhere.next);
8696             break;
8697       case NNOT:
8698             new->nnot.com = copynode(n->nnot.com);
8699             break;
8700       };
8701       new->type = n->type;
8702         return new;
8703 }
8704
8705
8706 static struct nodelist *
8707 copynodelist(struct nodelist *lp)
8708 {
8709         struct nodelist *start;
8710         struct nodelist **lpp;
8711
8712         lpp = &start;
8713         while (lp) {
8714                 *lpp = funcblock;
8715                 funcblock = (char *) funcblock +
8716                     SHELL_ALIGN(sizeof(struct nodelist));
8717                 (*lpp)->n = copynode(lp->n);
8718                 lp = lp->next;
8719                 lpp = &(*lpp)->next;
8720         }
8721         *lpp = NULL;
8722         return start;
8723 }
8724
8725
8726 static char *
8727 nodesavestr(char   *s)
8728 {
8729         char   *rtn = funcstring;
8730
8731         funcstring = stpcpy(funcstring, s) + 1;
8732         return rtn;
8733 }
8734
8735
8736 /*
8737  * Free a parse tree.
8738  */
8739
8740 static void
8741 freefunc(struct funcnode *f)
8742 {
8743         if (f && --f->count < 0)
8744                 ckfree(f);
8745 }
8746
8747
8748 static void options(int);
8749 static void setoption(int, int);
8750
8751
8752 /*
8753  * Process the shell command line arguments.
8754  */
8755
8756 void
8757 procargs(int argc, char **argv)
8758 {
8759         int i;
8760         const char *xminusc;
8761         char **xargv;
8762
8763         xargv = argv;
8764         arg0 = xargv[0];
8765         if (argc > 0)
8766                 xargv++;
8767         for (i = 0; i < NOPTS; i++)
8768                 optlist[i] = 2;
8769         argptr = xargv;
8770         options(1);
8771         xargv = argptr;
8772         xminusc = minusc;
8773         if (*xargv == NULL) {
8774                 if (xminusc)
8775                         error("-c requires an argument");
8776                 sflag = 1;
8777         }
8778         if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
8779                 iflag = 1;
8780         if (mflag == 2)
8781                 mflag = iflag;
8782         for (i = 0; i < NOPTS; i++)
8783                 if (optlist[i] == 2)
8784                         optlist[i] = 0;
8785 #if DEBUG == 2
8786         debug = 1;
8787 #endif
8788         /* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
8789         if (xminusc) {
8790                 minusc = *xargv++;
8791                 if (*xargv)
8792                         goto setarg0;
8793         } else if (!sflag) {
8794                 setinputfile(*xargv, 0);
8795 setarg0:
8796                 arg0 = *xargv++;
8797                 commandname = arg0;
8798         }
8799
8800         shellparam.p = xargv;
8801 #ifdef CONFIG_ASH_GETOPTS
8802         shellparam.optind = 1;
8803         shellparam.optoff = -1;
8804 #endif
8805         /* assert(shellparam.malloc == 0 && shellparam.nparam == 0); */
8806         while (*xargv) {
8807                 shellparam.nparam++;
8808                 xargv++;
8809         }
8810         optschanged();
8811 }
8812
8813
8814 void
8815 optschanged(void)
8816 {
8817 #ifdef DEBUG
8818         opentrace();
8819 #endif
8820         setinteractive(iflag);
8821         setjobctl(mflag);
8822 }
8823
8824 static inline void
8825 minus_o(char *name, int val)
8826 {
8827         int i;
8828
8829         if (name == NULL) {
8830                 out1str("Current option settings\n");
8831                 for (i = 0; i < NOPTS; i++)
8832                         out1fmt("%-16s%s\n", optnames(i),
8833                                 optlist[i] ? "on" : "off");
8834         } else {
8835                 for (i = 0; i < NOPTS; i++)
8836                         if (equal(name, optnames(i))) {
8837                                 optlist[i] = val;
8838                                 return;
8839                         }
8840                 error("Illegal option -o %s", name);
8841         }
8842 }
8843
8844 /*
8845  * Process shell options.  The global variable argptr contains a pointer
8846  * to the argument list; we advance it past the options.
8847  */
8848
8849 static void
8850 options(int cmdline)
8851 {
8852         char *p;
8853         int val;
8854         int c;
8855
8856         if (cmdline)
8857                 minusc = NULL;
8858         while ((p = *argptr) != NULL) {
8859                 argptr++;
8860                 if ((c = *p++) == '-') {
8861                         val = 1;
8862                         if (p[0] == '\0' || (p[0] == '-' && p[1] == '\0')) {
8863                                 if (!cmdline) {
8864                                         /* "-" means turn off -x and -v */
8865                                         if (p[0] == '\0')
8866                                                 xflag = vflag = 0;
8867                                         /* "--" means reset params */
8868                                         else if (*argptr == NULL)
8869                                                 setparam(argptr);
8870                                 }
8871                                 break;    /* "-" or  "--" terminates options */
8872                         }
8873                 } else if (c == '+') {
8874                         val = 0;
8875                 } else {
8876                         argptr--;
8877                         break;
8878                 }
8879                 while ((c = *p++) != '\0') {
8880                         if (c == 'c' && cmdline) {
8881                                 minusc = p;     /* command is after shell args*/
8882                         } else if (c == 'o') {
8883                                 minus_o(*argptr, val);
8884                                 if (*argptr)
8885                                         argptr++;
8886                         } else if (cmdline && (c == '-')) {     // long options
8887                                 if (strcmp(p, "login") == 0)
8888                                         isloginsh = 1;
8889                                 break;
8890                         } else {
8891                                 setoption(c, val);
8892                         }
8893                 }
8894         }
8895 }
8896
8897
8898 static void
8899 setoption(int flag, int val)
8900 {
8901         int i;
8902
8903         for (i = 0; i < NOPTS; i++)
8904                 if (optletters(i) == flag) {
8905                         optlist[i] = val;
8906                         return;
8907                 }
8908         error("Illegal option -%c", flag);
8909         /* NOTREACHED */
8910 }
8911
8912
8913
8914 /*
8915  * Set the shell parameters.
8916  */
8917
8918 void
8919 setparam(char **argv)
8920 {
8921         char **newparam;
8922         char **ap;
8923         int nparam;
8924
8925         for (nparam = 0 ; argv[nparam] ; nparam++);
8926         ap = newparam = ckmalloc((nparam + 1) * sizeof *ap);
8927         while (*argv) {
8928                 *ap++ = savestr(*argv++);
8929         }
8930         *ap = NULL;
8931         freeparam(&shellparam);
8932         shellparam.malloc = 1;
8933         shellparam.nparam = nparam;
8934         shellparam.p = newparam;
8935 #ifdef CONFIG_ASH_GETOPTS
8936         shellparam.optind = 1;
8937         shellparam.optoff = -1;
8938 #endif
8939 }
8940
8941
8942 /*
8943  * Free the list of positional parameters.
8944  */
8945
8946 void
8947 freeparam(volatile struct shparam *param)
8948 {
8949         char **ap;
8950
8951         if (param->malloc) {
8952                 for (ap = param->p ; *ap ; ap++)
8953                         ckfree(*ap);
8954                 ckfree(param->p);
8955         }
8956 }
8957
8958
8959
8960 /*
8961  * The shift builtin command.
8962  */
8963
8964 int
8965 shiftcmd(int argc, char **argv)
8966 {
8967         int n;
8968         char **ap1, **ap2;
8969
8970         n = 1;
8971         if (argc > 1)
8972                 n = number(argv[1]);
8973         if (n > shellparam.nparam)
8974                 error("can't shift that many");
8975         INTOFF;
8976         shellparam.nparam -= n;
8977         for (ap1 = shellparam.p ; --n >= 0 ; ap1++) {
8978                 if (shellparam.malloc)
8979                         ckfree(*ap1);
8980         }
8981         ap2 = shellparam.p;
8982         while ((*ap2++ = *ap1++) != NULL);
8983 #ifdef CONFIG_ASH_GETOPTS
8984         shellparam.optind = 1;
8985         shellparam.optoff = -1;
8986 #endif
8987         INTON;
8988         return 0;
8989 }
8990
8991
8992
8993 /*
8994  * The set command builtin.
8995  */
8996
8997 int
8998 setcmd(int argc, char **argv)
8999 {
9000         if (argc == 1)
9001                 return showvars(nullstr, 0, VUNSET);
9002         INTOFF;
9003         options(0);
9004         optschanged();
9005         if (*argptr != NULL) {
9006                 setparam(argptr);
9007         }
9008         INTON;
9009         return 0;
9010 }
9011
9012
9013 #ifdef CONFIG_ASH_GETOPTS
9014 static void
9015 getoptsreset(value)
9016         const char *value;
9017 {
9018         shellparam.optind = number(value);
9019         shellparam.optoff = -1;
9020 }
9021 #endif
9022
9023 #ifdef CONFIG_LOCALE_SUPPORT
9024 static void change_lc_all(const char *value)
9025 {
9026         if (value != 0 && *value != 0)
9027                 setlocale(LC_ALL, value);
9028 }
9029
9030 static void change_lc_ctype(const char *value)
9031 {
9032         if (value != 0 && *value != 0)
9033                 setlocale(LC_CTYPE, value);
9034 }
9035
9036 #endif
9037
9038 #ifdef CONFIG_ASH_GETOPTS
9039 static int
9040 getopts(char *optstr, char *optvar, char **optfirst, int *param_optind, int *optoff)
9041 {
9042         char *p, *q;
9043         char c = '?';
9044         int done = 0;
9045         int err = 0;
9046         char s[12];
9047         char **optnext;
9048
9049         if(*param_optind < 1)
9050                 return 1;
9051         optnext = optfirst + *param_optind - 1;
9052
9053         if (*param_optind <= 1 || *optoff < 0 || strlen(optnext[-1]) < *optoff)
9054                 p = NULL;
9055         else
9056                 p = optnext[-1] + *optoff;
9057         if (p == NULL || *p == '\0') {
9058                 /* Current word is done, advance */
9059                 p = *optnext;
9060                 if (p == NULL || *p != '-' || *++p == '\0') {
9061 atend:
9062                         p = NULL;
9063                         done = 1;
9064                         goto out;
9065                 }
9066                 optnext++;
9067                 if (p[0] == '-' && p[1] == '\0')        /* check for "--" */
9068                         goto atend;
9069         }
9070
9071         c = *p++;
9072         for (q = optstr; *q != c; ) {
9073                 if (*q == '\0') {
9074                         if (optstr[0] == ':') {
9075                                 s[0] = c;
9076                                 s[1] = '\0';
9077                                 err |= setvarsafe("OPTARG", s, 0);
9078                         } else {
9079                                 fprintf(stderr, "Illegal option -%c\n", c);
9080                                 (void) unsetvar("OPTARG");
9081                         }
9082                         c = '?';
9083                         goto out;
9084                 }
9085                 if (*++q == ':')
9086                         q++;
9087         }
9088
9089         if (*++q == ':') {
9090                 if (*p == '\0' && (p = *optnext) == NULL) {
9091                         if (optstr[0] == ':') {
9092                                 s[0] = c;
9093                                 s[1] = '\0';
9094                                 err |= setvarsafe("OPTARG", s, 0);
9095                                 c = ':';
9096                         } else {
9097                                 fprintf(stderr, "No arg for -%c option\n", c);
9098                                 (void) unsetvar("OPTARG");
9099                                 c = '?';
9100                         }
9101                         goto out;
9102                 }
9103
9104                 if (p == *optnext)
9105                         optnext++;
9106                 err |= setvarsafe("OPTARG", p, 0);
9107                 p = NULL;
9108         } else
9109                 err |= setvarsafe("OPTARG", nullstr, 0);
9110
9111 out:
9112         *optoff = p ? p - *(optnext - 1) : -1;
9113         *param_optind = optnext - optfirst + 1;
9114         fmtstr(s, sizeof(s), "%d", *param_optind);
9115         err |= setvarsafe("OPTIND", s, VNOFUNC);
9116         s[0] = c;
9117         s[1] = '\0';
9118         err |= setvarsafe(optvar, s, 0);
9119         if (err) {
9120                 *param_optind = 1;
9121                 *optoff = -1;
9122                 flushall();
9123                 exraise(EXERROR);
9124         }
9125         return done;
9126 }
9127
9128 /*
9129  * The getopts builtin.  Shellparam.optnext points to the next argument
9130  * to be processed.  Shellparam.optptr points to the next character to
9131  * be processed in the current argument.  If shellparam.optnext is NULL,
9132  * then it's the first time getopts has been called.
9133  */
9134
9135 int
9136 getoptscmd(int argc, char **argv)
9137 {
9138         char **optbase;
9139
9140         if (argc < 3)
9141                 error("Usage: getopts optstring var [arg]");
9142         else if (argc == 3) {
9143                 optbase = shellparam.p;
9144                 if (shellparam.optind > shellparam.nparam + 1) {
9145                         shellparam.optind = 1;
9146                         shellparam.optoff = -1;
9147                 }
9148         }
9149         else {
9150                 optbase = &argv[3];
9151                 if (shellparam.optind > argc - 2) {
9152                         shellparam.optind = 1;
9153                         shellparam.optoff = -1;
9154                 }
9155         }
9156
9157         return getopts(argv[1], argv[2], optbase, &shellparam.optind,
9158                        &shellparam.optoff);
9159 }
9160 #endif /* CONFIG_ASH_GETOPTS */
9161
9162 /*
9163  * XXX - should get rid of.  have all builtins use getopt(3).  the
9164  * library getopt must have the BSD extension static variable "optreset"
9165  * otherwise it can't be used within the shell safely.
9166  *
9167  * Standard option processing (a la getopt) for builtin routines.  The
9168  * only argument that is passed to nextopt is the option string; the
9169  * other arguments are unnecessary.  It return the character, or '\0' on
9170  * end of input.
9171  */
9172
9173 static int
9174 nextopt(const char *optstring)
9175 {
9176         char *p;
9177         const char *q;
9178         char c;
9179
9180         if ((p = optptr) == NULL || *p == '\0') {
9181                 p = *argptr;
9182                 if (p == NULL || *p != '-' || *++p == '\0')
9183                         return '\0';
9184                 argptr++;
9185                 if (p[0] == '-' && p[1] == '\0')        /* check for "--" */
9186                         return '\0';
9187         }
9188         c = *p++;
9189         for (q = optstring ; *q != c ; ) {
9190                 if (*q == '\0')
9191                         error("Illegal option -%c", c);
9192                 if (*++q == ':')
9193                         q++;
9194         }
9195         if (*++q == ':') {
9196                 if (*p == '\0' && (p = *argptr++) == NULL)
9197                         error("No arg for -%c option", c);
9198                 optionarg = p;
9199                 p = NULL;
9200         }
9201         optptr = p;
9202         return c;
9203 }
9204
9205
9206 /*      $NetBSD: output.c,v 1.27 2002/11/24 22:35:42 christos Exp $     */
9207
9208 void
9209 outstr(const char *p, FILE *file)
9210 {
9211         INTOFF;
9212         fputs(p, file);
9213         INTON;
9214 }
9215
9216 void
9217 flushall(void)
9218 {
9219         INTOFF;
9220         fflush(stdout);
9221         fflush(stderr);
9222         INTON;
9223 }
9224
9225 void
9226 flushout(FILE *dest)
9227 {
9228         INTOFF;
9229         fflush(dest);
9230         INTON;
9231 }
9232
9233 static void
9234 outcslow(int c, FILE *dest)
9235 {
9236         INTOFF;
9237         putc(c, dest);
9238         fflush(dest);
9239         INTON;
9240 }
9241
9242
9243 static int
9244 out1fmt(const char *fmt, ...)
9245 {
9246         va_list ap;
9247         int r;
9248
9249         INTOFF;
9250         va_start(ap, fmt);
9251         r = vprintf(fmt, ap);
9252         va_end(ap);
9253         INTON;
9254         return r;
9255 }
9256
9257
9258 int
9259 fmtstr(char *outbuf, size_t length, const char *fmt, ...)
9260 {
9261         va_list ap;
9262         int ret;
9263
9264         va_start(ap, fmt);
9265         INTOFF;
9266         ret = vsnprintf(outbuf, length, fmt, ap);
9267         va_end(ap);
9268         INTON;
9269         return ret;
9270 }
9271
9272
9273 /*
9274  * Version of write which resumes after a signal is caught.
9275  */
9276
9277 static void
9278 xwrite(int fd, const void *p, size_t n)
9279 {
9280         ssize_t i;
9281
9282         do {
9283                 i = bb_full_write(fd, p, n);
9284         } while (i < 0 && errno == EINTR);
9285 }
9286
9287
9288 /*      $NetBSD: parser.c,v 1.54 2002/11/24 22:35:42 christos Exp $     */
9289
9290
9291 /*
9292  * Shell command parser.
9293  */
9294
9295 #define EOFMARKLEN 79
9296
9297
9298 struct heredoc {
9299         struct heredoc *next;   /* next here document in list */
9300         union node *here;               /* redirection node */
9301         char *eofmark;          /* string indicating end of input */
9302         int striptabs;          /* if set, strip leading tabs */
9303 };
9304
9305
9306
9307 static struct heredoc *heredoclist;    /* list of here documents to read */
9308
9309
9310 static union node *list(int);
9311 static union node *andor(void);
9312 static union node *pipeline(void);
9313 static union node *command(void);
9314 static union node *simplecmd(void);
9315 static union node *makename(void);
9316 static void parsefname(void);
9317 static void parseheredoc(void);
9318 static char peektoken(void);
9319 static int readtoken(void);
9320 static int xxreadtoken(void);
9321 static int readtoken1(int firstc, int syntax, char *eofmark, int striptabs);
9322 static int noexpand(char *);
9323 static void synexpect(int) __attribute__((__noreturn__));
9324 static void synerror(const char *) __attribute__((__noreturn__));
9325 static void setprompt(int);
9326
9327
9328 static inline int
9329 goodname(const char *p)
9330 {
9331         return !*endofname(p);
9332 }
9333
9334 static inline int
9335 isassignment(const char *p)
9336 {
9337         const char *q = endofname(p);
9338         if (p == q)
9339                 return 0;
9340         return *q == '=';
9341 }
9342
9343
9344 /*
9345  * Read and parse a command.  Returns NEOF on end of file.  (NULL is a
9346  * valid parse tree indicating a blank line.)
9347  */
9348
9349 union node *
9350 parsecmd(int interact)
9351 {
9352         int t;
9353
9354         tokpushback = 0;
9355         doprompt = interact;
9356         if (doprompt)
9357                 setprompt(doprompt);
9358         needprompt = 0;
9359         t = readtoken();
9360         if (t == TEOF)
9361                 return NEOF;
9362         if (t == TNL)
9363                 return NULL;
9364         tokpushback++;
9365         return list(1);
9366 }
9367
9368
9369 static union node *
9370 list(int nlflag)
9371 {
9372         union node *n1, *n2, *n3;
9373         int tok;
9374
9375         checkkwd = CHKNL | CHKKWD | CHKALIAS;
9376         if (nlflag == 2 && peektoken())
9377                 return NULL;
9378         n1 = NULL;
9379         for (;;) {
9380                 n2 = andor();
9381                 tok = readtoken();
9382                 if (tok == TBACKGND) {
9383                         if (n2->type == NPIPE) {
9384                                 n2->npipe.backgnd = 1;
9385                         } else {
9386                                 if (n2->type != NREDIR) {
9387                                         n3 = stalloc(sizeof(struct nredir));
9388                                         n3->nredir.n = n2;
9389                                         n3->nredir.redirect = NULL;
9390                                         n2 = n3;
9391                                 }
9392                                 n2->type = NBACKGND;
9393                         }
9394                 }
9395                 if (n1 == NULL) {
9396                         n1 = n2;
9397                 }
9398                 else {
9399                         n3 = (union node *)stalloc(sizeof (struct nbinary));
9400                         n3->type = NSEMI;
9401                         n3->nbinary.ch1 = n1;
9402                         n3->nbinary.ch2 = n2;
9403                         n1 = n3;
9404                 }
9405                 switch (tok) {
9406                 case TBACKGND:
9407                 case TSEMI:
9408                         tok = readtoken();
9409                         /* fall through */
9410                 case TNL:
9411                         if (tok == TNL) {
9412                                 parseheredoc();
9413                                 if (nlflag == 1)
9414                                         return n1;
9415                         } else {
9416                                 tokpushback++;
9417                         }
9418                         checkkwd = CHKNL | CHKKWD | CHKALIAS;
9419                         if (peektoken())
9420                                 return n1;
9421                         break;
9422                 case TEOF:
9423                         if (heredoclist)
9424                                 parseheredoc();
9425                         else
9426                                 pungetc();              /* push back EOF on input */
9427                         return n1;
9428                 default:
9429                         if (nlflag == 1)
9430                                 synexpect(-1);
9431                         tokpushback++;
9432                         return n1;
9433                 }
9434         }
9435 }
9436
9437
9438
9439 static union node *
9440 andor(void)
9441 {
9442         union node *n1, *n2, *n3;
9443         int t;
9444
9445         n1 = pipeline();
9446         for (;;) {
9447                 if ((t = readtoken()) == TAND) {
9448                         t = NAND;
9449                 } else if (t == TOR) {
9450                         t = NOR;
9451                 } else {
9452                         tokpushback++;
9453                         return n1;
9454                 }
9455                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9456                 n2 = pipeline();
9457                 n3 = (union node *)stalloc(sizeof (struct nbinary));
9458                 n3->type = t;
9459                 n3->nbinary.ch1 = n1;
9460                 n3->nbinary.ch2 = n2;
9461                 n1 = n3;
9462         }
9463 }
9464
9465
9466
9467 static union node *
9468 pipeline(void)
9469 {
9470         union node *n1, *n2, *pipenode;
9471         struct nodelist *lp, *prev;
9472         int negate;
9473
9474         negate = 0;
9475         TRACE(("pipeline: entered\n"));
9476         if (readtoken() == TNOT) {
9477                 negate = !negate;
9478                 checkkwd = CHKKWD | CHKALIAS;
9479         } else
9480                 tokpushback++;
9481         n1 = command();
9482         if (readtoken() == TPIPE) {
9483                 pipenode = (union node *)stalloc(sizeof (struct npipe));
9484                 pipenode->type = NPIPE;
9485                 pipenode->npipe.backgnd = 0;
9486                 lp = (struct nodelist *)stalloc(sizeof (struct nodelist));
9487                 pipenode->npipe.cmdlist = lp;
9488                 lp->n = n1;
9489                 do {
9490                         prev = lp;
9491                         lp = (struct nodelist *)stalloc(sizeof (struct nodelist));
9492                         checkkwd = CHKNL | CHKKWD | CHKALIAS;
9493                         lp->n = command();
9494                         prev->next = lp;
9495                 } while (readtoken() == TPIPE);
9496                 lp->next = NULL;
9497                 n1 = pipenode;
9498         }
9499         tokpushback++;
9500         if (negate) {
9501                 n2 = (union node *)stalloc(sizeof (struct nnot));
9502                 n2->type = NNOT;
9503                 n2->nnot.com = n1;
9504                 return n2;
9505         } else
9506                 return n1;
9507 }
9508
9509
9510
9511 static union node *
9512 command(void)
9513 {
9514         union node *n1, *n2;
9515         union node *ap, **app;
9516         union node *cp, **cpp;
9517         union node *redir, **rpp;
9518         union node **rpp2;
9519         int t;
9520
9521         redir = NULL;
9522         rpp2 = &redir;
9523
9524         switch (readtoken()) {
9525         default:
9526                 synexpect(-1);
9527                 /* NOTREACHED */
9528         case TIF:
9529                 n1 = (union node *)stalloc(sizeof (struct nif));
9530                 n1->type = NIF;
9531                 n1->nif.test = list(0);
9532                 if (readtoken() != TTHEN)
9533                         synexpect(TTHEN);
9534                 n1->nif.ifpart = list(0);
9535                 n2 = n1;
9536                 while (readtoken() == TELIF) {
9537                         n2->nif.elsepart = (union node *)stalloc(sizeof (struct nif));
9538                         n2 = n2->nif.elsepart;
9539                         n2->type = NIF;
9540                         n2->nif.test = list(0);
9541                         if (readtoken() != TTHEN)
9542                                 synexpect(TTHEN);
9543                         n2->nif.ifpart = list(0);
9544                 }
9545                 if (lasttoken == TELSE)
9546                         n2->nif.elsepart = list(0);
9547                 else {
9548                         n2->nif.elsepart = NULL;
9549                         tokpushback++;
9550                 }
9551                 t = TFI;
9552                 break;
9553         case TWHILE:
9554         case TUNTIL: {
9555                 int got;
9556                 n1 = (union node *)stalloc(sizeof (struct nbinary));
9557                 n1->type = (lasttoken == TWHILE)? NWHILE : NUNTIL;
9558                 n1->nbinary.ch1 = list(0);
9559                 if ((got=readtoken()) != TDO) {
9560 TRACE(("expecting DO got %s %s\n", tokname(got), got == TWORD ? wordtext : ""));
9561                         synexpect(TDO);
9562                 }
9563                 n1->nbinary.ch2 = list(0);
9564                 t = TDONE;
9565                 break;
9566         }
9567         case TFOR:
9568                 if (readtoken() != TWORD || quoteflag || ! goodname(wordtext))
9569                         synerror("Bad for loop variable");
9570                 n1 = (union node *)stalloc(sizeof (struct nfor));
9571                 n1->type = NFOR;
9572                 n1->nfor.var = wordtext;
9573                 checkkwd = CHKKWD | CHKALIAS;
9574                 if (readtoken() == TIN) {
9575                         app = &ap;
9576                         while (readtoken() == TWORD) {
9577                                 n2 = (union node *)stalloc(sizeof (struct narg));
9578                                 n2->type = NARG;
9579                                 n2->narg.text = wordtext;
9580                                 n2->narg.backquote = backquotelist;
9581                                 *app = n2;
9582                                 app = &n2->narg.next;
9583                         }
9584                         *app = NULL;
9585                         n1->nfor.args = ap;
9586                         if (lasttoken != TNL && lasttoken != TSEMI)
9587                                 synexpect(-1);
9588                 } else {
9589                         n2 = (union node *)stalloc(sizeof (struct narg));
9590                         n2->type = NARG;
9591                         n2->narg.text = (char *)dolatstr;
9592                         n2->narg.backquote = NULL;
9593                         n2->narg.next = NULL;
9594                         n1->nfor.args = n2;
9595                         /*
9596                          * Newline or semicolon here is optional (but note
9597                          * that the original Bourne shell only allowed NL).
9598                          */
9599                         if (lasttoken != TNL && lasttoken != TSEMI)
9600                                 tokpushback++;
9601                 }
9602                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9603                 if (readtoken() != TDO)
9604                         synexpect(TDO);
9605                 n1->nfor.body = list(0);
9606                 t = TDONE;
9607                 break;
9608         case TCASE:
9609                 n1 = (union node *)stalloc(sizeof (struct ncase));
9610                 n1->type = NCASE;
9611                 if (readtoken() != TWORD)
9612                         synexpect(TWORD);
9613                 n1->ncase.expr = n2 = (union node *)stalloc(sizeof (struct narg));
9614                 n2->type = NARG;
9615                 n2->narg.text = wordtext;
9616                 n2->narg.backquote = backquotelist;
9617                 n2->narg.next = NULL;
9618                 do {
9619                         checkkwd = CHKKWD | CHKALIAS;
9620                 } while (readtoken() == TNL);
9621                 if (lasttoken != TIN)
9622                         synexpect(TIN);
9623                 cpp = &n1->ncase.cases;
9624 next_case:
9625                 checkkwd = CHKNL | CHKKWD;
9626                 t = readtoken();
9627                 while(t != TESAC) {
9628                         if (lasttoken == TLP)
9629                                 readtoken();
9630                         *cpp = cp = (union node *)stalloc(sizeof (struct nclist));
9631                         cp->type = NCLIST;
9632                         app = &cp->nclist.pattern;
9633                         for (;;) {
9634                                 *app = ap = (union node *)stalloc(sizeof (struct narg));
9635                                 ap->type = NARG;
9636                                 ap->narg.text = wordtext;
9637                                 ap->narg.backquote = backquotelist;
9638                                 if (readtoken() != TPIPE)
9639                                         break;
9640                                 app = &ap->narg.next;
9641                                 readtoken();
9642                         }
9643                         ap->narg.next = NULL;
9644                         if (lasttoken != TRP)
9645                                 synexpect(TRP);
9646                         cp->nclist.body = list(2);
9647
9648                         cpp = &cp->nclist.next;
9649
9650                         checkkwd = CHKNL | CHKKWD;
9651                         if ((t = readtoken()) != TESAC) {
9652                                 if (t != TENDCASE)
9653                                         synexpect(TENDCASE);
9654                                 else
9655                                         goto next_case;
9656                         }
9657                 }
9658                 *cpp = NULL;
9659                 goto redir;
9660         case TLP:
9661                 n1 = (union node *)stalloc(sizeof (struct nredir));
9662                 n1->type = NSUBSHELL;
9663                 n1->nredir.n = list(0);
9664                 n1->nredir.redirect = NULL;
9665                 t = TRP;
9666                 break;
9667         case TBEGIN:
9668                 n1 = list(0);
9669                 t = TEND;
9670                 break;
9671         case TWORD:
9672         case TREDIR:
9673                 tokpushback++;
9674                 return simplecmd();
9675         }
9676
9677         if (readtoken() != t)
9678                 synexpect(t);
9679
9680 redir:
9681         /* Now check for redirection which may follow command */
9682         checkkwd = CHKKWD | CHKALIAS;
9683         rpp = rpp2;
9684         while (readtoken() == TREDIR) {
9685                 *rpp = n2 = redirnode;
9686                 rpp = &n2->nfile.next;
9687                 parsefname();
9688         }
9689         tokpushback++;
9690         *rpp = NULL;
9691         if (redir) {
9692                 if (n1->type != NSUBSHELL) {
9693                         n2 = (union node *)stalloc(sizeof (struct nredir));
9694                         n2->type = NREDIR;
9695                         n2->nredir.n = n1;
9696                         n1 = n2;
9697                 }
9698                 n1->nredir.redirect = redir;
9699         }
9700
9701         return n1;
9702 }
9703
9704
9705 static union node *
9706 simplecmd(void) {
9707         union node *args, **app;
9708         union node *n = NULL;
9709         union node *vars, **vpp;
9710         union node **rpp, *redir;
9711         int savecheckkwd;
9712
9713         args = NULL;
9714         app = &args;
9715         vars = NULL;
9716         vpp = &vars;
9717         redir = NULL;
9718         rpp = &redir;
9719
9720         savecheckkwd = CHKALIAS;
9721         for (;;) {
9722                 checkkwd = savecheckkwd;
9723                 switch (readtoken()) {
9724                 case TWORD:
9725                         n = (union node *)stalloc(sizeof (struct narg));
9726                         n->type = NARG;
9727                         n->narg.text = wordtext;
9728                         n->narg.backquote = backquotelist;
9729                         if (savecheckkwd && isassignment(wordtext)) {
9730                                 *vpp = n;
9731                                 vpp = &n->narg.next;
9732                         } else {
9733                                 *app = n;
9734                                 app = &n->narg.next;
9735                                 savecheckkwd = 0;
9736                         }
9737                         break;
9738                 case TREDIR:
9739                         *rpp = n = redirnode;
9740                         rpp = &n->nfile.next;
9741                         parsefname();   /* read name of redirection file */
9742                         break;
9743                 case TLP:
9744                         if (
9745                                 args && app == &args->narg.next &&
9746                                 !vars && !redir
9747                         ) {
9748                                 struct builtincmd *bcmd;
9749                                 const char *name;
9750
9751                                 /* We have a function */
9752                                 if (readtoken() != TRP)
9753                                         synexpect(TRP);
9754                                 name = n->narg.text;
9755                                 if (
9756                                         !goodname(name) || (
9757                                                 (bcmd = find_builtin(name)) &&
9758                                                 IS_BUILTIN_SPECIAL(bcmd)
9759                                         )
9760                                 )
9761                                         synerror("Bad function name");
9762                                 n->type = NDEFUN;
9763                                 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9764                                 n->narg.next = command();
9765                                 return n;
9766                         }
9767                         /* fall through */
9768                 default:
9769                         tokpushback++;
9770                         goto out;
9771                 }
9772         }
9773 out:
9774         *app = NULL;
9775         *vpp = NULL;
9776         *rpp = NULL;
9777         n = (union node *)stalloc(sizeof (struct ncmd));
9778         n->type = NCMD;
9779         n->ncmd.args = args;
9780         n->ncmd.assign = vars;
9781         n->ncmd.redirect = redir;
9782         return n;
9783 }
9784
9785 static union node *
9786 makename(void)
9787 {
9788         union node *n;
9789
9790         n = (union node *)stalloc(sizeof (struct narg));
9791         n->type = NARG;
9792         n->narg.next = NULL;
9793         n->narg.text = wordtext;
9794         n->narg.backquote = backquotelist;
9795         return n;
9796 }
9797
9798 void fixredir(union node *n, const char *text, int err)
9799 {
9800         TRACE(("Fix redir %s %d\n", text, err));
9801         if (!err)
9802                 n->ndup.vname = NULL;
9803
9804         if (is_digit(text[0]) && text[1] == '\0')
9805                 n->ndup.dupfd = digit_val(text[0]);
9806         else if (text[0] == '-' && text[1] == '\0')
9807                 n->ndup.dupfd = -1;
9808         else {
9809
9810                 if (err)
9811                         synerror("Bad fd number");
9812                 else
9813                         n->ndup.vname = makename();
9814         }
9815 }
9816
9817
9818 static void
9819 parsefname(void)
9820 {
9821         union node *n = redirnode;
9822
9823         if (readtoken() != TWORD)
9824                 synexpect(-1);
9825         if (n->type == NHERE) {
9826                 struct heredoc *here = heredoc;
9827                 struct heredoc *p;
9828                 int i;
9829
9830                 if (quoteflag == 0)
9831                         n->type = NXHERE;
9832                 TRACE(("Here document %d\n", n->type));
9833                 if (! noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)
9834                         synerror("Illegal eof marker for << redirection");
9835                 rmescapes(wordtext);
9836                 here->eofmark = wordtext;
9837                 here->next = NULL;
9838                 if (heredoclist == NULL)
9839                         heredoclist = here;
9840                 else {
9841                         for (p = heredoclist ; p->next ; p = p->next);
9842                         p->next = here;
9843                 }
9844         } else if (n->type == NTOFD || n->type == NFROMFD) {
9845                 fixredir(n, wordtext, 0);
9846         } else {
9847                 n->nfile.fname = makename();
9848         }
9849 }
9850
9851
9852 /*
9853  * Input any here documents.
9854  */
9855
9856 static void
9857 parseheredoc(void)
9858 {
9859         struct heredoc *here;
9860         union node *n;
9861
9862         here = heredoclist;
9863         heredoclist = 0;
9864
9865         while (here) {
9866                 if (needprompt) {
9867                         setprompt(2);
9868                         needprompt = 0;
9869                 }
9870                 readtoken1(pgetc(), here->here->type == NHERE? SQSYNTAX : DQSYNTAX,
9871                                 here->eofmark, here->striptabs);
9872                 n = (union node *)stalloc(sizeof (struct narg));
9873                 n->narg.type = NARG;
9874                 n->narg.next = NULL;
9875                 n->narg.text = wordtext;
9876                 n->narg.backquote = backquotelist;
9877                 here->here->nhere.doc = n;
9878                 here = here->next;
9879         }
9880 }
9881
9882 static char peektoken(void)
9883 {
9884         int t;
9885
9886         t = readtoken();
9887         tokpushback++;
9888         return tokname_array[t][0];
9889 }
9890
9891 static int
9892 readtoken(void)
9893 {
9894         int t;
9895 #ifdef DEBUG
9896         int alreadyseen = tokpushback;
9897 #endif
9898
9899 #ifdef CONFIG_ASH_ALIAS
9900 top:
9901 #endif
9902
9903         t = xxreadtoken();
9904
9905         /*
9906          * eat newlines
9907          */
9908         if (checkkwd & CHKNL) {
9909                 while (t == TNL) {
9910                         parseheredoc();
9911                         t = xxreadtoken();
9912                 }
9913         }
9914
9915         if (t != TWORD || quoteflag) {
9916                 goto out;
9917         }
9918
9919         /*
9920          * check for keywords
9921          */
9922         if (checkkwd & CHKKWD) {
9923                 const char *const *pp;
9924
9925                 if ((pp = findkwd(wordtext))) {
9926                         lasttoken = t = pp - tokname_array;
9927                         TRACE(("keyword %s recognized\n", tokname(t)));
9928                         goto out;
9929                 }
9930         }
9931
9932         if (checkkwd & CHKALIAS) {
9933 #ifdef CONFIG_ASH_ALIAS
9934                 struct alias *ap;
9935                 if ((ap = lookupalias(wordtext, 1)) != NULL) {
9936                         if (*ap->val) {
9937                                 pushstring(ap->val, ap);
9938                         }
9939                         goto top;
9940                 }
9941 #endif
9942         }
9943 out:
9944         checkkwd = 0;
9945 #ifdef DEBUG
9946         if (!alreadyseen)
9947             TRACE(("token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
9948         else
9949             TRACE(("reread token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
9950 #endif
9951         return (t);
9952 }
9953
9954
9955 /*
9956  * Read the next input token.
9957  * If the token is a word, we set backquotelist to the list of cmds in
9958  *      backquotes.  We set quoteflag to true if any part of the word was
9959  *      quoted.
9960  * If the token is TREDIR, then we set redirnode to a structure containing
9961  *      the redirection.
9962  * In all cases, the variable startlinno is set to the number of the line
9963  *      on which the token starts.
9964  *
9965  * [Change comment:  here documents and internal procedures]
9966  * [Readtoken shouldn't have any arguments.  Perhaps we should make the
9967  *  word parsing code into a separate routine.  In this case, readtoken
9968  *  doesn't need to have any internal procedures, but parseword does.
9969  *  We could also make parseoperator in essence the main routine, and
9970  *  have parseword (readtoken1?) handle both words and redirection.]
9971  */
9972
9973 #define NEW_xxreadtoken
9974 #ifdef NEW_xxreadtoken
9975
9976 /* singles must be first! */
9977 static const char xxreadtoken_chars[7] = { '\n', '(', ')', '&', '|', ';', 0 };
9978
9979 static const char xxreadtoken_tokens[] = {
9980         TNL, TLP, TRP,          /* only single occurrence allowed */
9981         TBACKGND, TPIPE, TSEMI, /* if single occurrence */
9982         TEOF,                   /* corresponds to trailing nul */
9983         TAND, TOR, TENDCASE,    /* if double occurrence */
9984 };
9985
9986 #define xxreadtoken_doubles \
9987         (sizeof(xxreadtoken_tokens) - sizeof(xxreadtoken_chars))
9988 #define xxreadtoken_singles \
9989         (sizeof(xxreadtoken_chars) - xxreadtoken_doubles - 1)
9990
9991 static int xxreadtoken()
9992 {
9993         int c;
9994
9995         if (tokpushback) {
9996                 tokpushback = 0;
9997                 return lasttoken;
9998         }
9999         if (needprompt) {
10000                 setprompt(2);
10001                 needprompt = 0;
10002         }
10003         startlinno = plinno;
10004         for (;;) {                      /* until token or start of word found */
10005                 c = pgetc_macro();
10006
10007                 if ((c != ' ') && (c != '\t')
10008 #ifdef CONFIG_ASH_ALIAS
10009                         && (c != PEOA)
10010 #endif
10011                         ) {
10012                         if (c == '#') {
10013                                 while ((c = pgetc()) != '\n' && c != PEOF);
10014                                 pungetc();
10015                         } else if (c == '\\') {
10016                                 if (pgetc() != '\n') {
10017                                         pungetc();
10018                                         goto READTOKEN1;
10019                                 }
10020                                 startlinno = ++plinno;
10021                                 if (doprompt)
10022                                         setprompt(2);
10023                         } else {
10024                                 const char *p
10025                                         = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
10026
10027                                 if (c != PEOF) {
10028                                         if (c == '\n') {
10029                                                 plinno++;
10030                                                 needprompt = doprompt;
10031                                         }
10032
10033                                         p = strchr(xxreadtoken_chars, c);
10034                                         if (p == NULL) {
10035                                           READTOKEN1:
10036                                                 return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
10037                                         }
10038
10039                                         if (p - xxreadtoken_chars >= xxreadtoken_singles) {
10040                                                 if (pgetc() == *p) {    /* double occurrence? */
10041                                                         p += xxreadtoken_doubles + 1;
10042                                                 } else {
10043                                                         pungetc();
10044                                                 }
10045                                         }
10046                                 }
10047
10048                                 return lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
10049                         }
10050                 }
10051         }
10052 }
10053
10054
10055 #else
10056 #define RETURN(token)   return lasttoken = token
10057
10058 static int
10059 xxreadtoken(void)
10060 {
10061         int c;
10062
10063         if (tokpushback) {
10064                 tokpushback = 0;
10065                 return lasttoken;
10066         }
10067         if (needprompt) {
10068                 setprompt(2);
10069                 needprompt = 0;
10070         }
10071         startlinno = plinno;
10072         for (;;) {      /* until token or start of word found */
10073                 c = pgetc_macro();
10074                 switch (c) {
10075                 case ' ': case '\t':
10076 #ifdef CONFIG_ASH_ALIAS
10077                 case PEOA:
10078 #endif
10079                         continue;
10080                 case '#':
10081                         while ((c = pgetc()) != '\n' && c != PEOF);
10082                         pungetc();
10083                         continue;
10084                 case '\\':
10085                         if (pgetc() == '\n') {
10086                                 startlinno = ++plinno;
10087                                 if (doprompt)
10088                                         setprompt(2);
10089                                 continue;
10090                         }
10091                         pungetc();
10092                         goto breakloop;
10093                 case '\n':
10094                         plinno++;
10095                         needprompt = doprompt;
10096                         RETURN(TNL);
10097                 case PEOF:
10098                         RETURN(TEOF);
10099                 case '&':
10100                         if (pgetc() == '&')
10101                                 RETURN(TAND);
10102                         pungetc();
10103                         RETURN(TBACKGND);
10104                 case '|':
10105                         if (pgetc() == '|')
10106                                 RETURN(TOR);
10107                         pungetc();
10108                         RETURN(TPIPE);
10109                 case ';':
10110                         if (pgetc() == ';')
10111                                 RETURN(TENDCASE);
10112                         pungetc();
10113                         RETURN(TSEMI);
10114                 case '(':
10115                         RETURN(TLP);
10116                 case ')':
10117                         RETURN(TRP);
10118                 default:
10119                         goto breakloop;
10120                 }
10121         }
10122 breakloop:
10123         return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
10124 #undef RETURN
10125 }
10126 #endif /* NEW_xxreadtoken */
10127
10128
10129 /*
10130  * If eofmark is NULL, read a word or a redirection symbol.  If eofmark
10131  * is not NULL, read a here document.  In the latter case, eofmark is the
10132  * word which marks the end of the document and striptabs is true if
10133  * leading tabs should be stripped from the document.  The argument firstc
10134  * is the first character of the input token or document.
10135  *
10136  * Because C does not have internal subroutines, I have simulated them
10137  * using goto's to implement the subroutine linkage.  The following macros
10138  * will run code that appears at the end of readtoken1.
10139  */
10140
10141 #define CHECKEND()      {goto checkend; checkend_return:;}
10142 #define PARSEREDIR()    {goto parseredir; parseredir_return:;}
10143 #define PARSESUB()      {goto parsesub; parsesub_return:;}
10144 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
10145 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
10146 #define PARSEARITH()    {goto parsearith; parsearith_return:;}
10147
10148 static int
10149 readtoken1(int firstc, int syntax, char *eofmark, int striptabs)
10150 {
10151         int c = firstc;
10152         char *out;
10153         int len;
10154         char line[EOFMARKLEN + 1];
10155         struct nodelist *bqlist;
10156         int quotef;
10157         int dblquote;
10158         int varnest;    /* levels of variables expansion */
10159         int arinest;    /* levels of arithmetic expansion */
10160         int parenlevel; /* levels of parens in arithmetic */
10161         int dqvarnest;  /* levels of variables expansion within double quotes */
10162         int oldstyle;
10163         int prevsyntax; /* syntax before arithmetic */
10164 #if __GNUC__
10165         /* Avoid longjmp clobbering */
10166         (void) &out;
10167         (void) &quotef;
10168         (void) &dblquote;
10169         (void) &varnest;
10170         (void) &arinest;
10171         (void) &parenlevel;
10172         (void) &dqvarnest;
10173         (void) &oldstyle;
10174         (void) &prevsyntax;
10175         (void) &syntax;
10176 #endif
10177
10178         startlinno = plinno;
10179         dblquote = 0;
10180         if (syntax == DQSYNTAX)
10181                 dblquote = 1;
10182         quotef = 0;
10183         bqlist = NULL;
10184         varnest = 0;
10185         arinest = 0;
10186         parenlevel = 0;
10187         dqvarnest = 0;
10188
10189         STARTSTACKSTR(out);
10190         loop: { /* for each line, until end of word */
10191                 CHECKEND();     /* set c to PEOF if at end of here document */
10192                 for (;;) {      /* until end of line or end of word */
10193                         CHECKSTRSPACE(4, out);  /* permit 4 calls to USTPUTC */
10194                         switch(SIT(c, syntax)) {
10195                         case CNL:       /* '\n' */
10196                                 if (syntax == BASESYNTAX)
10197                                         goto endword;   /* exit outer loop */
10198                                 USTPUTC(c, out);
10199                                 plinno++;
10200                                 if (doprompt)
10201                                         setprompt(2);
10202                                 c = pgetc();
10203                                 goto loop;              /* continue outer loop */
10204                         case CWORD:
10205                                 USTPUTC(c, out);
10206                                 break;
10207                         case CCTL:
10208                                 if (eofmark == NULL || dblquote)
10209                                         USTPUTC(CTLESC, out);
10210                                 USTPUTC(c, out);
10211                                 break;
10212                         case CBACK:     /* backslash */
10213                                 c = pgetc2();
10214                                 if (c == PEOF) {
10215                                         USTPUTC(CTLESC, out);
10216                                         USTPUTC('\\', out);
10217                                         pungetc();
10218                                 } else if (c == '\n') {
10219                                         if (doprompt)
10220                                                 setprompt(2);
10221                                 } else {
10222                                         if (
10223                                                 dblquote &&
10224                                                 c != '\\' && c != '`' &&
10225                                                 c != '$' && (
10226                                                         c != '"' ||
10227                                                         eofmark != NULL
10228                                                 )
10229                                         ) {
10230                                                 USTPUTC(CTLESC, out);
10231                                                 USTPUTC('\\', out);
10232                                         }
10233                                         if (SIT(c, SQSYNTAX) == CCTL)
10234                                                 USTPUTC(CTLESC, out);
10235                                         USTPUTC(c, out);
10236                                         quotef++;
10237                                 }
10238                                 break;
10239                         case CSQUOTE:
10240                                 syntax = SQSYNTAX;
10241 quotemark:
10242                                 if (eofmark == NULL) {
10243                                         USTPUTC(CTLQUOTEMARK, out);
10244                                 }
10245                                 break;
10246                         case CDQUOTE:
10247                                 syntax = DQSYNTAX;
10248                                 dblquote = 1;
10249                                 goto quotemark;
10250                         case CENDQUOTE:
10251                                 if (eofmark != NULL && arinest == 0 &&
10252                                     varnest == 0) {
10253                                         USTPUTC(c, out);
10254                                 } else {
10255                                         if (dqvarnest == 0) {
10256                                                 syntax = BASESYNTAX;
10257                                                 dblquote = 0;
10258                                         }
10259                                         quotef++;
10260                                         goto quotemark;
10261                                 }
10262                                 break;
10263                         case CVAR:      /* '$' */
10264                                 PARSESUB();             /* parse substitution */
10265                                 break;
10266                         case CENDVAR:   /* '}' */
10267                                 if (varnest > 0) {
10268                                         varnest--;
10269                                         if (dqvarnest > 0) {
10270                                                 dqvarnest--;
10271                                         }
10272                                         USTPUTC(CTLENDVAR, out);
10273                                 } else {
10274                                         USTPUTC(c, out);
10275                                 }
10276                                 break;
10277 #ifdef CONFIG_ASH_MATH_SUPPORT
10278                         case CLP:       /* '(' in arithmetic */
10279                                 parenlevel++;
10280                                 USTPUTC(c, out);
10281                                 break;
10282                         case CRP:       /* ')' in arithmetic */
10283                                 if (parenlevel > 0) {
10284                                         USTPUTC(c, out);
10285                                         --parenlevel;
10286                                 } else {
10287                                         if (pgetc() == ')') {
10288                                                 if (--arinest == 0) {
10289                                                         USTPUTC(CTLENDARI, out);
10290                                                         syntax = prevsyntax;
10291                                                         if (syntax == DQSYNTAX)
10292                                                                 dblquote = 1;
10293                                                         else
10294                                                                 dblquote = 0;
10295                                                 } else
10296                                                         USTPUTC(')', out);
10297                                         } else {
10298                                                 /*
10299                                                  * unbalanced parens
10300                                                  *  (don't 2nd guess - no error)
10301                                                  */
10302                                                 pungetc();
10303                                                 USTPUTC(')', out);
10304                                         }
10305                                 }
10306                                 break;
10307 #endif
10308                         case CBQUOTE:   /* '`' */
10309                                 PARSEBACKQOLD();
10310                                 break;
10311                         case CENDFILE:
10312                                 goto endword;           /* exit outer loop */
10313                         case CIGN:
10314                                 break;
10315                         default:
10316                                 if (varnest == 0)
10317                                         goto endword;   /* exit outer loop */
10318 #ifdef CONFIG_ASH_ALIAS
10319                                 if (c != PEOA)
10320 #endif
10321                                         USTPUTC(c, out);
10322
10323                         }
10324                         c = pgetc_macro();
10325                 }
10326         }
10327 endword:
10328 #ifdef CONFIG_ASH_MATH_SUPPORT
10329         if (syntax == ARISYNTAX)
10330                 synerror("Missing '))'");
10331 #endif
10332         if (syntax != BASESYNTAX && ! parsebackquote && eofmark == NULL)
10333                 synerror("Unterminated quoted string");
10334         if (varnest != 0) {
10335                 startlinno = plinno;
10336                 /* { */
10337                 synerror("Missing '}'");
10338         }
10339         USTPUTC('\0', out);
10340         len = out - (char *)stackblock();
10341         out = stackblock();
10342         if (eofmark == NULL) {
10343                 if ((c == '>' || c == '<')
10344                  && quotef == 0
10345                  && len <= 2
10346                  && (*out == '\0' || is_digit(*out))) {
10347                         PARSEREDIR();
10348                         return lasttoken = TREDIR;
10349                 } else {
10350                         pungetc();
10351                 }
10352         }
10353         quoteflag = quotef;
10354         backquotelist = bqlist;
10355         grabstackblock(len);
10356         wordtext = out;
10357         return lasttoken = TWORD;
10358 /* end of readtoken routine */
10359
10360
10361
10362 /*
10363  * Check to see whether we are at the end of the here document.  When this
10364  * is called, c is set to the first character of the next input line.  If
10365  * we are at the end of the here document, this routine sets the c to PEOF.
10366  */
10367
10368 checkend: {
10369         if (eofmark) {
10370 #ifdef CONFIG_ASH_ALIAS
10371                 if (c == PEOA) {
10372                         c = pgetc2();
10373                 }
10374 #endif
10375                 if (striptabs) {
10376                         while (c == '\t') {
10377                                 c = pgetc2();
10378                         }
10379                 }
10380                 if (c == *eofmark) {
10381                         if (pfgets(line, sizeof line) != NULL) {
10382                                 char *p, *q;
10383
10384                                 p = line;
10385                                 for (q = eofmark + 1 ; *q && *p == *q ; p++, q++);
10386                                 if (*p == '\n' && *q == '\0') {
10387                                         c = PEOF;
10388                                         plinno++;
10389                                         needprompt = doprompt;
10390                                 } else {
10391                                         pushstring(line, NULL);
10392                                 }
10393                         }
10394                 }
10395         }
10396         goto checkend_return;
10397 }
10398
10399
10400 /*
10401  * Parse a redirection operator.  The variable "out" points to a string
10402  * specifying the fd to be redirected.  The variable "c" contains the
10403  * first character of the redirection operator.
10404  */
10405
10406 parseredir: {
10407         char fd = *out;
10408         union node *np;
10409
10410         np = (union node *)stalloc(sizeof (struct nfile));
10411         if (c == '>') {
10412                 np->nfile.fd = 1;
10413                 c = pgetc();
10414                 if (c == '>')
10415                         np->type = NAPPEND;
10416                 else if (c == '|')
10417                         np->type = NCLOBBER;
10418                 else if (c == '&')
10419                         np->type = NTOFD;
10420                 else {
10421                         np->type = NTO;
10422                         pungetc();
10423                 }
10424         } else {        /* c == '<' */
10425                 np->nfile.fd = 0;
10426                 switch (c = pgetc()) {
10427                 case '<':
10428                         if (sizeof (struct nfile) != sizeof (struct nhere)) {
10429                                 np = (union node *)stalloc(sizeof (struct nhere));
10430                                 np->nfile.fd = 0;
10431                         }
10432                         np->type = NHERE;
10433                         heredoc = (struct heredoc *)stalloc(sizeof (struct heredoc));
10434                         heredoc->here = np;
10435                         if ((c = pgetc()) == '-') {
10436                                 heredoc->striptabs = 1;
10437                         } else {
10438                                 heredoc->striptabs = 0;
10439                                 pungetc();
10440                         }
10441                         break;
10442
10443                 case '&':
10444                         np->type = NFROMFD;
10445                         break;
10446
10447                 case '>':
10448                         np->type = NFROMTO;
10449                         break;
10450
10451                 default:
10452                         np->type = NFROM;
10453                         pungetc();
10454                         break;
10455                 }
10456         }
10457         if (fd != '\0')
10458                 np->nfile.fd = digit_val(fd);
10459         redirnode = np;
10460         goto parseredir_return;
10461 }
10462
10463
10464 /*
10465  * Parse a substitution.  At this point, we have read the dollar sign
10466  * and nothing else.
10467  */
10468
10469 parsesub: {
10470         int subtype;
10471         int typeloc;
10472         int flags;
10473         char *p;
10474         static const char types[] = "}-+?=";
10475
10476         c = pgetc();
10477         if (
10478                 c <= PEOA_OR_PEOF  ||
10479                 (c != '(' && c != '{' && !is_name(c) && !is_special(c))
10480         ) {
10481                 USTPUTC('$', out);
10482                 pungetc();
10483         } else if (c == '(') {  /* $(command) or $((arith)) */
10484                 if (pgetc() == '(') {
10485 #ifdef CONFIG_ASH_MATH_SUPPORT
10486                         PARSEARITH();
10487 #else
10488                         synerror("We unsupport $((arith))");
10489 #endif
10490                 } else {
10491                         pungetc();
10492                         PARSEBACKQNEW();
10493                 }
10494         } else {
10495                 USTPUTC(CTLVAR, out);
10496                 typeloc = out - (char *)stackblock();
10497                 USTPUTC(VSNORMAL, out);
10498                 subtype = VSNORMAL;
10499                 if (c == '{') {
10500                         c = pgetc();
10501                         if (c == '#') {
10502                                 if ((c = pgetc()) == '}')
10503                                         c = '#';
10504                                 else
10505                                         subtype = VSLENGTH;
10506                         }
10507                         else
10508                                 subtype = 0;
10509                 }
10510                 if (c > PEOA_OR_PEOF && is_name(c)) {
10511                         do {
10512                                 STPUTC(c, out);
10513                                 c = pgetc();
10514                         } while (c > PEOA_OR_PEOF && is_in_name(c));
10515                 } else if (is_digit(c)) {
10516                         do {
10517                                 STPUTC(c, out);
10518                                 c = pgetc();
10519                         } while (is_digit(c));
10520                 }
10521                 else if (is_special(c)) {
10522                         USTPUTC(c, out);
10523                         c = pgetc();
10524                 }
10525                 else
10526 badsub:                 synerror("Bad substitution");
10527
10528                 STPUTC('=', out);
10529                 flags = 0;
10530                 if (subtype == 0) {
10531                         switch (c) {
10532                         case ':':
10533                                 flags = VSNUL;
10534                                 c = pgetc();
10535                                 /*FALLTHROUGH*/
10536                         default:
10537                                 p = strchr(types, c);
10538                                 if (p == NULL)
10539                                         goto badsub;
10540                                 subtype = p - types + VSNORMAL;
10541                                 break;
10542                         case '%':
10543                         case '#':
10544                                 {
10545                                         int cc = c;
10546                                         subtype = c == '#' ? VSTRIMLEFT :
10547                                                              VSTRIMRIGHT;
10548                                         c = pgetc();
10549                                         if (c == cc)
10550                                                 subtype++;
10551                                         else
10552                                                 pungetc();
10553                                         break;
10554                                 }
10555                         }
10556                 } else {
10557                         pungetc();
10558                 }
10559                 if (dblquote || arinest)
10560                         flags |= VSQUOTE;
10561                 *((char *)stackblock() + typeloc) = subtype | flags;
10562                 if (subtype != VSNORMAL) {
10563                         varnest++;
10564                         if (dblquote || arinest) {
10565                                 dqvarnest++;
10566                         }
10567                 }
10568         }
10569         goto parsesub_return;
10570 }
10571
10572
10573 /*
10574  * Called to parse command substitutions.  Newstyle is set if the command
10575  * is enclosed inside $(...); nlpp is a pointer to the head of the linked
10576  * list of commands (passed by reference), and savelen is the number of
10577  * characters on the top of the stack which must be preserved.
10578  */
10579
10580 parsebackq: {
10581         struct nodelist **nlpp;
10582         int savepbq;
10583         union node *n;
10584         char *volatile str;
10585         struct jmploc jmploc;
10586         struct jmploc *volatile savehandler;
10587         size_t savelen;
10588         int saveprompt;
10589 #ifdef __GNUC__
10590         (void) &saveprompt;
10591 #endif
10592
10593         savepbq = parsebackquote;
10594         if (setjmp(jmploc.loc)) {
10595                 if (str)
10596                         ckfree(str);
10597                 parsebackquote = 0;
10598                 handler = savehandler;
10599                 longjmp(handler->loc, 1);
10600         }
10601         INTOFF;
10602         str = NULL;
10603         savelen = out - (char *)stackblock();
10604         if (savelen > 0) {
10605                 str = ckmalloc(savelen);
10606                 memcpy(str, stackblock(), savelen);
10607         }
10608         savehandler = handler;
10609         handler = &jmploc;
10610         INTON;
10611         if (oldstyle) {
10612                 /* We must read until the closing backquote, giving special
10613                    treatment to some slashes, and then push the string and
10614                    reread it as input, interpreting it normally.  */
10615                 char *pout;
10616                 int pc;
10617                 size_t psavelen;
10618                 char *pstr;
10619
10620
10621                 STARTSTACKSTR(pout);
10622                 for (;;) {
10623                         if (needprompt) {
10624                                 setprompt(2);
10625                                 needprompt = 0;
10626                         }
10627                         switch (pc = pgetc()) {
10628                         case '`':
10629                                 goto done;
10630
10631                         case '\\':
10632                                 if ((pc = pgetc()) == '\n') {
10633                                         plinno++;
10634                                         if (doprompt)
10635                                                 setprompt(2);
10636                                         /*
10637                                          * If eating a newline, avoid putting
10638                                          * the newline into the new character
10639                                          * stream (via the STPUTC after the
10640                                          * switch).
10641                                          */
10642                                         continue;
10643                                 }
10644                                 if (pc != '\\' && pc != '`' && pc != '$'
10645                                     && (!dblquote || pc != '"'))
10646                                         STPUTC('\\', pout);
10647                                 if (pc > PEOA_OR_PEOF) {
10648                                         break;
10649                                 }
10650                                 /* fall through */
10651
10652                         case PEOF:
10653 #ifdef CONFIG_ASH_ALIAS
10654                         case PEOA:
10655 #endif
10656                                 startlinno = plinno;
10657                                 synerror("EOF in backquote substitution");
10658
10659                         case '\n':
10660                                 plinno++;
10661                                 needprompt = doprompt;
10662                                 break;
10663
10664                         default:
10665                                 break;
10666                         }
10667                         STPUTC(pc, pout);
10668                 }
10669 done:
10670                 STPUTC('\0', pout);
10671                 psavelen = pout - (char *)stackblock();
10672                 if (psavelen > 0) {
10673                         pstr = grabstackstr(pout);
10674                         setinputstring(pstr);
10675                 }
10676         }
10677         nlpp = &bqlist;
10678         while (*nlpp)
10679                 nlpp = &(*nlpp)->next;
10680         *nlpp = (struct nodelist *)stalloc(sizeof (struct nodelist));
10681         (*nlpp)->next = NULL;
10682         parsebackquote = oldstyle;
10683
10684         if (oldstyle) {
10685                 saveprompt = doprompt;
10686                 doprompt = 0;
10687         }
10688
10689         n = list(2);
10690
10691         if (oldstyle)
10692                 doprompt = saveprompt;
10693         else {
10694                 if (readtoken() != TRP)
10695                         synexpect(TRP);
10696         }
10697
10698         (*nlpp)->n = n;
10699         if (oldstyle) {
10700                 /*
10701                  * Start reading from old file again, ignoring any pushed back
10702                  * tokens left from the backquote parsing
10703                  */
10704                 popfile();
10705                 tokpushback = 0;
10706         }
10707         while (stackblocksize() <= savelen)
10708                 growstackblock();
10709         STARTSTACKSTR(out);
10710         if (str) {
10711                 memcpy(out, str, savelen);
10712                 STADJUST(savelen, out);
10713                 INTOFF;
10714                 ckfree(str);
10715                 str = NULL;
10716                 INTON;
10717         }
10718         parsebackquote = savepbq;
10719         handler = savehandler;
10720         if (arinest || dblquote)
10721                 USTPUTC(CTLBACKQ | CTLQUOTE, out);
10722         else
10723                 USTPUTC(CTLBACKQ, out);
10724         if (oldstyle)
10725                 goto parsebackq_oldreturn;
10726         else
10727                 goto parsebackq_newreturn;
10728 }
10729
10730 #ifdef CONFIG_ASH_MATH_SUPPORT
10731 /*
10732  * Parse an arithmetic expansion (indicate start of one and set state)
10733  */
10734 parsearith: {
10735
10736         if (++arinest == 1) {
10737                 prevsyntax = syntax;
10738                 syntax = ARISYNTAX;
10739                 USTPUTC(CTLARI, out);
10740                 if (dblquote)
10741                         USTPUTC('"',out);
10742                 else
10743                         USTPUTC(' ',out);
10744         } else {
10745                 /*
10746                  * we collapse embedded arithmetic expansion to
10747                  * parenthesis, which should be equivalent
10748                  */
10749                 USTPUTC('(', out);
10750         }
10751         goto parsearith_return;
10752 }
10753 #endif
10754
10755 } /* end of readtoken */
10756
10757
10758
10759 /*
10760  * Returns true if the text contains nothing to expand (no dollar signs
10761  * or backquotes).
10762  */
10763
10764 static int
10765 noexpand(char *text)
10766 {
10767         char *p;
10768         char c;
10769
10770         p = text;
10771         while ((c = *p++) != '\0') {
10772                 if (c == CTLQUOTEMARK)
10773                         continue;
10774                 if (c == CTLESC)
10775                         p++;
10776                 else if (SIT(c, BASESYNTAX) == CCTL)
10777                         return 0;
10778         }
10779         return 1;
10780 }
10781
10782
10783 /*
10784  * Return of a legal variable name (a letter or underscore followed by zero or
10785  * more letters, underscores, and digits).
10786  */
10787
10788 char *
10789 endofname(const char *name)
10790 {
10791         char *p;
10792
10793         p = (char *) name;
10794         if (! is_name(*p))
10795                 return p;
10796         while (*++p) {
10797                 if (! is_in_name(*p))
10798                         break;
10799         }
10800         return p;
10801 }
10802
10803
10804 /*
10805  * Called when an unexpected token is read during the parse.  The argument
10806  * is the token that is expected, or -1 if more than one type of token can
10807  * occur at this point.
10808  */
10809
10810 static void synexpect(int token)
10811 {
10812         char msg[64];
10813         int l;
10814
10815         l = sprintf(msg, "%s unexpected", tokname(lasttoken));
10816         if (token >= 0)
10817                 sprintf(msg + l, " (expecting %s)", tokname(token));
10818         synerror(msg);
10819         /* NOTREACHED */
10820 }
10821
10822 static void
10823 synerror(const char *msg)
10824 {
10825         error("Syntax error: %s", msg);
10826         /* NOTREACHED */
10827 }
10828
10829
10830 /*
10831  * called by editline -- any expansions to the prompt
10832  *    should be added here.
10833  */
10834
10835 static void setprompt(int whichprompt)
10836 {
10837         const char *prompt;
10838
10839         switch (whichprompt) {
10840         case 1:
10841                 prompt = ps1val();
10842                 break;
10843         case 2:
10844                 prompt = ps2val();
10845                 break;
10846         default:                        /* 0 */
10847                 prompt = nullstr;
10848         }
10849         putprompt(prompt);
10850 }
10851
10852
10853 static const char *const *findkwd(const char *s)
10854 {
10855         return bsearch(s, tokname_array + KWDOFFSET,
10856                        (sizeof(tokname_array) / sizeof(const char *)) - KWDOFFSET,
10857                                    sizeof(const char *), pstrcmp);
10858 }
10859
10860 /*      $NetBSD: redir.c,v 1.27 2002/11/24 22:35:42 christos Exp $      */
10861
10862 /*
10863  * Code for dealing with input/output redirection.
10864  */
10865
10866 #define EMPTY -2                /* marks an unused slot in redirtab */
10867 #ifndef PIPE_BUF
10868 # define PIPESIZE 4096          /* amount of buffering in a pipe */
10869 #else
10870 # define PIPESIZE PIPE_BUF
10871 #endif
10872
10873 /*
10874  * Open a file in noclobber mode.
10875  * The code was copied from bash.
10876  */
10877 static inline int
10878 noclobberopen(const char *fname)
10879 {
10880         int r, fd;
10881         struct stat finfo, finfo2;
10882
10883         /*
10884          * If the file exists and is a regular file, return an error
10885          * immediately.
10886          */
10887         r = stat(fname, &finfo);
10888         if (r == 0 && S_ISREG(finfo.st_mode)) {
10889                 errno = EEXIST;
10890                 return -1;
10891         }
10892
10893         /*
10894          * If the file was not present (r != 0), make sure we open it
10895          * exclusively so that if it is created before we open it, our open
10896          * will fail.  Make sure that we do not truncate an existing file.
10897          * Note that we don't turn on O_EXCL unless the stat failed -- if the
10898          * file was not a regular file, we leave O_EXCL off.
10899          */
10900         if (r != 0)
10901                 return open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
10902         fd = open(fname, O_WRONLY|O_CREAT, 0666);
10903
10904         /* If the open failed, return the file descriptor right away. */
10905         if (fd < 0)
10906                 return fd;
10907
10908         /*
10909          * OK, the open succeeded, but the file may have been changed from a
10910          * non-regular file to a regular file between the stat and the open.
10911          * We are assuming that the O_EXCL open handles the case where FILENAME
10912          * did not exist and is symlinked to an existing file between the stat
10913          * and open.
10914          */
10915
10916         /*
10917          * If we can open it and fstat the file descriptor, and neither check
10918          * revealed that it was a regular file, and the file has not been
10919          * replaced, return the file descriptor.
10920          */
10921          if (fstat(fd, &finfo2) == 0 && !S_ISREG(finfo2.st_mode) &&
10922              finfo.st_dev == finfo2.st_dev && finfo.st_ino == finfo2.st_ino)
10923                 return fd;
10924
10925         /* The file has been replaced.  badness. */
10926         close(fd);
10927         errno = EEXIST;
10928         return -1;
10929 }
10930
10931 /*
10932  * Handle here documents.  Normally we fork off a process to write the
10933  * data to a pipe.  If the document is short, we can stuff the data in
10934  * the pipe without forking.
10935  */
10936
10937 static inline int
10938 openhere(union node *redir)
10939 {
10940         int pip[2];
10941         size_t len = 0;
10942
10943         if (pipe(pip) < 0)
10944                 error("Pipe call failed");
10945         if (redir->type == NHERE) {
10946                 len = strlen(redir->nhere.doc->narg.text);
10947                 if (len <= PIPESIZE) {
10948                         xwrite(pip[1], redir->nhere.doc->narg.text, len);
10949                         goto out;
10950                 }
10951         }
10952         if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
10953                 close(pip[0]);
10954                 signal(SIGINT, SIG_IGN);
10955                 signal(SIGQUIT, SIG_IGN);
10956                 signal(SIGHUP, SIG_IGN);
10957 #ifdef SIGTSTP
10958                 signal(SIGTSTP, SIG_IGN);
10959 #endif
10960                 signal(SIGPIPE, SIG_DFL);
10961                 if (redir->type == NHERE)
10962                         xwrite(pip[1], redir->nhere.doc->narg.text, len);
10963                 else
10964                         expandhere(redir->nhere.doc, pip[1]);
10965                 _exit(0);
10966         }
10967 out:
10968         close(pip[1]);
10969         return pip[0];
10970 }
10971
10972 static int
10973 openredirect(union node *redir)
10974 {
10975         char *fname;
10976         int f;
10977
10978         switch (redir->nfile.type) {
10979         case NFROM:
10980                 fname = redir->nfile.expfname;
10981                 if ((f = open(fname, O_RDONLY)) < 0)
10982                         goto eopen;
10983                 break;
10984         case NFROMTO:
10985                 fname = redir->nfile.expfname;
10986                 if ((f = open(fname, O_RDWR|O_CREAT|O_TRUNC, 0666)) < 0)
10987                         goto ecreate;
10988                 break;
10989         case NTO:
10990                 /* Take care of noclobber mode. */
10991                 if (Cflag) {
10992                         fname = redir->nfile.expfname;
10993                         if ((f = noclobberopen(fname)) < 0)
10994                                 goto ecreate;
10995                         break;
10996                 }
10997                 /* FALLTHROUGH */
10998         case NCLOBBER:
10999                 fname = redir->nfile.expfname;
11000                 if ((f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0)
11001                         goto ecreate;
11002                 break;
11003         case NAPPEND:
11004                 fname = redir->nfile.expfname;
11005                 if ((f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666)) < 0)
11006                         goto ecreate;
11007                 break;
11008         default:
11009 #ifdef DEBUG
11010                 abort();
11011 #endif
11012                 /* Fall through to eliminate warning. */
11013         case NTOFD:
11014         case NFROMFD:
11015                 f = -1;
11016                 break;
11017         case NHERE:
11018         case NXHERE:
11019                 f = openhere(redir);
11020                 break;
11021         }
11022
11023         return f;
11024 ecreate:
11025         error("cannot create %s: %s", fname, errmsg(errno, E_CREAT));
11026 eopen:
11027         error("cannot open %s: %s", fname, errmsg(errno, E_OPEN));
11028 }
11029
11030 static inline void
11031 dupredirect(union node *redir, int f)
11032 {
11033         int fd = redir->nfile.fd;
11034
11035         if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
11036                 if (redir->ndup.dupfd >= 0) {   /* if not ">&-" */
11037                                 copyfd(redir->ndup.dupfd, fd);
11038                 }
11039                 return;
11040         }
11041
11042         if (f != fd) {
11043                 copyfd(f, fd);
11044                 close(f);
11045         }
11046         return;
11047 }
11048
11049 /*
11050  * Process a list of redirection commands.  If the REDIR_PUSH flag is set,
11051  * old file descriptors are stashed away so that the redirection can be
11052  * undone by calling popredir.  If the REDIR_BACKQ flag is set, then the
11053  * standard output, and the standard error if it becomes a duplicate of
11054  * stdout, is saved in memory.
11055  */
11056
11057 static void
11058 redirect(union node *redir, int flags)
11059 {
11060         union node *n;
11061         struct redirtab *sv;
11062         int i;
11063         int fd;
11064         int newfd;
11065         int *p;
11066         nullredirs++;
11067         if (!redir) {
11068                 return;
11069         }
11070         sv = NULL;
11071         INTOFF;
11072         if (flags & REDIR_PUSH) {
11073                 struct redirtab *q;
11074                 q = ckmalloc(sizeof (struct redirtab));
11075                 q->next = redirlist;
11076                 redirlist = q;
11077                 q->nullredirs = nullredirs - 1;
11078                 for (i = 0 ; i < 10 ; i++)
11079                         q->renamed[i] = EMPTY;
11080                 nullredirs = 0;
11081                 sv = q;
11082         }
11083         n = redir;
11084         do {
11085                 fd = n->nfile.fd;
11086                 if ((n->nfile.type == NTOFD || n->nfile.type == NFROMFD) &&
11087                     n->ndup.dupfd == fd)
11088                         continue; /* redirect from/to same file descriptor */
11089
11090                 newfd = openredirect(n);
11091                 if (fd == newfd)
11092                         continue;
11093                 if (sv && *(p = &sv->renamed[fd]) == EMPTY) {
11094                         i = fcntl(fd, F_DUPFD, 10);
11095
11096                         if (i == -1) {
11097                                 i = errno;
11098                                 if (i != EBADF) {
11099                                         close(newfd);
11100                                         errno = i;
11101                                         error("%d: %m", fd);
11102                                         /* NOTREACHED */
11103                                 }
11104                         } else {
11105                                 *p = i;
11106                                 close(fd);
11107                         }
11108                 } else {
11109                         close(fd);
11110                 }
11111                 dupredirect(n, newfd);
11112         } while ((n = n->nfile.next));
11113         INTON;
11114         if (flags & REDIR_SAVEFD2 && sv && sv->renamed[2] >= 0)
11115                 preverrout_fd = sv->renamed[2];
11116 }
11117
11118
11119 /*
11120  * Undo the effects of the last redirection.
11121  */
11122
11123 void
11124 popredir(int drop)
11125 {
11126         struct redirtab *rp;
11127         int i;
11128
11129         if (--nullredirs >= 0)
11130                 return;
11131         INTOFF;
11132         rp = redirlist;
11133         for (i = 0 ; i < 10 ; i++) {
11134                 if (rp->renamed[i] != EMPTY) {
11135                         if (!drop) {
11136                                 close(i);
11137                                 copyfd(rp->renamed[i], i);
11138                         }
11139                         close(rp->renamed[i]);
11140                 }
11141         }
11142         redirlist = rp->next;
11143         nullredirs = rp->nullredirs;
11144         ckfree(rp);
11145         INTON;
11146 }
11147
11148 /*
11149  * Undo all redirections.  Called on error or interrupt.
11150  */
11151
11152 /*
11153  * Discard all saved file descriptors.
11154  */
11155
11156 void
11157 clearredir(int drop)
11158 {
11159         for (;;) {
11160                 nullredirs = 0;
11161                 if (!redirlist)
11162                         break;
11163                 popredir(drop);
11164         }
11165 }
11166
11167
11168 /*
11169  * Copy a file descriptor to be >= to.  Returns -1
11170  * if the source file descriptor is closed, EMPTY if there are no unused
11171  * file descriptors left.
11172  */
11173
11174 int
11175 copyfd(int from, int to)
11176 {
11177         int newfd;
11178
11179         newfd = fcntl(from, F_DUPFD, to);
11180         if (newfd < 0) {
11181                 if (errno == EMFILE)
11182                         return EMPTY;
11183                 else
11184                         error("%d: %m", from);
11185         }
11186         return newfd;
11187 }
11188
11189
11190 int
11191 redirectsafe(union node *redir, int flags)
11192 {
11193         int err;
11194         volatile int saveint;
11195         struct jmploc *volatile savehandler = handler;
11196         struct jmploc jmploc;
11197
11198         SAVEINT(saveint);
11199         if (!(err = setjmp(jmploc.loc) * 2)) {
11200                 handler = &jmploc;
11201                 redirect(redir, flags);
11202         }
11203         handler = savehandler;
11204         if (err && exception != EXERROR)
11205                 longjmp(handler->loc, 1);
11206         RESTOREINT(saveint);
11207         return err;
11208 }
11209
11210 /*      $NetBSD: show.c,v 1.24 2003/01/22 20:36:04 dsl Exp $    */
11211
11212 #ifdef DEBUG
11213 static void shtree(union node *, int, char *, FILE*);
11214 static void shcmd(union node *, FILE *);
11215 static void sharg(union node *, FILE *);
11216 static void indent(int, char *, FILE *);
11217 static void trstring(char *);
11218
11219
11220 void
11221 showtree(union node *n)
11222 {
11223         trputs("showtree called\n");
11224         shtree(n, 1, NULL, stdout);
11225 }
11226
11227
11228 static void
11229 shtree(union node *n, int ind, char *pfx, FILE *fp)
11230 {
11231         struct nodelist *lp;
11232         const char *s;
11233
11234         if (n == NULL)
11235                 return;
11236
11237         indent(ind, pfx, fp);
11238         switch(n->type) {
11239         case NSEMI:
11240                 s = "; ";
11241                 goto binop;
11242         case NAND:
11243                 s = " && ";
11244                 goto binop;
11245         case NOR:
11246                 s = " || ";
11247 binop:
11248                 shtree(n->nbinary.ch1, ind, NULL, fp);
11249            /*    if (ind < 0) */
11250                         fputs(s, fp);
11251                 shtree(n->nbinary.ch2, ind, NULL, fp);
11252                 break;
11253         case NCMD:
11254                 shcmd(n, fp);
11255                 if (ind >= 0)
11256                         putc('\n', fp);
11257                 break;
11258         case NPIPE:
11259                 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
11260                         shcmd(lp->n, fp);
11261                         if (lp->next)
11262                                 fputs(" | ", fp);
11263                 }
11264                 if (n->npipe.backgnd)
11265                         fputs(" &", fp);
11266                 if (ind >= 0)
11267                         putc('\n', fp);
11268                 break;
11269         default:
11270                 fprintf(fp, "<node type %d>", n->type);
11271                 if (ind >= 0)
11272                         putc('\n', fp);
11273                 break;
11274         }
11275 }
11276
11277
11278 static void
11279 shcmd(union node *cmd, FILE *fp)
11280 {
11281         union node *np;
11282         int first;
11283         const char *s;
11284         int dftfd;
11285
11286         first = 1;
11287         for (np = cmd->ncmd.args ; np ; np = np->narg.next) {
11288                 if (! first)
11289                         putchar(' ');
11290                 sharg(np, fp);
11291                 first = 0;
11292         }
11293         for (np = cmd->ncmd.redirect ; np ; np = np->nfile.next) {
11294                 if (! first)
11295                         putchar(' ');
11296                 switch (np->nfile.type) {
11297                         case NTO:       s = ">";  dftfd = 1; break;
11298                         case NCLOBBER:  s = ">|"; dftfd = 1; break;
11299                         case NAPPEND:   s = ">>"; dftfd = 1; break;
11300                         case NTOFD:     s = ">&"; dftfd = 1; break;
11301                         case NFROM:     s = "<";  dftfd = 0; break;
11302                         case NFROMFD:   s = "<&"; dftfd = 0; break;
11303                         case NFROMTO:   s = "<>"; dftfd = 0; break;
11304                         default:        s = "*error*"; dftfd = 0; break;
11305                 }
11306                 if (np->nfile.fd != dftfd)
11307                         fprintf(fp, "%d", np->nfile.fd);
11308                 fputs(s, fp);
11309                 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
11310                         fprintf(fp, "%d", np->ndup.dupfd);
11311                 } else {
11312                         sharg(np->nfile.fname, fp);
11313                 }
11314                 first = 0;
11315         }
11316 }
11317
11318
11319
11320 static void
11321 sharg(union node *arg, FILE *fp)
11322 {
11323         char *p;
11324         struct nodelist *bqlist;
11325         int subtype;
11326
11327         if (arg->type != NARG) {
11328                 out1fmt("<node type %d>\n", arg->type);
11329                 abort();
11330         }
11331         bqlist = arg->narg.backquote;
11332         for (p = arg->narg.text ; *p ; p++) {
11333                 switch (*p) {
11334                 case CTLESC:
11335                         putc(*++p, fp);
11336                         break;
11337                 case CTLVAR:
11338                         putc('$', fp);
11339                         putc('{', fp);
11340                         subtype = *++p;
11341                         if (subtype == VSLENGTH)
11342                                 putc('#', fp);
11343
11344                         while (*p != '=')
11345                                 putc(*p++, fp);
11346
11347                         if (subtype & VSNUL)
11348                                 putc(':', fp);
11349
11350                         switch (subtype & VSTYPE) {
11351                         case VSNORMAL:
11352                                 putc('}', fp);
11353                                 break;
11354                         case VSMINUS:
11355                                 putc('-', fp);
11356                                 break;
11357                         case VSPLUS:
11358                                 putc('+', fp);
11359                                 break;
11360                         case VSQUESTION:
11361                                 putc('?', fp);
11362                                 break;
11363                         case VSASSIGN:
11364                                 putc('=', fp);
11365                                 break;
11366                         case VSTRIMLEFT:
11367                                 putc('#', fp);
11368                                 break;
11369                         case VSTRIMLEFTMAX:
11370                                 putc('#', fp);
11371                                 putc('#', fp);
11372                                 break;
11373                         case VSTRIMRIGHT:
11374                                 putc('%', fp);
11375                                 break;
11376                         case VSTRIMRIGHTMAX:
11377                                 putc('%', fp);
11378                                 putc('%', fp);
11379                                 break;
11380                         case VSLENGTH:
11381                                 break;
11382                         default:
11383                                 out1fmt("<subtype %d>", subtype);
11384                         }
11385                         break;
11386                 case CTLENDVAR:
11387                      putc('}', fp);
11388                      break;
11389                 case CTLBACKQ:
11390                 case CTLBACKQ|CTLQUOTE:
11391                         putc('$', fp);
11392                         putc('(', fp);
11393                         shtree(bqlist->n, -1, NULL, fp);
11394                         putc(')', fp);
11395                         break;
11396                 default:
11397                         putc(*p, fp);
11398                         break;
11399                 }
11400         }
11401 }
11402
11403
11404 static void
11405 indent(int amount, char *pfx, FILE *fp)
11406 {
11407         int i;
11408
11409         for (i = 0 ; i < amount ; i++) {
11410                 if (pfx && i == amount - 1)
11411                         fputs(pfx, fp);
11412                 putc('\t', fp);
11413         }
11414 }
11415
11416
11417
11418 /*
11419  * Debugging stuff.
11420  */
11421
11422
11423 FILE *tracefile;
11424
11425
11426 void
11427 trputc(int c)
11428 {
11429         if (debug != 1)
11430                 return;
11431         putc(c, tracefile);
11432 }
11433
11434 void
11435 trace(const char *fmt, ...)
11436 {
11437         va_list va;
11438
11439         if (debug != 1)
11440                 return;
11441         va_start(va, fmt);
11442         (void) vfprintf(tracefile, fmt, va);
11443         va_end(va);
11444 }
11445
11446 void
11447 tracev(const char *fmt, va_list va)
11448 {
11449         if (debug != 1)
11450                 return;
11451         (void) vfprintf(tracefile, fmt, va);
11452 }
11453
11454
11455 void
11456 trputs(const char *s)
11457 {
11458         if (debug != 1)
11459                 return;
11460         fputs(s, tracefile);
11461 }
11462
11463
11464 static void
11465 trstring(char *s)
11466 {
11467         char *p;
11468         char c;
11469
11470         if (debug != 1)
11471                 return;
11472         putc('"', tracefile);
11473         for (p = s ; *p ; p++) {
11474                 switch (*p) {
11475                 case '\n':  c = 'n';  goto backslash;
11476                 case '\t':  c = 't';  goto backslash;
11477                 case '\r':  c = 'r';  goto backslash;
11478                 case '"':  c = '"';  goto backslash;
11479                 case '\\':  c = '\\';  goto backslash;
11480                 case CTLESC:  c = 'e';  goto backslash;
11481                 case CTLVAR:  c = 'v';  goto backslash;
11482                 case CTLVAR+CTLQUOTE:  c = 'V';  goto backslash;
11483                 case CTLBACKQ:  c = 'q';  goto backslash;
11484                 case CTLBACKQ+CTLQUOTE:  c = 'Q';  goto backslash;
11485 backslash:        putc('\\', tracefile);
11486                         putc(c, tracefile);
11487                         break;
11488                 default:
11489                         if (*p >= ' ' && *p <= '~')
11490                                 putc(*p, tracefile);
11491                         else {
11492                                 putc('\\', tracefile);
11493                                 putc(*p >> 6 & 03, tracefile);
11494                                 putc(*p >> 3 & 07, tracefile);
11495                                 putc(*p & 07, tracefile);
11496                         }
11497                         break;
11498                 }
11499         }
11500         putc('"', tracefile);
11501 }
11502
11503
11504 void
11505 trargs(char **ap)
11506 {
11507         if (debug != 1)
11508                 return;
11509         while (*ap) {
11510                 trstring(*ap++);
11511                 if (*ap)
11512                         putc(' ', tracefile);
11513                 else
11514                         putc('\n', tracefile);
11515         }
11516 }
11517
11518
11519 void
11520 opentrace(void)
11521 {
11522         char s[100];
11523 #ifdef O_APPEND
11524         int flags;
11525 #endif
11526
11527         if (debug != 1) {
11528                 if (tracefile)
11529                         fflush(tracefile);
11530                 /* leave open because libedit might be using it */
11531                 return;
11532         }
11533         scopy("./trace", s);
11534         if (tracefile) {
11535                 if (!freopen(s, "a", tracefile)) {
11536                         fprintf(stderr, "Can't re-open %s\n", s);
11537                         debug = 0;
11538                         return;
11539                 }
11540         } else {
11541                 if ((tracefile = fopen(s, "a")) == NULL) {
11542                         fprintf(stderr, "Can't open %s\n", s);
11543                         debug = 0;
11544                         return;
11545                 }
11546         }
11547 #ifdef O_APPEND
11548         if ((flags = fcntl(fileno(tracefile), F_GETFL, 0)) >= 0)
11549                 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
11550 #endif
11551         setlinebuf(tracefile);
11552         fputs("\nTracing started.\n", tracefile);
11553 }
11554 #endif /* DEBUG */
11555
11556
11557 /*      $NetBSD: trap.c,v 1.28 2002/11/24 22:35:43 christos Exp $       */
11558
11559 /*
11560  * Sigmode records the current value of the signal handlers for the various
11561  * modes.  A value of zero means that the current handler is not known.
11562  * S_HARD_IGN indicates that the signal was ignored on entry to the shell,
11563  */
11564
11565 #define S_DFL 1                 /* default signal handling (SIG_DFL) */
11566 #define S_CATCH 2               /* signal is caught */
11567 #define S_IGN 3                 /* signal is ignored (SIG_IGN) */
11568 #define S_HARD_IGN 4            /* signal is ignored permenantly */
11569 #define S_RESET 5               /* temporary - to reset a hard ignored sig */
11570
11571
11572
11573 /*
11574  * The trap builtin.
11575  */
11576
11577 int
11578 trapcmd(int argc, char **argv)
11579 {
11580         char *action;
11581         char **ap;
11582         int signo;
11583
11584         nextopt(nullstr);
11585         ap = argptr;
11586         if (!*ap) {
11587                 for (signo = 0 ; signo < NSIG ; signo++) {
11588                         if (trap[signo] != NULL) {
11589                                 const char *sn;
11590
11591                                 sn = u_signal_names(0, &signo, 0);
11592                                 if (sn == NULL)
11593                                         sn = "???";
11594                                 out1fmt("trap -- %s %s\n",
11595                                         single_quote(trap[signo]), sn);
11596                         }
11597                 }
11598                 return 0;
11599         }
11600         if (!ap[1])
11601                 action = NULL;
11602         else
11603                 action = *ap++;
11604         while (*ap) {
11605                 if ((signo = decode_signal(*ap, 0)) < 0)
11606                         error("%s: bad trap", *ap);
11607                 INTOFF;
11608                 if (action) {
11609                         if (action[0] == '-' && action[1] == '\0')
11610                                 action = NULL;
11611                         else
11612                                 action = savestr(action);
11613                 }
11614                 if (trap[signo])
11615                         ckfree(trap[signo]);
11616                 trap[signo] = action;
11617                 if (signo != 0)
11618                         setsignal(signo);
11619                 INTON;
11620                 ap++;
11621         }
11622         return 0;
11623 }
11624
11625
11626 /*
11627  * Clear traps on a fork.
11628  */
11629
11630 void
11631 clear_traps(void)
11632 {
11633         char **tp;
11634
11635         for (tp = trap ; tp < &trap[NSIG] ; tp++) {
11636                 if (*tp && **tp) {      /* trap not NULL or SIG_IGN */
11637                         INTOFF;
11638                         ckfree(*tp);
11639                         *tp = NULL;
11640                         if (tp != &trap[0])
11641                                 setsignal(tp - trap);
11642                         INTON;
11643                 }
11644         }
11645 }
11646
11647
11648 /*
11649  * Set the signal handler for the specified signal.  The routine figures
11650  * out what it should be set to.
11651  */
11652
11653 void
11654 setsignal(int signo)
11655 {
11656         int action;
11657         char *t, tsig;
11658         struct sigaction act;
11659
11660         if ((t = trap[signo]) == NULL)
11661                 action = S_DFL;
11662         else if (*t != '\0')
11663                 action = S_CATCH;
11664         else
11665                 action = S_IGN;
11666         if (rootshell && action == S_DFL) {
11667                 switch (signo) {
11668                 case SIGINT:
11669                         if (iflag || minusc || sflag == 0)
11670                                 action = S_CATCH;
11671                         break;
11672                 case SIGQUIT:
11673 #ifdef DEBUG
11674                         if (debug)
11675                                 break;
11676 #endif
11677                         /* FALLTHROUGH */
11678                 case SIGTERM:
11679                         if (iflag)
11680                                 action = S_IGN;
11681                         break;
11682 #if JOBS
11683                 case SIGTSTP:
11684                 case SIGTTOU:
11685                         if (mflag)
11686                                 action = S_IGN;
11687                         break;
11688 #endif
11689                 }
11690         }
11691
11692         t = &sigmode[signo - 1];
11693         tsig = *t;
11694         if (tsig == 0) {
11695                 /*
11696                  * current setting unknown
11697                  */
11698                 if (sigaction(signo, 0, &act) == -1) {
11699                         /*
11700                          * Pretend it worked; maybe we should give a warning
11701                          * here, but other shells don't. We don't alter
11702                          * sigmode, so that we retry every time.
11703                          */
11704                         return;
11705                 }
11706                 if (act.sa_handler == SIG_IGN) {
11707                         if (mflag && (signo == SIGTSTP ||
11708                              signo == SIGTTIN || signo == SIGTTOU)) {
11709                                 tsig = S_IGN;   /* don't hard ignore these */
11710                         } else
11711                                 tsig = S_HARD_IGN;
11712                 } else {
11713                         tsig = S_RESET; /* force to be set */
11714                 }
11715         }
11716         if (tsig == S_HARD_IGN || tsig == action)
11717                 return;
11718         switch (action) {
11719         case S_CATCH:
11720                 act.sa_handler = onsig;
11721                 break;
11722         case S_IGN:
11723                 act.sa_handler = SIG_IGN;
11724                 break;
11725         default:
11726                 act.sa_handler = SIG_DFL;
11727         }
11728         *t = action;
11729         act.sa_flags = 0;
11730         sigfillset(&act.sa_mask);
11731         sigaction(signo, &act, 0);
11732 }
11733
11734 /*
11735  * Ignore a signal.
11736  */
11737
11738 void
11739 ignoresig(int signo)
11740 {
11741         if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
11742                 signal(signo, SIG_IGN);
11743         }
11744         sigmode[signo - 1] = S_HARD_IGN;
11745 }
11746
11747
11748 /*
11749  * Signal handler.
11750  */
11751
11752 void
11753 onsig(int signo)
11754 {
11755         gotsig[signo - 1] = 1;
11756         pendingsigs = signo;
11757
11758         if (exsig || (signo == SIGINT && !trap[SIGINT])) {
11759                 if (!suppressint)
11760                         onint();
11761                 intpending = 1;
11762         }
11763 }
11764
11765
11766 /*
11767  * Called to execute a trap.  Perhaps we should avoid entering new trap
11768  * handlers while we are executing a trap handler.
11769  */
11770
11771 void
11772 dotrap(void)
11773 {
11774         char *p;
11775         char *q;
11776         int savestatus;
11777
11778         savestatus = exitstatus;
11779         q = gotsig;
11780         while (pendingsigs = 0, barrier(), (p = memchr(q, 1, NSIG - 1))) {
11781                 *p = 0;
11782                 p = trap[p - q + 1];
11783                 if (!p)
11784                         continue;
11785                 evalstring(p, 0);
11786                 exitstatus = savestatus;
11787         }
11788 }
11789
11790
11791 /*
11792  * Controls whether the shell is interactive or not.
11793  */
11794
11795 void
11796 setinteractive(int on)
11797 {
11798         static int is_interactive;
11799
11800         if (++on == is_interactive)
11801                 return;
11802         is_interactive = on;
11803         setsignal(SIGINT);
11804         setsignal(SIGQUIT);
11805         setsignal(SIGTERM);
11806 #ifndef CONFIG_FEATURE_SH_EXTRA_QUIET
11807                 if(is_interactive > 1) {
11808                         /* Looks like they want an interactive shell */
11809                         static int do_banner;
11810
11811                                 if(!do_banner) {
11812                                         out1fmt(
11813                         "\n\n" BB_BANNER " Built-in shell (ash)\n"
11814                         "Enter 'help' for a list of built-in commands.\n\n");
11815                                         do_banner++;
11816                                 }
11817                 }
11818 #endif
11819 }
11820
11821
11822 #ifndef CONFIG_FEATURE_SH_EXTRA_QUIET
11823 /*** List the available builtins ***/
11824
11825 static int helpcmd(int argc, char **argv)
11826 {
11827         int col, i;
11828
11829         out1fmt("\nBuilt-in commands:\n-------------------\n");
11830         for (col = 0, i = 0; i < NUMBUILTINS; i++) {
11831                 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
11832                                           builtincmd[i].name + 1);
11833                 if (col > 60) {
11834                         out1fmt("\n");
11835                         col = 0;
11836                 }
11837         }
11838 #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
11839         {
11840                 extern const struct BB_applet applets[];
11841                 extern const size_t NUM_APPLETS;
11842
11843                 for (i = 0; i < NUM_APPLETS; i++) {
11844
11845                         col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), applets[i].name);
11846                         if (col > 60) {
11847                                 out1fmt("\n");
11848                                 col = 0;
11849                         }
11850                 }
11851         }
11852 #endif
11853         out1fmt("\n\n");
11854         return EXIT_SUCCESS;
11855 }
11856 #endif /* CONFIG_FEATURE_SH_EXTRA_QUIET */
11857
11858 /*
11859  * Called to exit the shell.
11860  */
11861
11862 void
11863 exitshell(void)
11864 {
11865         struct jmploc loc;
11866         char *p;
11867         int status;
11868
11869         status = exitstatus;
11870         TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
11871         if (setjmp(loc.loc)) {
11872                 goto out;
11873         }
11874         handler = &loc;
11875         if ((p = trap[0]) != NULL && *p != '\0') {
11876                 trap[0] = NULL;
11877                 evalstring(p, 0);
11878         }
11879         flushall();
11880 #ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
11881         if (iflag && rootshell) {
11882                 const char *hp = lookupvar("HISTFILE");
11883
11884                 if(hp != NULL )
11885                         save_history ( hp );
11886         }
11887 #endif
11888 out:
11889         _exit(status);
11890         /* NOTREACHED */
11891 }
11892
11893 static int decode_signal(const char *string, int minsig)
11894 {
11895         int signo;
11896         const char *name = u_signal_names(string, &signo, minsig);
11897
11898         return name ? signo : -1;
11899 }
11900
11901 /*      $NetBSD: var.c,v 1.32 2003/01/22 20:36:04 dsl Exp $     */
11902
11903 static struct var *vartab[VTABSIZE];
11904
11905 static int vpcmp(const void *, const void *);
11906 static struct var **findvar(struct var **, const char *);
11907
11908 /*
11909  * Initialize the varable symbol tables and import the environment
11910  */
11911
11912
11913 #ifdef CONFIG_ASH_GETOPTS
11914 /*
11915  * Safe version of setvar, returns 1 on success 0 on failure.
11916  */
11917
11918 int
11919 setvarsafe(const char *name, const char *val, int flags)
11920 {
11921         int err;
11922         volatile int saveint;
11923         struct jmploc *volatile savehandler = handler;
11924         struct jmploc jmploc;
11925
11926         SAVEINT(saveint);
11927         if (setjmp(jmploc.loc))
11928                 err = 1;
11929         else {
11930                 handler = &jmploc;
11931                 setvar(name, val, flags);
11932                 err = 0;
11933         }
11934         handler = savehandler;
11935         RESTOREINT(saveint);
11936         return err;
11937 }
11938 #endif
11939
11940 /*
11941  * Set the value of a variable.  The flags argument is ored with the
11942  * flags of the variable.  If val is NULL, the variable is unset.
11943  */
11944
11945 static void
11946 setvar(const char *name, const char *val, int flags)
11947 {
11948         char *p, *q;
11949         size_t namelen;
11950         char *nameeq;
11951         size_t vallen;
11952
11953         q = endofname(name);
11954         p = strchrnul(q, '=');
11955         namelen = p - name;
11956         if (!namelen || p != q)
11957                 error("%.*s: bad variable name", namelen, name);
11958         vallen = 0;
11959         if (val == NULL) {
11960                 flags |= VUNSET;
11961         } else {
11962                 vallen = strlen(val);
11963         }
11964         INTOFF;
11965         p = mempcpy(nameeq = ckmalloc(namelen + vallen + 2), name, namelen);
11966         *p++ = '\0';
11967         if (vallen) {
11968                 p[-1] = '=';
11969                 p = mempcpy(p, val, vallen);
11970         }
11971         *p = '\0';
11972         setvareq(nameeq, flags | VNOSAVE);
11973         INTON;
11974 }
11975
11976
11977 /*
11978  * Same as setvar except that the variable and value are passed in
11979  * the first argument as name=value.  Since the first argument will
11980  * be actually stored in the table, it should not be a string that
11981  * will go away.
11982  * Called with interrupts off.
11983  */
11984
11985 void
11986 setvareq(char *s, int flags)
11987 {
11988         struct var *vp, **vpp;
11989
11990         vpp = hashvar(s);
11991         flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
11992         vp = *findvar(vpp, s);
11993         if (vp) {
11994                 if (vp->flags & VREADONLY) {
11995                         if (flags & VNOSAVE)
11996                                 free(s);
11997                         error("%.*s: is read only", strchrnul(s, '=') - s, s);
11998                 }
11999
12000                 if (flags & VNOSET)
12001                         return;
12002
12003                 if (vp->func && (flags & VNOFUNC) == 0)
12004                         (*vp->func)(strchrnul(s, '=') + 1);
12005
12006                 if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
12007                         ckfree(vp->text);
12008
12009                 flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET);
12010         } else {
12011                 if (flags & VNOSET)
12012                         return;
12013                 /* not found */
12014                 vp = ckmalloc(sizeof (*vp));
12015                 vp->next = *vpp;
12016                 vp->func = NULL;
12017                 *vpp = vp;
12018         }
12019         if (!(flags & (VTEXTFIXED|VSTACK|VNOSAVE)))
12020                 s = savestr(s);
12021         vp->text = s;
12022         vp->flags = flags;
12023 }
12024
12025
12026 /*
12027  * Process a linked list of variable assignments.
12028  */
12029
12030 static void
12031 listsetvar(struct strlist *list_set_var, int flags)
12032 {
12033         struct strlist *lp = list_set_var;
12034
12035         if (!lp)
12036                 return;
12037         INTOFF;
12038         do {
12039                 setvareq(lp->text, flags);
12040         } while ((lp = lp->next));
12041         INTON;
12042 }
12043
12044
12045 /*
12046  * Find the value of a variable.  Returns NULL if not set.
12047  */
12048
12049 static char *
12050 lookupvar(const char *name)
12051 {
12052         struct var *v;
12053
12054         if ((v = *findvar(hashvar(name), name)) && !(v->flags & VUNSET)) {
12055                 return strchrnul(v->text, '=') + 1;
12056         }
12057         return NULL;
12058 }
12059
12060
12061 /*
12062  * Search the environment of a builtin command.
12063  */
12064
12065 static char *
12066 bltinlookup(const char *name)
12067 {
12068         struct strlist *sp;
12069
12070         for (sp = cmdenviron ; sp ; sp = sp->next) {
12071                 if (varequal(sp->text, name))
12072                         return strchrnul(sp->text, '=') + 1;
12073         }
12074         return lookupvar(name);
12075 }
12076
12077
12078 /*
12079  * Generate a list of variables satisfying the given conditions.
12080  */
12081
12082 static char **
12083 listvars(int on, int off, char ***end)
12084 {
12085         struct var **vpp;
12086         struct var *vp;
12087         char **ep;
12088         int mask;
12089
12090         STARTSTACKSTR(ep);
12091         vpp = vartab;
12092         mask = on | off;
12093         do {
12094                 for (vp = *vpp ; vp ; vp = vp->next)
12095                         if ((vp->flags & mask) == on) {
12096                                 if (ep == stackstrend())
12097                                         ep = growstackstr();
12098                                 *ep++ = (char *) vp->text;
12099                         }
12100         } while (++vpp < vartab + VTABSIZE);
12101         if (ep == stackstrend())
12102                 ep = growstackstr();
12103         if (end)
12104                 *end = ep;
12105         *ep++ = NULL;
12106         return grabstackstr(ep);
12107 }
12108
12109
12110 /*
12111  * POSIX requires that 'set' (but not export or readonly) output the
12112  * variables in lexicographic order - by the locale's collating order (sigh).
12113  * Maybe we could keep them in an ordered balanced binary tree
12114  * instead of hashed lists.
12115  * For now just roll 'em through qsort for printing...
12116  */
12117
12118 static int
12119 showvars(const char *sep_prefix, int on, int off)
12120 {
12121         const char *sep;
12122         char **ep, **epend;
12123
12124         ep = listvars(on, off, &epend);
12125         qsort(ep, epend - ep, sizeof(char *), vpcmp);
12126
12127         sep = *sep_prefix ? spcstr : sep_prefix;
12128
12129         for (; ep < epend; ep++) {
12130                 const char *p;
12131                 const char *q;
12132
12133                 p = strchrnul(*ep, '=');
12134                 q = nullstr;
12135                 if (*p)
12136                         q = single_quote(++p);
12137
12138                 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
12139         }
12140
12141         return 0;
12142 }
12143
12144
12145
12146 /*
12147  * The export and readonly commands.
12148  */
12149
12150 static int
12151 exportcmd(int argc, char **argv)
12152 {
12153         struct var *vp;
12154         char *name;
12155         const char *p;
12156         char **aptr;
12157         int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT;
12158         int notp;
12159
12160         notp = nextopt("p") - 'p';
12161         if (notp && ((name = *(aptr = argptr)))) {
12162                 do {
12163                         if ((p = strchr(name, '=')) != NULL) {
12164                                 p++;
12165                         } else {
12166                                 if ((vp = *findvar(hashvar(name), name))) {
12167                                         vp->flags |= flag;
12168                                         continue;
12169                                 }
12170                         }
12171                         setvar(name, p, flag);
12172                 } while ((name = *++aptr) != NULL);
12173         } else {
12174                 showvars(argv[0], flag, 0);
12175         }
12176         return 0;
12177 }
12178
12179
12180 /*
12181  * Make a variable a local variable.  When a variable is made local, it's
12182  * value and flags are saved in a localvar structure.  The saved values
12183  * will be restored when the shell function returns.  We handle the name
12184  * "-" as a special case.
12185  */
12186
12187 static inline void
12188 mklocal(char *name)
12189 {
12190         struct localvar *lvp;
12191         struct var **vpp;
12192         struct var *vp;
12193
12194         INTOFF;
12195         lvp = ckmalloc(sizeof (struct localvar));
12196         if (name[0] == '-' && name[1] == '\0') {
12197                 char *p;
12198                 p = ckmalloc(sizeof(optlist));
12199                 lvp->text = memcpy(p, optlist, sizeof(optlist));
12200                 vp = NULL;
12201         } else {
12202                 char *eq;
12203
12204                 vpp = hashvar(name);
12205                 vp = *findvar(vpp, name);
12206                 eq = strchr(name, '=');
12207                 if (vp == NULL) {
12208                         if (eq)
12209                                 setvareq(name, VSTRFIXED);
12210                         else
12211                                 setvar(name, NULL, VSTRFIXED);
12212                         vp = *vpp;      /* the new variable */
12213                         lvp->flags = VUNSET;
12214                 } else {
12215                         lvp->text = vp->text;
12216                         lvp->flags = vp->flags;
12217                         vp->flags |= VSTRFIXED|VTEXTFIXED;
12218                         if (eq)
12219                                 setvareq(name, 0);
12220                 }
12221         }
12222         lvp->vp = vp;
12223         lvp->next = localvars;
12224         localvars = lvp;
12225         INTON;
12226 }
12227
12228 /*
12229  * The "local" command.
12230  */
12231
12232 static int
12233 localcmd(int argc, char **argv)
12234 {
12235         char *name;
12236
12237         argv = argptr;
12238         while ((name = *argv++) != NULL) {
12239                 mklocal(name);
12240         }
12241         return 0;
12242 }
12243
12244
12245 /*
12246  * Called after a function returns.
12247  * Interrupts must be off.
12248  */
12249
12250 static void
12251 poplocalvars(void)
12252 {
12253         struct localvar *lvp;
12254         struct var *vp;
12255
12256         while ((lvp = localvars) != NULL) {
12257                 localvars = lvp->next;
12258                 vp = lvp->vp;
12259                 TRACE(("poplocalvar %s", vp ? vp->text : "-"));
12260                 if (vp == NULL) {       /* $- saved */
12261                         memcpy(optlist, lvp->text, sizeof(optlist));
12262                         ckfree(lvp->text);
12263                         optschanged();
12264                 } else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
12265                         unsetvar(vp->text);
12266                 } else {
12267                         if (vp->func)
12268                                 (*vp->func)(strchrnul(lvp->text, '=') + 1);
12269                         if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
12270                                 ckfree(vp->text);
12271                         vp->flags = lvp->flags;
12272                         vp->text = lvp->text;
12273                 }
12274                 ckfree(lvp);
12275         }
12276 }
12277
12278
12279 /*
12280  * The unset builtin command.  We unset the function before we unset the
12281  * variable to allow a function to be unset when there is a readonly variable
12282  * with the same name.
12283  */
12284
12285 int
12286 unsetcmd(int argc, char **argv)
12287 {
12288         char **ap;
12289         int i;
12290         int flag = 0;
12291         int ret = 0;
12292
12293         while ((i = nextopt("vf")) != '\0') {
12294                 flag = i;
12295         }
12296
12297         for (ap = argptr; *ap ; ap++) {
12298                 if (flag != 'f') {
12299                         i = unsetvar(*ap);
12300                         ret |= i;
12301                         if (!(i & 2))
12302                                 continue;
12303                 }
12304                 if (flag != 'v')
12305                         unsetfunc(*ap);
12306         }
12307         return ret & 1;
12308 }
12309
12310
12311 /*
12312  * Unset the specified variable.
12313  */
12314
12315 int
12316 unsetvar(const char *s)
12317 {
12318         struct var **vpp;
12319         struct var *vp;
12320         int retval;
12321
12322         vpp = findvar(hashvar(s), s);
12323         vp = *vpp;
12324         retval = 2;
12325         if (vp) {
12326                 int flags = vp->flags;
12327
12328                 retval = 1;
12329                 if (flags & VREADONLY)
12330                         goto out;
12331                 if (flags & VUNSET)
12332                         goto ok;
12333                 if ((flags & VSTRFIXED) == 0) {
12334                         INTOFF;
12335                         if ((flags & (VTEXTFIXED|VSTACK)) == 0)
12336                                 ckfree(vp->text);
12337                         *vpp = vp->next;
12338                         ckfree(vp);
12339                         INTON;
12340                 } else {
12341                         setvar(s, 0, 0);
12342                         vp->flags &= ~VEXPORT;
12343                 }
12344 ok:
12345                 retval = 0;
12346         }
12347
12348 out:
12349         return retval;
12350 }
12351
12352
12353
12354 /*
12355  * Find the appropriate entry in the hash table from the name.
12356  */
12357
12358 static struct var **
12359 hashvar(const char *p)
12360 {
12361         unsigned int hashval;
12362
12363         hashval = ((unsigned char) *p) << 4;
12364         while (*p && *p != '=')
12365                 hashval += (unsigned char) *p++;
12366         return &vartab[hashval % VTABSIZE];
12367 }
12368
12369
12370
12371 /*
12372  * Compares two strings up to the first = or '\0'.  The first
12373  * string must be terminated by '='; the second may be terminated by
12374  * either '=' or '\0'.
12375  */
12376
12377 int
12378 varcmp(const char *p, const char *q)
12379 {
12380         int c, d;
12381
12382         while ((c = *p) == (d = *q)) {
12383                 if (!c || c == '=')
12384                         goto out;
12385                 p++;
12386                 q++;
12387         }
12388         if (c == '=')
12389                 c = 0;
12390         if (d == '=')
12391                 d = 0;
12392 out:
12393         return c - d;
12394 }
12395
12396 static int
12397 vpcmp(const void *a, const void *b)
12398 {
12399         return varcmp(*(const char **)a, *(const char **)b);
12400 }
12401
12402 static struct var **
12403 findvar(struct var **vpp, const char *name)
12404 {
12405         for (; *vpp; vpp = &(*vpp)->next) {
12406                 if (varequal((*vpp)->text, name)) {
12407                         break;
12408                 }
12409         }
12410         return vpp;
12411 }
12412 /*      $NetBSD: setmode.c,v 1.29 2003/01/15 23:58:03 kleink Exp $      */
12413
12414 #include <sys/times.h>
12415
12416 static const unsigned char timescmd_str[] = {
12417         ' ',  offsetof(struct tms, tms_utime),
12418         '\n', offsetof(struct tms, tms_stime),
12419         ' ',  offsetof(struct tms, tms_cutime),
12420         '\n', offsetof(struct tms, tms_cstime),
12421         0
12422 };
12423
12424 static int timescmd(int ac, char **av)
12425 {
12426         long int clk_tck, s, t;
12427         const unsigned char *p;
12428         struct tms buf;
12429
12430         clk_tck = sysconf(_SC_CLK_TCK);
12431         times(&buf);
12432
12433         p = timescmd_str;
12434         do {
12435                 t = *(clock_t *)(((char *) &buf) + p[1]);
12436                 s = t / clk_tck;
12437                 out1fmt("%ldm%ld.%.3lds%c",
12438                         s/60, s%60,
12439                         ((t - s * clk_tck) * 1000) / clk_tck,
12440                         p[0]);
12441         } while (*(p += 2));
12442
12443         return 0;
12444 }
12445
12446 #ifdef CONFIG_ASH_MATH_SUPPORT
12447 static int
12448 dash_arith(const char *s)
12449 {
12450         long result;
12451         int errcode = 0;
12452
12453         INTOFF;
12454         result = arith(s, &errcode);
12455         if (errcode < 0) {
12456                 if (errcode == -3)
12457                         error("exponent less than 0");
12458                 else if (errcode == -2)
12459                         error("divide by zero");
12460                 else if (errcode == -5)
12461                         error("expression recursion loop detected");
12462                 else
12463                         synerror(s);
12464         }
12465         INTON;
12466
12467         return (result);
12468 }
12469
12470
12471 /*
12472  *  The let builtin. partial stolen from GNU Bash, the Bourne Again SHell.
12473  *  Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
12474  *
12475  *  Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
12476  */
12477
12478 static int
12479 letcmd(int argc, char **argv)
12480 {
12481         char **ap;
12482         long i;
12483
12484         ap = argv + 1;
12485         if(!*ap)
12486                 error("expression expected");
12487         for (ap = argv + 1; *ap; ap++) {
12488                 i = dash_arith(*ap);
12489         }
12490
12491         return (!i);
12492 }
12493 #endif /* CONFIG_ASH_MATH_SUPPORT */
12494
12495 /*      $NetBSD: miscbltin.c,v 1.31 2002/11/24 22:35:41 christos Exp $  */
12496
12497 /*
12498  * Miscelaneous builtins.
12499  */
12500
12501 #undef rflag
12502
12503 #ifdef __GLIBC__
12504 #if !defined(__GLIBC__) || __GLIBC__ == 2 && __GLIBC_MINOR__ < 1
12505 typedef enum __rlimit_resource rlim_t;
12506 #endif
12507 #endif
12508
12509
12510 /*
12511  * The read builtin.  The -e option causes backslashes to escape the
12512  * following character.
12513  *
12514  * This uses unbuffered input, which may be avoidable in some cases.
12515  */
12516
12517 static int
12518 readcmd(int argc, char **argv)
12519 {
12520         char **ap;
12521         int backslash;
12522         char c;
12523         int rflag;
12524         char *prompt;
12525         const char *ifs;
12526         char *p;
12527         int startword;
12528         int status;
12529         int i;
12530
12531         rflag = 0;
12532         prompt = NULL;
12533         while ((i = nextopt("p:r")) != '\0') {
12534                 if (i == 'p')
12535                         prompt = optionarg;
12536                 else
12537                         rflag = 1;
12538         }
12539         if (prompt && isatty(0)) {
12540                 out2str(prompt);
12541         }
12542         if (*(ap = argptr) == NULL)
12543                 error("arg count");
12544         if ((ifs = bltinlookup("IFS")) == NULL)
12545                 ifs = defifs;
12546         status = 0;
12547         startword = 1;
12548         backslash = 0;
12549         STARTSTACKSTR(p);
12550         for (;;) {
12551                 if (read(0, &c, 1) != 1) {
12552                         status = 1;
12553                         break;
12554                 }
12555                 if (c == '\0')
12556                         continue;
12557                 if (backslash) {
12558                         backslash = 0;
12559                         if (c != '\n')
12560                                 goto put;
12561                         continue;
12562                 }
12563                 if (!rflag && c == '\\') {
12564                         backslash++;
12565                         continue;
12566                 }
12567                 if (c == '\n')
12568                         break;
12569                 if (startword && *ifs == ' ' && strchr(ifs, c)) {
12570                         continue;
12571                 }
12572                 startword = 0;
12573                 if (ap[1] != NULL && strchr(ifs, c) != NULL) {
12574                         STACKSTRNUL(p);
12575                         setvar(*ap, stackblock(), 0);
12576                         ap++;
12577                         startword = 1;
12578                         STARTSTACKSTR(p);
12579                 } else {
12580 put:
12581                         STPUTC(c, p);
12582                 }
12583         }
12584         STACKSTRNUL(p);
12585         /* Remove trailing blanks */
12586         while ((char *)stackblock() <= --p && strchr(ifs, *p) != NULL)
12587                 *p = '\0';
12588         setvar(*ap, stackblock(), 0);
12589         while (*++ap != NULL)
12590                 setvar(*ap, nullstr, 0);
12591         return status;
12592 }
12593
12594
12595 static int umaskcmd(int argc, char **argv)
12596 {
12597         static const char permuser[3] = "ugo";
12598         static const char permmode[3] = "rwx";
12599         static const short int permmask[] = {
12600                 S_IRUSR, S_IWUSR, S_IXUSR,
12601                 S_IRGRP, S_IWGRP, S_IXGRP,
12602                 S_IROTH, S_IWOTH, S_IXOTH
12603         };
12604
12605         char *ap;
12606         mode_t mask;
12607         int i;
12608         int symbolic_mode = 0;
12609
12610         while (nextopt("S") != '\0') {
12611                 symbolic_mode = 1;
12612         }
12613
12614         INTOFF;
12615         mask = umask(0);
12616         umask(mask);
12617         INTON;
12618
12619         if ((ap = *argptr) == NULL) {
12620                 if (symbolic_mode) {
12621                         char buf[18];
12622                         char *p = buf;
12623
12624                         for (i = 0; i < 3; i++) {
12625                                 int j;
12626
12627                                 *p++ = permuser[i];
12628                                 *p++ = '=';
12629                                 for (j = 0; j < 3; j++) {
12630                                         if ((mask & permmask[3 * i + j]) == 0) {
12631                                                 *p++ = permmode[j];
12632                                         }
12633                                 }
12634                                 *p++ = ',';
12635                         }
12636                         *--p = 0;
12637                         puts(buf);
12638                 } else {
12639                         out1fmt("%.4o\n", mask);
12640                 }
12641         } else {
12642                 if (is_digit((unsigned char) *ap)) {
12643                         mask = 0;
12644                         do {
12645                                 if (*ap >= '8' || *ap < '0')
12646                                         error(illnum, argv[1]);
12647                                 mask = (mask << 3) + (*ap - '0');
12648                         } while (*++ap != '\0');
12649                         umask(mask);
12650                 } else {
12651                         mask = ~mask & 0777;
12652                         if (!bb_parse_mode(ap, &mask)) {
12653                                 error("Illegal mode: %s", ap);
12654                         }
12655                         umask(~mask & 0777);
12656                 }
12657         }
12658         return 0;
12659 }
12660
12661 /*
12662  * ulimit builtin
12663  *
12664  * This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and
12665  * Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with
12666  * ash by J.T. Conklin.
12667  *
12668  * Public domain.
12669  */
12670
12671 struct limits {
12672         const char *name;
12673         int     cmd;
12674         int     factor; /* multiply by to get rlim_{cur,max} values */
12675         char    option;
12676 };
12677
12678 static const struct limits limits[] = {
12679 #ifdef RLIMIT_CPU
12680         { "time(seconds)",              RLIMIT_CPU,        1, 't' },
12681 #endif
12682 #ifdef RLIMIT_FSIZE
12683         { "file(blocks)",               RLIMIT_FSIZE,    512, 'f' },
12684 #endif
12685 #ifdef RLIMIT_DATA
12686         { "data(kbytes)",               RLIMIT_DATA,    1024, 'd' },
12687 #endif
12688 #ifdef RLIMIT_STACK
12689         { "stack(kbytes)",              RLIMIT_STACK,   1024, 's' },
12690 #endif
12691 #ifdef  RLIMIT_CORE
12692         { "coredump(blocks)",           RLIMIT_CORE,     512, 'c' },
12693 #endif
12694 #ifdef RLIMIT_RSS
12695         { "memory(kbytes)",             RLIMIT_RSS,     1024, 'm' },
12696 #endif
12697 #ifdef RLIMIT_MEMLOCK
12698         { "locked memory(kbytes)",      RLIMIT_MEMLOCK, 1024, 'l' },
12699 #endif
12700 #ifdef RLIMIT_NPROC
12701         { "process(processes)",         RLIMIT_NPROC,      1, 'p' },
12702 #endif
12703 #ifdef RLIMIT_NOFILE
12704         { "nofiles(descriptors)",       RLIMIT_NOFILE,     1, 'n' },
12705 #endif
12706 #ifdef RLIMIT_VMEM
12707         { "vmemory(kbytes)",            RLIMIT_VMEM,    1024, 'v' },
12708 #endif
12709 #ifdef RLIMIT_SWAP
12710         { "swap(kbytes)",               RLIMIT_SWAP,    1024, 'w' },
12711 #endif
12712         { (char *) 0,                   0,                 0,  '\0' }
12713 };
12714
12715 int
12716 ulimitcmd(int argc, char **argv)
12717 {
12718         int     c;
12719         rlim_t val = 0;
12720         enum { SOFT = 0x1, HARD = 0x2 }
12721                         how = SOFT | HARD;
12722         const struct limits     *l;
12723         int             set, all = 0;
12724         int             optc, what;
12725         struct rlimit   limit;
12726
12727         what = 'f';
12728         while ((optc = nextopt("HSatfdsmcnpl")) != '\0')
12729                 switch (optc) {
12730                 case 'H':
12731                         how = HARD;
12732                         break;
12733                 case 'S':
12734                         how = SOFT;
12735                         break;
12736                 case 'a':
12737                         all = 1;
12738                         break;
12739                 default:
12740                         what = optc;
12741                 }
12742
12743         for (l = limits; l->name && l->option != what; l++)
12744                 ;
12745         if (!l->name)
12746                 error("internal error (%c)", what);
12747
12748         set = *argptr ? 1 : 0;
12749         if (set) {
12750                 char *p = *argptr;
12751
12752                 if (all || argptr[1])
12753                         error("too many arguments");
12754                 if (strncmp(p, "unlimited\n", 9) == 0)
12755                         val = RLIM_INFINITY;
12756                 else {
12757                         val = (rlim_t) 0;
12758
12759                         while ((c = *p++) >= '0' && c <= '9')
12760                         {
12761                                 val = (val * 10) + (long)(c - '0');
12762                                 if (val < (rlim_t) 0)
12763                                         break;
12764                         }
12765                         if (c)
12766                                 error("bad number");
12767                         val *= l->factor;
12768                 }
12769         }
12770         if (all) {
12771                 for (l = limits; l->name; l++) {
12772                         getrlimit(l->cmd, &limit);
12773                         if (how & SOFT)
12774                                 val = limit.rlim_cur;
12775                         else if (how & HARD)
12776                                 val = limit.rlim_max;
12777
12778                         out1fmt("%-20s ", l->name);
12779                         if (val == RLIM_INFINITY)
12780                                 out1fmt("unlimited\n");
12781                         else
12782                         {
12783                                 val /= l->factor;
12784                                 out1fmt("%lld\n", (long long) val);
12785                         }
12786                 }
12787                 return 0;
12788         }
12789
12790         getrlimit(l->cmd, &limit);
12791         if (set) {
12792                 if (how & HARD)
12793                         limit.rlim_max = val;
12794                 if (how & SOFT)
12795                         limit.rlim_cur = val;
12796                 if (setrlimit(l->cmd, &limit) < 0)
12797                         error("error setting limit (%m)");
12798         } else {
12799                 if (how & SOFT)
12800                         val = limit.rlim_cur;
12801                 else if (how & HARD)
12802                         val = limit.rlim_max;
12803
12804                 if (val == RLIM_INFINITY)
12805                         out1fmt("unlimited\n");
12806                 else
12807                 {
12808                         val /= l->factor;
12809                         out1fmt("%lld\n", (long long) val);
12810                 }
12811         }
12812         return 0;
12813 }
12814
12815
12816 #ifdef CONFIG_ASH_MATH_SUPPORT
12817
12818 /* Copyright (c) 2001 Aaron Lehmann <aaronl@vitelus.com>
12819
12820    Permission is hereby granted, free of charge, to any person obtaining
12821    a copy of this software and associated documentation files (the
12822    "Software"), to deal in the Software without restriction, including
12823    without limitation the rights to use, copy, modify, merge, publish,
12824    distribute, sublicense, and/or sell copies of the Software, and to
12825    permit persons to whom the Software is furnished to do so, subject to
12826    the following conditions:
12827
12828    The above copyright notice and this permission notice shall be
12829    included in all copies or substantial portions of the Software.
12830
12831    THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
12832    EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
12833    MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
12834    IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
12835    CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
12836    TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
12837    SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
12838 */
12839
12840 /* This is my infix parser/evaluator. It is optimized for size, intended
12841  * as a replacement for yacc-based parsers. However, it may well be faster
12842  * than a comparable parser writen in yacc. The supported operators are
12843  * listed in #defines below. Parens, order of operations, and error handling
12844  * are supported. This code is threadsafe. The exact expression format should
12845  * be that which POSIX specifies for shells. */
12846
12847 /* The code uses a simple two-stack algorithm. See
12848  * http://www.onthenet.com.au/~grahamis/int2008/week02/lect02.html
12849  * for a detailed explaination of the infix-to-postfix algorithm on which
12850  * this is based (this code differs in that it applies operators immediately
12851  * to the stack instead of adding them to a queue to end up with an
12852  * expression). */
12853
12854 /* To use the routine, call it with an expression string and error return
12855  * pointer */
12856
12857 /*
12858  * Aug 24, 2001              Manuel Novoa III
12859  *
12860  * Reduced the generated code size by about 30% (i386) and fixed several bugs.
12861  *
12862  * 1) In arith_apply():
12863  *    a) Cached values of *numptr and &(numptr[-1]).
12864  *    b) Removed redundant test for zero denominator.
12865  *
12866  * 2) In arith():
12867  *    a) Eliminated redundant code for processing operator tokens by moving
12868  *       to a table-based implementation.  Also folded handling of parens
12869  *       into the table.
12870  *    b) Combined all 3 loops which called arith_apply to reduce generated
12871  *       code size at the cost of speed.
12872  *
12873  * 3) The following expressions were treated as valid by the original code:
12874  *       1()  ,    0!  ,    1 ( *3 )   .
12875  *    These bugs have been fixed by internally enclosing the expression in
12876  *    parens and then checking that all binary ops and right parens are
12877  *    preceded by a valid expression (NUM_TOKEN).
12878  *
12879  * Note: It may be desireable to replace Aaron's test for whitespace with
12880  * ctype's isspace() if it is used by another busybox applet or if additional
12881  * whitespace chars should be considered.  Look below the "#include"s for a
12882  * precompiler test.
12883  */
12884
12885 /*
12886  * Aug 26, 2001              Manuel Novoa III
12887  *
12888  * Return 0 for null expressions.  Pointed out by Vladimir Oleynik.
12889  *
12890  * Merge in Aaron's comments previously posted to the busybox list,
12891  * modified slightly to take account of my changes to the code.
12892  *
12893  */
12894
12895 /*
12896  *  (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
12897  *
12898  * - allow access to variable,
12899  *   used recursive find value indirection (c=2*2; a="c"; $((a+=2)) produce 6)
12900  * - realize assign syntax (VAR=expr, +=, *= etc)
12901  * - realize exponentiation (** operator)
12902  * - realize comma separated - expr, expr
12903  * - realise ++expr --expr expr++ expr--
12904  * - realise expr ? expr : expr (but, second expr calculate always)
12905  * - allow hexdecimal and octal numbers
12906  * - was restored loses XOR operator
12907  * - remove one goto label, added three ;-)
12908  * - protect $((num num)) as true zero expr (Manuel`s error)
12909  * - always use special isspace(), see comment from bash ;-)
12910  */
12911
12912
12913 #define arith_isspace(arithval) \
12914         (arithval == ' ' || arithval == '\n' || arithval == '\t')
12915
12916
12917 typedef unsigned char operator;
12918
12919 /* An operator's token id is a bit of a bitfield. The lower 5 bits are the
12920  * precedence, and 3 high bits are an ID unique accross operators of that
12921  * precedence. The ID portion is so that multiple operators can have the
12922  * same precedence, ensuring that the leftmost one is evaluated first.
12923  * Consider * and /. */
12924
12925 #define tok_decl(prec,id) (((id)<<5)|(prec))
12926 #define PREC(op) ((op) & 0x1F)
12927
12928 #define TOK_LPAREN tok_decl(0,0)
12929
12930 #define TOK_COMMA tok_decl(1,0)
12931
12932 #define TOK_ASSIGN tok_decl(2,0)
12933 #define TOK_AND_ASSIGN tok_decl(2,1)
12934 #define TOK_OR_ASSIGN tok_decl(2,2)
12935 #define TOK_XOR_ASSIGN tok_decl(2,3)
12936 #define TOK_PLUS_ASSIGN tok_decl(2,4)
12937 #define TOK_MINUS_ASSIGN tok_decl(2,5)
12938 #define TOK_LSHIFT_ASSIGN tok_decl(2,6)
12939 #define TOK_RSHIFT_ASSIGN tok_decl(2,7)
12940
12941 #define TOK_MUL_ASSIGN tok_decl(3,0)
12942 #define TOK_DIV_ASSIGN tok_decl(3,1)
12943 #define TOK_REM_ASSIGN tok_decl(3,2)
12944
12945 /* all assign is right associativity and precedence eq, but (7+3)<<5 > 256 */
12946 #define convert_prec_is_assing(prec) do { if(prec == 3) prec = 2; } while(0)
12947
12948 /* conditional is right associativity too */
12949 #define TOK_CONDITIONAL tok_decl(4,0)
12950 #define TOK_CONDITIONAL_SEP tok_decl(4,1)
12951
12952 #define TOK_OR tok_decl(5,0)
12953
12954 #define TOK_AND tok_decl(6,0)
12955
12956 #define TOK_BOR tok_decl(7,0)
12957
12958 #define TOK_BXOR tok_decl(8,0)
12959
12960 #define TOK_BAND tok_decl(9,0)
12961
12962 #define TOK_EQ tok_decl(10,0)
12963 #define TOK_NE tok_decl(10,1)
12964
12965 #define TOK_LT tok_decl(11,0)
12966 #define TOK_GT tok_decl(11,1)
12967 #define TOK_GE tok_decl(11,2)
12968 #define TOK_LE tok_decl(11,3)
12969
12970 #define TOK_LSHIFT tok_decl(12,0)
12971 #define TOK_RSHIFT tok_decl(12,1)
12972
12973 #define TOK_ADD tok_decl(13,0)
12974 #define TOK_SUB tok_decl(13,1)
12975
12976 #define TOK_MUL tok_decl(14,0)
12977 #define TOK_DIV tok_decl(14,1)
12978 #define TOK_REM tok_decl(14,2)
12979
12980 /* exponent is right associativity */
12981 #define TOK_EXPONENT tok_decl(15,1)
12982
12983 /* For now unary operators. */
12984 #define UNARYPREC 16
12985 #define TOK_BNOT tok_decl(UNARYPREC,0)
12986 #define TOK_NOT tok_decl(UNARYPREC,1)
12987
12988 #define TOK_UMINUS tok_decl(UNARYPREC+1,0)
12989 #define TOK_UPLUS tok_decl(UNARYPREC+1,1)
12990
12991 #define PREC_PRE (UNARYPREC+2)
12992
12993 #define TOK_PRE_INC tok_decl(PREC_PRE, 0)
12994 #define TOK_PRE_DEC tok_decl(PREC_PRE, 1)
12995
12996 #define PREC_POST (UNARYPREC+3)
12997
12998 #define TOK_POST_INC tok_decl(PREC_POST, 0)
12999 #define TOK_POST_DEC tok_decl(PREC_POST, 1)
13000
13001 #define SPEC_PREC (UNARYPREC+4)
13002
13003 #define TOK_NUM tok_decl(SPEC_PREC, 0)
13004 #define TOK_RPAREN tok_decl(SPEC_PREC, 1)
13005
13006 #define NUMPTR (*numstackptr)
13007
13008 static inline int tok_have_assign(operator op)
13009 {
13010         operator prec = PREC(op);
13011
13012         convert_prec_is_assing(prec);
13013         return (prec == PREC(TOK_ASSIGN) ||
13014                         prec == PREC_PRE || prec == PREC_POST);
13015 }
13016
13017 static inline int is_right_associativity(operator prec)
13018 {
13019     return (prec == PREC(TOK_ASSIGN) || prec == PREC(TOK_EXPONENT) ||
13020             prec == PREC(TOK_CONDITIONAL));
13021 }
13022
13023
13024 typedef struct ARITCH_VAR_NUM {
13025         long val;
13026         long contidional_second_val;
13027         char contidional_second_val_initialized;
13028         char *var;      /* if NULL then is regular number,
13029                            else is varable name */
13030 } v_n_t;
13031
13032
13033 typedef struct CHK_VAR_RECURSIVE_LOOPED {
13034         const char *var;
13035         struct CHK_VAR_RECURSIVE_LOOPED *next;
13036 } chk_var_recursive_looped_t;
13037
13038 static chk_var_recursive_looped_t *prev_chk_var_recursive;
13039
13040
13041 static int arith_lookup_val(v_n_t *t)
13042 {
13043     if(t->var) {
13044         const char * p = lookupvar(t->var);
13045
13046         if(p) {
13047             int errcode;
13048
13049             /* recursive try as expression */
13050             chk_var_recursive_looped_t *cur;
13051             chk_var_recursive_looped_t cur_save;
13052
13053             for(cur = prev_chk_var_recursive; cur; cur = cur->next) {
13054                 if(strcmp(cur->var, t->var) == 0) {
13055                     /* expression recursion loop detected */
13056                     return -5;
13057                 }
13058             }
13059             /* save current lookuped var name */
13060             cur = prev_chk_var_recursive;
13061             cur_save.var = t->var;
13062             cur_save.next = cur;
13063             prev_chk_var_recursive = &cur_save;
13064
13065             t->val = arith (p, &errcode);
13066             /* restore previous ptr after recursiving */
13067             prev_chk_var_recursive = cur;
13068             return errcode;
13069         } else {
13070             /* allow undefined var as 0 */
13071             t->val = 0;
13072         }
13073     }
13074     return 0;
13075 }
13076
13077 /* "applying" a token means performing it on the top elements on the integer
13078  * stack. For a unary operator it will only change the top element, but a
13079  * binary operator will pop two arguments and push a result */
13080 static inline int
13081 arith_apply(operator op, v_n_t *numstack, v_n_t **numstackptr)
13082 {
13083         long numptr_val;
13084         v_n_t *numptr_m1;
13085         long rez;
13086         int ret_arith_lookup_val;
13087
13088         if (NUMPTR == numstack) goto err; /* There is no operator that can work
13089                                                                                  without arguments */
13090         numptr_m1 = NUMPTR - 1;
13091
13092         /* check operand is var with noninteger value */
13093         ret_arith_lookup_val = arith_lookup_val(numptr_m1);
13094         if(ret_arith_lookup_val)
13095                 return ret_arith_lookup_val;
13096
13097         rez = numptr_m1->val;
13098         if (op == TOK_UMINUS)
13099                 rez *= -1;
13100         else if (op == TOK_NOT)
13101                 rez = !rez;
13102         else if (op == TOK_BNOT)
13103                 rez = ~rez;
13104         else if (op == TOK_POST_INC || op == TOK_PRE_INC)
13105                 rez++;
13106         else if (op == TOK_POST_DEC || op == TOK_PRE_DEC)
13107                 rez--;
13108         else if (op != TOK_UPLUS) {
13109                 /* Binary operators */
13110
13111             /* check and binary operators need two arguments */
13112             if (numptr_m1 == numstack) goto err;
13113
13114             /* ... and they pop one */
13115             --NUMPTR;
13116             numptr_val = rez;
13117             if (op == TOK_CONDITIONAL) {
13118                 if(! numptr_m1->contidional_second_val_initialized) {
13119                     /* protect $((expr1 ? expr2)) without ": expr" */
13120                     goto err;
13121                 }
13122                 rez = numptr_m1->contidional_second_val;
13123             } else if(numptr_m1->contidional_second_val_initialized) {
13124                     /* protect $((expr1 : expr2)) without "expr ? " */
13125                     goto err;
13126             }
13127             numptr_m1 = NUMPTR - 1;
13128             if(op != TOK_ASSIGN) {
13129                 /* check operand is var with noninteger value for not '=' */
13130                 ret_arith_lookup_val = arith_lookup_val(numptr_m1);
13131                 if(ret_arith_lookup_val)
13132                     return ret_arith_lookup_val;
13133             }
13134             if (op == TOK_CONDITIONAL) {
13135                     numptr_m1->contidional_second_val = rez;
13136             }
13137             rez = numptr_m1->val;
13138             if (op == TOK_BOR || op == TOK_OR_ASSIGN)
13139                         rez |= numptr_val;
13140             else if (op == TOK_OR)
13141                         rez = numptr_val || rez;
13142             else if (op == TOK_BAND || op == TOK_AND_ASSIGN)
13143                         rez &= numptr_val;
13144             else if (op == TOK_BXOR || op == TOK_XOR_ASSIGN)
13145                         rez ^= numptr_val;
13146             else if (op == TOK_AND)
13147                         rez = rez && numptr_val;
13148             else if (op == TOK_EQ)
13149                         rez = (rez == numptr_val);
13150             else if (op == TOK_NE)
13151                         rez = (rez != numptr_val);
13152             else if (op == TOK_GE)
13153                         rez = (rez >= numptr_val);
13154             else if (op == TOK_RSHIFT || op == TOK_RSHIFT_ASSIGN)
13155                         rez >>= numptr_val;
13156             else if (op == TOK_LSHIFT || op == TOK_LSHIFT_ASSIGN)
13157                         rez <<= numptr_val;
13158             else if (op == TOK_GT)
13159                         rez = (rez > numptr_val);
13160             else if (op == TOK_LT)
13161                         rez = (rez < numptr_val);
13162             else if (op == TOK_LE)
13163                         rez = (rez <= numptr_val);
13164             else if (op == TOK_MUL || op == TOK_MUL_ASSIGN)
13165                         rez *= numptr_val;
13166             else if (op == TOK_ADD || op == TOK_PLUS_ASSIGN)
13167                         rez += numptr_val;
13168             else if (op == TOK_SUB || op == TOK_MINUS_ASSIGN)
13169                         rez -= numptr_val;
13170             else if (op == TOK_ASSIGN || op == TOK_COMMA)
13171                         rez = numptr_val;
13172             else if (op == TOK_CONDITIONAL_SEP) {
13173                         if (numptr_m1 == numstack) {
13174                             /* protect $((expr : expr)) without "expr ? " */
13175                             goto err;
13176                         }
13177                         numptr_m1->contidional_second_val_initialized = op;
13178                         numptr_m1->contidional_second_val = numptr_val;
13179             }
13180             else if (op == TOK_CONDITIONAL) {
13181                         rez = rez ?
13182                               numptr_val : numptr_m1->contidional_second_val;
13183             }
13184             else if(op == TOK_EXPONENT) {
13185                         if(numptr_val < 0)
13186                                 return -3;      /* exponent less than 0 */
13187                         else {
13188                                 long c = 1;
13189
13190                                 if(numptr_val)
13191                                         while(numptr_val--)
13192                                                 c *= rez;
13193                                 rez = c;
13194                         }
13195             }
13196             else if(numptr_val==0)          /* zero divisor check */
13197                         return -2;
13198             else if (op == TOK_DIV || op == TOK_DIV_ASSIGN)
13199                         rez /= numptr_val;
13200             else if (op == TOK_REM || op == TOK_REM_ASSIGN)
13201                         rez %= numptr_val;
13202         }
13203         if(tok_have_assign(op)) {
13204                 char buf[32];
13205
13206                 if(numptr_m1->var == NULL) {
13207                         /* Hmm, 1=2 ? */
13208                         goto err;
13209                 }
13210                 /* save to shell variable */
13211                 sprintf(buf, "%ld", rez);
13212                 setvar(numptr_m1->var, buf, 0);
13213                 /* after saving, make previous value for v++ or v-- */
13214                 if(op == TOK_POST_INC)
13215                         rez--;
13216                 else if(op == TOK_POST_DEC)
13217                         rez++;
13218         }
13219         numptr_m1->val = rez;
13220         /* protect geting var value, is number now */
13221         numptr_m1->var = NULL;
13222         return 0;
13223 err: return(-1);
13224 }
13225
13226 /* longest must first */
13227 static const char op_tokens[] = {
13228         '<','<','=',0, TOK_LSHIFT_ASSIGN,
13229         '>','>','=',0, TOK_RSHIFT_ASSIGN,
13230         '<','<',    0, TOK_LSHIFT,
13231         '>','>',    0, TOK_RSHIFT,
13232         '|','|',    0, TOK_OR,
13233         '&','&',    0, TOK_AND,
13234         '!','=',    0, TOK_NE,
13235         '<','=',    0, TOK_LE,
13236         '>','=',    0, TOK_GE,
13237         '=','=',    0, TOK_EQ,
13238         '|','=',    0, TOK_OR_ASSIGN,
13239         '&','=',    0, TOK_AND_ASSIGN,
13240         '*','=',    0, TOK_MUL_ASSIGN,
13241         '/','=',    0, TOK_DIV_ASSIGN,
13242         '%','=',    0, TOK_REM_ASSIGN,
13243         '+','=',    0, TOK_PLUS_ASSIGN,
13244         '-','=',    0, TOK_MINUS_ASSIGN,
13245         '-','-',    0, TOK_POST_DEC,
13246         '^','=',    0, TOK_XOR_ASSIGN,
13247         '+','+',    0, TOK_POST_INC,
13248         '*','*',    0, TOK_EXPONENT,
13249         '!',        0, TOK_NOT,
13250         '<',        0, TOK_LT,
13251         '>',        0, TOK_GT,
13252         '=',        0, TOK_ASSIGN,
13253         '|',        0, TOK_BOR,
13254         '&',        0, TOK_BAND,
13255         '*',        0, TOK_MUL,
13256         '/',        0, TOK_DIV,
13257         '%',        0, TOK_REM,
13258         '+',        0, TOK_ADD,
13259         '-',        0, TOK_SUB,
13260         '^',        0, TOK_BXOR,
13261         /* uniq */
13262         '~',        0, TOK_BNOT,
13263         ',',        0, TOK_COMMA,
13264         '?',        0, TOK_CONDITIONAL,
13265         ':',        0, TOK_CONDITIONAL_SEP,
13266         ')',        0, TOK_RPAREN,
13267         '(',        0, TOK_LPAREN,
13268         0
13269 };
13270 /* ptr to ")" */
13271 #define endexpression &op_tokens[sizeof(op_tokens)-7]
13272
13273
13274 extern long arith (const char *expr, int *perrcode)
13275 {
13276     register char arithval; /* Current character under analysis */
13277     operator lasttok, op;
13278     operator prec;
13279
13280     const char *p = endexpression;
13281     int errcode;
13282
13283     size_t datasizes = strlen(expr) + 2;
13284
13285     /* Stack of integers */
13286     /* The proof that there can be no more than strlen(startbuf)/2+1 integers
13287      * in any given correct or incorrect expression is left as an excersize to
13288      * the reader. */
13289     v_n_t *numstack = alloca(((datasizes)/2)*sizeof(v_n_t)),
13290             *numstackptr = numstack;
13291     /* Stack of operator tokens */
13292     operator *stack = alloca((datasizes) * sizeof(operator)),
13293             *stackptr = stack;
13294
13295     *stackptr++ = lasttok = TOK_LPAREN;     /* start off with a left paren */
13296     *perrcode = errcode = 0;
13297
13298     while(1) {
13299         if ((arithval = *expr) == 0) {
13300                 if (p == endexpression) {
13301                         /* Null expression. */
13302                         return 0;
13303                 }
13304
13305                 /* This is only reached after all tokens have been extracted from the
13306                  * input stream. If there are still tokens on the operator stack, they
13307                  * are to be applied in order. At the end, there should be a final
13308                  * result on the integer stack */
13309
13310                 if (expr != endexpression + 1) {
13311                         /* If we haven't done so already, */
13312                         /* append a closing right paren */
13313                         expr = endexpression;
13314                         /* and let the loop process it. */
13315                         continue;
13316                 }
13317                 /* At this point, we're done with the expression. */
13318                 if (numstackptr != numstack+1) {
13319                         /* ... but if there isn't, it's bad */
13320                   err:
13321                         return (*perrcode = -1);
13322                 }
13323                 if(numstack->var) {
13324                     /* expression is $((var)) only, lookup now */
13325                     errcode = arith_lookup_val(numstack);
13326                 }
13327         ret:
13328                 *perrcode = errcode;
13329                 return numstack->val;
13330         } else {
13331                 /* Continue processing the expression. */
13332                 if (arith_isspace(arithval)) {
13333                         /* Skip whitespace */
13334                         goto prologue;
13335                 }
13336                 if((p = endofname(expr)) != expr) {
13337                         int var_name_size = (p-expr) + 1;  /* trailing zero */
13338
13339                         numstackptr->var = alloca(var_name_size);
13340                         safe_strncpy(numstackptr->var, expr, var_name_size);
13341                         expr = p;
13342                 num:
13343                         numstackptr->contidional_second_val_initialized = 0;
13344                         numstackptr++;
13345                         lasttok = TOK_NUM;
13346                         continue;
13347                 } else if (is_digit(arithval)) {
13348                         numstackptr->var = NULL;
13349                         numstackptr->val = strtol(expr, (char **) &expr, 0);
13350                         goto num;
13351                 }
13352                 for(p = op_tokens; ; p++) {
13353                         const char *o;
13354
13355                         if(*p == 0) {
13356                                 /* strange operator not found */
13357                                 goto err;
13358                         }
13359                         for(o = expr; *p && *o == *p; p++)
13360                                 o++;
13361                         if(! *p) {
13362                                 /* found */
13363                                 expr = o - 1;
13364                                 break;
13365                         }
13366                         /* skip tail uncompared token */
13367                         while(*p)
13368                                 p++;
13369                         /* skip zero delim */
13370                         p++;
13371                 }
13372                 op = p[1];
13373
13374                 /* post grammar: a++ reduce to num */
13375                 if(lasttok == TOK_POST_INC || lasttok == TOK_POST_DEC)
13376                     lasttok = TOK_NUM;
13377
13378                 /* Plus and minus are binary (not unary) _only_ if the last
13379                  * token was as number, or a right paren (which pretends to be
13380                  * a number, since it evaluates to one). Think about it.
13381                  * It makes sense. */
13382                 if (lasttok != TOK_NUM) {
13383                         switch(op) {
13384                                 case TOK_ADD:
13385                                     op = TOK_UPLUS;
13386                                     break;
13387                                 case TOK_SUB:
13388                                     op = TOK_UMINUS;
13389                                     break;
13390                                 case TOK_POST_INC:
13391                                     op = TOK_PRE_INC;
13392                                     break;
13393                                 case TOK_POST_DEC:
13394                                     op = TOK_PRE_DEC;
13395                                     break;
13396                         }
13397                 }
13398                 /* We don't want a unary operator to cause recursive descent on the
13399                  * stack, because there can be many in a row and it could cause an
13400                  * operator to be evaluated before its argument is pushed onto the
13401                  * integer stack. */
13402                 /* But for binary operators, "apply" everything on the operator
13403                  * stack until we find an operator with a lesser priority than the
13404                  * one we have just extracted. */
13405                 /* Left paren is given the lowest priority so it will never be
13406                  * "applied" in this way.
13407                  * if associativity is right and priority eq, applied also skip
13408                  */
13409                 prec = PREC(op);
13410                 if ((prec > 0 && prec < UNARYPREC) || prec == SPEC_PREC) {
13411                         /* not left paren or unary */
13412                         if (lasttok != TOK_NUM) {
13413                                 /* binary op must be preceded by a num */
13414                                 goto err;
13415                         }
13416                         while (stackptr != stack) {
13417                             if (op == TOK_RPAREN) {
13418                                 /* The algorithm employed here is simple: while we don't
13419                                  * hit an open paren nor the bottom of the stack, pop
13420                                  * tokens and apply them */
13421                                 if (stackptr[-1] == TOK_LPAREN) {
13422                                     --stackptr;
13423                                     /* Any operator directly after a */
13424                                     lasttok = TOK_NUM;
13425                                     /* close paren should consider itself binary */
13426                                     goto prologue;
13427                                 }
13428                             } else {
13429                                 operator prev_prec = PREC(stackptr[-1]);
13430
13431                                 convert_prec_is_assing(prec);
13432                                 convert_prec_is_assing(prev_prec);
13433                                 if (prev_prec < prec)
13434                                         break;
13435                                 /* check right assoc */
13436                                 if(prev_prec == prec && is_right_associativity(prec))
13437                                         break;
13438                             }
13439                             errcode = arith_apply(*--stackptr, numstack, &numstackptr);
13440                             if(errcode) goto ret;
13441                         }
13442                         if (op == TOK_RPAREN) {
13443                                 goto err;
13444                         }
13445                 }
13446
13447                 /* Push this operator to the stack and remember it. */
13448                 *stackptr++ = lasttok = op;
13449
13450           prologue:
13451                 ++expr;
13452         }
13453     }
13454 }
13455 #endif /* CONFIG_ASH_MATH_SUPPORT */
13456
13457
13458 #ifdef DEBUG
13459 const char *bb_applet_name = "debug stuff usage";
13460 int main(int argc, char **argv)
13461 {
13462         return ash_main(argc, argv);
13463 }
13464 #endif
13465
13466 /*-
13467  * Copyright (c) 1989, 1991, 1993, 1994
13468  *      The Regents of the University of California.  All rights reserved.
13469  *
13470  * This code is derived from software contributed to Berkeley by
13471  * Kenneth Almquist.
13472  *
13473  * Redistribution and use in source and binary forms, with or without
13474  * modification, are permitted provided that the following conditions
13475  * are met:
13476  * 1. Redistributions of source code must retain the above copyright
13477  *    notice, this list of conditions and the following disclaimer.
13478  * 2. Redistributions in binary form must reproduce the above copyright
13479  *    notice, this list of conditions and the following disclaimer in the
13480  *    documentation and/or other materials provided with the distribution.
13481  *
13482  * 3. <BSD Advertising Clause omitted per the July 22, 1999 licensing change
13483  *              ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change>
13484  *
13485  * 4. Neither the name of the University nor the names of its contributors
13486  *    may be used to endorse or promote products derived from this software
13487  *    without specific prior written permission.
13488  *
13489  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
13490  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
13491  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
13492  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
13493  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
13494  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
13495  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13496  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
13497  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
13498  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
13499  * SUCH DAMAGE.
13500  */