1 /* vi: set sw=4 ts=4: */
3 * ash shell port for busybox
5 * Copyright (c) 1989, 1991, 1993, 1994
6 * The Regents of the University of California. All rights reserved.
8 * This code is derived from software contributed to Berkeley by
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 * This version of ash is adapted from the source in Debian's ash 0.3.8-5
28 * Modified by Erik Andersen <andersee@debian.org> and
29 * Vladimir Oleynik <dzo@simtreas.ru> to be used in busybox
32 * Original copyright notice is retained at the end of this file.
36 /* Enable this to compile in extra debugging noise. When debugging is
37 * on, debugging info will be written to $HOME/trace and a quit signal
38 * will generate a core dump. */
41 /* These are here to work with glibc -- Don't change these... */
63 #include <sys/cdefs.h>
64 #include <sys/ioctl.h>
65 #include <sys/param.h>
66 #include <sys/resource.h>
68 #include <sys/times.h>
69 #include <sys/types.h>
75 #if !defined(FNMATCH_BROKEN)
78 #if !defined(GLOB_BROKEN)
82 #ifdef CONFIG_ASH_JOB_CONTROL
88 #if defined(__uClinux__)
89 #error "Do not even bother, ash will not run on uClinux"
93 * This file was generated by the mksyntax program.
97 #define CWORD 0 /* character is nothing special */
98 #define CNL 1 /* newline character */
99 #define CBACK 2 /* a backslash character */
100 #define CSQUOTE 3 /* single quote */
101 #define CDQUOTE 4 /* double quote */
102 #define CENDQUOTE 5 /* a terminating quote */
103 #define CBQUOTE 6 /* backwards single quote */
104 #define CVAR 7 /* a dollar sign */
105 #define CENDVAR 8 /* a '}' character */
106 #define CLP 9 /* a left paren in arithmetic */
107 #define CRP 10 /* a right paren in arithmetic */
108 #define CENDFILE 11 /* end of file */
109 #define CCTL 12 /* like CWORD, except it must be escaped */
110 #define CSPCL 13 /* these terminate a word */
111 #define CIGN 14 /* character should be ignored */
131 #define TENDBQUOTE 13
151 /* control characters in argument strings */
152 #define CTLESC '\201'
153 #define CTLVAR '\202'
154 #define CTLENDVAR '\203'
155 #define CTLBACKQ '\204'
156 #define CTLQUOTE 01 /* ored with CTLBACKQ code if in quotes */
157 /* CTLBACKQ | CTLQUOTE == '\205' */
158 #define CTLARI '\206'
159 #define CTLENDARI '\207'
160 #define CTLQUOTEMARK '\210'
163 #define is_digit(c) ((c)>='0' && (c)<='9')
164 #define is_name(c) (((c) < CTLESC || (c) > CTLENDARI) && ((c) == '_' || isalpha((unsigned char) (c))))
165 #define is_in_name(c) (((c) < CTLESC || (c) > CTLENDARI) && ((c) == '_' || isalnum((unsigned char) (c))))
168 * is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
169 * (assuming ascii char codes, as the original implementation did)
171 #define is_special(c) \
172 ( (((unsigned int)c) - 33 < 32) \
173 && ((0xc1ff920dUL >> (((unsigned int)c) - 33)) & 1))
175 #define digit_val(c) ((c) - '0')
178 #define S_DFL 1 /* default signal handling (SIG_DFL) */
179 #define S_CATCH 2 /* signal is caught */
180 #define S_IGN 3 /* signal is ignored (SIG_IGN) */
181 #define S_HARD_IGN 4 /* signal is ignored permenantly */
182 #define S_RESET 5 /* temporary - to reset a hard ignored sig */
185 /* variable substitution byte (follows CTLVAR) */
186 #define VSTYPE 0x0f /* type of variable substitution */
187 #define VSNUL 0x10 /* colon--treat the empty string as unset */
188 #define VSQUOTE 0x80 /* inside double quotes--suppress splitting */
190 /* values of VSTYPE field */
191 #define VSNORMAL 0x1 /* normal variable: $var or ${var} */
192 #define VSMINUS 0x2 /* ${var-text} */
193 #define VSPLUS 0x3 /* ${var+text} */
194 #define VSQUESTION 0x4 /* ${var?message} */
195 #define VSASSIGN 0x5 /* ${var=text} */
196 #define VSTRIMLEFT 0x6 /* ${var#pattern} */
197 #define VSTRIMLEFTMAX 0x7 /* ${var##pattern} */
198 #define VSTRIMRIGHT 0x8 /* ${var%pattern} */
199 #define VSTRIMRIGHTMAX 0x9 /* ${var%%pattern} */
200 #define VSLENGTH 0xa /* ${#var} */
202 /* flags passed to redirect */
203 #define REDIR_PUSH 01 /* save previous values of file descriptors */
204 #define REDIR_BACKQ 02 /* save the command output to pipe */
207 * BSD setjmp saves the signal mask, which violates ANSI C and takes time,
208 * so we use _setjmp instead.
212 #define setjmp(jmploc) _setjmp(jmploc)
213 #define longjmp(jmploc, val) _longjmp(jmploc, val)
217 * Most machines require the value returned from malloc to be aligned
218 * in some way. The following macro will get this right on many machines.
227 #define ALIGN(nbytes) (((nbytes) + sizeof(union align) - 1) & ~(sizeof(union align) - 1))
230 #ifdef CONFIG_LOCALE_SUPPORT
232 static void change_lc_all(const char *value);
233 static void change_lc_ctype(const char *value);
237 * These macros allow the user to suspend the handling of interrupt signals
238 * over a period of time. This is similar to SIGHOLD to or sigblock, but
239 * much more efficient and portable. (But hacking the kernel is so much
240 * more fun than worrying about efficiency and portability. :-))
243 static void onint(void);
244 static volatile int suppressint;
245 static volatile int intpending;
247 #define INTOFF suppressint++
248 #ifndef CONFIG_ASH_OPTIMIZE_FOR_SIZE
249 #define INTON { if (--suppressint == 0 && intpending) onint(); }
250 #define FORCEINTON {suppressint = 0; if (intpending) onint();}
252 static void __inton(void);
253 static void forceinton(void);
255 #define INTON __inton()
256 #define FORCEINTON forceinton()
259 #define CLEAR_PENDING_INT intpending = 0
260 #define int_pending() intpending
263 typedef void *pointer;
266 #define NULL (void *)0
269 static pointer stalloc(int);
270 static void stunalloc(pointer);
271 static void ungrabstackstr(char *, char *);
272 static char *growstackstr(void);
273 static char *makestrspace(size_t newlen);
276 * Parse trees for commands are allocated in lifo order, so we use a stack
277 * to make this more efficient, and also to avoid all sorts of exception
278 * handling code to handle interrupts in the middle of a parse.
280 * The size 504 was chosen because the Ultrix malloc handles that size
284 #define MINSIZE 504 /* minimum size of a block */
288 struct stack_block *prev;
292 static struct stack_block stackbase;
293 static struct stack_block *stackp = &stackbase;
294 static struct stackmark *markp;
295 static char *stacknxt = stackbase.space;
296 static int stacknleft = MINSIZE;
299 #define equal(s1, s2) (strcmp(s1, s2) == 0)
301 #define stackblock() stacknxt
302 #define stackblocksize() stacknleft
303 #define STARTSTACKSTR(p) p = stackblock(), sstrnleft = stackblocksize()
305 #define STPUTC(c, p) (--sstrnleft >= 0? (*p++ = (c)) : (p = growstackstr(), *p++ = (c)))
306 #define CHECKSTRSPACE(n, p) { if (sstrnleft < n) p = makestrspace(n); }
307 #define STACKSTRNUL(p) (sstrnleft == 0? (p = growstackstr(), *p = '\0') : (*p = '\0'))
310 #define USTPUTC(c, p) (--sstrnleft, *p++ = (c))
311 #define STUNPUTC(p) (++sstrnleft, --p)
312 #define STTOPC(p) p[-1]
313 #define STADJUST(amount, p) (p += (amount), sstrnleft -= (amount))
314 #define grabstackstr(p) stalloc(stackblocksize() - sstrnleft)
318 #define TRACE(param) trace param
319 typedef union node unode;
320 static void trace(const char *, ...);
321 static void trargs(char **);
322 static void showtree(unode *);
323 static void trputc(int);
324 static void trputs(const char *);
325 static void opentrace(void);
360 #define EXP_FULL 0x1 /* perform word splitting & file globbing */
361 #define EXP_TILDE 0x2 /* do normal tilde expansion */
362 #define EXP_VARTILDE 0x4 /* expand tildes in an assignment */
363 #define EXP_REDIR 0x8 /* file glob for a redirection (1 match only) */
364 #define EXP_CASE 0x10 /* keeps quotes around for CASE pattern */
365 #define EXP_RECORD 0x20 /* need to record arguments for ifs breakup */
370 static char optet_vals[NOPTS];
372 static const char *const optlist[NOPTS] = {
391 #define optent_name(optent) (optent+1)
392 #define optent_letter(optent) optent[0]
393 #define optent_val(optent) optet_vals[optent]
395 #define eflag optent_val(0)
396 #define fflag optent_val(1)
397 #define Iflag optent_val(2)
398 #define iflag optent_val(3)
399 #define mflag optent_val(4)
400 #define nflag optent_val(5)
401 #define sflag optent_val(6)
402 #define xflag optent_val(7)
403 #define vflag optent_val(8)
404 #define Vflag optent_val(9)
405 #define Eflag optent_val(10)
406 #define Cflag optent_val(11)
407 #define aflag optent_val(12)
408 #define bflag optent_val(13)
409 #define uflag optent_val(14)
410 #define qflag optent_val(15)
413 /* Mode argument to forkshell. Don't change FORK_FG or FORK_BG. */
431 union node *redirect;
438 struct nodelist *cmdlist;
445 union node *redirect;
453 union node *elsepart;
484 struct nodelist *backquote;
522 struct nbinary nbinary;
525 struct nredir nredir;
529 struct nclist nclist;
539 struct nodelist *next;
543 struct backcmd { /* result of evalbackcmd */
544 int fd; /* file descriptor to read from */
545 char *buf; /* buffer */
546 int nleft; /* number of chars in buffer */
547 struct job *jp; /* job structure for command */
555 const struct builtincmd *cmd;
560 struct strlist *next;
566 struct strlist *list;
567 struct strlist **lastp;
571 struct strpush *prev; /* preceding string on stack */
574 #ifdef CONFIG_ASH_ALIAS
575 struct alias *ap; /* if push was associated with an alias */
577 char *string; /* remember the string since it may change */
581 struct parsefile *prev; /* preceding file on stack */
582 int linno; /* current line */
583 int fd; /* file descriptor (or -1 if string) */
584 int nleft; /* number of chars left in this line */
585 int lleft; /* number of chars left in this buffer */
586 char *nextc; /* next char in buffer */
587 char *buf; /* input buffer */
588 struct strpush *strpush; /* for pushing strings at this level */
589 struct strpush basestrpush; /* so pushing one is fast */
593 struct stack_block *stackp;
596 struct stackmark *marknext;
600 int nparam; /* # of positional parameters (without $0) */
601 unsigned char malloc; /* if parameter list dynamically allocated */
602 char **p; /* parameter list */
603 int optind; /* next parameter to be processed by getopts */
604 int optoff; /* used by getopts */
608 * When commands are first encountered, they are entered in a hash table.
609 * This ensures that a full path search will not have to be done for them
610 * on each invocation.
612 * We should investigate converting to a linear search, even though that
613 * would make the command name "hash" a misnomer.
615 #define CMDTABLESIZE 31 /* should be prime */
616 #define ARB 1 /* actual size determined at run time */
621 struct tblentry *next; /* next entry in hash chain */
622 union param param; /* definition of builtin function */
623 short cmdtype; /* index identifying command */
624 char rehash; /* if set, cd done since entry created */
625 char cmdname[ARB]; /* name of command */
629 static struct tblentry *cmdtable[CMDTABLESIZE];
630 static int builtinloc = -1; /* index in path of %builtin, or -1 */
631 static int exerrno = 0; /* Last exec error */
634 static void tryexec(char *, char **, char **);
635 static void printentry(struct tblentry *, int);
636 static void clearcmdentry(int);
637 static struct tblentry *cmdlookup(const char *, int);
638 static void delete_cmd_entry(void);
639 static int path_change(const char *, int *);
642 static void flushall(void);
643 static void out2fmt(const char *, ...)
644 __attribute__ ((__format__(__printf__, 1, 2)));
645 static int xwrite(int, const char *, int);
647 static inline void outstr(const char *p, FILE * file)
651 static void out1str(const char *p)
655 static void out2str(const char *p)
660 #ifndef CONFIG_ASH_OPTIMIZE_FOR_SIZE
661 #define out2c(c) putc((c), stderr)
663 static void out2c(int c)
670 #ifdef CONFIG_ASH_OPTIMIZE_FOR_SIZE
671 #define USE_SIT_FUNCTION
674 /* number syntax index */
675 #define BASESYNTAX 0 /* not in quotes */
676 #define DQSYNTAX 1 /* in double quotes */
677 #define SQSYNTAX 2 /* in single quotes */
678 #define ARISYNTAX 3 /* in arithmetic */
680 static const char S_I_T[][4] = {
681 {CSPCL, CIGN, CIGN, CIGN}, /* 0, PEOA */
682 {CSPCL, CWORD, CWORD, CWORD}, /* 1, ' ' */
683 {CNL, CNL, CNL, CNL}, /* 2, \n */
684 {CWORD, CCTL, CCTL, CWORD}, /* 3, !*-/:=?[]~ */
685 {CDQUOTE, CENDQUOTE, CWORD, CDQUOTE}, /* 4, '"' */
686 {CVAR, CVAR, CWORD, CVAR}, /* 5, $ */
687 {CSQUOTE, CWORD, CENDQUOTE, CSQUOTE}, /* 6, "'" */
688 {CSPCL, CWORD, CWORD, CLP}, /* 7, ( */
689 {CSPCL, CWORD, CWORD, CRP}, /* 8, ) */
690 {CBACK, CBACK, CCTL, CBACK}, /* 9, \ */
691 {CBQUOTE, CBQUOTE, CWORD, CBQUOTE}, /* 10, ` */
692 {CENDVAR, CENDVAR, CWORD, CENDVAR}, /* 11, } */
693 #ifndef USE_SIT_FUNCTION
694 {CENDFILE, CENDFILE, CENDFILE, CENDFILE}, /* 12, PEOF */
695 {CWORD, CWORD, CWORD, CWORD}, /* 13, 0-9A-Za-z */
696 {CCTL, CCTL, CCTL, CCTL} /* 14, CTLESC ... */
700 #ifdef USE_SIT_FUNCTION
702 #define U_C(c) ((unsigned char)(c))
704 static int SIT(int c, int syntax)
706 static const char spec_symbls[] = "\t\n !\"$&'()*-/:;<=>?[\\]`|}~";
707 static const char syntax_index_table[] = {
708 1, 2, 1, 3, 4, 5, 1, 6, /* "\t\n !\"$&'" */
709 7, 8, 3, 3, 3, 3, 1, 1, /* "()*-/:;<" */
710 3, 1, 3, 3, 9, 3, 10, 1, /* "=>?[\\]`|" */
716 if (c == PEOF) /* 2^8+2 */
718 if (c == PEOA) /* 2^8+1 */
720 else if (U_C(c) >= U_C(CTLESC) && U_C(c) <= U_C(CTLQUOTEMARK))
723 s = strchr(spec_symbls, c);
726 indx = syntax_index_table[(s - spec_symbls)];
728 return S_I_T[indx][syntax];
731 #else /* USE_SIT_FUNCTION */
733 #define SIT(c, syntax) S_I_T[(int)syntax_index_table[((int)c)+SYNBASE]][syntax]
735 #define CSPCL_CIGN_CIGN_CIGN 0
736 #define CSPCL_CWORD_CWORD_CWORD 1
737 #define CNL_CNL_CNL_CNL 2
738 #define CWORD_CCTL_CCTL_CWORD 3
739 #define CDQUOTE_CENDQUOTE_CWORD_CDQUOTE 4
740 #define CVAR_CVAR_CWORD_CVAR 5
741 #define CSQUOTE_CWORD_CENDQUOTE_CSQUOTE 6
742 #define CSPCL_CWORD_CWORD_CLP 7
743 #define CSPCL_CWORD_CWORD_CRP 8
744 #define CBACK_CBACK_CCTL_CBACK 9
745 #define CBQUOTE_CBQUOTE_CWORD_CBQUOTE 10
746 #define CENDVAR_CENDVAR_CWORD_CENDVAR 11
747 #define CENDFILE_CENDFILE_CENDFILE_CENDFILE 12
748 #define CWORD_CWORD_CWORD_CWORD 13
749 #define CCTL_CCTL_CCTL_CCTL 14
751 static const char syntax_index_table[258] = {
752 /* BASESYNTAX_DQSYNTAX_SQSYNTAX_ARISYNTAX */
753 /* 0 -130 PEOF */ CENDFILE_CENDFILE_CENDFILE_CENDFILE,
754 /* 1 -129 PEOA */ CSPCL_CIGN_CIGN_CIGN,
755 /* 2 -128 0xff */ CWORD_CWORD_CWORD_CWORD,
756 /* 3 -127 */ CCTL_CCTL_CCTL_CCTL,
758 /* 4 -126 */ CCTL_CCTL_CCTL_CCTL,
759 /* 5 -125 */ CCTL_CCTL_CCTL_CCTL,
760 /* 6 -124 */ CCTL_CCTL_CCTL_CCTL,
761 /* 7 -123 */ CCTL_CCTL_CCTL_CCTL,
762 /* 8 -122 */ CCTL_CCTL_CCTL_CCTL,
763 /* 9 -121 */ CCTL_CCTL_CCTL_CCTL,
764 /* 10 -120 */ CCTL_CCTL_CCTL_CCTL,
766 /* 11 -119 */ CWORD_CWORD_CWORD_CWORD,
767 /* 12 -118 */ CWORD_CWORD_CWORD_CWORD,
768 /* 13 -117 */ CWORD_CWORD_CWORD_CWORD,
769 /* 14 -116 */ CWORD_CWORD_CWORD_CWORD,
770 /* 15 -115 */ CWORD_CWORD_CWORD_CWORD,
771 /* 16 -114 */ CWORD_CWORD_CWORD_CWORD,
772 /* 17 -113 */ CWORD_CWORD_CWORD_CWORD,
773 /* 18 -112 */ CWORD_CWORD_CWORD_CWORD,
774 /* 19 -111 */ CWORD_CWORD_CWORD_CWORD,
775 /* 20 -110 */ CWORD_CWORD_CWORD_CWORD,
776 /* 21 -109 */ CWORD_CWORD_CWORD_CWORD,
777 /* 22 -108 */ CWORD_CWORD_CWORD_CWORD,
778 /* 23 -107 */ CWORD_CWORD_CWORD_CWORD,
779 /* 24 -106 */ CWORD_CWORD_CWORD_CWORD,
780 /* 25 -105 */ CWORD_CWORD_CWORD_CWORD,
781 /* 26 -104 */ CWORD_CWORD_CWORD_CWORD,
782 /* 27 -103 */ CWORD_CWORD_CWORD_CWORD,
783 /* 28 -102 */ CWORD_CWORD_CWORD_CWORD,
784 /* 29 -101 */ CWORD_CWORD_CWORD_CWORD,
785 /* 30 -100 */ CWORD_CWORD_CWORD_CWORD,
786 /* 31 -99 */ CWORD_CWORD_CWORD_CWORD,
787 /* 32 -98 */ CWORD_CWORD_CWORD_CWORD,
788 /* 33 -97 */ CWORD_CWORD_CWORD_CWORD,
789 /* 34 -96 */ CWORD_CWORD_CWORD_CWORD,
790 /* 35 -95 */ CWORD_CWORD_CWORD_CWORD,
791 /* 36 -94 */ CWORD_CWORD_CWORD_CWORD,
792 /* 37 -93 */ CWORD_CWORD_CWORD_CWORD,
793 /* 38 -92 */ CWORD_CWORD_CWORD_CWORD,
794 /* 39 -91 */ CWORD_CWORD_CWORD_CWORD,
795 /* 40 -90 */ CWORD_CWORD_CWORD_CWORD,
796 /* 41 -89 */ CWORD_CWORD_CWORD_CWORD,
797 /* 42 -88 */ CWORD_CWORD_CWORD_CWORD,
798 /* 43 -87 */ CWORD_CWORD_CWORD_CWORD,
799 /* 44 -86 */ CWORD_CWORD_CWORD_CWORD,
800 /* 45 -85 */ CWORD_CWORD_CWORD_CWORD,
801 /* 46 -84 */ CWORD_CWORD_CWORD_CWORD,
802 /* 47 -83 */ CWORD_CWORD_CWORD_CWORD,
803 /* 48 -82 */ CWORD_CWORD_CWORD_CWORD,
804 /* 49 -81 */ CWORD_CWORD_CWORD_CWORD,
805 /* 50 -80 */ CWORD_CWORD_CWORD_CWORD,
806 /* 51 -79 */ CWORD_CWORD_CWORD_CWORD,
807 /* 52 -78 */ CWORD_CWORD_CWORD_CWORD,
808 /* 53 -77 */ CWORD_CWORD_CWORD_CWORD,
809 /* 54 -76 */ CWORD_CWORD_CWORD_CWORD,
810 /* 55 -75 */ CWORD_CWORD_CWORD_CWORD,
811 /* 56 -74 */ CWORD_CWORD_CWORD_CWORD,
812 /* 57 -73 */ CWORD_CWORD_CWORD_CWORD,
813 /* 58 -72 */ CWORD_CWORD_CWORD_CWORD,
814 /* 59 -71 */ CWORD_CWORD_CWORD_CWORD,
815 /* 60 -70 */ CWORD_CWORD_CWORD_CWORD,
816 /* 61 -69 */ CWORD_CWORD_CWORD_CWORD,
817 /* 62 -68 */ CWORD_CWORD_CWORD_CWORD,
818 /* 63 -67 */ CWORD_CWORD_CWORD_CWORD,
819 /* 64 -66 */ CWORD_CWORD_CWORD_CWORD,
820 /* 65 -65 */ CWORD_CWORD_CWORD_CWORD,
821 /* 66 -64 */ CWORD_CWORD_CWORD_CWORD,
822 /* 67 -63 */ CWORD_CWORD_CWORD_CWORD,
823 /* 68 -62 */ CWORD_CWORD_CWORD_CWORD,
824 /* 69 -61 */ CWORD_CWORD_CWORD_CWORD,
825 /* 70 -60 */ CWORD_CWORD_CWORD_CWORD,
826 /* 71 -59 */ CWORD_CWORD_CWORD_CWORD,
827 /* 72 -58 */ CWORD_CWORD_CWORD_CWORD,
828 /* 73 -57 */ CWORD_CWORD_CWORD_CWORD,
829 /* 74 -56 */ CWORD_CWORD_CWORD_CWORD,
830 /* 75 -55 */ CWORD_CWORD_CWORD_CWORD,
831 /* 76 -54 */ CWORD_CWORD_CWORD_CWORD,
832 /* 77 -53 */ CWORD_CWORD_CWORD_CWORD,
833 /* 78 -52 */ CWORD_CWORD_CWORD_CWORD,
834 /* 79 -51 */ CWORD_CWORD_CWORD_CWORD,
835 /* 80 -50 */ CWORD_CWORD_CWORD_CWORD,
836 /* 81 -49 */ CWORD_CWORD_CWORD_CWORD,
837 /* 82 -48 */ CWORD_CWORD_CWORD_CWORD,
838 /* 83 -47 */ CWORD_CWORD_CWORD_CWORD,
839 /* 84 -46 */ CWORD_CWORD_CWORD_CWORD,
840 /* 85 -45 */ CWORD_CWORD_CWORD_CWORD,
841 /* 86 -44 */ CWORD_CWORD_CWORD_CWORD,
842 /* 87 -43 */ CWORD_CWORD_CWORD_CWORD,
843 /* 88 -42 */ CWORD_CWORD_CWORD_CWORD,
844 /* 89 -41 */ CWORD_CWORD_CWORD_CWORD,
845 /* 90 -40 */ CWORD_CWORD_CWORD_CWORD,
846 /* 91 -39 */ CWORD_CWORD_CWORD_CWORD,
847 /* 92 -38 */ CWORD_CWORD_CWORD_CWORD,
848 /* 93 -37 */ CWORD_CWORD_CWORD_CWORD,
849 /* 94 -36 */ CWORD_CWORD_CWORD_CWORD,
850 /* 95 -35 */ CWORD_CWORD_CWORD_CWORD,
851 /* 96 -34 */ CWORD_CWORD_CWORD_CWORD,
852 /* 97 -33 */ CWORD_CWORD_CWORD_CWORD,
853 /* 98 -32 */ CWORD_CWORD_CWORD_CWORD,
854 /* 99 -31 */ CWORD_CWORD_CWORD_CWORD,
855 /* 100 -30 */ CWORD_CWORD_CWORD_CWORD,
856 /* 101 -29 */ CWORD_CWORD_CWORD_CWORD,
857 /* 102 -28 */ CWORD_CWORD_CWORD_CWORD,
858 /* 103 -27 */ CWORD_CWORD_CWORD_CWORD,
859 /* 104 -26 */ CWORD_CWORD_CWORD_CWORD,
860 /* 105 -25 */ CWORD_CWORD_CWORD_CWORD,
861 /* 106 -24 */ CWORD_CWORD_CWORD_CWORD,
862 /* 107 -23 */ CWORD_CWORD_CWORD_CWORD,
863 /* 108 -22 */ CWORD_CWORD_CWORD_CWORD,
864 /* 109 -21 */ CWORD_CWORD_CWORD_CWORD,
865 /* 110 -20 */ CWORD_CWORD_CWORD_CWORD,
866 /* 111 -19 */ CWORD_CWORD_CWORD_CWORD,
867 /* 112 -18 */ CWORD_CWORD_CWORD_CWORD,
868 /* 113 -17 */ CWORD_CWORD_CWORD_CWORD,
869 /* 114 -16 */ CWORD_CWORD_CWORD_CWORD,
870 /* 115 -15 */ CWORD_CWORD_CWORD_CWORD,
871 /* 116 -14 */ CWORD_CWORD_CWORD_CWORD,
872 /* 117 -13 */ CWORD_CWORD_CWORD_CWORD,
873 /* 118 -12 */ CWORD_CWORD_CWORD_CWORD,
874 /* 119 -11 */ CWORD_CWORD_CWORD_CWORD,
875 /* 120 -10 */ CWORD_CWORD_CWORD_CWORD,
876 /* 121 -9 */ CWORD_CWORD_CWORD_CWORD,
877 /* 122 -8 */ CWORD_CWORD_CWORD_CWORD,
878 /* 123 -7 */ CWORD_CWORD_CWORD_CWORD,
879 /* 124 -6 */ CWORD_CWORD_CWORD_CWORD,
880 /* 125 -5 */ CWORD_CWORD_CWORD_CWORD,
881 /* 126 -4 */ CWORD_CWORD_CWORD_CWORD,
882 /* 127 -3 */ CWORD_CWORD_CWORD_CWORD,
883 /* 128 -2 */ CWORD_CWORD_CWORD_CWORD,
884 /* 129 -1 */ CWORD_CWORD_CWORD_CWORD,
885 /* 130 0 */ CWORD_CWORD_CWORD_CWORD,
886 /* 131 1 */ CWORD_CWORD_CWORD_CWORD,
887 /* 132 2 */ CWORD_CWORD_CWORD_CWORD,
888 /* 133 3 */ CWORD_CWORD_CWORD_CWORD,
889 /* 134 4 */ CWORD_CWORD_CWORD_CWORD,
890 /* 135 5 */ CWORD_CWORD_CWORD_CWORD,
891 /* 136 6 */ CWORD_CWORD_CWORD_CWORD,
892 /* 137 7 */ CWORD_CWORD_CWORD_CWORD,
893 /* 138 8 */ CWORD_CWORD_CWORD_CWORD,
894 /* 139 9 "\t" */ CSPCL_CWORD_CWORD_CWORD,
895 /* 140 10 "\n" */ CNL_CNL_CNL_CNL,
896 /* 141 11 */ CWORD_CWORD_CWORD_CWORD,
897 /* 142 12 */ CWORD_CWORD_CWORD_CWORD,
898 /* 143 13 */ CWORD_CWORD_CWORD_CWORD,
899 /* 144 14 */ CWORD_CWORD_CWORD_CWORD,
900 /* 145 15 */ CWORD_CWORD_CWORD_CWORD,
901 /* 146 16 */ CWORD_CWORD_CWORD_CWORD,
902 /* 147 17 */ CWORD_CWORD_CWORD_CWORD,
903 /* 148 18 */ CWORD_CWORD_CWORD_CWORD,
904 /* 149 19 */ CWORD_CWORD_CWORD_CWORD,
905 /* 150 20 */ CWORD_CWORD_CWORD_CWORD,
906 /* 151 21 */ CWORD_CWORD_CWORD_CWORD,
907 /* 152 22 */ CWORD_CWORD_CWORD_CWORD,
908 /* 153 23 */ CWORD_CWORD_CWORD_CWORD,
909 /* 154 24 */ CWORD_CWORD_CWORD_CWORD,
910 /* 155 25 */ CWORD_CWORD_CWORD_CWORD,
911 /* 156 26 */ CWORD_CWORD_CWORD_CWORD,
912 /* 157 27 */ CWORD_CWORD_CWORD_CWORD,
913 /* 158 28 */ CWORD_CWORD_CWORD_CWORD,
914 /* 159 29 */ CWORD_CWORD_CWORD_CWORD,
915 /* 160 30 */ CWORD_CWORD_CWORD_CWORD,
916 /* 161 31 */ CWORD_CWORD_CWORD_CWORD,
917 /* 162 32 " " */ CSPCL_CWORD_CWORD_CWORD,
918 /* 163 33 "!" */ CWORD_CCTL_CCTL_CWORD,
919 /* 164 34 """ */ CDQUOTE_CENDQUOTE_CWORD_CDQUOTE,
920 /* 165 35 "#" */ CWORD_CWORD_CWORD_CWORD,
921 /* 166 36 "$" */ CVAR_CVAR_CWORD_CVAR,
922 /* 167 37 "%" */ CWORD_CWORD_CWORD_CWORD,
923 /* 168 38 "&" */ CSPCL_CWORD_CWORD_CWORD,
924 /* 169 39 "'" */ CSQUOTE_CWORD_CENDQUOTE_CSQUOTE,
925 /* 170 40 "(" */ CSPCL_CWORD_CWORD_CLP,
926 /* 171 41 ")" */ CSPCL_CWORD_CWORD_CRP,
927 /* 172 42 "*" */ CWORD_CCTL_CCTL_CWORD,
928 /* 173 43 "+" */ CWORD_CWORD_CWORD_CWORD,
929 /* 174 44 "," */ CWORD_CWORD_CWORD_CWORD,
930 /* 175 45 "-" */ CWORD_CCTL_CCTL_CWORD,
931 /* 176 46 "." */ CWORD_CWORD_CWORD_CWORD,
932 /* 177 47 "/" */ CWORD_CCTL_CCTL_CWORD,
933 /* 178 48 "0" */ CWORD_CWORD_CWORD_CWORD,
934 /* 179 49 "1" */ CWORD_CWORD_CWORD_CWORD,
935 /* 180 50 "2" */ CWORD_CWORD_CWORD_CWORD,
936 /* 181 51 "3" */ CWORD_CWORD_CWORD_CWORD,
937 /* 182 52 "4" */ CWORD_CWORD_CWORD_CWORD,
938 /* 183 53 "5" */ CWORD_CWORD_CWORD_CWORD,
939 /* 184 54 "6" */ CWORD_CWORD_CWORD_CWORD,
940 /* 185 55 "7" */ CWORD_CWORD_CWORD_CWORD,
941 /* 186 56 "8" */ CWORD_CWORD_CWORD_CWORD,
942 /* 187 57 "9" */ CWORD_CWORD_CWORD_CWORD,
943 /* 188 58 ":" */ CWORD_CCTL_CCTL_CWORD,
944 /* 189 59 ";" */ CSPCL_CWORD_CWORD_CWORD,
945 /* 190 60 "<" */ CSPCL_CWORD_CWORD_CWORD,
946 /* 191 61 "=" */ CWORD_CCTL_CCTL_CWORD,
947 /* 192 62 ">" */ CSPCL_CWORD_CWORD_CWORD,
948 /* 193 63 "?" */ CWORD_CCTL_CCTL_CWORD,
949 /* 194 64 "@" */ CWORD_CWORD_CWORD_CWORD,
950 /* 195 65 "A" */ CWORD_CWORD_CWORD_CWORD,
951 /* 196 66 "B" */ CWORD_CWORD_CWORD_CWORD,
952 /* 197 67 "C" */ CWORD_CWORD_CWORD_CWORD,
953 /* 198 68 "D" */ CWORD_CWORD_CWORD_CWORD,
954 /* 199 69 "E" */ CWORD_CWORD_CWORD_CWORD,
955 /* 200 70 "F" */ CWORD_CWORD_CWORD_CWORD,
956 /* 201 71 "G" */ CWORD_CWORD_CWORD_CWORD,
957 /* 202 72 "H" */ CWORD_CWORD_CWORD_CWORD,
958 /* 203 73 "I" */ CWORD_CWORD_CWORD_CWORD,
959 /* 204 74 "J" */ CWORD_CWORD_CWORD_CWORD,
960 /* 205 75 "K" */ CWORD_CWORD_CWORD_CWORD,
961 /* 206 76 "L" */ CWORD_CWORD_CWORD_CWORD,
962 /* 207 77 "M" */ CWORD_CWORD_CWORD_CWORD,
963 /* 208 78 "N" */ CWORD_CWORD_CWORD_CWORD,
964 /* 209 79 "O" */ CWORD_CWORD_CWORD_CWORD,
965 /* 210 80 "P" */ CWORD_CWORD_CWORD_CWORD,
966 /* 211 81 "Q" */ CWORD_CWORD_CWORD_CWORD,
967 /* 212 82 "R" */ CWORD_CWORD_CWORD_CWORD,
968 /* 213 83 "S" */ CWORD_CWORD_CWORD_CWORD,
969 /* 214 84 "T" */ CWORD_CWORD_CWORD_CWORD,
970 /* 215 85 "U" */ CWORD_CWORD_CWORD_CWORD,
971 /* 216 86 "V" */ CWORD_CWORD_CWORD_CWORD,
972 /* 217 87 "W" */ CWORD_CWORD_CWORD_CWORD,
973 /* 218 88 "X" */ CWORD_CWORD_CWORD_CWORD,
974 /* 219 89 "Y" */ CWORD_CWORD_CWORD_CWORD,
975 /* 220 90 "Z" */ CWORD_CWORD_CWORD_CWORD,
976 /* 221 91 "[" */ CWORD_CCTL_CCTL_CWORD,
977 /* 222 92 "\" */ CBACK_CBACK_CCTL_CBACK,
978 /* 223 93 "]" */ CWORD_CCTL_CCTL_CWORD,
979 /* 224 94 "^" */ CWORD_CWORD_CWORD_CWORD,
980 /* 225 95 "_" */ CWORD_CWORD_CWORD_CWORD,
981 /* 226 96 "`" */ CBQUOTE_CBQUOTE_CWORD_CBQUOTE,
982 /* 227 97 "a" */ CWORD_CWORD_CWORD_CWORD,
983 /* 228 98 "b" */ CWORD_CWORD_CWORD_CWORD,
984 /* 229 99 "c" */ CWORD_CWORD_CWORD_CWORD,
985 /* 230 100 "d" */ CWORD_CWORD_CWORD_CWORD,
986 /* 231 101 "e" */ CWORD_CWORD_CWORD_CWORD,
987 /* 232 102 "f" */ CWORD_CWORD_CWORD_CWORD,
988 /* 233 103 "g" */ CWORD_CWORD_CWORD_CWORD,
989 /* 234 104 "h" */ CWORD_CWORD_CWORD_CWORD,
990 /* 235 105 "i" */ CWORD_CWORD_CWORD_CWORD,
991 /* 236 106 "j" */ CWORD_CWORD_CWORD_CWORD,
992 /* 237 107 "k" */ CWORD_CWORD_CWORD_CWORD,
993 /* 238 108 "l" */ CWORD_CWORD_CWORD_CWORD,
994 /* 239 109 "m" */ CWORD_CWORD_CWORD_CWORD,
995 /* 240 110 "n" */ CWORD_CWORD_CWORD_CWORD,
996 /* 241 111 "o" */ CWORD_CWORD_CWORD_CWORD,
997 /* 242 112 "p" */ CWORD_CWORD_CWORD_CWORD,
998 /* 243 113 "q" */ CWORD_CWORD_CWORD_CWORD,
999 /* 244 114 "r" */ CWORD_CWORD_CWORD_CWORD,
1000 /* 245 115 "s" */ CWORD_CWORD_CWORD_CWORD,
1001 /* 246 116 "t" */ CWORD_CWORD_CWORD_CWORD,
1002 /* 247 117 "u" */ CWORD_CWORD_CWORD_CWORD,
1003 /* 248 118 "v" */ CWORD_CWORD_CWORD_CWORD,
1004 /* 249 119 "w" */ CWORD_CWORD_CWORD_CWORD,
1005 /* 250 120 "x" */ CWORD_CWORD_CWORD_CWORD,
1006 /* 251 121 "y" */ CWORD_CWORD_CWORD_CWORD,
1007 /* 252 122 "z" */ CWORD_CWORD_CWORD_CWORD,
1008 /* 253 123 "{" */ CWORD_CWORD_CWORD_CWORD,
1009 /* 254 124 "|" */ CSPCL_CWORD_CWORD_CWORD,
1010 /* 255 125 "}" */ CENDVAR_CENDVAR_CWORD_CENDVAR,
1011 /* 256 126 "~" */ CWORD_CCTL_CCTL_CWORD,
1012 /* 257 127 */ CWORD_CWORD_CWORD_CWORD,
1015 #endif /* USE_SIT_FUNCTION */
1018 /* first char is indicating which tokens mark the end of a list */
1019 static const char *const tokname_array[] = {
1034 #define KWDOFFSET 14
1035 /* the following are keywords */
1054 static const char *tokname(int tok)
1056 static char buf[16];
1060 sprintf(buf + (tok >= TSEMI), "%s%c",
1061 tokname_array[tok] + 1, (tok >= TSEMI ? '"' : 0));
1065 static int plinno = 1; /* input line number */
1067 static int parselleft; /* copy of parsefile->lleft */
1069 static struct parsefile basepf; /* top level input file */
1070 static char basebuf[BUFSIZ]; /* buffer for top level input file */
1071 static struct parsefile *parsefile = &basepf; /* current input file */
1074 * NEOF is returned by parsecmd when it encounters an end of file. It
1075 * must be distinct from NULL, so we use the address of a variable that
1076 * happens to be handy.
1079 static int tokpushback; /* last token pushed back */
1081 #define NEOF ((union node *)&tokpushback)
1082 static int checkkwd; /* 1 == check for kwds, 2 == also eat newlines */
1085 static void error(const char *, ...) __attribute__ ((__noreturn__));
1086 static void exerror(int, const char *, ...) __attribute__ ((__noreturn__));
1087 static void shellexec(char **, char **, const char *, int)
1088 __attribute__ ((noreturn));
1089 static void exitshell(int) __attribute__ ((noreturn));
1091 static int goodname(const char *);
1092 static void ignoresig(int);
1093 static void onsig(int);
1094 static void dotrap(void);
1095 static int decode_signal(const char *, int);
1097 static void setparam(char **);
1098 static void freeparam(volatile struct shparam *);
1100 /* reasons for skipping commands (see comment on breakcmd routine) */
1106 /* values of cmdtype */
1107 #define CMDUNKNOWN -1 /* no entry in table for command */
1108 #define CMDNORMAL 0 /* command is an executable program */
1109 #define CMDBUILTIN 1 /* command is a shell builtin */
1110 #define CMDFUNCTION 2 /* command is a shell function */
1112 #define DO_ERR 1 /* find_command prints errors */
1113 #define DO_ABS 2 /* find_command checks absolute paths */
1114 #define DO_NOFUN 4 /* find_command ignores functions */
1115 #define DO_BRUTE 8 /* find_command ignores hash table */
1122 #define VEXPORT 0x01 /* variable is exported */
1123 #define VREADONLY 0x02 /* variable cannot be modified */
1124 #define VSTRFIXED 0x04 /* variable struct is staticly allocated */
1125 #define VTEXTFIXED 0x08 /* text is staticly allocated */
1126 #define VSTACK 0x10 /* text is allocated on the stack */
1127 #define VUNSET 0x20 /* the variable is not set */
1128 #define VNOFUNC 0x40 /* don't call the callback function */
1132 struct var *next; /* next entry in hash list */
1133 int flags; /* flags are defined above */
1134 char *text; /* name=value */
1135 void (*func) (const char *);
1136 /* function to be called when */
1137 /* the variable gets set/unset */
1141 struct localvar *next; /* next local variable in list */
1142 struct var *vp; /* the variable that was made local */
1143 int flags; /* saved flags */
1144 char *text; /* saved text */
1148 #if defined(__GLIBC__) && __GLIBC__ >= 2 && !defined(FNMATCH_BROKEN)
1149 #define rmescapes(p) _rmescapes((p), 0)
1150 static char *_rmescapes(char *, int);
1152 static void rmescapes(char *);
1155 static int casematch(union node *, const char *);
1156 static void clearredir(void);
1157 static void popstring(void);
1158 static void readcmdfile(const char *);
1160 static int number(const char *);
1161 static int is_number(const char *, int *num);
1162 static char *single_quote(const char *);
1163 static int nextopt(const char *);
1165 static void redirect(union node *, int);
1166 static void popredir(void);
1167 static int dup_as_newfd(int, int);
1169 static void changepath(const char *newval);
1170 static void getoptsreset(const char *value);
1173 static int parsenleft; /* copy of parsefile->nleft */
1174 static char *parsenextc; /* copy of parsefile->nextc */
1175 static int rootpid; /* pid of main shell */
1176 static int rootshell; /* true if we aren't a child of the main shell */
1178 static const char spcstr[] = " ";
1179 static const char snlfmt[] = "%s\n";
1181 static int sstrnleft;
1182 static int herefd = -1;
1184 static struct localvar *localvars;
1186 static struct var vifs;
1187 static struct var vmail;
1188 static struct var vmpath;
1189 static struct var vpath;
1190 static struct var vps1;
1191 static struct var vps2;
1192 static struct var voptind;
1194 #ifdef CONFIG_LOCALE_SUPPORT
1195 static struct var vlc_all;
1196 static struct var vlc_ctype;
1199 #ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
1200 static struct var vhistfile;
1207 void (*func) (const char *);
1210 static const char defpathvar[] =
1211 "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin";
1212 #define defpath (defpathvar + 5)
1215 static const char defifsvar[] = "IFS= \t\n";
1217 #define defifs (defifsvar + 4)
1219 static const char defifs[] = " \t\n";
1222 static const struct varinit varinit[] = {
1224 {&vifs, VSTRFIXED | VTEXTFIXED, defifsvar,
1226 {&vifs, VSTRFIXED | VTEXTFIXED | VUNSET, "IFS=",
1229 {&vmail, VSTRFIXED | VTEXTFIXED | VUNSET, "MAIL=",
1231 {&vmpath, VSTRFIXED | VTEXTFIXED | VUNSET, "MAILPATH=",
1233 {&vpath, VSTRFIXED | VTEXTFIXED, defpathvar,
1235 #if defined(CONFIG_FEATURE_COMMAND_EDITING) && defined(CONFIG_FEATURE_SH_FANCY_PROMPT)
1236 {&vps1, VSTRFIXED | VTEXTFIXED, "PS1=\\w \\$ ",
1238 #endif /* else vps1 depends on uid */
1239 {&vps2, VSTRFIXED | VTEXTFIXED, "PS2=> ",
1241 {&voptind, VSTRFIXED | VTEXTFIXED, "OPTIND=1",
1243 #ifdef CONFIG_LOCALE_SUPPORT
1244 {&vlc_all, VSTRFIXED | VTEXTFIXED | VUNSET, "LC_ALL=",
1246 {&vlc_ctype, VSTRFIXED | VTEXTFIXED | VUNSET, "LC_CTYPE=",
1249 #ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
1250 {&vhistfile, VSTRFIXED | VTEXTFIXED | VUNSET, "HISTFILE=",
1259 static struct var *vartab[VTABSIZE];
1262 * The following macros access the values of the above variables.
1263 * They have to skip over the name. They return the null string
1264 * for unset variables.
1267 #define ifsval() (vifs.text + 4)
1268 #define ifsset() ((vifs.flags & VUNSET) == 0)
1269 #define mailval() (vmail.text + 5)
1270 #define mpathval() (vmpath.text + 9)
1271 #define pathval() (vpath.text + 5)
1272 #define ps1val() (vps1.text + 4)
1273 #define ps2val() (vps2.text + 4)
1274 #define optindval() (voptind.text + 7)
1276 #define mpathset() ((vmpath.flags & VUNSET) == 0)
1278 static void initvar(void);
1279 static void setvar(const char *, const char *, int);
1280 static void setvareq(char *, int);
1281 static void listsetvar(struct strlist *);
1282 static const char *lookupvar(const char *);
1283 static const char *bltinlookup(const char *);
1284 static char **environment(void);
1285 static int showvarscmd(int, char **);
1286 static void mklocal(char *);
1287 static void poplocalvars(void);
1288 static int unsetvar(const char *);
1289 static int varequal(const char *, const char *);
1292 static char *arg0; /* value of $0 */
1293 static struct shparam shellparam; /* current positional parameters */
1294 static char **argptr; /* argument list for builtin commands */
1295 static char *optionarg; /* set by nextopt (like getopt) */
1296 static char *optptr; /* used by nextopt */
1297 static char *minusc; /* argument to -c option */
1300 #ifdef CONFIG_ASH_ALIAS
1302 #define ALIASINUSE 1
1314 static struct alias *atab[ATABSIZE];
1316 static void setalias(char *, char *);
1317 static struct alias **hashalias(const char *);
1318 static struct alias *freealias(struct alias *);
1319 static struct alias **__lookupalias(const char *);
1321 static void setalias(char *name, char *val)
1323 struct alias *ap, **app;
1325 app = __lookupalias(name);
1329 if (!(ap->flag & ALIASINUSE)) {
1332 ap->val = xstrdup(val);
1333 ap->flag &= ~ALIASDEAD;
1336 ap = xmalloc(sizeof(struct alias));
1337 ap->name = xstrdup(name);
1338 ap->val = xstrdup(val);
1346 static int unalias(char *name)
1350 app = __lookupalias(name);
1354 *app = freealias(*app);
1362 static void rmaliases(void)
1364 struct alias *ap, **app;
1368 for (i = 0; i < ATABSIZE; i++) {
1370 for (ap = *app; ap; ap = *app) {
1371 *app = freealias(*app);
1380 static void printalias(const struct alias *ap)
1384 p = single_quote(ap->val);
1385 printf("alias %s=%s\n", ap->name, p);
1391 * TODO - sort output
1393 static int aliascmd(int argc, char **argv)
1402 for (i = 0; i < ATABSIZE; i++)
1403 for (ap = atab[i]; ap; ap = ap->next) {
1408 while ((n = *++argv) != NULL) {
1409 if ((v = strchr(n + 1, '=')) == NULL) { /* n+1: funny ksh stuff */
1410 if ((ap = *__lookupalias(n)) == NULL) {
1411 out2fmt("%s: %s not found\n", "alias", n);
1424 static int unaliascmd(int argc, char **argv)
1428 while ((i = nextopt("a")) != '\0') {
1434 for (i = 0; *argptr; argptr++) {
1435 if (unalias(*argptr)) {
1436 out2fmt("%s: %s not found\n", "unalias", *argptr);
1444 static struct alias **hashalias(const char *p)
1446 unsigned int hashval;
1451 return &atab[hashval % ATABSIZE];
1454 static struct alias *freealias(struct alias *ap)
1458 if (ap->flag & ALIASINUSE) {
1459 ap->flag |= ALIASDEAD;
1471 static struct alias **__lookupalias(const char *name)
1473 struct alias **app = hashalias(name);
1475 for (; *app; app = &(*app)->next) {
1476 if (equal(name, (*app)->name)) {
1485 #ifdef CONFIG_ASH_MATH_SUPPORT
1486 /* The generated file arith.c has been replaced with a custom hand
1487 * written implementation written by Aaron Lehmann <aaronl@vitelus.com>.
1488 * This is now part of libbb, so that it can be used by all the shells
1490 static void expari(int);
1493 static char *trap[NSIG]; /* trap handler commands */
1494 static char sigmode[NSIG - 1]; /* current value of signal */
1495 static char gotsig[NSIG - 1]; /* indicates specified signal received */
1496 static int pendingsigs; /* indicates some signal received */
1499 * This file was generated by the mkbuiltins program.
1502 #ifdef CONFIG_ASH_JOB_CONTROL
1503 static int bgcmd(int, char **);
1504 static int fgcmd(int, char **);
1505 static int killcmd(int, char **);
1507 static int bltincmd(int, char **);
1508 static int cdcmd(int, char **);
1509 static int breakcmd(int, char **);
1511 #ifdef CONFIG_ASH_CMDCMD
1512 static int commandcmd(int, char **);
1514 static int dotcmd(int, char **);
1515 static int evalcmd(int, char **);
1516 static int execcmd(int, char **);
1517 static int exitcmd(int, char **);
1518 static int exportcmd(int, char **);
1519 static int histcmd(int, char **);
1520 static int hashcmd(int, char **);
1521 static int helpcmd(int, char **);
1522 static int jobscmd(int, char **);
1523 static int localcmd(int, char **);
1524 static int pwdcmd(int, char **);
1525 static int readcmd(int, char **);
1526 static int returncmd(int, char **);
1527 static int setcmd(int, char **);
1528 static int setvarcmd(int, char **);
1529 static int shiftcmd(int, char **);
1530 static int trapcmd(int, char **);
1531 static int umaskcmd(int, char **);
1533 #ifdef CONFIG_ASH_ALIAS
1534 static int aliascmd(int, char **);
1535 static int unaliascmd(int, char **);
1537 static int unsetcmd(int, char **);
1538 static int waitcmd(int, char **);
1539 static int ulimitcmd(int, char **);
1540 static int timescmd(int, char **);
1542 #ifdef CONFIG_ASH_MATH_SUPPORT
1543 static int letcmd(int, char **);
1545 static int typecmd(int, char **);
1547 #ifdef CONFIG_ASH_GETOPTS
1548 static int getoptscmd(int, char **);
1552 static int true_main(int, char **);
1554 #ifndef CONFIG_FALSE
1555 static int false_main(int, char **);
1558 static void setpwd(const char *, int);
1561 #define BUILTIN_NOSPEC "0"
1562 #define BUILTIN_SPECIAL "1"
1563 #define BUILTIN_REGULAR "2"
1564 #define BUILTIN_ASSIGN "4"
1565 #define BUILTIN_SPEC_ASSG "5"
1566 #define BUILTIN_REG_ASSG "6"
1568 #define IS_BUILTIN_SPECIAL(builtincmd) ((builtincmd)->name[0] & 1)
1569 #define IS_BUILTIN_REGULAR(builtincmd) ((builtincmd)->name[0] & 2)
1570 #define IS_BUILTIN_ASSIGN(builtincmd) ((builtincmd)->name[0] & 4)
1574 int (*const builtinfunc) (int, char **);
1579 /* It is CRUCIAL that this listing be kept in ascii order, otherwise
1580 * the binary search in find_builtin() will stop working. If you value
1581 * your kneecaps, you'll be sure to *make sure* that any changes made
1582 * to this array result in the listing remaining in ascii order. You
1585 static const struct builtincmd builtincmds[] = {
1586 {BUILTIN_SPECIAL ".", dotcmd}, /* first, see declare DOTCMD */
1587 {BUILTIN_SPECIAL ":", true_main},
1588 #ifdef CONFIG_ASH_ALIAS
1589 {BUILTIN_REG_ASSG "alias", aliascmd},
1591 #ifdef CONFIG_ASH_JOB_CONTROL
1592 {BUILTIN_REGULAR "bg", bgcmd},
1594 {BUILTIN_SPECIAL "break", breakcmd},
1595 {BUILTIN_SPECIAL "builtin", bltincmd},
1596 {BUILTIN_REGULAR "cd", cdcmd},
1597 {BUILTIN_NOSPEC "chdir", cdcmd},
1598 #ifdef CONFIG_ASH_CMDCMD
1599 {BUILTIN_REGULAR "command", commandcmd},
1601 {BUILTIN_SPECIAL "continue", breakcmd},
1602 {BUILTIN_SPECIAL "eval", evalcmd},
1603 {BUILTIN_SPECIAL "exec", execcmd},
1604 {BUILTIN_SPECIAL "exit", exitcmd},
1605 {BUILTIN_SPEC_ASSG "export", exportcmd},
1606 {BUILTIN_REGULAR "false", false_main},
1607 {BUILTIN_REGULAR "fc", histcmd},
1608 #ifdef CONFIG_ASH_JOB_CONTROL
1609 {BUILTIN_REGULAR "fg", fgcmd},
1611 #ifdef CONFIG_ASH_GETOPTS
1612 {BUILTIN_REGULAR "getopts", getoptscmd},
1614 {BUILTIN_NOSPEC "hash", hashcmd},
1615 {BUILTIN_NOSPEC "help", helpcmd},
1616 {BUILTIN_REGULAR "jobs", jobscmd},
1617 #ifdef CONFIG_ASH_JOB_CONTROL
1618 {BUILTIN_REGULAR "kill", killcmd},
1620 #ifdef CONFIG_ASH_MATH_SUPPORT
1621 {BUILTIN_REGULAR "let", letcmd},
1623 {BUILTIN_ASSIGN "local", localcmd},
1624 {BUILTIN_NOSPEC "pwd", pwdcmd},
1625 {BUILTIN_REGULAR "read", readcmd},
1626 {BUILTIN_SPEC_ASSG "readonly", exportcmd},
1627 {BUILTIN_SPECIAL "return", returncmd},
1628 {BUILTIN_SPECIAL "set", setcmd},
1629 {BUILTIN_NOSPEC "setvar", setvarcmd},
1630 {BUILTIN_SPECIAL "shift", shiftcmd},
1631 {BUILTIN_SPECIAL "times", timescmd},
1632 {BUILTIN_SPECIAL "trap", trapcmd},
1633 {BUILTIN_REGULAR "true", true_main},
1634 {BUILTIN_NOSPEC "type", typecmd},
1635 {BUILTIN_NOSPEC "ulimit", ulimitcmd},
1636 {BUILTIN_REGULAR "umask", umaskcmd},
1637 #ifdef CONFIG_ASH_ALIAS
1638 {BUILTIN_REGULAR "unalias", unaliascmd},
1640 {BUILTIN_SPECIAL "unset", unsetcmd},
1641 {BUILTIN_REGULAR "wait", waitcmd},
1644 #define NUMBUILTINS (sizeof (builtincmds) / sizeof (struct builtincmd) )
1646 #define DOTCMD &builtincmds[0]
1647 static struct builtincmd *BLTINCMD;
1648 static struct builtincmd *EXECCMD;
1649 static struct builtincmd *EVALCMD;
1652 #define JOBSTOPPED 1 /* all procs are stopped */
1653 #define JOBDONE 2 /* all procs are completed */
1656 * A job structure contains information about a job. A job is either a
1657 * single process or a set of processes contained in a pipeline. In the
1658 * latter case, pidlist will be non-NULL, and will point to a -1 terminated
1663 pid_t pid; /* process id */
1664 int status; /* status flags (defined above) */
1665 char *cmd; /* text of command being run */
1669 static int job_warning; /* user was warned about stopped jobs */
1671 #ifdef CONFIG_ASH_JOB_CONTROL
1672 static void setjobctl(int enable);
1674 #define setjobctl(on) /* do nothing */
1679 struct procstat ps0; /* status of process */
1680 struct procstat *ps; /* status or processes when more than one */
1681 short nprocs; /* number of processes */
1682 short pgrp; /* process group of this job */
1683 char state; /* true if job is finished */
1684 char used; /* true if this entry is in used */
1685 char changed; /* true if status has changed */
1686 #ifdef CONFIG_ASH_JOB_CONTROL
1687 char jobctl; /* job running under job control */
1691 static struct job *jobtab; /* array of jobs */
1692 static int njobs; /* size of array */
1693 static int backgndpid = -1; /* pid of last background process */
1695 #ifdef CONFIG_ASH_JOB_CONTROL
1696 static int initialpgrp; /* pgrp of shell on invocation */
1697 static int curjob; /* current job */
1701 static struct job *makejob(const union node *, int);
1702 static int forkshell(struct job *, const union node *, int);
1703 static int waitforjob(struct job *);
1705 static int docd(char *, int);
1706 static void getpwd(void);
1708 static char *padvance(const char **, const char *);
1710 static char nullstr[1]; /* zero length string */
1711 static char *curdir = nullstr; /* current working directory */
1713 static int cdcmd(int argc, char **argv)
1722 if ((dest = *argptr) == NULL && (dest = bltinlookup("HOME")) == NULL)
1723 error("HOME not set");
1726 if (dest[0] == '-' && dest[1] == '\0') {
1727 dest = bltinlookup("OLDPWD");
1728 if (!dest || !*dest) {
1737 if (*dest == '/' || (path = bltinlookup("CDPATH")) == NULL)
1739 while ((p = padvance(&path, dest)) != NULL) {
1740 if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
1745 if (p[0] == '.' && p[1] == '/' && p[2] != '\0')
1747 print = strcmp(p, dest);
1749 if (docd(p, print) >= 0)
1754 error("can't cd to %s", dest);
1760 * Update curdir (the name of the current directory) in response to a
1761 * cd command. We also call hashcd to let the routines in exec.c know
1762 * that the current directory has changed.
1765 static void hashcd(void);
1767 static inline void updatepwd(const char *dir)
1769 hashcd(); /* update command hash table */
1772 * If our argument is NULL, we don't know the current directory
1774 if (dir == NULL || curdir == nullstr) {
1782 * Actually do the chdir. In an interactive shell, print the
1783 * directory name if "print" is nonzero.
1786 static int docd(char *dest, int print)
1788 TRACE(("docd(\"%s\", %d) called\n", dest, print));
1790 if (chdir(dest) < 0) {
1802 static int pwdcmd(int argc, char **argv)
1808 /* Ask system the current directory */
1809 static void getpwd(void)
1811 curdir = xgetcwd(0);
1816 static void setpwd(const char *val, int setold)
1821 setvar("OLDPWD", curdir, VEXPORT);
1824 if (curdir != nullstr) {
1825 if (val != NULL && *val != '/')
1826 val = cated = concat_path_file(curdir, val);
1832 curdir = simplify_path(val);
1835 setvar("PWD", curdir, VEXPORT);
1839 * Errors and exceptions.
1843 * Code to handle exceptions in C.
1847 * We enclose jmp_buf in a structure so that we can declare pointers to
1848 * jump locations. The global variable handler contains the location to
1849 * jump to when an exception occurs, and the global variable exception
1850 * contains a code identifying the exeception. To implement nested
1851 * exception handlers, the user should save the value of handler on entry
1852 * to an inner scope, set handler to point to a jmploc structure for the
1853 * inner scope, and restore handler on exit from the scope.
1861 #define EXINT 0 /* SIGINT received */
1862 #define EXERROR 1 /* a generic error */
1863 #define EXSHELLPROC 2 /* execute a shell procedure */
1864 #define EXEXEC 3 /* command execution failed */
1865 #define EXREDIR 4 /* redirection error */
1867 static struct jmploc *handler;
1868 static int exception;
1870 static void exverror(int, const char *, va_list)
1871 __attribute__ ((__noreturn__));
1874 * Called to raise an exception. Since C doesn't include exceptions, we
1875 * just do a longjmp to the exception handler. The type of exception is
1876 * stored in the global variable "exception".
1879 static void exraise(int) __attribute__ ((__noreturn__));
1881 static void exraise(int e)
1884 if (handler == NULL)
1889 longjmp(handler->loc, 1);
1894 * Called from trap.c when a SIGINT is received. (If the user specifies
1895 * that SIGINT is to be trapped or ignored using the trap builtin, then
1896 * this routine is not called.) Suppressint is nonzero when interrupts
1897 * are held using the INTOFF macro. The call to _exit is necessary because
1898 * there is a short period after a fork before the signal handlers are
1899 * set to the appropriate value for the child. (The test for iflag is
1900 * just defensive programming.)
1903 static void onint(void)
1912 sigemptyset(&mysigset);
1913 sigprocmask(SIG_SETMASK, &mysigset, NULL);
1914 if (!(rootshell && iflag)) {
1915 signal(SIGINT, SIG_DFL);
1923 static char *commandname; /* currently executing command */
1926 * Exverror is called to raise the error exception. If the first argument
1927 * is not NULL then error prints an error message using printf style
1928 * formatting. It then raises the error exception.
1930 static void exverror(int cond, const char *msg, va_list ap)
1937 TRACE(("exverror(%d, \"%s\") pid=%d\n", cond, msg, getpid()));
1939 TRACE(("exverror(%d, NULL) pid=%d\n", cond, getpid()));
1943 out2fmt("%s: ", commandname);
1944 vfprintf(stderr, msg, ap);
1952 static void error(const char *msg, ...)
1957 exverror(EXERROR, msg, ap);
1963 static void exerror(int cond, const char *msg, ...)
1968 exverror(cond, msg, ap);
1976 * Table of error messages.
1980 short errcode; /* error number */
1981 short action; /* operation which encountered the error */
1985 * Types of operations (passed to the errmsg routine).
1988 #define E_OPEN 01 /* opening a file */
1989 #define E_CREAT 02 /* creating a file */
1990 #define E_EXEC 04 /* executing a program */
1992 #define ALL (E_OPEN|E_CREAT|E_EXEC)
1994 static const struct errname errormsg[] = {
2048 #define ERRNAME_SIZE (sizeof(errormsg)/sizeof(struct errname))
2051 * Return a string describing an error. The returned string may be a
2052 * pointer to a static buffer that will be overwritten on the next call.
2053 * Action describes the operation that got the error.
2056 static const char *errmsg(int e, int action)
2058 struct errname const *ep;
2059 static char buf[12];
2061 for (ep = errormsg; ep < errormsg + ERRNAME_SIZE; ep++) {
2062 if (ep->errcode == e && (ep->action & action) != 0)
2066 snprintf(buf, sizeof buf, "error %d", e);
2071 #ifdef CONFIG_ASH_OPTIMIZE_FOR_SIZE
2072 static void __inton()
2074 if (--suppressint == 0 && intpending) {
2078 static void forceinton(void)
2086 /* flags in argument to evaltree */
2087 #define EV_EXIT 01 /* exit after evaluating tree */
2088 #define EV_TESTED 02 /* exit status is checked; ignore -e flag */
2089 #define EV_BACKCMD 04 /* command executing within back quotes */
2091 static int evalskip; /* set if we are skipping commands */
2092 static int skipcount; /* number of levels to skip */
2093 static int loopnest; /* current loop nesting level */
2094 static int funcnest; /* depth of function calls */
2097 static struct strlist *cmdenviron; /* environment for builtin command */
2098 static int exitstatus; /* exit status of last command */
2099 static int oexitstatus; /* saved exit status */
2101 static void evalsubshell(const union node *, int);
2102 static void expredir(union node *);
2103 static void prehash(union node *);
2104 static void eprintlist(struct strlist *);
2106 static union node *parsecmd(int);
2109 * Called to reset things after an exception.
2113 * The eval commmand.
2115 static void evalstring(char *, int);
2117 static int evalcmd(int argc, char **argv)
2126 STARTSTACKSTR(concat);
2130 STPUTC(*p++, concat);
2131 if ((p = *ap++) == NULL)
2133 STPUTC(' ', concat);
2135 STPUTC('\0', concat);
2136 p = grabstackstr(concat);
2138 evalstring(p, EV_TESTED);
2144 * Execute a command or commands contained in a string.
2147 static void evaltree(union node *, int);
2148 static void setinputstring(char *);
2149 static void popfile(void);
2150 static void setstackmark(struct stackmark *mark);
2151 static void popstackmark(struct stackmark *mark);
2154 static void evalstring(char *s, int flag)
2157 struct stackmark smark;
2159 setstackmark(&smark);
2161 while ((n = parsecmd(0)) != NEOF) {
2163 popstackmark(&smark);
2166 popstackmark(&smark);
2169 static struct builtincmd *find_builtin(const char *);
2170 static void expandarg(union node *, struct arglist *, int);
2171 static void calcsize(const union node *);
2172 static union node *copynode(const union node *);
2175 * Make a copy of a parse tree.
2178 static int funcblocksize; /* size of structures in function */
2179 static int funcstringsize; /* size of strings in node */
2180 static pointer funcblock; /* block to allocate function from */
2181 static char *funcstring; /* block to allocate strings from */
2184 static inline union node *copyfunc(union node *n)
2191 funcblock = xmalloc(funcblocksize + funcstringsize);
2192 funcstring = (char *) funcblock + funcblocksize;
2197 * Add a new command entry, replacing any existing command entry for
2201 static inline void addcmdentry(char *name, struct cmdentry *entry)
2203 struct tblentry *cmdp;
2206 cmdp = cmdlookup(name, 1);
2207 if (cmdp->cmdtype == CMDFUNCTION) {
2208 free(cmdp->param.func);
2210 cmdp->cmdtype = entry->cmdtype;
2211 cmdp->param = entry->u;
2215 static inline void evalloop(const union node *n, int flags)
2223 evaltree(n->nbinary.ch1, EV_TESTED);
2225 skipping:if (evalskip == SKIPCONT && --skipcount <= 0) {
2229 if (evalskip == SKIPBREAK && --skipcount <= 0)
2233 if (n->type == NWHILE) {
2234 if (exitstatus != 0)
2237 if (exitstatus == 0)
2240 evaltree(n->nbinary.ch2, flags);
2241 status = exitstatus;
2246 exitstatus = status;
2249 static void evalfor(const union node *n, int flags)
2251 struct arglist arglist;
2254 struct stackmark smark;
2256 setstackmark(&smark);
2257 arglist.lastp = &arglist.list;
2258 for (argp = n->nfor.args; argp; argp = argp->narg.next) {
2259 oexitstatus = exitstatus;
2260 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE | EXP_RECORD);
2264 *arglist.lastp = NULL;
2269 for (sp = arglist.list; sp; sp = sp->next) {
2270 setvar(n->nfor.var, sp->text, 0);
2271 evaltree(n->nfor.body, flags);
2273 if (evalskip == SKIPCONT && --skipcount <= 0) {
2277 if (evalskip == SKIPBREAK && --skipcount <= 0)
2284 popstackmark(&smark);
2287 static inline void evalcase(const union node *n, int flags)
2291 struct arglist arglist;
2292 struct stackmark smark;
2294 setstackmark(&smark);
2295 arglist.lastp = &arglist.list;
2296 oexitstatus = exitstatus;
2297 expandarg(n->ncase.expr, &arglist, EXP_TILDE);
2298 for (cp = n->ncase.cases; cp && evalskip == 0; cp = cp->nclist.next) {
2299 for (patp = cp->nclist.pattern; patp; patp = patp->narg.next) {
2300 if (casematch(patp, arglist.list->text)) {
2301 if (evalskip == 0) {
2302 evaltree(cp->nclist.body, flags);
2309 popstackmark(&smark);
2313 * Evaluate a pipeline. All the processes in the pipeline are children
2314 * of the process creating the pipeline. (This differs from some versions
2315 * of the shell, which make the last process in a pipeline the parent
2319 static inline void evalpipe(union node *n, int flags)
2322 struct nodelist *lp;
2327 TRACE(("evalpipe(0x%lx) called\n", (long) n));
2329 for (lp = n->npipe.cmdlist; lp; lp = lp->next)
2333 jp = makejob(n, pipelen);
2335 for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
2339 if (pipe(pip) < 0) {
2341 error("Pipe call failed");
2344 if (forkshell(jp, lp->n, n->npipe.backgnd) == 0) {
2357 evaltree(lp->n, flags);
2364 if (n->npipe.backgnd == 0) {
2365 exitstatus = waitforjob(jp);
2366 TRACE(("evalpipe: job done exit status %d\n", exitstatus));
2371 static void find_command(const char *, struct cmdentry *, int, const char *);
2373 static int isassignment(const char *word)
2375 if (!is_name(*word)) {
2380 } while (is_in_name(*word));
2381 return *word == '=';
2385 static void evalcommand(union node *cmd, int flags)
2387 struct stackmark smark;
2389 struct arglist arglist;
2390 struct arglist varlist;
2396 struct cmdentry cmdentry;
2398 char *volatile savecmdname;
2399 volatile struct shparam saveparam;
2400 struct localvar *volatile savelocalvars;
2405 struct jmploc *volatile savehandler;
2406 struct jmploc jmploc;
2409 /* Avoid longjmp clobbering */
2417 /* First expand the arguments. */
2418 TRACE(("evalcommand(0x%lx, %d) called\n", (long) cmd, flags));
2419 setstackmark(&smark);
2420 arglist.lastp = &arglist.list;
2421 varlist.lastp = &varlist.list;
2423 oexitstatus = exitstatus;
2426 for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
2427 expandarg(argp, &varlist, EXP_VARTILDE);
2429 for (argp = cmd->ncmd.args; argp && !arglist.list; argp = argp->narg.next) {
2430 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
2433 struct builtincmd *bcmd;
2436 bcmd = find_builtin(arglist.list->text);
2437 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
2438 for (; argp; argp = argp->narg.next) {
2439 if (pseudovarflag && isassignment(argp->narg.text)) {
2440 expandarg(argp, &arglist, EXP_VARTILDE);
2443 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
2446 *arglist.lastp = NULL;
2447 *varlist.lastp = NULL;
2448 expredir(cmd->ncmd.redirect);
2450 for (sp = arglist.list; sp; sp = sp->next)
2452 argv = stalloc(sizeof(char *) * (argc + 1));
2454 for (sp = arglist.list; sp; sp = sp->next) {
2455 TRACE(("evalcommand arg: %s\n", sp->text));
2460 if (iflag && funcnest == 0 && argc > 0)
2464 /* Print the command if xflag is set. */
2467 eprintlist(varlist.list);
2468 eprintlist(arglist.list);
2472 /* Now locate the command. */
2474 cmdentry.cmdtype = CMDBUILTIN;
2475 cmdentry.u.cmd = BLTINCMD;
2478 const char *oldpath;
2479 int findflag = DO_ERR;
2483 * Modify the command lookup path, if a PATH= assignment
2486 for (sp = varlist.list; sp; sp = sp->next)
2487 if (varequal(sp->text, defpathvar)) {
2488 path = sp->text + 5;
2489 findflag |= DO_BRUTE;
2492 oldfindflag = findflag;
2495 find_command(argv[0], &cmdentry, findflag, path);
2496 if (cmdentry.cmdtype == CMDUNKNOWN) { /* command not found */
2500 /* implement bltin and command here */
2501 if (cmdentry.cmdtype != CMDBUILTIN) {
2504 if (spclbltin < 0) {
2505 spclbltin = !!(IS_BUILTIN_SPECIAL(cmdentry.u.cmd)) * 2;
2507 if (cmdentry.u.cmd == BLTINCMD) {
2509 struct builtincmd *bcmd;
2514 if (!(bcmd = find_builtin(*argv))) {
2515 out2fmt("%s: not found\n", *argv);
2519 cmdentry.u.cmd = bcmd;
2520 if (bcmd != BLTINCMD)
2524 if (cmdentry.u.cmd == find_builtin("command")) {
2529 if (*argv[0] == '-') {
2530 if (!equal(argv[0], "-p")) {
2540 findflag |= DO_BRUTE;
2543 findflag = oldfindflag;
2545 findflag |= DO_NOFUN;
2553 /* Fork off a child process if necessary. */
2554 if (cmd->ncmd.backgnd
2555 || (cmdentry.cmdtype == CMDNORMAL && (!(flags & EV_EXIT) || trap[0]))
2558 jp = makejob(cmd, 1);
2559 mode = cmd->ncmd.backgnd;
2560 if (forkshell(jp, cmd, mode) != 0)
2561 goto parent; /* at end of routine */
2568 /* This is the child process if a fork occurred. */
2569 /* Execute the command. */
2570 if (cmdentry.cmdtype == CMDFUNCTION) {
2572 trputs("Shell function: ");
2575 exitstatus = oexitstatus;
2576 saveparam = shellparam;
2577 shellparam.malloc = 0;
2578 shellparam.nparam = argc - 1;
2579 shellparam.p = argv + 1;
2581 savelocalvars = localvars;
2584 if (setjmp(jmploc.loc)) {
2585 if (exception == EXREDIR) {
2589 saveparam.optind = shellparam.optind;
2590 saveparam.optoff = shellparam.optoff;
2591 freeparam(&shellparam);
2592 shellparam = saveparam;
2594 localvars = savelocalvars;
2595 handler = savehandler;
2596 longjmp(handler->loc, 1);
2598 savehandler = handler;
2600 redirect(cmd->ncmd.redirect, REDIR_PUSH);
2601 listsetvar(varlist.list);
2603 evaltree(cmdentry.u.func, flags & EV_TESTED);
2608 localvars = savelocalvars;
2609 saveparam.optind = shellparam.optind;
2610 saveparam.optoff = shellparam.optoff;
2611 freeparam(&shellparam);
2612 shellparam = saveparam;
2613 handler = savehandler;
2616 if (evalskip == SKIPFUNC) {
2620 } else if (cmdentry.cmdtype == CMDBUILTIN) {
2624 trputs("builtin command: ");
2627 redir = (cmdentry.u.cmd == EXECCMD) ? 0 : REDIR_PUSH;
2628 savecmdname = commandname;
2630 listsetvar(varlist.list);
2632 cmdenviron = varlist.list;
2635 if (setjmp(jmploc.loc)) {
2637 exitstatus = (e == EXINT) ? SIGINT + 128 : 2;
2640 savehandler = handler;
2642 redirect(cmd->ncmd.redirect, redir);
2643 commandname = argv[0];
2645 optptr = NULL; /* initialize nextopt */
2646 exitstatus = (*cmdentry.u.cmd->builtinfunc) (argc, argv);
2650 commandname = savecmdname;
2651 handler = savehandler;
2653 if (e == EXINT || spclbltin & 2) {
2659 if (cmdentry.u.cmd != EXECCMD)
2663 trputs("normal command: ");
2666 redirect(cmd->ncmd.redirect, 0);
2668 for (sp = varlist.list; sp; sp = sp->next)
2669 setvareq(sp->text, VEXPORT | VSTACK);
2670 envp = environment();
2671 shellexec(argv, envp, path, cmdentry.u.index);
2673 if (flags & EV_EXIT)
2674 exitshell(exitstatus);
2677 parent: /* parent process gets here (if we forked) */
2678 if (mode == 0) { /* argument to fork */
2679 exitstatus = waitforjob(jp);
2685 setvar("_", lastarg, 0);
2686 popstackmark(&smark);
2690 * Evaluate a parse tree. The value is left in the global variable
2693 static void evaltree(union node *n, int flags)
2698 TRACE(("evaltree(NULL) called\n"));
2701 TRACE(("evaltree(0x%lx: %d) called\n", (long) n, n->type));
2704 evaltree(n->nbinary.ch1, flags & EV_TESTED);
2707 evaltree(n->nbinary.ch2, flags);
2710 evaltree(n->nbinary.ch1, EV_TESTED);
2711 if (evalskip || exitstatus != 0)
2713 evaltree(n->nbinary.ch2, flags);
2716 evaltree(n->nbinary.ch1, EV_TESTED);
2717 if (evalskip || exitstatus == 0)
2719 evaltree(n->nbinary.ch2, flags);
2722 expredir(n->nredir.redirect);
2723 redirect(n->nredir.redirect, REDIR_PUSH);
2724 evaltree(n->nredir.n, flags);
2728 evalsubshell(n, flags);
2731 evalsubshell(n, flags);
2734 evaltree(n->nif.test, EV_TESTED);
2737 if (exitstatus == 0)
2738 evaltree(n->nif.ifpart, flags);
2739 else if (n->nif.elsepart)
2740 evaltree(n->nif.elsepart, flags);
2756 struct builtincmd *bcmd;
2757 struct cmdentry entry;
2759 if ((bcmd = find_builtin(n->narg.text)) && IS_BUILTIN_SPECIAL(bcmd)
2761 out2fmt("%s is a special built-in\n", n->narg.text);
2765 entry.cmdtype = CMDFUNCTION;
2766 entry.u.func = copyfunc(n->narg.next);
2767 addcmdentry(n->narg.text, &entry);
2772 evaltree(n->nnot.com, EV_TESTED);
2773 exitstatus = !exitstatus;
2781 evalcommand(n, flags);
2786 printf("Node type = %d\n", n->type);
2793 if (flags & EV_EXIT ||
2794 (checkexit && eflag && exitstatus && !(flags & EV_TESTED))
2796 exitshell(exitstatus);
2800 * Kick off a subshell to evaluate a tree.
2803 static void evalsubshell(const union node *n, int flags)
2806 int backgnd = (n->type == NBACKGND);
2808 expredir(n->nredir.redirect);
2809 if (!backgnd && flags & EV_EXIT && !trap[0])
2813 if (forkshell(jp, n, backgnd) == 0) {
2817 flags &= ~EV_TESTED;
2819 redirect(n->nredir.redirect, 0);
2820 evaltree(n->nredir.n, flags); /* never returns */
2823 exitstatus = waitforjob(jp);
2829 * Compute the names of the files in a redirection list.
2832 static void fixredir(union node *n, const char *text, int err);
2834 static void expredir(union node *n)
2838 for (redir = n; redir; redir = redir->nfile.next) {
2841 fn.lastp = &fn.list;
2842 oexitstatus = exitstatus;
2843 switch (redir->type) {
2849 expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
2850 redir->nfile.expfname = fn.list->text;
2854 if (redir->ndup.vname) {
2855 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
2856 fixredir(redir, fn.list->text, 1);
2865 * Execute a command inside back quotes. If it's a builtin command, we
2866 * want to save its output in a block obtained from malloc. Otherwise
2867 * we fork off a subprocess and get the output of the command via a pipe.
2868 * Should be called with interrupts off.
2871 static void evalbackcmd(union node *n, struct backcmd *result)
2875 struct stackmark smark; /* unnecessary */
2877 setstackmark(&smark);
2888 error("Pipe call failed");
2890 if (forkshell(jp, n, FORK_NOJOB) == 0) {
2895 dup_as_newfd(pip[1], 1);
2899 evaltree(n, EV_EXIT);
2902 result->fd = pip[0];
2905 popstackmark(&smark);
2906 TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
2907 result->fd, result->buf, result->nleft, result->jp));
2912 * Execute a simple command.
2916 * Search for a command. This is called before we fork so that the
2917 * location of the command will be available in the parent as well as
2918 * the child. The check for "goodname" is an overly conservative
2919 * check that the name will not be subject to expansion.
2922 static void prehash(union node *n)
2924 struct cmdentry entry;
2926 if (n->type == NCMD && n->ncmd.args)
2927 if (goodname(n->ncmd.args->narg.text))
2928 find_command(n->ncmd.args->narg.text, &entry, 0, pathval());
2933 * Builtin commands. Builtin commands whose functions are closely
2934 * tied to evaluation are implemented here.
2938 * No command given, or a bltin command with no arguments. Set the
2939 * specified variables.
2942 int bltincmd(int argc, char **argv)
2945 * Preserve exitstatus of a previous possible redirection
2953 * Handle break and continue commands. Break, continue, and return are
2954 * all handled by setting the evalskip flag. The evaluation routines
2955 * above all check this flag, and if it is set they start skipping
2956 * commands rather than executing them. The variable skipcount is
2957 * the number of loops to break/continue, or the number of function
2958 * levels to return. (The latter is always 1.) It should probably
2959 * be an error to break out of more loops than exist, but it isn't
2960 * in the standard shell so we don't make it one here.
2963 static int breakcmd(int argc, char **argv)
2965 int n = argc > 1 ? number(argv[1]) : 1;
2968 error("Illegal number: %s", argv[1]);
2972 evalskip = (**argv == 'c') ? SKIPCONT : SKIPBREAK;
2980 * The return command.
2983 static int returncmd(int argc, char **argv)
2985 int ret = argc > 1 ? number(argv[1]) : oexitstatus;
2988 evalskip = SKIPFUNC;
2992 /* Do what ksh does; skip the rest of the file */
2993 evalskip = SKIPFILE;
3000 #ifndef CONFIG_FALSE
3001 static int false_main(int argc, char **argv)
3008 static int true_main(int argc, char **argv)
3015 * Controls whether the shell is interactive or not.
3018 static void setsignal(int signo);
3020 #ifdef CONFIG_ASH_MAIL
3021 static void chkmail(int silent);
3024 static void setinteractive(int on)
3026 static int is_interactive;
3027 static int do_banner = 0;
3029 if (on == is_interactive)
3034 #ifdef CONFIG_ASH_MAIL
3037 is_interactive = on;
3038 if (do_banner == 0 && is_interactive) {
3039 /* Looks like they want an interactive shell */
3040 #ifndef CONFIG_FEATURE_SH_EXTRA_QUIET
3041 printf("\n\n" BB_BANNER " Built-in shell (ash)\n");
3042 printf("Enter 'help' for a list of built-in commands.\n\n");
3048 static void optschanged(void)
3050 setinteractive(iflag);
3055 static int execcmd(int argc, char **argv)
3060 iflag = 0; /* exit on error */
3063 for (sp = cmdenviron; sp; sp = sp->next)
3064 setvareq(sp->text, VEXPORT | VSTACK);
3065 shellexec(argv + 1, environment(), pathval(), 0);
3070 static void eprintlist(struct strlist *sp)
3072 for (; sp; sp = sp->next) {
3073 out2fmt(" %s", sp->text);
3078 * Exec a program. Never returns. If you change this routine, you may
3079 * have to change the find_command routine as well.
3082 static const char *pathopt; /* set by padvance */
3084 static void shellexec(char **argv, char **envp, const char *path, int idx)
3089 if (strchr(argv[0], '/') != NULL
3090 #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
3091 || find_applet_by_name(argv[0])
3095 tryexec(argv[0], argv, envp);
3099 while ((cmdname = padvance(&path, argv[0])) != NULL) {
3100 if (--idx < 0 && pathopt == NULL) {
3101 tryexec(cmdname, argv, envp);
3102 if (errno != ENOENT && errno != ENOTDIR)
3109 /* Map to POSIX errors */
3121 exerror(EXEXEC, "%s: %s", argv[0], errmsg(e, E_EXEC));
3126 * Clear traps on a fork.
3128 static void clear_traps(void)
3132 for (tp = trap; tp < &trap[NSIG]; tp++) {
3133 if (*tp && **tp) { /* trap not NULL or SIG_IGN */
3138 setsignal(tp - trap);
3145 static int preadbuffer(void);
3146 static void pushfile(void);
3149 * Read a character from the script, returning PEOF on end of file.
3150 * Nul characters in the input are silently discarded.
3153 #ifndef CONFIG_ASH_OPTIMIZE_FOR_SIZE
3154 #define pgetc_macro() (--parsenleft >= 0? *parsenextc++ : preadbuffer())
3155 static int pgetc(void)
3157 return pgetc_macro();
3160 static int pgetc_macro(void)
3162 return --parsenleft >= 0 ? *parsenextc++ : preadbuffer();
3165 static inline int pgetc(void)
3167 return pgetc_macro();
3173 * Undo the last call to pgetc. Only one character may be pushed back.
3174 * PEOF may be pushed back.
3177 static void pungetc(void)
3184 static void popfile(void)
3186 struct parsefile *pf = parsefile;
3194 parsefile = pf->prev;
3196 parsenleft = parsefile->nleft;
3197 parselleft = parsefile->lleft;
3198 parsenextc = parsefile->nextc;
3199 plinno = parsefile->linno;
3205 * Return to top level.
3208 static void popallfiles(void)
3210 while (parsefile != &basepf)
3215 * Close the file(s) that the shell is reading commands from. Called
3216 * after a fork is done.
3219 static void closescript(void)
3222 if (parsefile->fd > 0) {
3223 close(parsefile->fd);
3230 * Like setinputfile, but takes an open file descriptor. Call this with
3234 static void setinputfd(int fd, int push)
3236 (void) fcntl(fd, F_SETFD, FD_CLOEXEC);
3242 while (parsefile->strpush)
3246 if (parsefile->buf == NULL)
3247 parsefile->buf = xmalloc(BUFSIZ);
3248 parselleft = parsenleft = 0;
3254 * Set the input to take input from a file. If push is set, push the
3255 * old input onto the stack first.
3258 static void setinputfile(const char *fname, int push)
3264 if ((fd = open(fname, O_RDONLY)) < 0)
3265 error("Can't open %s", fname);
3267 myfileno2 = dup_as_newfd(fd, 10);
3270 error("Out of file descriptors");
3273 setinputfd(fd, push);
3278 static void tryexec(char *cmd, char **argv, char **envp)
3282 #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
3286 #ifdef CONFIG_FEATURE_SH_APPLETS_ALWAYS_WIN
3287 name = get_last_path_component(name);
3288 if(find_applet_by_name(name) != NULL)
3291 if(strchr(name, '/') == NULL && find_applet_by_name(name) != NULL) {
3300 if(strcmp(name, "busybox")) {
3301 for (ap = argv; *ap; ap++);
3302 ap = new = xmalloc((ap - argv + 2) * sizeof(char *));
3303 *ap++ = cmd = "/bin/busybox";
3304 while ((*ap++ = *argv++));
3308 cmd = "/bin/busybox";
3313 execve(cmd, argv, envp);
3316 } else if (errno == ENOEXEC) {
3320 for (ap = argv; *ap; ap++);
3321 ap = new = xmalloc((ap - argv + 2) * sizeof(char *));
3322 *ap++ = cmd = "/bin/sh";
3323 while ((*ap++ = *argv++));
3329 static char *commandtext(const union node *);
3332 * Do a path search. The variable path (passed by reference) should be
3333 * set to the start of the path before the first call; padvance will update
3334 * this value as it proceeds. Successive calls to padvance will return
3335 * the possible path expansions in sequence. If an option (indicated by
3336 * a percent sign) appears in the path entry then the global variable
3337 * pathopt will be set to point to it; otherwise pathopt will be set to
3341 static const char *pathopt;
3343 static void growstackblock(void);
3346 static char *padvance(const char **path, const char *name)
3356 for (p = start; *p && *p != ':' && *p != '%'; p++);
3357 len = p - start + strlen(name) + 2; /* "2" is for '/' and '\0' */
3358 while (stackblocksize() < len)
3362 memcpy(q, start, p - start);
3370 while (*p && *p != ':')
3377 return stalloc(len);
3381 * Wrapper around strcmp for qsort/bsearch/...
3383 static int pstrcmp(const void *a, const void *b)
3385 return strcmp((const char *) a, (*(const char *const *) b) + 1);
3389 * Find a keyword is in a sorted array.
3392 static const char *const *findkwd(const char *s)
3394 return bsearch(s, tokname_array + KWDOFFSET,
3395 (sizeof(tokname_array) / sizeof(const char *)) - KWDOFFSET,
3396 sizeof(const char *), pstrcmp);
3400 /*** Command hashing code ***/
3402 static int hashcmd(int argc, char **argv)
3404 struct tblentry **pp;
3405 struct tblentry *cmdp;
3408 struct cmdentry entry;
3411 #ifdef CONFIG_ASH_ALIAS
3412 const struct alias *ap;
3416 while ((c = nextopt("rvV")) != '\0') {
3420 } else if (c == 'v' || c == 'V') {
3424 if (*argptr == NULL) {
3425 for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
3426 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
3427 if (cmdp->cmdtype != CMDBUILTIN) {
3428 printentry(cmdp, verbose);
3435 while ((name = *argptr++) != NULL) {
3436 if ((cmdp = cmdlookup(name, 0)) != NULL
3437 && (cmdp->cmdtype == CMDNORMAL
3438 || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0)))
3440 #ifdef CONFIG_ASH_ALIAS
3441 /* Then look at the aliases */
3442 if ((ap = *__lookupalias(name)) != NULL) {
3444 printf("%s is an alias for %s\n", name, ap->val);
3450 /* First look at the keywords */
3451 if (findkwd(name) != 0) {
3453 printf("%s is a shell keyword\n", name);
3459 find_command(name, &entry, DO_ERR, pathval());
3460 if (entry.cmdtype == CMDUNKNOWN)
3463 cmdp = cmdlookup(name, 0);
3465 printentry(cmdp, verbose == 'v');
3472 static void printentry(struct tblentry *cmdp, int verbose)
3478 printf("%s%s", cmdp->cmdname, (verbose ? " is " : ""));
3479 if (cmdp->cmdtype == CMDNORMAL) {
3480 idx = cmdp->param.index;
3483 name = padvance(&path, cmdp->cmdname);
3485 } while (--idx >= 0);
3488 } else if (cmdp->cmdtype == CMDBUILTIN) {
3490 out1str("a shell builtin");
3491 } else if (cmdp->cmdtype == CMDFUNCTION) {
3494 out1str("a function\n");
3495 name = commandtext(cmdp->param.func);
3496 printf("%s() {\n %s\n}", cmdp->cmdname, name);
3502 error("internal error: cmdtype %d", cmdp->cmdtype);
3505 puts(cmdp->rehash ? "*" : nullstr);
3510 /*** List the available builtins ***/
3513 static int helpcmd(int argc, char **argv)
3517 printf("\nBuilt-in commands:\n-------------------\n");
3518 for (col = 0, i = 0; i < NUMBUILTINS; i++) {
3519 col += printf("%c%s", ((col == 0) ? '\t' : ' '),
3520 builtincmds[i].name + 1);
3526 #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
3528 extern const struct BB_applet applets[];
3529 extern const size_t NUM_APPLETS;
3531 for (i = 0; i < NUM_APPLETS; i++) {
3533 col += printf("%c%s", ((col == 0) ? '\t' : ' '), applets[i].name);
3542 return EXIT_SUCCESS;
3546 * Resolve a command name. If you change this routine, you may have to
3547 * change the shellexec routine as well.
3550 static int prefix(const char *, const char *);
3553 find_command(const char *name, struct cmdentry *entry, int act,
3556 struct tblentry *cmdp;
3566 struct builtincmd *bcmd;
3568 /* If name contains a slash, don't use the hash table */
3569 if (strchr(name, '/') != NULL) {
3571 while (stat(name, &statb) < 0) {
3572 if (errno != ENOENT && errno != ENOTDIR)
3574 entry->cmdtype = CMDUNKNOWN;
3575 entry->u.index = -1;
3578 entry->cmdtype = CMDNORMAL;
3579 entry->u.index = -1;
3582 entry->cmdtype = CMDNORMAL;
3587 #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
3588 if (find_applet_by_name(name)) {
3589 entry->cmdtype = CMDNORMAL;
3590 entry->u.index = -1;
3596 if (act & DO_BRUTE) {
3597 firstchange = path_change(path, &bltin);
3603 /* If name is in the table, and not invalidated by cd, we're done */
3604 if ((cmdp = cmdlookup(name, 0)) != NULL && cmdp->rehash == 0) {
3605 if (cmdp->cmdtype == CMDFUNCTION) {
3606 if (act & DO_NOFUN) {
3611 } else if (act & DO_BRUTE) {
3612 if ((cmdp->cmdtype == CMDNORMAL &&
3613 cmdp->param.index >= firstchange) ||
3614 (cmdp->cmdtype == CMDBUILTIN &&
3615 ((builtinloc < 0 && bltin >= 0) ?
3616 bltin : builtinloc) >= firstchange)) {
3617 /* need to recompute the entry */
3626 bcmd = find_builtin(name);
3627 regular = bcmd && IS_BUILTIN_REGULAR(bcmd);
3630 if (cmdp && (cmdp->cmdtype == CMDBUILTIN)) {
3633 } else if (act & DO_BRUTE) {
3634 if (firstchange == 0) {
3639 /* If %builtin not in path, check for builtin next */
3640 if (regular || (bltin < 0 && bcmd)) {
3643 entry->cmdtype = CMDBUILTIN;
3644 entry->u.cmd = bcmd;
3648 cmdp = cmdlookup(name, 1);
3649 cmdp->cmdtype = CMDBUILTIN;
3650 cmdp->param.cmd = bcmd;
3655 /* We have to search path. */
3656 prev = -1; /* where to start */
3657 if (cmdp && cmdp->rehash) { /* doing a rehash */
3658 if (cmdp->cmdtype == CMDBUILTIN)
3661 prev = cmdp->param.index;
3667 while ((fullname = padvance(&path, name)) != NULL) {
3668 stunalloc(fullname);
3670 if (idx >= firstchange) {
3674 if (prefix("builtin", pathopt)) {
3675 if ((bcmd = find_builtin(name))) {
3679 } else if (!(act & DO_NOFUN) && prefix("func", pathopt)) {
3682 continue; /* ignore unimplemented options */
3685 /* if rehash, don't redo absolute path names */
3686 if (fullname[0] == '/' && idx <= prev && idx < firstchange) {
3689 TRACE(("searchexec \"%s\": no change\n", name));
3692 while (stat(fullname, &statb) < 0) {
3693 if (errno != ENOENT && errno != ENOTDIR)
3697 e = EACCES; /* if we fail, this will be the error */
3698 if (!S_ISREG(statb.st_mode))
3700 if (pathopt) { /* this is a %func directory */
3701 stalloc(strlen(fullname) + 1);
3702 readcmdfile(fullname);
3703 if ((cmdp = cmdlookup(name, 0)) == NULL
3704 || cmdp->cmdtype != CMDFUNCTION)
3705 error("%s not defined in %s", name, fullname);
3706 stunalloc(fullname);
3709 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
3710 /* If we aren't called with DO_BRUTE and cmdp is set, it must
3711 be a function and we're being called with DO_NOFUN */
3713 entry->cmdtype = CMDNORMAL;
3714 entry->u.index = idx;
3718 cmdp = cmdlookup(name, 1);
3719 cmdp->cmdtype = CMDNORMAL;
3720 cmdp->param.index = idx;
3725 /* We failed. If there was an entry for this command, delete it */
3726 if (cmdp && updatetbl)
3729 out2fmt("%s: %s\n", name, errmsg(e, E_EXEC));
3730 entry->cmdtype = CMDUNKNOWN;
3735 entry->cmdtype = cmdp->cmdtype;
3736 entry->u = cmdp->param;
3742 * Search the table of builtin commands.
3745 static struct builtincmd *find_builtin(const char *name)
3747 struct builtincmd *bp;
3749 bp = bsearch(name, builtincmds, NUMBUILTINS, sizeof(struct builtincmd),
3756 * Called when a cd is done. Marks all commands so the next time they
3757 * are executed they will be rehashed.
3760 static void hashcd(void)
3762 struct tblentry **pp;
3763 struct tblentry *cmdp;
3765 for (pp = cmdtable; pp < &cmdtable[CMDTABLESIZE]; pp++) {
3766 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
3767 if (cmdp->cmdtype == CMDNORMAL
3768 || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))
3777 * Called before PATH is changed. The argument is the new value of PATH;
3778 * pathval() still returns the old value at this point. Called with
3782 static void changepath(const char *newval)
3787 firstchange = path_change(newval, &bltin);
3788 if (builtinloc < 0 && bltin >= 0)
3789 builtinloc = bltin; /* zap builtins */
3790 clearcmdentry(firstchange);
3792 /* Ensure that getenv("PATH") stays current */
3793 setenv("PATH", newval, 1);
3798 * Clear out command entries. The argument specifies the first entry in
3799 * PATH which has changed.
3802 static void clearcmdentry(int firstchange)
3804 struct tblentry **tblp;
3805 struct tblentry **pp;
3806 struct tblentry *cmdp;
3809 for (tblp = cmdtable; tblp < &cmdtable[CMDTABLESIZE]; tblp++) {
3811 while ((cmdp = *pp) != NULL) {
3812 if ((cmdp->cmdtype == CMDNORMAL &&
3813 cmdp->param.index >= firstchange)
3814 || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= firstchange)) {
3827 * Locate a command in the command hash table. If "add" is nonzero,
3828 * add the command to the table if it is not already present. The
3829 * variable "lastcmdentry" is set to point to the address of the link
3830 * pointing to the entry, so that delete_cmd_entry can delete the
3834 static struct tblentry **lastcmdentry;
3836 static struct tblentry *cmdlookup(const char *name, int add)
3840 struct tblentry *cmdp;
3841 struct tblentry **pp;
3848 pp = &cmdtable[hashval % CMDTABLESIZE];
3849 for (cmdp = *pp; cmdp; cmdp = cmdp->next) {
3850 if (equal(cmdp->cmdname, name))
3854 if (add && cmdp == NULL) {
3856 cmdp = *pp = xmalloc(sizeof(struct tblentry) - ARB
3857 + strlen(name) + 1);
3859 cmdp->cmdtype = CMDUNKNOWN;
3861 strcpy(cmdp->cmdname, name);
3869 * Delete the command entry returned on the last lookup.
3872 static void delete_cmd_entry(void)
3874 struct tblentry *cmdp;
3877 cmdp = *lastcmdentry;
3878 *lastcmdentry = cmdp->next;
3887 static const unsigned char nodesize[26] = {
3888 ALIGN(sizeof(struct nbinary)),
3889 ALIGN(sizeof(struct ncmd)),
3890 ALIGN(sizeof(struct npipe)),
3891 ALIGN(sizeof(struct nredir)),
3892 ALIGN(sizeof(struct nredir)),
3893 ALIGN(sizeof(struct nredir)),
3894 ALIGN(sizeof(struct nbinary)),
3895 ALIGN(sizeof(struct nbinary)),
3896 ALIGN(sizeof(struct nif)),
3897 ALIGN(sizeof(struct nbinary)),
3898 ALIGN(sizeof(struct nbinary)),
3899 ALIGN(sizeof(struct nfor)),
3900 ALIGN(sizeof(struct ncase)),
3901 ALIGN(sizeof(struct nclist)),
3902 ALIGN(sizeof(struct narg)),
3903 ALIGN(sizeof(struct narg)),
3904 ALIGN(sizeof(struct nfile)),
3905 ALIGN(sizeof(struct nfile)),
3906 ALIGN(sizeof(struct nfile)),
3907 ALIGN(sizeof(struct nfile)),
3908 ALIGN(sizeof(struct nfile)),
3909 ALIGN(sizeof(struct ndup)),
3910 ALIGN(sizeof(struct ndup)),
3911 ALIGN(sizeof(struct nhere)),
3912 ALIGN(sizeof(struct nhere)),
3913 ALIGN(sizeof(struct nnot)),
3919 * Delete a function if it exists.
3922 static void unsetfunc(char *name)
3924 struct tblentry *cmdp;
3926 if ((cmdp = cmdlookup(name, 0)) != NULL && cmdp->cmdtype == CMDFUNCTION) {
3927 free(cmdp->param.func);
3934 * Locate and print what a word is...
3937 static int typecmd(int argc, char **argv)
3945 for (i = 1; i < argc; i++) {
3946 argv_a[0] = argv[i];
3949 err |= hashcmd(2, argv);
3954 #ifdef CONFIG_ASH_CMDCMD
3955 static int commandcmd(int argc, char **argv)
3958 int default_path = 0;
3959 int verify_only = 0;
3960 int verbose_verify_only = 0;
3962 while ((c = nextopt("pvV")) != '\0')
3971 verbose_verify_only = 1;
3975 if (default_path + verify_only + verbose_verify_only > 1 || !*argptr) {
3976 out2str("command [-p] command [arg ...]\n"
3977 "command {-v|-V} command\n");
3981 if (verify_only || verbose_verify_only) {
3985 argv_a[0] = *argptr;
3987 optptr = verbose_verify_only ? "v" : "V"; /* reverse special */
3988 return hashcmd(argc, argv);
3995 static int path_change(const char *newval, int *bltin)
3997 const char *old, *new;
4003 firstchange = 9999; /* assume no change */
4009 if ((*old == '\0' && *new == ':')
4010 || (*old == ':' && *new == '\0'))
4012 old = new; /* ignore subsequent differences */
4016 if (*new == '%' && *bltin < 0 && prefix("builtin", new + 1))
4023 if (builtinloc >= 0 && *bltin < 0)
4029 * Routines to expand arguments to commands. We have to deal with
4030 * backquotes, shell variables, and file metacharacters.
4035 #define RMESCAPE_ALLOC 0x1 /* Allocate a new string */
4036 #define RMESCAPE_GLOB 0x2 /* Add backslashes for glob */
4039 * Structure specifying which parts of the string should be searched
4040 * for IFS characters.
4044 struct ifsregion *next; /* next region in list */
4045 int begoff; /* offset of start of region */
4046 int endoff; /* offset of end of region */
4047 int nulonly; /* search for nul bytes only */
4051 static char *expdest; /* output of current string */
4052 static struct nodelist *argbackq; /* list of back quote expressions */
4053 static struct ifsregion ifsfirst; /* first struct in list of ifs regions */
4054 static struct ifsregion *ifslastp; /* last struct in list */
4055 static struct arglist exparg; /* holds expanded arg list */
4057 static void argstr(char *, int);
4058 static char *exptilde(char *, int);
4059 static void expbackq(union node *, int, int);
4060 static int subevalvar(char *, char *, int, int, int, int, int);
4061 static int varisset(char *, int);
4062 static void strtodest(const char *, int, int);
4063 static void varvalue(char *, int, int);
4064 static void recordregion(int, int, int);
4065 static void removerecordregions(int);
4066 static void ifsbreakup(char *, struct arglist *);
4067 static void ifsfree(void);
4068 static void expandmeta(struct strlist *, int);
4070 #if defined(__GLIBC__) && __GLIBC__ >= 2 && !defined(FNMATCH_BROKEN)
4071 #define preglob(p) _rmescapes((p), RMESCAPE_ALLOC | RMESCAPE_GLOB)
4072 #if !defined(GLOB_BROKEN)
4073 static void addglob(const glob_t *);
4076 #if !(defined(__GLIBC__) && __GLIBC__ >= 2 && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN))
4077 static void expmeta(char *, char *);
4079 #if !(defined(__GLIBC__) && __GLIBC__ >= 2 && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN))
4080 static struct strlist *expsort(struct strlist *);
4081 static struct strlist *msort(struct strlist *, int);
4083 static int patmatch(char *, char *, int);
4085 #if defined(__GLIBC__) && __GLIBC__ >= 2 && !defined(FNMATCH_BROKEN)
4086 static int patmatch2(char *, char *, int);
4088 static int pmatch(char *, char *, int);
4090 #define patmatch2 patmatch
4092 static char *cvtnum(int, char *);
4095 * Expand shell variables and backquotes inside a here document.
4098 /* arg: the document, fd: where to write the expanded version */
4099 static inline void expandhere(union node *arg, int fd)
4102 expandarg(arg, (struct arglist *) NULL, 0);
4103 xwrite(fd, stackblock(), expdest - stackblock());
4108 * Perform variable substitution and command substitution on an argument,
4109 * placing the resulting list of arguments in arglist. If EXP_FULL is true,
4110 * perform splitting and file name expansion. When arglist is NULL, perform
4111 * here document expansion.
4114 static void expandarg(union node *arg, struct arglist *arglist, int flag)
4119 argbackq = arg->narg.backquote;
4120 STARTSTACKSTR(expdest);
4121 ifsfirst.next = NULL;
4123 argstr(arg->narg.text, flag);
4124 if (arglist == NULL) {
4125 return; /* here document expanded */
4127 STPUTC('\0', expdest);
4128 p = grabstackstr(expdest);
4129 exparg.lastp = &exparg.list;
4133 if (flag & EXP_FULL) {
4134 ifsbreakup(p, &exparg);
4135 *exparg.lastp = NULL;
4136 exparg.lastp = &exparg.list;
4137 expandmeta(exparg.list, flag);
4139 if (flag & EXP_REDIR) /*XXX - for now, just remove escapes */
4141 sp = (struct strlist *) stalloc(sizeof(struct strlist));
4144 exparg.lastp = &sp->next;
4147 *exparg.lastp = NULL;
4149 *arglist->lastp = exparg.list;
4150 arglist->lastp = exparg.lastp;
4156 * Expand a variable, and return a pointer to the next character in the
4160 static inline char *evalvar(char *p, int flag)
4173 int quotes = flag & (EXP_FULL | EXP_CASE);
4176 subtype = varflags & VSTYPE;
4181 p = strchr(p, '=') + 1;
4182 again: /* jump here after setting a variable with ${var=text} */
4184 set = varisset(var, varflags & VSNUL);
4187 val = lookupvar(var);
4188 if (val == NULL || ((varflags & VSNUL) && val[0] == '\0')) {
4195 startloc = expdest - stackblock();
4196 if (set && subtype != VSPLUS) {
4197 /* insert the value of the variable */
4199 varvalue(var, varflags & VSQUOTE, flag);
4200 if (subtype == VSLENGTH) {
4201 varlen = expdest - stackblock() - startloc;
4202 STADJUST(-varlen, expdest);
4205 if (subtype == VSLENGTH) {
4206 varlen = strlen(val);
4209 varflags & VSQUOTE ? DQSYNTAX : BASESYNTAX, quotes);
4214 if (subtype == VSPLUS)
4217 easy = ((varflags & VSQUOTE) == 0 ||
4218 (*var == '@' && shellparam.nparam != 1));
4223 expdest = cvtnum(varlen, expdest);
4230 recordregion(startloc, expdest - stackblock(), varflags & VSQUOTE);
4246 case VSTRIMRIGHTMAX:
4250 * Terminate the string and start recording the pattern
4253 STPUTC('\0', expdest);
4254 patloc = expdest - stackblock();
4255 if (subevalvar(p, NULL, patloc, subtype,
4256 startloc, varflags, quotes) == 0) {
4257 int amount = (expdest - stackblock() - patloc) + 1;
4259 STADJUST(-amount, expdest);
4261 /* Remove any recorded regions beyond start of variable */
4262 removerecordregions(startloc);
4268 if (subevalvar(p, var, 0, subtype, startloc, varflags, quotes)) {
4271 * Remove any recorded regions beyond
4274 removerecordregions(startloc);
4289 if (subtype != VSNORMAL) { /* skip to end of alternative */
4293 if ((c = *p++) == CTLESC)
4295 else if (c == CTLBACKQ || c == (CTLBACKQ | CTLQUOTE)) {
4297 argbackq = argbackq->next;
4298 } else if (c == CTLVAR) {
4299 if ((*p++ & VSTYPE) != VSNORMAL)
4301 } else if (c == CTLENDVAR) {
4312 * Perform variable and command substitution. If EXP_FULL is set, output CTLESC
4313 * characters to allow for further processing. Otherwise treat
4314 * $@ like $* since no splitting will be performed.
4317 static void argstr(char *p, int flag)
4320 int quotes = flag & (EXP_FULL | EXP_CASE); /* do CTLESC */
4323 if (*p == '~' && (flag & (EXP_TILDE | EXP_VARTILDE)))
4324 p = exptilde(p, flag);
4328 case CTLENDVAR: /* ??? */
4331 /* "$@" syntax adherence hack */
4332 if (p[0] == CTLVAR && p[2] == '@' && p[3] == '=')
4334 if ((flag & EXP_FULL) != 0)
4344 p = evalvar(p, flag);
4347 case CTLBACKQ | CTLQUOTE:
4348 expbackq(argbackq->n, c & CTLQUOTE, flag);
4349 argbackq = argbackq->next;
4351 #ifdef CONFIG_ASH_MATH_SUPPORT
4359 * sort of a hack - expand tildes in variable
4360 * assignments (after the first '=' and after ':'s).
4363 if (flag & EXP_VARTILDE && *p == '~') {
4370 p = exptilde(p, flag);
4379 static char *exptilde(char *p, int flag)
4381 char c, *startp = p;
4384 int quotes = flag & (EXP_FULL | EXP_CASE);
4386 while ((c = *p) != '\0') {
4393 if (flag & EXP_VARTILDE)
4403 if (*(startp + 1) == '\0') {
4404 if ((home = lookupvar("HOME")) == NULL)
4407 if ((pw = getpwnam(startp + 1)) == NULL)
4414 strtodest(home, SQSYNTAX, quotes);
4422 static void removerecordregions(int endoff)
4424 if (ifslastp == NULL)
4427 if (ifsfirst.endoff > endoff) {
4428 while (ifsfirst.next != NULL) {
4429 struct ifsregion *ifsp;
4432 ifsp = ifsfirst.next->next;
4433 free(ifsfirst.next);
4434 ifsfirst.next = ifsp;
4437 if (ifsfirst.begoff > endoff)
4440 ifslastp = &ifsfirst;
4441 ifsfirst.endoff = endoff;
4446 ifslastp = &ifsfirst;
4447 while (ifslastp->next && ifslastp->next->begoff < endoff)
4448 ifslastp = ifslastp->next;
4449 while (ifslastp->next != NULL) {
4450 struct ifsregion *ifsp;
4453 ifsp = ifslastp->next->next;
4454 free(ifslastp->next);
4455 ifslastp->next = ifsp;
4458 if (ifslastp->endoff > endoff)
4459 ifslastp->endoff = endoff;
4463 #ifdef CONFIG_ASH_MATH_SUPPORT
4465 * Expand arithmetic expression. Backup to start of expression,
4466 * evaluate, place result in (backed up) result, adjust string position.
4468 static void expari(int flag)
4474 int quotes = flag & (EXP_FULL | EXP_CASE);
4480 * This routine is slightly over-complicated for
4481 * efficiency. First we make sure there is
4482 * enough space for the result, which may be bigger
4483 * than the expression if we add exponentation. Next we
4484 * scan backwards looking for the start of arithmetic. If the
4485 * next previous character is a CTLESC character, then we
4486 * have to rescan starting from the beginning since CTLESC
4487 * characters have to be processed left to right.
4489 CHECKSTRSPACE(10, expdest);
4490 USTPUTC('\0', expdest);
4491 start = stackblock();
4493 while (*p != CTLARI && p >= start)
4496 error("missing CTLARI (shouldn't happen)");
4497 if (p > start && *(p - 1) == CTLESC)
4498 for (p = start; *p != CTLARI; p++)
4507 removerecordregions(begoff);
4510 result = arith(p + 2, &errcode);
4513 error("divide by zero");
4515 error("syntax error: \"%s\"\n", p + 2);
4517 snprintf(p, 12, "%d", result);
4521 recordregion(begoff, p - 1 - start, 0);
4522 result = expdest - p + 1;
4523 STADJUST(-result, expdest);
4528 * Expand stuff in backwards quotes.
4531 static void expbackq(union node *cmd, int quoted, int flag)
4533 volatile struct backcmd in;
4537 char *dest = expdest;
4538 volatile struct ifsregion saveifs;
4539 struct ifsregion *volatile savelastp;
4540 struct nodelist *volatile saveargbackq;
4542 int startloc = dest - stackblock();
4543 int syntax = quoted ? DQSYNTAX : BASESYNTAX;
4544 volatile int saveherefd;
4545 int quotes = flag & (EXP_FULL | EXP_CASE);
4546 struct jmploc jmploc;
4547 struct jmploc *volatile savehandler;
4551 /* Avoid longjmp clobbering */
4562 savelastp = ifslastp;
4563 saveargbackq = argbackq;
4564 saveherefd = herefd;
4566 if ((ex = setjmp(jmploc.loc))) {
4569 savehandler = handler;
4572 p = grabstackstr(dest);
4573 evalbackcmd(cmd, (struct backcmd *) &in);
4574 ungrabstackstr(p, dest);
4578 ifslastp = savelastp;
4579 argbackq = saveargbackq;
4580 herefd = saveherefd;
4588 if (--in.nleft < 0) {
4591 i = safe_read(in.fd, buf, sizeof buf);
4592 TRACE(("expbackq: read returns %d\n", i));
4599 if (lastc != '\0') {
4600 if (quotes && SIT(lastc, syntax) == CCTL)
4601 STPUTC(CTLESC, dest);
4602 STPUTC(lastc, dest);
4606 /* Eat all trailing newlines */
4607 for (; dest > stackblock() && dest[-1] == '\n';)
4615 exitstatus = waitforjob(in.jp);
4616 handler = savehandler;
4618 longjmp(handler->loc, 1);
4621 recordregion(startloc, dest - stackblock(), 0);
4622 TRACE(("evalbackq: size=%d: \"%.*s\"\n",
4623 (dest - stackblock()) - startloc,
4624 (dest - stackblock()) - startloc, stackblock() + startloc));
4630 subevalvar(char *p, char *str, int strloc, int subtype, int startloc,
4631 int varflags, int quotes)
4637 int saveherefd = herefd;
4638 struct nodelist *saveargbackq = argbackq;
4642 argstr(p, subtype != VSASSIGN && subtype != VSQUESTION ? EXP_CASE : 0);
4643 STACKSTRNUL(expdest);
4644 herefd = saveherefd;
4645 argbackq = saveargbackq;
4646 startp = stackblock() + startloc;
4648 str = stackblock() + strloc;
4652 setvar(str, startp, 0);
4653 amount = startp - expdest;
4654 STADJUST(amount, expdest);
4661 if (*p != CTLENDVAR) {
4662 out2fmt(snlfmt, startp);
4663 error((char *) NULL);
4665 error("%.*s: parameter %snot set", p - str - 1,
4666 str, (varflags & VSNUL) ? "null or " : nullstr);
4670 for (loc = startp; loc < str; loc++) {
4673 if (patmatch2(str, startp, quotes))
4676 if (quotes && *loc == CTLESC)
4682 for (loc = str - 1; loc >= startp;) {
4685 if (patmatch2(str, startp, quotes))
4689 if (quotes && loc > startp && *(loc - 1) == CTLESC) {
4690 for (q = startp; q < loc; q++)
4700 for (loc = str - 1; loc >= startp;) {
4701 if (patmatch2(str, loc, quotes))
4704 if (quotes && loc > startp && *(loc - 1) == CTLESC) {
4705 for (q = startp; q < loc; q++)
4714 case VSTRIMRIGHTMAX:
4715 for (loc = startp; loc < str - 1; loc++) {
4716 if (patmatch2(str, loc, quotes))
4718 if (quotes && *loc == CTLESC)
4731 amount = ((str - 1) - (loc - startp)) - expdest;
4732 STADJUST(amount, expdest);
4733 while (loc != str - 1)
4738 amount = loc - expdest;
4739 STADJUST(amount, expdest);
4740 STPUTC('\0', expdest);
4741 STADJUST(-1, expdest);
4747 * Test whether a specialized variable is set.
4750 static int varisset(char *name, int nulok)
4753 return backgndpid != -1;
4754 else if (*name == '@' || *name == '*') {
4755 if (*shellparam.p == NULL)
4761 for (av = shellparam.p; *av; av++)
4766 } else if (is_digit(*name)) {
4768 int num = atoi(name);
4770 if (num > shellparam.nparam)
4776 ap = shellparam.p[num - 1];
4778 if (nulok && (ap == NULL || *ap == '\0'))
4785 * Put a string on the stack.
4788 static void strtodest(const char *p, int syntax, int quotes)
4791 if (quotes && SIT(*p, syntax) == CCTL)
4792 STPUTC(CTLESC, expdest);
4793 STPUTC(*p++, expdest);
4798 * Add the value of a specialized variable to the stack string.
4801 static void varvalue(char *name, int quoted, int flags)
4810 int allow_split = flags & EXP_FULL;
4811 int quotes = flags & (EXP_FULL | EXP_CASE);
4813 syntax = quoted ? DQSYNTAX : BASESYNTAX;
4822 num = shellparam.nparam;
4827 expdest = cvtnum(num, expdest);
4830 for (i = 0; i < NOPTS; i++) {
4832 STPUTC(optent_letter(optlist[i]), expdest);
4836 if (allow_split && quoted) {
4837 sep = 1 << CHAR_BIT;
4842 sep = ifsset()? ifsval()[0] : ' ';
4844 sepq = SIT(sep, syntax) == CCTL;
4847 for (ap = shellparam.p; (p = *ap++) != NULL;) {
4848 strtodest(p, syntax, quotes);
4851 STPUTC(CTLESC, expdest);
4852 STPUTC(sep, expdest);
4857 strtodest(arg0, syntax, quotes);
4861 if (num > 0 && num <= shellparam.nparam) {
4862 strtodest(shellparam.p[num - 1], syntax, quotes);
4870 * Record the fact that we have to scan this region of the
4871 * string for IFS characters.
4874 static void recordregion(int start, int end, int nulonly)
4876 struct ifsregion *ifsp;
4878 if (ifslastp == NULL) {
4882 ifsp = (struct ifsregion *) xmalloc(sizeof(struct ifsregion));
4884 ifslastp->next = ifsp;
4888 ifslastp->begoff = start;
4889 ifslastp->endoff = end;
4890 ifslastp->nulonly = nulonly;
4896 * Break the argument string into pieces based upon IFS and add the
4897 * strings to the argument list. The regions of the string to be
4898 * searched for IFS characters have been stored by recordregion.
4900 static void ifsbreakup(char *string, struct arglist *arglist)
4902 struct ifsregion *ifsp;
4907 const char *ifs, *realifs;
4915 realifs = ifsset()? ifsval() : defifs;
4916 if (ifslastp != NULL) {
4919 p = string + ifsp->begoff;
4920 nulonly = ifsp->nulonly;
4921 ifs = nulonly ? nullstr : realifs;
4923 while (p < string + ifsp->endoff) {
4927 if (strchr(ifs, *p)) {
4929 ifsspc = (strchr(defifs, *p) != NULL);
4930 /* Ignore IFS whitespace at start */
4931 if (q == start && ifsspc) {
4937 sp = (struct strlist *) stalloc(sizeof *sp);
4939 *arglist->lastp = sp;
4940 arglist->lastp = &sp->next;
4944 if (p >= string + ifsp->endoff) {
4950 if (strchr(ifs, *p) == NULL) {
4953 } else if (strchr(defifs, *p) == NULL) {
4969 } while ((ifsp = ifsp->next) != NULL);
4970 if (!(*start || (!ifsspc && start > string && nulonly))) {
4975 sp = (struct strlist *) stalloc(sizeof *sp);
4977 *arglist->lastp = sp;
4978 arglist->lastp = &sp->next;
4981 static void ifsfree(void)
4983 while (ifsfirst.next != NULL) {
4984 struct ifsregion *ifsp;
4987 ifsp = ifsfirst.next->next;
4988 free(ifsfirst.next);
4989 ifsfirst.next = ifsp;
4993 ifsfirst.next = NULL;
4997 * Add a file name to the list.
5000 static void addfname(const char *name)
5003 size_t len = strlen(name) + 1;
5005 sp = (struct strlist *) stalloc(sizeof *sp);
5006 sp->text = memcpy(stalloc(len), name, len);
5008 exparg.lastp = &sp->next;
5012 * Expand shell metacharacters. At this point, the only control characters
5013 * should be escapes. The results are stored in the list exparg.
5016 #if defined(__GLIBC__) && __GLIBC__ >= 2 && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN)
5017 static void expandmeta(struct strlist *str, int flag)
5022 /* TODO - EXP_REDIR */
5027 p = preglob(str->text);
5029 switch (glob(p, 0, 0, &pglob)) {
5031 if (pglob.gl_pathv[1] == 0 && !strcmp(p, pglob.gl_pathv[0]))
5042 *exparg.lastp = str;
5043 rmescapes(str->text);
5044 exparg.lastp = &str->next;
5046 default: /* GLOB_NOSPACE */
5047 error("Out of space");
5055 * Add the result of glob(3) to the list.
5058 static void addglob(const glob_t * pglob)
5060 char **p = pglob->gl_pathv;
5068 #else /* defined(__GLIBC__) && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN) */
5069 static char *expdir;
5072 static void expandmeta(struct strlist *str, int flag)
5075 struct strlist **savelastp;
5079 /* TODO - EXP_REDIR */
5085 for (;;) { /* fast check for meta chars */
5086 if ((c = *p++) == '\0')
5088 if (c == '*' || c == '?' || c == '[' || c == '!')
5091 savelastp = exparg.lastp;
5093 if (expdir == NULL) {
5094 int i = strlen(str->text);
5096 expdir = xmalloc(i < 2048 ? 2048 : i); /* XXX */
5099 expmeta(expdir, str->text);
5103 if (exparg.lastp == savelastp) {
5108 *exparg.lastp = str;
5109 rmescapes(str->text);
5110 exparg.lastp = &str->next;
5112 *exparg.lastp = NULL;
5113 *savelastp = sp = expsort(*savelastp);
5114 while (sp->next != NULL)
5116 exparg.lastp = &sp->next;
5124 * Do metacharacter (i.e. *, ?, [...]) expansion.
5127 static void expmeta(char *enddir, char *name)
5143 for (p = name;; p++) {
5144 if (*p == '*' || *p == '?')
5146 else if (*p == '[') {
5151 while (*q == CTLQUOTEMARK)
5155 if (*q == '/' || *q == '\0')
5162 } else if (*p == '!' && p[1] == '!' && (p == name || p[-1] == '/')) {
5164 } else if (*p == '\0')
5166 else if (*p == CTLQUOTEMARK)
5168 else if (*p == CTLESC)
5176 if (metaflag == 0) { /* we've reached the end of the file name */
5177 if (enddir != expdir)
5179 for (p = name;; p++) {
5180 if (*p == CTLQUOTEMARK)
5188 if (metaflag == 0 || lstat(expdir, &statb) >= 0)
5193 if (start != name) {
5196 while (*p == CTLQUOTEMARK)
5203 if (enddir == expdir) {
5205 } else if (enddir == expdir + 1 && *expdir == '/') {
5211 if ((dirp = opendir(cp)) == NULL)
5213 if (enddir != expdir)
5215 if (*endname == 0) {
5223 while (*p == CTLQUOTEMARK)
5229 while (!int_pending() && (dp = readdir(dirp)) != NULL) {
5230 if (dp->d_name[0] == '.' && !matchdot)
5232 if (patmatch(start, dp->d_name, 0)) {
5234 strcpy(enddir, dp->d_name);
5237 for (p = enddir, cp = dp->d_name; (*p++ = *cp++) != '\0';)
5240 expmeta(p, endname);
5248 #endif /* defined(__GLIBC__) && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN) */
5252 #if !(defined(__GLIBC__) && __GLIBC__ >= 2 && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN))
5254 * Sort the results of file name expansion. It calculates the number of
5255 * strings to sort and then calls msort (short for merge sort) to do the
5259 static struct strlist *expsort(struct strlist *str)
5265 for (sp = str; sp; sp = sp->next)
5267 return msort(str, len);
5271 static struct strlist *msort(struct strlist *list, int len)
5273 struct strlist *p, *q = NULL;
5274 struct strlist **lpp;
5282 for (n = half; --n >= 0;) {
5286 q->next = NULL; /* terminate first half of list */
5287 q = msort(list, half); /* sort first half of list */
5288 p = msort(p, len - half); /* sort second half */
5291 if (strcmp(p->text, q->text) < 0) {
5294 if ((p = *lpp) == NULL) {
5301 if ((q = *lpp) == NULL) {
5314 * Returns true if the pattern matches the string.
5317 #if defined(__GLIBC__) && __GLIBC__ >= 2 && !defined(FNMATCH_BROKEN)
5318 /* squoted: string might have quote chars */
5319 static int patmatch(char *pattern, char *string, int squoted)
5324 p = preglob(pattern);
5325 q = squoted ? _rmescapes(string, RMESCAPE_ALLOC) : string;
5327 return !fnmatch(p, q, 0);
5331 static int patmatch2(char *pattern, char *string, int squoted)
5337 p = grabstackstr(expdest);
5338 res = patmatch(pattern, string, squoted);
5339 ungrabstackstr(p, expdest);
5343 static int patmatch(char *pattern, char *string, int squoted)
5345 return pmatch(pattern, string, squoted);
5349 static int pmatch(char *pattern, char *string, int squoted)
5361 if (squoted && *q == CTLESC)
5369 if (squoted && *q == CTLESC)
5376 while (c == CTLQUOTEMARK || c == '*')
5378 if (c != CTLESC && c != CTLQUOTEMARK &&
5379 c != '?' && c != '*' && c != '[') {
5381 if (squoted && *q == CTLESC && q[1] == c)
5385 if (squoted && *q == CTLESC)
5391 if (pmatch(p, q, squoted))
5393 if (squoted && *q == CTLESC)
5395 } while (*q++ != '\0');
5406 while (*endp == CTLQUOTEMARK)
5409 goto dft; /* no matching ] */
5410 if (*endp == CTLESC)
5422 if (squoted && chr == CTLESC)
5428 if (c == CTLQUOTEMARK)
5432 if (*p == '-' && p[1] != ']') {
5434 while (*p == CTLQUOTEMARK)
5438 if (chr >= c && chr <= *p)
5445 } while ((c = *p++) != ']');
5446 if (found == invert)
5451 if (squoted && *q == CTLESC)
5468 * Remove any CTLESC characters from a string.
5471 #if defined(__GLIBC__) && __GLIBC__ >= 2 && !defined(FNMATCH_BROKEN)
5472 static char *_rmescapes(char *str, int flag)
5475 static const char qchars[] = { CTLESC, CTLQUOTEMARK, 0 };
5477 p = strpbrk(str, qchars);
5483 if (flag & RMESCAPE_ALLOC) {
5484 size_t len = p - str;
5486 q = r = stalloc(strlen(p) + len + 1);
5488 memcpy(q, str, len);
5493 if (*p == CTLQUOTEMARK) {
5499 if (flag & RMESCAPE_GLOB && *p != '/') {
5509 static void rmescapes(char *str)
5514 while (*p != CTLESC && *p != CTLQUOTEMARK) {
5520 if (*p == CTLQUOTEMARK) {
5535 * See if a pattern matches in a case statement.
5538 static int casematch(union node *pattern, const char *val)
5540 struct stackmark smark;
5544 setstackmark(&smark);
5545 argbackq = pattern->narg.backquote;
5546 STARTSTACKSTR(expdest);
5548 argstr(pattern->narg.text, EXP_TILDE | EXP_CASE);
5549 STPUTC('\0', expdest);
5550 p = grabstackstr(expdest);
5551 result = patmatch(p, (char *) val, 0);
5552 popstackmark(&smark);
5560 static char *cvtnum(int num, char *buf)
5564 CHECKSTRSPACE(32, buf);
5565 len = sprintf(buf, "%d", num);
5571 * Editline and history functions (and glue).
5573 static int histcmd(int argc, char **argv)
5575 error("not compiled with history support");
5581 struct redirtab *next;
5582 short renamed[10]; /* Current ash support only 0-9 descriptors */
5583 /* char on arm (and others) can't be negative */
5586 static struct redirtab *redirlist;
5588 extern char **environ;
5593 * Initialization code.
5596 static void init(void)
5607 basepf.nextc = basepf.buf = basebuf;
5616 for (envp = environ; *envp; envp++) {
5617 if (strchr(*envp, '=')) {
5618 setvareq(*envp, VEXPORT | VTEXTFIXED);
5622 snprintf(ppid, sizeof(ppid), "%d", (int) getppid());
5623 setvar("PPID", ppid, 0);
5630 * This routine is called when an error or an interrupt occurs in an
5631 * interactive shell and control is returned to the main command loop.
5634 /* 1 == check for aliases, 2 == also check for assignments */
5635 static int checkalias; /* also used in no alias mode for check assignments */
5637 static void reset(void)
5649 parselleft = parsenleft = 0; /* clear input buffer */
5653 /* from parser.c: */
5671 * This file implements the input routines used by the parser.
5674 #ifdef CONFIG_FEATURE_COMMAND_EDITING
5675 static const char *cmdedit_prompt;
5676 static inline void putprompt(const char *s)
5681 static inline void putprompt(const char *s)
5687 #define EOF_NLEFT -99 /* value of parsenleft when EOF pushed back */
5692 * Same as pgetc(), but ignores PEOA.
5695 #ifdef CONFIG_ASH_ALIAS
5696 static int pgetc2(void)
5702 } while (c == PEOA);
5706 static inline int pgetc2(void)
5708 return pgetc_macro();
5713 * Read a line from the script.
5716 static inline char *pfgets(char *line, int len)
5722 while (--nleft > 0) {
5737 static inline int preadfd(void)
5740 char *buf = parsefile->buf;
5745 #ifdef CONFIG_FEATURE_COMMAND_EDITING
5747 if (!iflag || parsefile->fd)
5748 nr = safe_read(parsefile->fd, buf, BUFSIZ - 1);
5750 nr = cmdedit_read_input((char *) cmdedit_prompt, buf);
5754 nr = safe_read(parsefile->fd, buf, BUFSIZ - 1);
5758 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
5759 int flags = fcntl(0, F_GETFL, 0);
5761 if (flags >= 0 && flags & O_NONBLOCK) {
5762 flags &= ~O_NONBLOCK;
5763 if (fcntl(0, F_SETFL, flags) >= 0) {
5764 out2str("sh: turning off NDELAY mode\n");
5773 static void popstring(void)
5775 struct strpush *sp = parsefile->strpush;
5778 #ifdef CONFIG_ASH_ALIAS
5780 if (parsenextc[-1] == ' ' || parsenextc[-1] == '\t') {
5785 if (sp->string != sp->ap->val) {
5789 sp->ap->flag &= ~ALIASINUSE;
5790 if (sp->ap->flag & ALIASDEAD) {
5791 unalias(sp->ap->name);
5795 parsenextc = sp->prevstring;
5796 parsenleft = sp->prevnleft;
5797 /*dprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/
5798 parsefile->strpush = sp->prev;
5799 if (sp != &(parsefile->basestrpush))
5806 * Refill the input buffer and return the next input character:
5808 * 1) If a string was pushed back on the input, pop it;
5809 * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading
5810 * from a string so we can't refill the buffer, return EOF.
5811 * 3) If the is more stuff in this buffer, use it else call read to fill it.
5812 * 4) Process input up to the next newline, deleting nul characters.
5815 static int preadbuffer(void)
5821 while (parsefile->strpush) {
5822 #ifdef CONFIG_ASH_ALIAS
5823 if (parsenleft == -1 && parsefile->strpush->ap &&
5824 parsenextc[-1] != ' ' && parsenextc[-1] != '\t') {
5829 if (--parsenleft >= 0)
5830 return (*parsenextc++);
5832 if (parsenleft == EOF_NLEFT || parsefile->buf == NULL)
5837 if (parselleft <= 0) {
5838 if ((parselleft = preadfd()) <= 0) {
5839 parselleft = parsenleft = EOF_NLEFT;
5846 /* delete nul characters */
5847 for (more = 1; more;) {
5855 parsenleft = q - parsenextc;
5856 more = 0; /* Stop processing here */
5862 if (--parselleft <= 0 && more) {
5863 parsenleft = q - parsenextc - 1;
5874 out2str(parsenextc);
5879 return *parsenextc++;
5884 * Push a string back onto the input at this current parsefile level.
5885 * We handle aliases this way.
5887 static void pushstring(char *s, int len, void *ap)
5892 /*dprintf("*** calling pushstring: %s, %d\n", s, len);*/
5893 if (parsefile->strpush) {
5894 sp = xmalloc(sizeof(struct strpush));
5895 sp->prev = parsefile->strpush;
5896 parsefile->strpush = sp;
5898 sp = parsefile->strpush = &(parsefile->basestrpush);
5899 sp->prevstring = parsenextc;
5900 sp->prevnleft = parsenleft;
5901 #ifdef CONFIG_ASH_ALIAS
5902 sp->ap = (struct alias *) ap;
5904 ((struct alias *) ap)->flag |= ALIASINUSE;
5915 * Like setinputfile, but takes input from a string.
5918 static void setinputstring(char *string)
5922 parsenextc = string;
5923 parsenleft = strlen(string);
5924 parsefile->buf = NULL;
5932 * To handle the "." command, a stack of input files is used. Pushfile
5933 * adds a new entry to the stack and popfile restores the previous level.
5936 static void pushfile(void)
5938 struct parsefile *pf;
5940 parsefile->nleft = parsenleft;
5941 parsefile->lleft = parselleft;
5942 parsefile->nextc = parsenextc;
5943 parsefile->linno = plinno;
5944 pf = (struct parsefile *) xmalloc(sizeof(struct parsefile));
5945 pf->prev = parsefile;
5948 pf->basestrpush.prev = NULL;
5952 #ifdef CONFIG_ASH_JOB_CONTROL
5953 static void restartjob(struct job *);
5955 static void freejob(struct job *);
5956 static struct job *getjob(const char *);
5957 static int dowait(int, struct job *);
5961 * We keep track of whether or not fd0 has been redirected. This is for
5962 * background commands, where we want to redirect fd0 to /dev/null only
5963 * if it hasn't already been redirected.
5965 static int fd0_redirected = 0;
5967 /* Return true if fd 0 has already been redirected at least once. */
5968 static inline int fd0_redirected_p(void)
5970 return fd0_redirected != 0;
5973 static void dupredirect(const union node *, int, int fd1dup);
5975 #ifdef CONFIG_ASH_JOB_CONTROL
5977 * Turn job control on and off.
5979 * Note: This code assumes that the third arg to ioctl is a character
5980 * pointer, which is true on Berkeley systems but not System V. Since
5981 * System V doesn't have job control yet, this isn't a problem now.
5986 static void setjobctl(int enable)
5988 if (enable == jobctl || rootshell == 0)
5991 do { /* while we are in the background */
5992 initialpgrp = tcgetpgrp(2);
5993 if (initialpgrp < 0) {
5994 out2str("sh: can't access tty; job control turned off\n");
5998 if (initialpgrp == -1)
5999 initialpgrp = getpgrp();
6000 else if (initialpgrp != getpgrp()) {
6001 killpg(initialpgrp, SIGTTIN);
6008 setpgid(0, rootpid);
6009 tcsetpgrp(2, rootpid);
6010 } else { /* turning job control off */
6011 setpgid(0, initialpgrp);
6012 tcsetpgrp(2, initialpgrp);
6022 #ifdef CONFIG_ASH_JOB_CONTROL
6023 static int killcmd(int argc, char **argv)
6034 ("Usage: kill [-s sigspec | -signum | -sigspec] [pid | job]... or\n"
6035 "kill -l [exitstatus]");
6038 if (*argv[1] == '-') {
6039 signo = decode_signal(argv[1] + 1, 1);
6043 while ((c = nextopt("ls:")) != '\0')
6049 signo = decode_signal(optionarg, 1);
6051 error("invalid signal number or name: %s", optionarg);
6056 error("nextopt returned character code 0%o", c);
6063 if (!list && signo < 0)
6066 if ((signo < 0 || !*argptr) ^ list) {
6075 for (i = 1; i < NSIG; i++) {
6076 name = u_signal_names(0, &i, 1);
6082 name = u_signal_names(*argptr, &signo, -1);
6086 error("invalid signal number or exit status: %s", *argptr);
6091 if (**argptr == '%') {
6092 jp = getjob(*argptr);
6093 if (jp->jobctl == 0)
6094 error("job %s not created under job control", *argptr);
6095 pid = -jp->ps[0].pid;
6097 pid = atoi(*argptr);
6098 if (kill(pid, signo) != 0)
6099 error("%s: %m", *argptr);
6100 } while (*++argptr);
6105 static int fgcmd(int argc, char **argv)
6111 jp = getjob(argv[1]);
6112 if (jp->jobctl == 0)
6113 error("job not created under job control");
6114 pgrp = jp->ps[0].pid;
6115 ioctl(2, TIOCSPGRP, (char *) &pgrp);
6117 status = waitforjob(jp);
6122 static int bgcmd(int argc, char **argv)
6127 jp = getjob(*++argv);
6128 if (jp->jobctl == 0)
6129 error("job not created under job control");
6131 } while (--argc > 1);
6136 static void restartjob(struct job *jp)
6138 struct procstat *ps;
6141 if (jp->state == JOBDONE)
6144 killpg(jp->ps[0].pid, SIGCONT);
6145 for (ps = jp->ps, i = jp->nprocs; --i >= 0; ps++) {
6146 if (WIFSTOPPED(ps->status)) {
6155 static void showjobs(int change);
6158 static int jobscmd(int argc, char **argv)
6166 * Print a list of jobs. If "change" is nonzero, only print jobs whose
6167 * statuses have changed since the last call to showjobs.
6169 * If the shell is interrupted in the process of creating a job, the
6170 * result may be a job structure containing zero processes. Such structures
6171 * will be freed here.
6174 static void showjobs(int change)
6180 struct procstat *ps;
6184 TRACE(("showjobs(%d) called\n", change));
6185 while (dowait(0, (struct job *) NULL) > 0);
6186 for (jobno = 1, jp = jobtab; jobno <= njobs; jobno++, jp++) {
6189 if (jp->nprocs == 0) {
6193 if (change && !jp->changed)
6195 procno = jp->nprocs;
6196 for (ps = jp->ps;; ps++) { /* for each process */
6198 snprintf(s, 64, "[%d] %ld ", jobno, (long) ps->pid);
6200 snprintf(s, 64, " %ld ", (long) ps->pid);
6204 if (ps->status == -1) {
6205 /* don't print anything */
6206 } else if (WIFEXITED(ps->status)) {
6207 snprintf(s, 64, "Exit %d", WEXITSTATUS(ps->status));
6209 #ifdef CONFIG_ASH_JOB_CONTROL
6210 if (WIFSTOPPED(ps->status))
6211 i = WSTOPSIG(ps->status);
6212 else /* WIFSIGNALED(ps->status) */
6214 i = WTERMSIG(ps->status);
6215 if ((i & 0x7F) < NSIG && sys_siglist[i & 0x7F])
6216 strcpy(s, sys_siglist[i & 0x7F]);
6218 snprintf(s, 64, "Signal %d", i & 0x7F);
6219 if (WCOREDUMP(ps->status))
6220 strcat(s, " (core dumped)");
6224 printf("%*c%s\n", 30 - col >= 0 ? 30 - col : 0, ' ', ps->cmd);
6229 if (jp->state == JOBDONE) {
6237 * Mark a job structure as unused.
6240 static void freejob(struct job *jp)
6242 const struct procstat *ps;
6246 for (i = jp->nprocs, ps = jp->ps; --i >= 0; ps++) {
6247 if (ps->cmd != nullstr)
6250 if (jp->ps != &jp->ps0)
6253 #ifdef CONFIG_ASH_JOB_CONTROL
6254 if (curjob == jp - jobtab + 1)
6262 static int waitcmd(int argc, char **argv)
6270 job = getjob(*++argv);
6274 for (;;) { /* loop until process terminated or stopped */
6277 status = job->ps[job->nprocs - 1].status;
6283 if (WIFEXITED(status))
6284 retval = WEXITSTATUS(status);
6285 #ifdef CONFIG_ASH_JOB_CONTROL
6286 else if (WIFSTOPPED(status))
6287 retval = WSTOPSIG(status) + 128;
6290 /* XXX: limits number of signals */
6291 retval = WTERMSIG(status) + 128;
6296 for (jp = jobtab;; jp++) {
6297 if (jp >= jobtab + njobs) { /* no running procs */
6300 if (jp->used && jp->state == 0)
6304 if (dowait(2, 0) < 0 && errno == EINTR) {
6313 * Convert a job name to a job structure.
6316 static struct job *getjob(const char *name)
6324 #ifdef CONFIG_ASH_JOB_CONTROL
6326 if ((jobno = curjob) == 0 || jobtab[jobno - 1].used == 0)
6327 error("No current job");
6328 return &jobtab[jobno - 1];
6330 error("No current job");
6332 } else if (name[0] == '%') {
6333 if (is_digit(name[1])) {
6334 jobno = number(name + 1);
6335 if (jobno > 0 && jobno <= njobs && jobtab[jobno - 1].used != 0)
6336 return &jobtab[jobno - 1];
6337 #ifdef CONFIG_ASH_JOB_CONTROL
6338 } else if (name[1] == '%' && name[2] == '\0') {
6342 struct job *found = NULL;
6344 for (jp = jobtab, i = njobs; --i >= 0; jp++) {
6345 if (jp->used && jp->nprocs > 0
6346 && prefix(name + 1, jp->ps[0].cmd)) {
6348 error("%s: ambiguous", name);
6355 } else if (is_number(name, &pid)) {
6356 for (jp = jobtab, i = njobs; --i >= 0; jp++) {
6357 if (jp->used && jp->nprocs > 0
6358 && jp->ps[jp->nprocs - 1].pid == pid)
6362 error("No such job: %s", name);
6369 * Return a new job structure,
6372 static struct job *makejob(const union node *node, int nprocs)
6377 for (i = njobs, jp = jobtab;; jp++) {
6381 jobtab = xmalloc(4 * sizeof jobtab[0]);
6383 jp = xmalloc((njobs + 4) * sizeof jobtab[0]);
6384 memcpy(jp, jobtab, njobs * sizeof jp[0]);
6385 /* Relocate `ps' pointers */
6386 for (i = 0; i < njobs; i++)
6387 if (jp[i].ps == &jobtab[i].ps0)
6388 jp[i].ps = &jp[i].ps0;
6392 jp = jobtab + njobs;
6393 for (i = 4; --i >= 0; jobtab[njobs++].used = 0);
6405 #ifdef CONFIG_ASH_JOB_CONTROL
6406 jp->jobctl = jobctl;
6409 jp->ps = xmalloc(nprocs * sizeof(struct procstat));
6414 TRACE(("makejob(0x%lx, %d) returns %%%d\n", (long) node, nprocs,
6421 * Fork of a subshell. If we are doing job control, give the subshell its
6422 * own process group. Jp is a job structure that the job is to be added to.
6423 * N is the command that will be evaluated by the child. Both jp and n may
6424 * be NULL. The mode parameter can be one of the following:
6425 * FORK_FG - Fork off a foreground process.
6426 * FORK_BG - Fork off a background process.
6427 * FORK_NOJOB - Like FORK_FG, but don't give the process its own
6428 * process group even if job control is on.
6430 * When job control is turned off, background processes have their standard
6431 * input redirected to /dev/null (except for the second and later processes
6437 static int forkshell(struct job *jp, const union node *n, int mode)
6441 #ifdef CONFIG_ASH_JOB_CONTROL
6444 const char *devnull = _PATH_DEVNULL;
6445 const char *nullerr = "Can't open %s";
6447 TRACE(("forkshell(%%%d, 0x%lx, %d) called\n", jp - jobtab, (long) n,
6452 TRACE(("Fork failed, errno=%d\n", errno));
6454 error("Cannot fork");
6461 TRACE(("Child shell %d\n", getpid()));
6462 wasroot = rootshell;
6467 #ifdef CONFIG_ASH_JOB_CONTROL
6468 jobctl = 0; /* do job control only in root shell */
6469 if (wasroot && mode != FORK_NOJOB && mflag) {
6470 if (jp == NULL || jp->nprocs == 0)
6473 pgrp = jp->ps[0].pid;
6475 if (mode == FORK_FG) {
6476 /*** this causes superfluous TIOCSPGRPS ***/
6477 if (tcsetpgrp(2, pgrp) < 0)
6478 error("tcsetpgrp failed, errno=%d", errno);
6482 } else if (mode == FORK_BG) {
6484 if (mode == FORK_BG) {
6488 if ((jp == NULL || jp->nprocs == 0) && !fd0_redirected_p()) {
6490 if (open(devnull, O_RDONLY) != 0)
6491 error(nullerr, devnull);
6494 for (i = njobs, p = jobtab; --i >= 0; p++)
6497 if (wasroot && iflag) {
6504 #ifdef CONFIG_ASH_JOB_CONTROL
6505 if (rootshell && mode != FORK_NOJOB && mflag) {
6506 if (jp == NULL || jp->nprocs == 0)
6509 pgrp = jp->ps[0].pid;
6513 if (mode == FORK_BG)
6514 backgndpid = pid; /* set $! */
6516 struct procstat *ps = &jp->ps[jp->nprocs++];
6521 if (iflag && rootshell && n)
6522 ps->cmd = commandtext(n);
6525 TRACE(("In parent shell: child = %d\n", pid));
6532 * Wait for job to finish.
6534 * Under job control we have the problem that while a child process is
6535 * running interrupts generated by the user are sent to the child but not
6536 * to the shell. This means that an infinite loop started by an inter-
6537 * active user may be hard to kill. With job control turned off, an
6538 * interactive user may place an interactive program inside a loop. If
6539 * the interactive program catches interrupts, the user doesn't want
6540 * these interrupts to also abort the loop. The approach we take here
6541 * is to have the shell ignore interrupt signals while waiting for a
6542 * forground process to terminate, and then send itself an interrupt
6543 * signal if the child process was terminated by an interrupt signal.
6544 * Unfortunately, some programs want to do a bit of cleanup and then
6545 * exit on interrupt; unless these processes terminate themselves by
6546 * sending a signal to themselves (instead of calling exit) they will
6547 * confuse this approach.
6550 static int waitforjob(struct job *jp)
6552 #ifdef CONFIG_ASH_JOB_CONTROL
6553 int mypgrp = getpgrp();
6559 TRACE(("waitforjob(%%%d) called\n", jp - jobtab + 1));
6560 while (jp->state == 0) {
6563 #ifdef CONFIG_ASH_JOB_CONTROL
6565 if (tcsetpgrp(2, mypgrp) < 0)
6566 error("tcsetpgrp failed, errno=%d\n", errno);
6568 if (jp->state == JOBSTOPPED)
6569 curjob = jp - jobtab + 1;
6571 status = jp->ps[jp->nprocs - 1].status;
6572 /* convert to 8 bits */
6573 if (WIFEXITED(status))
6574 st = WEXITSTATUS(status);
6575 #ifdef CONFIG_ASH_JOB_CONTROL
6576 else if (WIFSTOPPED(status))
6577 st = WSTOPSIG(status) + 128;
6580 st = WTERMSIG(status) + 128;
6581 #ifdef CONFIG_ASH_JOB_CONTROL
6584 * This is truly gross.
6585 * If we're doing job control, then we did a TIOCSPGRP which
6586 * caused us (the shell) to no longer be in the controlling
6587 * session -- so we wouldn't have seen any ^C/SIGINT. So, we
6588 * intuit from the subprocess exit status whether a SIGINT
6589 * occured, and if so interrupt ourselves. Yuck. - mycroft
6591 if (WIFSIGNALED(status) && WTERMSIG(status) == SIGINT)
6594 if (jp->state == JOBDONE)
6604 * Wait for a process to terminate.
6608 * Do a wait system call. If job control is compiled in, we accept
6609 * stopped processes. If block is zero, we return a value of zero
6610 * rather than blocking.
6612 * System V doesn't have a non-blocking wait system call. It does
6613 * have a SIGCLD signal that is sent to a process when one of it's
6614 * children dies. The obvious way to use SIGCLD would be to install
6615 * a handler for SIGCLD which simply bumped a counter when a SIGCLD
6616 * was received, and have waitproc bump another counter when it got
6617 * the status of a process. Waitproc would then know that a wait
6618 * system call would not block if the two counters were different.
6619 * This approach doesn't work because if a process has children that
6620 * have not been waited for, System V will send it a SIGCLD when it
6621 * installs a signal handler for SIGCLD. What this means is that when
6622 * a child exits, the shell will be sent SIGCLD signals continuously
6623 * until is runs out of stack space, unless it does a wait call before
6624 * restoring the signal handler. The code below takes advantage of
6625 * this (mis)feature by installing a signal handler for SIGCLD and
6626 * then checking to see whether it was called. If there are any
6627 * children to be waited for, it will be.
6631 static inline int waitproc(int block, int *status)
6636 #ifdef CONFIG_ASH_JOB_CONTROL
6642 return wait3(status, flags, (struct rusage *) NULL);
6645 static int dowait(int block, struct job *job)
6649 struct procstat *sp;
6651 struct job *thisjob;
6657 TRACE(("dowait(%d) called\n", block));
6659 pid = waitproc(block, &status);
6660 TRACE(("wait returns %d, status=%d\n", pid, status));
6661 } while (!(block & 2) && pid == -1 && errno == EINTR);
6666 for (jp = jobtab; jp < jobtab + njobs; jp++) {
6670 for (sp = jp->ps; sp < jp->ps + jp->nprocs; sp++) {
6673 if (sp->pid == pid) {
6674 TRACE(("Changing status of proc %d from 0x%x to 0x%x\n",
6675 pid, sp->status, status));
6676 sp->status = status;
6679 if (sp->status == -1)
6681 else if (WIFSTOPPED(sp->status))
6684 if (stopped) { /* stopped or done */
6685 int state = done ? JOBDONE : JOBSTOPPED;
6687 if (jp->state != state) {
6688 TRACE(("Job %d: changing state from %d to %d\n",
6689 jp - jobtab + 1, jp->state, state));
6691 #ifdef CONFIG_ASH_JOB_CONTROL
6692 if (done && curjob == jp - jobtab + 1)
6693 curjob = 0; /* no current job */
6700 if (!rootshell || !iflag || (job && thisjob == job)) {
6701 core = WCOREDUMP(status);
6702 #ifdef CONFIG_ASH_JOB_CONTROL
6703 if (WIFSTOPPED(status))
6704 sig = WSTOPSIG(status);
6707 if (WIFEXITED(status))
6710 sig = WTERMSIG(status);
6712 if (sig != 0 && sig != SIGINT && sig != SIGPIPE) {
6714 out2fmt("%d: ", pid);
6715 #ifdef CONFIG_ASH_JOB_CONTROL
6716 if (sig == SIGTSTP && rootshell && iflag)
6717 out2fmt("%%%ld ", (long) (job - jobtab + 1));
6719 if (sig < NSIG && sys_siglist[sig])
6720 out2str(sys_siglist[sig]);
6722 out2fmt("Signal %d", sig);
6724 out2str(" - core dumped");
6727 TRACE(("Not printing status: status=%d, sig=%d\n", status, sig));
6730 TRACE(("Not printing status, rootshell=%d, job=0x%x\n", rootshell,
6733 thisjob->changed = 1;
6742 * return 1 if there are stopped jobs, otherwise 0
6744 static int stoppedjobs(void)
6751 for (jobno = 1, jp = jobtab; jobno <= njobs; jobno++, jp++) {
6754 if (jp->state == JOBSTOPPED) {
6755 out2str("You have stopped jobs.\n");
6765 * Return a string identifying a command (to be printed by the
6769 static char *cmdnextc;
6770 static int cmdnleft;
6772 #define MAXCMDTEXT 200
6774 static void cmdputs(const char *s)
6785 while ((c = *p++) != '\0') {
6788 else if (c == CTLVAR) {
6793 } else if (c == '=' && subtype != 0) {
6794 *q++ = "}-+?="[(subtype & VSTYPE) - VSNORMAL];
6796 } else if (c == CTLENDVAR) {
6798 } else if (c == CTLBACKQ || c == CTLBACKQ + CTLQUOTE)
6799 cmdnleft++; /* ignore it */
6802 if (--cmdnleft <= 0) {
6812 #define CMDTXT_TABLE
6815 * To collect a lot of redundant code in cmdtxt() case statements, we
6816 * implement a mini language here. Each type of node struct has an
6817 * associated instruction sequence that operates on its members via
6818 * their offsets. The instruction are pack in unsigned chars with
6819 * format IIDDDDDE where the bits are
6820 * I : part of the instruction opcode, which are
6821 * 00 : member is a pointer to another node -- process it recursively
6822 * 40 : member is a pointer to a char string -- output it
6823 * 80 : output the string whose index is stored in the data field
6824 * CC : flag signaling that this case needs external processing
6825 * D : data - either the (shifted) index of a fixed string to output or
6826 * the actual offset of the member to operate on in the struct
6827 * (since we assume bit 0 is set, the offset is not shifted)
6828 * E : flag signaling end of instruction sequence
6830 * WARNING: In order to handle larger offsets for 64bit archs, this code
6831 * assumes that no offset can be an odd number and stores the
6832 * end-of-instructions flag in bit 0.
6835 #define CMDTXT_NOMORE 0x01 /* NOTE: no offset should be odd */
6836 #define CMDTXT_CHARPTR 0x40
6837 #define CMDTXT_STRING 0x80
6838 #define CMDTXT_SPECIAL 0xC0
6839 #define CMDTXT_OFFSETMASK 0x3E
6841 static const char *const cmdtxt_strings[] = {
6842 /* 0 1 2 3 4 5 6 7 */
6843 "; ", "(", ")", " && ", " || ", "if ", "; then ", "...",
6844 /* 8 9 10 11 12 13 */
6845 "while ", "; do ", "; done", "until ", "for ", " in ...",
6847 "case ", "???", "() ...", "<<..."
6850 static const char *const redir_strings[] = {
6851 ">", "<", "<>", ">>", ">|", ">&", "<&"
6854 static const unsigned char cmdtxt_ops[] = {
6855 #define CMDTXT_NSEMI 0
6856 offsetof(union node, nbinary.ch1),
6858 offsetof(union node, nbinary.ch2) | CMDTXT_NOMORE,
6859 #define CMDTXT_NCMD (CMDTXT_NSEMI + 3)
6860 #define CMDTXT_NPIPE (CMDTXT_NCMD)
6861 #define CMDTXT_NCASE (CMDTXT_NCMD)
6862 #define CMDTXT_NTO (CMDTXT_NCMD)
6863 #define CMDTXT_NFROM (CMDTXT_NCMD)
6864 #define CMDTXT_NFROMTO (CMDTXT_NCMD)
6865 #define CMDTXT_NAPPEND (CMDTXT_NCMD)
6866 #define CMDTXT_NTOOV (CMDTXT_NCMD)
6867 #define CMDTXT_NTOFD (CMDTXT_NCMD)
6868 #define CMDTXT_NFROMFD (CMDTXT_NCMD)
6870 #define CMDTXT_NREDIR (CMDTXT_NPIPE + 1)
6871 #define CMDTXT_NBACKGND (CMDTXT_NREDIR)
6872 offsetof(union node, nredir.n) | CMDTXT_NOMORE,
6873 #define CMDTXT_NSUBSHELL (CMDTXT_NBACKGND + 1)
6874 (1 * 2) | CMDTXT_STRING,
6875 offsetof(union node, nredir.n),
6876 (2 * 2) | CMDTXT_STRING | CMDTXT_NOMORE,
6877 #define CMDTXT_NAND (CMDTXT_NSUBSHELL + 3)
6878 offsetof(union node, nbinary.ch1),
6879 (3 * 2) | CMDTXT_STRING,
6880 offsetof(union node, nbinary.ch2) | CMDTXT_NOMORE,
6881 #define CMDTXT_NOR (CMDTXT_NAND + 3)
6882 offsetof(union node, nbinary.ch1),
6883 (4 * 2) | CMDTXT_STRING,
6884 offsetof(union node, nbinary.ch2) | CMDTXT_NOMORE,
6885 #define CMDTXT_NIF (CMDTXT_NOR + 3)
6886 (5 * 2) | CMDTXT_STRING,
6887 offsetof(union node, nif.test),
6888 (6 * 2) | CMDTXT_STRING,
6889 offsetof(union node, nif.ifpart),
6890 (7 * 2) | CMDTXT_STRING | CMDTXT_NOMORE,
6891 #define CMDTXT_NWHILE (CMDTXT_NIF + 5)
6892 (8 * 2) | CMDTXT_STRING,
6893 offsetof(union node, nbinary.ch1),
6894 (9 * 2) | CMDTXT_STRING,
6895 offsetof(union node, nbinary.ch2),
6896 (10 * 2) | CMDTXT_STRING | CMDTXT_NOMORE,
6897 #define CMDTXT_NUNTIL (CMDTXT_NWHILE + 5)
6898 (11 * 2) | CMDTXT_STRING,
6899 offsetof(union node, nbinary.ch1),
6900 (9 * 2) | CMDTXT_STRING,
6901 offsetof(union node, nbinary.ch2),
6902 (10 * 2) | CMDTXT_STRING | CMDTXT_NOMORE,
6903 #define CMDTXT_NFOR (CMDTXT_NUNTIL + 5)
6904 (12 * 2) | CMDTXT_STRING,
6905 offsetof(union node, nfor.var) | CMDTXT_CHARPTR,
6906 (13 * 2) | CMDTXT_STRING | CMDTXT_NOMORE,
6907 #define CMDTXT_NCLIST (CMDTXT_NFOR + 3) /* TODO: IS THIS CORRECT??? */
6908 #define CMDTXT_NNOT (CMDTXT_NCLIST) /* TODO: IS THIS CORRECT??? */
6909 (15 * 2) | CMDTXT_STRING | CMDTXT_NOMORE,
6910 #define CMDTXT_NDEFUN (CMDTXT_NCLIST + 1)
6911 offsetof(union node, narg.text) | CMDTXT_CHARPTR,
6912 (16 * 2) | CMDTXT_STRING | CMDTXT_NOMORE,
6913 #define CMDTXT_NARG (CMDTXT_NDEFUN + 2)
6914 offsetof(union node, narg.text) | CMDTXT_CHARPTR | CMDTXT_NOMORE,
6915 #define CMDTXT_NHERE (CMDTXT_NARG + 1)
6916 #define CMDTXT_NXHERE (CMDTXT_NHERE)
6917 (17 * 2) | CMDTXT_STRING | CMDTXT_NOMORE,
6920 #if CMDTXT_NXHERE != 36
6921 #error CMDTXT_NXHERE
6924 static const unsigned char cmdtxt_ops_index[26] = {
6953 static void cmdtxt(const union node *n)
6960 p = cmdtxt_ops + (int) cmdtxt_ops_index[n->type];
6961 if ((*p & CMDTXT_SPECIAL) != CMDTXT_SPECIAL) { /* normal case */
6963 if (*p & CMDTXT_STRING) { /* output fixed string */
6964 cmdputs(cmdtxt_strings
6965 [((int) (*p & CMDTXT_OFFSETMASK) >> 1)]);
6967 const char *pf = ((const char *) n)
6968 + ((int) (*p & CMDTXT_OFFSETMASK));
6970 if (*p & CMDTXT_CHARPTR) { /* output dynamic string */
6971 cmdputs(*((const char **) pf));
6972 } else { /* output field */
6973 cmdtxt(*((const union node **) pf));
6976 } while (!(*p++ & CMDTXT_NOMORE));
6977 } else if (n->type == NCMD) {
6980 for (np = n->ncmd.args; np; np = np->narg.next) {
6985 for (np = n->ncmd.redirect; np; np = np->nfile.next) {
6989 } else if (n->type == NPIPE) {
6990 struct nodelist *lp;
6992 for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
6997 } else if (n->type == NCASE) {
6998 cmdputs(cmdtxt_strings[14]);
6999 cmdputs(n->ncase.expr->narg.text);
7000 cmdputs(cmdtxt_strings[13]);
7002 #if (NTO != 16) || (NFROM != 17) || (NFROMTO != 18) || (NAPPEND != 19) || (NTOOV != 20) || (NTOFD != 21) || (NFROMFD != 22)
7003 #error Assumption violated regarding range and ordering of NTO ... NFROMFD!
7008 assert((n->type >= NTO) && (n->type <= NFROMFD));
7011 p = redir_strings[n->type - NTO];
7012 if (n->nfile.fd != ('>' == *p)) {
7013 s[0] = n->nfile.fd + '0';
7018 if (n->type >= NTOFD) {
7019 s[0] = n->ndup.dupfd + '0';
7023 cmdtxt(n->nfile.fname);
7027 #else /* CMDTXT_TABLE */
7028 static void cmdtxt(const union node *n)
7031 struct nodelist *lp;
7040 cmdtxt(n->nbinary.ch1);
7042 cmdtxt(n->nbinary.ch2);
7045 cmdtxt(n->nbinary.ch1);
7047 cmdtxt(n->nbinary.ch2);
7050 cmdtxt(n->nbinary.ch1);
7052 cmdtxt(n->nbinary.ch2);
7055 for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
7063 cmdtxt(n->nredir.n);
7068 cmdtxt(n->nredir.n);
7072 cmdtxt(n->nif.test);
7074 cmdtxt(n->nif.ifpart);
7083 cmdtxt(n->nbinary.ch1);
7085 cmdtxt(n->nbinary.ch2);
7090 cmdputs(n->nfor.var);
7095 cmdputs(n->ncase.expr->narg.text);
7099 cmdputs(n->narg.text);
7103 for (np = n->ncmd.args; np; np = np->narg.next) {
7108 for (np = n->ncmd.redirect; np; np = np->nfile.next) {
7114 cmdputs(n->narg.text);
7145 if (n->nfile.fd != i) {
7146 s[0] = n->nfile.fd + '0';
7151 if (n->type == NTOFD || n->type == NFROMFD) {
7152 s[0] = n->ndup.dupfd + '0';
7156 cmdtxt(n->nfile.fname);
7168 #endif /* CMDTXT_TABLE */
7170 static char *commandtext(const union node *n)
7174 cmdnextc = name = xmalloc(MAXCMDTEXT);
7175 cmdnleft = MAXCMDTEXT - 4;
7182 #ifdef CONFIG_ASH_MAIL
7185 * Routines to check for mail.
7189 #define MAXMBOXES 10
7192 static int nmboxes; /* number of mailboxes */
7193 static time_t mailtime[MAXMBOXES]; /* times of mailboxes */
7198 * Print appropriate message(s) if mail has arrived. If the argument is
7199 * nozero, then the value of MAIL has changed, so we just update the
7203 static void chkmail(int silent)
7209 struct stackmark smark;
7216 setstackmark(&smark);
7217 mpath = mpathset()? mpathval() : mailval();
7218 for (i = 0; i < nmboxes; i++) {
7219 p = padvance(&mpath, nullstr);
7224 for (q = p; *q; q++);
7229 q[-1] = '\0'; /* delete trailing '/' */
7230 if (stat(p, &statb) < 0)
7232 if (statb.st_size > mailtime[i] && !silent) {
7233 out2fmt(snlfmt, pathopt ? pathopt : "you have mail");
7235 mailtime[i] = statb.st_size;
7238 popstackmark(&smark);
7241 #endif /* CONFIG_ASH_MAIL */
7246 static short profile_buf[16384];
7250 static int isloginsh = 0;
7252 static void read_profile(const char *);
7253 static void cmdloop(int);
7254 static void options(int);
7255 static void setoption(int, int);
7256 static void procargs(int, char **);
7260 * Main routine. We initialize things, parse the arguments, execute
7261 * profiles if we're a login shell, and then call cmdloop to execute
7262 * commands. The setjmp call sets up the location to jump to when an
7263 * exception occurs. When an exception occurs the variable "state"
7264 * is used to figure out how far we had gotten.
7267 int ash_main(int argc, char **argv)
7269 struct jmploc jmploc;
7270 struct stackmark smark;
7274 BLTINCMD = find_builtin("builtin");
7275 EXECCMD = find_builtin("exec");
7276 EVALCMD = find_builtin("eval");
7278 #ifndef CONFIG_FEATURE_SH_FANCY_PROMPT
7284 monitor(4, etext, profile_buf, sizeof profile_buf, 50);
7286 #if defined(linux) || defined(__GNU__)
7287 signal(SIGCHLD, SIG_DFL);
7290 if (setjmp(jmploc.loc)) {
7293 * When a shell procedure is executed, we raise the
7294 * exception EXSHELLPROC to clean up before executing
7295 * the shell procedure.
7297 if (exception == EXSHELLPROC) {
7303 if (exception == EXEXEC) {
7304 exitstatus = exerrno;
7305 } else if (exception == EXERROR) {
7308 if (state == 0 || iflag == 0 || !rootshell)
7309 exitshell(exitstatus);
7312 if (exception == EXINT) {
7315 popstackmark(&smark);
7316 FORCEINTON; /* enable interrupts */
7319 else if (state == 2)
7321 else if (state == 3)
7329 trputs("Shell args: ");
7335 setstackmark(&smark);
7336 procargs(argc, argv);
7337 #ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
7339 const char *hp = lookupvar("HISTFILE");
7342 hp = lookupvar("HOME");
7344 char *defhp = concat_path_file(hp, ".ash_history");
7345 setvar("HISTFILE", defhp, 0);
7351 if (argv[0] && argv[0][0] == '-')
7355 read_profile("/etc/profile");
7358 read_profile(".profile");
7363 if (getuid() == geteuid() && getgid() == getegid()) {
7365 if ((shinit = lookupvar("ENV")) != NULL && *shinit != '\0') {
7367 read_profile(shinit);
7374 if (sflag == 0 || minusc) {
7375 static const char sigs[] = {
7376 SIGINT, SIGQUIT, SIGHUP,
7383 #define SIGSSIZE ((sizeof(sigs)/sizeof(sigs[0])))
7386 for (i = 0; i < SIGSSIZE; i++)
7391 evalstring(minusc, 0);
7393 if (sflag || minusc == NULL) {
7394 state4: /* XXX ??? - why isn't this before the "if" statement */
7395 #ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
7397 const char *hp = lookupvar("HISTFILE");
7400 load_history ( hp );
7408 exitshell(exitstatus);
7414 * Read and execute commands. "Top" is nonzero for the top level command
7415 * loop; it turns on prompting if the shell is interactive.
7418 static void cmdloop(int top)
7421 struct stackmark smark;
7425 TRACE(("cmdloop(%d) called\n", top));
7426 setstackmark(&smark);
7434 #ifdef CONFIG_ASH_MAIL
7439 n = parsecmd(inter);
7440 /* showtree(n); DEBUG */
7442 if (!top || numeof >= 50)
7444 if (!stoppedjobs()) {
7447 out2str("\nUse \"exit\" to leave shell.\n");
7450 } else if (n != NULL && nflag == 0) {
7451 job_warning = (job_warning == 2) ? 1 : 0;
7455 popstackmark(&smark);
7456 setstackmark(&smark);
7457 if (evalskip == SKIPFILE) {
7462 popstackmark(&smark);
7468 * Read /etc/profile or .profile. Return on error.
7471 static void read_profile(const char *name)
7478 if ((fd = open(name, O_RDONLY)) >= 0)
7483 /* -q turns off -x and -v just when executing init files */
7484 /* Note: Might do a little redundant work, but reduces code size. */
7499 * Read a file containing shell functions.
7502 static void readcmdfile(const char *name)
7507 if ((fd = open(name, O_RDONLY)) >= 0)
7510 error("Can't open %s", name);
7519 * Take commands from a file. To be compatable we should do a path
7520 * search for the file, which is necessary to find sub-commands.
7523 static inline char *find_dot_file(char *mybasename)
7526 const char *path = pathval();
7529 /* don't try this for absolute or relative paths */
7530 if (strchr(mybasename, '/'))
7533 while ((fullname = padvance(&path, mybasename)) != NULL) {
7534 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
7536 * Don't bother freeing here, since it will
7537 * be freed by the caller.
7541 stunalloc(fullname);
7544 /* not found in the PATH */
7545 error("%s: not found", mybasename);
7549 static int dotcmd(int argc, char **argv)
7552 volatile struct shparam saveparam;
7556 for (sp = cmdenviron; sp; sp = sp->next)
7557 setvareq(xstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
7559 if (argc >= 2) { /* That's what SVR2 does */
7561 struct stackmark smark;
7563 setstackmark(&smark);
7564 fullname = find_dot_file(argv[1]);
7567 saveparam = shellparam;
7568 shellparam.malloc = 0;
7569 shellparam.nparam = argc - 2;
7570 shellparam.p = argv + 2;
7573 setinputfile(fullname, 1);
7574 commandname = fullname;
7579 freeparam(&shellparam);
7580 shellparam = saveparam;
7583 popstackmark(&smark);
7589 static int exitcmd(int argc, char **argv)
7595 exitstatus = number(argv[1]);
7597 exitstatus = oexitstatus;
7598 exitshell(exitstatus);
7602 static pointer stalloc(int nbytes)
7606 nbytes = ALIGN(nbytes);
7607 if (nbytes > stacknleft) {
7609 struct stack_block *sp;
7612 if (blocksize < MINSIZE)
7613 blocksize = MINSIZE;
7615 sp = xmalloc(sizeof(struct stack_block) - MINSIZE + blocksize);
7617 stacknxt = sp->space;
7618 stacknleft = blocksize;
7624 stacknleft -= nbytes;
7629 static void stunalloc(pointer p)
7632 if (p == NULL) { /*DEBUG */
7633 write(2, "stunalloc\n", 10);
7637 if (!(stacknxt >= (char *) p && (char *) p >= stackp->space)) {
7640 stacknleft += stacknxt - (char *) p;
7645 static void setstackmark(struct stackmark *mark)
7647 mark->stackp = stackp;
7648 mark->stacknxt = stacknxt;
7649 mark->stacknleft = stacknleft;
7650 mark->marknext = markp;
7655 static void popstackmark(struct stackmark *mark)
7657 struct stack_block *sp;
7660 markp = mark->marknext;
7661 while (stackp != mark->stackp) {
7666 stacknxt = mark->stacknxt;
7667 stacknleft = mark->stacknleft;
7673 * When the parser reads in a string, it wants to stick the string on the
7674 * stack and only adjust the stack pointer when it knows how big the
7675 * string is. Stackblock (defined in stack.h) returns a pointer to a block
7676 * of space on top of the stack and stackblocklen returns the length of
7677 * this block. Growstackblock will grow this space by at least one byte,
7678 * possibly moving it (like realloc). Grabstackblock actually allocates the
7679 * part of the block that has been used.
7682 static void growstackblock(void)
7685 int newlen = ALIGN(stacknleft * 2 + 100);
7686 char *oldspace = stacknxt;
7687 int oldlen = stacknleft;
7688 struct stack_block *sp;
7689 struct stack_block *oldstackp;
7691 if (stacknxt == stackp->space && stackp != &stackbase) {
7696 sp = xrealloc((pointer) sp,
7697 sizeof(struct stack_block) - MINSIZE + newlen);
7700 stacknxt = sp->space;
7701 stacknleft = newlen;
7703 /* Stack marks pointing to the start of the old block
7704 * must be relocated to point to the new block
7706 struct stackmark *xmark;
7709 while (xmark != NULL && xmark->stackp == oldstackp) {
7710 xmark->stackp = stackp;
7711 xmark->stacknxt = stacknxt;
7712 xmark->stacknleft = stacknleft;
7713 xmark = xmark->marknext;
7718 p = stalloc(newlen);
7719 memcpy(p, oldspace, oldlen);
7720 stacknxt = p; /* free the space */
7721 stacknleft += newlen; /* we just allocated */
7727 static inline void grabstackblock(int len)
7737 * The following routines are somewhat easier to use that the above.
7738 * The user declares a variable of type STACKSTR, which may be declared
7739 * to be a register. The macro STARTSTACKSTR initializes things. Then
7740 * the user uses the macro STPUTC to add characters to the string. In
7741 * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
7742 * grown as necessary. When the user is done, she can just leave the
7743 * string there and refer to it using stackblock(). Or she can allocate
7744 * the space for it using grabstackstr(). If it is necessary to allow
7745 * someone else to use the stack temporarily and then continue to grow
7746 * the string, the user should use grabstack to allocate the space, and
7747 * then call ungrabstr(p) to return to the previous mode of operation.
7749 * USTPUTC is like STPUTC except that it doesn't check for overflow.
7750 * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
7751 * is space for at least one character.
7755 static char *growstackstr(void)
7757 int len = stackblocksize();
7759 if (herefd >= 0 && len >= 1024) {
7760 xwrite(herefd, stackblock(), len);
7761 sstrnleft = len - 1;
7762 return stackblock();
7765 sstrnleft = stackblocksize() - len - 1;
7766 return stackblock() + len;
7771 * Called from CHECKSTRSPACE.
7774 static char *makestrspace(size_t newlen)
7776 int len = stackblocksize() - sstrnleft;
7780 sstrnleft = stackblocksize() - len;
7781 } while (sstrnleft < newlen);
7782 return stackblock() + len;
7787 static void ungrabstackstr(char *s, char *p)
7789 stacknleft += stacknxt - s;
7791 sstrnleft = stacknleft - (p - s);
7795 * Miscelaneous builtins.
7801 #if !defined(__GLIBC__) || __GLIBC__ == 2 && __GLIBC_MINOR__ < 1
7802 typedef long rlim_t;
7808 * The read builtin. The -e option causes backslashes to escape the
7809 * following character.
7811 * This uses unbuffered input, which may be avoidable in some cases.
7814 static int readcmd(int argc, char **argv)
7829 while ((i = nextopt("p:r")) != '\0') {
7835 if (prompt && isatty(0)) {
7836 out2str(prompt); /* read without cmdedit */
7839 if (*(ap = argptr) == NULL)
7841 if ((ifs = bltinlookup("IFS")) == NULL)
7848 if (read(0, &c, 1) != 1) {
7860 if (!rflag && c == '\\') {
7866 if (startword && *ifs == ' ' && strchr(ifs, c)) {
7870 if (backslash && c == '\\') {
7871 if (read(0, &c, 1) != 1) {
7876 } else if (ap[1] != NULL && strchr(ifs, c) != NULL) {
7878 setvar(*ap, stackblock(), 0);
7887 /* Remove trailing blanks */
7888 while (stackblock() <= --p && strchr(ifs, *p) != NULL)
7890 setvar(*ap, stackblock(), 0);
7891 while (*++ap != NULL)
7892 setvar(*ap, nullstr, 0);
7898 static int umaskcmd(int argc, char **argv)
7900 static const char permuser[3] = "ugo";
7901 static const char permmode[3] = "rwx";
7902 static const short int permmask[] = {
7903 S_IRUSR, S_IWUSR, S_IXUSR,
7904 S_IRGRP, S_IWGRP, S_IXGRP,
7905 S_IROTH, S_IWOTH, S_IXOTH
7911 int symbolic_mode = 0;
7913 while (nextopt("S") != '\0') {
7922 if ((ap = *argptr) == NULL) {
7923 if (symbolic_mode) {
7927 for (i = 0; i < 3; i++) {
7932 for (j = 0; j < 3; j++) {
7933 if ((mask & permmask[3 * i + j]) == 0) {
7942 printf("%.4o\n", mask);
7945 if (is_digit((unsigned char) *ap)) {
7948 if (*ap >= '8' || *ap < '0')
7949 error("Illegal number: %s", argv[1]);
7950 mask = (mask << 3) + (*ap - '0');
7951 } while (*++ap != '\0');
7954 mask = ~mask & 0777;
7955 if (!parse_mode(ap, &mask)) {
7956 error("Illegal mode: %s", ap);
7958 umask(~mask & 0777);
7967 * This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and
7968 * Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with
7969 * ash by J.T. Conklin.
7977 short factor; /* multiply by to get rlim_{cur,max} values */
7980 static const struct limits limits[] = {
7982 {"time(seconds)", RLIMIT_CPU, 1},
7985 {"file(blocks)", RLIMIT_FSIZE, 512},
7988 {"data(kbytes)", RLIMIT_DATA, 1024},
7991 {"stack(kbytes)", RLIMIT_STACK, 1024},
7994 {"coredump(blocks)", RLIMIT_CORE, 512},
7997 {"memory(kbytes)", RLIMIT_RSS, 1024},
7999 #ifdef RLIMIT_MEMLOCK
8000 {"locked memory(kbytes)", RLIMIT_MEMLOCK, 1024},
8003 {"process(processes)", RLIMIT_NPROC, 1},
8005 #ifdef RLIMIT_NOFILE
8006 {"nofiles(descriptors)", RLIMIT_NOFILE, 1},
8009 {"vmemory(kbytes)", RLIMIT_VMEM, 1024},
8012 {"swap(kbytes)", RLIMIT_SWAP, 1024},
8017 static int ulimitcmd(int argc, char **argv)
8019 static const char unlimited_string[] = "unlimited";
8022 enum { SOFT = 0x1, HARD = 0x2 } how = SOFT | HARD;
8023 const struct limits *l;
8026 struct rlimit limit;
8030 while ((optc = nextopt("HSa"
8049 #ifdef RLIMIT_MEMLOCK
8055 #ifdef RLIMIT_NOFILE
8067 } else if (optc == 'S') {
8069 } else if (optc == 'a') {
8076 for (l = limits; l->name; l++) {
8077 if (l->name[0] == what)
8079 if (l->name[1] == 'w' && what == 'w')
8083 set = *argptr ? 1 : 0;
8087 if (all || argptr[1])
8088 error("too many arguments");
8089 if (strcmp(p, unlimited_string) == 0)
8090 val = RLIM_INFINITY;
8094 while ((c = *p++) >= '0' && c <= '9') {
8095 val = (val * 10) + (long) (c - '0');
8096 if (val < (rlim_t) 0)
8100 error("bad number");
8106 for (l = limits; l->name; l++) {
8107 printf("%-20s ", l->name);
8108 getrlimit(l->cmd, &limit);
8111 val = limit.rlim_cur;
8112 else if (how & HARD)
8113 val = limit.rlim_max;
8115 if (val == RLIM_INFINITY)
8116 puts(unlimited_string);
8119 printf("%lld\n", (long long) val);
8132 getrlimit(l->cmd, &limit);
8134 limit.rlim_max = val;
8136 limit.rlim_cur = val;
8137 if (setrlimit(l->cmd, &limit) < 0)
8138 error("error setting limit (%m)");
8143 * prefix -- see if pfx is a prefix of string.
8146 static int prefix(char const *pfx, char const *string)
8149 if (*pfx++ != *string++)
8156 * Return true if s is a string of digits, and save munber in intptr
8160 static int is_number(const char *p, int *intptr)
8168 ret += digit_val(*p);
8170 } while (*p != '\0');
8177 * Convert a string of digits to an integer, printing an error message on
8181 static int number(const char *s)
8185 if (!is_number(s, &i))
8186 error("Illegal number: %s", s);
8191 * Produce a possibly single quoted string suitable as input to the shell.
8192 * The return string is allocated on the stack.
8195 static char *single_quote(const char *s)
8203 size_t len1, len1p, len2, len2p;
8205 len1 = strcspn(s, "'");
8206 len2 = strspn(s + len1, "'");
8208 len1p = len1 ? len1 + 2 : len1;
8209 len2p = len2 + ((len2 < 2) ? len2 : 2);
8211 CHECKSTRSPACE(len1p + len2p + 1, p);
8216 memcpy(p + 1, s, len1);
8224 memcpy(q + 1, s, len2);
8227 } else if (len2 == 1) {
8233 STADJUST(len1p + len2p, p);
8238 return grabstackstr(p);
8242 * Routine for dealing with parsed shell commands.
8246 static void sizenodelist(const struct nodelist *);
8247 static struct nodelist *copynodelist(const struct nodelist *);
8248 static char *nodesavestr(const char *);
8250 #define CALCSIZE_TABLE
8251 #define COPYNODE_TABLE
8252 #if defined(CALCSIZE_TABLE) || defined(COPYNODE_TABLE)
8254 * To collect a lot of redundant code in case statements for copynode()
8255 * and calcsize(), we implement a mini language here. Each type of node
8256 * struct has an associated instruction sequence that operates on its
8257 * members via their offsets. The instruction are pack in unsigned chars
8258 * with format IIDDDDDE where the bits are
8259 * I : part of the instruction opcode, which are
8260 * 00 : member is a pointer to another node
8261 * 40 : member is an integer
8262 * 80 : member is a pointer to a nodelist
8263 * CC : member is a pointer to a char string
8264 * D : data - the actual offset of the member to operate on in the struct
8265 * (since we assume bit 0 is set, it is not shifted)
8266 * E : flag signaling end of instruction sequence
8268 * WARNING: In order to handle larger offsets for 64bit archs, this code
8269 * assumes that no offset can be an odd number and stores the
8270 * end-of-instructions flag in bit 0.
8273 #define NODE_INTEGER 0x40
8274 #define NODE_NODELIST 0x80
8275 #define NODE_CHARPTR 0xC0
8276 #define NODE_NOMORE 0x01 /* Note: no offset should be odd (aligned) */
8277 #define NODE_MBRMASK 0xC0
8278 #define NODE_OFFSETMASK 0x3E
8280 static const unsigned char copynode_ops[35] = {
8281 #define COPYNODE_OPS0 0
8282 offsetof(union node, nbinary.ch2),
8283 offsetof(union node, nbinary.ch1) | NODE_NOMORE,
8284 #define COPYNODE_OPS1 (COPYNODE_OPS0 + 2)
8285 offsetof(union node, ncmd.redirect),
8286 offsetof(union node, ncmd.args),
8287 offsetof(union node, ncmd.assign),
8288 offsetof(union node, ncmd.backgnd) | NODE_INTEGER | NODE_NOMORE,
8289 #define COPYNODE_OPS2 (COPYNODE_OPS1 + 4)
8290 offsetof(union node, npipe.cmdlist) | NODE_NODELIST,
8291 offsetof(union node, npipe.backgnd) | NODE_INTEGER | NODE_NOMORE,
8292 #define COPYNODE_OPS3 (COPYNODE_OPS2 + 2)
8293 offsetof(union node, nredir.redirect),
8294 offsetof(union node, nredir.n) | NODE_NOMORE,
8295 #define COPYNODE_OPS4 (COPYNODE_OPS3 + 2)
8296 offsetof(union node, nif.elsepart),
8297 offsetof(union node, nif.ifpart),
8298 offsetof(union node, nif.test) | NODE_NOMORE,
8299 #define COPYNODE_OPS5 (COPYNODE_OPS4 + 3)
8300 offsetof(union node, nfor.var) | NODE_CHARPTR,
8301 offsetof(union node, nfor.body),
8302 offsetof(union node, nfor.args) | NODE_NOMORE,
8303 #define COPYNODE_OPS6 (COPYNODE_OPS5 + 3)
8304 offsetof(union node, ncase.cases),
8305 offsetof(union node, ncase.expr) | NODE_NOMORE,
8306 #define COPYNODE_OPS7 (COPYNODE_OPS6 + 2)
8307 offsetof(union node, nclist.body),
8308 offsetof(union node, nclist.pattern),
8309 offsetof(union node, nclist.next) | NODE_NOMORE,
8310 #define COPYNODE_OPS8 (COPYNODE_OPS7 + 3)
8311 offsetof(union node, narg.backquote) | NODE_NODELIST,
8312 offsetof(union node, narg.text) | NODE_CHARPTR,
8313 offsetof(union node, narg.next) | NODE_NOMORE,
8314 #define COPYNODE_OPS9 (COPYNODE_OPS8 + 3)
8315 offsetof(union node, nfile.fname),
8316 offsetof(union node, nfile.fd) | NODE_INTEGER,
8317 offsetof(union node, nfile.next) | NODE_NOMORE,
8318 #define COPYNODE_OPS10 (COPYNODE_OPS9 + 3)
8319 offsetof(union node, ndup.vname),
8320 offsetof(union node, ndup.dupfd) | NODE_INTEGER,
8321 offsetof(union node, ndup.fd) | NODE_INTEGER,
8322 offsetof(union node, ndup.next) | NODE_NOMORE,
8323 #define COPYNODE_OPS11 (COPYNODE_OPS10 + 4)
8324 offsetof(union node, nhere.doc),
8325 offsetof(union node, nhere.fd) | NODE_INTEGER,
8326 offsetof(union node, nhere.next) | NODE_NOMORE,
8327 #define COPYNODE_OPS12 (COPYNODE_OPS11 + 3)
8328 offsetof(union node, nnot.com) | NODE_NOMORE,
8331 #if COPYNODE_OPS12 != 34
8332 #error COPYNODE_OPS12 is incorrect
8335 static const unsigned char copynode_ops_index[26] = {
8336 COPYNODE_OPS0, /* NSEMI */
8337 COPYNODE_OPS1, /* NCMD */
8338 COPYNODE_OPS2, /* NPIPE */
8339 COPYNODE_OPS3, /* NREDIR */
8340 COPYNODE_OPS3, /* NBACKGND */
8341 COPYNODE_OPS3, /* NSUBSHELL */
8342 COPYNODE_OPS0, /* NAND */
8343 COPYNODE_OPS0, /* NOR */
8344 COPYNODE_OPS4, /* NIF */
8345 COPYNODE_OPS0, /* NWHILE */
8346 COPYNODE_OPS0, /* NUNTIL */
8347 COPYNODE_OPS5, /* NFOR */
8348 COPYNODE_OPS6, /* NCASE */
8349 COPYNODE_OPS7, /* NCLIST */
8350 COPYNODE_OPS8, /* NDEFUN */
8351 COPYNODE_OPS8, /* NARG */
8352 COPYNODE_OPS9, /* NTO */
8353 COPYNODE_OPS9, /* NFROM */
8354 COPYNODE_OPS9, /* NFROMTO */
8355 COPYNODE_OPS9, /* NAPPEND */
8356 COPYNODE_OPS9, /* NTOOV */
8357 COPYNODE_OPS10, /* NTOFD */
8358 COPYNODE_OPS10, /* NFROMFD */
8359 COPYNODE_OPS11, /* NHERE */
8360 COPYNODE_OPS11, /* NXHERE */
8361 COPYNODE_OPS12, /* NNOT */
8364 #if NODE_CHARPTR != NODE_MBRMASK
8365 #error NODE_CHARPTR != NODE_MBRMASK!!!
8367 #endif /* defined(CALCSIZE_TABLE) || defined(COPYNODE_TABLE) */
8369 #ifdef COPYNODE_TABLE
8370 static union node *copynode(const union node *n)
8373 const unsigned char *p;
8379 new->type = n->type;
8380 funcblock = (char *) funcblock + (int) nodesize[n->type];
8381 p = copynode_ops + (int) copynode_ops_index[n->type];
8383 char *nn = ((char *) new) + ((int) (*p & NODE_OFFSETMASK));
8384 const char *no = ((const char *) n) + ((int) (*p & NODE_OFFSETMASK));
8386 if (!(*p & NODE_MBRMASK)) { /* standard node */
8387 *((union node **) nn) = copynode(*((const union node **) no));
8388 } else if ((*p & NODE_MBRMASK) == NODE_CHARPTR) { /* string */
8389 *((const char **) nn) = nodesavestr(*((const char **) no));
8390 } else if (*p & NODE_NODELIST) { /* nodelist */
8391 *((struct nodelist **) nn)
8392 = copynodelist(*((const struct nodelist **) no));
8393 } else { /* integer */
8394 *((int *) nn) = *((int *) no);
8396 } while (!(*p++ & NODE_NOMORE));
8399 #else /* COPYNODE_TABLE */
8400 static union node *copynode(const union node *n)
8407 funcblock = (char *) funcblock + nodesize[n->type];
8414 new->nbinary.ch2 = copynode(n->nbinary.ch2);
8415 new->nbinary.ch1 = copynode(n->nbinary.ch1);
8418 new->ncmd.redirect = copynode(n->ncmd.redirect);
8419 new->ncmd.args = copynode(n->ncmd.args);
8420 new->ncmd.assign = copynode(n->ncmd.assign);
8421 new->ncmd.backgnd = n->ncmd.backgnd;
8424 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
8425 new->npipe.backgnd = n->npipe.backgnd;
8430 new->nredir.redirect = copynode(n->nredir.redirect);
8431 new->nredir.n = copynode(n->nredir.n);
8434 new->nif.elsepart = copynode(n->nif.elsepart);
8435 new->nif.ifpart = copynode(n->nif.ifpart);
8436 new->nif.test = copynode(n->nif.test);
8439 new->nfor.var = nodesavestr(n->nfor.var);
8440 new->nfor.body = copynode(n->nfor.body);
8441 new->nfor.args = copynode(n->nfor.args);
8444 new->ncase.cases = copynode(n->ncase.cases);
8445 new->ncase.expr = copynode(n->ncase.expr);
8448 new->nclist.body = copynode(n->nclist.body);
8449 new->nclist.pattern = copynode(n->nclist.pattern);
8450 new->nclist.next = copynode(n->nclist.next);
8454 new->narg.backquote = copynodelist(n->narg.backquote);
8455 new->narg.text = nodesavestr(n->narg.text);
8456 new->narg.next = copynode(n->narg.next);
8463 new->nfile.fname = copynode(n->nfile.fname);
8464 new->nfile.fd = n->nfile.fd;
8465 new->nfile.next = copynode(n->nfile.next);
8469 new->ndup.vname = copynode(n->ndup.vname);
8470 new->ndup.dupfd = n->ndup.dupfd;
8471 new->ndup.fd = n->ndup.fd;
8472 new->ndup.next = copynode(n->ndup.next);
8476 new->nhere.doc = copynode(n->nhere.doc);
8477 new->nhere.fd = n->nhere.fd;
8478 new->nhere.next = copynode(n->nhere.next);
8481 new->nnot.com = copynode(n->nnot.com);
8484 new->type = n->type;
8487 #endif /* COPYNODE_TABLE */
8489 #ifdef CALCSIZE_TABLE
8490 static void calcsize(const union node *n)
8492 const unsigned char *p;
8496 funcblocksize += (int) nodesize[n->type];
8498 p = copynode_ops + (int) copynode_ops_index[n->type];
8500 const char *no = ((const char *) n) + ((int) (*p & NODE_OFFSETMASK));
8502 if (!(*p & NODE_MBRMASK)) { /* standard node */
8503 calcsize(*((const union node **) no));
8504 } else if ((*p & NODE_MBRMASK) == NODE_CHARPTR) { /* string */
8505 funcstringsize += strlen(*((const char **) no)) + 1;
8506 } else if (*p & NODE_NODELIST) { /* nodelist */
8507 sizenodelist(*((const struct nodelist **) no));
8508 } /* else integer -- ignore */
8509 } while (!(*p++ & NODE_NOMORE));
8511 #else /* CALCSIZE_TABLE */
8512 static void calcsize(const union node *n)
8516 funcblocksize += nodesize[n->type];
8523 calcsize(n->nbinary.ch2);
8524 calcsize(n->nbinary.ch1);
8527 calcsize(n->ncmd.redirect);
8528 calcsize(n->ncmd.args);
8529 calcsize(n->ncmd.assign);
8532 sizenodelist(n->npipe.cmdlist);
8537 calcsize(n->nredir.redirect);
8538 calcsize(n->nredir.n);
8541 calcsize(n->nif.elsepart);
8542 calcsize(n->nif.ifpart);
8543 calcsize(n->nif.test);
8546 funcstringsize += strlen(n->nfor.var) + 1;
8547 calcsize(n->nfor.body);
8548 calcsize(n->nfor.args);
8551 calcsize(n->ncase.cases);
8552 calcsize(n->ncase.expr);
8555 calcsize(n->nclist.body);
8556 calcsize(n->nclist.pattern);
8557 calcsize(n->nclist.next);
8561 sizenodelist(n->narg.backquote);
8562 funcstringsize += strlen(n->narg.text) + 1;
8563 calcsize(n->narg.next);
8570 calcsize(n->nfile.fname);
8571 calcsize(n->nfile.next);
8575 calcsize(n->ndup.vname);
8576 calcsize(n->ndup.next);
8580 calcsize(n->nhere.doc);
8581 calcsize(n->nhere.next);
8584 calcsize(n->nnot.com);
8588 #endif /* CALCSIZE_TABLE */
8590 static void sizenodelist(const struct nodelist *lp)
8593 funcblocksize += ALIGN(sizeof(struct nodelist));
8600 static struct nodelist *copynodelist(const struct nodelist *lp)
8602 struct nodelist *start;
8603 struct nodelist **lpp;
8608 funcblock = (char *) funcblock + ALIGN(sizeof(struct nodelist));
8609 (*lpp)->n = copynode(lp->n);
8611 lpp = &(*lpp)->next;
8618 static char *nodesavestr(const char *s)
8621 char *q = funcstring;
8622 char *rtn = funcstring;
8624 while ((*q++ = *p++) != '\0')
8630 #ifdef CONFIG_ASH_GETOPTS
8631 static int getopts(char *, char *, char **, int *, int *);
8635 * Process the shell command line arguments.
8638 static void procargs(int argc, char **argv)
8645 for (i = 0; i < NOPTS; i++)
8648 if (*argptr == NULL && minusc == NULL)
8650 if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
8654 for (i = 0; i < NOPTS; i++)
8655 if (optent_val(i) == 2)
8658 if (sflag == 0 && minusc == NULL) {
8659 commandname = argv[0];
8661 setinputfile(arg0, 0);
8664 /* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
8665 if (argptr && minusc && *argptr)
8668 shellparam.p = argptr;
8669 shellparam.optind = 1;
8670 shellparam.optoff = -1;
8671 /* assert(shellparam.malloc == 0 && shellparam.nparam == 0); */
8673 shellparam.nparam++;
8682 * Process shell options. The global variable argptr contains a pointer
8683 * to the argument list; we advance it past the options.
8686 static inline void minus_o(const char *name, int val)
8691 out1str("Current option settings\n");
8692 for (i = 0; i < NOPTS; i++)
8693 printf("%-16s%s\n", optent_name(optlist[i]),
8694 optent_val(i) ? "on" : "off");
8696 for (i = 0; i < NOPTS; i++)
8697 if (equal(name, optent_name(optlist[i]))) {
8698 setoption(optent_letter(optlist[i]), val);
8701 error("Illegal option -o %s", name);
8706 static void options(int cmdline)
8714 while ((p = *argptr) != NULL) {
8716 if ((c = *p++) == '-') {
8718 if (p[0] == '\0' || (p[0] == '-' && p[1] == '\0')) {
8720 /* "-" means turn off -x and -v */
8723 /* "--" means reset params */
8724 else if (*argptr == NULL)
8727 break; /* "-" or "--" terminates options */
8729 } else if (c == '+') {
8735 while ((c = *p++) != '\0') {
8736 if (c == 'c' && cmdline) {
8739 #ifdef NOHACK /* removing this code allows sh -ce 'foo' for compat */
8743 if (q == NULL || minusc != NULL)
8744 error("Bad -c option");
8749 } else if (c == 'o') {
8750 minus_o(*argptr, val);
8753 } else if (cmdline && (c == '-')) { // long options
8754 if (strcmp(p, "login") == 0)
8765 static void setoption(int flag, int val)
8769 for (i = 0; i < NOPTS; i++)
8770 if (optent_letter(optlist[i]) == flag) {
8771 optent_val(i) = val;
8773 /* #%$ hack for ksh semantics */
8776 else if (flag == 'E')
8781 error("Illegal option -%c", flag);
8788 * Set the shell parameters.
8791 static void setparam(char **argv)
8797 for (nparam = 0; argv[nparam]; nparam++);
8798 ap = newparam = xmalloc((nparam + 1) * sizeof *ap);
8800 *ap++ = xstrdup(*argv++);
8803 freeparam(&shellparam);
8804 shellparam.malloc = 1;
8805 shellparam.nparam = nparam;
8806 shellparam.p = newparam;
8807 shellparam.optind = 1;
8808 shellparam.optoff = -1;
8813 * Free the list of positional parameters.
8816 static void freeparam(volatile struct shparam *param)
8820 if (param->malloc) {
8821 for (ap = param->p; *ap; ap++)
8830 * The shift builtin command.
8833 static int shiftcmd(int argc, char **argv)
8840 n = number(argv[1]);
8841 if (n > shellparam.nparam)
8842 error("can't shift that many");
8844 shellparam.nparam -= n;
8845 for (ap1 = shellparam.p; --n >= 0; ap1++) {
8846 if (shellparam.malloc)
8850 while ((*ap2++ = *ap1++) != NULL);
8851 shellparam.optind = 1;
8852 shellparam.optoff = -1;
8860 * The set command builtin.
8863 static int setcmd(int argc, char **argv)
8866 return showvarscmd(argc, argv);
8870 if (*argptr != NULL) {
8878 static void getoptsreset(const char *value)
8880 shellparam.optind = number(value);
8881 shellparam.optoff = -1;
8884 #ifdef CONFIG_LOCALE_SUPPORT
8885 static void change_lc_all(const char *value)
8887 if (value != 0 && *value != 0)
8888 setlocale(LC_ALL, value);
8891 static void change_lc_ctype(const char *value)
8893 if (value != 0 && *value != 0)
8894 setlocale(LC_CTYPE, value);
8899 #ifdef CONFIG_ASH_GETOPTS
8901 * The getopts builtin. Shellparam.optnext points to the next argument
8902 * to be processed. Shellparam.optptr points to the next character to
8903 * be processed in the current argument. If shellparam.optnext is NULL,
8904 * then it's the first time getopts has been called.
8907 static int getoptscmd(int argc, char **argv)
8912 error("Usage: getopts optstring var [arg]");
8913 else if (argc == 3) {
8914 optbase = shellparam.p;
8915 if (shellparam.optind > shellparam.nparam + 1) {
8916 shellparam.optind = 1;
8917 shellparam.optoff = -1;
8921 if (shellparam.optind > argc - 2) {
8922 shellparam.optind = 1;
8923 shellparam.optoff = -1;
8927 return getopts(argv[1], argv[2], optbase, &shellparam.optind,
8928 &shellparam.optoff);
8932 * Safe version of setvar, returns 1 on success 0 on failure.
8935 static int setvarsafe(const char *name, const char *val, int flags)
8937 struct jmploc jmploc;
8938 struct jmploc *volatile savehandler = handler;
8945 if (setjmp(jmploc.loc))
8949 setvar(name, val, flags);
8951 handler = savehandler;
8956 getopts(char *optstr, char *optvar, char **optfirst, int *myoptind,
8964 char **optnext = optfirst + *myoptind - 1;
8966 if (*myoptind <= 1 || *optoff < 0 || !(*(optnext - 1)) ||
8967 strlen(*(optnext - 1)) < *optoff)
8970 p = *(optnext - 1) + *optoff;
8971 if (p == NULL || *p == '\0') {
8972 /* Current word is done, advance */
8973 if (optnext == NULL)
8976 if (p == NULL || *p != '-' || *++p == '\0') {
8978 *myoptind = optnext - optfirst + 1;
8984 if (p[0] == '-' && p[1] == '\0') /* check for "--" */
8989 for (q = optstr; *q != c;) {
8991 if (optstr[0] == ':') {
8994 err |= setvarsafe("OPTARG", s, 0);
8996 out2fmt("Illegal option -%c\n", c);
8997 (void) unsetvar("OPTARG");
9007 if (*p == '\0' && (p = *optnext) == NULL) {
9008 if (optstr[0] == ':') {
9011 err |= setvarsafe("OPTARG", s, 0);
9014 out2fmt("No arg for -%c option\n", c);
9015 (void) unsetvar("OPTARG");
9023 setvarsafe("OPTARG", p, 0);
9026 setvarsafe("OPTARG", "", 0);
9027 *myoptind = optnext - optfirst + 1;
9034 *optoff = p ? p - *(optnext - 1) : -1;
9035 snprintf(s, sizeof(s), "%d", *myoptind);
9036 err |= setvarsafe("OPTIND", s, VNOFUNC);
9039 err |= setvarsafe(optvar, s, 0);
9050 * XXX - should get rid of. have all builtins use getopt(3). the
9051 * library getopt must have the BSD extension static variable "optreset"
9052 * otherwise it can't be used within the shell safely.
9054 * Standard option processing (a la getopt) for builtin routines. The
9055 * only argument that is passed to nextopt is the option string; the
9056 * other arguments are unnecessary. It return the character, or '\0' on
9060 static int nextopt(const char *optstring)
9066 if ((p = optptr) == NULL || *p == '\0') {
9068 if (p == NULL || *p != '-' || *++p == '\0')
9071 if (p[0] == '-' && p[1] == '\0') /* check for "--" */
9075 for (q = optstring; *q != c;) {
9077 error("Illegal option -%c", c);
9082 if (*p == '\0' && (p = *argptr++) == NULL)
9083 error("No arg for -%c option", c);
9091 static void flushall()
9099 static void out2fmt(const char *fmt, ...)
9104 vfprintf(stderr, fmt, ap);
9109 * Version of write which resumes after a signal is caught.
9112 static int xwrite(int fd, const char *buf, int nbytes)
9121 i = write(fd, buf, n);
9127 } else if (i == 0) {
9130 } else if (errno != EINTR) {
9138 * Shell command parser.
9141 #define EOFMARKLEN 79
9146 struct heredoc *next; /* next here document in list */
9147 union node *here; /* redirection node */
9148 char *eofmark; /* string indicating end of input */
9149 int striptabs; /* if set, strip leading tabs */
9152 static struct heredoc *heredoclist; /* list of here documents to read */
9153 static int parsebackquote; /* nonzero if we are inside backquotes */
9154 static int doprompt; /* if set, prompt the user */
9155 static int needprompt; /* true if interactive and at start of line */
9156 static int lasttoken; /* last token read */
9158 static char *wordtext; /* text of last word returned by readtoken */
9160 static struct nodelist *backquotelist;
9161 static union node *redirnode;
9162 static struct heredoc *heredoc;
9163 static int quoteflag; /* set if (part of) last token was quoted */
9164 static int startlinno; /* line # where last token started */
9167 static union node *list(int);
9168 static union node *andor(void);
9169 static union node *pipeline(void);
9170 static union node *command(void);
9171 static union node *simplecmd(union node **rpp, union node *redir);
9172 static void parsefname(void);
9173 static void parseheredoc(void);
9174 static char peektoken(void);
9175 static int readtoken(void);
9176 static int xxreadtoken(void);
9177 static int readtoken1(int, int, const char *, int);
9178 static int noexpand(char *);
9179 static void synexpect(int) __attribute__ ((noreturn));
9180 static void synerror(const char *) __attribute__ ((noreturn));
9181 static void setprompt(int);
9185 * Read and parse a command. Returns NEOF on end of file. (NULL is a
9186 * valid parse tree indicating a blank line.)
9189 static union node *parsecmd(int interact)
9194 doprompt = interact;
9210 static union node *list(int nlflag)
9212 union node *n1, *n2, *n3;
9216 if (nlflag == 0 && peektoken())
9222 if (tok == TBACKGND) {
9223 if (n2->type == NCMD || n2->type == NPIPE) {
9224 n2->ncmd.backgnd = 1;
9225 } else if (n2->type == NREDIR) {
9226 n2->type = NBACKGND;
9228 n3 = (union node *) stalloc(sizeof(struct nredir));
9229 n3->type = NBACKGND;
9231 n3->nredir.redirect = NULL;
9238 n3 = (union node *) stalloc(sizeof(struct nbinary));
9240 n3->nbinary.ch1 = n1;
9241 n3->nbinary.ch2 = n2;
9265 pungetc(); /* push back EOF on input */
9278 static union node *andor()
9280 union node *n1, *n2, *n3;
9286 if ((t = readtoken()) == TAND) {
9288 } else if (t == TOR) {
9296 n3 = (union node *) stalloc(sizeof(struct nbinary));
9298 n3->nbinary.ch1 = n1;
9299 n3->nbinary.ch2 = n2;
9306 static union node *pipeline()
9308 union node *n1, *n2, *pipenode;
9309 struct nodelist *lp, *prev;
9313 TRACE(("pipeline: entered\n"));
9314 if (readtoken() == TNOT) {
9320 if (readtoken() == TPIPE) {
9321 pipenode = (union node *) stalloc(sizeof(struct npipe));
9322 pipenode->type = NPIPE;
9323 pipenode->npipe.backgnd = 0;
9324 lp = (struct nodelist *) stalloc(sizeof(struct nodelist));
9325 pipenode->npipe.cmdlist = lp;
9329 lp = (struct nodelist *) stalloc(sizeof(struct nodelist));
9333 } while (readtoken() == TPIPE);
9339 n2 = (union node *) stalloc(sizeof(struct nnot));
9349 static union node *command(void)
9351 union node *n1, *n2;
9352 union node *ap, **app;
9353 union node *cp, **cpp;
9354 union node *redir, **rpp;
9361 /* Check for redirection which may precede command */
9362 while (readtoken() == TREDIR) {
9363 *rpp = n2 = redirnode;
9364 rpp = &n2->nfile.next;
9369 switch (readtoken()) {
9371 n1 = (union node *) stalloc(sizeof(struct nif));
9373 n1->nif.test = list(0);
9374 if (readtoken() != TTHEN)
9376 n1->nif.ifpart = list(0);
9378 while (readtoken() == TELIF) {
9379 n2->nif.elsepart = (union node *) stalloc(sizeof(struct nif));
9380 n2 = n2->nif.elsepart;
9382 n2->nif.test = list(0);
9383 if (readtoken() != TTHEN)
9385 n2->nif.ifpart = list(0);
9387 if (lasttoken == TELSE)
9388 n2->nif.elsepart = list(0);
9390 n2->nif.elsepart = NULL;
9393 if (readtoken() != TFI)
9400 n1 = (union node *) stalloc(sizeof(struct nbinary));
9401 n1->type = (lasttoken == TWHILE) ? NWHILE : NUNTIL;
9402 n1->nbinary.ch1 = list(0);
9403 if ((got = readtoken()) != TDO) {
9404 TRACE(("expecting DO got %s %s\n", tokname(got),
9405 got == TWORD ? wordtext : ""));
9408 n1->nbinary.ch2 = list(0);
9409 if (readtoken() != TDONE)
9415 if (readtoken() != TWORD || quoteflag || !goodname(wordtext))
9416 synerror("Bad for loop variable");
9417 n1 = (union node *) stalloc(sizeof(struct nfor));
9419 n1->nfor.var = wordtext;
9421 if (readtoken() == TIN) {
9423 while (readtoken() == TWORD) {
9424 n2 = (union node *) stalloc(sizeof(struct narg));
9426 n2->narg.text = wordtext;
9427 n2->narg.backquote = backquotelist;
9429 app = &n2->narg.next;
9433 if (lasttoken != TNL && lasttoken != TSEMI)
9436 static char argvars[5] = { CTLVAR, VSNORMAL | VSQUOTE,
9439 n2 = (union node *) stalloc(sizeof(struct narg));
9441 n2->narg.text = argvars;
9442 n2->narg.backquote = NULL;
9443 n2->narg.next = NULL;
9446 * Newline or semicolon here is optional (but note
9447 * that the original Bourne shell only allowed NL).
9449 if (lasttoken != TNL && lasttoken != TSEMI)
9453 if (readtoken() != TDO)
9455 n1->nfor.body = list(0);
9456 if (readtoken() != TDONE)
9461 n1 = (union node *) stalloc(sizeof(struct ncase));
9463 if (readtoken() != TWORD)
9465 n1->ncase.expr = n2 = (union node *) stalloc(sizeof(struct narg));
9467 n2->narg.text = wordtext;
9468 n2->narg.backquote = backquotelist;
9469 n2->narg.next = NULL;
9472 } while (readtoken() == TNL);
9473 if (lasttoken != TIN)
9474 synerror("expecting \"in\"");
9475 cpp = &n1->ncase.cases;
9476 checkkwd = 2, readtoken();
9478 if (lasttoken == TLP)
9480 *cpp = cp = (union node *) stalloc(sizeof(struct nclist));
9482 app = &cp->nclist.pattern;
9484 *app = ap = (union node *) stalloc(sizeof(struct narg));
9486 ap->narg.text = wordtext;
9487 ap->narg.backquote = backquotelist;
9488 if (checkkwd = 2, readtoken() != TPIPE)
9490 app = &ap->narg.next;
9493 ap->narg.next = NULL;
9494 if (lasttoken != TRP)
9496 cp->nclist.body = list(0);
9499 if ((t = readtoken()) != TESAC) {
9501 synexpect(TENDCASE);
9503 checkkwd = 2, readtoken();
9505 cpp = &cp->nclist.next;
9506 } while (lasttoken != TESAC);
9511 n1 = (union node *) stalloc(sizeof(struct nredir));
9512 n1->type = NSUBSHELL;
9513 n1->nredir.n = list(0);
9514 n1->nredir.redirect = NULL;
9515 if (readtoken() != TRP)
9521 if (readtoken() != TEND)
9525 /* Handle an empty command like other simple commands. */
9534 * An empty command before a ; doesn't make much sense, and
9535 * should certainly be disallowed in the case of `if ;'.
9541 n1 = simplecmd(rpp, redir);
9548 /* Now check for redirection which may follow command */
9549 while (readtoken() == TREDIR) {
9550 *rpp = n2 = redirnode;
9551 rpp = &n2->nfile.next;
9557 if (n1->type != NSUBSHELL) {
9558 n2 = (union node *) stalloc(sizeof(struct nredir));
9563 n1->nredir.redirect = redir;
9570 static union node *simplecmd(union node **rpp, union node *redir)
9572 union node *args, **app;
9573 union node *n = NULL;
9574 union node *vars, **vpp;
9575 union node **orig_rpp;
9582 /* If we don't have any redirections already, then we must reset
9583 rpp to be the address of the local redir variable. */
9586 /* We save the incoming value, because we need this for shell
9587 functions. There can not be a redirect or an argument between
9588 the function name and the open parenthesis. */
9593 switch (readtoken()) {
9596 n = (union node *) stalloc(sizeof(struct narg));
9598 n->narg.text = wordtext;
9599 n->narg.backquote = backquotelist;
9600 if (lasttoken == TWORD) {
9602 app = &n->narg.next;
9605 vpp = &n->narg.next;
9609 *rpp = n = redirnode;
9610 rpp = &n->nfile.next;
9611 parsefname(); /* read name of redirection file */
9614 if (args && app == &args->narg.next && !vars && rpp == orig_rpp) {
9615 /* We have a function */
9616 if (readtoken() != TRP)
9620 n->narg.next = command();
9633 n = (union node *) stalloc(sizeof(struct ncmd));
9635 n->ncmd.backgnd = 0;
9636 n->ncmd.args = args;
9637 n->ncmd.assign = vars;
9638 n->ncmd.redirect = redir;
9642 static union node *makename(void)
9646 n = (union node *) stalloc(sizeof(struct narg));
9648 n->narg.next = NULL;
9649 n->narg.text = wordtext;
9650 n->narg.backquote = backquotelist;
9654 static void fixredir(union node *n, const char *text, int err)
9656 TRACE(("Fix redir %s %d\n", text, err));
9658 n->ndup.vname = NULL;
9660 if (is_digit(text[0]) && text[1] == '\0')
9661 n->ndup.dupfd = digit_val(text[0]);
9662 else if (text[0] == '-' && text[1] == '\0')
9667 synerror("Bad fd number");
9669 n->ndup.vname = makename();
9674 static void parsefname(void)
9676 union node *n = redirnode;
9678 if (readtoken() != TWORD)
9680 if (n->type == NHERE) {
9681 struct heredoc *here = heredoc;
9687 TRACE(("Here document %d\n", n->type));
9688 if (here->striptabs) {
9689 while (*wordtext == '\t')
9692 if (!noexpand(wordtext) || (i = strlen(wordtext)) == 0
9694 synerror("Illegal eof marker for << redirection");
9695 rmescapes(wordtext);
9696 here->eofmark = wordtext;
9698 if (heredoclist == NULL)
9701 for (p = heredoclist; p->next; p = p->next);
9704 } else if (n->type == NTOFD || n->type == NFROMFD) {
9705 fixredir(n, wordtext, 0);
9707 n->nfile.fname = makename();
9713 * Input any here documents.
9716 static void parseheredoc()
9718 struct heredoc *here;
9721 while (heredoclist) {
9723 heredoclist = here->next;
9728 readtoken1(pgetc(), here->here->type == NHERE ? SQSYNTAX : DQSYNTAX,
9729 here->eofmark, here->striptabs);
9730 n = (union node *) stalloc(sizeof(struct narg));
9731 n->narg.type = NARG;
9732 n->narg.next = NULL;
9733 n->narg.text = wordtext;
9734 n->narg.backquote = backquotelist;
9735 here->here->nhere.doc = n;
9739 static char peektoken()
9745 return tokname_array[t][0];
9748 static int readtoken()
9752 int savecheckalias = checkalias;
9754 #ifdef CONFIG_ASH_ALIAS
9755 int savecheckkwd = checkkwd;
9760 int alreadyseen = tokpushback;
9763 #ifdef CONFIG_ASH_ALIAS
9769 checkalias = savecheckalias;
9775 if (checkkwd == 2) {
9784 * check for keywords
9786 if (t == TWORD && !quoteflag) {
9787 const char *const *pp;
9789 if ((pp = findkwd(wordtext))) {
9790 lasttoken = t = pp - tokname_array;
9791 TRACE(("keyword %s recognized\n", tokname(t)));
9802 } else if (checkalias == 2 && isassignment(wordtext)) {
9803 lasttoken = t = TASSIGN;
9804 } else if (checkalias) {
9805 #ifdef CONFIG_ASH_ALIAS
9806 if (!quoteflag && (ap = *__lookupalias(wordtext)) != NULL
9807 && !(ap->flag & ALIASINUSE)) {
9809 pushstring(ap->val, strlen(ap->val), ap);
9811 checkkwd = savecheckkwd;
9820 TRACE(("token %s %s\n", tokname(t), t == TWORD
9821 || t == TASSIGN ? wordtext : ""));
9823 TRACE(("reread token %s %s\n", tokname(t), t == TWORD
9824 || t == TASSIGN ? wordtext : ""));
9831 * Read the next input token.
9832 * If the token is a word, we set backquotelist to the list of cmds in
9833 * backquotes. We set quoteflag to true if any part of the word was
9835 * If the token is TREDIR, then we set redirnode to a structure containing
9837 * In all cases, the variable startlinno is set to the number of the line
9838 * on which the token starts.
9840 * [Change comment: here documents and internal procedures]
9841 * [Readtoken shouldn't have any arguments. Perhaps we should make the
9842 * word parsing code into a separate routine. In this case, readtoken
9843 * doesn't need to have any internal procedures, but parseword does.
9844 * We could also make parseoperator in essence the main routine, and
9845 * have parseword (readtoken1?) handle both words and redirection.]
9848 #define NEW_xxreadtoken
9849 #ifdef NEW_xxreadtoken
9851 static const char xxreadtoken_chars[] = "\n()&|;"; /* singles must be first! */
9852 static const char xxreadtoken_tokens[] = {
9853 TNL, TLP, TRP, /* only single occurrence allowed */
9854 TBACKGND, TPIPE, TSEMI, /* if single occurrence */
9855 TEOF, /* corresponds to trailing nul */
9856 TAND, TOR, TENDCASE, /* if double occurrence */
9859 #define xxreadtoken_doubles \
9860 (sizeof(xxreadtoken_tokens) - sizeof(xxreadtoken_chars))
9861 #define xxreadtoken_singles \
9862 (sizeof(xxreadtoken_chars) - xxreadtoken_doubles - 1)
9864 static int xxreadtoken()
9876 startlinno = plinno;
9877 for (;;) { /* until token or start of word found */
9880 if ((c != ' ') && (c != '\t')
9881 #ifdef CONFIG_ASH_ALIAS
9886 while ((c = pgetc()) != '\n' && c != PEOF);
9888 } else if (c == '\\') {
9889 if (pgetc() != '\n') {
9893 startlinno = ++plinno;
9894 setprompt(doprompt ? 2 : 0);
9897 = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
9902 needprompt = doprompt;
9905 p = strchr(xxreadtoken_chars, c);
9908 return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
9911 if (p - xxreadtoken_chars >= xxreadtoken_singles) {
9912 if (pgetc() == *p) { /* double occurrence? */
9913 p += xxreadtoken_doubles + 1;
9920 return lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
9928 #define RETURN(token) return lasttoken = token
9930 static int xxreadtoken()
9942 startlinno = plinno;
9943 for (;;) { /* until token or start of word found */
9948 #ifdef CONFIG_ASH_ALIAS
9953 while ((c = pgetc()) != '\n' && c != PEOF);
9957 if (pgetc() == '\n') {
9958 startlinno = ++plinno;
9969 needprompt = doprompt;
9997 return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
10003 * If eofmark is NULL, read a word or a redirection symbol. If eofmark
10004 * is not NULL, read a here document. In the latter case, eofmark is the
10005 * word which marks the end of the document and striptabs is true if
10006 * leading tabs should be stripped from the document. The argument firstc
10007 * is the first character of the input token or document.
10009 * Because C does not have internal subroutines, I have simulated them
10010 * using goto's to implement the subroutine linkage. The following macros
10011 * will run code that appears at the end of readtoken1.
10014 #define CHECKEND() {goto checkend; checkend_return:;}
10015 #define PARSEREDIR() {goto parseredir; parseredir_return:;}
10016 #define PARSESUB() {goto parsesub; parsesub_return:;}
10017 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
10018 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
10019 #define PARSEARITH() {goto parsearith; parsearith_return:;}
10022 readtoken1(int firstc, int syntax, const char *eofmark, int striptabs)
10027 char line[EOFMARKLEN + 1];
10028 struct nodelist *bqlist;
10031 int varnest; /* levels of variables expansion */
10032 int arinest; /* levels of arithmetic expansion */
10033 int parenlevel; /* levels of parens in arithmetic */
10034 int dqvarnest; /* levels of variables expansion within double quotes */
10036 int prevsyntax; /* syntax before arithmetic */
10039 /* Avoid longjmp clobbering */
10045 (void) &parenlevel;
10048 (void) &prevsyntax;
10052 startlinno = plinno;
10054 if (syntax == DQSYNTAX)
10063 STARTSTACKSTR(out);
10064 loop:{ /* for each line, until end of word */
10065 CHECKEND(); /* set c to PEOF if at end of here document */
10066 for (;;) { /* until end of line or end of word */
10067 CHECKSTRSPACE(3, out); /* permit 3 calls to USTPUTC */
10068 switch (SIT(c, syntax)) {
10069 case CNL: /* '\n' */
10070 if (syntax == BASESYNTAX)
10071 goto endword; /* exit outer loop */
10079 goto loop; /* continue outer loop */
10084 if ((eofmark == NULL || dblquote) && dqvarnest == 0)
10085 USTPUTC(CTLESC, out);
10088 case CBACK: /* backslash */
10091 USTPUTC('\\', out);
10093 } else if (c == '\n') {
10099 if (dblquote && c != '\\' && c != '`' && c != '$'
10100 && (c != '"' || eofmark != NULL))
10101 USTPUTC('\\', out);
10102 if (SIT(c, SQSYNTAX) == CCTL)
10103 USTPUTC(CTLESC, out);
10104 else if (eofmark == NULL)
10105 USTPUTC(CTLQUOTEMARK, out);
10111 if (eofmark == NULL)
10112 USTPUTC(CTLQUOTEMARK, out);
10116 if (eofmark == NULL)
10117 USTPUTC(CTLQUOTEMARK, out);
10122 if (eofmark != NULL && arinest == 0 && varnest == 0) {
10126 syntax = ARISYNTAX;
10128 } else if (eofmark == NULL && dqvarnest == 0) {
10129 syntax = BASESYNTAX;
10135 case CVAR: /* '$' */
10136 PARSESUB(); /* parse substitution */
10138 case CENDVAR: /* '}' */
10141 if (dqvarnest > 0) {
10144 USTPUTC(CTLENDVAR, out);
10149 #ifdef CONFIG_ASH_MATH_SUPPORT
10150 case CLP: /* '(' in arithmetic */
10154 case CRP: /* ')' in arithmetic */
10155 if (parenlevel > 0) {
10159 if (pgetc() == ')') {
10160 if (--arinest == 0) {
10161 USTPUTC(CTLENDARI, out);
10162 syntax = prevsyntax;
10163 if (syntax == DQSYNTAX)
10171 * unbalanced parens
10172 * (don't 2nd guess - no error)
10180 case CBQUOTE: /* '`' */
10184 goto endword; /* exit outer loop */
10189 goto endword; /* exit outer loop */
10190 #ifdef CONFIG_ASH_ALIAS
10200 if (syntax == ARISYNTAX)
10201 synerror("Missing '))'");
10202 if (syntax != BASESYNTAX && !parsebackquote && eofmark == NULL)
10203 synerror("Unterminated quoted string");
10204 if (varnest != 0) {
10205 startlinno = plinno;
10206 synerror("Missing '}'");
10208 USTPUTC('\0', out);
10209 len = out - stackblock();
10210 out = stackblock();
10211 if (eofmark == NULL) {
10212 if ((c == '>' || c == '<')
10213 && quotef == 0 && len <= 2 && (*out == '\0' || is_digit(*out))) {
10215 return lasttoken = TREDIR;
10220 quoteflag = quotef;
10221 backquotelist = bqlist;
10222 grabstackblock(len);
10224 return lasttoken = TWORD;
10225 /* end of readtoken routine */
10230 * Check to see whether we are at the end of the here document. When this
10231 * is called, c is set to the first character of the next input line. If
10232 * we are at the end of the here document, this routine sets the c to PEOF.
10237 #ifdef CONFIG_ASH_ALIAS
10243 while (c == '\t') {
10247 if (c == *eofmark) {
10248 if (pfgets(line, sizeof line) != NULL) {
10252 for (q = eofmark + 1; *q && *p == *q; p++, q++);
10253 if (*p == '\n' && *q == '\0') {
10256 needprompt = doprompt;
10258 pushstring(line, strlen(line), NULL);
10263 goto checkend_return;
10268 * Parse a redirection operator. The variable "out" points to a string
10269 * specifying the fd to be redirected. The variable "c" contains the
10270 * first character of the redirection operator.
10277 np = (union node *) stalloc(sizeof(struct nfile));
10282 np->type = NAPPEND;
10291 } else { /* c == '<' */
10293 switch (c = pgetc()) {
10295 if (sizeof(struct nfile) != sizeof(struct nhere)) {
10296 np = (union node *) stalloc(sizeof(struct nhere));
10300 heredoc = (struct heredoc *) stalloc(sizeof(struct heredoc));
10301 heredoc->here = np;
10302 if ((c = pgetc()) == '-') {
10303 heredoc->striptabs = 1;
10305 heredoc->striptabs = 0;
10311 np->type = NFROMFD;
10315 np->type = NFROMTO;
10325 np->nfile.fd = digit_val(fd);
10327 goto parseredir_return;
10332 * Parse a substitution. At this point, we have read the dollar sign
10333 * and nothing else.
10341 static const char types[] = "}-+?=";
10345 (c != '(' && c != '{' && !is_name(c) && !is_special(c))
10349 } else if (c == '(') { /* $(command) or $((arith)) */
10350 if (pgetc() == '(') {
10357 USTPUTC(CTLVAR, out);
10358 typeloc = out - stackblock();
10359 USTPUTC(VSNORMAL, out);
10360 subtype = VSNORMAL;
10364 if ((c = pgetc()) == '}')
10367 subtype = VSLENGTH;
10371 if (c > PEOA && is_name(c)) {
10375 } while (c > PEOA && is_in_name(c));
10376 } else if (is_digit(c)) {
10380 } while (is_digit(c));
10381 } else if (is_special(c)) {
10385 badsub:synerror("Bad substitution");
10389 if (subtype == 0) {
10394 /*FALLTHROUGH*/ default:
10395 p = strchr(types, c);
10398 subtype = p - types + VSNORMAL;
10405 subtype = c == '#' ? VSTRIMLEFT : VSTRIMRIGHT;
10417 if (dblquote || arinest)
10419 *(stackblock() + typeloc) = subtype | flags;
10420 if (subtype != VSNORMAL) {
10427 goto parsesub_return;
10432 * Called to parse command substitutions. Newstyle is set if the command
10433 * is enclosed inside $(...); nlpp is a pointer to the head of the linked
10434 * list of commands (passed by reference), and savelen is the number of
10435 * characters on the top of the stack which must be preserved.
10439 struct nodelist **nlpp;
10442 char *volatile str;
10443 struct jmploc jmploc;
10444 struct jmploc *volatile savehandler;
10449 (void) &saveprompt;
10452 savepbq = parsebackquote;
10453 if (setjmp(jmploc.loc)) {
10455 parsebackquote = 0;
10456 handler = savehandler;
10457 longjmp(handler->loc, 1);
10461 savelen = out - stackblock();
10463 str = xmalloc(savelen);
10464 memcpy(str, stackblock(), savelen);
10466 savehandler = handler;
10470 /* We must read until the closing backquote, giving special
10471 treatment to some slashes, and then push the string and
10472 reread it as input, interpreting it normally. */
10479 STARTSTACKSTR(pout);
10485 switch (pc = pgetc()) {
10490 if ((pc = pgetc()) == '\n') {
10497 * If eating a newline, avoid putting
10498 * the newline into the new character
10499 * stream (via the STPUTC after the
10504 if (pc != '\\' && pc != '`' && pc != '$'
10505 && (!dblquote || pc != '"'))
10506 STPUTC('\\', pout);
10513 #ifdef CONFIG_ASH_ALIAS
10516 startlinno = plinno;
10517 synerror("EOF in backquote substitution");
10521 needprompt = doprompt;
10530 STPUTC('\0', pout);
10531 psavelen = pout - stackblock();
10532 if (psavelen > 0) {
10533 pstr = grabstackstr(pout);
10534 setinputstring(pstr);
10539 nlpp = &(*nlpp)->next;
10540 *nlpp = (struct nodelist *) stalloc(sizeof(struct nodelist));
10541 (*nlpp)->next = NULL;
10542 parsebackquote = oldstyle;
10545 saveprompt = doprompt;
10552 doprompt = saveprompt;
10554 if (readtoken() != TRP)
10561 * Start reading from old file again, ignoring any pushed back
10562 * tokens left from the backquote parsing
10567 while (stackblocksize() <= savelen)
10569 STARTSTACKSTR(out);
10571 memcpy(out, str, savelen);
10572 STADJUST(savelen, out);
10578 parsebackquote = savepbq;
10579 handler = savehandler;
10580 if (arinest || dblquote)
10581 USTPUTC(CTLBACKQ | CTLQUOTE, out);
10583 USTPUTC(CTLBACKQ, out);
10585 goto parsebackq_oldreturn;
10587 goto parsebackq_newreturn;
10591 * Parse an arithmetic expansion (indicate start of one and set state)
10595 if (++arinest == 1) {
10596 prevsyntax = syntax;
10597 syntax = ARISYNTAX;
10598 USTPUTC(CTLARI, out);
10605 * we collapse embedded arithmetic expansion to
10606 * parenthesis, which should be equivalent
10610 goto parsearith_return;
10613 } /* end of readtoken */
10617 * Returns true if the text contains nothing to expand (no dollar signs
10621 static int noexpand(char *text)
10627 while ((c = *p++) != '\0') {
10628 if (c == CTLQUOTEMARK)
10632 else if (SIT(c, BASESYNTAX) == CCTL)
10640 * Return true if the argument is a legal variable name (a letter or
10641 * underscore followed by zero or more letters, underscores, and digits).
10644 static int goodname(const char *name)
10652 if (!is_in_name(*p))
10660 * Called when an unexpected token is read during the parse. The argument
10661 * is the token that is expected, or -1 if more than one type of token can
10662 * occur at this point.
10665 static void synexpect(int token)
10670 l = sprintf(msg, "%s unexpected", tokname(lasttoken));
10672 sprintf(msg + l, " (expecting %s)", tokname(token));
10678 static void synerror(const char *msg)
10681 out2fmt("%s: %d: ", commandname, startlinno);
10682 out2fmt("Syntax error: %s\n", msg);
10683 error((char *) NULL);
10689 * called by editline -- any expansions to the prompt
10690 * should be added here.
10692 static void setprompt(int whichprompt)
10696 switch (whichprompt) {
10711 * Code for dealing with input/output redirection.
10714 #define EMPTY -2 /* marks an unused slot in redirtab */
10716 # define PIPESIZE 4096 /* amount of buffering in a pipe */
10718 # define PIPESIZE PIPE_BUF
10723 * Open a file in noclobber mode.
10724 * The code was copied from bash.
10726 static inline int noclobberopen(const char *fname)
10729 struct stat finfo, finfo2;
10732 * If the file exists and is a regular file, return an error
10735 r = stat(fname, &finfo);
10736 if (r == 0 && S_ISREG(finfo.st_mode)) {
10742 * If the file was not present (r != 0), make sure we open it
10743 * exclusively so that if it is created before we open it, our open
10744 * will fail. Make sure that we do not truncate an existing file.
10745 * Note that we don't turn on O_EXCL unless the stat failed -- if the
10746 * file was not a regular file, we leave O_EXCL off.
10749 return open(fname, O_WRONLY | O_CREAT | O_EXCL, 0666);
10750 fd = open(fname, O_WRONLY | O_CREAT, 0666);
10752 /* If the open failed, return the file descriptor right away. */
10757 * OK, the open succeeded, but the file may have been changed from a
10758 * non-regular file to a regular file between the stat and the open.
10759 * We are assuming that the O_EXCL open handles the case where FILENAME
10760 * did not exist and is symlinked to an existing file between the stat
10765 * If we can open it and fstat the file descriptor, and neither check
10766 * revealed that it was a regular file, and the file has not been
10767 * replaced, return the file descriptor.
10769 if (fstat(fd, &finfo2) == 0 && !S_ISREG(finfo2.st_mode) &&
10770 finfo.st_dev == finfo2.st_dev && finfo.st_ino == finfo2.st_ino)
10773 /* The file has been replaced. badness. */
10780 * Handle here documents. Normally we fork off a process to write the
10781 * data to a pipe. If the document is short, we can stuff the data in
10782 * the pipe without forking.
10785 static inline int openhere(const union node *redir)
10791 error("Pipe call failed");
10792 if (redir->type == NHERE) {
10793 len = strlen(redir->nhere.doc->narg.text);
10794 if (len <= PIPESIZE) {
10795 xwrite(pip[1], redir->nhere.doc->narg.text, len);
10799 if (forkshell((struct job *) NULL, (union node *) NULL, FORK_NOJOB) == 0) {
10801 signal(SIGINT, SIG_IGN);
10802 signal(SIGQUIT, SIG_IGN);
10803 signal(SIGHUP, SIG_IGN);
10805 signal(SIGTSTP, SIG_IGN);
10807 signal(SIGPIPE, SIG_DFL);
10808 if (redir->type == NHERE)
10809 xwrite(pip[1], redir->nhere.doc->narg.text, len);
10811 expandhere(redir->nhere.doc, pip[1]);
10820 static inline int openredirect(const union node *redir)
10825 switch (redir->nfile.type) {
10827 fname = redir->nfile.expfname;
10828 if ((f = open(fname, O_RDONLY)) < 0)
10832 fname = redir->nfile.expfname;
10833 if ((f = open(fname, O_RDWR | O_CREAT | O_TRUNC, 0666)) < 0)
10837 /* Take care of noclobber mode. */
10839 fname = redir->nfile.expfname;
10840 if ((f = noclobberopen(fname)) < 0)
10845 fname = redir->nfile.expfname;
10847 if ((f = open(fname, O_WRONLY | O_CREAT | O_TRUNC, 0666)) < 0)
10850 if ((f = creat(fname, 0666)) < 0)
10855 fname = redir->nfile.expfname;
10857 if ((f = open(fname, O_WRONLY | O_CREAT | O_APPEND, 0666)) < 0)
10860 if ((f = open(fname, O_WRONLY)) < 0 && (f = creat(fname, 0666)) < 0)
10862 lseek(f, (off_t) 0, 2);
10869 /* Fall through to eliminate warning. */
10876 f = openhere(redir);
10882 error("cannot create %s: %s", fname, errmsg(errno, E_CREAT));
10884 error("cannot open %s: %s", fname, errmsg(errno, E_OPEN));
10889 * Process a list of redirection commands. If the REDIR_PUSH flag is set,
10890 * old file descriptors are stashed away so that the redirection can be
10891 * undone by calling popredir. If the REDIR_BACKQ flag is set, then the
10892 * standard output, and the standard error if it becomes a duplicate of
10896 static void redirect(union node *redir, int flags)
10899 struct redirtab *sv = NULL;
10904 int fd1dup = flags & REDIR_BACKQ;; /* stdout `cmd` redir to pipe */
10906 TRACE(("redirect(%s) called\n",
10907 flags & REDIR_PUSH ? "REDIR_PUSH" : "NO_REDIR_PUSH"));
10908 if (flags & REDIR_PUSH) {
10909 sv = xmalloc(sizeof(struct redirtab));
10910 for (i = 0; i < 10; i++)
10911 sv->renamed[i] = EMPTY;
10912 sv->next = redirlist;
10915 for (n = redir; n; n = n->nfile.next) {
10918 if ((n->nfile.type == NTOFD || n->nfile.type == NFROMFD) &&
10919 n->ndup.dupfd == fd)
10920 continue; /* redirect from/to same file descriptor */
10923 newfd = openredirect(n);
10924 if ((flags & REDIR_PUSH) && sv->renamed[fd] == EMPTY) {
10928 } else if ((i = fcntl(fd, F_DUPFD, 10)) == -1) {
10932 dupredirect(n, newfd, fd1dup);
10942 error("%d: %m", fd);
10948 if (flags & REDIR_PUSH) {
10949 sv->renamed[fd] = i;
10952 } else if (fd != newfd) {
10958 dupredirect(n, newfd, fd1dup);
10964 static void dupredirect(const union node *redir, int f, int fd1dup)
10966 int fd = redir->nfile.fd;
10970 if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
10971 if (redir->ndup.dupfd >= 0) { /* if not ">&-" */
10972 if (redir->ndup.dupfd != 1 || fd1dup != 1)
10973 dup_as_newfd(redir->ndup.dupfd, fd);
10979 dup_as_newfd(f, fd);
10988 * Undo the effects of the last redirection.
10991 static void popredir(void)
10993 struct redirtab *rp = redirlist;
10997 for (i = 0; i < 10; i++) {
10998 if (rp->renamed[i] != EMPTY) {
11002 if (rp->renamed[i] >= 0) {
11003 dup_as_newfd(rp->renamed[i], i);
11004 close(rp->renamed[i]);
11008 redirlist = rp->next;
11014 * Discard all saved file descriptors.
11017 static void clearredir(void)
11019 struct redirtab *rp;
11022 for (rp = redirlist; rp; rp = rp->next) {
11023 for (i = 0; i < 10; i++) {
11024 if (rp->renamed[i] >= 0) {
11025 close(rp->renamed[i]);
11027 rp->renamed[i] = EMPTY;
11034 * Copy a file descriptor to be >= to. Returns -1
11035 * if the source file descriptor is closed, EMPTY if there are no unused
11036 * file descriptors left.
11039 static int dup_as_newfd(int from, int to)
11043 newfd = fcntl(from, F_DUPFD, to);
11045 if (errno == EMFILE)
11048 error("%d: %m", from);
11058 static void shtree(union node *, int, char *, FILE *);
11059 static void shcmd(union node *, FILE *);
11060 static void sharg(union node *, FILE *);
11061 static void indent(int, char *, FILE *);
11062 static void trstring(char *);
11066 static void showtree(node * n)
11068 trputs("showtree called\n");
11069 shtree(n, 1, NULL, stdout);
11073 static void shtree(union node *n, int ind, char *pfx, FILE * fp)
11075 struct nodelist *lp;
11081 indent(ind, pfx, fp);
11092 shtree(n->nbinary.ch1, ind, NULL, fp);
11095 shtree(n->nbinary.ch2, ind, NULL, fp);
11103 for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
11108 if (n->npipe.backgnd)
11114 fprintf(fp, "<node type %d>", n->type);
11122 static void shcmd(union node *cmd, FILE * fp)
11130 for (np = cmd->ncmd.args; np; np = np->narg.next) {
11136 for (np = cmd->ncmd.redirect; np; np = np->nfile.next) {
11142 if ((np->nfile.type <= NFROMFD) && (np->nfile.type >= NTO)) {
11143 s = redir_strings[np->nfile.type - NTO];
11149 switch (np->nfile.type) {
11184 if (np->nfile.fd != dftfd)
11185 fprintf(fp, "%d", np->nfile.fd);
11187 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
11188 fprintf(fp, "%d", np->ndup.dupfd);
11190 sharg(np->nfile.fname, fp);
11197 static void sharg(union node *arg, FILE * fp)
11200 struct nodelist *bqlist;
11203 if (arg->type != NARG) {
11204 printf("<node type %d>\n", arg->type);
11208 bqlist = arg->narg.backquote;
11209 for (p = arg->narg.text; *p; p++) {
11218 if (subtype == VSLENGTH)
11224 if (subtype & VSNUL)
11227 switch (subtype & VSTYPE) {
11246 case VSTRIMLEFTMAX:
11253 case VSTRIMRIGHTMAX:
11260 printf("<subtype %d>", subtype);
11267 case CTLBACKQ | CTLQUOTE:
11270 shtree(bqlist->n, -1, NULL, fp);
11281 static void indent(int amount, char *pfx, FILE * fp)
11285 for (i = 0; i < amount; i++) {
11286 if (pfx && i == amount - 1)
11295 static int debug = 1;
11297 static int debug = 0;
11301 static void trputc(int c)
11303 if (tracefile == NULL)
11305 putc(c, tracefile);
11310 static void trace(const char *fmt, ...)
11315 if (tracefile != NULL) {
11316 (void) vfprintf(tracefile, fmt, va);
11317 if (strchr(fmt, '\n'))
11318 (void) fflush(tracefile);
11324 static void trputs(const char *s)
11326 if (tracefile == NULL)
11328 fputs(s, tracefile);
11329 if (strchr(s, '\n'))
11334 static void trstring(char *s)
11339 if (tracefile == NULL)
11341 putc('"', tracefile);
11342 for (p = s; *p; p++) {
11365 case CTLVAR + CTLQUOTE:
11371 case CTLBACKQ + CTLQUOTE:
11374 backslash:putc('\\', tracefile);
11375 putc(c, tracefile);
11378 if (*p >= ' ' && *p <= '~')
11379 putc(*p, tracefile);
11381 putc('\\', tracefile);
11382 putc(*p >> 6 & 03, tracefile);
11383 putc(*p >> 3 & 07, tracefile);
11384 putc(*p & 07, tracefile);
11389 putc('"', tracefile);
11393 static void trargs(char **ap)
11395 if (tracefile == NULL)
11400 putc(' ', tracefile);
11402 putc('\n', tracefile);
11408 static void opentrace()
11418 #ifdef not_this_way
11422 if ((p = getenv("HOME")) == NULL) {
11423 if (geteuid() == 0)
11429 strcat(s, "/trace");
11432 strcpy(s, "./trace");
11433 #endif /* not_this_way */
11434 if ((tracefile = wfopen(s, "a")) == NULL)
11437 if ((flags = fcntl(fileno(tracefile), F_GETFL, 0)) >= 0)
11438 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
11440 fputs("\nTracing started.\n", tracefile);
11447 * The trap builtin.
11450 static int trapcmd(int argc, char **argv)
11457 for (signo = 0; signo < NSIG; signo++) {
11458 if (trap[signo] != NULL) {
11462 p = single_quote(trap[signo]);
11463 sn = sys_siglist[signo];
11465 sn = u_signal_names(0, &signo, 0);
11468 printf("trap -- %s %s\n", p, sn);
11480 if ((signo = decode_signal(*ap, 0)) < 0)
11481 error("%s: bad trap", *ap);
11484 if (action[0] == '-' && action[1] == '\0')
11487 action = xstrdup(action);
11490 trap[signo] = action;
11501 * Set the signal handler for the specified signal. The routine figures
11502 * out what it should be set to.
11505 static void setsignal(int signo)
11509 struct sigaction act;
11511 if ((t = trap[signo]) == NULL)
11513 else if (*t != '\0')
11517 if (rootshell && action == S_DFL) {
11520 if (iflag || minusc || sflag == 0)
11536 #ifdef CONFIG_ASH_JOB_CONTROL
11546 t = &sigmode[signo - 1];
11549 * current setting unknown
11551 if (sigaction(signo, 0, &act) == -1) {
11553 * Pretend it worked; maybe we should give a warning
11554 * here, but other shells don't. We don't alter
11555 * sigmode, so that we retry every time.
11559 if (act.sa_handler == SIG_IGN) {
11560 if (mflag && (signo == SIGTSTP ||
11561 signo == SIGTTIN || signo == SIGTTOU)) {
11562 *t = S_IGN; /* don't hard ignore these */
11566 *t = S_RESET; /* force to be set */
11569 if (*t == S_HARD_IGN || *t == action)
11571 act.sa_handler = ((action == S_CATCH) ? onsig
11572 : ((action == S_IGN) ? SIG_IGN : SIG_DFL));
11575 sigemptyset(&act.sa_mask);
11576 sigaction(signo, &act, 0);
11583 static void ignoresig(int signo)
11585 if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
11586 signal(signo, SIG_IGN);
11588 sigmode[signo - 1] = S_HARD_IGN;
11596 static void onsig(int signo)
11598 if (signo == SIGINT && trap[SIGINT] == NULL) {
11602 gotsig[signo - 1] = 1;
11608 * Called to execute a trap. Perhaps we should avoid entering new trap
11609 * handlers while we are executing a trap handler.
11612 static void dotrap(void)
11618 for (i = 1;; i++) {
11625 savestatus = exitstatus;
11626 evalstring(trap[i], 0);
11627 exitstatus = savestatus;
11634 * Called to exit the shell.
11637 static void exitshell(int status)
11639 struct jmploc loc1, loc2;
11642 TRACE(("exitshell(%d) pid=%d\n", status, getpid()));
11643 if (setjmp(loc1.loc)) {
11646 if (setjmp(loc2.loc)) {
11650 if ((p = trap[0]) != NULL && *p != '\0') {
11655 handler = &loc2; /* probably unnecessary */
11657 #ifdef CONFIG_ASH_JOB_CONTROL
11660 #ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
11661 if (iflag && rootshell) {
11662 const char *hp = lookupvar("HISTFILE");
11665 save_history ( hp );
11673 static int decode_signal(const char *string, int minsig)
11676 const char *name = u_signal_names(string, &signo, minsig);
11678 return name ? signo : -1;
11681 static struct var **hashvar(const char *);
11682 static void showvars(const char *, int, int);
11683 static struct var **findvar(struct var **, const char *);
11686 * Initialize the varable symbol tables and import the environment
11690 * This routine initializes the builtin variables. It is called when the
11691 * shell is initialized and again when a shell procedure is spawned.
11694 static void initvar()
11696 const struct varinit *ip;
11700 for (ip = varinit; (vp = ip->var) != NULL; ip++) {
11701 if ((vp->flags & VEXPORT) == 0) {
11702 vpp = hashvar(ip->text);
11705 vp->text = xstrdup(ip->text);
11706 vp->flags = ip->flags;
11707 vp->func = ip->func;
11710 #if !defined(CONFIG_FEATURE_COMMAND_EDITING) || !defined(CONFIG_FEATURE_SH_FANCY_PROMPT)
11712 * PS1 depends on uid
11714 if ((vps1.flags & VEXPORT) == 0) {
11715 vpp = hashvar("PS1=$ ");
11718 vps1.text = xstrdup(geteuid()? "PS1=$ " : "PS1=# ");
11719 vps1.flags = VSTRFIXED | VTEXTFIXED;
11725 * Set the value of a variable. The flags argument is ored with the
11726 * flags of the variable. If val is NULL, the variable is unset.
11729 static void setvar(const char *name, const char *val, int flags)
11744 if (!is_in_name(*p)) {
11745 if (*p == '\0' || *p == '=')
11751 namelen = p - name;
11753 error("%.*s: bad variable name", namelen, name);
11754 len = namelen + 2; /* 2 is space for '=' and '\0' */
11758 len += vallen = strlen(val);
11761 nameeq = xmalloc(len);
11762 memcpy(nameeq, name, namelen);
11763 nameeq[namelen] = '=';
11765 memcpy(nameeq + namelen + 1, val, vallen + 1);
11767 nameeq[namelen + 1] = '\0';
11769 setvareq(nameeq, flags);
11776 * Same as setvar except that the variable and value are passed in
11777 * the first argument as name=value. Since the first argument will
11778 * be actually stored in the table, it should not be a string that
11782 static void setvareq(char *s, int flags)
11784 struct var *vp, **vpp;
11787 flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
11788 if ((vp = *findvar(vpp, s))) {
11789 if (vp->flags & VREADONLY) {
11790 size_t len = strchr(s, '=') - s;
11792 error("%.*s: is read only", len, s);
11796 if (vp->func && (flags & VNOFUNC) == 0)
11797 (*vp->func) (strchr(s, '=') + 1);
11799 if ((vp->flags & (VTEXTFIXED | VSTACK)) == 0)
11802 vp->flags &= ~(VTEXTFIXED | VSTACK | VUNSET);
11803 vp->flags |= flags;
11806 #ifdef CONFIG_ASH_MAIL
11808 * We could roll this to a function, to handle it as
11809 * a regular variable function callback, but why bother?
11811 if (iflag && (vp == &vmpath || (vp == &vmail && !mpathset())))
11818 vp = xmalloc(sizeof(*vp));
11829 * Process a linked list of variable assignments.
11832 static void listsetvar(struct strlist *mylist)
11834 struct strlist *lp;
11837 for (lp = mylist; lp; lp = lp->next) {
11838 setvareq(xstrdup(lp->text), 0);
11846 * Find the value of a variable. Returns NULL if not set.
11849 static const char *lookupvar(const char *name)
11853 if ((v = *findvar(hashvar(name), name)) && !(v->flags & VUNSET)) {
11854 return strchr(v->text, '=') + 1;
11862 * Search the environment of a builtin command.
11865 static const char *bltinlookup(const char *name)
11867 const struct strlist *sp;
11869 for (sp = cmdenviron; sp; sp = sp->next) {
11870 if (varequal(sp->text, name))
11871 return strchr(sp->text, '=') + 1;
11873 return lookupvar(name);
11879 * Generate a list of exported variables. This routine is used to construct
11880 * the third argument to execve when executing a program.
11883 static char **environment()
11892 for (vpp = vartab; vpp < vartab + VTABSIZE; vpp++) {
11893 for (vp = *vpp; vp; vp = vp->next)
11894 if (vp->flags & VEXPORT)
11897 ep = env = stalloc((nenv + 1) * sizeof *env);
11898 for (vpp = vartab; vpp < vartab + VTABSIZE; vpp++) {
11899 for (vp = *vpp; vp; vp = vp->next)
11900 if (vp->flags & VEXPORT)
11909 * Command to list all variables which are set. Currently this command
11910 * is invoked from the set command when the set command is called without
11914 static int showvarscmd(int argc, char **argv)
11916 showvars(nullstr, VUNSET, VUNSET);
11923 * The export and readonly commands.
11926 static int exportcmd(int argc, char **argv)
11931 int flag = argv[0][0] == 'r' ? VREADONLY : VEXPORT;
11934 listsetvar(cmdenviron);
11935 pflag = (nextopt("p") == 'p');
11936 if (argc > 1 && !pflag) {
11937 while ((name = *argptr++) != NULL) {
11938 if ((p = strchr(name, '=')) != NULL) {
11941 if ((vp = *findvar(hashvar(name), name))) {
11946 setvar(name, p, flag);
11950 showvars(argv[0], flag, 0);
11957 * The "local" command.
11960 /* funcnest nonzero if we are currently evaluating a function */
11962 static int localcmd(int argc, char **argv)
11967 error("Not in a function");
11968 while ((name = *argptr++) != NULL) {
11976 * Make a variable a local variable. When a variable is made local, it's
11977 * value and flags are saved in a localvar structure. The saved values
11978 * will be restored when the shell function returns. We handle the name
11979 * "-" as a special case.
11982 static void mklocal(char *name)
11984 struct localvar *lvp;
11989 lvp = xmalloc(sizeof(struct localvar));
11990 if (name[0] == '-' && name[1] == '\0') {
11993 p = xmalloc(sizeof optet_vals);
11994 lvp->text = memcpy(p, optet_vals, sizeof optet_vals);
11997 vpp = hashvar(name);
11998 vp = *findvar(vpp, name);
12000 if (strchr(name, '='))
12001 setvareq(xstrdup(name), VSTRFIXED);
12003 setvar(name, NULL, VSTRFIXED);
12004 vp = *vpp; /* the new variable */
12006 lvp->flags = VUNSET;
12008 lvp->text = vp->text;
12009 lvp->flags = vp->flags;
12010 vp->flags |= VSTRFIXED | VTEXTFIXED;
12011 if (strchr(name, '='))
12012 setvareq(xstrdup(name), 0);
12016 lvp->next = localvars;
12023 * Called after a function returns.
12026 static void poplocalvars()
12028 struct localvar *lvp;
12031 while ((lvp = localvars) != NULL) {
12032 localvars = lvp->next;
12034 if (vp == NULL) { /* $- saved */
12035 memcpy(optet_vals, lvp->text, sizeof optet_vals);
12037 } else if ((lvp->flags & (VUNSET | VSTRFIXED)) == VUNSET) {
12038 (void) unsetvar(vp->text);
12040 if ((vp->flags & VTEXTFIXED) == 0)
12042 vp->flags = lvp->flags;
12043 vp->text = lvp->text;
12050 static int setvarcmd(int argc, char **argv)
12053 return unsetcmd(argc, argv);
12054 else if (argc == 3)
12055 setvar(argv[1], argv[2], 0);
12057 error("List assignment not implemented");
12063 * The unset builtin command. We unset the function before we unset the
12064 * variable to allow a function to be unset when there is a readonly variable
12065 * with the same name.
12068 static int unsetcmd(int argc, char **argv)
12076 while ((i = nextopt("vf")) != '\0') {
12082 if (flg_func == 0 && flg_var == 0)
12085 for (ap = argptr; *ap; ap++) {
12089 ret |= unsetvar(*ap);
12096 * Unset the specified variable.
12099 static int unsetvar(const char *s)
12104 vpp = findvar(hashvar(s), s);
12107 if (vp->flags & VREADONLY)
12110 if (*(strchr(vp->text, '=') + 1) != '\0')
12111 setvar(s, nullstr, 0);
12112 vp->flags &= ~VEXPORT;
12113 vp->flags |= VUNSET;
12114 if ((vp->flags & VSTRFIXED) == 0) {
12115 if ((vp->flags & VTEXTFIXED) == 0)
12130 * Find the appropriate entry in the hash table from the name.
12133 static struct var **hashvar(const char *p)
12135 unsigned int hashval;
12137 hashval = ((unsigned char) *p) << 4;
12138 while (*p && *p != '=')
12139 hashval += (unsigned char) *p++;
12140 return &vartab[hashval % VTABSIZE];
12146 * Returns true if the two strings specify the same varable. The first
12147 * variable name is terminated by '='; the second may be terminated by
12148 * either '=' or '\0'.
12151 static int varequal(const char *p, const char *q)
12153 while (*p == *q++) {
12157 if (*p == '=' && *(q - 1) == '\0')
12162 static void showvars(const char *myprefix, int mask, int xor)
12166 const char *sep = myprefix == nullstr ? myprefix : spcstr;
12168 for (vpp = vartab; vpp < vartab + VTABSIZE; vpp++) {
12169 for (vp = *vpp; vp; vp = vp->next) {
12170 if ((vp->flags & mask) ^ xor) {
12174 p = strchr(vp->text, '=') + 1;
12175 len = p - vp->text;
12176 p = single_quote(p);
12178 printf("%s%s%.*s%s\n", myprefix, sep, len, vp->text, p);
12185 static struct var **findvar(struct var **vpp, const char *name)
12187 for (; *vpp; vpp = &(*vpp)->next) {
12188 if (varequal((*vpp)->text, name)) {
12196 * Copyright (c) 1999 Herbert Xu <herbert@debian.org>
12197 * This file contains code for the times builtin.
12199 static int timescmd(int argc, char **argv)
12202 long int clk_tck = sysconf(_SC_CLK_TCK);
12205 printf("%dm%fs %dm%fs\n%dm%fs %dm%fs\n",
12206 (int) (buf.tms_utime / clk_tck / 60),
12207 ((double) buf.tms_utime) / clk_tck,
12208 (int) (buf.tms_stime / clk_tck / 60),
12209 ((double) buf.tms_stime) / clk_tck,
12210 (int) (buf.tms_cutime / clk_tck / 60),
12211 ((double) buf.tms_cutime) / clk_tck,
12212 (int) (buf.tms_cstime / clk_tck / 60),
12213 ((double) buf.tms_cstime) / clk_tck);
12217 #ifdef CONFIG_ASH_MATH_SUPPORT
12218 /* The let builtin. */
12219 int letcmd(int argc, char **argv)
12225 char *tmp, *expression, p[13];
12227 expression = strchr(argv[1], '=');
12229 /* Cannot use 'error()' here, or the return code
12230 * will be incorrect */
12231 out2fmt("sh: let: syntax error: \"%s\"\n", argv[1]);
12234 *expression = '\0';
12235 tmp = ++expression;
12236 result = arith(tmp, &errcode);
12238 /* Cannot use 'error()' here, or the return code
12239 * will be incorrect */
12240 out2fmt("sh: let: ");
12242 out2fmt("divide by zero");
12244 out2fmt("syntax error: \"%s=%s\"\n", argv[1], expression);
12247 snprintf(p, 12, "%ld", result);
12248 setvar(argv[1], xstrdup(p), 0);
12249 } else if (argc >= 3)
12250 synerror("invalid operand");
12258 * Copyright (c) 1989, 1991, 1993, 1994
12259 * The Regents of the University of California. All rights reserved.
12261 * This code is derived from software contributed to Berkeley by
12262 * Kenneth Almquist.
12264 * Redistribution and use in source and binary forms, with or without
12265 * modification, are permitted provided that the following conditions
12267 * 1. Redistributions of source code must retain the above copyright
12268 * notice, this list of conditions and the following disclaimer.
12269 * 2. Redistributions in binary form must reproduce the above copyright
12270 * notice, this list of conditions and the following disclaimer in the
12271 * documentation and/or other materials provided with the distribution.
12273 * 3. <BSD Advertising Clause omitted per the July 22, 1999 licensing change
12274 * ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change>
12276 * 4. Neither the name of the University nor the names of its contributors
12277 * may be used to endorse or promote products derived from this software
12278 * without specific prior written permission.
12280 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
12281 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
12282 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
12283 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
12284 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
12285 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
12286 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
12287 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
12288 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
12289 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF