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 * Copyright (c) 1997-2005 Herbert Xu <herbert@gondor.apana.org.au>
9 * was re-ported from NetBSD and debianized.
12 * This code is derived from software contributed to Berkeley by
15 * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
17 * Original BSD copyright notice is retained at the end of this file.
21 * rewrite arith.y to micro stack based cryptic algorithm by
22 * Copyright (c) 2001 Aaron Lehmann <aaronl@vitelus.com>
24 * Modified by Paul Mundt <lethal@linux-sh.org> (c) 2004 to support
27 * Modified by Vladimir Oleynik <dzo@simtreas.ru> (c) 2001-2005 to be
28 * used in busybox and size optimizations,
29 * rewrote arith (see notes to this), added locale support,
30 * rewrote dynamic variables.
36 * The follow should be set to reflect the type of system you have:
37 * JOBS -> 1 if you have Berkeley job control, 0 otherwise.
38 * define SYSV if you are running under System V.
39 * define DEBUG=1 to compile in debugging ('set -o debug' to turn on)
40 * define DEBUG=2 to compile in and turn on debugging.
42 * When debugging is on, debugging info will be written to ./trace and
43 * a quit signal will generate a core dump.
56 #include <sys/types.h>
57 #include <sys/ioctl.h>
58 #include <sys/param.h>
59 #include <sys/resource.h>
88 #ifdef CONFIG_ASH_JOB_CONTROL
94 #if JOBS || defined(CONFIG_ASH_READ_NCHARS)
102 static int *dash_errno;
104 #define errno (*dash_errno)
107 #if defined(__uClinux__)
108 #error "Do not even bother, ash will not run on uClinux"
112 #define _DIAGASSERT(assert_expr) assert(assert_expr)
114 #define _DIAGASSERT(assert_expr)
118 #ifdef CONFIG_ASH_ALIAS
131 static struct alias *lookupalias(const char *, int);
132 static int aliascmd(int, char **);
133 static int unaliascmd(int, char **);
134 static void rmaliases(void);
135 static int unalias(const char *);
136 static void printalias(const struct alias *);
142 static void setpwd(const char *, int);
148 * Types of operations (passed to the errmsg routine).
152 static const char not_found_msg[] = "%s: not found";
155 #define E_OPEN "No such file" /* opening a file */
156 #define E_CREAT "Directory nonexistent" /* creating a file */
157 #define E_EXEC not_found_msg+4 /* executing a program */
160 * We enclose jmp_buf in a structure so that we can declare pointers to
161 * jump locations. The global variable handler contains the location to
162 * jump to when an exception occurs, and the global variable exception
163 * contains a code identifying the exception. To implement nested
164 * exception handlers, the user should save the value of handler on entry
165 * to an inner scope, set handler to point to a jmploc structure for the
166 * inner scope, and restore handler on exit from the scope.
173 static struct jmploc *handler;
174 static int exception;
175 static volatile int suppressint;
176 static volatile sig_atomic_t intpending;
179 #define EXINT 0 /* SIGINT received */
180 #define EXERROR 1 /* a generic error */
181 #define EXSHELLPROC 2 /* execute a shell procedure */
182 #define EXEXEC 3 /* command execution failed */
183 #define EXEXIT 4 /* exit the shell */
184 #define EXSIG 5 /* trapped signal in wait(1) */
187 /* do we generate EXSIG events */
189 /* last pending signal */
190 static volatile sig_atomic_t pendingsigs;
193 * These macros allow the user to suspend the handling of interrupt signals
194 * over a period of time. This is similar to SIGHOLD to or sigblock, but
195 * much more efficient and portable. (But hacking the kernel is so much
196 * more fun than worrying about efficiency and portability. :-))
199 #define xbarrier() ({ __asm__ __volatile__ ("": : :"memory"); })
206 #define SAVEINT(v) ((v) = suppressint)
207 #define RESTOREINT(v) \
210 if ((suppressint = (v)) == 0 && intpending) onint(); \
221 /* EXSIG is turned off by evalbltin(). */
224 static void exraise(int) ATTRIBUTE_NORETURN;
225 static void onint(void) ATTRIBUTE_NORETURN;
227 static void sh_error(const char *, ...) ATTRIBUTE_NORETURN;
228 static void exerror(int, const char *, ...) ATTRIBUTE_NORETURN;
230 static void sh_warnx(const char *, ...);
232 #ifdef CONFIG_ASH_OPTIMIZE_FOR_SIZE
235 if (--suppressint == 0 && intpending) {
239 #define INTON inton()
240 static void forceinton(void)
246 #define FORCEINTON forceinton()
251 if (--suppressint == 0 && intpending) onint(); \
258 if (intpending) onint(); \
261 #endif /* CONFIG_ASH_OPTIMIZE_FOR_SIZE */
266 struct strlist *next;
272 struct strlist *list;
273 struct strlist **lastp;
279 #define EXP_FULL 0x1 /* perform word splitting & file globbing */
280 #define EXP_TILDE 0x2 /* do normal tilde expansion */
281 #define EXP_VARTILDE 0x4 /* expand tildes in an assignment */
282 #define EXP_REDIR 0x8 /* file glob for a redirection (1 match only) */
283 #define EXP_CASE 0x10 /* keeps quotes around for CASE pattern */
284 #define EXP_RECORD 0x20 /* need to record arguments for ifs breakup */
285 #define EXP_VARTILDE2 0x40 /* expand tildes after colons only */
286 #define EXP_WORD 0x80 /* expand word in parameter expansion */
287 #define EXP_QWORD 0x100 /* expand word in quoted parameter expansion */
291 static void expandarg(union node *, struct arglist *, int);
292 #define rmescapes(p) _rmescapes((p), 0)
293 static char *_rmescapes(char *, int);
294 static int casematch(union node *, char *);
296 #ifdef CONFIG_ASH_MATH_SUPPORT
297 static void expari(int);
302 static char *commandname; /* currently executing command */
303 static struct strlist *cmdenviron; /* environment for builtin command */
304 static int exitstatus; /* exit status of last command */
305 static int back_exitstatus; /* exit status of backquoted command */
308 struct backcmd { /* result of evalbackcmd */
309 int fd; /* file descriptor to read from */
310 char *buf; /* buffer */
311 int nleft; /* number of chars in buffer */
312 struct job *jp; /* job structure for command */
316 * This file was generated by the mknodes program.
352 union node *redirect;
359 struct nodelist *cmdlist;
366 union node *redirect;
381 union node *elsepart;
412 struct nodelist *backquote;
452 struct nredir nredir;
453 struct nbinary nbinary;
457 struct nclist nclist;
467 struct nodelist *next;
478 static void freefunc(struct funcnode *);
481 /* control characters in argument strings */
482 #define CTL_FIRST '\201' /* first 'special' character */
483 #define CTLESC '\201' /* escape next character */
484 #define CTLVAR '\202' /* variable defn */
485 #define CTLENDVAR '\203'
486 #define CTLBACKQ '\204'
487 #define CTLQUOTE 01 /* ored with CTLBACKQ code if in quotes */
488 /* CTLBACKQ | CTLQUOTE == '\205' */
489 #define CTLARI '\206' /* arithmetic expression */
490 #define CTLENDARI '\207'
491 #define CTLQUOTEMARK '\210'
492 #define CTL_LAST '\210' /* last 'special' character */
494 /* variable substitution byte (follows CTLVAR) */
495 #define VSTYPE 0x0f /* type of variable substitution */
496 #define VSNUL 0x10 /* colon--treat the empty string as unset */
497 #define VSQUOTE 0x80 /* inside double quotes--suppress splitting */
499 /* values of VSTYPE field */
500 #define VSNORMAL 0x1 /* normal variable: $var or ${var} */
501 #define VSMINUS 0x2 /* ${var-text} */
502 #define VSPLUS 0x3 /* ${var+text} */
503 #define VSQUESTION 0x4 /* ${var?message} */
504 #define VSASSIGN 0x5 /* ${var=text} */
505 #define VSTRIMRIGHT 0x6 /* ${var%pattern} */
506 #define VSTRIMRIGHTMAX 0x7 /* ${var%%pattern} */
507 #define VSTRIMLEFT 0x8 /* ${var#pattern} */
508 #define VSTRIMLEFTMAX 0x9 /* ${var##pattern} */
509 #define VSLENGTH 0xa /* ${#var} */
511 /* values of checkkwd variable */
516 #define IBUFSIZ (BUFSIZ + 1)
519 * NEOF is returned by parsecmd when it encounters an end of file. It
520 * must be distinct from NULL, so we use the address of a variable that
521 * happens to be handy.
523 static int plinno = 1; /* input line number */
525 /* number of characters left in input buffer */
526 static int parsenleft; /* copy of parsefile->nleft */
527 static int parselleft; /* copy of parsefile->lleft */
529 /* next character in input buffer */
530 static char *parsenextc; /* copy of parsefile->nextc */
533 struct strpush *prev; /* preceding string on stack */
536 #ifdef CONFIG_ASH_ALIAS
537 struct alias *ap; /* if push was associated with an alias */
539 char *string; /* remember the string since it may change */
543 struct parsefile *prev; /* preceding file on stack */
544 int linno; /* current line */
545 int fd; /* file descriptor (or -1 if string) */
546 int nleft; /* number of chars left in this line */
547 int lleft; /* number of chars left in this buffer */
548 char *nextc; /* next char in buffer */
549 char *buf; /* input buffer */
550 struct strpush *strpush; /* for pushing strings at this level */
551 struct strpush basestrpush; /* so pushing one is fast */
554 static struct parsefile basepf; /* top level input file */
555 #define basebuf bb_common_bufsiz1 /* buffer for top level input file */
556 static struct parsefile *parsefile = &basepf; /* current input file */
559 static int tokpushback; /* last token pushed back */
560 #define NEOF ((union node *)&tokpushback)
561 static int parsebackquote; /* nonzero if we are inside backquotes */
562 static int doprompt; /* if set, prompt the user */
563 static int needprompt; /* true if interactive and at start of line */
564 static int lasttoken; /* last token read */
565 static char *wordtext; /* text of last word returned by readtoken */
567 static struct nodelist *backquotelist;
568 static union node *redirnode;
569 static struct heredoc *heredoc;
570 static int quoteflag; /* set if (part of) last token was quoted */
571 static int startlinno; /* line # where last token started */
573 static union node *parsecmd(int);
574 static void fixredir(union node *, const char *, int);
575 static const char *const *findkwd(const char *);
576 static char *endofname(const char *);
580 typedef void *pointer;
582 static char nullstr[1]; /* zero length string */
583 static const char spcstr[] = " ";
584 static const char snlfmt[] = "%s\n";
585 static const char dolatstr[] = { CTLVAR, VSNORMAL|VSQUOTE, '@', '=', '\0' };
586 static const char illnum[] = "Illegal number: %s";
587 static const char homestr[] = "HOME";
590 #define TRACE(param) trace param
591 #define TRACEV(param) tracev param
594 #define TRACEV(param)
597 #if !defined(__GNUC__) || (__GNUC__ == 2 && __GNUC_MINOR__ < 96)
598 #define __builtin_expect(x, expected_value) (x)
601 #define xlikely(x) __builtin_expect((x),1)
616 #define TENDBQUOTE 12
634 /* first char is indicating which tokens mark the end of a list */
635 static const char *const tokname_array[] = {
650 /* the following are keywords */
669 static const char *tokname(int tok)
675 sprintf(buf + (tok >= TSEMI), "%s%c",
676 tokname_array[tok] + 1, (tok >= TSEMI ? '"' : 0));
683 * Most machines require the value returned from malloc to be aligned
684 * in some way. The following macro will get this right on many machines.
687 #define SHELL_SIZE (sizeof(union {int i; char *cp; double d; }) - 1)
689 * It appears that grabstackstr() will barf with such alignments
690 * because stalloc() will return a string allocated in a new stackblock.
692 #define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE)
695 * This file was generated by the mksyntax program.
700 #define CWORD 0 /* character is nothing special */
701 #define CNL 1 /* newline character */
702 #define CBACK 2 /* a backslash character */
703 #define CSQUOTE 3 /* single quote */
704 #define CDQUOTE 4 /* double quote */
705 #define CENDQUOTE 5 /* a terminating quote */
706 #define CBQUOTE 6 /* backwards single quote */
707 #define CVAR 7 /* a dollar sign */
708 #define CENDVAR 8 /* a '}' character */
709 #define CLP 9 /* a left paren in arithmetic */
710 #define CRP 10 /* a right paren in arithmetic */
711 #define CENDFILE 11 /* end of file */
712 #define CCTL 12 /* like CWORD, except it must be escaped */
713 #define CSPCL 13 /* these terminate a word */
714 #define CIGN 14 /* character should be ignored */
716 #ifdef CONFIG_ASH_ALIAS
720 #define PEOA_OR_PEOF PEOA
724 #define PEOA_OR_PEOF PEOF
727 #define is_digit(c) ((unsigned)((c) - '0') <= 9)
728 #define is_name(c) ((c) == '_' || isalpha((unsigned char)(c)))
729 #define is_in_name(c) ((c) == '_' || isalnum((unsigned char)(c)))
731 /* C99 say: "char" declaration may be signed or unsigned default */
732 #define SC2INT(chr2may_be_negative_int) (int)((signed char)chr2may_be_negative_int)
735 * is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
736 * (assuming ascii char codes, as the original implementation did)
738 #define is_special(c) \
739 ( (((unsigned int)c) - 33 < 32) \
740 && ((0xc1ff920dUL >> (((unsigned int)c) - 33)) & 1))
742 #define digit_val(c) ((c) - '0')
745 * This file was generated by the mksyntax program.
748 #ifdef CONFIG_ASH_OPTIMIZE_FOR_SIZE
749 #define USE_SIT_FUNCTION
752 /* number syntax index */
753 #define BASESYNTAX 0 /* not in quotes */
754 #define DQSYNTAX 1 /* in double quotes */
755 #define SQSYNTAX 2 /* in single quotes */
756 #define ARISYNTAX 3 /* in arithmetic */
758 #ifdef CONFIG_ASH_MATH_SUPPORT
759 static const char S_I_T[][4] = {
760 #ifdef CONFIG_ASH_ALIAS
761 {CSPCL, CIGN, CIGN, CIGN}, /* 0, PEOA */
763 {CSPCL, CWORD, CWORD, CWORD}, /* 1, ' ' */
764 {CNL, CNL, CNL, CNL}, /* 2, \n */
765 {CWORD, CCTL, CCTL, CWORD}, /* 3, !*-/:=?[]~ */
766 {CDQUOTE, CENDQUOTE, CWORD, CWORD}, /* 4, '"' */
767 {CVAR, CVAR, CWORD, CVAR}, /* 5, $ */
768 {CSQUOTE, CWORD, CENDQUOTE, CWORD}, /* 6, "'" */
769 {CSPCL, CWORD, CWORD, CLP}, /* 7, ( */
770 {CSPCL, CWORD, CWORD, CRP}, /* 8, ) */
771 {CBACK, CBACK, CCTL, CBACK}, /* 9, \ */
772 {CBQUOTE, CBQUOTE, CWORD, CBQUOTE}, /* 10, ` */
773 {CENDVAR, CENDVAR, CWORD, CENDVAR}, /* 11, } */
774 #ifndef USE_SIT_FUNCTION
775 {CENDFILE, CENDFILE, CENDFILE, CENDFILE}, /* 12, PEOF */
776 {CWORD, CWORD, CWORD, CWORD}, /* 13, 0-9A-Za-z */
777 {CCTL, CCTL, CCTL, CCTL} /* 14, CTLESC ... */
781 static const char S_I_T[][3] = {
782 #ifdef CONFIG_ASH_ALIAS
783 {CSPCL, CIGN, CIGN}, /* 0, PEOA */
785 {CSPCL, CWORD, CWORD}, /* 1, ' ' */
786 {CNL, CNL, CNL}, /* 2, \n */
787 {CWORD, CCTL, CCTL}, /* 3, !*-/:=?[]~ */
788 {CDQUOTE, CENDQUOTE, CWORD}, /* 4, '"' */
789 {CVAR, CVAR, CWORD}, /* 5, $ */
790 {CSQUOTE, CWORD, CENDQUOTE}, /* 6, "'" */
791 {CSPCL, CWORD, CWORD}, /* 7, ( */
792 {CSPCL, CWORD, CWORD}, /* 8, ) */
793 {CBACK, CBACK, CCTL}, /* 9, \ */
794 {CBQUOTE, CBQUOTE, CWORD}, /* 10, ` */
795 {CENDVAR, CENDVAR, CWORD}, /* 11, } */
796 #ifndef USE_SIT_FUNCTION
797 {CENDFILE, CENDFILE, CENDFILE}, /* 12, PEOF */
798 {CWORD, CWORD, CWORD}, /* 13, 0-9A-Za-z */
799 {CCTL, CCTL, CCTL} /* 14, CTLESC ... */
802 #endif /* CONFIG_ASH_MATH_SUPPORT */
804 #ifdef USE_SIT_FUNCTION
806 #define U_C(c) ((unsigned char)(c))
808 static int SIT(int c, int syntax)
810 static const char spec_symbls[] = "\t\n !\"$&'()*-/:;<=>?[\\]`|}~";
811 #ifdef CONFIG_ASH_ALIAS
812 static const char syntax_index_table[] = {
813 1, 2, 1, 3, 4, 5, 1, 6, /* "\t\n !\"$&'" */
814 7, 8, 3, 3, 3, 3, 1, 1, /* "()*-/:;<" */
815 3, 1, 3, 3, 9, 3, 10, 1, /* "=>?[\\]`|" */
819 static const char syntax_index_table[] = {
820 0, 1, 0, 2, 3, 4, 0, 5, /* "\t\n !\"$&'" */
821 6, 7, 2, 2, 2, 2, 0, 0, /* "()*-/:;<" */
822 2, 0, 2, 2, 8, 2, 9, 0, /* "=>?[\\]`|" */
829 if (c == PEOF) /* 2^8+2 */
831 #ifdef CONFIG_ASH_ALIAS
832 if (c == PEOA) /* 2^8+1 */
836 if (U_C(c) >= U_C(CTLESC) && U_C(c) <= U_C(CTLQUOTEMARK))
839 s = strchr(spec_symbls, c);
840 if (s == 0 || *s == 0)
842 indx = syntax_index_table[(s - spec_symbls)];
844 return S_I_T[indx][syntax];
847 #else /* USE_SIT_FUNCTION */
849 #define SIT(c, syntax) S_I_T[(int)syntax_index_table[((int)c)+SYNBASE]][syntax]
851 #ifdef CONFIG_ASH_ALIAS
852 #define CSPCL_CIGN_CIGN_CIGN 0
853 #define CSPCL_CWORD_CWORD_CWORD 1
854 #define CNL_CNL_CNL_CNL 2
855 #define CWORD_CCTL_CCTL_CWORD 3
856 #define CDQUOTE_CENDQUOTE_CWORD_CWORD 4
857 #define CVAR_CVAR_CWORD_CVAR 5
858 #define CSQUOTE_CWORD_CENDQUOTE_CWORD 6
859 #define CSPCL_CWORD_CWORD_CLP 7
860 #define CSPCL_CWORD_CWORD_CRP 8
861 #define CBACK_CBACK_CCTL_CBACK 9
862 #define CBQUOTE_CBQUOTE_CWORD_CBQUOTE 10
863 #define CENDVAR_CENDVAR_CWORD_CENDVAR 11
864 #define CENDFILE_CENDFILE_CENDFILE_CENDFILE 12
865 #define CWORD_CWORD_CWORD_CWORD 13
866 #define CCTL_CCTL_CCTL_CCTL 14
868 #define CSPCL_CWORD_CWORD_CWORD 0
869 #define CNL_CNL_CNL_CNL 1
870 #define CWORD_CCTL_CCTL_CWORD 2
871 #define CDQUOTE_CENDQUOTE_CWORD_CWORD 3
872 #define CVAR_CVAR_CWORD_CVAR 4
873 #define CSQUOTE_CWORD_CENDQUOTE_CWORD 5
874 #define CSPCL_CWORD_CWORD_CLP 6
875 #define CSPCL_CWORD_CWORD_CRP 7
876 #define CBACK_CBACK_CCTL_CBACK 8
877 #define CBQUOTE_CBQUOTE_CWORD_CBQUOTE 9
878 #define CENDVAR_CENDVAR_CWORD_CENDVAR 10
879 #define CENDFILE_CENDFILE_CENDFILE_CENDFILE 11
880 #define CWORD_CWORD_CWORD_CWORD 12
881 #define CCTL_CCTL_CCTL_CCTL 13
884 static const char syntax_index_table[258] = {
885 /* BASESYNTAX_DQSYNTAX_SQSYNTAX_ARISYNTAX */
886 /* 0 PEOF */ CENDFILE_CENDFILE_CENDFILE_CENDFILE,
887 #ifdef CONFIG_ASH_ALIAS
888 /* 1 PEOA */ CSPCL_CIGN_CIGN_CIGN,
890 /* 2 -128 0x80 */ CWORD_CWORD_CWORD_CWORD,
891 /* 3 -127 CTLESC */ CCTL_CCTL_CCTL_CCTL,
892 /* 4 -126 CTLVAR */ CCTL_CCTL_CCTL_CCTL,
893 /* 5 -125 CTLENDVAR */ CCTL_CCTL_CCTL_CCTL,
894 /* 6 -124 CTLBACKQ */ CCTL_CCTL_CCTL_CCTL,
895 /* 7 -123 CTLQUOTE */ CCTL_CCTL_CCTL_CCTL,
896 /* 8 -122 CTLARI */ CCTL_CCTL_CCTL_CCTL,
897 /* 9 -121 CTLENDARI */ CCTL_CCTL_CCTL_CCTL,
898 /* 10 -120 CTLQUOTEMARK */ CCTL_CCTL_CCTL_CCTL,
899 /* 11 -119 */ CWORD_CWORD_CWORD_CWORD,
900 /* 12 -118 */ CWORD_CWORD_CWORD_CWORD,
901 /* 13 -117 */ CWORD_CWORD_CWORD_CWORD,
902 /* 14 -116 */ CWORD_CWORD_CWORD_CWORD,
903 /* 15 -115 */ CWORD_CWORD_CWORD_CWORD,
904 /* 16 -114 */ CWORD_CWORD_CWORD_CWORD,
905 /* 17 -113 */ CWORD_CWORD_CWORD_CWORD,
906 /* 18 -112 */ CWORD_CWORD_CWORD_CWORD,
907 /* 19 -111 */ CWORD_CWORD_CWORD_CWORD,
908 /* 20 -110 */ CWORD_CWORD_CWORD_CWORD,
909 /* 21 -109 */ CWORD_CWORD_CWORD_CWORD,
910 /* 22 -108 */ CWORD_CWORD_CWORD_CWORD,
911 /* 23 -107 */ CWORD_CWORD_CWORD_CWORD,
912 /* 24 -106 */ CWORD_CWORD_CWORD_CWORD,
913 /* 25 -105 */ CWORD_CWORD_CWORD_CWORD,
914 /* 26 -104 */ CWORD_CWORD_CWORD_CWORD,
915 /* 27 -103 */ CWORD_CWORD_CWORD_CWORD,
916 /* 28 -102 */ CWORD_CWORD_CWORD_CWORD,
917 /* 29 -101 */ CWORD_CWORD_CWORD_CWORD,
918 /* 30 -100 */ CWORD_CWORD_CWORD_CWORD,
919 /* 31 -99 */ CWORD_CWORD_CWORD_CWORD,
920 /* 32 -98 */ CWORD_CWORD_CWORD_CWORD,
921 /* 33 -97 */ CWORD_CWORD_CWORD_CWORD,
922 /* 34 -96 */ CWORD_CWORD_CWORD_CWORD,
923 /* 35 -95 */ CWORD_CWORD_CWORD_CWORD,
924 /* 36 -94 */ CWORD_CWORD_CWORD_CWORD,
925 /* 37 -93 */ CWORD_CWORD_CWORD_CWORD,
926 /* 38 -92 */ CWORD_CWORD_CWORD_CWORD,
927 /* 39 -91 */ CWORD_CWORD_CWORD_CWORD,
928 /* 40 -90 */ CWORD_CWORD_CWORD_CWORD,
929 /* 41 -89 */ CWORD_CWORD_CWORD_CWORD,
930 /* 42 -88 */ CWORD_CWORD_CWORD_CWORD,
931 /* 43 -87 */ CWORD_CWORD_CWORD_CWORD,
932 /* 44 -86 */ CWORD_CWORD_CWORD_CWORD,
933 /* 45 -85 */ CWORD_CWORD_CWORD_CWORD,
934 /* 46 -84 */ CWORD_CWORD_CWORD_CWORD,
935 /* 47 -83 */ CWORD_CWORD_CWORD_CWORD,
936 /* 48 -82 */ CWORD_CWORD_CWORD_CWORD,
937 /* 49 -81 */ CWORD_CWORD_CWORD_CWORD,
938 /* 50 -80 */ CWORD_CWORD_CWORD_CWORD,
939 /* 51 -79 */ CWORD_CWORD_CWORD_CWORD,
940 /* 52 -78 */ CWORD_CWORD_CWORD_CWORD,
941 /* 53 -77 */ CWORD_CWORD_CWORD_CWORD,
942 /* 54 -76 */ CWORD_CWORD_CWORD_CWORD,
943 /* 55 -75 */ CWORD_CWORD_CWORD_CWORD,
944 /* 56 -74 */ CWORD_CWORD_CWORD_CWORD,
945 /* 57 -73 */ CWORD_CWORD_CWORD_CWORD,
946 /* 58 -72 */ CWORD_CWORD_CWORD_CWORD,
947 /* 59 -71 */ CWORD_CWORD_CWORD_CWORD,
948 /* 60 -70 */ CWORD_CWORD_CWORD_CWORD,
949 /* 61 -69 */ CWORD_CWORD_CWORD_CWORD,
950 /* 62 -68 */ CWORD_CWORD_CWORD_CWORD,
951 /* 63 -67 */ CWORD_CWORD_CWORD_CWORD,
952 /* 64 -66 */ CWORD_CWORD_CWORD_CWORD,
953 /* 65 -65 */ CWORD_CWORD_CWORD_CWORD,
954 /* 66 -64 */ CWORD_CWORD_CWORD_CWORD,
955 /* 67 -63 */ CWORD_CWORD_CWORD_CWORD,
956 /* 68 -62 */ CWORD_CWORD_CWORD_CWORD,
957 /* 69 -61 */ CWORD_CWORD_CWORD_CWORD,
958 /* 70 -60 */ CWORD_CWORD_CWORD_CWORD,
959 /* 71 -59 */ CWORD_CWORD_CWORD_CWORD,
960 /* 72 -58 */ CWORD_CWORD_CWORD_CWORD,
961 /* 73 -57 */ CWORD_CWORD_CWORD_CWORD,
962 /* 74 -56 */ CWORD_CWORD_CWORD_CWORD,
963 /* 75 -55 */ CWORD_CWORD_CWORD_CWORD,
964 /* 76 -54 */ CWORD_CWORD_CWORD_CWORD,
965 /* 77 -53 */ CWORD_CWORD_CWORD_CWORD,
966 /* 78 -52 */ CWORD_CWORD_CWORD_CWORD,
967 /* 79 -51 */ CWORD_CWORD_CWORD_CWORD,
968 /* 80 -50 */ CWORD_CWORD_CWORD_CWORD,
969 /* 81 -49 */ CWORD_CWORD_CWORD_CWORD,
970 /* 82 -48 */ CWORD_CWORD_CWORD_CWORD,
971 /* 83 -47 */ CWORD_CWORD_CWORD_CWORD,
972 /* 84 -46 */ CWORD_CWORD_CWORD_CWORD,
973 /* 85 -45 */ CWORD_CWORD_CWORD_CWORD,
974 /* 86 -44 */ CWORD_CWORD_CWORD_CWORD,
975 /* 87 -43 */ CWORD_CWORD_CWORD_CWORD,
976 /* 88 -42 */ CWORD_CWORD_CWORD_CWORD,
977 /* 89 -41 */ CWORD_CWORD_CWORD_CWORD,
978 /* 90 -40 */ CWORD_CWORD_CWORD_CWORD,
979 /* 91 -39 */ CWORD_CWORD_CWORD_CWORD,
980 /* 92 -38 */ CWORD_CWORD_CWORD_CWORD,
981 /* 93 -37 */ CWORD_CWORD_CWORD_CWORD,
982 /* 94 -36 */ CWORD_CWORD_CWORD_CWORD,
983 /* 95 -35 */ CWORD_CWORD_CWORD_CWORD,
984 /* 96 -34 */ CWORD_CWORD_CWORD_CWORD,
985 /* 97 -33 */ CWORD_CWORD_CWORD_CWORD,
986 /* 98 -32 */ CWORD_CWORD_CWORD_CWORD,
987 /* 99 -31 */ CWORD_CWORD_CWORD_CWORD,
988 /* 100 -30 */ CWORD_CWORD_CWORD_CWORD,
989 /* 101 -29 */ CWORD_CWORD_CWORD_CWORD,
990 /* 102 -28 */ CWORD_CWORD_CWORD_CWORD,
991 /* 103 -27 */ CWORD_CWORD_CWORD_CWORD,
992 /* 104 -26 */ CWORD_CWORD_CWORD_CWORD,
993 /* 105 -25 */ CWORD_CWORD_CWORD_CWORD,
994 /* 106 -24 */ CWORD_CWORD_CWORD_CWORD,
995 /* 107 -23 */ CWORD_CWORD_CWORD_CWORD,
996 /* 108 -22 */ CWORD_CWORD_CWORD_CWORD,
997 /* 109 -21 */ CWORD_CWORD_CWORD_CWORD,
998 /* 110 -20 */ CWORD_CWORD_CWORD_CWORD,
999 /* 111 -19 */ CWORD_CWORD_CWORD_CWORD,
1000 /* 112 -18 */ CWORD_CWORD_CWORD_CWORD,
1001 /* 113 -17 */ CWORD_CWORD_CWORD_CWORD,
1002 /* 114 -16 */ CWORD_CWORD_CWORD_CWORD,
1003 /* 115 -15 */ CWORD_CWORD_CWORD_CWORD,
1004 /* 116 -14 */ CWORD_CWORD_CWORD_CWORD,
1005 /* 117 -13 */ CWORD_CWORD_CWORD_CWORD,
1006 /* 118 -12 */ CWORD_CWORD_CWORD_CWORD,
1007 /* 119 -11 */ CWORD_CWORD_CWORD_CWORD,
1008 /* 120 -10 */ CWORD_CWORD_CWORD_CWORD,
1009 /* 121 -9 */ CWORD_CWORD_CWORD_CWORD,
1010 /* 122 -8 */ CWORD_CWORD_CWORD_CWORD,
1011 /* 123 -7 */ CWORD_CWORD_CWORD_CWORD,
1012 /* 124 -6 */ CWORD_CWORD_CWORD_CWORD,
1013 /* 125 -5 */ CWORD_CWORD_CWORD_CWORD,
1014 /* 126 -4 */ CWORD_CWORD_CWORD_CWORD,
1015 /* 127 -3 */ CWORD_CWORD_CWORD_CWORD,
1016 /* 128 -2 */ CWORD_CWORD_CWORD_CWORD,
1017 /* 129 -1 */ CWORD_CWORD_CWORD_CWORD,
1018 /* 130 0 */ CWORD_CWORD_CWORD_CWORD,
1019 /* 131 1 */ CWORD_CWORD_CWORD_CWORD,
1020 /* 132 2 */ CWORD_CWORD_CWORD_CWORD,
1021 /* 133 3 */ CWORD_CWORD_CWORD_CWORD,
1022 /* 134 4 */ CWORD_CWORD_CWORD_CWORD,
1023 /* 135 5 */ CWORD_CWORD_CWORD_CWORD,
1024 /* 136 6 */ CWORD_CWORD_CWORD_CWORD,
1025 /* 137 7 */ CWORD_CWORD_CWORD_CWORD,
1026 /* 138 8 */ CWORD_CWORD_CWORD_CWORD,
1027 /* 139 9 "\t" */ CSPCL_CWORD_CWORD_CWORD,
1028 /* 140 10 "\n" */ CNL_CNL_CNL_CNL,
1029 /* 141 11 */ CWORD_CWORD_CWORD_CWORD,
1030 /* 142 12 */ CWORD_CWORD_CWORD_CWORD,
1031 /* 143 13 */ CWORD_CWORD_CWORD_CWORD,
1032 /* 144 14 */ CWORD_CWORD_CWORD_CWORD,
1033 /* 145 15 */ CWORD_CWORD_CWORD_CWORD,
1034 /* 146 16 */ CWORD_CWORD_CWORD_CWORD,
1035 /* 147 17 */ CWORD_CWORD_CWORD_CWORD,
1036 /* 148 18 */ CWORD_CWORD_CWORD_CWORD,
1037 /* 149 19 */ CWORD_CWORD_CWORD_CWORD,
1038 /* 150 20 */ CWORD_CWORD_CWORD_CWORD,
1039 /* 151 21 */ CWORD_CWORD_CWORD_CWORD,
1040 /* 152 22 */ CWORD_CWORD_CWORD_CWORD,
1041 /* 153 23 */ CWORD_CWORD_CWORD_CWORD,
1042 /* 154 24 */ CWORD_CWORD_CWORD_CWORD,
1043 /* 155 25 */ CWORD_CWORD_CWORD_CWORD,
1044 /* 156 26 */ CWORD_CWORD_CWORD_CWORD,
1045 /* 157 27 */ CWORD_CWORD_CWORD_CWORD,
1046 /* 158 28 */ CWORD_CWORD_CWORD_CWORD,
1047 /* 159 29 */ CWORD_CWORD_CWORD_CWORD,
1048 /* 160 30 */ CWORD_CWORD_CWORD_CWORD,
1049 /* 161 31 */ CWORD_CWORD_CWORD_CWORD,
1050 /* 162 32 " " */ CSPCL_CWORD_CWORD_CWORD,
1051 /* 163 33 "!" */ CWORD_CCTL_CCTL_CWORD,
1052 /* 164 34 """ */ CDQUOTE_CENDQUOTE_CWORD_CWORD,
1053 /* 165 35 "#" */ CWORD_CWORD_CWORD_CWORD,
1054 /* 166 36 "$" */ CVAR_CVAR_CWORD_CVAR,
1055 /* 167 37 "%" */ CWORD_CWORD_CWORD_CWORD,
1056 /* 168 38 "&" */ CSPCL_CWORD_CWORD_CWORD,
1057 /* 169 39 "'" */ CSQUOTE_CWORD_CENDQUOTE_CWORD,
1058 /* 170 40 "(" */ CSPCL_CWORD_CWORD_CLP,
1059 /* 171 41 ")" */ CSPCL_CWORD_CWORD_CRP,
1060 /* 172 42 "*" */ CWORD_CCTL_CCTL_CWORD,
1061 /* 173 43 "+" */ CWORD_CWORD_CWORD_CWORD,
1062 /* 174 44 "," */ CWORD_CWORD_CWORD_CWORD,
1063 /* 175 45 "-" */ CWORD_CCTL_CCTL_CWORD,
1064 /* 176 46 "." */ CWORD_CWORD_CWORD_CWORD,
1065 /* 177 47 "/" */ CWORD_CCTL_CCTL_CWORD,
1066 /* 178 48 "0" */ CWORD_CWORD_CWORD_CWORD,
1067 /* 179 49 "1" */ CWORD_CWORD_CWORD_CWORD,
1068 /* 180 50 "2" */ CWORD_CWORD_CWORD_CWORD,
1069 /* 181 51 "3" */ CWORD_CWORD_CWORD_CWORD,
1070 /* 182 52 "4" */ CWORD_CWORD_CWORD_CWORD,
1071 /* 183 53 "5" */ CWORD_CWORD_CWORD_CWORD,
1072 /* 184 54 "6" */ CWORD_CWORD_CWORD_CWORD,
1073 /* 185 55 "7" */ CWORD_CWORD_CWORD_CWORD,
1074 /* 186 56 "8" */ CWORD_CWORD_CWORD_CWORD,
1075 /* 187 57 "9" */ CWORD_CWORD_CWORD_CWORD,
1076 /* 188 58 ":" */ CWORD_CCTL_CCTL_CWORD,
1077 /* 189 59 ";" */ CSPCL_CWORD_CWORD_CWORD,
1078 /* 190 60 "<" */ CSPCL_CWORD_CWORD_CWORD,
1079 /* 191 61 "=" */ CWORD_CCTL_CCTL_CWORD,
1080 /* 192 62 ">" */ CSPCL_CWORD_CWORD_CWORD,
1081 /* 193 63 "?" */ CWORD_CCTL_CCTL_CWORD,
1082 /* 194 64 "@" */ CWORD_CWORD_CWORD_CWORD,
1083 /* 195 65 "A" */ CWORD_CWORD_CWORD_CWORD,
1084 /* 196 66 "B" */ CWORD_CWORD_CWORD_CWORD,
1085 /* 197 67 "C" */ CWORD_CWORD_CWORD_CWORD,
1086 /* 198 68 "D" */ CWORD_CWORD_CWORD_CWORD,
1087 /* 199 69 "E" */ CWORD_CWORD_CWORD_CWORD,
1088 /* 200 70 "F" */ CWORD_CWORD_CWORD_CWORD,
1089 /* 201 71 "G" */ CWORD_CWORD_CWORD_CWORD,
1090 /* 202 72 "H" */ CWORD_CWORD_CWORD_CWORD,
1091 /* 203 73 "I" */ CWORD_CWORD_CWORD_CWORD,
1092 /* 204 74 "J" */ CWORD_CWORD_CWORD_CWORD,
1093 /* 205 75 "K" */ CWORD_CWORD_CWORD_CWORD,
1094 /* 206 76 "L" */ CWORD_CWORD_CWORD_CWORD,
1095 /* 207 77 "M" */ CWORD_CWORD_CWORD_CWORD,
1096 /* 208 78 "N" */ CWORD_CWORD_CWORD_CWORD,
1097 /* 209 79 "O" */ CWORD_CWORD_CWORD_CWORD,
1098 /* 210 80 "P" */ CWORD_CWORD_CWORD_CWORD,
1099 /* 211 81 "Q" */ CWORD_CWORD_CWORD_CWORD,
1100 /* 212 82 "R" */ CWORD_CWORD_CWORD_CWORD,
1101 /* 213 83 "S" */ CWORD_CWORD_CWORD_CWORD,
1102 /* 214 84 "T" */ CWORD_CWORD_CWORD_CWORD,
1103 /* 215 85 "U" */ CWORD_CWORD_CWORD_CWORD,
1104 /* 216 86 "V" */ CWORD_CWORD_CWORD_CWORD,
1105 /* 217 87 "W" */ CWORD_CWORD_CWORD_CWORD,
1106 /* 218 88 "X" */ CWORD_CWORD_CWORD_CWORD,
1107 /* 219 89 "Y" */ CWORD_CWORD_CWORD_CWORD,
1108 /* 220 90 "Z" */ CWORD_CWORD_CWORD_CWORD,
1109 /* 221 91 "[" */ CWORD_CCTL_CCTL_CWORD,
1110 /* 222 92 "\" */ CBACK_CBACK_CCTL_CBACK,
1111 /* 223 93 "]" */ CWORD_CCTL_CCTL_CWORD,
1112 /* 224 94 "^" */ CWORD_CWORD_CWORD_CWORD,
1113 /* 225 95 "_" */ CWORD_CWORD_CWORD_CWORD,
1114 /* 226 96 "`" */ CBQUOTE_CBQUOTE_CWORD_CBQUOTE,
1115 /* 227 97 "a" */ CWORD_CWORD_CWORD_CWORD,
1116 /* 228 98 "b" */ CWORD_CWORD_CWORD_CWORD,
1117 /* 229 99 "c" */ CWORD_CWORD_CWORD_CWORD,
1118 /* 230 100 "d" */ CWORD_CWORD_CWORD_CWORD,
1119 /* 231 101 "e" */ CWORD_CWORD_CWORD_CWORD,
1120 /* 232 102 "f" */ CWORD_CWORD_CWORD_CWORD,
1121 /* 233 103 "g" */ CWORD_CWORD_CWORD_CWORD,
1122 /* 234 104 "h" */ CWORD_CWORD_CWORD_CWORD,
1123 /* 235 105 "i" */ CWORD_CWORD_CWORD_CWORD,
1124 /* 236 106 "j" */ CWORD_CWORD_CWORD_CWORD,
1125 /* 237 107 "k" */ CWORD_CWORD_CWORD_CWORD,
1126 /* 238 108 "l" */ CWORD_CWORD_CWORD_CWORD,
1127 /* 239 109 "m" */ CWORD_CWORD_CWORD_CWORD,
1128 /* 240 110 "n" */ CWORD_CWORD_CWORD_CWORD,
1129 /* 241 111 "o" */ CWORD_CWORD_CWORD_CWORD,
1130 /* 242 112 "p" */ CWORD_CWORD_CWORD_CWORD,
1131 /* 243 113 "q" */ CWORD_CWORD_CWORD_CWORD,
1132 /* 244 114 "r" */ CWORD_CWORD_CWORD_CWORD,
1133 /* 245 115 "s" */ CWORD_CWORD_CWORD_CWORD,
1134 /* 246 116 "t" */ CWORD_CWORD_CWORD_CWORD,
1135 /* 247 117 "u" */ CWORD_CWORD_CWORD_CWORD,
1136 /* 248 118 "v" */ CWORD_CWORD_CWORD_CWORD,
1137 /* 249 119 "w" */ CWORD_CWORD_CWORD_CWORD,
1138 /* 250 120 "x" */ CWORD_CWORD_CWORD_CWORD,
1139 /* 251 121 "y" */ CWORD_CWORD_CWORD_CWORD,
1140 /* 252 122 "z" */ CWORD_CWORD_CWORD_CWORD,
1141 /* 253 123 "{" */ CWORD_CWORD_CWORD_CWORD,
1142 /* 254 124 "|" */ CSPCL_CWORD_CWORD_CWORD,
1143 /* 255 125 "}" */ CENDVAR_CENDVAR_CWORD_CENDVAR,
1144 /* 256 126 "~" */ CWORD_CCTL_CCTL_CWORD,
1145 /* 257 127 */ CWORD_CWORD_CWORD_CWORD,
1148 #endif /* USE_SIT_FUNCTION */
1155 static int funcblocksize; /* size of structures in function */
1156 static int funcstringsize; /* size of strings in node */
1157 static pointer funcblock; /* block to allocate function from */
1158 static char *funcstring; /* block to allocate strings from */
1160 static const short nodesize[26] = {
1161 SHELL_ALIGN(sizeof (struct ncmd)),
1162 SHELL_ALIGN(sizeof (struct npipe)),
1163 SHELL_ALIGN(sizeof (struct nredir)),
1164 SHELL_ALIGN(sizeof (struct nredir)),
1165 SHELL_ALIGN(sizeof (struct nredir)),
1166 SHELL_ALIGN(sizeof (struct nbinary)),
1167 SHELL_ALIGN(sizeof (struct nbinary)),
1168 SHELL_ALIGN(sizeof (struct nbinary)),
1169 SHELL_ALIGN(sizeof (struct nif)),
1170 SHELL_ALIGN(sizeof (struct nbinary)),
1171 SHELL_ALIGN(sizeof (struct nbinary)),
1172 SHELL_ALIGN(sizeof (struct nfor)),
1173 SHELL_ALIGN(sizeof (struct ncase)),
1174 SHELL_ALIGN(sizeof (struct nclist)),
1175 SHELL_ALIGN(sizeof (struct narg)),
1176 SHELL_ALIGN(sizeof (struct narg)),
1177 SHELL_ALIGN(sizeof (struct nfile)),
1178 SHELL_ALIGN(sizeof (struct nfile)),
1179 SHELL_ALIGN(sizeof (struct nfile)),
1180 SHELL_ALIGN(sizeof (struct nfile)),
1181 SHELL_ALIGN(sizeof (struct nfile)),
1182 SHELL_ALIGN(sizeof (struct ndup)),
1183 SHELL_ALIGN(sizeof (struct ndup)),
1184 SHELL_ALIGN(sizeof (struct nhere)),
1185 SHELL_ALIGN(sizeof (struct nhere)),
1186 SHELL_ALIGN(sizeof (struct nnot)),
1190 static void calcsize(union node *);
1191 static void sizenodelist(struct nodelist *);
1192 static union node *copynode(union node *);
1193 static struct nodelist *copynodelist(struct nodelist *);
1194 static char *nodesavestr(char *);
1197 static int evalstring(char *, int mask);
1198 union node; /* BLETCH for ansi C */
1199 static void evaltree(union node *, int);
1200 static void evalbackcmd(union node *, struct backcmd *);
1202 static int evalskip; /* set if we are skipping commands */
1203 static int skipcount; /* number of levels to skip */
1204 static int funcnest; /* depth of function calls */
1206 /* reasons for skipping commands (see comment on breakcmd routine) */
1207 #define SKIPBREAK (1 << 0)
1208 #define SKIPCONT (1 << 1)
1209 #define SKIPFUNC (1 << 2)
1210 #define SKIPFILE (1 << 3)
1211 #define SKIPEVAL (1 << 4)
1214 * This file was generated by the mkbuiltins program.
1218 static int bgcmd(int, char **);
1220 static int breakcmd(int, char **);
1221 static int cdcmd(int, char **);
1222 #ifdef CONFIG_ASH_CMDCMD
1223 static int commandcmd(int, char **);
1225 static int dotcmd(int, char **);
1226 static int evalcmd(int, char **);
1227 #ifdef CONFIG_ASH_BUILTIN_ECHO
1228 static int echocmd(int, char **);
1230 static int execcmd(int, char **);
1231 static int exitcmd(int, char **);
1232 static int exportcmd(int, char **);
1233 static int falsecmd(int, char **);
1235 static int fgcmd(int, char **);
1237 #ifdef CONFIG_ASH_GETOPTS
1238 static int getoptscmd(int, char **);
1240 static int hashcmd(int, char **);
1241 #ifndef CONFIG_FEATURE_SH_EXTRA_QUIET
1242 static int helpcmd(int argc, char **argv);
1245 static int jobscmd(int, char **);
1247 #ifdef CONFIG_ASH_MATH_SUPPORT
1248 static int letcmd(int, char **);
1250 static int localcmd(int, char **);
1251 static int pwdcmd(int, char **);
1252 static int readcmd(int, char **);
1253 static int returncmd(int, char **);
1254 static int setcmd(int, char **);
1255 static int shiftcmd(int, char **);
1256 static int timescmd(int, char **);
1257 static int trapcmd(int, char **);
1258 static int truecmd(int, char **);
1259 static int typecmd(int, char **);
1260 static int umaskcmd(int, char **);
1261 static int unsetcmd(int, char **);
1262 static int waitcmd(int, char **);
1263 static int ulimitcmd(int, char **);
1265 static int killcmd(int, char **);
1270 #ifdef CONFIG_ASH_MAIL
1271 static void chkmail(void);
1272 static void changemail(const char *);
1277 /* values of cmdtype */
1278 #define CMDUNKNOWN -1 /* no entry in table for command */
1279 #define CMDNORMAL 0 /* command is an executable program */
1280 #define CMDFUNCTION 1 /* command is a shell function */
1281 #define CMDBUILTIN 2 /* command is a shell builtin */
1285 int (*builtin)(int, char **);
1286 /* unsigned flags; */
1290 #define COMMANDCMD (builtincmd + 5 + \
1291 ENABLE_ASH_ALIAS + ENABLE_ASH_JOB_CONTROL)
1292 #define EXECCMD (builtincmd + 7 + \
1293 ENABLE_ASH_CMDCMD + ENABLE_ASH_ALIAS + \
1294 ENABLE_ASH_BUILTIN_ECHO + ENABLE_ASH_JOB_CONTROL)
1296 #define BUILTIN_NOSPEC "0"
1297 #define BUILTIN_SPECIAL "1"
1298 #define BUILTIN_REGULAR "2"
1299 #define BUILTIN_SPEC_REG "3"
1300 #define BUILTIN_ASSIGN "4"
1301 #define BUILTIN_SPEC_ASSG "5"
1302 #define BUILTIN_REG_ASSG "6"
1303 #define BUILTIN_SPEC_REG_ASSG "7"
1305 #define IS_BUILTIN_SPECIAL(builtincmd) ((builtincmd)->name[0] & 1)
1306 #define IS_BUILTIN_REGULAR(builtincmd) ((builtincmd)->name[0] & 2)
1307 #define IS_BUILTIN_ASSIGN(builtincmd) ((builtincmd)->name[0] & 4)
1309 static const struct builtincmd builtincmd[] = {
1310 { BUILTIN_SPEC_REG ".", dotcmd },
1311 { BUILTIN_SPEC_REG ":", truecmd },
1312 #ifdef CONFIG_ASH_ALIAS
1313 { BUILTIN_REG_ASSG "alias", aliascmd },
1316 { BUILTIN_REGULAR "bg", bgcmd },
1318 { BUILTIN_SPEC_REG "break", breakcmd },
1319 { BUILTIN_REGULAR "cd", cdcmd },
1320 { BUILTIN_NOSPEC "chdir", cdcmd },
1321 #ifdef CONFIG_ASH_CMDCMD
1322 { BUILTIN_REGULAR "command", commandcmd },
1324 { BUILTIN_SPEC_REG "continue", breakcmd },
1325 #ifdef CONFIG_ASH_BUILTIN_ECHO
1326 { BUILTIN_REGULAR "echo", echocmd },
1328 { BUILTIN_SPEC_REG "eval", evalcmd },
1329 { BUILTIN_SPEC_REG "exec", execcmd },
1330 { BUILTIN_SPEC_REG "exit", exitcmd },
1331 { BUILTIN_SPEC_REG_ASSG "export", exportcmd },
1332 { BUILTIN_REGULAR "false", falsecmd },
1334 { BUILTIN_REGULAR "fg", fgcmd },
1336 #ifdef CONFIG_ASH_GETOPTS
1337 { BUILTIN_REGULAR "getopts", getoptscmd },
1339 { BUILTIN_NOSPEC "hash", hashcmd },
1340 #ifndef CONFIG_FEATURE_SH_EXTRA_QUIET
1341 { BUILTIN_NOSPEC "help", helpcmd },
1344 { BUILTIN_REGULAR "jobs", jobscmd },
1345 { BUILTIN_REGULAR "kill", killcmd },
1347 #ifdef CONFIG_ASH_MATH_SUPPORT
1348 { BUILTIN_NOSPEC "let", letcmd },
1350 { BUILTIN_ASSIGN "local", localcmd },
1351 { BUILTIN_NOSPEC "pwd", pwdcmd },
1352 { BUILTIN_REGULAR "read", readcmd },
1353 { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd },
1354 { BUILTIN_SPEC_REG "return", returncmd },
1355 { BUILTIN_SPEC_REG "set", setcmd },
1356 { BUILTIN_SPEC_REG "shift", shiftcmd },
1357 { BUILTIN_SPEC_REG "times", timescmd },
1358 { BUILTIN_SPEC_REG "trap", trapcmd },
1359 { BUILTIN_REGULAR "true", truecmd },
1360 { BUILTIN_NOSPEC "type", typecmd },
1361 { BUILTIN_NOSPEC "ulimit", ulimitcmd },
1362 { BUILTIN_REGULAR "umask", umaskcmd },
1363 #ifdef CONFIG_ASH_ALIAS
1364 { BUILTIN_REGULAR "unalias", unaliascmd },
1366 { BUILTIN_SPEC_REG "unset", unsetcmd },
1367 { BUILTIN_REGULAR "wait", waitcmd },
1370 #define NUMBUILTINS (sizeof (builtincmd) / sizeof (struct builtincmd) )
1378 const struct builtincmd *cmd;
1379 struct funcnode *func;
1384 /* action to find_command() */
1385 #define DO_ERR 0x01 /* prints errors */
1386 #define DO_ABS 0x02 /* checks absolute paths */
1387 #define DO_NOFUNC 0x04 /* don't return shell functions, for command */
1388 #define DO_ALTPATH 0x08 /* using alternate path */
1389 #define DO_ALTBLTIN 0x20 /* %builtin in alt. path */
1391 static const char *pathopt; /* set by padvance */
1393 static void shellexec(char **, const char *, int)
1395 static char *padvance(const char **, const char *);
1396 static void find_command(char *, struct cmdentry *, int, const char *);
1397 static struct builtincmd *find_builtin(const char *);
1398 static void hashcd(void);
1399 static void changepath(const char *);
1400 static void defun(char *, union node *);
1401 static void unsetfunc(const char *);
1403 #ifdef CONFIG_ASH_MATH_SUPPORT_64
1404 typedef int64_t arith_t;
1406 typedef long arith_t;
1409 #ifdef CONFIG_ASH_MATH_SUPPORT
1410 static arith_t dash_arith(const char *);
1411 static arith_t arith(const char *expr, int *perrcode);
1414 #ifdef CONFIG_ASH_RANDOM_SUPPORT
1415 static unsigned long rseed;
1416 static void change_random(const char *);
1417 # ifndef DYNAMIC_VAR
1418 # define DYNAMIC_VAR
1424 static void reset(void);
1433 #define VEXPORT 0x01 /* variable is exported */
1434 #define VREADONLY 0x02 /* variable cannot be modified */
1435 #define VSTRFIXED 0x04 /* variable struct is statically allocated */
1436 #define VTEXTFIXED 0x08 /* text is statically allocated */
1437 #define VSTACK 0x10 /* text is allocated on the stack */
1438 #define VUNSET 0x20 /* the variable is not set */
1439 #define VNOFUNC 0x40 /* don't call the callback function */
1440 #define VNOSET 0x80 /* do not set variable - just readonly test */
1441 #define VNOSAVE 0x100 /* when text is on the heap before setvareq */
1443 # define VDYNAMIC 0x200 /* dynamic variable */
1449 struct var *next; /* next entry in hash list */
1450 int flags; /* flags are defined above */
1451 const char *text; /* name=value */
1452 void (*func)(const char *); /* function to be called when */
1453 /* the variable gets set/unset */
1457 struct localvar *next; /* next local variable in list */
1458 struct var *vp; /* the variable that was made local */
1459 int flags; /* saved flags */
1460 const char *text; /* saved text */
1464 static struct localvar *localvars;
1470 #ifdef CONFIG_ASH_GETOPTS
1471 static void getoptsreset(const char *);
1474 #ifdef CONFIG_LOCALE_SUPPORT
1476 static void change_lc_all(const char *value);
1477 static void change_lc_ctype(const char *value);
1483 static const char defpathvar[] = "PATH=/usr/local/bin:/usr/bin:/sbin:/bin";
1485 static const char defifsvar[] = "IFS= \t\n";
1486 #define defifs (defifsvar + 4)
1488 static const char defifs[] = " \t\n";
1492 static struct var varinit[] = {
1494 { 0, VSTRFIXED|VTEXTFIXED, defifsvar, 0 },
1496 { 0, VSTRFIXED|VTEXTFIXED|VUNSET, "IFS\0", 0 },
1499 #ifdef CONFIG_ASH_MAIL
1500 { 0, VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL\0", changemail },
1501 { 0, VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH\0", changemail },
1504 { 0, VSTRFIXED|VTEXTFIXED, defpathvar, changepath },
1505 { 0, VSTRFIXED|VTEXTFIXED, "PS1=$ ", 0 },
1506 { 0, VSTRFIXED|VTEXTFIXED, "PS2=> ", 0 },
1507 { 0, VSTRFIXED|VTEXTFIXED, "PS4=+ ", 0 },
1508 #ifdef CONFIG_ASH_GETOPTS
1509 { 0, VSTRFIXED|VTEXTFIXED, "OPTIND=1", getoptsreset },
1511 #ifdef CONFIG_ASH_RANDOM_SUPPORT
1512 {0, VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM\0", change_random },
1514 #ifdef CONFIG_LOCALE_SUPPORT
1515 {0, VSTRFIXED | VTEXTFIXED | VUNSET, "LC_ALL\0", change_lc_all },
1516 {0, VSTRFIXED | VTEXTFIXED | VUNSET, "LC_CTYPE\0", change_lc_ctype },
1518 #ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
1519 {0, VSTRFIXED | VTEXTFIXED | VUNSET, "HISTFILE\0", NULL },
1523 #define vifs varinit[0]
1524 #ifdef CONFIG_ASH_MAIL
1525 #define vmail (&vifs)[1]
1526 #define vmpath (&vmail)[1]
1530 #define vpath (&vmpath)[1]
1531 #define vps1 (&vpath)[1]
1532 #define vps2 (&vps1)[1]
1533 #define vps4 (&vps2)[1]
1534 #define voptind (&vps4)[1]
1535 #ifdef CONFIG_ASH_GETOPTS
1536 #define vrandom (&voptind)[1]
1538 #define vrandom (&vps4)[1]
1540 #define defpath (defpathvar + 5)
1543 * The following macros access the values of the above variables.
1544 * They have to skip over the name. They return the null string
1545 * for unset variables.
1548 #define ifsval() (vifs.text + 4)
1549 #define ifsset() ((vifs.flags & VUNSET) == 0)
1550 #define mailval() (vmail.text + 5)
1551 #define mpathval() (vmpath.text + 9)
1552 #define pathval() (vpath.text + 5)
1553 #define ps1val() (vps1.text + 4)
1554 #define ps2val() (vps2.text + 4)
1555 #define ps4val() (vps4.text + 4)
1556 #define optindval() (voptind.text + 7)
1558 #define mpathset() ((vmpath.flags & VUNSET) == 0)
1560 static void setvar(const char *, const char *, int);
1561 static void setvareq(char *, int);
1562 static void listsetvar(struct strlist *, int);
1563 static char *lookupvar(const char *);
1564 static char *bltinlookup(const char *);
1565 static char **listvars(int, int, char ***);
1566 #define environment() listvars(VEXPORT, VUNSET, 0)
1567 static int showvars(const char *, int, int);
1568 static void poplocalvars(void);
1569 static int unsetvar(const char *);
1570 #ifdef CONFIG_ASH_GETOPTS
1571 static int setvarsafe(const char *, const char *, int);
1573 static int varcmp(const char *, const char *);
1574 static struct var **hashvar(const char *);
1577 static inline int varequal(const char *a, const char *b) {
1578 return !varcmp(a, b);
1582 static int loopnest; /* current loop nesting level */
1585 * The parsefile structure pointed to by the global variable parsefile
1586 * contains information about the current file being read.
1591 struct redirtab *next;
1596 static struct redirtab *redirlist;
1597 static int nullredirs;
1599 extern char **environ;
1604 static void outstr(const char *, FILE *);
1605 static void outcslow(int, FILE *);
1606 static void flushall(void);
1607 static void flusherr(void);
1608 static int out1fmt(const char *, ...)
1609 __attribute__((__format__(__printf__,1,2)));
1610 static int fmtstr(char *, size_t, const char *, ...)
1611 __attribute__((__format__(__printf__,3,4)));
1613 static int preverrout_fd; /* save fd2 before print debug if xflag is set. */
1616 static void out1str(const char *p)
1621 static void out2str(const char *p)
1628 * Initialization code.
1632 * This routine initializes the builtin variables.
1643 * PS1 depends on uid
1645 #if defined(CONFIG_FEATURE_COMMAND_EDITING) && defined(CONFIG_FEATURE_SH_FANCY_PROMPT)
1646 vps1.text = "PS1=\\w \\$ ";
1649 vps1.text = "PS1=# ";
1652 end = vp + sizeof(varinit) / sizeof(varinit[0]);
1654 vpp = hashvar(vp->text);
1657 } while (++vp < end);
1666 basepf.nextc = basepf.buf = basebuf;
1671 signal(SIGCHLD, SIG_DFL);
1679 struct stat st1, st2;
1682 for (envp = environ ; envp && *envp ; envp++) {
1683 if (strchr(*envp, '=')) {
1684 setvareq(*envp, VEXPORT|VTEXTFIXED);
1688 snprintf(ppid, sizeof(ppid), "%d", (int) getppid());
1689 setvar("PPID", ppid, 0);
1691 p = lookupvar("PWD");
1693 if (*p != '/' || stat(p, &st1) || stat(".", &st2) ||
1694 st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino)
1700 /* PEOF (the end of file marker) */
1703 INPUT_PUSH_FILE = 1,
1704 INPUT_NOFILE_OK = 2,
1708 * The input line number. Input.c just defines this variable, and saves
1709 * and restores it when files are pushed and popped. The user of this
1710 * package must set its value.
1713 static int pgetc(void);
1714 static int pgetc2(void);
1715 static int preadbuffer(void);
1716 static void pungetc(void);
1717 static void pushstring(char *, void *);
1718 static void popstring(void);
1719 static void setinputfd(int, int);
1720 static void setinputstring(char *);
1721 static void popfile(void);
1722 static void popallfiles(void);
1723 static void closescript(void);
1729 /* Mode argument to forkshell. Don't change FORK_FG or FORK_BG. */
1732 #define FORK_NOJOB 2
1734 /* mode flags for showjob(s) */
1735 #define SHOW_PGID 0x01 /* only show pgid - for jobs -p */
1736 #define SHOW_PID 0x04 /* include process pid */
1737 #define SHOW_CHANGED 0x08 /* only jobs whose state has changed */
1741 * A job structure contains information about a job. A job is either a
1742 * single process or a set of processes contained in a pipeline. In the
1743 * latter case, pidlist will be non-NULL, and will point to a -1 terminated
1748 pid_t pid; /* process id */
1749 int status; /* last process status from wait() */
1750 char *cmd; /* text of command being run */
1754 struct procstat ps0; /* status of process */
1755 struct procstat *ps; /* status or processes when more than one */
1757 int stopstatus; /* status of a stopped job */
1760 nprocs: 16, /* number of processes */
1762 #define JOBRUNNING 0 /* at least one proc running */
1763 #define JOBSTOPPED 1 /* all procs are stopped */
1764 #define JOBDONE 2 /* all procs are completed */
1766 sigint: 1, /* job was killed by SIGINT */
1767 jobctl: 1, /* job running under job control */
1769 waited: 1, /* true if this entry has been waited for */
1770 used: 1, /* true if this entry is in used */
1771 changed: 1; /* true if status has changed */
1772 struct job *prev_job; /* previous job */
1775 static pid_t backgndpid; /* pid of last background process */
1776 static int job_warning; /* user was warned about stopped jobs */
1778 static int jobctl; /* true if doing job control */
1781 static struct job *makejob(union node *, int);
1782 static int forkshell(struct job *, union node *, int);
1783 static int waitforjob(struct job *);
1784 static int stoppedjobs(void);
1787 #define setjobctl(on) /* do nothing */
1789 static void setjobctl(int);
1790 static void showjobs(FILE *, int);
1796 /* pid of main shell */
1798 /* shell level: 0 for the main shell, 1 for its children, and so on */
1800 #define rootshell (!shlvl)
1802 static void readcmdfile(char *);
1803 static int cmdloop(int);
1809 struct stack_block *stackp;
1812 struct stackmark *marknext;
1815 /* minimum size of a block */
1816 #define MINSIZE SHELL_ALIGN(504)
1818 struct stack_block {
1819 struct stack_block *prev;
1820 char space[MINSIZE];
1823 static struct stack_block stackbase;
1824 static struct stack_block *stackp = &stackbase;
1825 static struct stackmark *markp;
1826 static char *stacknxt = stackbase.space;
1827 static size_t stacknleft = MINSIZE;
1828 static char *sstrend = stackbase.space + MINSIZE;
1829 static int herefd = -1;
1832 static pointer ckmalloc(size_t);
1833 static pointer ckrealloc(pointer, size_t);
1834 static char *savestr(const char *);
1835 static pointer stalloc(size_t);
1836 static void stunalloc(pointer);
1837 static void setstackmark(struct stackmark *);
1838 static void popstackmark(struct stackmark *);
1839 static void growstackblock(void);
1840 static void *growstackstr(void);
1841 static char *makestrspace(size_t, char *);
1842 static char *stnputs(const char *, size_t, char *);
1843 static char *stputs(const char *, char *);
1846 static inline char *_STPUTC(int c, char *p) {
1853 #define stackblock() ((void *)stacknxt)
1854 #define stackblocksize() stacknleft
1855 #define STARTSTACKSTR(p) ((p) = stackblock())
1856 #define STPUTC(c, p) ((p) = _STPUTC((c), (p)))
1857 #define CHECKSTRSPACE(n, p) \
1861 size_t m = sstrend - q; \
1863 (p) = makestrspace(l, q); \
1866 #define USTPUTC(c, p) (*p++ = (c))
1867 #define STACKSTRNUL(p) ((p) == sstrend? (p = growstackstr(), *p = '\0') : (*p = '\0'))
1868 #define STUNPUTC(p) (--p)
1869 #define STTOPC(p) p[-1]
1870 #define STADJUST(amount, p) (p += (amount))
1872 #define grabstackstr(p) stalloc((char *)(p) - (char *)stackblock())
1873 #define ungrabstackstr(s, p) stunalloc((s))
1874 #define stackstrend() ((void *)sstrend)
1876 #define ckfree(p) free((pointer)(p))
1881 #define DOLATSTRLEN 4
1883 static char *prefix(const char *, const char *);
1884 static int number(const char *);
1885 static int is_number(const char *);
1886 static char *single_quote(const char *);
1887 static char *sstrdup(const char *);
1889 #define equal(s1, s2) (strcmp(s1, s2) == 0)
1890 #define scopy(s1, s2) ((void)strcpy(s2, s1))
1895 int nparam; /* # of positional parameters (without $0) */
1896 unsigned char malloc; /* if parameter list dynamically allocated */
1897 char **p; /* parameter list */
1898 #ifdef CONFIG_ASH_GETOPTS
1899 int optind; /* next parameter to be processed by getopts */
1900 int optoff; /* used by getopts */
1905 #define eflag optlist[0]
1906 #define fflag optlist[1]
1907 #define Iflag optlist[2]
1908 #define iflag optlist[3]
1909 #define mflag optlist[4]
1910 #define nflag optlist[5]
1911 #define sflag optlist[6]
1912 #define xflag optlist[7]
1913 #define vflag optlist[8]
1914 #define Cflag optlist[9]
1915 #define aflag optlist[10]
1916 #define bflag optlist[11]
1917 #define uflag optlist[12]
1918 #define viflag optlist[13]
1921 #define nolog optlist[14]
1922 #define debug optlist[15]
1925 #ifndef CONFIG_FEATURE_COMMAND_EDITING_VI
1926 #define setvimode(on) viflag = 0 /* forcibly keep the option off */
1932 static const char *const optletters_optnames[] = {
1953 #define optletters(n) optletters_optnames[(n)][0]
1954 #define optnames(n) (&optletters_optnames[(n)][1])
1956 #define NOPTS (sizeof(optletters_optnames)/sizeof(optletters_optnames[0]))
1958 static char optlist[NOPTS];
1961 static char *arg0; /* value of $0 */
1962 static struct shparam shellparam; /* $@ current positional parameters */
1963 static char **argptr; /* argument list for builtin commands */
1964 static char *optionarg; /* set by nextopt (like getopt) */
1965 static char *optptr; /* used by nextopt */
1967 static char *minusc; /* argument to -c option */
1970 static void procargs(int, char **);
1971 static void optschanged(void);
1972 static void setparam(char **);
1973 static void freeparam(volatile struct shparam *);
1974 static int shiftcmd(int, char **);
1975 static int setcmd(int, char **);
1976 static int nextopt(const char *);
1980 /* flags passed to redirect */
1981 #define REDIR_PUSH 01 /* save previous values of file descriptors */
1982 #define REDIR_SAVEFD2 03 /* set preverrout */
1985 static void redirect(union node *, int);
1986 static void popredir(int);
1987 static void clearredir(int);
1988 static int copyfd(int, int);
1989 static int redirectsafe(union node *, int);
1995 static void showtree(union node *);
1996 static void trace(const char *, ...);
1997 static void tracev(const char *, va_list);
1998 static void trargs(char **);
1999 static void trputc(int);
2000 static void trputs(const char *);
2001 static void opentrace(void);
2007 /* trap handler commands */
2008 static char *trap[NSIG];
2009 /* current value of signal */
2010 static char sigmode[NSIG - 1];
2011 /* indicates specified signal received */
2012 static char gotsig[NSIG - 1];
2014 static void clear_traps(void);
2015 static void setsignal(int);
2016 static void ignoresig(int);
2017 static void onsig(int);
2018 static int dotrap(void);
2019 static void setinteractive(int);
2020 static void exitshell(void) ATTRIBUTE_NORETURN;
2021 static int decode_signal(const char *, int);
2024 * This routine is called when an error or an interrupt occurs in an
2025 * interactive shell and control is returned to the main command loop.
2039 parselleft = parsenleft = 0; /* clear input buffer */
2043 /* from parser.c: */
2056 #ifdef CONFIG_ASH_ALIAS
2057 static struct alias *atab[ATABSIZE];
2059 static void setalias(const char *, const char *);
2060 static struct alias *freealias(struct alias *);
2061 static struct alias **__lookupalias(const char *);
2064 setalias(const char *name, const char *val)
2066 struct alias *ap, **app;
2068 app = __lookupalias(name);
2072 if (!(ap->flag & ALIASINUSE)) {
2075 ap->val = savestr(val);
2076 ap->flag &= ~ALIASDEAD;
2079 ap = ckmalloc(sizeof (struct alias));
2080 ap->name = savestr(name);
2081 ap->val = savestr(val);
2090 unalias(const char *name)
2094 app = __lookupalias(name);
2098 *app = freealias(*app);
2109 struct alias *ap, **app;
2113 for (i = 0; i < ATABSIZE; i++) {
2115 for (ap = *app; ap; ap = *app) {
2116 *app = freealias(*app);
2125 static struct alias *
2126 lookupalias(const char *name, int check)
2128 struct alias *ap = *__lookupalias(name);
2130 if (check && ap && (ap->flag & ALIASINUSE))
2136 * TODO - sort output
2139 aliascmd(int argc, char **argv)
2148 for (i = 0; i < ATABSIZE; i++)
2149 for (ap = atab[i]; ap; ap = ap->next) {
2154 while ((n = *++argv) != NULL) {
2155 if ((v = strchr(n+1, '=')) == NULL) { /* n+1: funny ksh stuff */
2156 if ((ap = *__lookupalias(n)) == NULL) {
2157 fprintf(stderr, "%s: %s not found\n", "alias", n);
2171 unaliascmd(int argc, char **argv)
2175 while ((i = nextopt("a")) != '\0') {
2181 for (i = 0; *argptr; argptr++) {
2182 if (unalias(*argptr)) {
2183 fprintf(stderr, "%s: %s not found\n", "unalias", *argptr);
2191 static struct alias *
2192 freealias(struct alias *ap) {
2195 if (ap->flag & ALIASINUSE) {
2196 ap->flag |= ALIASDEAD;
2208 printalias(const struct alias *ap) {
2209 out1fmt("%s=%s\n", ap->name, single_quote(ap->val));
2212 static struct alias **
2213 __lookupalias(const char *name) {
2214 unsigned int hashval;
2221 ch = (unsigned char)*p;
2225 ch = (unsigned char)*++p;
2227 app = &atab[hashval % ATABSIZE];
2229 for (; *app; app = &(*app)->next) {
2230 if (equal(name, (*app)->name)) {
2237 #endif /* CONFIG_ASH_ALIAS */
2243 * The cd and pwd commands.
2246 #define CD_PHYSICAL 1
2249 static int docd(const char *, int);
2250 static int cdopt(void);
2252 static char *curdir = nullstr; /* current working directory */
2253 static char *physdir = nullstr; /* physical working directory */
2262 while ((i = nextopt("LP"))) {
2264 flags ^= CD_PHYSICAL;
2273 cdcmd(int argc, char **argv)
2285 dest = bltinlookup(homestr);
2286 else if (dest[0] == '-' && dest[1] == '\0') {
2287 dest = bltinlookup("OLDPWD");
2309 if (!(path = bltinlookup("CDPATH"))) {
2317 p = padvance(&path, dest);
2318 if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
2322 if (!docd(p, flags))
2327 sh_error("can't cd to %s", dest);
2330 if (flags & CD_PRINT)
2331 out1fmt(snlfmt, curdir);
2337 * Update curdir (the name of the current directory) in response to a
2341 static inline const char *
2342 updatepwd(const char *dir)
2349 cdcomppath = sstrdup(dir);
2352 if (curdir == nullstr)
2354 new = stputs(curdir, new);
2356 new = makestrspace(strlen(dir) + 2, new);
2357 lim = stackblock() + 1;
2361 if (new > lim && *lim == '/')
2366 if (dir[1] == '/' && dir[2] != '/') {
2372 p = strtok(cdcomppath, "/");
2376 if (p[1] == '.' && p[2] == '\0') {
2383 } else if (p[1] == '\0')
2387 new = stputs(p, new);
2395 return stackblock();
2399 * Actually do the chdir. We also call hashcd to let the routines in exec.c
2400 * know that the current directory has changed.
2404 docd(const char *dest, int flags)
2406 const char *dir = 0;
2409 TRACE(("docd(\"%s\", %d) called\n", dest, flags));
2412 if (!(flags & CD_PHYSICAL)) {
2413 dir = updatepwd(dest);
2428 * Find out what the current directory is. If we already know the current
2429 * directory, this routine returns immediately.
2431 static inline char *
2434 char *dir = getcwd(0, 0);
2435 return dir ? dir : nullstr;
2439 pwdcmd(int argc, char **argv)
2442 const char *dir = curdir;
2446 if (physdir == nullstr)
2450 out1fmt(snlfmt, dir);
2455 setpwd(const char *val, int setold)
2459 oldcur = dir = curdir;
2462 setvar("OLDPWD", oldcur, VEXPORT);
2465 if (physdir != nullstr) {
2466 if (physdir != oldcur)
2470 if (oldcur == val || !val) {
2477 if (oldcur != dir && oldcur != nullstr) {
2482 setvar("PWD", dir, VEXPORT);
2488 * Errors and exceptions.
2492 * Code to handle exceptions in C.
2497 static void exverror(int, const char *, va_list)
2501 * Called to raise an exception. Since C doesn't include exceptions, we
2502 * just do a longjmp to the exception handler. The type of exception is
2503 * stored in the global variable "exception".
2510 if (handler == NULL)
2516 longjmp(handler->loc, 1);
2521 * Called from trap.c when a SIGINT is received. (If the user specifies
2522 * that SIGINT is to be trapped or ignored using the trap builtin, then
2523 * this routine is not called.) Suppressint is nonzero when interrupts
2524 * are held using the INTOFF macro. (The test for iflag is just
2525 * defensive programming.)
2534 /* comment by vodz: its strange for me, this programm don`t use other
2539 if (gotsig[SIGINT - 1] && !trap[SIGINT]) {
2540 if (!(rootshell && iflag)) {
2541 signal(SIGINT, SIG_DFL);
2551 exvwarning(const char *msg, va_list ap)
2556 fprintf(errs, "%s: ", arg0);
2558 const char *fmt = (!iflag || parsefile->fd) ?
2559 "%s: %d: " : "%s: ";
2560 fprintf(errs, fmt, commandname, startlinno);
2562 vfprintf(errs, msg, ap);
2563 outcslow('\n', errs);
2567 * Exverror is called to raise the error exception. If the second argument
2568 * is not NULL then error prints an error message using printf style
2569 * formatting. It then raises the error exception.
2572 exverror(int cond, const char *msg, va_list ap)
2576 TRACE(("exverror(%d, \"", cond));
2578 TRACE(("\") pid=%d\n", getpid()));
2580 TRACE(("exverror(%d, NULL) pid=%d\n", cond, getpid()));
2583 exvwarning(msg, ap);
2592 sh_error(const char *msg, ...)
2597 exverror(EXERROR, msg, ap);
2604 exerror(int cond, const char *msg, ...)
2609 exverror(cond, msg, ap);
2615 * error/warning routines for external builtins
2619 sh_warnx(const char *fmt, ...)
2624 exvwarning(fmt, ap);
2630 * Return a string describing an error. The returned string may be a
2631 * pointer to a static buffer that will be overwritten on the next call.
2632 * Action describes the operation that got the error.
2636 errmsg(int e, const char *em)
2638 if(e == ENOENT || e == ENOTDIR) {
2649 * Evaluate a command.
2652 /* flags in argument to evaltree */
2653 #define EV_EXIT 01 /* exit after evaluating tree */
2654 #define EV_TESTED 02 /* exit status is checked; ignore -e flag */
2655 #define EV_BACKCMD 04 /* command executing within back quotes */
2658 static void evalloop(union node *, int);
2659 static void evalfor(union node *, int);
2660 static void evalcase(union node *, int);
2661 static void evalsubshell(union node *, int);
2662 static void expredir(union node *);
2663 static void evalpipe(union node *, int);
2664 static void evalcommand(union node *, int);
2665 static int evalbltin(const struct builtincmd *, int, char **);
2666 static int evalfun(struct funcnode *, int, char **, int);
2667 static void prehash(union node *);
2668 static int bltincmd(int, char **);
2671 static const struct builtincmd bltin = {
2677 * Called to reset things after an exception.
2685 evalcmd(int argc, char **argv)
2694 STARTSTACKSTR(concat);
2697 concat = stputs(p, concat);
2698 if ((p = *ap++) == NULL)
2700 STPUTC(' ', concat);
2702 STPUTC('\0', concat);
2703 p = grabstackstr(concat);
2705 evalstring(p, ~SKIPEVAL);
2713 * Execute a command or commands contained in a string.
2717 evalstring(char *s, int mask)
2720 struct stackmark smark;
2724 setstackmark(&smark);
2727 while ((n = parsecmd(0)) != NEOF) {
2729 popstackmark(&smark);
2744 * Evaluate a parse tree. The value is left in the global variable
2749 evaltree(union node *n, int flags)
2752 void (*evalfn)(union node *, int);
2756 TRACE(("evaltree(NULL) called\n"));
2759 TRACE(("pid %d, evaltree(%p: %d, %d) called\n",
2760 getpid(), n, n->type, flags));
2764 out1fmt("Node type = %d\n", n->type);
2769 evaltree(n->nnot.com, EV_TESTED);
2770 status = !exitstatus;
2773 expredir(n->nredir.redirect);
2774 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
2776 evaltree(n->nredir.n, flags & EV_TESTED);
2777 status = exitstatus;
2782 evalfn = evalcommand;
2784 if (eflag && !(flags & EV_TESTED))
2796 evalfn = evalsubshell;
2808 #error NAND + 1 != NOR
2810 #if NOR + 1 != NSEMI
2811 #error NOR + 1 != NSEMI
2813 isor = n->type - NAND;
2816 (flags | ((isor >> 1) - 1)) & EV_TESTED
2818 if (!exitstatus == isor)
2830 evaltree(n->nif.test, EV_TESTED);
2833 if (exitstatus == 0) {
2836 } else if (n->nif.elsepart) {
2837 n = n->nif.elsepart;
2842 defun(n->narg.text, n->narg.next);
2846 exitstatus = status;
2850 if ((checkexit & exitstatus))
2851 evalskip |= SKIPEVAL;
2852 else if (pendingsigs && dotrap())
2855 if (flags & EV_EXIT) {
2862 #if !defined(__alpha__) || (defined(__GNUC__) && __GNUC__ >= 3)
2865 void evaltreenr(union node *, int) __attribute__ ((alias("evaltree"),__noreturn__));
2869 evalloop(union node *n, int flags)
2879 evaltree(n->nbinary.ch1, EV_TESTED);
2881 skipping: if (evalskip == SKIPCONT && --skipcount <= 0) {
2885 if (evalskip == SKIPBREAK && --skipcount <= 0)
2890 if (n->type != NWHILE)
2894 evaltree(n->nbinary.ch2, flags);
2895 status = exitstatus;
2900 exitstatus = status;
2906 evalfor(union node *n, int flags)
2908 struct arglist arglist;
2911 struct stackmark smark;
2913 setstackmark(&smark);
2914 arglist.lastp = &arglist.list;
2915 for (argp = n->nfor.args ; argp ; argp = argp->narg.next) {
2916 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE | EXP_RECORD);
2921 *arglist.lastp = NULL;
2926 for (sp = arglist.list ; sp ; sp = sp->next) {
2927 setvar(n->nfor.var, sp->text, 0);
2928 evaltree(n->nfor.body, flags);
2930 if (evalskip == SKIPCONT && --skipcount <= 0) {
2934 if (evalskip == SKIPBREAK && --skipcount <= 0)
2941 popstackmark(&smark);
2947 evalcase(union node *n, int flags)
2951 struct arglist arglist;
2952 struct stackmark smark;
2954 setstackmark(&smark);
2955 arglist.lastp = &arglist.list;
2956 expandarg(n->ncase.expr, &arglist, EXP_TILDE);
2958 for (cp = n->ncase.cases ; cp && evalskip == 0 ; cp = cp->nclist.next) {
2959 for (patp = cp->nclist.pattern ; patp ; patp = patp->narg.next) {
2960 if (casematch(patp, arglist.list->text)) {
2961 if (evalskip == 0) {
2962 evaltree(cp->nclist.body, flags);
2969 popstackmark(&smark);
2975 * Kick off a subshell to evaluate a tree.
2979 evalsubshell(union node *n, int flags)
2982 int backgnd = (n->type == NBACKGND);
2985 expredir(n->nredir.redirect);
2986 if (!backgnd && flags & EV_EXIT && !trap[0])
2990 if (forkshell(jp, n, backgnd) == 0) {
2994 flags &=~ EV_TESTED;
2996 redirect(n->nredir.redirect, 0);
2997 evaltreenr(n->nredir.n, flags);
3002 status = waitforjob(jp);
3003 exitstatus = status;
3010 * Compute the names of the files in a redirection list.
3014 expredir(union node *n)
3018 for (redir = n ; redir ; redir = redir->nfile.next) {
3020 fn.lastp = &fn.list;
3021 switch (redir->type) {
3027 expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
3028 redir->nfile.expfname = fn.list->text;
3032 if (redir->ndup.vname) {
3033 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
3034 fixredir(redir, fn.list->text, 1);
3044 * Evaluate a pipeline. All the processes in the pipeline are children
3045 * of the process creating the pipeline. (This differs from some versions
3046 * of the shell, which make the last process in a pipeline the parent
3051 evalpipe(union node *n, int flags)
3054 struct nodelist *lp;
3059 TRACE(("evalpipe(0x%lx) called\n", (long)n));
3061 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next)
3065 jp = makejob(n, pipelen);
3067 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
3071 if (pipe(pip) < 0) {
3073 sh_error("Pipe call failed");
3076 if (forkshell(jp, lp->n, n->npipe.backgnd) == 0) {
3089 evaltreenr(lp->n, flags);
3097 if (n->npipe.backgnd == 0) {
3098 exitstatus = waitforjob(jp);
3099 TRACE(("evalpipe: job done exit status %d\n", exitstatus));
3107 * Execute a command inside back quotes. If it's a builtin command, we
3108 * want to save its output in a block obtained from malloc. Otherwise
3109 * we fork off a subprocess and get the output of the command via a pipe.
3110 * Should be called with interrupts off.
3114 evalbackcmd(union node *n, struct backcmd *result)
3126 saveherefd = herefd;
3134 sh_error("Pipe call failed");
3136 if (forkshell(jp, n, FORK_NOJOB) == 0) {
3145 evaltreenr(n, EV_EXIT);
3149 result->fd = pip[0];
3152 herefd = saveherefd;
3154 TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
3155 result->fd, result->buf, result->nleft, result->jp));
3158 #ifdef CONFIG_ASH_CMDCMD
3159 static inline char **
3160 parse_command_args(char **argv, const char **path)
3172 if (c == '-' && !*cp) {
3182 /* run 'typecmd' for other options */
3185 } while ((c = *cp++));
3192 isassignment(const char *p)
3194 const char *q = endofname(p);
3200 #ifdef CONFIG_ASH_EXPAND_PRMT
3201 static const char *expandstr(const char *ps);
3203 #define expandstr(s) s
3207 * Execute a simple command.
3211 evalcommand(union node *cmd, int flags)
3213 struct stackmark smark;
3215 struct arglist arglist;
3216 struct arglist varlist;
3219 const struct strlist *sp;
3220 struct cmdentry cmdentry;
3228 struct builtincmd *bcmd;
3229 int pseudovarflag = 0;
3231 /* First expand the arguments. */
3232 TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
3233 setstackmark(&smark);
3234 back_exitstatus = 0;
3236 cmdentry.cmdtype = CMDBUILTIN;
3237 cmdentry.u.cmd = &bltin;
3238 varlist.lastp = &varlist.list;
3239 *varlist.lastp = NULL;
3240 arglist.lastp = &arglist.list;
3241 *arglist.lastp = NULL;
3246 bcmd = find_builtin(cmd->ncmd.args->narg.text);
3247 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
3250 for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
3251 struct strlist **spp;
3253 spp = arglist.lastp;
3254 if (pseudovarflag && isassignment(argp->narg.text))
3255 expandarg(argp, &arglist, EXP_VARTILDE);
3257 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
3259 for (sp = *spp; sp; sp = sp->next)
3263 argv = nargv = stalloc(sizeof (char *) * (argc + 1));
3264 for (sp = arglist.list ; sp ; sp = sp->next) {
3265 TRACE(("evalcommand arg: %s\n", sp->text));
3266 *nargv++ = sp->text;
3271 if (iflag && funcnest == 0 && argc > 0)
3272 lastarg = nargv[-1];
3275 expredir(cmd->ncmd.redirect);
3276 status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH|REDIR_SAVEFD2);
3279 for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
3280 struct strlist **spp;
3283 spp = varlist.lastp;
3284 expandarg(argp, &varlist, EXP_VARTILDE);
3287 * Modify the command lookup path, if a PATH= assignment
3291 if (varequal(p, path))
3295 /* Print the command if xflag is set. */
3298 const char *p = " %s";
3301 dprintf(preverrout_fd, p, expandstr(ps4val()));
3304 for(n = 0; n < 2; n++) {
3306 dprintf(preverrout_fd, p, sp->text);
3314 bb_full_write(preverrout_fd, "\n", 1);
3320 /* Now locate the command. */
3322 const char *oldpath;
3323 int cmd_flag = DO_ERR;
3328 find_command(argv[0], &cmdentry, cmd_flag, path);
3329 if (cmdentry.cmdtype == CMDUNKNOWN) {
3335 /* implement bltin and command here */
3336 if (cmdentry.cmdtype != CMDBUILTIN)
3339 spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
3340 if (cmdentry.u.cmd == EXECCMD)
3342 #ifdef CONFIG_ASH_CMDCMD
3343 if (cmdentry.u.cmd == COMMANDCMD) {
3346 nargv = parse_command_args(argv, &path);
3349 argc -= nargv - argv;
3351 cmd_flag |= DO_NOFUNC;
3359 /* We have a redirection error. */
3363 exitstatus = status;
3367 /* Execute the command. */
3368 switch (cmdentry.cmdtype) {
3370 /* Fork off a child process if necessary. */
3371 if (!(flags & EV_EXIT) || trap[0]) {
3373 jp = makejob(cmd, 1);
3374 if (forkshell(jp, cmd, FORK_FG) != 0) {
3375 exitstatus = waitforjob(jp);
3381 listsetvar(varlist.list, VEXPORT|VSTACK);
3382 shellexec(argv, path, cmdentry.u.index);
3386 cmdenviron = varlist.list;
3388 struct strlist *list = cmdenviron;
3390 if (spclbltin > 0 || argc == 0) {
3392 if (cmd_is_exec && argc > 1)
3395 listsetvar(list, i);
3397 if (evalbltin(cmdentry.u.cmd, argc, argv)) {
3412 exit_status = j + 128;
3413 exitstatus = exit_status;
3415 if (i == EXINT || spclbltin > 0) {
3417 longjmp(handler->loc, 1);
3424 listsetvar(varlist.list, 0);
3425 if (evalfun(cmdentry.u.func, argc, argv, flags))
3431 popredir(cmd_is_exec);
3433 /* dsl: I think this is intended to be used to support
3434 * '_' in 'vi' command mode during line editing...
3435 * However I implemented that within libedit itself.
3437 setvar("_", lastarg, 0);
3438 popstackmark(&smark);
3442 evalbltin(const struct builtincmd *cmd, int argc, char **argv) {
3443 char *volatile savecmdname;
3444 struct jmploc *volatile savehandler;
3445 struct jmploc jmploc;
3448 savecmdname = commandname;
3449 if ((i = setjmp(jmploc.loc)))
3451 savehandler = handler;
3453 commandname = argv[0];
3455 optptr = NULL; /* initialize nextopt */
3456 exitstatus = (*cmd->builtin)(argc, argv);
3459 exitstatus |= ferror(stdout);
3460 commandname = savecmdname;
3462 handler = savehandler;
3468 evalfun(struct funcnode *func, int argc, char **argv, int flags)
3470 volatile struct shparam saveparam;
3471 struct localvar *volatile savelocalvars;
3472 struct jmploc *volatile savehandler;
3473 struct jmploc jmploc;
3476 saveparam = shellparam;
3477 savelocalvars = localvars;
3478 if ((e = setjmp(jmploc.loc))) {
3482 savehandler = handler;
3485 shellparam.malloc = 0;
3489 shellparam.nparam = argc - 1;
3490 shellparam.p = argv + 1;
3491 #ifdef CONFIG_ASH_GETOPTS
3492 shellparam.optind = 1;
3493 shellparam.optoff = -1;
3495 evaltree(&func->n, flags & EV_TESTED);
3501 localvars = savelocalvars;
3502 freeparam(&shellparam);
3503 shellparam = saveparam;
3504 handler = savehandler;
3506 evalskip &= ~SKIPFUNC;
3512 goodname(const char *p)
3514 return !*endofname(p);
3518 * Search for a command. This is called before we fork so that the
3519 * location of the command will be available in the parent as well as
3520 * the child. The check for "goodname" is an overly conservative
3521 * check that the name will not be subject to expansion.
3525 prehash(union node *n)
3527 struct cmdentry entry;
3529 if (n->type == NCMD && n->ncmd.args)
3530 if (goodname(n->ncmd.args->narg.text))
3531 find_command(n->ncmd.args->narg.text, &entry, 0,
3538 * Builtin commands. Builtin commands whose functions are closely
3539 * tied to evaluation are implemented here.
3547 bltincmd(int argc, char **argv)
3550 * Preserve exitstatus of a previous possible redirection
3553 return back_exitstatus;
3558 * Handle break and continue commands. Break, continue, and return are
3559 * all handled by setting the evalskip flag. The evaluation routines
3560 * above all check this flag, and if it is set they start skipping
3561 * commands rather than executing them. The variable skipcount is
3562 * the number of loops to break/continue, or the number of function
3563 * levels to return. (The latter is always 1.) It should probably
3564 * be an error to break out of more loops than exist, but it isn't
3565 * in the standard shell so we don't make it one here.
3569 breakcmd(int argc, char **argv)
3571 int n = argc > 1 ? number(argv[1]) : 1;
3574 sh_error(illnum, argv[1]);
3578 evalskip = (**argv == 'c')? SKIPCONT : SKIPBREAK;
3586 * The return command.
3590 returncmd(int argc, char **argv)
3593 * If called outside a function, do what ksh does;
3594 * skip the rest of the file.
3596 evalskip = funcnest ? SKIPFUNC : SKIPFILE;
3597 return argv[1] ? number(argv[1]) : exitstatus;
3602 falsecmd(int argc, char **argv)
3609 truecmd(int argc, char **argv)
3616 execcmd(int argc, char **argv)
3619 iflag = 0; /* exit on error */
3622 shellexec(argv + 1, pathval(), 0);
3631 * When commands are first encountered, they are entered in a hash table.
3632 * This ensures that a full path search will not have to be done for them
3633 * on each invocation.
3635 * We should investigate converting to a linear search, even though that
3636 * would make the command name "hash" a misnomer.
3639 #define CMDTABLESIZE 31 /* should be prime */
3640 #define ARB 1 /* actual size determined at run time */
3645 struct tblentry *next; /* next entry in hash chain */
3646 union param param; /* definition of builtin function */
3647 short cmdtype; /* index identifying command */
3648 char rehash; /* if set, cd done since entry created */
3649 char cmdname[ARB]; /* name of command */
3653 static struct tblentry *cmdtable[CMDTABLESIZE];
3654 static int builtinloc = -1; /* index in path of %builtin, or -1 */
3657 static void tryexec(char *, char **, char **);
3658 static void clearcmdentry(int);
3659 static struct tblentry *cmdlookup(const char *, int);
3660 static void delete_cmd_entry(void);
3664 * Exec a program. Never returns. If you change this routine, you may
3665 * have to change the find_command routine as well.
3669 shellexec(char **argv, const char *path, int idx)
3677 envp = environment();
3678 if (strchr(argv[0], '/') != NULL
3679 #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
3680 || find_applet_by_name(argv[0])
3683 tryexec(argv[0], argv, envp);
3687 while ((cmdname = padvance(&path, argv[0])) != NULL) {
3688 if (--idx < 0 && pathopt == NULL) {
3689 tryexec(cmdname, argv, envp);
3690 if (errno != ENOENT && errno != ENOTDIR)
3697 /* Map to POSIX errors */
3709 exitstatus = exerrno;
3710 TRACE(("shellexec failed for %s, errno %d, suppressint %d\n",
3711 argv[0], e, suppressint ));
3712 exerror(EXEXEC, "%s: %s", argv[0], errmsg(e, E_EXEC));
3718 tryexec(char *cmd, char **argv, char **envp)
3721 #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
3722 if(find_applet_by_name(cmd) != NULL) {
3723 /* re-exec ourselves with the new arguments */
3724 execve("/proc/self/exe",argv,envp);
3725 /* If proc isn't mounted, try hardcoded path to busybox binary*/
3726 execve("/bin/busybox",argv,envp);
3727 /* If they called chroot or otherwise made the binary no longer
3728 * executable, fall through */
3735 execve(cmd, argv, envp);
3736 } while (errno == EINTR);
3738 execve(cmd, argv, envp);
3742 } else if (errno == ENOEXEC) {
3746 for (ap = argv; *ap; ap++)
3748 ap = new = ckmalloc((ap - argv + 2) * sizeof(char *));
3750 *ap = cmd = (char *)DEFAULT_SHELL;
3753 while ((*ap++ = *argv++))
3763 * Do a path search. The variable path (passed by reference) should be
3764 * set to the start of the path before the first call; padvance will update
3765 * this value as it proceeds. Successive calls to padvance will return
3766 * the possible path expansions in sequence. If an option (indicated by
3767 * a percent sign) appears in the path entry then the global variable
3768 * pathopt will be set to point to it; otherwise pathopt will be set to
3773 padvance(const char **path, const char *name)
3783 for (p = start ; *p && *p != ':' && *p != '%' ; p++);
3784 len = p - start + strlen(name) + 2; /* "2" is for '/' and '\0' */
3785 while (stackblocksize() < len)
3789 memcpy(q, start, p - start);
3797 while (*p && *p != ':') p++;
3803 return stalloc(len);
3807 /*** Command hashing code ***/
3810 printentry(struct tblentry *cmdp)
3816 idx = cmdp->param.index;
3819 name = padvance(&path, cmdp->cmdname);
3821 } while (--idx >= 0);
3822 out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
3827 hashcmd(int argc, char **argv)
3829 struct tblentry **pp;
3830 struct tblentry *cmdp;
3832 struct cmdentry entry;
3835 while ((c = nextopt("r")) != '\0') {
3839 if (*argptr == NULL) {
3840 for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
3841 for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
3842 if (cmdp->cmdtype == CMDNORMAL)
3849 while ((name = *argptr) != NULL) {
3850 if ((cmdp = cmdlookup(name, 0)) != NULL
3851 && (cmdp->cmdtype == CMDNORMAL
3852 || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0)))
3854 find_command(name, &entry, DO_ERR, pathval());
3855 if (entry.cmdtype == CMDUNKNOWN)
3864 * Resolve a command name. If you change this routine, you may have to
3865 * change the shellexec routine as well.
3869 find_command(char *name, struct cmdentry *entry, int act, const char *path)
3871 struct tblentry *cmdp;
3878 struct builtincmd *bcmd;
3880 /* If name contains a slash, don't use PATH or hash table */
3881 if (strchr(name, '/') != NULL) {
3882 entry->u.index = -1;
3884 while (stat(name, &statb) < 0) {
3889 entry->cmdtype = CMDUNKNOWN;
3893 entry->cmdtype = CMDNORMAL;
3897 #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
3898 if (find_applet_by_name(name)) {
3899 entry->cmdtype = CMDNORMAL;
3900 entry->u.index = -1;
3905 updatetbl = (path == pathval());
3908 if (strstr(path, "%builtin") != NULL)
3912 /* If name is in the table, check answer will be ok */
3913 if ((cmdp = cmdlookup(name, 0)) != NULL) {
3916 switch (cmdp->cmdtype) {
3934 } else if (cmdp->rehash == 0)
3935 /* if not invalidated by cd, we're done */
3939 /* If %builtin not in path, check for builtin next */
3940 bcmd = find_builtin(name);
3941 if (bcmd && (IS_BUILTIN_REGULAR(bcmd) || (
3942 act & DO_ALTPATH ? !(act & DO_ALTBLTIN) : builtinloc <= 0
3944 goto builtin_success;
3946 /* We have to search path. */
3947 prev = -1; /* where to start */
3948 if (cmdp && cmdp->rehash) { /* doing a rehash */
3949 if (cmdp->cmdtype == CMDBUILTIN)
3952 prev = cmdp->param.index;
3958 while ((fullname = padvance(&path, name)) != NULL) {
3959 stunalloc(fullname);
3962 if (prefix(pathopt, "builtin")) {
3964 goto builtin_success;
3966 } else if (!(act & DO_NOFUNC) &&
3967 prefix(pathopt, "func")) {
3970 /* ignore unimplemented options */
3974 /* if rehash, don't redo absolute path names */
3975 if (fullname[0] == '/' && idx <= prev) {
3978 TRACE(("searchexec \"%s\": no change\n", name));
3981 while (stat(fullname, &statb) < 0) {
3986 if (errno != ENOENT && errno != ENOTDIR)
3990 e = EACCES; /* if we fail, this will be the error */
3991 if (!S_ISREG(statb.st_mode))
3993 if (pathopt) { /* this is a %func directory */
3994 stalloc(strlen(fullname) + 1);
3995 readcmdfile(fullname);
3996 if ((cmdp = cmdlookup(name, 0)) == NULL ||
3997 cmdp->cmdtype != CMDFUNCTION)
3998 sh_error("%s not defined in %s", name, fullname);
3999 stunalloc(fullname);
4002 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
4004 entry->cmdtype = CMDNORMAL;
4005 entry->u.index = idx;
4009 cmdp = cmdlookup(name, 1);
4010 cmdp->cmdtype = CMDNORMAL;
4011 cmdp->param.index = idx;
4016 /* We failed. If there was an entry for this command, delete it */
4017 if (cmdp && updatetbl)
4020 sh_warnx("%s: %s", name, errmsg(e, E_EXEC));
4021 entry->cmdtype = CMDUNKNOWN;
4026 entry->cmdtype = CMDBUILTIN;
4027 entry->u.cmd = bcmd;
4031 cmdp = cmdlookup(name, 1);
4032 cmdp->cmdtype = CMDBUILTIN;
4033 cmdp->param.cmd = bcmd;
4037 entry->cmdtype = cmdp->cmdtype;
4038 entry->u = cmdp->param;
4043 * Wrapper around strcmp for qsort/bsearch/...
4045 static int pstrcmp(const void *a, const void *b)
4047 return strcmp((const char *) a, (*(const char *const *) b) + 1);
4051 * Search the table of builtin commands.
4054 static struct builtincmd *
4055 find_builtin(const char *name)
4057 struct builtincmd *bp;
4060 name, builtincmd, NUMBUILTINS, sizeof(struct builtincmd),
4069 * Called when a cd is done. Marks all commands so the next time they
4070 * are executed they will be rehashed.
4076 struct tblentry **pp;
4077 struct tblentry *cmdp;
4079 for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
4080 for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
4081 if (cmdp->cmdtype == CMDNORMAL || (
4082 cmdp->cmdtype == CMDBUILTIN &&
4083 !(IS_BUILTIN_REGULAR(cmdp->param.cmd)) &&
4094 * Fix command hash table when PATH changed.
4095 * Called before PATH is changed. The argument is the new value of PATH;
4096 * pathval() still returns the old value at this point.
4097 * Called with interrupts off.
4101 changepath(const char *newval)
4103 const char *old, *new;
4110 firstchange = 9999; /* assume no change */
4116 if ((*old == '\0' && *new == ':')
4117 || (*old == ':' && *new == '\0'))
4119 old = new; /* ignore subsequent differences */
4123 if (*new == '%' && idx_bltin < 0 && prefix(new + 1, "builtin"))
4130 if (builtinloc < 0 && idx_bltin >= 0)
4131 builtinloc = idx_bltin; /* zap builtins */
4132 if (builtinloc >= 0 && idx_bltin < 0)
4134 clearcmdentry(firstchange);
4135 builtinloc = idx_bltin;
4140 * Clear out command entries. The argument specifies the first entry in
4141 * PATH which has changed.
4145 clearcmdentry(int firstchange)
4147 struct tblentry **tblp;
4148 struct tblentry **pp;
4149 struct tblentry *cmdp;
4152 for (tblp = cmdtable ; tblp < &cmdtable[CMDTABLESIZE] ; tblp++) {
4154 while ((cmdp = *pp) != NULL) {
4155 if ((cmdp->cmdtype == CMDNORMAL &&
4156 cmdp->param.index >= firstchange)
4157 || (cmdp->cmdtype == CMDBUILTIN &&
4158 builtinloc >= firstchange)) {
4172 * Locate a command in the command hash table. If "add" is nonzero,
4173 * add the command to the table if it is not already present. The
4174 * variable "lastcmdentry" is set to point to the address of the link
4175 * pointing to the entry, so that delete_cmd_entry can delete the
4178 * Interrupts must be off if called with add != 0.
4181 static struct tblentry **lastcmdentry;
4184 static struct tblentry *
4185 cmdlookup(const char *name, int add)
4187 unsigned int hashval;
4189 struct tblentry *cmdp;
4190 struct tblentry **pp;
4193 hashval = (unsigned char)*p << 4;
4195 hashval += (unsigned char)*p++;
4197 pp = &cmdtable[hashval % CMDTABLESIZE];
4198 for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
4199 if (equal(cmdp->cmdname, name))
4203 if (add && cmdp == NULL) {
4204 cmdp = *pp = ckmalloc(sizeof (struct tblentry) - ARB
4205 + strlen(name) + 1);
4207 cmdp->cmdtype = CMDUNKNOWN;
4208 strcpy(cmdp->cmdname, name);
4215 * Delete the command entry returned on the last lookup.
4219 delete_cmd_entry(void)
4221 struct tblentry *cmdp;
4224 cmdp = *lastcmdentry;
4225 *lastcmdentry = cmdp->next;
4226 if (cmdp->cmdtype == CMDFUNCTION)
4227 freefunc(cmdp->param.func);
4234 * Add a new command entry, replacing any existing command entry for
4235 * the same name - except special builtins.
4239 addcmdentry(char *name, struct cmdentry *entry)
4241 struct tblentry *cmdp;
4243 cmdp = cmdlookup(name, 1);
4244 if (cmdp->cmdtype == CMDFUNCTION) {
4245 freefunc(cmdp->param.func);
4247 cmdp->cmdtype = entry->cmdtype;
4248 cmdp->param = entry->u;
4253 * Make a copy of a parse tree.
4256 static inline struct funcnode *
4257 copyfunc(union node *n)
4262 funcblocksize = offsetof(struct funcnode, n);
4265 blocksize = funcblocksize;
4266 f = ckmalloc(blocksize + funcstringsize);
4267 funcblock = (char *) f + offsetof(struct funcnode, n);
4268 funcstring = (char *) f + blocksize;
4275 * Define a shell function.
4279 defun(char *name, union node *func)
4281 struct cmdentry entry;
4284 entry.cmdtype = CMDFUNCTION;
4285 entry.u.func = copyfunc(func);
4286 addcmdentry(name, &entry);
4292 * Delete a function if it exists.
4296 unsetfunc(const char *name)
4298 struct tblentry *cmdp;
4300 if ((cmdp = cmdlookup(name, 0)) != NULL &&
4301 cmdp->cmdtype == CMDFUNCTION)
4306 * Locate and print what a word is...
4310 #ifdef CONFIG_ASH_CMDCMD
4312 describe_command(char *command, int describe_command_verbose)
4314 #define describe_command_verbose 1
4316 describe_command(char *command)
4319 struct cmdentry entry;
4320 struct tblentry *cmdp;
4321 #ifdef CONFIG_ASH_ALIAS
4322 const struct alias *ap;
4324 const char *path = pathval();
4326 if (describe_command_verbose) {
4330 /* First look at the keywords */
4331 if (findkwd(command)) {
4332 out1str(describe_command_verbose ? " is a shell keyword" : command);
4336 #ifdef CONFIG_ASH_ALIAS
4337 /* Then look at the aliases */
4338 if ((ap = lookupalias(command, 0)) != NULL) {
4339 if (describe_command_verbose) {
4340 out1fmt(" is an alias for %s", ap->val);
4349 /* Then check if it is a tracked alias */
4350 if ((cmdp = cmdlookup(command, 0)) != NULL) {
4351 entry.cmdtype = cmdp->cmdtype;
4352 entry.u = cmdp->param;
4354 /* Finally use brute force */
4355 find_command(command, &entry, DO_ABS, path);
4358 switch (entry.cmdtype) {
4360 int j = entry.u.index;
4366 p = padvance(&path, command);
4370 if (describe_command_verbose) {
4372 (cmdp ? " a tracked alias for" : nullstr), p
4381 if (describe_command_verbose) {
4382 out1str(" is a shell function");
4389 if (describe_command_verbose) {
4390 out1fmt(" is a %sshell builtin",
4391 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
4392 "special " : nullstr
4400 if (describe_command_verbose) {
4401 out1str(": not found\n");
4407 outstr("\n", stdout);
4412 typecmd(int argc, char **argv)
4417 for (i = 1; i < argc; i++) {
4418 #ifdef CONFIG_ASH_CMDCMD
4419 err |= describe_command(argv[i], 1);
4421 err |= describe_command(argv[i]);
4427 #ifdef CONFIG_ASH_CMDCMD
4429 commandcmd(int argc, char **argv)
4437 while ((c = nextopt("pvV")) != '\0')
4439 verify |= VERIFY_VERBOSE;
4441 verify |= VERIFY_BRIEF;
4447 return describe_command(*argptr, verify - VERIFY_BRIEF);
4456 * Routines to expand arguments to commands. We have to deal with
4457 * backquotes, shell variables, and file metacharacters.
4463 #define RMESCAPE_ALLOC 0x1 /* Allocate a new string */
4464 #define RMESCAPE_GLOB 0x2 /* Add backslashes for glob */
4465 #define RMESCAPE_QUOTED 0x4 /* Remove CTLESC unless in quotes */
4466 #define RMESCAPE_GROW 0x8 /* Grow strings instead of stalloc */
4467 #define RMESCAPE_HEAP 0x10 /* Malloc strings instead of stalloc */
4470 * Structure specifying which parts of the string should be searched
4471 * for IFS characters.
4475 struct ifsregion *next; /* next region in list */
4476 int begoff; /* offset of start of region */
4477 int endoff; /* offset of end of region */
4478 int nulonly; /* search for nul bytes only */
4481 /* output of current string */
4482 static char *expdest;
4483 /* list of back quote expressions */
4484 static struct nodelist *argbackq;
4485 /* first struct in list of ifs regions */
4486 static struct ifsregion ifsfirst;
4487 /* last struct in list */
4488 static struct ifsregion *ifslastp;
4489 /* holds expanded arg list */
4490 static struct arglist exparg;
4492 static void argstr(char *, int);
4493 static char *exptilde(char *, char *, int);
4494 static void expbackq(union node *, int, int);
4495 static const char *subevalvar(char *, char *, int, int, int, int, int);
4496 static char *evalvar(char *, int);
4497 static void strtodest(const char *, int, int);
4498 static void memtodest(const char *p, size_t len, int syntax, int quotes);
4499 static ssize_t varvalue(char *, int, int);
4500 static void recordregion(int, int, int);
4501 static void removerecordregions(int);
4502 static void ifsbreakup(char *, struct arglist *);
4503 static void ifsfree(void);
4504 static void expandmeta(struct strlist *, int);
4505 static int patmatch(char *, const char *);
4507 static int cvtnum(arith_t);
4508 static size_t esclen(const char *, const char *);
4509 static char *scanleft(char *, char *, char *, char *, int, int);
4510 static char *scanright(char *, char *, char *, char *, int, int);
4511 static void varunset(const char *, const char *, const char *, int)
4515 #define pmatch(a, b) !fnmatch((a), (b), 0)
4517 * Prepare a pattern for a expmeta (internal glob(3)) call.
4519 * Returns an stalloced string.
4522 static inline char *
4523 preglob(const char *pattern, int quoted, int flag) {
4524 flag |= RMESCAPE_GLOB;
4526 flag |= RMESCAPE_QUOTED;
4528 return _rmescapes((char *)pattern, flag);
4533 esclen(const char *start, const char *p) {
4536 while (p > start && *--p == CTLESC) {
4544 * Expand shell variables and backquotes inside a here document.
4548 expandhere(union node *arg, int fd)
4551 expandarg(arg, (struct arglist *)NULL, 0);
4552 bb_full_write(fd, stackblock(), expdest - (char *)stackblock());
4557 * Perform variable substitution and command substitution on an argument,
4558 * placing the resulting list of arguments in arglist. If EXP_FULL is true,
4559 * perform splitting and file name expansion. When arglist is NULL, perform
4560 * here document expansion.
4564 expandarg(union node *arg, struct arglist *arglist, int flag)
4569 argbackq = arg->narg.backquote;
4570 STARTSTACKSTR(expdest);
4571 ifsfirst.next = NULL;
4573 argstr(arg->narg.text, flag);
4574 p = _STPUTC('\0', expdest);
4576 if (arglist == NULL) {
4577 return; /* here document expanded */
4579 p = grabstackstr(p);
4580 exparg.lastp = &exparg.list;
4584 if (flag & EXP_FULL) {
4585 ifsbreakup(p, &exparg);
4586 *exparg.lastp = NULL;
4587 exparg.lastp = &exparg.list;
4588 expandmeta(exparg.list, flag);
4590 if (flag & EXP_REDIR) /*XXX - for now, just remove escapes */
4592 sp = (struct strlist *)stalloc(sizeof (struct strlist));
4595 exparg.lastp = &sp->next;
4599 *exparg.lastp = NULL;
4601 *arglist->lastp = exparg.list;
4602 arglist->lastp = exparg.lastp;
4608 * Perform variable and command substitution. If EXP_FULL is set, output CTLESC
4609 * characters to allow for further processing. Otherwise treat
4610 * $@ like $* since no splitting will be performed.
4614 argstr(char *p, int flag)
4616 static const char spclchars[] = {
4624 CTLBACKQ | CTLQUOTE,
4625 #ifdef CONFIG_ASH_MATH_SUPPORT
4630 const char *reject = spclchars;
4632 int quotes = flag & (EXP_FULL | EXP_CASE); /* do CTLESC */
4633 int breakall = flag & EXP_WORD;
4638 if (!(flag & EXP_VARTILDE)) {
4640 } else if (flag & EXP_VARTILDE2) {
4645 if (flag & EXP_TILDE) {
4651 if (*q == CTLESC && (flag & EXP_QWORD))
4654 p = exptilde(p, q, flag);
4657 startloc = expdest - (char *)stackblock();
4659 length += strcspn(p + length, reject);
4661 if (c && (!(c & 0x80)
4662 #ifdef CONFIG_ASH_MATH_SUPPORT
4666 /* c == '=' || c == ':' || c == CTLENDARI */
4671 expdest = stnputs(p, length, expdest);
4672 newloc = expdest - (char *)stackblock();
4673 if (breakall && !inquotes && newloc > startloc) {
4674 recordregion(startloc, newloc, 0);
4685 if (flag & EXP_VARTILDE2) {
4689 flag |= EXP_VARTILDE2;
4694 * sort of a hack - expand tildes in variable
4695 * assignments (after the first '=' and after ':'s).
4704 case CTLENDVAR: /* ??? */
4707 /* "$@" syntax adherence hack */
4710 !memcmp(p, dolatstr, DOLATSTRLEN) &&
4711 (p[4] == CTLQUOTEMARK || (
4712 p[4] == CTLENDVAR &&
4713 p[5] == CTLQUOTEMARK
4716 p = evalvar(p + 1, flag) + 1;
4719 inquotes = !inquotes;
4732 p = evalvar(p, flag);
4736 case CTLBACKQ|CTLQUOTE:
4737 expbackq(argbackq->n, c, quotes);
4738 argbackq = argbackq->next;
4740 #ifdef CONFIG_ASH_MATH_SUPPORT
4753 exptilde(char *startp, char *p, int flag)
4759 int quotes = flag & (EXP_FULL | EXP_CASE);
4764 while ((c = *++p) != '\0') {
4771 if (flag & EXP_VARTILDE)
4781 if (*name == '\0') {
4782 home = lookupvar(homestr);
4784 if ((pw = getpwnam(name)) == NULL)
4788 if (!home || !*home)
4791 startloc = expdest - (char *)stackblock();
4792 strtodest(home, SQSYNTAX, quotes);
4793 recordregion(startloc, expdest - (char *)stackblock(), 0);
4802 removerecordregions(int endoff)
4804 if (ifslastp == NULL)
4807 if (ifsfirst.endoff > endoff) {
4808 while (ifsfirst.next != NULL) {
4809 struct ifsregion *ifsp;
4811 ifsp = ifsfirst.next->next;
4812 ckfree(ifsfirst.next);
4813 ifsfirst.next = ifsp;
4816 if (ifsfirst.begoff > endoff)
4819 ifslastp = &ifsfirst;
4820 ifsfirst.endoff = endoff;
4825 ifslastp = &ifsfirst;
4826 while (ifslastp->next && ifslastp->next->begoff < endoff)
4827 ifslastp=ifslastp->next;
4828 while (ifslastp->next != NULL) {
4829 struct ifsregion *ifsp;
4831 ifsp = ifslastp->next->next;
4832 ckfree(ifslastp->next);
4833 ifslastp->next = ifsp;
4836 if (ifslastp->endoff > endoff)
4837 ifslastp->endoff = endoff;
4841 #ifdef CONFIG_ASH_MATH_SUPPORT
4843 * Expand arithmetic expression. Backup to start of expression,
4844 * evaluate, place result in (backed up) result, adjust string position.
4857 * This routine is slightly over-complicated for
4858 * efficiency. Next we scan backwards looking for the
4859 * start of arithmetic.
4861 start = stackblock();
4868 while (*p != CTLARI) {
4872 sh_error("missing CTLARI (shouldn't happen)");
4877 esc = esclen(start, p);
4887 removerecordregions(begoff);
4896 len = cvtnum(dash_arith(p + 2));
4899 recordregion(begoff, begoff + len, 0);
4904 * Expand stuff in backwards quotes.
4908 expbackq(union node *cmd, int quoted, int quotes)
4916 int syntax = quoted? DQSYNTAX : BASESYNTAX;
4917 struct stackmark smark;
4920 setstackmark(&smark);
4922 startloc = dest - (char *)stackblock();
4924 evalbackcmd(cmd, (struct backcmd *) &in);
4925 popstackmark(&smark);
4932 memtodest(p, i, syntax, quotes);
4936 i = safe_read(in.fd, buf, sizeof buf);
4937 TRACE(("expbackq: read returns %d\n", i));
4947 back_exitstatus = waitforjob(in.jp);
4951 /* Eat all trailing newlines */
4953 for (; dest > (char *)stackblock() && dest[-1] == '\n';)
4958 recordregion(startloc, dest - (char *)stackblock(), 0);
4959 TRACE(("evalbackq: size=%d: \"%.*s\"\n",
4960 (dest - (char *)stackblock()) - startloc,
4961 (dest - (char *)stackblock()) - startloc,
4962 stackblock() + startloc));
4967 scanleft(char *startp, char *rmesc, char *rmescend, char *str, int quotes,
4978 const char *s = loc2;
4984 match = pmatch(str, s);
4988 if (quotes && *loc == CTLESC)
4998 scanright(char *startp, char *rmesc, char *rmescend, char *str, int quotes,
5005 for (loc = str - 1, loc2 = rmescend; loc >= startp; loc2--) {
5008 const char *s = loc2;
5013 match = pmatch(str, s);
5020 esc = esclen(startp, loc);
5032 subevalvar(char *p, char *str, int strloc, int subtype, int startloc, int varflags, int quotes)
5036 int saveherefd = herefd;
5037 struct nodelist *saveargbackq = argbackq;
5039 char *rmesc, *rmescend;
5041 char *(*scan)(char *, char *, char *, char *, int , int);
5044 argstr(p, subtype != VSASSIGN && subtype != VSQUESTION ? EXP_CASE : 0);
5045 STPUTC('\0', expdest);
5046 herefd = saveherefd;
5047 argbackq = saveargbackq;
5048 startp = stackblock() + startloc;
5052 setvar(str, startp, 0);
5053 amount = startp - expdest;
5054 STADJUST(amount, expdest);
5058 varunset(p, str, startp, varflags);
5062 subtype -= VSTRIMRIGHT;
5064 if (subtype < 0 || subtype > 3)
5069 rmescend = stackblock() + strloc;
5071 rmesc = _rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW);
5072 if (rmesc != startp) {
5074 startp = stackblock() + startloc;
5078 str = stackblock() + strloc;
5079 preglob(str, varflags & VSQUOTE, 0);
5081 /* zero = subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX */
5082 zero = subtype >> 1;
5083 /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
5084 scan = (subtype & 1) ^ zero ? scanleft : scanright;
5086 loc = scan(startp, rmesc, rmescend, str, quotes, zero);
5089 memmove(startp, loc, str - loc);
5090 loc = startp + (str - loc) - 1;
5093 amount = loc - expdest;
5094 STADJUST(amount, expdest);
5101 * Expand a variable, and return a pointer to the next character in the
5105 evalvar(char *p, int flag)
5118 quotes = flag & (EXP_FULL | EXP_CASE);
5120 subtype = varflags & VSTYPE;
5121 quoted = varflags & VSQUOTE;
5123 easy = (!quoted || (*var == '@' && shellparam.nparam));
5124 startloc = expdest - (char *)stackblock();
5125 p = strchr(p, '=') + 1;
5128 varlen = varvalue(var, varflags, flag);
5129 if (varflags & VSNUL)
5132 if (subtype == VSPLUS) {
5133 varlen = -1 - varlen;
5137 if (subtype == VSMINUS) {
5141 p, flag | EXP_TILDE |
5142 (quoted ? EXP_QWORD : EXP_WORD)
5151 if (subtype == VSASSIGN || subtype == VSQUESTION) {
5153 if (subevalvar(p, var, 0, subtype, startloc,
5157 * Remove any recorded regions beyond
5160 removerecordregions(startloc);
5170 if (varlen < 0 && uflag)
5171 varunset(p, var, 0, 0);
5173 if (subtype == VSLENGTH) {
5174 cvtnum(varlen > 0 ? varlen : 0);
5178 if (subtype == VSNORMAL) {
5182 recordregion(startloc, expdest - (char *)stackblock(), quoted);
5191 case VSTRIMRIGHTMAX:
5200 * Terminate the string and start recording the pattern
5203 STPUTC('\0', expdest);
5204 patloc = expdest - (char *)stackblock();
5205 if (subevalvar(p, NULL, patloc, subtype,
5206 startloc, varflags, quotes) == 0) {
5207 int amount = expdest - (
5208 (char *)stackblock() + patloc - 1
5210 STADJUST(-amount, expdest);
5212 /* Remove any recorded regions beyond start of variable */
5213 removerecordregions(startloc);
5218 if (subtype != VSNORMAL) { /* skip to end of alternative */
5221 if ((c = *p++) == CTLESC)
5223 else if (c == CTLBACKQ || c == (CTLBACKQ|CTLQUOTE)) {
5225 argbackq = argbackq->next;
5226 } else if (c == CTLVAR) {
5227 if ((*p++ & VSTYPE) != VSNORMAL)
5229 } else if (c == CTLENDVAR) {
5240 * Put a string on the stack.
5244 memtodest(const char *p, size_t len, int syntax, int quotes) {
5247 q = makestrspace(len * 2, q);
5250 int c = SC2INT(*p++);
5253 if (quotes && (SIT(c, syntax) == CCTL || SIT(c, syntax) == CBACK))
5263 strtodest(const char *p, int syntax, int quotes)
5265 memtodest(p, strlen(p), syntax, quotes);
5270 * Add the value of a specialized variable to the stack string.
5274 varvalue(char *name, int varflags, int flags)
5284 int quoted = varflags & VSQUOTE;
5285 int subtype = varflags & VSTYPE;
5286 int quotes = flags & (EXP_FULL | EXP_CASE);
5288 if (quoted && (flags & EXP_FULL))
5289 sep = 1 << CHAR_BIT;
5291 syntax = quoted ? DQSYNTAX : BASESYNTAX;
5300 num = shellparam.nparam;
5310 p = makestrspace(NOPTS, expdest);
5311 for (i = NOPTS - 1; i >= 0; i--) {
5313 USTPUTC(optletters(i), p);
5324 sep = ifsset() ? SC2INT(ifsval()[0]) : ' ';
5325 if (quotes && (SIT(sep, syntax) == CCTL || SIT(sep, syntax) == CBACK))
5328 if (!(ap = shellparam.p))
5330 while ((p = *ap++)) {
5333 partlen = strlen(p);
5336 if (!(subtype == VSPLUS || subtype == VSLENGTH))
5337 memtodest(p, partlen, syntax, quotes);
5343 if (subtype == VSPLUS || subtype == VSLENGTH) {
5365 if (num < 0 || num > shellparam.nparam)
5367 p = num ? shellparam.p[num - 1] : arg0;
5370 p = lookupvar(name);
5376 if (!(subtype == VSPLUS || subtype == VSLENGTH))
5377 memtodest(p, len, syntax, quotes);
5381 if (subtype == VSPLUS || subtype == VSLENGTH)
5382 STADJUST(-len, expdest);
5388 * Record the fact that we have to scan this region of the
5389 * string for IFS characters.
5393 recordregion(int start, int end, int nulonly)
5395 struct ifsregion *ifsp;
5397 if (ifslastp == NULL) {
5401 ifsp = (struct ifsregion *)ckmalloc(sizeof (struct ifsregion));
5403 ifslastp->next = ifsp;
5407 ifslastp->begoff = start;
5408 ifslastp->endoff = end;
5409 ifslastp->nulonly = nulonly;
5414 * Break the argument string into pieces based upon IFS and add the
5415 * strings to the argument list. The regions of the string to be
5416 * searched for IFS characters have been stored by recordregion.
5419 ifsbreakup(char *string, struct arglist *arglist)
5421 struct ifsregion *ifsp;
5426 const char *ifs, *realifs;
5432 if (ifslastp != NULL) {
5435 realifs = ifsset() ? ifsval() : defifs;
5438 p = string + ifsp->begoff;
5439 nulonly = ifsp->nulonly;
5440 ifs = nulonly ? nullstr : realifs;
5442 while (p < string + ifsp->endoff) {
5446 if (strchr(ifs, *p)) {
5448 ifsspc = (strchr(defifs, *p) != NULL);
5449 /* Ignore IFS whitespace at start */
5450 if (q == start && ifsspc) {
5456 sp = (struct strlist *)stalloc(sizeof *sp);
5458 *arglist->lastp = sp;
5459 arglist->lastp = &sp->next;
5463 if (p >= string + ifsp->endoff) {
5469 if (strchr(ifs, *p) == NULL ) {
5472 } else if (strchr(defifs, *p) == NULL) {
5488 } while ((ifsp = ifsp->next) != NULL);
5497 sp = (struct strlist *)stalloc(sizeof *sp);
5499 *arglist->lastp = sp;
5500 arglist->lastp = &sp->next;
5506 struct ifsregion *p;
5511 struct ifsregion *ifsp;
5517 ifsfirst.next = NULL;
5521 static void expmeta(char *, char *);
5522 static struct strlist *expsort(struct strlist *);
5523 static struct strlist *msort(struct strlist *, int);
5525 static char *expdir;
5529 expandmeta(struct strlist *str, int flag)
5531 static const char metachars[] = {
5534 /* TODO - EXP_REDIR */
5537 struct strlist **savelastp;
5543 if (!strpbrk(str->text, metachars))
5545 savelastp = exparg.lastp;
5548 p = preglob(str->text, 0, RMESCAPE_ALLOC | RMESCAPE_HEAP);
5550 int i = strlen(str->text);
5551 expdir = ckmalloc(i < 2048 ? 2048 : i); /* XXX */
5559 if (exparg.lastp == savelastp) {
5564 *exparg.lastp = str;
5565 rmescapes(str->text);
5566 exparg.lastp = &str->next;
5568 *exparg.lastp = NULL;
5569 *savelastp = sp = expsort(*savelastp);
5570 while (sp->next != NULL)
5572 exparg.lastp = &sp->next;
5579 * Add a file name to the list.
5583 addfname(const char *name)
5587 sp = (struct strlist *)stalloc(sizeof *sp);
5588 sp->text = sstrdup(name);
5590 exparg.lastp = &sp->next;
5595 * Do metacharacter (i.e. *, ?, [...]) expansion.
5599 expmeta(char *enddir, char *name)
5614 for (p = name; *p; p++) {
5615 if (*p == '*' || *p == '?')
5617 else if (*p == '[') {
5624 if (*q == '/' || *q == '\0')
5631 } else if (*p == '\\')
5633 else if (*p == '/') {
5640 if (metaflag == 0) { /* we've reached the end of the file name */
5641 if (enddir != expdir)
5649 if (metaflag == 0 || lstat(expdir, &statb) >= 0)
5660 } while (p < start);
5662 if (enddir == expdir) {
5664 } else if (enddir == expdir + 1 && *expdir == '/') {
5670 if ((dirp = opendir(cp)) == NULL)
5672 if (enddir != expdir)
5674 if (*endname == 0) {
5686 while (! intpending && (dp = readdir(dirp)) != NULL) {
5687 if (dp->d_name[0] == '.' && ! matchdot)
5689 if (pmatch(start, dp->d_name)) {
5691 scopy(dp->d_name, enddir);
5694 for (p = enddir, cp = dp->d_name;
5695 (*p++ = *cp++) != '\0';)
5698 expmeta(p, endname);
5708 * Sort the results of file name expansion. It calculates the number of
5709 * strings to sort and then calls msort (short for merge sort) to do the
5713 static struct strlist *
5714 expsort(struct strlist *str)
5720 for (sp = str ; sp ; sp = sp->next)
5722 return msort(str, len);
5726 static struct strlist *
5727 msort(struct strlist *list, int len)
5729 struct strlist *p, *q = NULL;
5730 struct strlist **lpp;
5738 for (n = half ; --n >= 0 ; ) {
5742 q->next = NULL; /* terminate first half of list */
5743 q = msort(list, half); /* sort first half of list */
5744 p = msort(p, len - half); /* sort second half */
5747 #ifdef CONFIG_LOCALE_SUPPORT
5748 if (strcoll(p->text, q->text) < 0)
5750 if (strcmp(p->text, q->text) < 0)
5755 if ((p = *lpp) == NULL) {
5762 if ((q = *lpp) == NULL) {
5773 * Returns true if the pattern matches the string.
5777 patmatch(char *pattern, const char *string)
5779 return pmatch(preglob(pattern, 0, 0), string);
5784 * Remove any CTLESC characters from a string.
5788 _rmescapes(char *str, int flag)
5791 static const char qchars[] = { CTLESC, CTLQUOTEMARK, 0 };
5796 p = strpbrk(str, qchars);
5802 if (flag & RMESCAPE_ALLOC) {
5803 size_t len = p - str;
5804 size_t fulllen = len + strlen(p) + 1;
5806 if (flag & RMESCAPE_GROW) {
5807 r = makestrspace(fulllen, expdest);
5808 } else if (flag & RMESCAPE_HEAP) {
5809 r = ckmalloc(fulllen);
5811 r = stalloc(fulllen);
5815 q = mempcpy(q, str, len);
5818 inquotes = (flag & RMESCAPE_QUOTED) ^ RMESCAPE_QUOTED;
5819 globbing = flag & RMESCAPE_GLOB;
5820 notescaped = globbing;
5822 if (*p == CTLQUOTEMARK) {
5823 inquotes = ~inquotes;
5825 notescaped = globbing;
5829 /* naked back slash */
5835 if (notescaped && inquotes && *p != '/') {
5839 notescaped = globbing;
5844 if (flag & RMESCAPE_GROW) {
5846 STADJUST(q - r + 1, expdest);
5853 * See if a pattern matches in a case statement.
5857 casematch(union node *pattern, char *val)
5859 struct stackmark smark;
5862 setstackmark(&smark);
5863 argbackq = pattern->narg.backquote;
5864 STARTSTACKSTR(expdest);
5866 argstr(pattern->narg.text, EXP_TILDE | EXP_CASE);
5867 STACKSTRNUL(expdest);
5868 result = patmatch(stackblock(), val);
5869 popstackmark(&smark);
5882 expdest = makestrspace(32, expdest);
5883 #ifdef CONFIG_ASH_MATH_SUPPORT_64
5884 len = fmtstr(expdest, 32, "%lld", (long long) num);
5886 len = fmtstr(expdest, 32, "%ld", num);
5888 STADJUST(len, expdest);
5893 varunset(const char *end, const char *var, const char *umsg, int varflags)
5899 msg = "parameter not set";
5901 if (*end == CTLENDVAR) {
5902 if (varflags & VSNUL)
5907 sh_error("%.*s: %s%s", end - var - 1, var, msg, tail);
5914 * This implements the input routines used by the parser.
5917 #define EOF_NLEFT -99 /* value of parsenleft when EOF pushed back */
5919 static void pushfile(void);
5922 * Read a character from the script, returning PEOF on end of file.
5923 * Nul characters in the input are silently discarded.
5927 #define pgetc_as_macro() (--parsenleft >= 0? SC2INT(*parsenextc++) : preadbuffer())
5929 #ifdef CONFIG_ASH_OPTIMIZE_FOR_SIZE
5930 #define pgetc_macro() pgetc()
5934 return pgetc_as_macro();
5937 #define pgetc_macro() pgetc_as_macro()
5941 return pgetc_macro();
5947 * Same as pgetc(), but ignores PEOA.
5949 #ifdef CONFIG_ASH_ALIAS
5950 static int pgetc2(void)
5956 } while (c == PEOA);
5960 static inline int pgetc2(void)
5962 return pgetc_macro();
5967 * Read a line from the script.
5970 static inline char *
5971 pfgets(char *line, int len)
5977 while (--nleft > 0) {
5994 #ifdef CONFIG_FEATURE_COMMAND_EDITING
5995 #ifdef CONFIG_ASH_EXPAND_PRMT
5996 static char *cmdedit_prompt;
5998 static const char *cmdedit_prompt;
6000 static inline void putprompt(const char *s)
6002 #ifdef CONFIG_ASH_EXPAND_PRMT
6003 free(cmdedit_prompt);
6004 cmdedit_prompt = bb_xstrdup(s);
6010 static inline void putprompt(const char *s)
6020 char *buf = parsefile->buf;
6024 #ifdef CONFIG_FEATURE_COMMAND_EDITING
6025 if (!iflag || parsefile->fd)
6026 nr = safe_read(parsefile->fd, buf, BUFSIZ - 1);
6028 #ifdef CONFIG_FEATURE_COMMAND_TAB_COMPLETION
6029 cmdedit_path_lookup = pathval();
6031 nr = cmdedit_read_input((char *) cmdedit_prompt, buf);
6033 /* Ctrl+C presend */
6042 if(nr < 0 && errno == 0) {
6043 /* Ctrl+D presend */
6048 nr = safe_read(parsefile->fd, buf, BUFSIZ - 1);
6052 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
6053 int flags = fcntl(0, F_GETFL, 0);
6054 if (flags >= 0 && flags & O_NONBLOCK) {
6055 flags &=~ O_NONBLOCK;
6056 if (fcntl(0, F_SETFL, flags) >= 0) {
6057 out2str("sh: turning off NDELAY mode\n");
6067 * Refill the input buffer and return the next input character:
6069 * 1) If a string was pushed back on the input, pop it;
6070 * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading
6071 * from a string so we can't refill the buffer, return EOF.
6072 * 3) If the is more stuff in this buffer, use it else call read to fill it.
6073 * 4) Process input up to the next newline, deleting nul characters.
6083 while (parsefile->strpush) {
6084 #ifdef CONFIG_ASH_ALIAS
6085 if (parsenleft == -1 && parsefile->strpush->ap &&
6086 parsenextc[-1] != ' ' && parsenextc[-1] != '\t') {
6091 if (--parsenleft >= 0)
6092 return SC2INT(*parsenextc++);
6094 if (parsenleft == EOF_NLEFT || parsefile->buf == NULL)
6101 if ((more = preadfd()) <= 0) {
6102 parselleft = parsenleft = EOF_NLEFT;
6109 /* delete nul characters */
6117 memmove(q, q + 1, more);
6121 parsenleft = q - parsenextc - 1;
6127 parsenleft = q - parsenextc - 1;
6139 out2str(parsenextc);
6144 return SC2INT(*parsenextc++);
6148 * Undo the last call to pgetc. Only one character may be pushed back.
6149 * PEOF may be pushed back.
6160 * Push a string back onto the input at this current parsefile level.
6161 * We handle aliases this way.
6164 pushstring(char *s, void *ap)
6171 /*dprintf("*** calling pushstring: %s, %d\n", s, len);*/
6172 if (parsefile->strpush) {
6173 sp = ckmalloc(sizeof (struct strpush));
6174 sp->prev = parsefile->strpush;
6175 parsefile->strpush = sp;
6177 sp = parsefile->strpush = &(parsefile->basestrpush);
6178 sp->prevstring = parsenextc;
6179 sp->prevnleft = parsenleft;
6180 #ifdef CONFIG_ASH_ALIAS
6181 sp->ap = (struct alias *)ap;
6183 ((struct alias *)ap)->flag |= ALIASINUSE;
6195 struct strpush *sp = parsefile->strpush;
6198 #ifdef CONFIG_ASH_ALIAS
6200 if (parsenextc[-1] == ' ' || parsenextc[-1] == '\t') {
6201 checkkwd |= CHKALIAS;
6203 if (sp->string != sp->ap->val) {
6206 sp->ap->flag &= ~ALIASINUSE;
6207 if (sp->ap->flag & ALIASDEAD) {
6208 unalias(sp->ap->name);
6212 parsenextc = sp->prevstring;
6213 parsenleft = sp->prevnleft;
6214 /*dprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/
6215 parsefile->strpush = sp->prev;
6216 if (sp != &(parsefile->basestrpush))
6222 * Set the input to take input from a file. If push is set, push the
6223 * old input onto the stack first.
6227 setinputfile(const char *fname, int flags)
6233 if ((fd = open(fname, O_RDONLY)) < 0) {
6234 if (flags & INPUT_NOFILE_OK)
6236 sh_error("Can't open %s", fname);
6239 fd2 = copyfd(fd, 10);
6242 sh_error("Out of file descriptors");
6245 setinputfd(fd, flags & INPUT_PUSH_FILE);
6253 * Like setinputfile, but takes an open file descriptor. Call this with
6258 setinputfd(int fd, int push)
6260 (void) fcntl(fd, F_SETFD, FD_CLOEXEC);
6266 if (parsefile->buf == NULL)
6267 parsefile->buf = ckmalloc(IBUFSIZ);
6268 parselleft = parsenleft = 0;
6274 * Like setinputfile, but takes input from a string.
6278 setinputstring(char *string)
6282 parsenextc = string;
6283 parsenleft = strlen(string);
6284 parsefile->buf = NULL;
6291 * To handle the "." command, a stack of input files is used. Pushfile
6292 * adds a new entry to the stack and popfile restores the previous level.
6298 struct parsefile *pf;
6300 parsefile->nleft = parsenleft;
6301 parsefile->lleft = parselleft;
6302 parsefile->nextc = parsenextc;
6303 parsefile->linno = plinno;
6304 pf = (struct parsefile *)ckmalloc(sizeof (struct parsefile));
6305 pf->prev = parsefile;
6308 pf->basestrpush.prev = NULL;
6316 struct parsefile *pf = parsefile;
6325 parsefile = pf->prev;
6327 parsenleft = parsefile->nleft;
6328 parselleft = parsefile->lleft;
6329 parsenextc = parsefile->nextc;
6330 plinno = parsefile->linno;
6336 * Return to top level.
6342 while (parsefile != &basepf)
6348 * Close the file(s) that the shell is reading commands from. Called
6349 * after a fork is done.
6356 if (parsefile->fd > 0) {
6357 close(parsefile->fd);
6364 /* mode flags for set_curjob */
6365 #define CUR_DELETE 2
6366 #define CUR_RUNNING 1
6367 #define CUR_STOPPED 0
6369 /* mode flags for dowait */
6370 #define DOWAIT_NORMAL 0
6371 #define DOWAIT_BLOCK 1
6374 static struct job *jobtab;
6376 static unsigned njobs;
6378 /* pgrp of shell on invocation */
6379 static int initialpgrp;
6380 static int ttyfd = -1;
6383 static struct job *curjob;
6384 /* number of presumed living untracked jobs */
6387 static void set_curjob(struct job *, unsigned);
6389 static int restartjob(struct job *, int);
6390 static void xtcsetpgrp(int, pid_t);
6391 static char *commandtext(union node *);
6392 static void cmdlist(union node *, int);
6393 static void cmdtxt(union node *);
6394 static void cmdputs(const char *);
6395 static void showpipe(struct job *, FILE *);
6397 static int sprint_status(char *, int, int);
6398 static void freejob(struct job *);
6399 static struct job *getjob(const char *, int);
6400 static struct job *growjobtab(void);
6401 static void forkchild(struct job *, union node *, int);
6402 static void forkparent(struct job *, union node *, int, pid_t);
6403 static int dowait(int, struct job *);
6404 static int getstatus(struct job *);
6407 set_curjob(struct job *jp, unsigned mode)
6410 struct job **jpp, **curp;
6412 /* first remove from list */
6413 jpp = curp = &curjob;
6418 jpp = &jp1->prev_job;
6420 *jpp = jp1->prev_job;
6422 /* Then re-insert in correct position */
6430 /* job being deleted */
6433 /* newly created job or backgrounded job,
6434 put after all stopped jobs. */
6438 if (!jp1 || jp1->state != JOBSTOPPED)
6441 jpp = &jp1->prev_job;
6447 /* newly stopped job - becomes curjob */
6448 jp->prev_job = *jpp;
6456 * Turn job control on and off.
6458 * Note: This code assumes that the third arg to ioctl is a character
6459 * pointer, which is true on Berkeley systems but not System V. Since
6460 * System V doesn't have job control yet, this isn't a problem now.
6462 * Called with interrupts off.
6471 if (on == jobctl || rootshell == 0)
6475 ofd = fd = open(_PATH_TTY, O_RDWR);
6478 while (!isatty(fd) && --fd >= 0)
6481 fd = fcntl(fd, F_DUPFD, 10);
6485 fcntl(fd, F_SETFD, FD_CLOEXEC);
6486 do { /* while we are in the background */
6487 if ((pgrp = tcgetpgrp(fd)) < 0) {
6489 sh_warnx("can't access tty; job control turned off");
6493 if (pgrp == getpgrp())
6504 xtcsetpgrp(fd, pgrp);
6506 /* turning job control off */
6509 xtcsetpgrp(fd, pgrp);
6523 killcmd(int argc, char **argv)
6534 "Usage: kill [-s sigspec | -signum | -sigspec] [pid | job]... or\n"
6535 "kill -l [exitstatus]"
6539 if (**++argv == '-') {
6540 signo = decode_signal(*argv + 1, 1);
6544 while ((c = nextopt("ls:")) != '\0')
6554 signo = decode_signal(optionarg, 1);
6557 "invalid signal number or name: %s",
6568 if (!list && signo < 0)
6571 if ((signo < 0 || !*argv) ^ list) {
6579 for (i = 1; i < NSIG; i++) {
6580 name = u_signal_names(0, &i, 1);
6582 out1fmt(snlfmt, name);
6586 name = u_signal_names(*argptr, &signo, -1);
6588 out1fmt(snlfmt, name);
6590 sh_error("invalid signal number or exit status: %s", *argptr);
6596 if (**argv == '%') {
6597 jp = getjob(*argv, 0);
6598 pid = -jp->ps[0].pid;
6600 pid = **argv == '-' ?
6601 -number(*argv + 1) : number(*argv);
6603 if (kill(pid, signo) != 0) {
6604 sh_warnx("(%d) - %m", pid);
6613 #if defined(JOBS) || defined(DEBUG)
6615 jobno(const struct job *jp)
6617 return jp - jobtab + 1;
6623 fgcmd(int argc, char **argv)
6630 mode = (**argv == 'f') ? FORK_FG : FORK_BG;
6635 jp = getjob(*argv, 1);
6636 if (mode == FORK_BG) {
6637 set_curjob(jp, CUR_RUNNING);
6638 fprintf(out, "[%d] ", jobno(jp));
6640 outstr(jp->ps->cmd, out);
6642 retval = restartjob(jp, mode);
6643 } while (*argv && *++argv);
6647 static int bgcmd(int, char **) __attribute__((__alias__("fgcmd")));
6651 restartjob(struct job *jp, int mode)
6653 struct procstat *ps;
6659 if (jp->state == JOBDONE)
6661 jp->state = JOBRUNNING;
6663 if (mode == FORK_FG)
6664 xtcsetpgrp(ttyfd, pgid);
6665 killpg(pgid, SIGCONT);
6669 if (WIFSTOPPED(ps->status)) {
6672 } while (ps++, --i);
6674 status = (mode == FORK_FG) ? waitforjob(jp) : 0;
6681 sprint_status(char *s, int status, int sigonly)
6687 if (!WIFEXITED(status)) {
6689 if (WIFSTOPPED(status))
6690 st = WSTOPSIG(status);
6693 st = WTERMSIG(status);
6695 if (st == SIGINT || st == SIGPIPE)
6698 if (WIFSTOPPED(status))
6703 col = fmtstr(s, 32, strsignal(st));
6704 if (WCOREDUMP(status)) {
6705 col += fmtstr(s + col, 16, " (core dumped)");
6707 } else if (!sigonly) {
6708 st = WEXITSTATUS(status);
6710 col = fmtstr(s, 16, "Done(%d)", st);
6712 col = fmtstr(s, 16, "Done");
6721 showjob(FILE *out, struct job *jp, int mode)
6723 struct procstat *ps;
6724 struct procstat *psend;
6731 if (mode & SHOW_PGID) {
6732 /* just output process (group) id of pipeline */
6733 fprintf(out, "%d\n", ps->pid);
6737 col = fmtstr(s, 16, "[%d] ", jobno(jp));
6742 else if (curjob && jp == curjob->prev_job)
6745 if (mode & SHOW_PID)
6746 col += fmtstr(s + col, 16, "%d ", ps->pid);
6748 psend = ps + jp->nprocs;
6750 if (jp->state == JOBRUNNING) {
6751 scopy("Running", s + col);
6752 col += strlen("Running");
6754 int status = psend[-1].status;
6756 if (jp->state == JOBSTOPPED)
6757 status = jp->stopstatus;
6759 col += sprint_status(s + col, status, 0);
6765 /* for each process */
6766 col = fmtstr(s, 48, " |\n%*c%d ", indent, ' ', ps->pid) - 3;
6769 fprintf(out, "%s%*c%s",
6770 s, 33 - col >= 0 ? 33 - col : 0, ' ', ps->cmd
6772 if (!(mode & SHOW_PID)) {
6776 if (++ps == psend) {
6777 outcslow('\n', out);
6784 if (jp->state == JOBDONE) {
6785 TRACE(("showjob: freeing job %d\n", jobno(jp)));
6792 jobscmd(int argc, char **argv)
6798 while ((m = nextopt("lp")))
6808 showjob(out, getjob(*argv,0), mode);
6811 showjobs(out, mode);
6818 * Print a list of jobs. If "change" is nonzero, only print jobs whose
6819 * statuses have changed since the last call to showjobs.
6823 showjobs(FILE *out, int mode)
6827 TRACE(("showjobs(%x) called\n", mode));
6829 /* If not even one one job changed, there is nothing to do */
6830 while (dowait(DOWAIT_NORMAL, NULL) > 0)
6833 for (jp = curjob; jp; jp = jp->prev_job) {
6834 if (!(mode & SHOW_CHANGED) || jp->changed)
6835 showjob(out, jp, mode);
6841 * Mark a job structure as unused.
6845 freejob(struct job *jp)
6847 struct procstat *ps;
6851 for (i = jp->nprocs, ps = jp->ps ; --i >= 0 ; ps++) {
6852 if (ps->cmd != nullstr)
6855 if (jp->ps != &jp->ps0)
6858 set_curjob(jp, CUR_DELETE);
6864 waitcmd(int argc, char **argv)
6877 /* wait for all jobs */
6882 /* no running procs */
6885 if (jp->state == JOBRUNNING)
6890 dowait(DOWAIT_BLOCK, 0);
6896 if (**argv != '%') {
6897 pid_t pid = number(*argv);
6901 if (job->ps[job->nprocs - 1].pid == pid)
6903 job = job->prev_job;
6909 job = getjob(*argv, 0);
6910 /* loop until process terminated or stopped */
6911 while (job->state == JOBRUNNING)
6912 dowait(DOWAIT_BLOCK, 0);
6914 retval = getstatus(job);
6925 * Convert a job name to a job structure.
6929 getjob(const char *name, int getctl)
6933 const char *err_msg = "No such job: %s";
6937 char *(*match)(const char *, const char *);
6952 if (c == '+' || c == '%') {
6954 err_msg = "No current job";
6956 } else if (c == '-') {
6959 err_msg = "No previous job";
6970 jp = jobtab + num - 1;
6987 if (match(jp->ps[0].cmd, p)) {
6991 err_msg = "%s: ambiguous";
6998 err_msg = "job %s not created under job control";
6999 if (getctl && jp->jobctl == 0)
7004 sh_error(err_msg, name);
7009 * Return a new job structure.
7010 * Called with interrupts off.
7014 makejob(union node *node, int nprocs)
7019 for (i = njobs, jp = jobtab ; ; jp++) {
7026 if (jp->state != JOBDONE || !jp->waited)
7035 memset(jp, 0, sizeof(*jp));
7040 jp->prev_job = curjob;
7045 jp->ps = ckmalloc(nprocs * sizeof (struct procstat));
7047 TRACE(("makejob(0x%lx, %d) returns %%%d\n", (long)node, nprocs,
7057 struct job *jp, *jq;
7059 len = njobs * sizeof(*jp);
7061 jp = ckrealloc(jq, len + 4 * sizeof(*jp));
7063 offset = (char *)jp - (char *)jq;
7065 /* Relocate pointers */
7068 jq = (struct job *)((char *)jq + l);
7072 #define joff(p) ((struct job *)((char *)(p) + l))
7073 #define jmove(p) (p) = (void *)((char *)(p) + offset)
7074 if (xlikely(joff(jp)->ps == &jq->ps0))
7075 jmove(joff(jp)->ps);
7076 if (joff(jp)->prev_job)
7077 jmove(joff(jp)->prev_job);
7087 jp = (struct job *)((char *)jp + len);
7091 } while (--jq >= jp);
7097 * Fork off a subshell. If we are doing job control, give the subshell its
7098 * own process group. Jp is a job structure that the job is to be added to.
7099 * N is the command that will be evaluated by the child. Both jp and n may
7100 * be NULL. The mode parameter can be one of the following:
7101 * FORK_FG - Fork off a foreground process.
7102 * FORK_BG - Fork off a background process.
7103 * FORK_NOJOB - Like FORK_FG, but don't give the process its own
7104 * process group even if job control is on.
7106 * When job control is turned off, background processes have their standard
7107 * input redirected to /dev/null (except for the second and later processes
7110 * Called with interrupts off.
7114 forkchild(struct job *jp, union node *n, int mode)
7118 TRACE(("Child shell %d\n", getpid()));
7125 /* do job control only in root shell */
7127 if (mode != FORK_NOJOB && jp->jobctl && !oldlvl) {
7130 if (jp->nprocs == 0)
7133 pgrp = jp->ps[0].pid;
7134 /* This can fail because we are doing it in the parent also */
7135 (void)setpgid(0, pgrp);
7136 if (mode == FORK_FG)
7137 xtcsetpgrp(ttyfd, pgrp);
7142 if (mode == FORK_BG) {
7145 if (jp->nprocs == 0) {
7147 if (open(_PATH_DEVNULL, O_RDONLY) != 0)
7148 sh_error("Can't open %s", _PATH_DEVNULL);
7151 if (!oldlvl && iflag) {
7156 for (jp = curjob; jp; jp = jp->prev_job)
7162 forkparent(struct job *jp, union node *n, int mode, pid_t pid)
7164 TRACE(("In parent shell: child = %d\n", pid));
7166 while (jobless && dowait(DOWAIT_NORMAL, 0) > 0);
7171 if (mode != FORK_NOJOB && jp->jobctl) {
7174 if (jp->nprocs == 0)
7177 pgrp = jp->ps[0].pid;
7178 /* This can fail because we are doing it in the child also */
7179 (void)setpgid(pid, pgrp);
7182 if (mode == FORK_BG) {
7183 backgndpid = pid; /* set $! */
7184 set_curjob(jp, CUR_RUNNING);
7187 struct procstat *ps = &jp->ps[jp->nprocs++];
7193 ps->cmd = commandtext(n);
7199 forkshell(struct job *jp, union node *n, int mode)
7203 TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode));
7206 TRACE(("Fork failed, errno=%d", errno));
7209 sh_error("Cannot fork");
7212 forkchild(jp, n, mode);
7214 forkparent(jp, n, mode, pid);
7219 * Wait for job to finish.
7221 * Under job control we have the problem that while a child process is
7222 * running interrupts generated by the user are sent to the child but not
7223 * to the shell. This means that an infinite loop started by an inter-
7224 * active user may be hard to kill. With job control turned off, an
7225 * interactive user may place an interactive program inside a loop. If
7226 * the interactive program catches interrupts, the user doesn't want
7227 * these interrupts to also abort the loop. The approach we take here
7228 * is to have the shell ignore interrupt signals while waiting for a
7229 * foreground process to terminate, and then send itself an interrupt
7230 * signal if the child process was terminated by an interrupt signal.
7231 * Unfortunately, some programs want to do a bit of cleanup and then
7232 * exit on interrupt; unless these processes terminate themselves by
7233 * sending a signal to themselves (instead of calling exit) they will
7234 * confuse this approach.
7236 * Called with interrupts off.
7240 waitforjob(struct job *jp)
7244 TRACE(("waitforjob(%%%d) called\n", jobno(jp)));
7245 while (jp->state == JOBRUNNING) {
7246 dowait(DOWAIT_BLOCK, jp);
7251 xtcsetpgrp(ttyfd, rootpid);
7253 * This is truly gross.
7254 * If we're doing job control, then we did a TIOCSPGRP which
7255 * caused us (the shell) to no longer be in the controlling
7256 * session -- so we wouldn't have seen any ^C/SIGINT. So, we
7257 * intuit from the subprocess exit status whether a SIGINT
7258 * occurred, and if so interrupt ourselves. Yuck. - mycroft
7263 if (jp->state == JOBDONE)
7271 * Do a wait system call. If job control is compiled in, we accept
7272 * stopped processes. If block is zero, we return a value of zero
7273 * rather than blocking.
7275 * System V doesn't have a non-blocking wait system call. It does
7276 * have a SIGCLD signal that is sent to a process when one of it's
7277 * children dies. The obvious way to use SIGCLD would be to install
7278 * a handler for SIGCLD which simply bumped a counter when a SIGCLD
7279 * was received, and have waitproc bump another counter when it got
7280 * the status of a process. Waitproc would then know that a wait
7281 * system call would not block if the two counters were different.
7282 * This approach doesn't work because if a process has children that
7283 * have not been waited for, System V will send it a SIGCLD when it
7284 * installs a signal handler for SIGCLD. What this means is that when
7285 * a child exits, the shell will be sent SIGCLD signals continuously
7286 * until is runs out of stack space, unless it does a wait call before
7287 * restoring the signal handler. The code below takes advantage of
7288 * this (mis)feature by installing a signal handler for SIGCLD and
7289 * then checking to see whether it was called. If there are any
7290 * children to be waited for, it will be.
7292 * If neither SYSV nor BSD is defined, we don't implement nonblocking
7293 * waits at all. In this case, the user will not be informed when
7294 * a background process until the next time she runs a real program
7295 * (as opposed to running a builtin command or just typing return),
7296 * and the jobs command may give out of date information.
7300 waitproc(int block, int *status)
7310 return wait3(status, flags, (struct rusage *)NULL);
7314 * Wait for a process to terminate.
7318 dowait(int block, struct job *job)
7323 struct job *thisjob;
7326 TRACE(("dowait(%d) called\n", block));
7327 pid = waitproc(block, &status);
7328 TRACE(("wait returns pid %d, status=%d\n", pid, status));
7333 for (jp = curjob; jp; jp = jp->prev_job) {
7334 struct procstat *sp;
7335 struct procstat *spend;
7336 if (jp->state == JOBDONE)
7339 spend = jp->ps + jp->nprocs;
7342 if (sp->pid == pid) {
7343 TRACE(("Job %d: changing status of proc %d from 0x%x to 0x%x\n", jobno(jp), pid, sp->status, status));
7344 sp->status = status;
7347 if (sp->status == -1)
7350 if (state == JOBRUNNING)
7352 if (WIFSTOPPED(sp->status)) {
7353 jp->stopstatus = sp->status;
7357 } while (++sp < spend);
7362 if (!WIFSTOPPED(status))
7369 if (state != JOBRUNNING) {
7370 thisjob->changed = 1;
7372 if (thisjob->state != state) {
7373 TRACE(("Job %d: changing state from %d to %d\n", jobno(thisjob), thisjob->state, state));
7374 thisjob->state = state;
7376 if (state == JOBSTOPPED) {
7377 set_curjob(thisjob, CUR_STOPPED);
7386 if (thisjob && thisjob == job) {
7390 len = sprint_status(s, status, 1);
7402 * return 1 if there are stopped jobs, otherwise 0
7415 if (jp && jp->state == JOBSTOPPED) {
7416 out2str("You have stopped jobs.\n");
7426 * Return a string identifying a command (to be printed by the
7431 static char *cmdnextc;
7434 commandtext(union node *n)
7438 STARTSTACKSTR(cmdnextc);
7440 name = stackblock();
7441 TRACE(("commandtext: name %p, end %p\n\t\"%s\"\n",
7442 name, cmdnextc, cmdnextc));
7443 return savestr(name);
7447 cmdtxt(union node *n)
7450 struct nodelist *lp;
7462 lp = n->npipe.cmdlist;
7480 cmdtxt(n->nbinary.ch1);
7496 cmdtxt(n->nif.test);
7499 if (n->nif.elsepart) {
7502 n = n->nif.elsepart;
7518 cmdtxt(n->nbinary.ch1);
7528 cmdputs(n->nfor.var);
7530 cmdlist(n->nfor.args, 1);
7535 cmdputs(n->narg.text);
7539 cmdlist(n->ncmd.args, 1);
7540 cmdlist(n->ncmd.redirect, 0);
7553 cmdputs(n->ncase.expr->narg.text);
7555 for (np = n->ncase.cases; np; np = np->nclist.next) {
7556 cmdtxt(np->nclist.pattern);
7558 cmdtxt(np->nclist.body);
7584 s[0] = n->nfile.fd + '0';
7588 if (n->type == NTOFD || n->type == NFROMFD) {
7589 s[0] = n->ndup.dupfd + '0';
7600 cmdlist(union node *np, int sep)
7602 for (; np; np = np->narg.next) {
7606 if (sep && np->narg.next)
7612 cmdputs(const char *s)
7614 const char *p, *str;
7615 char c, cc[2] = " ";
7619 static const char vstype[VSTYPE + 1][4] = {
7620 "", "}", "-", "+", "?", "=",
7621 "%", "%%", "#", "##"
7623 nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc);
7625 while ((c = *p++) != 0) {
7633 if ((subtype & VSTYPE) == VSLENGTH)
7637 if (!(subtype & VSQUOTE) != !(quoted & 1)) {
7644 str = "\"}" + !(quoted & 1);
7651 case CTLBACKQ+CTLQUOTE:
7654 #ifdef CONFIG_ASH_MATH_SUPPORT
7669 if ((subtype & VSTYPE) != VSNORMAL)
7671 str = vstype[subtype & VSTYPE];
7672 if (subtype & VSNUL)
7681 /* These can only happen inside quotes */
7694 while ((c = *str++)) {
7699 USTPUTC('"', nextc);
7707 showpipe(struct job *jp, FILE *out)
7709 struct procstat *sp;
7710 struct procstat *spend;
7712 spend = jp->ps + jp->nprocs;
7713 for (sp = jp->ps + 1; sp < spend; sp++)
7714 fprintf(out, " | %s", sp->cmd);
7715 outcslow('\n', out);
7720 xtcsetpgrp(int fd, pid_t pgrp)
7722 if (tcsetpgrp(fd, pgrp))
7723 sh_error("Cannot set tty process group (%m)");
7728 getstatus(struct job *job) {
7732 status = job->ps[job->nprocs - 1].status;
7733 retval = WEXITSTATUS(status);
7734 if (!WIFEXITED(status)) {
7736 retval = WSTOPSIG(status);
7737 if (!WIFSTOPPED(status))
7740 /* XXX: limits number of signals */
7741 retval = WTERMSIG(status);
7743 if (retval == SIGINT)
7749 TRACE(("getstatus: job %d, nproc %d, status %x, retval %x\n",
7750 jobno(job), job->nprocs, status, retval));
7754 #ifdef CONFIG_ASH_MAIL
7758 * Routines to check for mail. (Perhaps make part of main.c?)
7761 #define MAXMBOXES 10
7763 /* times of mailboxes */
7764 static time_t mailtime[MAXMBOXES];
7765 /* Set if MAIL or MAILPATH is changed. */
7766 static int mail_var_path_changed;
7771 * Print appropriate message(s) if mail has arrived.
7772 * If mail_var_path_changed is set,
7773 * then the value of MAIL has mail_var_path_changed,
7774 * so we just update the values.
7784 struct stackmark smark;
7787 setstackmark(&smark);
7788 mpath = mpathset() ? mpathval() : mailval();
7789 for (mtp = mailtime; mtp < mailtime + MAXMBOXES; mtp++) {
7790 p = padvance(&mpath, nullstr);
7795 for (q = p ; *q ; q++);
7800 q[-1] = '\0'; /* delete trailing '/' */
7801 if (stat(p, &statb) < 0) {
7805 if (!mail_var_path_changed && statb.st_mtime != *mtp) {
7808 pathopt ? pathopt : "you have mail"
7811 *mtp = statb.st_mtime;
7813 mail_var_path_changed = 0;
7814 popstackmark(&smark);
7819 changemail(const char *val)
7821 mail_var_path_changed++;
7824 #endif /* CONFIG_ASH_MAIL */
7830 static short profile_buf[16384];
7834 static int isloginsh;
7836 static void read_profile(const char *);
7839 * Main routine. We initialize things, parse the arguments, execute
7840 * profiles if we're a login shell, and then call cmdloop to execute
7841 * commands. The setjmp call sets up the location to jump to when an
7842 * exception occurs. When an exception occurs the variable "state"
7843 * is used to figure out how far we had gotten.
7847 ash_main(int argc, char **argv)
7851 struct jmploc jmploc;
7852 struct stackmark smark;
7855 dash_errno = __errno_location();
7859 monitor(4, etext, profile_buf, sizeof profile_buf, 50);
7862 if (setjmp(jmploc.loc)) {
7872 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl)
7876 outcslow('\n', stderr);
7878 popstackmark(&smark);
7879 FORCEINTON; /* enable interrupts */
7892 trputs("Shell args: "); trargs(argv);
7896 #ifdef CONFIG_ASH_RANDOM_SUPPORT
7897 rseed = rootpid + ((time_t)time((time_t *)0));
7900 setstackmark(&smark);
7901 procargs(argc, argv);
7902 #ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
7904 const char *hp = lookupvar("HISTFILE");
7907 hp = lookupvar("HOME");
7909 char *defhp = concat_path_file(hp, ".ash_history");
7910 setvar("HISTFILE", defhp, 0);
7916 if (argv[0] && argv[0][0] == '-')
7920 read_profile("/etc/profile");
7923 read_profile(".profile");
7929 getuid() == geteuid() && getgid() == getegid() &&
7933 if ((shinit = lookupvar("ENV")) != NULL && *shinit != '\0') {
7934 read_profile(shinit);
7940 evalstring(minusc, 0);
7942 if (sflag || minusc == NULL) {
7943 #ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
7945 const char *hp = lookupvar("HISTFILE");
7948 load_history ( hp );
7951 state4: /* XXX ??? - why isn't this before the "if" statement */
7959 extern void _mcleanup(void);
7969 * Read and execute commands. "Top" is nonzero for the top level command
7970 * loop; it turns on prompting if the shell is interactive.
7977 struct stackmark smark;
7981 TRACE(("cmdloop(%d) called\n", top));
7985 setstackmark(&smark);
7988 showjobs(stderr, SHOW_CHANGED);
7993 #ifdef CONFIG_ASH_MAIL
7997 n = parsecmd(inter);
7998 /* showtree(n); DEBUG */
8000 if (!top || numeof >= 50)
8002 if (!stoppedjobs()) {
8005 out2str("\nUse \"exit\" to leave shell.\n");
8008 } else if (nflag == 0) {
8009 job_warning = (job_warning == 2) ? 1 : 0;
8013 popstackmark(&smark);
8018 return skip & SKIPEVAL;
8027 * Read /etc/profile or .profile. Return on error.
8031 read_profile(const char *name)
8035 if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
8047 * Read a file containing shell functions.
8051 readcmdfile(char *name)
8053 setinputfile(name, INPUT_PUSH_FILE);
8060 * Take commands from a file. To be compatible we should do a path
8061 * search for the file, which is necessary to find sub-commands.
8064 static inline char *
8065 find_dot_file(char *name)
8068 const char *path = pathval();
8071 /* don't try this for absolute or relative paths */
8072 if (strchr(name, '/'))
8075 while ((fullname = padvance(&path, name)) != NULL) {
8076 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
8078 * Don't bother freeing here, since it will
8079 * be freed by the caller.
8083 stunalloc(fullname);
8086 /* not found in the PATH */
8087 sh_error(not_found_msg, name);
8091 static int dotcmd(int argc, char **argv)
8094 volatile struct shparam saveparam;
8097 for (sp = cmdenviron; sp; sp = sp->next)
8098 setvareq(bb_xstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
8100 if (argc >= 2) { /* That's what SVR2 does */
8103 fullname = find_dot_file(argv[1]);
8106 saveparam = shellparam;
8107 shellparam.malloc = 0;
8108 shellparam.nparam = argc - 2;
8109 shellparam.p = argv + 2;
8112 setinputfile(fullname, INPUT_PUSH_FILE);
8113 commandname = fullname;
8118 freeparam(&shellparam);
8119 shellparam = saveparam;
8121 status = exitstatus;
8128 exitcmd(int argc, char **argv)
8133 exitstatus = number(argv[1]);
8138 #ifdef CONFIG_ASH_BUILTIN_ECHO
8140 echocmd(int argc, char **argv)
8142 return bb_echo(argc, argv);
8148 * Same for malloc, realloc, but returns an error when out of space.
8152 ckrealloc(pointer p, size_t nbytes)
8154 p = realloc(p, nbytes);
8156 sh_error(bb_msg_memory_exhausted);
8161 ckmalloc(size_t nbytes)
8163 return ckrealloc(NULL, nbytes);
8167 * Make a copy of a string in safe storage.
8171 savestr(const char *s)
8173 char *p = strdup(s);
8175 sh_error(bb_msg_memory_exhausted);
8181 * Parse trees for commands are allocated in lifo order, so we use a stack
8182 * to make this more efficient, and also to avoid all sorts of exception
8183 * handling code to handle interrupts in the middle of a parse.
8185 * The size 504 was chosen because the Ultrix malloc handles that size
8191 stalloc(size_t nbytes)
8196 aligned = SHELL_ALIGN(nbytes);
8197 if (aligned > stacknleft) {
8200 struct stack_block *sp;
8202 blocksize = aligned;
8203 if (blocksize < MINSIZE)
8204 blocksize = MINSIZE;
8205 len = sizeof(struct stack_block) - MINSIZE + blocksize;
8206 if (len < blocksize)
8207 sh_error(bb_msg_memory_exhausted);
8211 stacknxt = sp->space;
8212 stacknleft = blocksize;
8213 sstrend = stacknxt + blocksize;
8218 stacknxt += aligned;
8219 stacknleft -= aligned;
8225 stunalloc(pointer p)
8228 if (!p || (stacknxt < (char *)p) || ((char *)p < stackp->space)) {
8229 write(2, "stunalloc\n", 10);
8233 stacknleft += stacknxt - (char *)p;
8239 setstackmark(struct stackmark *mark)
8241 mark->stackp = stackp;
8242 mark->stacknxt = stacknxt;
8243 mark->stacknleft = stacknleft;
8244 mark->marknext = markp;
8250 popstackmark(struct stackmark *mark)
8252 struct stack_block *sp;
8255 markp = mark->marknext;
8256 while (stackp != mark->stackp) {
8261 stacknxt = mark->stacknxt;
8262 stacknleft = mark->stacknleft;
8263 sstrend = mark->stacknxt + mark->stacknleft;
8269 * When the parser reads in a string, it wants to stick the string on the
8270 * stack and only adjust the stack pointer when it knows how big the
8271 * string is. Stackblock (defined in stack.h) returns a pointer to a block
8272 * of space on top of the stack and stackblocklen returns the length of
8273 * this block. Growstackblock will grow this space by at least one byte,
8274 * possibly moving it (like realloc). Grabstackblock actually allocates the
8275 * part of the block that has been used.
8279 growstackblock(void)
8283 newlen = stacknleft * 2;
8284 if (newlen < stacknleft)
8285 sh_error(bb_msg_memory_exhausted);
8289 if (stacknxt == stackp->space && stackp != &stackbase) {
8290 struct stack_block *oldstackp;
8291 struct stackmark *xmark;
8292 struct stack_block *sp;
8293 struct stack_block *prevstackp;
8299 prevstackp = sp->prev;
8300 grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
8301 sp = ckrealloc((pointer)sp, grosslen);
8302 sp->prev = prevstackp;
8304 stacknxt = sp->space;
8305 stacknleft = newlen;
8306 sstrend = sp->space + newlen;
8309 * Stack marks pointing to the start of the old block
8310 * must be relocated to point to the new block
8313 while (xmark != NULL && xmark->stackp == oldstackp) {
8314 xmark->stackp = stackp;
8315 xmark->stacknxt = stacknxt;
8316 xmark->stacknleft = stacknleft;
8317 xmark = xmark->marknext;
8321 char *oldspace = stacknxt;
8322 int oldlen = stacknleft;
8323 char *p = stalloc(newlen);
8325 /* free the space we just allocated */
8326 stacknxt = memcpy(p, oldspace, oldlen);
8327 stacknleft += newlen;
8332 grabstackblock(size_t len)
8334 len = SHELL_ALIGN(len);
8340 * The following routines are somewhat easier to use than the above.
8341 * The user declares a variable of type STACKSTR, which may be declared
8342 * to be a register. The macro STARTSTACKSTR initializes things. Then
8343 * the user uses the macro STPUTC to add characters to the string. In
8344 * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
8345 * grown as necessary. When the user is done, she can just leave the
8346 * string there and refer to it using stackblock(). Or she can allocate
8347 * the space for it using grabstackstr(). If it is necessary to allow
8348 * someone else to use the stack temporarily and then continue to grow
8349 * the string, the user should use grabstack to allocate the space, and
8350 * then call ungrabstr(p) to return to the previous mode of operation.
8352 * USTPUTC is like STPUTC except that it doesn't check for overflow.
8353 * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
8354 * is space for at least one character.
8360 size_t len = stackblocksize();
8361 if (herefd >= 0 && len >= 1024) {
8362 bb_full_write(herefd, stackblock(), len);
8363 return stackblock();
8366 return stackblock() + len;
8370 * Called from CHECKSTRSPACE.
8374 makestrspace(size_t newlen, char *p)
8376 size_t len = p - stacknxt;
8377 size_t size = stackblocksize();
8382 size = stackblocksize();
8384 if (nleft >= newlen)
8388 return stackblock() + len;
8392 stnputs(const char *s, size_t n, char *p)
8394 p = makestrspace(n, p);
8395 p = mempcpy(p, s, n);
8400 stputs(const char *s, char *p)
8402 return stnputs(s, strlen(s), p);
8410 * number(s) Convert a string of digits to an integer.
8411 * is_number(s) Return true if s is a string of digits.
8415 * prefix -- see if pfx is a prefix of string.
8419 prefix(const char *string, const char *pfx)
8422 if (*pfx++ != *string++)
8425 return (char *) string;
8430 * Convert a string of digits to an integer, printing an error message on
8435 number(const char *s)
8439 sh_error(illnum, s);
8445 * Check for a valid number. This should be elsewhere.
8449 is_number(const char *p)
8454 } while (*++p != '\0');
8460 * Produce a possibly single quoted string suitable as input to the shell.
8461 * The return string is allocated on the stack.
8465 single_quote(const char *s) {
8474 len = strchrnul(s, '\'') - s;
8476 q = p = makestrspace(len + 3, p);
8479 q = mempcpy(q, s, len);
8485 len = strspn(s, "'");
8489 q = p = makestrspace(len + 3, p);
8492 q = mempcpy(q, s, len);
8501 return stackblock();
8505 * Like strdup but works with the ash stack.
8509 sstrdup(const char *p)
8511 size_t len = strlen(p) + 1;
8512 return memcpy(stalloc(len), p, len);
8517 calcsize(union node *n)
8521 funcblocksize += nodesize[n->type];
8524 calcsize(n->ncmd.redirect);
8525 calcsize(n->ncmd.args);
8526 calcsize(n->ncmd.assign);
8529 sizenodelist(n->npipe.cmdlist);
8534 calcsize(n->nredir.redirect);
8535 calcsize(n->nredir.n);
8542 calcsize(n->nbinary.ch2);
8543 calcsize(n->nbinary.ch1);
8546 calcsize(n->nif.elsepart);
8547 calcsize(n->nif.ifpart);
8548 calcsize(n->nif.test);
8551 funcstringsize += strlen(n->nfor.var) + 1;
8552 calcsize(n->nfor.body);
8553 calcsize(n->nfor.args);
8556 calcsize(n->ncase.cases);
8557 calcsize(n->ncase.expr);
8560 calcsize(n->nclist.body);
8561 calcsize(n->nclist.pattern);
8562 calcsize(n->nclist.next);
8566 sizenodelist(n->narg.backquote);
8567 funcstringsize += strlen(n->narg.text) + 1;
8568 calcsize(n->narg.next);
8575 calcsize(n->nfile.fname);
8576 calcsize(n->nfile.next);
8580 calcsize(n->ndup.vname);
8581 calcsize(n->ndup.next);
8585 calcsize(n->nhere.doc);
8586 calcsize(n->nhere.next);
8589 calcsize(n->nnot.com);
8596 sizenodelist(struct nodelist *lp)
8599 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
8607 copynode(union node *n)
8614 funcblock = (char *) funcblock + nodesize[n->type];
8617 new->ncmd.redirect = copynode(n->ncmd.redirect);
8618 new->ncmd.args = copynode(n->ncmd.args);
8619 new->ncmd.assign = copynode(n->ncmd.assign);
8622 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
8623 new->npipe.backgnd = n->npipe.backgnd;
8628 new->nredir.redirect = copynode(n->nredir.redirect);
8629 new->nredir.n = copynode(n->nredir.n);
8636 new->nbinary.ch2 = copynode(n->nbinary.ch2);
8637 new->nbinary.ch1 = copynode(n->nbinary.ch1);
8640 new->nif.elsepart = copynode(n->nif.elsepart);
8641 new->nif.ifpart = copynode(n->nif.ifpart);
8642 new->nif.test = copynode(n->nif.test);
8645 new->nfor.var = nodesavestr(n->nfor.var);
8646 new->nfor.body = copynode(n->nfor.body);
8647 new->nfor.args = copynode(n->nfor.args);
8650 new->ncase.cases = copynode(n->ncase.cases);
8651 new->ncase.expr = copynode(n->ncase.expr);
8654 new->nclist.body = copynode(n->nclist.body);
8655 new->nclist.pattern = copynode(n->nclist.pattern);
8656 new->nclist.next = copynode(n->nclist.next);
8660 new->narg.backquote = copynodelist(n->narg.backquote);
8661 new->narg.text = nodesavestr(n->narg.text);
8662 new->narg.next = copynode(n->narg.next);
8669 new->nfile.fname = copynode(n->nfile.fname);
8670 new->nfile.fd = n->nfile.fd;
8671 new->nfile.next = copynode(n->nfile.next);
8675 new->ndup.vname = copynode(n->ndup.vname);
8676 new->ndup.dupfd = n->ndup.dupfd;
8677 new->ndup.fd = n->ndup.fd;
8678 new->ndup.next = copynode(n->ndup.next);
8682 new->nhere.doc = copynode(n->nhere.doc);
8683 new->nhere.fd = n->nhere.fd;
8684 new->nhere.next = copynode(n->nhere.next);
8687 new->nnot.com = copynode(n->nnot.com);
8690 new->type = n->type;
8695 static struct nodelist *
8696 copynodelist(struct nodelist *lp)
8698 struct nodelist *start;
8699 struct nodelist **lpp;
8704 funcblock = (char *) funcblock +
8705 SHELL_ALIGN(sizeof(struct nodelist));
8706 (*lpp)->n = copynode(lp->n);
8708 lpp = &(*lpp)->next;
8716 nodesavestr(char *s)
8718 char *rtn = funcstring;
8720 funcstring = stpcpy(funcstring, s) + 1;
8726 * Free a parse tree.
8730 freefunc(struct funcnode *f)
8732 if (f && --f->count < 0)
8737 static void options(int);
8738 static void setoption(int, int);
8742 * Process the shell command line arguments.
8746 procargs(int argc, char **argv)
8749 const char *xminusc;
8756 for (i = 0; i < NOPTS; i++)
8762 if (*xargv == NULL) {
8764 sh_error("-c requires an argument");
8767 if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
8771 for (i = 0; i < NOPTS; i++)
8772 if (optlist[i] == 2)
8777 /* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
8782 } else if (!sflag) {
8783 setinputfile(*xargv, 0);
8789 shellparam.p = xargv;
8790 #ifdef CONFIG_ASH_GETOPTS
8791 shellparam.optind = 1;
8792 shellparam.optoff = -1;
8794 /* assert(shellparam.malloc == 0 && shellparam.nparam == 0); */
8796 shellparam.nparam++;
8809 setinteractive(iflag);
8815 minus_o(char *name, int val)
8820 out1str("Current option settings\n");
8821 for (i = 0; i < NOPTS; i++)
8822 out1fmt("%-16s%s\n", optnames(i),
8823 optlist[i] ? "on" : "off");
8825 for (i = 0; i < NOPTS; i++)
8826 if (equal(name, optnames(i))) {
8830 sh_error("Illegal option -o %s", name);
8835 * Process shell options. The global variable argptr contains a pointer
8836 * to the argument list; we advance it past the options.
8840 options(int cmdline)
8848 while ((p = *argptr) != NULL) {
8850 if ((c = *p++) == '-') {
8852 if (p[0] == '\0' || (p[0] == '-' && p[1] == '\0')) {
8854 /* "-" means turn off -x and -v */
8857 /* "--" means reset params */
8858 else if (*argptr == NULL)
8861 break; /* "-" or "--" terminates options */
8863 } else if (c == '+') {
8869 while ((c = *p++) != '\0') {
8870 if (c == 'c' && cmdline) {
8871 minusc = p; /* command is after shell args*/
8872 } else if (c == 'o') {
8873 minus_o(*argptr, val);
8876 } else if (cmdline && (c == '-')) { // long options
8877 if (strcmp(p, "login") == 0)
8889 setoption(int flag, int val)
8893 for (i = 0; i < NOPTS; i++)
8894 if (optletters(i) == flag) {
8898 sh_error("Illegal option -%c", flag);
8905 * Set the shell parameters.
8909 setparam(char **argv)
8915 for (nparam = 0 ; argv[nparam] ; nparam++);
8916 ap = newparam = ckmalloc((nparam + 1) * sizeof *ap);
8918 *ap++ = savestr(*argv++);
8921 freeparam(&shellparam);
8922 shellparam.malloc = 1;
8923 shellparam.nparam = nparam;
8924 shellparam.p = newparam;
8925 #ifdef CONFIG_ASH_GETOPTS
8926 shellparam.optind = 1;
8927 shellparam.optoff = -1;
8933 * Free the list of positional parameters.
8937 freeparam(volatile struct shparam *param)
8941 if (param->malloc) {
8942 for (ap = param->p ; *ap ; ap++)
8951 * The shift builtin command.
8955 shiftcmd(int argc, char **argv)
8962 n = number(argv[1]);
8963 if (n > shellparam.nparam)
8964 sh_error("can't shift that many");
8966 shellparam.nparam -= n;
8967 for (ap1 = shellparam.p ; --n >= 0 ; ap1++) {
8968 if (shellparam.malloc)
8972 while ((*ap2++ = *ap1++) != NULL);
8973 #ifdef CONFIG_ASH_GETOPTS
8974 shellparam.optind = 1;
8975 shellparam.optoff = -1;
8984 * The set command builtin.
8988 setcmd(int argc, char **argv)
8991 return showvars(nullstr, 0, VUNSET);
8995 if (*argptr != NULL) {
9003 #ifdef CONFIG_ASH_GETOPTS
9008 shellparam.optind = number(value);
9009 shellparam.optoff = -1;
9013 #ifdef CONFIG_LOCALE_SUPPORT
9014 static void change_lc_all(const char *value)
9016 if (value != 0 && *value != 0)
9017 setlocale(LC_ALL, value);
9020 static void change_lc_ctype(const char *value)
9022 if (value != 0 && *value != 0)
9023 setlocale(LC_CTYPE, value);
9028 #ifdef CONFIG_ASH_RANDOM_SUPPORT
9029 /* Roughly copied from bash.. */
9030 static void change_random(const char *value)
9033 /* "get", generate */
9036 rseed = rseed * 1103515245 + 12345;
9037 sprintf(buf, "%d", (unsigned int)((rseed & 32767)));
9038 /* set without recursion */
9039 setvar(vrandom.text, buf, VNOFUNC);
9040 vrandom.flags &= ~VNOFUNC;
9043 rseed = strtoul(value, (char **)NULL, 10);
9049 #ifdef CONFIG_ASH_GETOPTS
9051 getopts(char *optstr, char *optvar, char **optfirst, int *param_optind, int *optoff)
9060 if(*param_optind < 1)
9062 optnext = optfirst + *param_optind - 1;
9064 if (*param_optind <= 1 || *optoff < 0 || strlen(optnext[-1]) < *optoff)
9067 p = optnext[-1] + *optoff;
9068 if (p == NULL || *p == '\0') {
9069 /* Current word is done, advance */
9071 if (p == NULL || *p != '-' || *++p == '\0') {
9078 if (p[0] == '-' && p[1] == '\0') /* check for "--" */
9083 for (q = optstr; *q != c; ) {
9085 if (optstr[0] == ':') {
9088 err |= setvarsafe("OPTARG", s, 0);
9090 fprintf(stderr, "Illegal option -%c\n", c);
9091 (void) unsetvar("OPTARG");
9101 if (*p == '\0' && (p = *optnext) == NULL) {
9102 if (optstr[0] == ':') {
9105 err |= setvarsafe("OPTARG", s, 0);
9108 fprintf(stderr, "No arg for -%c option\n", c);
9109 (void) unsetvar("OPTARG");
9117 err |= setvarsafe("OPTARG", p, 0);
9120 err |= setvarsafe("OPTARG", nullstr, 0);
9123 *optoff = p ? p - *(optnext - 1) : -1;
9124 *param_optind = optnext - optfirst + 1;
9125 fmtstr(s, sizeof(s), "%d", *param_optind);
9126 err |= setvarsafe("OPTIND", s, VNOFUNC);
9129 err |= setvarsafe(optvar, s, 0);
9140 * The getopts builtin. Shellparam.optnext points to the next argument
9141 * to be processed. Shellparam.optptr points to the next character to
9142 * be processed in the current argument. If shellparam.optnext is NULL,
9143 * then it's the first time getopts has been called.
9147 getoptscmd(int argc, char **argv)
9152 sh_error("Usage: getopts optstring var [arg]");
9153 else if (argc == 3) {
9154 optbase = shellparam.p;
9155 if (shellparam.optind > shellparam.nparam + 1) {
9156 shellparam.optind = 1;
9157 shellparam.optoff = -1;
9162 if (shellparam.optind > argc - 2) {
9163 shellparam.optind = 1;
9164 shellparam.optoff = -1;
9168 return getopts(argv[1], argv[2], optbase, &shellparam.optind,
9169 &shellparam.optoff);
9171 #endif /* CONFIG_ASH_GETOPTS */
9174 * XXX - should get rid of. have all builtins use getopt(3). the
9175 * library getopt must have the BSD extension static variable "optreset"
9176 * otherwise it can't be used within the shell safely.
9178 * Standard option processing (a la getopt) for builtin routines. The
9179 * only argument that is passed to nextopt is the option string; the
9180 * other arguments are unnecessary. It return the character, or '\0' on
9185 nextopt(const char *optstring)
9191 if ((p = optptr) == NULL || *p == '\0') {
9193 if (p == NULL || *p != '-' || *++p == '\0')
9196 if (p[0] == '-' && p[1] == '\0') /* check for "--" */
9200 for (q = optstring ; *q != c ; ) {
9202 sh_error("Illegal option -%c", c);
9207 if (*p == '\0' && (p = *argptr++) == NULL)
9208 sh_error("No arg for -%c option", c);
9220 outstr(const char *p, FILE *file)
9245 outcslow(int c, FILE *dest)
9255 out1fmt(const char *fmt, ...)
9262 r = vprintf(fmt, ap);
9270 fmtstr(char *outbuf, size_t length, const char *fmt, ...)
9277 ret = vsnprintf(outbuf, length, fmt, ap);
9289 * Shell command parser.
9292 #define EOFMARKLEN 79
9296 struct heredoc *next; /* next here document in list */
9297 union node *here; /* redirection node */
9298 char *eofmark; /* string indicating end of input */
9299 int striptabs; /* if set, strip leading tabs */
9304 static struct heredoc *heredoclist; /* list of here documents to read */
9307 static union node *list(int);
9308 static union node *andor(void);
9309 static union node *pipeline(void);
9310 static union node *command(void);
9311 static union node *simplecmd(void);
9312 static union node *makename(void);
9313 static void parsefname(void);
9314 static void parseheredoc(void);
9315 static char peektoken(void);
9316 static int readtoken(void);
9317 static int xxreadtoken(void);
9318 static int readtoken1(int firstc, int syntax, char *eofmark, int striptabs);
9319 static int noexpand(char *);
9320 static void synexpect(int) ATTRIBUTE_NORETURN;
9321 static void synerror(const char *) ATTRIBUTE_NORETURN;
9322 static void setprompt(int);
9328 * Read and parse a command. Returns NEOF on end of file. (NULL is a
9329 * valid parse tree indicating a blank line.)
9333 parsecmd(int interact)
9338 doprompt = interact;
9340 setprompt(doprompt);
9355 union node *n1, *n2, *n3;
9358 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9359 if (nlflag == 2 && peektoken())
9365 if (tok == TBACKGND) {
9366 if (n2->type == NPIPE) {
9367 n2->npipe.backgnd = 1;
9369 if (n2->type != NREDIR) {
9370 n3 = stalloc(sizeof(struct nredir));
9372 n3->nredir.redirect = NULL;
9375 n2->type = NBACKGND;
9382 n3 = (union node *)stalloc(sizeof (struct nbinary));
9384 n3->nbinary.ch1 = n1;
9385 n3->nbinary.ch2 = n2;
9401 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9409 pungetc(); /* push back EOF on input */
9425 union node *n1, *n2, *n3;
9430 if ((t = readtoken()) == TAND) {
9432 } else if (t == TOR) {
9438 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9440 n3 = (union node *)stalloc(sizeof (struct nbinary));
9442 n3->nbinary.ch1 = n1;
9443 n3->nbinary.ch2 = n2;
9453 union node *n1, *n2, *pipenode;
9454 struct nodelist *lp, *prev;
9458 TRACE(("pipeline: entered\n"));
9459 if (readtoken() == TNOT) {
9461 checkkwd = CHKKWD | CHKALIAS;
9465 if (readtoken() == TPIPE) {
9466 pipenode = (union node *)stalloc(sizeof (struct npipe));
9467 pipenode->type = NPIPE;
9468 pipenode->npipe.backgnd = 0;
9469 lp = (struct nodelist *)stalloc(sizeof (struct nodelist));
9470 pipenode->npipe.cmdlist = lp;
9474 lp = (struct nodelist *)stalloc(sizeof (struct nodelist));
9475 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9478 } while (readtoken() == TPIPE);
9484 n2 = (union node *)stalloc(sizeof (struct nnot));
9497 union node *n1, *n2;
9498 union node *ap, **app;
9499 union node *cp, **cpp;
9500 union node *redir, **rpp;
9507 switch (readtoken()) {
9512 n1 = (union node *)stalloc(sizeof (struct nif));
9514 n1->nif.test = list(0);
9515 if (readtoken() != TTHEN)
9517 n1->nif.ifpart = list(0);
9519 while (readtoken() == TELIF) {
9520 n2->nif.elsepart = (union node *)stalloc(sizeof (struct nif));
9521 n2 = n2->nif.elsepart;
9523 n2->nif.test = list(0);
9524 if (readtoken() != TTHEN)
9526 n2->nif.ifpart = list(0);
9528 if (lasttoken == TELSE)
9529 n2->nif.elsepart = list(0);
9531 n2->nif.elsepart = NULL;
9539 n1 = (union node *)stalloc(sizeof (struct nbinary));
9540 n1->type = (lasttoken == TWHILE)? NWHILE : NUNTIL;
9541 n1->nbinary.ch1 = list(0);
9542 if ((got=readtoken()) != TDO) {
9543 TRACE(("expecting DO got %s %s\n", tokname(got), got == TWORD ? wordtext : ""));
9546 n1->nbinary.ch2 = list(0);
9551 if (readtoken() != TWORD || quoteflag || ! goodname(wordtext))
9552 synerror("Bad for loop variable");
9553 n1 = (union node *)stalloc(sizeof (struct nfor));
9555 n1->nfor.var = wordtext;
9556 checkkwd = CHKKWD | CHKALIAS;
9557 if (readtoken() == TIN) {
9559 while (readtoken() == TWORD) {
9560 n2 = (union node *)stalloc(sizeof (struct narg));
9562 n2->narg.text = wordtext;
9563 n2->narg.backquote = backquotelist;
9565 app = &n2->narg.next;
9569 if (lasttoken != TNL && lasttoken != TSEMI)
9572 n2 = (union node *)stalloc(sizeof (struct narg));
9574 n2->narg.text = (char *)dolatstr;
9575 n2->narg.backquote = NULL;
9576 n2->narg.next = NULL;
9579 * Newline or semicolon here is optional (but note
9580 * that the original Bourne shell only allowed NL).
9582 if (lasttoken != TNL && lasttoken != TSEMI)
9585 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9586 if (readtoken() != TDO)
9588 n1->nfor.body = list(0);
9592 n1 = (union node *)stalloc(sizeof (struct ncase));
9594 if (readtoken() != TWORD)
9596 n1->ncase.expr = n2 = (union node *)stalloc(sizeof (struct narg));
9598 n2->narg.text = wordtext;
9599 n2->narg.backquote = backquotelist;
9600 n2->narg.next = NULL;
9602 checkkwd = CHKKWD | CHKALIAS;
9603 } while (readtoken() == TNL);
9604 if (lasttoken != TIN)
9606 cpp = &n1->ncase.cases;
9608 checkkwd = CHKNL | CHKKWD;
9611 if (lasttoken == TLP)
9613 *cpp = cp = (union node *)stalloc(sizeof (struct nclist));
9615 app = &cp->nclist.pattern;
9617 *app = ap = (union node *)stalloc(sizeof (struct narg));
9619 ap->narg.text = wordtext;
9620 ap->narg.backquote = backquotelist;
9621 if (readtoken() != TPIPE)
9623 app = &ap->narg.next;
9626 ap->narg.next = NULL;
9627 if (lasttoken != TRP)
9629 cp->nclist.body = list(2);
9631 cpp = &cp->nclist.next;
9633 checkkwd = CHKNL | CHKKWD;
9634 if ((t = readtoken()) != TESAC) {
9636 synexpect(TENDCASE);
9644 n1 = (union node *)stalloc(sizeof (struct nredir));
9645 n1->type = NSUBSHELL;
9646 n1->nredir.n = list(0);
9647 n1->nredir.redirect = NULL;
9660 if (readtoken() != t)
9664 /* Now check for redirection which may follow command */
9665 checkkwd = CHKKWD | CHKALIAS;
9667 while (readtoken() == TREDIR) {
9668 *rpp = n2 = redirnode;
9669 rpp = &n2->nfile.next;
9675 if (n1->type != NSUBSHELL) {
9676 n2 = (union node *)stalloc(sizeof (struct nredir));
9681 n1->nredir.redirect = redir;
9690 union node *args, **app;
9691 union node *n = NULL;
9692 union node *vars, **vpp;
9693 union node **rpp, *redir;
9703 savecheckkwd = CHKALIAS;
9705 checkkwd = savecheckkwd;
9706 switch (readtoken()) {
9708 n = (union node *)stalloc(sizeof (struct narg));
9710 n->narg.text = wordtext;
9711 n->narg.backquote = backquotelist;
9712 if (savecheckkwd && isassignment(wordtext)) {
9714 vpp = &n->narg.next;
9717 app = &n->narg.next;
9722 *rpp = n = redirnode;
9723 rpp = &n->nfile.next;
9724 parsefname(); /* read name of redirection file */
9728 args && app == &args->narg.next &&
9731 struct builtincmd *bcmd;
9734 /* We have a function */
9735 if (readtoken() != TRP)
9737 name = n->narg.text;
9739 !goodname(name) || (
9740 (bcmd = find_builtin(name)) &&
9741 IS_BUILTIN_SPECIAL(bcmd)
9744 synerror("Bad function name");
9746 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9747 n->narg.next = command();
9760 n = (union node *)stalloc(sizeof (struct ncmd));
9762 n->ncmd.args = args;
9763 n->ncmd.assign = vars;
9764 n->ncmd.redirect = redir;
9773 n = (union node *)stalloc(sizeof (struct narg));
9775 n->narg.next = NULL;
9776 n->narg.text = wordtext;
9777 n->narg.backquote = backquotelist;
9781 void fixredir(union node *n, const char *text, int err)
9783 TRACE(("Fix redir %s %d\n", text, err));
9785 n->ndup.vname = NULL;
9787 if (is_digit(text[0]) && text[1] == '\0')
9788 n->ndup.dupfd = digit_val(text[0]);
9789 else if (text[0] == '-' && text[1] == '\0')
9794 synerror("Bad fd number");
9796 n->ndup.vname = makename();
9804 union node *n = redirnode;
9806 if (readtoken() != TWORD)
9808 if (n->type == NHERE) {
9809 struct heredoc *here = heredoc;
9815 TRACE(("Here document %d\n", n->type));
9816 if (! noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)
9817 synerror("Illegal eof marker for << redirection");
9818 rmescapes(wordtext);
9819 here->eofmark = wordtext;
9821 if (heredoclist == NULL)
9824 for (p = heredoclist ; p->next ; p = p->next);
9827 } else if (n->type == NTOFD || n->type == NFROMFD) {
9828 fixredir(n, wordtext, 0);
9830 n->nfile.fname = makename();
9836 * Input any here documents.
9842 struct heredoc *here;
9852 readtoken1(pgetc(), here->here->type == NHERE? SQSYNTAX : DQSYNTAX,
9853 here->eofmark, here->striptabs);
9854 n = (union node *)stalloc(sizeof (struct narg));
9855 n->narg.type = NARG;
9856 n->narg.next = NULL;
9857 n->narg.text = wordtext;
9858 n->narg.backquote = backquotelist;
9859 here->here->nhere.doc = n;
9864 static char peektoken(void)
9870 return tokname_array[t][0];
9878 int alreadyseen = tokpushback;
9881 #ifdef CONFIG_ASH_ALIAS
9890 if (checkkwd & CHKNL) {
9897 if (t != TWORD || quoteflag) {
9902 * check for keywords
9904 if (checkkwd & CHKKWD) {
9905 const char *const *pp;
9907 if ((pp = findkwd(wordtext))) {
9908 lasttoken = t = pp - tokname_array;
9909 TRACE(("keyword %s recognized\n", tokname(t)));
9914 if (checkkwd & CHKALIAS) {
9915 #ifdef CONFIG_ASH_ALIAS
9917 if ((ap = lookupalias(wordtext, 1)) != NULL) {
9919 pushstring(ap->val, ap);
9929 TRACE(("token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
9931 TRACE(("reread token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
9938 * Read the next input token.
9939 * If the token is a word, we set backquotelist to the list of cmds in
9940 * backquotes. We set quoteflag to true if any part of the word was
9942 * If the token is TREDIR, then we set redirnode to a structure containing
9944 * In all cases, the variable startlinno is set to the number of the line
9945 * on which the token starts.
9947 * [Change comment: here documents and internal procedures]
9948 * [Readtoken shouldn't have any arguments. Perhaps we should make the
9949 * word parsing code into a separate routine. In this case, readtoken
9950 * doesn't need to have any internal procedures, but parseword does.
9951 * We could also make parseoperator in essence the main routine, and
9952 * have parseword (readtoken1?) handle both words and redirection.]
9955 #define NEW_xxreadtoken
9956 #ifdef NEW_xxreadtoken
9958 /* singles must be first! */
9959 static const char xxreadtoken_chars[7] = { '\n', '(', ')', '&', '|', ';', 0 };
9961 static const char xxreadtoken_tokens[] = {
9962 TNL, TLP, TRP, /* only single occurrence allowed */
9963 TBACKGND, TPIPE, TSEMI, /* if single occurrence */
9964 TEOF, /* corresponds to trailing nul */
9965 TAND, TOR, TENDCASE, /* if double occurrence */
9968 #define xxreadtoken_doubles \
9969 (sizeof(xxreadtoken_tokens) - sizeof(xxreadtoken_chars))
9970 #define xxreadtoken_singles \
9971 (sizeof(xxreadtoken_chars) - xxreadtoken_doubles - 1)
9973 static int xxreadtoken()
9984 startlinno = plinno;
9985 for (;;) { /* until token or start of word found */
9988 if ((c != ' ') && (c != '\t')
9989 #ifdef CONFIG_ASH_ALIAS
9994 while ((c = pgetc()) != '\n' && c != PEOF);
9996 } else if (c == '\\') {
9997 if (pgetc() != '\n') {
10001 startlinno = ++plinno;
10006 = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
10011 needprompt = doprompt;
10014 p = strchr(xxreadtoken_chars, c);
10017 return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
10020 if (p - xxreadtoken_chars >= xxreadtoken_singles) {
10021 if (pgetc() == *p) { /* double occurrence? */
10022 p += xxreadtoken_doubles + 1;
10029 return lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
10037 #define RETURN(token) return lasttoken = token
10051 startlinno = plinno;
10052 for (;;) { /* until token or start of word found */
10055 case ' ': case '\t':
10056 #ifdef CONFIG_ASH_ALIAS
10061 while ((c = pgetc()) != '\n' && c != PEOF);
10065 if (pgetc() == '\n') {
10066 startlinno = ++plinno;
10075 needprompt = doprompt;
10080 if (pgetc() == '&')
10085 if (pgetc() == '|')
10090 if (pgetc() == ';')
10103 return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
10106 #endif /* NEW_xxreadtoken */
10110 * If eofmark is NULL, read a word or a redirection symbol. If eofmark
10111 * is not NULL, read a here document. In the latter case, eofmark is the
10112 * word which marks the end of the document and striptabs is true if
10113 * leading tabs should be stripped from the document. The argument firstc
10114 * is the first character of the input token or document.
10116 * Because C does not have internal subroutines, I have simulated them
10117 * using goto's to implement the subroutine linkage. The following macros
10118 * will run code that appears at the end of readtoken1.
10121 #define CHECKEND() {goto checkend; checkend_return:;}
10122 #define PARSEREDIR() {goto parseredir; parseredir_return:;}
10123 #define PARSESUB() {goto parsesub; parsesub_return:;}
10124 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
10125 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
10126 #define PARSEARITH() {goto parsearith; parsearith_return:;}
10129 readtoken1(int firstc, int syntax, char *eofmark, int striptabs)
10134 char line[EOFMARKLEN + 1];
10135 struct nodelist *bqlist;
10138 int varnest; /* levels of variables expansion */
10139 int arinest; /* levels of arithmetic expansion */
10140 int parenlevel; /* levels of parens in arithmetic */
10141 int dqvarnest; /* levels of variables expansion within double quotes */
10143 int prevsyntax; /* syntax before arithmetic */
10145 /* Avoid longjmp clobbering */
10151 (void) &parenlevel;
10154 (void) &prevsyntax;
10158 startlinno = plinno;
10160 if (syntax == DQSYNTAX)
10169 STARTSTACKSTR(out);
10170 loop: { /* for each line, until end of word */
10171 CHECKEND(); /* set c to PEOF if at end of here document */
10172 for (;;) { /* until end of line or end of word */
10173 CHECKSTRSPACE(4, out); /* permit 4 calls to USTPUTC */
10174 switch(SIT(c, syntax)) {
10175 case CNL: /* '\n' */
10176 if (syntax == BASESYNTAX)
10177 goto endword; /* exit outer loop */
10183 goto loop; /* continue outer loop */
10188 if (eofmark == NULL || dblquote)
10189 USTPUTC(CTLESC, out);
10192 case CBACK: /* backslash */
10195 USTPUTC(CTLESC, out);
10196 USTPUTC('\\', out);
10198 } else if (c == '\n') {
10203 c != '\\' && c != '`' &&
10208 USTPUTC(CTLESC, out);
10209 USTPUTC('\\', out);
10211 if (SIT(c, SQSYNTAX) == CCTL)
10212 USTPUTC(CTLESC, out);
10220 if (eofmark == NULL) {
10221 USTPUTC(CTLQUOTEMARK, out);
10229 if (eofmark != NULL && arinest == 0 &&
10233 if (dqvarnest == 0) {
10234 syntax = BASESYNTAX;
10241 case CVAR: /* '$' */
10242 PARSESUB(); /* parse substitution */
10244 case CENDVAR: /* '}' */
10247 if (dqvarnest > 0) {
10250 USTPUTC(CTLENDVAR, out);
10255 #ifdef CONFIG_ASH_MATH_SUPPORT
10256 case CLP: /* '(' in arithmetic */
10260 case CRP: /* ')' in arithmetic */
10261 if (parenlevel > 0) {
10265 if (pgetc() == ')') {
10266 if (--arinest == 0) {
10267 USTPUTC(CTLENDARI, out);
10268 syntax = prevsyntax;
10269 if (syntax == DQSYNTAX)
10277 * unbalanced parens
10278 * (don't 2nd guess - no error)
10286 case CBQUOTE: /* '`' */
10290 goto endword; /* exit outer loop */
10295 goto endword; /* exit outer loop */
10296 #ifdef CONFIG_ASH_ALIAS
10306 #ifdef CONFIG_ASH_MATH_SUPPORT
10307 if (syntax == ARISYNTAX)
10308 synerror("Missing '))'");
10310 if (syntax != BASESYNTAX && ! parsebackquote && eofmark == NULL)
10311 synerror("Unterminated quoted string");
10312 if (varnest != 0) {
10313 startlinno = plinno;
10315 synerror("Missing '}'");
10317 USTPUTC('\0', out);
10318 len = out - (char *)stackblock();
10319 out = stackblock();
10320 if (eofmark == NULL) {
10321 if ((c == '>' || c == '<')
10324 && (*out == '\0' || is_digit(*out))) {
10326 return lasttoken = TREDIR;
10331 quoteflag = quotef;
10332 backquotelist = bqlist;
10333 grabstackblock(len);
10335 return lasttoken = TWORD;
10336 /* end of readtoken routine */
10341 * Check to see whether we are at the end of the here document. When this
10342 * is called, c is set to the first character of the next input line. If
10343 * we are at the end of the here document, this routine sets the c to PEOF.
10348 #ifdef CONFIG_ASH_ALIAS
10354 while (c == '\t') {
10358 if (c == *eofmark) {
10359 if (pfgets(line, sizeof line) != NULL) {
10363 for (q = eofmark + 1 ; *q && *p == *q ; p++, q++);
10364 if (*p == '\n' && *q == '\0') {
10367 needprompt = doprompt;
10369 pushstring(line, NULL);
10374 goto checkend_return;
10379 * Parse a redirection operator. The variable "out" points to a string
10380 * specifying the fd to be redirected. The variable "c" contains the
10381 * first character of the redirection operator.
10388 np = (union node *)stalloc(sizeof (struct nfile));
10393 np->type = NAPPEND;
10395 np->type = NCLOBBER;
10402 } else { /* c == '<' */
10404 switch (c = pgetc()) {
10406 if (sizeof (struct nfile) != sizeof (struct nhere)) {
10407 np = (union node *)stalloc(sizeof (struct nhere));
10411 heredoc = (struct heredoc *)stalloc(sizeof (struct heredoc));
10412 heredoc->here = np;
10413 if ((c = pgetc()) == '-') {
10414 heredoc->striptabs = 1;
10416 heredoc->striptabs = 0;
10422 np->type = NFROMFD;
10426 np->type = NFROMTO;
10436 np->nfile.fd = digit_val(fd);
10438 goto parseredir_return;
10443 * Parse a substitution. At this point, we have read the dollar sign
10444 * and nothing else.
10452 static const char types[] = "}-+?=";
10456 c <= PEOA_OR_PEOF ||
10457 (c != '(' && c != '{' && !is_name(c) && !is_special(c))
10461 } else if (c == '(') { /* $(command) or $((arith)) */
10462 if (pgetc() == '(') {
10463 #ifdef CONFIG_ASH_MATH_SUPPORT
10466 synerror("We unsupport $((arith))");
10473 USTPUTC(CTLVAR, out);
10474 typeloc = out - (char *)stackblock();
10475 USTPUTC(VSNORMAL, out);
10476 subtype = VSNORMAL;
10480 if ((c = pgetc()) == '}')
10483 subtype = VSLENGTH;
10488 if (c > PEOA_OR_PEOF && is_name(c)) {
10492 } while (c > PEOA_OR_PEOF && is_in_name(c));
10493 } else if (is_digit(c)) {
10497 } while (is_digit(c));
10499 else if (is_special(c)) {
10504 badsub: synerror("Bad substitution");
10508 if (subtype == 0) {
10515 p = strchr(types, c);
10518 subtype = p - types + VSNORMAL;
10524 subtype = c == '#' ? VSTRIMLEFT :
10537 if (dblquote || arinest)
10539 *((char *)stackblock() + typeloc) = subtype | flags;
10540 if (subtype != VSNORMAL) {
10542 if (dblquote || arinest) {
10547 goto parsesub_return;
10552 * Called to parse command substitutions. Newstyle is set if the command
10553 * is enclosed inside $(...); nlpp is a pointer to the head of the linked
10554 * list of commands (passed by reference), and savelen is the number of
10555 * characters on the top of the stack which must be preserved.
10559 struct nodelist **nlpp;
10562 char *volatile str;
10563 struct jmploc jmploc;
10564 struct jmploc *volatile savehandler;
10568 (void) &saveprompt;
10571 savepbq = parsebackquote;
10572 if (setjmp(jmploc.loc)) {
10575 parsebackquote = 0;
10576 handler = savehandler;
10577 longjmp(handler->loc, 1);
10581 savelen = out - (char *)stackblock();
10583 str = ckmalloc(savelen);
10584 memcpy(str, stackblock(), savelen);
10586 savehandler = handler;
10590 /* We must read until the closing backquote, giving special
10591 treatment to some slashes, and then push the string and
10592 reread it as input, interpreting it normally. */
10599 STARTSTACKSTR(pout);
10604 switch (pc = pgetc()) {
10609 if ((pc = pgetc()) == '\n') {
10614 * If eating a newline, avoid putting
10615 * the newline into the new character
10616 * stream (via the STPUTC after the
10621 if (pc != '\\' && pc != '`' && pc != '$'
10622 && (!dblquote || pc != '"'))
10623 STPUTC('\\', pout);
10624 if (pc > PEOA_OR_PEOF) {
10630 #ifdef CONFIG_ASH_ALIAS
10633 startlinno = plinno;
10634 synerror("EOF in backquote substitution");
10638 needprompt = doprompt;
10647 STPUTC('\0', pout);
10648 psavelen = pout - (char *)stackblock();
10649 if (psavelen > 0) {
10650 pstr = grabstackstr(pout);
10651 setinputstring(pstr);
10656 nlpp = &(*nlpp)->next;
10657 *nlpp = (struct nodelist *)stalloc(sizeof (struct nodelist));
10658 (*nlpp)->next = NULL;
10659 parsebackquote = oldstyle;
10662 saveprompt = doprompt;
10669 doprompt = saveprompt;
10671 if (readtoken() != TRP)
10678 * Start reading from old file again, ignoring any pushed back
10679 * tokens left from the backquote parsing
10684 while (stackblocksize() <= savelen)
10686 STARTSTACKSTR(out);
10688 memcpy(out, str, savelen);
10689 STADJUST(savelen, out);
10695 parsebackquote = savepbq;
10696 handler = savehandler;
10697 if (arinest || dblquote)
10698 USTPUTC(CTLBACKQ | CTLQUOTE, out);
10700 USTPUTC(CTLBACKQ, out);
10702 goto parsebackq_oldreturn;
10704 goto parsebackq_newreturn;
10707 #ifdef CONFIG_ASH_MATH_SUPPORT
10709 * Parse an arithmetic expansion (indicate start of one and set state)
10713 if (++arinest == 1) {
10714 prevsyntax = syntax;
10715 syntax = ARISYNTAX;
10716 USTPUTC(CTLARI, out);
10723 * we collapse embedded arithmetic expansion to
10724 * parenthesis, which should be equivalent
10728 goto parsearith_return;
10732 } /* end of readtoken */
10737 * Returns true if the text contains nothing to expand (no dollar signs
10742 noexpand(char *text)
10748 while ((c = *p++) != '\0') {
10749 if (c == CTLQUOTEMARK)
10753 else if (SIT(c, BASESYNTAX) == CCTL)
10761 * Return of a legal variable name (a letter or underscore followed by zero or
10762 * more letters, underscores, and digits).
10766 endofname(const char *name)
10774 if (! is_in_name(*p))
10782 * Called when an unexpected token is read during the parse. The argument
10783 * is the token that is expected, or -1 if more than one type of token can
10784 * occur at this point.
10787 static void synexpect(int token)
10792 l = sprintf(msg, "%s unexpected", tokname(lasttoken));
10794 sprintf(msg + l, " (expecting %s)", tokname(token));
10800 synerror(const char *msg)
10802 sh_error("Syntax error: %s", msg);
10808 * called by editline -- any expansions to the prompt
10809 * should be added here.
10812 #ifdef CONFIG_ASH_EXPAND_PRMT
10813 static const char *
10814 expandstr(const char *ps)
10818 /* XXX Fix (char *) cast. */
10819 setinputstring((char *)ps);
10820 readtoken1(pgetc(), DQSYNTAX, nullstr, 0);
10823 n.narg.type = NARG;
10824 n.narg.next = NULL;
10825 n.narg.text = wordtext;
10826 n.narg.backquote = backquotelist;
10828 expandarg(&n, NULL, 0);
10829 return stackblock();
10833 static void setprompt(int whichprompt)
10835 const char *prompt;
10836 #ifdef CONFIG_ASH_EXPAND_PRMT
10837 struct stackmark smark;
10842 switch (whichprompt) {
10852 #ifdef CONFIG_ASH_EXPAND_PRMT
10853 setstackmark(&smark);
10854 stalloc(stackblocksize());
10856 putprompt(expandstr(prompt));
10857 #ifdef CONFIG_ASH_EXPAND_PRMT
10858 popstackmark(&smark);
10863 static const char *const *findkwd(const char *s)
10865 return bsearch(s, tokname_array + KWDOFFSET,
10866 (sizeof(tokname_array) / sizeof(const char *)) - KWDOFFSET,
10867 sizeof(const char *), pstrcmp);
10873 * Code for dealing with input/output redirection.
10876 #define EMPTY -2 /* marks an unused slot in redirtab */
10878 # define PIPESIZE 4096 /* amount of buffering in a pipe */
10880 # define PIPESIZE PIPE_BUF
10884 * Open a file in noclobber mode.
10885 * The code was copied from bash.
10888 noclobberopen(const char *fname)
10891 struct stat finfo, finfo2;
10894 * If the file exists and is a regular file, return an error
10897 r = stat(fname, &finfo);
10898 if (r == 0 && S_ISREG(finfo.st_mode)) {
10904 * If the file was not present (r != 0), make sure we open it
10905 * exclusively so that if it is created before we open it, our open
10906 * will fail. Make sure that we do not truncate an existing file.
10907 * Note that we don't turn on O_EXCL unless the stat failed -- if the
10908 * file was not a regular file, we leave O_EXCL off.
10911 return open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
10912 fd = open(fname, O_WRONLY|O_CREAT, 0666);
10914 /* If the open failed, return the file descriptor right away. */
10919 * OK, the open succeeded, but the file may have been changed from a
10920 * non-regular file to a regular file between the stat and the open.
10921 * We are assuming that the O_EXCL open handles the case where FILENAME
10922 * did not exist and is symlinked to an existing file between the stat
10927 * If we can open it and fstat the file descriptor, and neither check
10928 * revealed that it was a regular file, and the file has not been
10929 * replaced, return the file descriptor.
10931 if (fstat(fd, &finfo2) == 0 && !S_ISREG(finfo2.st_mode) &&
10932 finfo.st_dev == finfo2.st_dev && finfo.st_ino == finfo2.st_ino)
10935 /* The file has been replaced. badness. */
10942 * Handle here documents. Normally we fork off a process to write the
10943 * data to a pipe. If the document is short, we can stuff the data in
10944 * the pipe without forking.
10948 openhere(union node *redir)
10954 sh_error("Pipe call failed");
10955 if (redir->type == NHERE) {
10956 len = strlen(redir->nhere.doc->narg.text);
10957 if (len <= PIPESIZE) {
10958 bb_full_write(pip[1], redir->nhere.doc->narg.text, len);
10962 if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
10964 signal(SIGINT, SIG_IGN);
10965 signal(SIGQUIT, SIG_IGN);
10966 signal(SIGHUP, SIG_IGN);
10968 signal(SIGTSTP, SIG_IGN);
10970 signal(SIGPIPE, SIG_DFL);
10971 if (redir->type == NHERE)
10972 bb_full_write(pip[1], redir->nhere.doc->narg.text, len);
10974 expandhere(redir->nhere.doc, pip[1]);
10983 openredirect(union node *redir)
10988 switch (redir->nfile.type) {
10990 fname = redir->nfile.expfname;
10991 if ((f = open(fname, O_RDONLY)) < 0)
10995 fname = redir->nfile.expfname;
10996 if ((f = open(fname, O_RDWR|O_CREAT|O_TRUNC, 0666)) < 0)
11000 /* Take care of noclobber mode. */
11002 fname = redir->nfile.expfname;
11003 if ((f = noclobberopen(fname)) < 0)
11009 fname = redir->nfile.expfname;
11010 if ((f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0)
11014 fname = redir->nfile.expfname;
11015 if ((f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666)) < 0)
11022 /* Fall through to eliminate warning. */
11029 f = openhere(redir);
11035 sh_error("cannot create %s: %s", fname, errmsg(errno, E_CREAT));
11037 sh_error("cannot open %s: %s", fname, errmsg(errno, E_OPEN));
11041 dupredirect(union node *redir, int f)
11043 int fd = redir->nfile.fd;
11045 if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
11046 if (redir->ndup.dupfd >= 0) { /* if not ">&-" */
11047 copyfd(redir->ndup.dupfd, fd);
11060 * Process a list of redirection commands. If the REDIR_PUSH flag is set,
11061 * old file descriptors are stashed away so that the redirection can be
11062 * undone by calling popredir. If the REDIR_BACKQ flag is set, then the
11063 * standard output, and the standard error if it becomes a duplicate of
11064 * stdout, is saved in memory.
11068 redirect(union node *redir, int flags)
11071 struct redirtab *sv;
11082 if (flags & REDIR_PUSH) {
11083 struct redirtab *q;
11084 q = ckmalloc(sizeof (struct redirtab));
11085 q->next = redirlist;
11087 q->nullredirs = nullredirs - 1;
11088 for (i = 0 ; i < 10 ; i++)
11089 q->renamed[i] = EMPTY;
11096 if ((n->nfile.type == NTOFD || n->nfile.type == NFROMFD) &&
11097 n->ndup.dupfd == fd)
11098 continue; /* redirect from/to same file descriptor */
11100 newfd = openredirect(n);
11103 if (sv && *(p = &sv->renamed[fd]) == EMPTY) {
11104 i = fcntl(fd, F_DUPFD, 10);
11111 sh_error("%d: %m", fd);
11121 dupredirect(n, newfd);
11122 } while ((n = n->nfile.next));
11124 if (flags & REDIR_SAVEFD2 && sv && sv->renamed[2] >= 0)
11125 preverrout_fd = sv->renamed[2];
11130 * Undo the effects of the last redirection.
11136 struct redirtab *rp;
11139 if (--nullredirs >= 0)
11143 for (i = 0 ; i < 10 ; i++) {
11144 if (rp->renamed[i] != EMPTY) {
11147 copyfd(rp->renamed[i], i);
11149 close(rp->renamed[i]);
11152 redirlist = rp->next;
11153 nullredirs = rp->nullredirs;
11159 * Undo all redirections. Called on error or interrupt.
11163 * Discard all saved file descriptors.
11167 clearredir(int drop)
11179 * Copy a file descriptor to be >= to. Returns -1
11180 * if the source file descriptor is closed, EMPTY if there are no unused
11181 * file descriptors left.
11185 copyfd(int from, int to)
11189 newfd = fcntl(from, F_DUPFD, to);
11191 if (errno == EMFILE)
11194 sh_error("%d: %m", from);
11201 redirectsafe(union node *redir, int flags)
11204 volatile int saveint;
11205 struct jmploc *volatile savehandler = handler;
11206 struct jmploc jmploc;
11209 if (!(err = setjmp(jmploc.loc) * 2)) {
11211 redirect(redir, flags);
11213 handler = savehandler;
11214 if (err && exception != EXERROR)
11215 longjmp(handler->loc, 1);
11216 RESTOREINT(saveint);
11223 static void shtree(union node *, int, char *, FILE*);
11224 static void shcmd(union node *, FILE *);
11225 static void sharg(union node *, FILE *);
11226 static void indent(int, char *, FILE *);
11227 static void trstring(char *);
11231 showtree(union node *n)
11233 trputs("showtree called\n");
11234 shtree(n, 1, NULL, stdout);
11239 shtree(union node *n, int ind, char *pfx, FILE *fp)
11241 struct nodelist *lp;
11247 indent(ind, pfx, fp);
11258 shtree(n->nbinary.ch1, ind, NULL, fp);
11261 shtree(n->nbinary.ch2, ind, NULL, fp);
11269 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
11274 if (n->npipe.backgnd)
11280 fprintf(fp, "<node type %d>", n->type);
11289 shcmd(union node *cmd, FILE *fp)
11297 for (np = cmd->ncmd.args ; np ; np = np->narg.next) {
11303 for (np = cmd->ncmd.redirect ; np ; np = np->nfile.next) {
11306 switch (np->nfile.type) {
11307 case NTO: s = ">"; dftfd = 1; break;
11308 case NCLOBBER: s = ">|"; dftfd = 1; break;
11309 case NAPPEND: s = ">>"; dftfd = 1; break;
11310 case NTOFD: s = ">&"; dftfd = 1; break;
11311 case NFROM: s = "<"; dftfd = 0; break;
11312 case NFROMFD: s = "<&"; dftfd = 0; break;
11313 case NFROMTO: s = "<>"; dftfd = 0; break;
11314 default: s = "*error*"; dftfd = 0; break;
11316 if (np->nfile.fd != dftfd)
11317 fprintf(fp, "%d", np->nfile.fd);
11319 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
11320 fprintf(fp, "%d", np->ndup.dupfd);
11322 sharg(np->nfile.fname, fp);
11331 sharg(union node *arg, FILE *fp)
11334 struct nodelist *bqlist;
11337 if (arg->type != NARG) {
11338 out1fmt("<node type %d>\n", arg->type);
11341 bqlist = arg->narg.backquote;
11342 for (p = arg->narg.text ; *p ; p++) {
11351 if (subtype == VSLENGTH)
11357 if (subtype & VSNUL)
11360 switch (subtype & VSTYPE) {
11379 case VSTRIMLEFTMAX:
11386 case VSTRIMRIGHTMAX:
11393 out1fmt("<subtype %d>", subtype);
11400 case CTLBACKQ|CTLQUOTE:
11403 shtree(bqlist->n, -1, NULL, fp);
11415 indent(int amount, char *pfx, FILE *fp)
11419 for (i = 0 ; i < amount ; i++) {
11420 if (pfx && i == amount - 1)
11441 putc(c, tracefile);
11445 trace(const char *fmt, ...)
11452 (void) vfprintf(tracefile, fmt, va);
11457 tracev(const char *fmt, va_list va)
11461 (void) vfprintf(tracefile, fmt, va);
11466 trputs(const char *s)
11470 fputs(s, tracefile);
11482 putc('"', tracefile);
11483 for (p = s ; *p ; p++) {
11485 case '\n': c = 'n'; goto backslash;
11486 case '\t': c = 't'; goto backslash;
11487 case '\r': c = 'r'; goto backslash;
11488 case '"': c = '"'; goto backslash;
11489 case '\\': c = '\\'; goto backslash;
11490 case CTLESC: c = 'e'; goto backslash;
11491 case CTLVAR: c = 'v'; goto backslash;
11492 case CTLVAR+CTLQUOTE: c = 'V'; goto backslash;
11493 case CTLBACKQ: c = 'q'; goto backslash;
11494 case CTLBACKQ+CTLQUOTE: c = 'Q'; goto backslash;
11495 backslash: putc('\\', tracefile);
11496 putc(c, tracefile);
11499 if (*p >= ' ' && *p <= '~')
11500 putc(*p, tracefile);
11502 putc('\\', tracefile);
11503 putc(*p >> 6 & 03, tracefile);
11504 putc(*p >> 3 & 07, tracefile);
11505 putc(*p & 07, tracefile);
11510 putc('"', tracefile);
11522 putc(' ', tracefile);
11524 putc('\n', tracefile);
11540 /* leave open because libedit might be using it */
11543 scopy("./trace", s);
11545 if (!freopen(s, "a", tracefile)) {
11546 fprintf(stderr, "Can't re-open %s\n", s);
11551 if ((tracefile = fopen(s, "a")) == NULL) {
11552 fprintf(stderr, "Can't open %s\n", s);
11558 if ((flags = fcntl(fileno(tracefile), F_GETFL, 0)) >= 0)
11559 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
11561 setlinebuf(tracefile);
11562 fputs("\nTracing started.\n", tracefile);
11570 * Sigmode records the current value of the signal handlers for the various
11571 * modes. A value of zero means that the current handler is not known.
11572 * S_HARD_IGN indicates that the signal was ignored on entry to the shell,
11575 #define S_DFL 1 /* default signal handling (SIG_DFL) */
11576 #define S_CATCH 2 /* signal is caught */
11577 #define S_IGN 3 /* signal is ignored (SIG_IGN) */
11578 #define S_HARD_IGN 4 /* signal is ignored permenantly */
11579 #define S_RESET 5 /* temporary - to reset a hard ignored sig */
11584 * The trap builtin.
11588 trapcmd(int argc, char **argv)
11597 for (signo = 0 ; signo < NSIG ; signo++) {
11598 if (trap[signo] != NULL) {
11601 sn = u_signal_names(0, &signo, 0);
11604 out1fmt("trap -- %s %s\n",
11605 single_quote(trap[signo]), sn);
11615 if ((signo = decode_signal(*ap, 0)) < 0)
11616 sh_error("%s: bad trap", *ap);
11619 if (action[0] == '-' && action[1] == '\0')
11622 action = savestr(action);
11625 ckfree(trap[signo]);
11626 trap[signo] = action;
11637 * Clear traps on a fork.
11645 for (tp = trap ; tp < &trap[NSIG] ; tp++) {
11646 if (*tp && **tp) { /* trap not NULL or SIG_IGN */
11650 if (tp != &trap[0])
11651 setsignal(tp - trap);
11659 * Set the signal handler for the specified signal. The routine figures
11660 * out what it should be set to.
11664 setsignal(int signo)
11668 struct sigaction act;
11670 if ((t = trap[signo]) == NULL)
11672 else if (*t != '\0')
11676 if (rootshell && action == S_DFL) {
11679 if (iflag || minusc || sflag == 0)
11702 t = &sigmode[signo - 1];
11706 * current setting unknown
11708 if (sigaction(signo, 0, &act) == -1) {
11710 * Pretend it worked; maybe we should give a warning
11711 * here, but other shells don't. We don't alter
11712 * sigmode, so that we retry every time.
11716 if (act.sa_handler == SIG_IGN) {
11717 if (mflag && (signo == SIGTSTP ||
11718 signo == SIGTTIN || signo == SIGTTOU)) {
11719 tsig = S_IGN; /* don't hard ignore these */
11723 tsig = S_RESET; /* force to be set */
11726 if (tsig == S_HARD_IGN || tsig == action)
11730 act.sa_handler = onsig;
11733 act.sa_handler = SIG_IGN;
11736 act.sa_handler = SIG_DFL;
11740 sigfillset(&act.sa_mask);
11741 sigaction(signo, &act, 0);
11749 ignoresig(int signo)
11751 if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
11752 signal(signo, SIG_IGN);
11754 sigmode[signo - 1] = S_HARD_IGN;
11765 gotsig[signo - 1] = 1;
11766 pendingsigs = signo;
11768 if (exsig || (signo == SIGINT && !trap[SIGINT])) {
11777 * Called to execute a trap. Perhaps we should avoid entering new trap
11778 * handlers while we are executing a trap handler.
11790 savestatus = exitstatus;
11794 for (i = 0, q = gotsig; i < NSIG - 1; i++, q++) {
11802 skip = evalstring(p, SKIPEVAL);
11803 exitstatus = savestatus;
11813 * Controls whether the shell is interactive or not.
11817 setinteractive(int on)
11819 static int is_interactive;
11821 if (++on == is_interactive)
11823 is_interactive = on;
11825 setsignal(SIGQUIT);
11826 setsignal(SIGTERM);
11827 #ifndef CONFIG_FEATURE_SH_EXTRA_QUIET
11828 if(is_interactive > 1) {
11829 /* Looks like they want an interactive shell */
11830 static int do_banner;
11834 "\n\n" BB_BANNER " Built-in shell (ash)\n"
11835 "Enter 'help' for a list of built-in commands.\n\n");
11843 #ifndef CONFIG_FEATURE_SH_EXTRA_QUIET
11844 /*** List the available builtins ***/
11846 static int helpcmd(int argc, char **argv)
11850 out1fmt("\nBuilt-in commands:\n-------------------\n");
11851 for (col = 0, i = 0; i < NUMBUILTINS; i++) {
11852 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
11853 builtincmd[i].name + 1);
11859 #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
11861 extern const struct BB_applet applets[];
11862 extern const size_t NUM_APPLETS;
11864 for (i = 0; i < NUM_APPLETS; i++) {
11866 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), applets[i].name);
11875 return EXIT_SUCCESS;
11877 #endif /* CONFIG_FEATURE_SH_EXTRA_QUIET */
11880 * Called to exit the shell.
11890 status = exitstatus;
11891 TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
11892 if (setjmp(loc.loc)) {
11893 if (exception == EXEXIT)
11898 if ((p = trap[0])) {
11904 #ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
11905 if (iflag && rootshell) {
11906 const char *hp = lookupvar("HISTFILE");
11909 save_history ( hp );
11917 static int decode_signal(const char *string, int minsig)
11920 const char *name = u_signal_names(string, &signo, minsig);
11922 return name ? signo : -1;
11927 static struct var *vartab[VTABSIZE];
11929 static int vpcmp(const void *, const void *);
11930 static struct var **findvar(struct var **, const char *);
11933 * Initialize the variable symbol tables and import the environment
11937 #ifdef CONFIG_ASH_GETOPTS
11939 * Safe version of setvar, returns 1 on success 0 on failure.
11943 setvarsafe(const char *name, const char *val, int flags)
11946 volatile int saveint;
11947 struct jmploc *volatile savehandler = handler;
11948 struct jmploc jmploc;
11951 if (setjmp(jmploc.loc))
11955 setvar(name, val, flags);
11958 handler = savehandler;
11959 RESTOREINT(saveint);
11965 * Set the value of a variable. The flags argument is ored with the
11966 * flags of the variable. If val is NULL, the variable is unset.
11970 setvar(const char *name, const char *val, int flags)
11977 q = endofname(name);
11978 p = strchrnul(q, '=');
11979 namelen = p - name;
11980 if (!namelen || p != q)
11981 sh_error("%.*s: bad variable name", namelen, name);
11986 vallen = strlen(val);
11989 p = mempcpy(nameeq = ckmalloc(namelen + vallen + 2), name, namelen);
11992 p = mempcpy(p, val, vallen);
11995 setvareq(nameeq, flags | VNOSAVE);
12001 * Same as setvar except that the variable and value are passed in
12002 * the first argument as name=value. Since the first argument will
12003 * be actually stored in the table, it should not be a string that
12005 * Called with interrupts off.
12009 setvareq(char *s, int flags)
12011 struct var *vp, **vpp;
12014 flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
12015 vp = *findvar(vpp, s);
12017 if ((vp->flags & (VREADONLY|VDYNAMIC)) == VREADONLY) {
12020 if (flags & VNOSAVE)
12023 sh_error("%.*s: is read only", strchrnul(n, '=') - n, n);
12026 if (flags & VNOSET)
12029 if (vp->func && (flags & VNOFUNC) == 0)
12030 (*vp->func)(strchrnul(s, '=') + 1);
12032 if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
12035 flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET);
12037 if (flags & VNOSET)
12040 vp = ckmalloc(sizeof (*vp));
12045 if (!(flags & (VTEXTFIXED|VSTACK|VNOSAVE)))
12053 * Process a linked list of variable assignments.
12057 listsetvar(struct strlist *list_set_var, int flags)
12059 struct strlist *lp = list_set_var;
12065 setvareq(lp->text, flags);
12066 } while ((lp = lp->next));
12072 * Find the value of a variable. Returns NULL if not set.
12076 lookupvar(const char *name)
12080 if ((v = *findvar(hashvar(name), name))) {
12083 * Dynamic variables are implemented roughly the same way they are
12084 * in bash. Namely, they're "special" so long as they aren't unset.
12085 * As soon as they're unset, they're no longer dynamic, and dynamic
12086 * lookup will no longer happen at that point. -- PFM.
12088 if((v->flags & VDYNAMIC))
12091 if(!(v->flags & VUNSET))
12092 return strchrnul(v->text, '=') + 1;
12100 * Search the environment of a builtin command.
12104 bltinlookup(const char *name)
12106 struct strlist *sp;
12108 for (sp = cmdenviron ; sp ; sp = sp->next) {
12109 if (varequal(sp->text, name))
12110 return strchrnul(sp->text, '=') + 1;
12112 return lookupvar(name);
12117 * Generate a list of variables satisfying the given conditions.
12121 listvars(int on, int off, char ***end)
12132 for (vp = *vpp ; vp ; vp = vp->next)
12133 if ((vp->flags & mask) == on) {
12134 if (ep == stackstrend())
12135 ep = growstackstr();
12136 *ep++ = (char *) vp->text;
12138 } while (++vpp < vartab + VTABSIZE);
12139 if (ep == stackstrend())
12140 ep = growstackstr();
12144 return grabstackstr(ep);
12149 * POSIX requires that 'set' (but not export or readonly) output the
12150 * variables in lexicographic order - by the locale's collating order (sigh).
12151 * Maybe we could keep them in an ordered balanced binary tree
12152 * instead of hashed lists.
12153 * For now just roll 'em through qsort for printing...
12157 showvars(const char *sep_prefix, int on, int off)
12160 char **ep, **epend;
12162 ep = listvars(on, off, &epend);
12163 qsort(ep, epend - ep, sizeof(char *), vpcmp);
12165 sep = *sep_prefix ? spcstr : sep_prefix;
12167 for (; ep < epend; ep++) {
12171 p = strchrnul(*ep, '=');
12174 q = single_quote(++p);
12176 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
12185 * The export and readonly commands.
12189 exportcmd(int argc, char **argv)
12195 int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT;
12198 notp = nextopt("p") - 'p';
12199 if (notp && ((name = *(aptr = argptr)))) {
12201 if ((p = strchr(name, '=')) != NULL) {
12204 if ((vp = *findvar(hashvar(name), name))) {
12209 setvar(name, p, flag);
12210 } while ((name = *++aptr) != NULL);
12212 showvars(argv[0], flag, 0);
12219 * Make a variable a local variable. When a variable is made local, it's
12220 * value and flags are saved in a localvar structure. The saved values
12221 * will be restored when the shell function returns. We handle the name
12222 * "-" as a special case.
12226 mklocal(char *name)
12228 struct localvar *lvp;
12233 lvp = ckmalloc(sizeof (struct localvar));
12234 if (name[0] == '-' && name[1] == '\0') {
12236 p = ckmalloc(sizeof(optlist));
12237 lvp->text = memcpy(p, optlist, sizeof(optlist));
12242 vpp = hashvar(name);
12243 vp = *findvar(vpp, name);
12244 eq = strchr(name, '=');
12247 setvareq(name, VSTRFIXED);
12249 setvar(name, NULL, VSTRFIXED);
12250 vp = *vpp; /* the new variable */
12251 lvp->flags = VUNSET;
12253 lvp->text = vp->text;
12254 lvp->flags = vp->flags;
12255 vp->flags |= VSTRFIXED|VTEXTFIXED;
12261 lvp->next = localvars;
12267 * The "local" command.
12271 localcmd(int argc, char **argv)
12276 while ((name = *argv++) != NULL) {
12284 * Called after a function returns.
12285 * Interrupts must be off.
12291 struct localvar *lvp;
12294 while ((lvp = localvars) != NULL) {
12295 localvars = lvp->next;
12297 TRACE(("poplocalvar %s", vp ? vp->text : "-"));
12298 if (vp == NULL) { /* $- saved */
12299 memcpy(optlist, lvp->text, sizeof(optlist));
12302 } else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
12303 unsetvar(vp->text);
12306 (*vp->func)(strchrnul(lvp->text, '=') + 1);
12307 if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
12309 vp->flags = lvp->flags;
12310 vp->text = lvp->text;
12318 * The unset builtin command. We unset the function before we unset the
12319 * variable to allow a function to be unset when there is a readonly variable
12320 * with the same name.
12324 unsetcmd(int argc, char **argv)
12331 while ((i = nextopt("vf")) != '\0') {
12335 for (ap = argptr; *ap ; ap++) {
12350 * Unset the specified variable.
12354 unsetvar(const char *s)
12360 vpp = findvar(hashvar(s), s);
12364 int flags = vp->flags;
12367 if (flags & VREADONLY)
12370 vp->flags &= ~VDYNAMIC;
12372 if (flags & VUNSET)
12374 if ((flags & VSTRFIXED) == 0) {
12376 if ((flags & (VTEXTFIXED|VSTACK)) == 0)
12383 vp->flags &= ~VEXPORT;
12396 * Find the appropriate entry in the hash table from the name.
12399 static struct var **
12400 hashvar(const char *p)
12402 unsigned int hashval;
12404 hashval = ((unsigned char) *p) << 4;
12405 while (*p && *p != '=')
12406 hashval += (unsigned char) *p++;
12407 return &vartab[hashval % VTABSIZE];
12413 * Compares two strings up to the first = or '\0'. The first
12414 * string must be terminated by '='; the second may be terminated by
12415 * either '=' or '\0'.
12419 varcmp(const char *p, const char *q)
12423 while ((c = *p) == (d = *q)) {
12424 if (!c || c == '=')
12438 vpcmp(const void *a, const void *b)
12440 return varcmp(*(const char **)a, *(const char **)b);
12443 static struct var **
12444 findvar(struct var **vpp, const char *name)
12446 for (; *vpp; vpp = &(*vpp)->next) {
12447 if (varequal((*vpp)->text, name)) {
12455 #include <sys/times.h>
12457 static const unsigned char timescmd_str[] = {
12458 ' ', offsetof(struct tms, tms_utime),
12459 '\n', offsetof(struct tms, tms_stime),
12460 ' ', offsetof(struct tms, tms_cutime),
12461 '\n', offsetof(struct tms, tms_cstime),
12465 static int timescmd(int ac, char **av)
12467 long int clk_tck, s, t;
12468 const unsigned char *p;
12471 clk_tck = sysconf(_SC_CLK_TCK);
12476 t = *(clock_t *)(((char *) &buf) + p[1]);
12478 out1fmt("%ldm%ld.%.3lds%c",
12480 ((t - s * clk_tck) * 1000) / clk_tck,
12482 } while (*(p += 2));
12487 #ifdef CONFIG_ASH_MATH_SUPPORT
12489 dash_arith(const char *s)
12495 result = arith(s, &errcode);
12498 sh_error("exponent less than 0");
12499 else if (errcode == -2)
12500 sh_error("divide by zero");
12501 else if (errcode == -5)
12502 sh_error("expression recursion loop detected");
12513 * The let builtin. partial stolen from GNU Bash, the Bourne Again SHell.
12514 * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
12516 * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
12520 letcmd(int argc, char **argv)
12527 sh_error("expression expected");
12528 for (ap = argv + 1; *ap; ap++) {
12529 i = dash_arith(*ap);
12534 #endif /* CONFIG_ASH_MATH_SUPPORT */
12539 * Miscellaneous builtins.
12545 #if __GLIBC__ == 2 && __GLIBC_MINOR__ < 1
12546 typedef enum __rlimit_resource rlim_t;
12552 * The read builtin. The -e option causes backslashes to escape the
12553 * following character.
12555 * This uses unbuffered input, which may be avoidable in some cases.
12559 readcmd(int argc, char **argv)
12571 #if defined(CONFIG_ASH_READ_NCHARS)
12575 struct termios tty, old_tty;
12577 #if defined(CONFIG_ASH_READ_TIMEOUT)
12581 ts.tv_sec = ts.tv_usec = 0;
12586 #if defined(CONFIG_ASH_READ_NCHARS) && defined(CONFIG_ASH_READ_TIMEOUT)
12587 while ((i = nextopt("p:rt:n:s")) != '\0')
12588 #elif defined(CONFIG_ASH_READ_NCHARS)
12589 while ((i = nextopt("p:rn:s")) != '\0')
12590 #elif defined(CONFIG_ASH_READ_TIMEOUT)
12591 while ((i = nextopt("p:rt:")) != '\0')
12593 while ((i = nextopt("p:r")) != '\0')
12598 prompt = optionarg;
12600 #if defined(CONFIG_ASH_READ_NCHARS)
12602 nchars = strtol(optionarg, &p, 10);
12604 sh_error("invalid count");
12605 nch_flag = (nchars > 0);
12611 #if defined(CONFIG_ASH_READ_TIMEOUT)
12613 ts.tv_sec = strtol(optionarg, &p, 10);
12619 ts.tv_usec = strtol(p, &p2, 10);
12621 sh_error("invalid timeout");
12623 /* normalize to usec */
12625 sh_error("invalid timeout");
12626 while (scale++ < 6)
12630 sh_error("invalid timeout");
12632 if ( ! ts.tv_sec && ! ts.tv_usec)
12633 sh_error("invalid timeout");
12643 if (prompt && isatty(0)) {
12646 if (*(ap = argptr) == NULL)
12647 sh_error("arg count");
12648 if ((ifs = bltinlookup("IFS")) == NULL)
12650 #if defined(CONFIG_ASH_READ_NCHARS)
12651 if (nch_flag || silent) {
12652 tcgetattr(0, &tty);
12655 tty.c_lflag &= ~ICANON;
12656 tty.c_cc[VMIN] = nchars;
12659 tty.c_lflag &= ~(ECHO|ECHOK|ECHONL);
12662 tcsetattr(0, TCSANOW, &tty);
12665 #if defined(CONFIG_ASH_READ_TIMEOUT)
12666 if (ts.tv_sec || ts.tv_usec) {
12670 i = select (FD_SETSIZE, &set, NULL, NULL, &ts);
12672 #if defined(CONFIG_ASH_READ_NCHARS)
12674 tcsetattr(0, TCSANOW, &old_tty);
12684 #if defined(CONFIG_ASH_READ_NCHARS)
12685 while (!nch_flag || nchars--)
12690 if (read(0, &c, 1) != 1) {
12702 if (!rflag && c == '\\') {
12708 if (startword && *ifs == ' ' && strchr(ifs, c)) {
12712 if (ap[1] != NULL && strchr(ifs, c) != NULL) {
12714 setvar(*ap, stackblock(), 0);
12723 #if defined(CONFIG_ASH_READ_NCHARS)
12724 if (nch_flag || silent)
12725 tcsetattr(0, TCSANOW, &old_tty);
12729 /* Remove trailing blanks */
12730 while ((char *)stackblock() <= --p && strchr(ifs, *p) != NULL)
12732 setvar(*ap, stackblock(), 0);
12733 while (*++ap != NULL)
12734 setvar(*ap, nullstr, 0);
12739 static int umaskcmd(int argc, char **argv)
12741 static const char permuser[3] = "ugo";
12742 static const char permmode[3] = "rwx";
12743 static const short int permmask[] = {
12744 S_IRUSR, S_IWUSR, S_IXUSR,
12745 S_IRGRP, S_IWGRP, S_IXGRP,
12746 S_IROTH, S_IWOTH, S_IXOTH
12752 int symbolic_mode = 0;
12754 while (nextopt("S") != '\0') {
12763 if ((ap = *argptr) == NULL) {
12764 if (symbolic_mode) {
12768 for (i = 0; i < 3; i++) {
12771 *p++ = permuser[i];
12773 for (j = 0; j < 3; j++) {
12774 if ((mask & permmask[3 * i + j]) == 0) {
12775 *p++ = permmode[j];
12783 out1fmt("%.4o\n", mask);
12786 if (is_digit((unsigned char) *ap)) {
12789 if (*ap >= '8' || *ap < '0')
12790 sh_error(illnum, argv[1]);
12791 mask = (mask << 3) + (*ap - '0');
12792 } while (*++ap != '\0');
12795 mask = ~mask & 0777;
12796 if (!bb_parse_mode(ap, &mask)) {
12797 sh_error("Illegal mode: %s", ap);
12799 umask(~mask & 0777);
12808 * This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and
12809 * Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with
12810 * ash by J.T. Conklin.
12818 int factor; /* multiply by to get rlim_{cur,max} values */
12822 static const struct limits limits[] = {
12824 { "time(seconds)", RLIMIT_CPU, 1, 't' },
12826 #ifdef RLIMIT_FSIZE
12827 { "file(blocks)", RLIMIT_FSIZE, 512, 'f' },
12830 { "data(kbytes)", RLIMIT_DATA, 1024, 'd' },
12832 #ifdef RLIMIT_STACK
12833 { "stack(kbytes)", RLIMIT_STACK, 1024, 's' },
12836 { "coredump(blocks)", RLIMIT_CORE, 512, 'c' },
12839 { "memory(kbytes)", RLIMIT_RSS, 1024, 'm' },
12841 #ifdef RLIMIT_MEMLOCK
12842 { "locked memory(kbytes)", RLIMIT_MEMLOCK, 1024, 'l' },
12844 #ifdef RLIMIT_NPROC
12845 { "process", RLIMIT_NPROC, 1, 'p' },
12847 #ifdef RLIMIT_NOFILE
12848 { "nofiles", RLIMIT_NOFILE, 1, 'n' },
12851 { "vmemory(kbytes)", RLIMIT_AS, 1024, 'v' },
12853 #ifdef RLIMIT_LOCKS
12854 { "locks", RLIMIT_LOCKS, 1, 'w' },
12856 { (char *) 0, 0, 0, '\0' }
12859 enum limtype { SOFT = 0x1, HARD = 0x2 };
12861 static void printlim(enum limtype how, const struct rlimit *limit,
12862 const struct limits *l)
12866 val = limit->rlim_max;
12868 val = limit->rlim_cur;
12870 if (val == RLIM_INFINITY)
12871 out1fmt("unlimited\n");
12874 out1fmt("%lld\n", (long long) val);
12879 ulimitcmd(int argc, char **argv)
12883 enum limtype how = SOFT | HARD;
12884 const struct limits *l;
12887 struct rlimit limit;
12890 while ((optc = nextopt("HSa"
12894 #ifdef RLIMIT_FSIZE
12900 #ifdef RLIMIT_STACK
12909 #ifdef RLIMIT_MEMLOCK
12912 #ifdef RLIMIT_NPROC
12915 #ifdef RLIMIT_NOFILE
12921 #ifdef RLIMIT_LOCKS
12939 for (l = limits; l->option != what; l++)
12942 set = *argptr ? 1 : 0;
12946 if (all || argptr[1])
12947 sh_error("too many arguments");
12948 if (strncmp(p, "unlimited\n", 9) == 0)
12949 val = RLIM_INFINITY;
12953 while ((c = *p++) >= '0' && c <= '9')
12955 val = (val * 10) + (long)(c - '0');
12956 if (val < (rlim_t) 0)
12960 sh_error("bad number");
12965 for (l = limits; l->name; l++) {
12966 getrlimit(l->cmd, &limit);
12967 out1fmt("%-20s ", l->name);
12968 printlim(how, &limit, l);
12973 getrlimit(l->cmd, &limit);
12976 limit.rlim_max = val;
12978 limit.rlim_cur = val;
12979 if (setrlimit(l->cmd, &limit) < 0)
12980 sh_error("error setting limit (%m)");
12982 printlim(how, &limit, l);
12988 #ifdef CONFIG_ASH_MATH_SUPPORT
12990 /* Copyright (c) 2001 Aaron Lehmann <aaronl@vitelus.com>
12992 Permission is hereby granted, free of charge, to any person obtaining
12993 a copy of this software and associated documentation files (the
12994 "Software"), to deal in the Software without restriction, including
12995 without limitation the rights to use, copy, modify, merge, publish,
12996 distribute, sublicense, and/or sell copies of the Software, and to
12997 permit persons to whom the Software is furnished to do so, subject to
12998 the following conditions:
13000 The above copyright notice and this permission notice shall be
13001 included in all copies or substantial portions of the Software.
13003 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13004 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
13005 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
13006 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
13007 CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
13008 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
13009 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
13012 /* This is my infix parser/evaluator. It is optimized for size, intended
13013 * as a replacement for yacc-based parsers. However, it may well be faster
13014 * than a comparable parser written in yacc. The supported operators are
13015 * listed in #defines below. Parens, order of operations, and error handling
13016 * are supported. This code is thread safe. The exact expression format should
13017 * be that which POSIX specifies for shells. */
13019 /* The code uses a simple two-stack algorithm. See
13020 * http://www.onthenet.com.au/~grahamis/int2008/week02/lect02.html
13021 * for a detailed explanation of the infix-to-postfix algorithm on which
13022 * this is based (this code differs in that it applies operators immediately
13023 * to the stack instead of adding them to a queue to end up with an
13026 /* To use the routine, call it with an expression string and error return
13030 * Aug 24, 2001 Manuel Novoa III
13032 * Reduced the generated code size by about 30% (i386) and fixed several bugs.
13034 * 1) In arith_apply():
13035 * a) Cached values of *numptr and &(numptr[-1]).
13036 * b) Removed redundant test for zero denominator.
13039 * a) Eliminated redundant code for processing operator tokens by moving
13040 * to a table-based implementation. Also folded handling of parens
13042 * b) Combined all 3 loops which called arith_apply to reduce generated
13043 * code size at the cost of speed.
13045 * 3) The following expressions were treated as valid by the original code:
13046 * 1() , 0! , 1 ( *3 ) .
13047 * These bugs have been fixed by internally enclosing the expression in
13048 * parens and then checking that all binary ops and right parens are
13049 * preceded by a valid expression (NUM_TOKEN).
13051 * Note: It may be desirable to replace Aaron's test for whitespace with
13052 * ctype's isspace() if it is used by another busybox applet or if additional
13053 * whitespace chars should be considered. Look below the "#include"s for a
13054 * precompiler test.
13058 * Aug 26, 2001 Manuel Novoa III
13060 * Return 0 for null expressions. Pointed out by Vladimir Oleynik.
13062 * Merge in Aaron's comments previously posted to the busybox list,
13063 * modified slightly to take account of my changes to the code.
13068 * (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
13070 * - allow access to variable,
13071 * used recursive find value indirection (c=2*2; a="c"; $((a+=2)) produce 6)
13072 * - realize assign syntax (VAR=expr, +=, *= etc)
13073 * - realize exponentiation (** operator)
13074 * - realize comma separated - expr, expr
13075 * - realise ++expr --expr expr++ expr--
13076 * - realise expr ? expr : expr (but, second expr calculate always)
13077 * - allow hexadecimal and octal numbers
13078 * - was restored loses XOR operator
13079 * - remove one goto label, added three ;-)
13080 * - protect $((num num)) as true zero expr (Manuel`s error)
13081 * - always use special isspace(), see comment from bash ;-)
13085 #define arith_isspace(arithval) \
13086 (arithval == ' ' || arithval == '\n' || arithval == '\t')
13089 typedef unsigned char operator;
13091 /* An operator's token id is a bit of a bitfield. The lower 5 bits are the
13092 * precedence, and 3 high bits are an ID unique across operators of that
13093 * precedence. The ID portion is so that multiple operators can have the
13094 * same precedence, ensuring that the leftmost one is evaluated first.
13095 * Consider * and /. */
13097 #define tok_decl(prec,id) (((id)<<5)|(prec))
13098 #define PREC(op) ((op) & 0x1F)
13100 #define TOK_LPAREN tok_decl(0,0)
13102 #define TOK_COMMA tok_decl(1,0)
13104 #define TOK_ASSIGN tok_decl(2,0)
13105 #define TOK_AND_ASSIGN tok_decl(2,1)
13106 #define TOK_OR_ASSIGN tok_decl(2,2)
13107 #define TOK_XOR_ASSIGN tok_decl(2,3)
13108 #define TOK_PLUS_ASSIGN tok_decl(2,4)
13109 #define TOK_MINUS_ASSIGN tok_decl(2,5)
13110 #define TOK_LSHIFT_ASSIGN tok_decl(2,6)
13111 #define TOK_RSHIFT_ASSIGN tok_decl(2,7)
13113 #define TOK_MUL_ASSIGN tok_decl(3,0)
13114 #define TOK_DIV_ASSIGN tok_decl(3,1)
13115 #define TOK_REM_ASSIGN tok_decl(3,2)
13117 /* all assign is right associativity and precedence eq, but (7+3)<<5 > 256 */
13118 #define convert_prec_is_assing(prec) do { if(prec == 3) prec = 2; } while(0)
13120 /* conditional is right associativity too */
13121 #define TOK_CONDITIONAL tok_decl(4,0)
13122 #define TOK_CONDITIONAL_SEP tok_decl(4,1)
13124 #define TOK_OR tok_decl(5,0)
13126 #define TOK_AND tok_decl(6,0)
13128 #define TOK_BOR tok_decl(7,0)
13130 #define TOK_BXOR tok_decl(8,0)
13132 #define TOK_BAND tok_decl(9,0)
13134 #define TOK_EQ tok_decl(10,0)
13135 #define TOK_NE tok_decl(10,1)
13137 #define TOK_LT tok_decl(11,0)
13138 #define TOK_GT tok_decl(11,1)
13139 #define TOK_GE tok_decl(11,2)
13140 #define TOK_LE tok_decl(11,3)
13142 #define TOK_LSHIFT tok_decl(12,0)
13143 #define TOK_RSHIFT tok_decl(12,1)
13145 #define TOK_ADD tok_decl(13,0)
13146 #define TOK_SUB tok_decl(13,1)
13148 #define TOK_MUL tok_decl(14,0)
13149 #define TOK_DIV tok_decl(14,1)
13150 #define TOK_REM tok_decl(14,2)
13152 /* exponent is right associativity */
13153 #define TOK_EXPONENT tok_decl(15,1)
13155 /* For now unary operators. */
13156 #define UNARYPREC 16
13157 #define TOK_BNOT tok_decl(UNARYPREC,0)
13158 #define TOK_NOT tok_decl(UNARYPREC,1)
13160 #define TOK_UMINUS tok_decl(UNARYPREC+1,0)
13161 #define TOK_UPLUS tok_decl(UNARYPREC+1,1)
13163 #define PREC_PRE (UNARYPREC+2)
13165 #define TOK_PRE_INC tok_decl(PREC_PRE, 0)
13166 #define TOK_PRE_DEC tok_decl(PREC_PRE, 1)
13168 #define PREC_POST (UNARYPREC+3)
13170 #define TOK_POST_INC tok_decl(PREC_POST, 0)
13171 #define TOK_POST_DEC tok_decl(PREC_POST, 1)
13173 #define SPEC_PREC (UNARYPREC+4)
13175 #define TOK_NUM tok_decl(SPEC_PREC, 0)
13176 #define TOK_RPAREN tok_decl(SPEC_PREC, 1)
13178 #define NUMPTR (*numstackptr)
13180 static inline int tok_have_assign(operator op)
13182 operator prec = PREC(op);
13184 convert_prec_is_assing(prec);
13185 return (prec == PREC(TOK_ASSIGN) ||
13186 prec == PREC_PRE || prec == PREC_POST);
13189 static inline int is_right_associativity(operator prec)
13191 return (prec == PREC(TOK_ASSIGN) || prec == PREC(TOK_EXPONENT) ||
13192 prec == PREC(TOK_CONDITIONAL));
13196 typedef struct ARITCH_VAR_NUM {
13198 arith_t contidional_second_val;
13199 char contidional_second_val_initialized;
13200 char *var; /* if NULL then is regular number,
13201 else is variable name */
13205 typedef struct CHK_VAR_RECURSIVE_LOOPED {
13207 struct CHK_VAR_RECURSIVE_LOOPED *next;
13208 } chk_var_recursive_looped_t;
13210 static chk_var_recursive_looped_t *prev_chk_var_recursive;
13213 static int arith_lookup_val(v_n_t *t)
13216 const char * p = lookupvar(t->var);
13221 /* recursive try as expression */
13222 chk_var_recursive_looped_t *cur;
13223 chk_var_recursive_looped_t cur_save;
13225 for(cur = prev_chk_var_recursive; cur; cur = cur->next) {
13226 if(strcmp(cur->var, t->var) == 0) {
13227 /* expression recursion loop detected */
13231 /* save current lookuped var name */
13232 cur = prev_chk_var_recursive;
13233 cur_save.var = t->var;
13234 cur_save.next = cur;
13235 prev_chk_var_recursive = &cur_save;
13237 t->val = arith (p, &errcode);
13238 /* restore previous ptr after recursiving */
13239 prev_chk_var_recursive = cur;
13242 /* allow undefined var as 0 */
13249 /* "applying" a token means performing it on the top elements on the integer
13250 * stack. For a unary operator it will only change the top element, but a
13251 * binary operator will pop two arguments and push a result */
13253 arith_apply(operator op, v_n_t *numstack, v_n_t **numstackptr)
13256 arith_t numptr_val, rez;
13257 int ret_arith_lookup_val;
13259 if (NUMPTR == numstack) goto err; /* There is no operator that can work
13260 without arguments */
13261 numptr_m1 = NUMPTR - 1;
13263 /* check operand is var with noninteger value */
13264 ret_arith_lookup_val = arith_lookup_val(numptr_m1);
13265 if(ret_arith_lookup_val)
13266 return ret_arith_lookup_val;
13268 rez = numptr_m1->val;
13269 if (op == TOK_UMINUS)
13271 else if (op == TOK_NOT)
13273 else if (op == TOK_BNOT)
13275 else if (op == TOK_POST_INC || op == TOK_PRE_INC)
13277 else if (op == TOK_POST_DEC || op == TOK_PRE_DEC)
13279 else if (op != TOK_UPLUS) {
13280 /* Binary operators */
13282 /* check and binary operators need two arguments */
13283 if (numptr_m1 == numstack) goto err;
13285 /* ... and they pop one */
13288 if (op == TOK_CONDITIONAL) {
13289 if(! numptr_m1->contidional_second_val_initialized) {
13290 /* protect $((expr1 ? expr2)) without ": expr" */
13293 rez = numptr_m1->contidional_second_val;
13294 } else if(numptr_m1->contidional_second_val_initialized) {
13295 /* protect $((expr1 : expr2)) without "expr ? " */
13298 numptr_m1 = NUMPTR - 1;
13299 if(op != TOK_ASSIGN) {
13300 /* check operand is var with noninteger value for not '=' */
13301 ret_arith_lookup_val = arith_lookup_val(numptr_m1);
13302 if(ret_arith_lookup_val)
13303 return ret_arith_lookup_val;
13305 if (op == TOK_CONDITIONAL) {
13306 numptr_m1->contidional_second_val = rez;
13308 rez = numptr_m1->val;
13309 if (op == TOK_BOR || op == TOK_OR_ASSIGN)
13311 else if (op == TOK_OR)
13312 rez = numptr_val || rez;
13313 else if (op == TOK_BAND || op == TOK_AND_ASSIGN)
13315 else if (op == TOK_BXOR || op == TOK_XOR_ASSIGN)
13317 else if (op == TOK_AND)
13318 rez = rez && numptr_val;
13319 else if (op == TOK_EQ)
13320 rez = (rez == numptr_val);
13321 else if (op == TOK_NE)
13322 rez = (rez != numptr_val);
13323 else if (op == TOK_GE)
13324 rez = (rez >= numptr_val);
13325 else if (op == TOK_RSHIFT || op == TOK_RSHIFT_ASSIGN)
13326 rez >>= numptr_val;
13327 else if (op == TOK_LSHIFT || op == TOK_LSHIFT_ASSIGN)
13328 rez <<= numptr_val;
13329 else if (op == TOK_GT)
13330 rez = (rez > numptr_val);
13331 else if (op == TOK_LT)
13332 rez = (rez < numptr_val);
13333 else if (op == TOK_LE)
13334 rez = (rez <= numptr_val);
13335 else if (op == TOK_MUL || op == TOK_MUL_ASSIGN)
13337 else if (op == TOK_ADD || op == TOK_PLUS_ASSIGN)
13339 else if (op == TOK_SUB || op == TOK_MINUS_ASSIGN)
13341 else if (op == TOK_ASSIGN || op == TOK_COMMA)
13343 else if (op == TOK_CONDITIONAL_SEP) {
13344 if (numptr_m1 == numstack) {
13345 /* protect $((expr : expr)) without "expr ? " */
13348 numptr_m1->contidional_second_val_initialized = op;
13349 numptr_m1->contidional_second_val = numptr_val;
13351 else if (op == TOK_CONDITIONAL) {
13353 numptr_val : numptr_m1->contidional_second_val;
13355 else if(op == TOK_EXPONENT) {
13357 return -3; /* exponent less than 0 */
13362 while(numptr_val--)
13367 else if(numptr_val==0) /* zero divisor check */
13369 else if (op == TOK_DIV || op == TOK_DIV_ASSIGN)
13371 else if (op == TOK_REM || op == TOK_REM_ASSIGN)
13374 if(tok_have_assign(op)) {
13377 if(numptr_m1->var == NULL) {
13381 /* save to shell variable */
13382 #ifdef CONFIG_ASH_MATH_SUPPORT_64
13383 snprintf(buf, sizeof(buf), "%lld", rez);
13385 snprintf(buf, sizeof(buf), "%ld", rez);
13387 setvar(numptr_m1->var, buf, 0);
13388 /* after saving, make previous value for v++ or v-- */
13389 if(op == TOK_POST_INC)
13391 else if(op == TOK_POST_DEC)
13394 numptr_m1->val = rez;
13395 /* protect geting var value, is number now */
13396 numptr_m1->var = NULL;
13401 /* longest must first */
13402 static const char op_tokens[] = {
13403 '<','<','=',0, TOK_LSHIFT_ASSIGN,
13404 '>','>','=',0, TOK_RSHIFT_ASSIGN,
13405 '<','<', 0, TOK_LSHIFT,
13406 '>','>', 0, TOK_RSHIFT,
13407 '|','|', 0, TOK_OR,
13408 '&','&', 0, TOK_AND,
13409 '!','=', 0, TOK_NE,
13410 '<','=', 0, TOK_LE,
13411 '>','=', 0, TOK_GE,
13412 '=','=', 0, TOK_EQ,
13413 '|','=', 0, TOK_OR_ASSIGN,
13414 '&','=', 0, TOK_AND_ASSIGN,
13415 '*','=', 0, TOK_MUL_ASSIGN,
13416 '/','=', 0, TOK_DIV_ASSIGN,
13417 '%','=', 0, TOK_REM_ASSIGN,
13418 '+','=', 0, TOK_PLUS_ASSIGN,
13419 '-','=', 0, TOK_MINUS_ASSIGN,
13420 '-','-', 0, TOK_POST_DEC,
13421 '^','=', 0, TOK_XOR_ASSIGN,
13422 '+','+', 0, TOK_POST_INC,
13423 '*','*', 0, TOK_EXPONENT,
13427 '=', 0, TOK_ASSIGN,
13439 '?', 0, TOK_CONDITIONAL,
13440 ':', 0, TOK_CONDITIONAL_SEP,
13441 ')', 0, TOK_RPAREN,
13442 '(', 0, TOK_LPAREN,
13446 #define endexpression &op_tokens[sizeof(op_tokens)-7]
13449 static arith_t arith (const char *expr, int *perrcode)
13451 register char arithval; /* Current character under analysis */
13452 operator lasttok, op;
13455 const char *p = endexpression;
13458 size_t datasizes = strlen(expr) + 2;
13460 /* Stack of integers */
13461 /* The proof that there can be no more than strlen(startbuf)/2+1 integers
13462 * in any given correct or incorrect expression is left as an exercise to
13464 v_n_t *numstack = alloca(((datasizes)/2)*sizeof(v_n_t)),
13465 *numstackptr = numstack;
13466 /* Stack of operator tokens */
13467 operator *stack = alloca((datasizes) * sizeof(operator)),
13470 *stackptr++ = lasttok = TOK_LPAREN; /* start off with a left paren */
13471 *perrcode = errcode = 0;
13474 if ((arithval = *expr) == 0) {
13475 if (p == endexpression) {
13476 /* Null expression. */
13480 /* This is only reached after all tokens have been extracted from the
13481 * input stream. If there are still tokens on the operator stack, they
13482 * are to be applied in order. At the end, there should be a final
13483 * result on the integer stack */
13485 if (expr != endexpression + 1) {
13486 /* If we haven't done so already, */
13487 /* append a closing right paren */
13488 expr = endexpression;
13489 /* and let the loop process it. */
13492 /* At this point, we're done with the expression. */
13493 if (numstackptr != numstack+1) {
13494 /* ... but if there isn't, it's bad */
13496 return (*perrcode = -1);
13498 if(numstack->var) {
13499 /* expression is $((var)) only, lookup now */
13500 errcode = arith_lookup_val(numstack);
13503 *perrcode = errcode;
13504 return numstack->val;
13506 /* Continue processing the expression. */
13507 if (arith_isspace(arithval)) {
13508 /* Skip whitespace */
13511 if((p = endofname(expr)) != expr) {
13512 size_t var_name_size = (p-expr) + 1; /* trailing zero */
13514 numstackptr->var = alloca(var_name_size);
13515 safe_strncpy(numstackptr->var, expr, var_name_size);
13518 numstackptr->contidional_second_val_initialized = 0;
13522 } else if (is_digit(arithval)) {
13523 numstackptr->var = NULL;
13524 #ifdef CONFIG_ASH_MATH_SUPPORT_64
13525 numstackptr->val = strtoll(expr, (char **) &expr, 0);
13527 numstackptr->val = strtol(expr, (char **) &expr, 0);
13531 for(p = op_tokens; ; p++) {
13535 /* strange operator not found */
13538 for(o = expr; *p && *o == *p; p++)
13545 /* skip tail uncompared token */
13548 /* skip zero delim */
13553 /* post grammar: a++ reduce to num */
13554 if(lasttok == TOK_POST_INC || lasttok == TOK_POST_DEC)
13557 /* Plus and minus are binary (not unary) _only_ if the last
13558 * token was as number, or a right paren (which pretends to be
13559 * a number, since it evaluates to one). Think about it.
13560 * It makes sense. */
13561 if (lasttok != TOK_NUM) {
13577 /* We don't want a unary operator to cause recursive descent on the
13578 * stack, because there can be many in a row and it could cause an
13579 * operator to be evaluated before its argument is pushed onto the
13580 * integer stack. */
13581 /* But for binary operators, "apply" everything on the operator
13582 * stack until we find an operator with a lesser priority than the
13583 * one we have just extracted. */
13584 /* Left paren is given the lowest priority so it will never be
13585 * "applied" in this way.
13586 * if associativity is right and priority eq, applied also skip
13589 if ((prec > 0 && prec < UNARYPREC) || prec == SPEC_PREC) {
13590 /* not left paren or unary */
13591 if (lasttok != TOK_NUM) {
13592 /* binary op must be preceded by a num */
13595 while (stackptr != stack) {
13596 if (op == TOK_RPAREN) {
13597 /* The algorithm employed here is simple: while we don't
13598 * hit an open paren nor the bottom of the stack, pop
13599 * tokens and apply them */
13600 if (stackptr[-1] == TOK_LPAREN) {
13602 /* Any operator directly after a */
13604 /* close paren should consider itself binary */
13608 operator prev_prec = PREC(stackptr[-1]);
13610 convert_prec_is_assing(prec);
13611 convert_prec_is_assing(prev_prec);
13612 if (prev_prec < prec)
13614 /* check right assoc */
13615 if(prev_prec == prec && is_right_associativity(prec))
13618 errcode = arith_apply(*--stackptr, numstack, &numstackptr);
13619 if(errcode) goto ret;
13621 if (op == TOK_RPAREN) {
13626 /* Push this operator to the stack and remember it. */
13627 *stackptr++ = lasttok = op;
13634 #endif /* CONFIG_ASH_MATH_SUPPORT */
13638 const char *bb_applet_name = "debug stuff usage";
13639 int main(int argc, char **argv)
13641 return ash_main(argc, argv);
13646 * Copyright (c) 1989, 1991, 1993, 1994
13647 * The Regents of the University of California. All rights reserved.
13649 * This code is derived from software contributed to Berkeley by
13650 * Kenneth Almquist.
13652 * Redistribution and use in source and binary forms, with or without
13653 * modification, are permitted provided that the following conditions
13655 * 1. Redistributions of source code must retain the above copyright
13656 * notice, this list of conditions and the following disclaimer.
13657 * 2. Redistributions in binary form must reproduce the above copyright
13658 * notice, this list of conditions and the following disclaimer in the
13659 * documentation and/or other materials provided with the distribution.
13660 * 3. Neither the name of the University nor the names of its contributors
13661 * may be used to endorse or promote products derived from this software
13662 * without specific prior written permission.
13664 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
13665 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
13666 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
13667 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
13668 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
13669 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
13670 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13671 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
13672 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
13673 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF