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