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 "source", dotcmd },
1357 { BUILTIN_SPEC_REG "shift", shiftcmd },
1358 { BUILTIN_SPEC_REG "times", timescmd },
1359 { BUILTIN_SPEC_REG "trap", trapcmd },
1360 { BUILTIN_REGULAR "true", truecmd },
1361 { BUILTIN_NOSPEC "type", typecmd },
1362 { BUILTIN_NOSPEC "ulimit", ulimitcmd },
1363 { BUILTIN_REGULAR "umask", umaskcmd },
1364 #ifdef CONFIG_ASH_ALIAS
1365 { BUILTIN_REGULAR "unalias", unaliascmd },
1367 { BUILTIN_SPEC_REG "unset", unsetcmd },
1368 { BUILTIN_REGULAR "wait", waitcmd },
1371 #define NUMBUILTINS (sizeof (builtincmd) / sizeof (struct builtincmd) )
1379 const struct builtincmd *cmd;
1380 struct funcnode *func;
1385 /* action to find_command() */
1386 #define DO_ERR 0x01 /* prints errors */
1387 #define DO_ABS 0x02 /* checks absolute paths */
1388 #define DO_NOFUNC 0x04 /* don't return shell functions, for command */
1389 #define DO_ALTPATH 0x08 /* using alternate path */
1390 #define DO_ALTBLTIN 0x20 /* %builtin in alt. path */
1392 static const char *pathopt; /* set by padvance */
1394 static void shellexec(char **, const char *, int)
1396 static char *padvance(const char **, const char *);
1397 static void find_command(char *, struct cmdentry *, int, const char *);
1398 static struct builtincmd *find_builtin(const char *);
1399 static void hashcd(void);
1400 static void changepath(const char *);
1401 static void defun(char *, union node *);
1402 static void unsetfunc(const char *);
1404 #ifdef CONFIG_ASH_MATH_SUPPORT_64
1405 typedef int64_t arith_t;
1406 #define arith_t_type (long long)
1408 typedef long arith_t;
1409 #define arith_t_type (long)
1412 #ifdef CONFIG_ASH_MATH_SUPPORT
1413 static arith_t dash_arith(const char *);
1414 static arith_t arith(const char *expr, int *perrcode);
1417 #ifdef CONFIG_ASH_RANDOM_SUPPORT
1418 static unsigned long rseed;
1419 static void change_random(const char *);
1420 # ifndef DYNAMIC_VAR
1421 # define DYNAMIC_VAR
1427 static void reset(void);
1436 #define VEXPORT 0x01 /* variable is exported */
1437 #define VREADONLY 0x02 /* variable cannot be modified */
1438 #define VSTRFIXED 0x04 /* variable struct is statically allocated */
1439 #define VTEXTFIXED 0x08 /* text is statically allocated */
1440 #define VSTACK 0x10 /* text is allocated on the stack */
1441 #define VUNSET 0x20 /* the variable is not set */
1442 #define VNOFUNC 0x40 /* don't call the callback function */
1443 #define VNOSET 0x80 /* do not set variable - just readonly test */
1444 #define VNOSAVE 0x100 /* when text is on the heap before setvareq */
1446 # define VDYNAMIC 0x200 /* dynamic variable */
1452 struct var *next; /* next entry in hash list */
1453 int flags; /* flags are defined above */
1454 const char *text; /* name=value */
1455 void (*func)(const char *); /* function to be called when */
1456 /* the variable gets set/unset */
1460 struct localvar *next; /* next local variable in list */
1461 struct var *vp; /* the variable that was made local */
1462 int flags; /* saved flags */
1463 const char *text; /* saved text */
1467 static struct localvar *localvars;
1473 #ifdef CONFIG_ASH_GETOPTS
1474 static void getoptsreset(const char *);
1477 #ifdef CONFIG_LOCALE_SUPPORT
1479 static void change_lc_all(const char *value);
1480 static void change_lc_ctype(const char *value);
1486 static const char defpathvar[] = "PATH=/usr/local/bin:/usr/bin:/sbin:/bin";
1488 static const char defifsvar[] = "IFS= \t\n";
1489 #define defifs (defifsvar + 4)
1491 static const char defifs[] = " \t\n";
1495 static struct var varinit[] = {
1497 { 0, VSTRFIXED|VTEXTFIXED, defifsvar, 0 },
1499 { 0, VSTRFIXED|VTEXTFIXED|VUNSET, "IFS\0", 0 },
1502 #ifdef CONFIG_ASH_MAIL
1503 { 0, VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL\0", changemail },
1504 { 0, VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH\0", changemail },
1507 { 0, VSTRFIXED|VTEXTFIXED, defpathvar, changepath },
1508 { 0, VSTRFIXED|VTEXTFIXED, "PS1=$ ", 0 },
1509 { 0, VSTRFIXED|VTEXTFIXED, "PS2=> ", 0 },
1510 { 0, VSTRFIXED|VTEXTFIXED, "PS4=+ ", 0 },
1511 #ifdef CONFIG_ASH_GETOPTS
1512 { 0, VSTRFIXED|VTEXTFIXED, "OPTIND=1", getoptsreset },
1514 #ifdef CONFIG_ASH_RANDOM_SUPPORT
1515 {0, VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM\0", change_random },
1517 #ifdef CONFIG_LOCALE_SUPPORT
1518 {0, VSTRFIXED | VTEXTFIXED | VUNSET, "LC_ALL\0", change_lc_all },
1519 {0, VSTRFIXED | VTEXTFIXED | VUNSET, "LC_CTYPE\0", change_lc_ctype },
1521 #ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
1522 {0, VSTRFIXED | VTEXTFIXED | VUNSET, "HISTFILE\0", NULL },
1526 #define vifs varinit[0]
1527 #ifdef CONFIG_ASH_MAIL
1528 #define vmail (&vifs)[1]
1529 #define vmpath (&vmail)[1]
1533 #define vpath (&vmpath)[1]
1534 #define vps1 (&vpath)[1]
1535 #define vps2 (&vps1)[1]
1536 #define vps4 (&vps2)[1]
1537 #define voptind (&vps4)[1]
1538 #ifdef CONFIG_ASH_GETOPTS
1539 #define vrandom (&voptind)[1]
1541 #define vrandom (&vps4)[1]
1543 #define defpath (defpathvar + 5)
1546 * The following macros access the values of the above variables.
1547 * They have to skip over the name. They return the null string
1548 * for unset variables.
1551 #define ifsval() (vifs.text + 4)
1552 #define ifsset() ((vifs.flags & VUNSET) == 0)
1553 #define mailval() (vmail.text + 5)
1554 #define mpathval() (vmpath.text + 9)
1555 #define pathval() (vpath.text + 5)
1556 #define ps1val() (vps1.text + 4)
1557 #define ps2val() (vps2.text + 4)
1558 #define ps4val() (vps4.text + 4)
1559 #define optindval() (voptind.text + 7)
1561 #define mpathset() ((vmpath.flags & VUNSET) == 0)
1563 static void setvar(const char *, const char *, int);
1564 static void setvareq(char *, int);
1565 static void listsetvar(struct strlist *, int);
1566 static char *lookupvar(const char *);
1567 static char *bltinlookup(const char *);
1568 static char **listvars(int, int, char ***);
1569 #define environment() listvars(VEXPORT, VUNSET, 0)
1570 static int showvars(const char *, int, int);
1571 static void poplocalvars(void);
1572 static int unsetvar(const char *);
1573 #ifdef CONFIG_ASH_GETOPTS
1574 static int setvarsafe(const char *, const char *, int);
1576 static int varcmp(const char *, const char *);
1577 static struct var **hashvar(const char *);
1580 static inline int varequal(const char *a, const char *b) {
1581 return !varcmp(a, b);
1585 static int loopnest; /* current loop nesting level */
1588 * The parsefile structure pointed to by the global variable parsefile
1589 * contains information about the current file being read.
1594 struct redirtab *next;
1599 static struct redirtab *redirlist;
1600 static int nullredirs;
1602 extern char **environ;
1607 static void outstr(const char *, FILE *);
1608 static void outcslow(int, FILE *);
1609 static void flushall(void);
1610 static void flusherr(void);
1611 static int out1fmt(const char *, ...)
1612 __attribute__((__format__(__printf__,1,2)));
1613 static int fmtstr(char *, size_t, const char *, ...)
1614 __attribute__((__format__(__printf__,3,4)));
1616 static int preverrout_fd; /* save fd2 before print debug if xflag is set. */
1619 static void out1str(const char *p)
1624 static void out2str(const char *p)
1631 * Initialization code.
1635 * This routine initializes the builtin variables.
1646 * PS1 depends on uid
1648 #if defined(CONFIG_FEATURE_COMMAND_EDITING) && defined(CONFIG_FEATURE_SH_FANCY_PROMPT)
1649 vps1.text = "PS1=\\w \\$ ";
1652 vps1.text = "PS1=# ";
1655 end = vp + sizeof(varinit) / sizeof(varinit[0]);
1657 vpp = hashvar(vp->text);
1660 } while (++vp < end);
1669 basepf.nextc = basepf.buf = basebuf;
1674 signal(SIGCHLD, SIG_DFL);
1682 struct stat st1, st2;
1685 for (envp = environ ; envp && *envp ; envp++) {
1686 if (strchr(*envp, '=')) {
1687 setvareq(*envp, VEXPORT|VTEXTFIXED);
1691 snprintf(ppid, sizeof(ppid), "%d", (int) getppid());
1692 setvar("PPID", ppid, 0);
1694 p = lookupvar("PWD");
1696 if (*p != '/' || stat(p, &st1) || stat(".", &st2) ||
1697 st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino)
1703 /* PEOF (the end of file marker) */
1706 INPUT_PUSH_FILE = 1,
1707 INPUT_NOFILE_OK = 2,
1711 * The input line number. Input.c just defines this variable, and saves
1712 * and restores it when files are pushed and popped. The user of this
1713 * package must set its value.
1716 static int pgetc(void);
1717 static int pgetc2(void);
1718 static int preadbuffer(void);
1719 static void pungetc(void);
1720 static void pushstring(char *, void *);
1721 static void popstring(void);
1722 static void setinputfd(int, int);
1723 static void setinputstring(char *);
1724 static void popfile(void);
1725 static void popallfiles(void);
1726 static void closescript(void);
1732 /* Mode argument to forkshell. Don't change FORK_FG or FORK_BG. */
1735 #define FORK_NOJOB 2
1737 /* mode flags for showjob(s) */
1738 #define SHOW_PGID 0x01 /* only show pgid - for jobs -p */
1739 #define SHOW_PID 0x04 /* include process pid */
1740 #define SHOW_CHANGED 0x08 /* only jobs whose state has changed */
1744 * A job structure contains information about a job. A job is either a
1745 * single process or a set of processes contained in a pipeline. In the
1746 * latter case, pidlist will be non-NULL, and will point to a -1 terminated
1751 pid_t pid; /* process id */
1752 int status; /* last process status from wait() */
1753 char *cmd; /* text of command being run */
1757 struct procstat ps0; /* status of process */
1758 struct procstat *ps; /* status or processes when more than one */
1760 int stopstatus; /* status of a stopped job */
1763 nprocs: 16, /* number of processes */
1765 #define JOBRUNNING 0 /* at least one proc running */
1766 #define JOBSTOPPED 1 /* all procs are stopped */
1767 #define JOBDONE 2 /* all procs are completed */
1769 sigint: 1, /* job was killed by SIGINT */
1770 jobctl: 1, /* job running under job control */
1772 waited: 1, /* true if this entry has been waited for */
1773 used: 1, /* true if this entry is in used */
1774 changed: 1; /* true if status has changed */
1775 struct job *prev_job; /* previous job */
1778 static pid_t backgndpid; /* pid of last background process */
1779 static int job_warning; /* user was warned about stopped jobs */
1781 static int jobctl; /* true if doing job control */
1784 static struct job *makejob(union node *, int);
1785 static int forkshell(struct job *, union node *, int);
1786 static int waitforjob(struct job *);
1787 static int stoppedjobs(void);
1790 #define setjobctl(on) /* do nothing */
1792 static void setjobctl(int);
1793 static void showjobs(FILE *, int);
1799 /* pid of main shell */
1801 /* shell level: 0 for the main shell, 1 for its children, and so on */
1803 #define rootshell (!shlvl)
1805 static void readcmdfile(char *);
1806 static int cmdloop(int);
1812 struct stack_block *stackp;
1815 struct stackmark *marknext;
1818 /* minimum size of a block */
1819 #define MINSIZE SHELL_ALIGN(504)
1821 struct stack_block {
1822 struct stack_block *prev;
1823 char space[MINSIZE];
1826 static struct stack_block stackbase;
1827 static struct stack_block *stackp = &stackbase;
1828 static struct stackmark *markp;
1829 static char *stacknxt = stackbase.space;
1830 static size_t stacknleft = MINSIZE;
1831 static char *sstrend = stackbase.space + MINSIZE;
1832 static int herefd = -1;
1835 static pointer ckmalloc(size_t);
1836 static pointer ckrealloc(pointer, size_t);
1837 static char *savestr(const char *);
1838 static pointer stalloc(size_t);
1839 static void stunalloc(pointer);
1840 static void setstackmark(struct stackmark *);
1841 static void popstackmark(struct stackmark *);
1842 static void growstackblock(void);
1843 static void *growstackstr(void);
1844 static char *makestrspace(size_t, char *);
1845 static char *stnputs(const char *, size_t, char *);
1846 static char *stputs(const char *, char *);
1849 static inline char *_STPUTC(int c, char *p) {
1856 #define stackblock() ((void *)stacknxt)
1857 #define stackblocksize() stacknleft
1858 #define STARTSTACKSTR(p) ((p) = stackblock())
1859 #define STPUTC(c, p) ((p) = _STPUTC((c), (p)))
1860 #define CHECKSTRSPACE(n, p) \
1864 size_t m = sstrend - q; \
1866 (p) = makestrspace(l, q); \
1869 #define USTPUTC(c, p) (*p++ = (c))
1870 #define STACKSTRNUL(p) ((p) == sstrend? (p = growstackstr(), *p = '\0') : (*p = '\0'))
1871 #define STUNPUTC(p) (--p)
1872 #define STTOPC(p) p[-1]
1873 #define STADJUST(amount, p) (p += (amount))
1875 #define grabstackstr(p) stalloc((char *)(p) - (char *)stackblock())
1876 #define ungrabstackstr(s, p) stunalloc((s))
1877 #define stackstrend() ((void *)sstrend)
1879 #define ckfree(p) free((pointer)(p))
1884 #define DOLATSTRLEN 4
1886 static char *prefix(const char *, const char *);
1887 static int number(const char *);
1888 static int is_number(const char *);
1889 static char *single_quote(const char *);
1890 static char *sstrdup(const char *);
1892 #define equal(s1, s2) (strcmp(s1, s2) == 0)
1893 #define scopy(s1, s2) ((void)strcpy(s2, s1))
1898 int nparam; /* # of positional parameters (without $0) */
1899 unsigned char malloc; /* if parameter list dynamically allocated */
1900 char **p; /* parameter list */
1901 #ifdef CONFIG_ASH_GETOPTS
1902 int optind; /* next parameter to be processed by getopts */
1903 int optoff; /* used by getopts */
1908 #define eflag optlist[0]
1909 #define fflag optlist[1]
1910 #define Iflag optlist[2]
1911 #define iflag optlist[3]
1912 #define mflag optlist[4]
1913 #define nflag optlist[5]
1914 #define sflag optlist[6]
1915 #define xflag optlist[7]
1916 #define vflag optlist[8]
1917 #define Cflag optlist[9]
1918 #define aflag optlist[10]
1919 #define bflag optlist[11]
1920 #define uflag optlist[12]
1921 #define viflag optlist[13]
1924 #define nolog optlist[14]
1925 #define debug optlist[15]
1928 #ifndef CONFIG_FEATURE_COMMAND_EDITING_VI
1929 #define setvimode(on) viflag = 0 /* forcibly keep the option off */
1935 static const char *const optletters_optnames[] = {
1956 #define optletters(n) optletters_optnames[(n)][0]
1957 #define optnames(n) (&optletters_optnames[(n)][1])
1959 #define NOPTS (sizeof(optletters_optnames)/sizeof(optletters_optnames[0]))
1961 static char optlist[NOPTS];
1964 static char *arg0; /* value of $0 */
1965 static struct shparam shellparam; /* $@ current positional parameters */
1966 static char **argptr; /* argument list for builtin commands */
1967 static char *optionarg; /* set by nextopt (like getopt) */
1968 static char *optptr; /* used by nextopt */
1970 static char *minusc; /* argument to -c option */
1973 static void procargs(int, char **);
1974 static void optschanged(void);
1975 static void setparam(char **);
1976 static void freeparam(volatile struct shparam *);
1977 static int shiftcmd(int, char **);
1978 static int setcmd(int, char **);
1979 static int nextopt(const char *);
1983 /* flags passed to redirect */
1984 #define REDIR_PUSH 01 /* save previous values of file descriptors */
1985 #define REDIR_SAVEFD2 03 /* set preverrout */
1988 static void redirect(union node *, int);
1989 static void popredir(int);
1990 static void clearredir(int);
1991 static int copyfd(int, int);
1992 static int redirectsafe(union node *, int);
1998 static void showtree(union node *);
1999 static void trace(const char *, ...);
2000 static void tracev(const char *, va_list);
2001 static void trargs(char **);
2002 static void trputc(int);
2003 static void trputs(const char *);
2004 static void opentrace(void);
2010 /* trap handler commands */
2011 static char *trap[NSIG];
2012 /* current value of signal */
2013 static char sigmode[NSIG - 1];
2014 /* indicates specified signal received */
2015 static char gotsig[NSIG - 1];
2017 static void clear_traps(void);
2018 static void setsignal(int);
2019 static void ignoresig(int);
2020 static void onsig(int);
2021 static int dotrap(void);
2022 static void setinteractive(int);
2023 static void exitshell(void) ATTRIBUTE_NORETURN;
2024 static int decode_signal(const char *, int);
2027 * This routine is called when an error or an interrupt occurs in an
2028 * interactive shell and control is returned to the main command loop.
2042 parselleft = parsenleft = 0; /* clear input buffer */
2046 /* from parser.c: */
2059 #ifdef CONFIG_ASH_ALIAS
2060 static struct alias *atab[ATABSIZE];
2062 static void setalias(const char *, const char *);
2063 static struct alias *freealias(struct alias *);
2064 static struct alias **__lookupalias(const char *);
2067 setalias(const char *name, const char *val)
2069 struct alias *ap, **app;
2071 app = __lookupalias(name);
2075 if (!(ap->flag & ALIASINUSE)) {
2078 ap->val = savestr(val);
2079 ap->flag &= ~ALIASDEAD;
2082 ap = ckmalloc(sizeof (struct alias));
2083 ap->name = savestr(name);
2084 ap->val = savestr(val);
2093 unalias(const char *name)
2097 app = __lookupalias(name);
2101 *app = freealias(*app);
2112 struct alias *ap, **app;
2116 for (i = 0; i < ATABSIZE; i++) {
2118 for (ap = *app; ap; ap = *app) {
2119 *app = freealias(*app);
2128 static struct alias *
2129 lookupalias(const char *name, int check)
2131 struct alias *ap = *__lookupalias(name);
2133 if (check && ap && (ap->flag & ALIASINUSE))
2139 * TODO - sort output
2142 aliascmd(int argc, char **argv)
2151 for (i = 0; i < ATABSIZE; i++)
2152 for (ap = atab[i]; ap; ap = ap->next) {
2157 while ((n = *++argv) != NULL) {
2158 if ((v = strchr(n+1, '=')) == NULL) { /* n+1: funny ksh stuff */
2159 if ((ap = *__lookupalias(n)) == NULL) {
2160 fprintf(stderr, "%s: %s not found\n", "alias", n);
2174 unaliascmd(int argc, char **argv)
2178 while ((i = nextopt("a")) != '\0') {
2184 for (i = 0; *argptr; argptr++) {
2185 if (unalias(*argptr)) {
2186 fprintf(stderr, "%s: %s not found\n", "unalias", *argptr);
2194 static struct alias *
2195 freealias(struct alias *ap) {
2198 if (ap->flag & ALIASINUSE) {
2199 ap->flag |= ALIASDEAD;
2211 printalias(const struct alias *ap) {
2212 out1fmt("%s=%s\n", ap->name, single_quote(ap->val));
2215 static struct alias **
2216 __lookupalias(const char *name) {
2217 unsigned int hashval;
2224 ch = (unsigned char)*p;
2228 ch = (unsigned char)*++p;
2230 app = &atab[hashval % ATABSIZE];
2232 for (; *app; app = &(*app)->next) {
2233 if (equal(name, (*app)->name)) {
2240 #endif /* CONFIG_ASH_ALIAS */
2246 * The cd and pwd commands.
2249 #define CD_PHYSICAL 1
2252 static int docd(const char *, int);
2253 static int cdopt(void);
2255 static char *curdir = nullstr; /* current working directory */
2256 static char *physdir = nullstr; /* physical working directory */
2265 while ((i = nextopt("LP"))) {
2267 flags ^= CD_PHYSICAL;
2276 cdcmd(int argc, char **argv)
2288 dest = bltinlookup(homestr);
2289 else if (dest[0] == '-' && dest[1] == '\0') {
2290 dest = bltinlookup("OLDPWD");
2312 if (!(path = bltinlookup("CDPATH"))) {
2320 p = padvance(&path, dest);
2321 if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
2325 if (!docd(p, flags))
2330 sh_error("can't cd to %s", dest);
2333 if (flags & CD_PRINT)
2334 out1fmt(snlfmt, curdir);
2340 * Update curdir (the name of the current directory) in response to a
2344 static inline const char *
2345 updatepwd(const char *dir)
2352 cdcomppath = sstrdup(dir);
2355 if (curdir == nullstr)
2357 new = stputs(curdir, new);
2359 new = makestrspace(strlen(dir) + 2, new);
2360 lim = stackblock() + 1;
2364 if (new > lim && *lim == '/')
2369 if (dir[1] == '/' && dir[2] != '/') {
2375 p = strtok(cdcomppath, "/");
2379 if (p[1] == '.' && p[2] == '\0') {
2386 } else if (p[1] == '\0')
2390 new = stputs(p, new);
2398 return stackblock();
2402 * Actually do the chdir. We also call hashcd to let the routines in exec.c
2403 * know that the current directory has changed.
2407 docd(const char *dest, int flags)
2409 const char *dir = 0;
2412 TRACE(("docd(\"%s\", %d) called\n", dest, flags));
2415 if (!(flags & CD_PHYSICAL)) {
2416 dir = updatepwd(dest);
2431 * Find out what the current directory is. If we already know the current
2432 * directory, this routine returns immediately.
2434 static inline char *
2437 char *dir = getcwd(0, 0);
2438 return dir ? dir : nullstr;
2442 pwdcmd(int argc, char **argv)
2445 const char *dir = curdir;
2449 if (physdir == nullstr)
2453 out1fmt(snlfmt, dir);
2458 setpwd(const char *val, int setold)
2462 oldcur = dir = curdir;
2465 setvar("OLDPWD", oldcur, VEXPORT);
2468 if (physdir != nullstr) {
2469 if (physdir != oldcur)
2473 if (oldcur == val || !val) {
2480 if (oldcur != dir && oldcur != nullstr) {
2485 setvar("PWD", dir, VEXPORT);
2491 * Errors and exceptions.
2495 * Code to handle exceptions in C.
2500 static void exverror(int, const char *, va_list)
2504 * Called to raise an exception. Since C doesn't include exceptions, we
2505 * just do a longjmp to the exception handler. The type of exception is
2506 * stored in the global variable "exception".
2513 if (handler == NULL)
2519 longjmp(handler->loc, 1);
2524 * Called from trap.c when a SIGINT is received. (If the user specifies
2525 * that SIGINT is to be trapped or ignored using the trap builtin, then
2526 * this routine is not called.) Suppressint is nonzero when interrupts
2527 * are held using the INTOFF macro. (The test for iflag is just
2528 * defensive programming.)
2537 /* comment by vodz: its strange for me, this programm don`t use other
2542 if (gotsig[SIGINT - 1] && !trap[SIGINT]) {
2543 if (!(rootshell && iflag)) {
2544 signal(SIGINT, SIG_DFL);
2554 exvwarning(const char *msg, va_list ap)
2559 fprintf(errs, "%s: ", arg0);
2561 const char *fmt = (!iflag || parsefile->fd) ?
2562 "%s: %d: " : "%s: ";
2563 fprintf(errs, fmt, commandname, startlinno);
2565 vfprintf(errs, msg, ap);
2566 outcslow('\n', errs);
2570 * Exverror is called to raise the error exception. If the second argument
2571 * is not NULL then error prints an error message using printf style
2572 * formatting. It then raises the error exception.
2575 exverror(int cond, const char *msg, va_list ap)
2579 TRACE(("exverror(%d, \"", cond));
2581 TRACE(("\") pid=%d\n", getpid()));
2583 TRACE(("exverror(%d, NULL) pid=%d\n", cond, getpid()));
2586 exvwarning(msg, ap);
2595 sh_error(const char *msg, ...)
2600 exverror(EXERROR, msg, ap);
2607 exerror(int cond, const char *msg, ...)
2612 exverror(cond, msg, ap);
2618 * error/warning routines for external builtins
2622 sh_warnx(const char *fmt, ...)
2627 exvwarning(fmt, ap);
2633 * Return a string describing an error. The returned string may be a
2634 * pointer to a static buffer that will be overwritten on the next call.
2635 * Action describes the operation that got the error.
2639 errmsg(int e, const char *em)
2641 if(e == ENOENT || e == ENOTDIR) {
2652 * Evaluate a command.
2655 /* flags in argument to evaltree */
2656 #define EV_EXIT 01 /* exit after evaluating tree */
2657 #define EV_TESTED 02 /* exit status is checked; ignore -e flag */
2658 #define EV_BACKCMD 04 /* command executing within back quotes */
2661 static void evalloop(union node *, int);
2662 static void evalfor(union node *, int);
2663 static void evalcase(union node *, int);
2664 static void evalsubshell(union node *, int);
2665 static void expredir(union node *);
2666 static void evalpipe(union node *, int);
2667 static void evalcommand(union node *, int);
2668 static int evalbltin(const struct builtincmd *, int, char **);
2669 static int evalfun(struct funcnode *, int, char **, int);
2670 static void prehash(union node *);
2671 static int bltincmd(int, char **);
2674 static const struct builtincmd bltin = {
2680 * Called to reset things after an exception.
2688 evalcmd(int argc, char **argv)
2697 STARTSTACKSTR(concat);
2700 concat = stputs(p, concat);
2701 if ((p = *ap++) == NULL)
2703 STPUTC(' ', concat);
2705 STPUTC('\0', concat);
2706 p = grabstackstr(concat);
2708 evalstring(p, ~SKIPEVAL);
2716 * Execute a command or commands contained in a string.
2720 evalstring(char *s, int mask)
2723 struct stackmark smark;
2727 setstackmark(&smark);
2730 while ((n = parsecmd(0)) != NEOF) {
2732 popstackmark(&smark);
2747 * Evaluate a parse tree. The value is left in the global variable
2752 evaltree(union node *n, int flags)
2755 void (*evalfn)(union node *, int);
2759 TRACE(("evaltree(NULL) called\n"));
2762 TRACE(("pid %d, evaltree(%p: %d, %d) called\n",
2763 getpid(), n, n->type, flags));
2767 out1fmt("Node type = %d\n", n->type);
2772 evaltree(n->nnot.com, EV_TESTED);
2773 status = !exitstatus;
2776 expredir(n->nredir.redirect);
2777 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
2779 evaltree(n->nredir.n, flags & EV_TESTED);
2780 status = exitstatus;
2785 evalfn = evalcommand;
2787 if (eflag && !(flags & EV_TESTED))
2799 evalfn = evalsubshell;
2811 #error NAND + 1 != NOR
2813 #if NOR + 1 != NSEMI
2814 #error NOR + 1 != NSEMI
2816 isor = n->type - NAND;
2819 (flags | ((isor >> 1) - 1)) & EV_TESTED
2821 if (!exitstatus == isor)
2833 evaltree(n->nif.test, EV_TESTED);
2836 if (exitstatus == 0) {
2839 } else if (n->nif.elsepart) {
2840 n = n->nif.elsepart;
2845 defun(n->narg.text, n->narg.next);
2849 exitstatus = status;
2853 if ((checkexit & exitstatus))
2854 evalskip |= SKIPEVAL;
2855 else if (pendingsigs && dotrap())
2858 if (flags & EV_EXIT) {
2865 #if !defined(__alpha__) || (defined(__GNUC__) && __GNUC__ >= 3)
2868 void evaltreenr(union node *, int) __attribute__ ((alias("evaltree"),__noreturn__));
2872 evalloop(union node *n, int flags)
2882 evaltree(n->nbinary.ch1, EV_TESTED);
2884 skipping: if (evalskip == SKIPCONT && --skipcount <= 0) {
2888 if (evalskip == SKIPBREAK && --skipcount <= 0)
2893 if (n->type != NWHILE)
2897 evaltree(n->nbinary.ch2, flags);
2898 status = exitstatus;
2903 exitstatus = status;
2909 evalfor(union node *n, int flags)
2911 struct arglist arglist;
2914 struct stackmark smark;
2916 setstackmark(&smark);
2917 arglist.lastp = &arglist.list;
2918 for (argp = n->nfor.args ; argp ; argp = argp->narg.next) {
2919 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE | EXP_RECORD);
2924 *arglist.lastp = NULL;
2929 for (sp = arglist.list ; sp ; sp = sp->next) {
2930 setvar(n->nfor.var, sp->text, 0);
2931 evaltree(n->nfor.body, flags);
2933 if (evalskip == SKIPCONT && --skipcount <= 0) {
2937 if (evalskip == SKIPBREAK && --skipcount <= 0)
2944 popstackmark(&smark);
2950 evalcase(union node *n, int flags)
2954 struct arglist arglist;
2955 struct stackmark smark;
2957 setstackmark(&smark);
2958 arglist.lastp = &arglist.list;
2959 expandarg(n->ncase.expr, &arglist, EXP_TILDE);
2961 for (cp = n->ncase.cases ; cp && evalskip == 0 ; cp = cp->nclist.next) {
2962 for (patp = cp->nclist.pattern ; patp ; patp = patp->narg.next) {
2963 if (casematch(patp, arglist.list->text)) {
2964 if (evalskip == 0) {
2965 evaltree(cp->nclist.body, flags);
2972 popstackmark(&smark);
2978 * Kick off a subshell to evaluate a tree.
2982 evalsubshell(union node *n, int flags)
2985 int backgnd = (n->type == NBACKGND);
2988 expredir(n->nredir.redirect);
2989 if (!backgnd && flags & EV_EXIT && !trap[0])
2993 if (forkshell(jp, n, backgnd) == 0) {
2997 flags &=~ EV_TESTED;
2999 redirect(n->nredir.redirect, 0);
3000 evaltreenr(n->nredir.n, flags);
3005 status = waitforjob(jp);
3006 exitstatus = status;
3013 * Compute the names of the files in a redirection list.
3017 expredir(union node *n)
3021 for (redir = n ; redir ; redir = redir->nfile.next) {
3023 fn.lastp = &fn.list;
3024 switch (redir->type) {
3030 expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
3031 redir->nfile.expfname = fn.list->text;
3035 if (redir->ndup.vname) {
3036 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
3037 fixredir(redir, fn.list->text, 1);
3047 * Evaluate a pipeline. All the processes in the pipeline are children
3048 * of the process creating the pipeline. (This differs from some versions
3049 * of the shell, which make the last process in a pipeline the parent
3054 evalpipe(union node *n, int flags)
3057 struct nodelist *lp;
3062 TRACE(("evalpipe(0x%lx) called\n", (long)n));
3064 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next)
3068 jp = makejob(n, pipelen);
3070 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
3074 if (pipe(pip) < 0) {
3076 sh_error("Pipe call failed");
3079 if (forkshell(jp, lp->n, n->npipe.backgnd) == 0) {
3092 evaltreenr(lp->n, flags);
3100 if (n->npipe.backgnd == 0) {
3101 exitstatus = waitforjob(jp);
3102 TRACE(("evalpipe: job done exit status %d\n", exitstatus));
3110 * Execute a command inside back quotes. If it's a builtin command, we
3111 * want to save its output in a block obtained from malloc. Otherwise
3112 * we fork off a subprocess and get the output of the command via a pipe.
3113 * Should be called with interrupts off.
3117 evalbackcmd(union node *n, struct backcmd *result)
3129 saveherefd = herefd;
3137 sh_error("Pipe call failed");
3139 if (forkshell(jp, n, FORK_NOJOB) == 0) {
3148 evaltreenr(n, EV_EXIT);
3152 result->fd = pip[0];
3155 herefd = saveherefd;
3157 TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
3158 result->fd, result->buf, result->nleft, result->jp));
3161 #ifdef CONFIG_ASH_CMDCMD
3162 static inline char **
3163 parse_command_args(char **argv, const char **path)
3175 if (c == '-' && !*cp) {
3185 /* run 'typecmd' for other options */
3188 } while ((c = *cp++));
3195 isassignment(const char *p)
3197 const char *q = endofname(p);
3203 #ifdef CONFIG_ASH_EXPAND_PRMT
3204 static const char *expandstr(const char *ps);
3206 #define expandstr(s) s
3210 * Execute a simple command.
3214 evalcommand(union node *cmd, int flags)
3216 struct stackmark smark;
3218 struct arglist arglist;
3219 struct arglist varlist;
3222 const struct strlist *sp;
3223 struct cmdentry cmdentry;
3231 struct builtincmd *bcmd;
3232 int pseudovarflag = 0;
3234 /* First expand the arguments. */
3235 TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
3236 setstackmark(&smark);
3237 back_exitstatus = 0;
3239 cmdentry.cmdtype = CMDBUILTIN;
3240 cmdentry.u.cmd = &bltin;
3241 varlist.lastp = &varlist.list;
3242 *varlist.lastp = NULL;
3243 arglist.lastp = &arglist.list;
3244 *arglist.lastp = NULL;
3249 bcmd = find_builtin(cmd->ncmd.args->narg.text);
3250 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
3253 for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
3254 struct strlist **spp;
3256 spp = arglist.lastp;
3257 if (pseudovarflag && isassignment(argp->narg.text))
3258 expandarg(argp, &arglist, EXP_VARTILDE);
3260 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
3262 for (sp = *spp; sp; sp = sp->next)
3266 argv = nargv = stalloc(sizeof (char *) * (argc + 1));
3267 for (sp = arglist.list ; sp ; sp = sp->next) {
3268 TRACE(("evalcommand arg: %s\n", sp->text));
3269 *nargv++ = sp->text;
3274 if (iflag && funcnest == 0 && argc > 0)
3275 lastarg = nargv[-1];
3278 expredir(cmd->ncmd.redirect);
3279 status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH|REDIR_SAVEFD2);
3282 for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
3283 struct strlist **spp;
3286 spp = varlist.lastp;
3287 expandarg(argp, &varlist, EXP_VARTILDE);
3290 * Modify the command lookup path, if a PATH= assignment
3294 if (varequal(p, path))
3298 /* Print the command if xflag is set. */
3301 const char *p = " %s";
3304 dprintf(preverrout_fd, p, expandstr(ps4val()));
3307 for(n = 0; n < 2; n++) {
3309 dprintf(preverrout_fd, p, sp->text);
3317 bb_full_write(preverrout_fd, "\n", 1);
3323 /* Now locate the command. */
3325 const char *oldpath;
3326 int cmd_flag = DO_ERR;
3331 find_command(argv[0], &cmdentry, cmd_flag, path);
3332 if (cmdentry.cmdtype == CMDUNKNOWN) {
3338 /* implement bltin and command here */
3339 if (cmdentry.cmdtype != CMDBUILTIN)
3342 spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
3343 if (cmdentry.u.cmd == EXECCMD)
3345 #ifdef CONFIG_ASH_CMDCMD
3346 if (cmdentry.u.cmd == COMMANDCMD) {
3349 nargv = parse_command_args(argv, &path);
3352 argc -= nargv - argv;
3354 cmd_flag |= DO_NOFUNC;
3362 /* We have a redirection error. */
3366 exitstatus = status;
3370 /* Execute the command. */
3371 switch (cmdentry.cmdtype) {
3373 /* Fork off a child process if necessary. */
3374 if (!(flags & EV_EXIT) || trap[0]) {
3376 jp = makejob(cmd, 1);
3377 if (forkshell(jp, cmd, FORK_FG) != 0) {
3378 exitstatus = waitforjob(jp);
3384 listsetvar(varlist.list, VEXPORT|VSTACK);
3385 shellexec(argv, path, cmdentry.u.index);
3389 cmdenviron = varlist.list;
3391 struct strlist *list = cmdenviron;
3393 if (spclbltin > 0 || argc == 0) {
3395 if (cmd_is_exec && argc > 1)
3398 listsetvar(list, i);
3400 if (evalbltin(cmdentry.u.cmd, argc, argv)) {
3415 exit_status = j + 128;
3416 exitstatus = exit_status;
3418 if (i == EXINT || spclbltin > 0) {
3420 longjmp(handler->loc, 1);
3427 listsetvar(varlist.list, 0);
3428 if (evalfun(cmdentry.u.func, argc, argv, flags))
3434 popredir(cmd_is_exec);
3436 /* dsl: I think this is intended to be used to support
3437 * '_' in 'vi' command mode during line editing...
3438 * However I implemented that within libedit itself.
3440 setvar("_", lastarg, 0);
3441 popstackmark(&smark);
3445 evalbltin(const struct builtincmd *cmd, int argc, char **argv) {
3446 char *volatile savecmdname;
3447 struct jmploc *volatile savehandler;
3448 struct jmploc jmploc;
3451 savecmdname = commandname;
3452 if ((i = setjmp(jmploc.loc)))
3454 savehandler = handler;
3456 commandname = argv[0];
3458 optptr = NULL; /* initialize nextopt */
3459 exitstatus = (*cmd->builtin)(argc, argv);
3462 exitstatus |= ferror(stdout);
3463 commandname = savecmdname;
3465 handler = savehandler;
3471 evalfun(struct funcnode *func, int argc, char **argv, int flags)
3473 volatile struct shparam saveparam;
3474 struct localvar *volatile savelocalvars;
3475 struct jmploc *volatile savehandler;
3476 struct jmploc jmploc;
3479 saveparam = shellparam;
3480 savelocalvars = localvars;
3481 if ((e = setjmp(jmploc.loc))) {
3485 savehandler = handler;
3488 shellparam.malloc = 0;
3492 shellparam.nparam = argc - 1;
3493 shellparam.p = argv + 1;
3494 #ifdef CONFIG_ASH_GETOPTS
3495 shellparam.optind = 1;
3496 shellparam.optoff = -1;
3498 evaltree(&func->n, flags & EV_TESTED);
3504 localvars = savelocalvars;
3505 freeparam(&shellparam);
3506 shellparam = saveparam;
3507 handler = savehandler;
3509 evalskip &= ~SKIPFUNC;
3515 goodname(const char *p)
3517 return !*endofname(p);
3521 * Search for a command. This is called before we fork so that the
3522 * location of the command will be available in the parent as well as
3523 * the child. The check for "goodname" is an overly conservative
3524 * check that the name will not be subject to expansion.
3528 prehash(union node *n)
3530 struct cmdentry entry;
3532 if (n->type == NCMD && n->ncmd.args)
3533 if (goodname(n->ncmd.args->narg.text))
3534 find_command(n->ncmd.args->narg.text, &entry, 0,
3541 * Builtin commands. Builtin commands whose functions are closely
3542 * tied to evaluation are implemented here.
3550 bltincmd(int argc, char **argv)
3553 * Preserve exitstatus of a previous possible redirection
3556 return back_exitstatus;
3561 * Handle break and continue commands. Break, continue, and return are
3562 * all handled by setting the evalskip flag. The evaluation routines
3563 * above all check this flag, and if it is set they start skipping
3564 * commands rather than executing them. The variable skipcount is
3565 * the number of loops to break/continue, or the number of function
3566 * levels to return. (The latter is always 1.) It should probably
3567 * be an error to break out of more loops than exist, but it isn't
3568 * in the standard shell so we don't make it one here.
3572 breakcmd(int argc, char **argv)
3574 int n = argc > 1 ? number(argv[1]) : 1;
3577 sh_error(illnum, argv[1]);
3581 evalskip = (**argv == 'c')? SKIPCONT : SKIPBREAK;
3589 * The return command.
3593 returncmd(int argc, char **argv)
3596 * If called outside a function, do what ksh does;
3597 * skip the rest of the file.
3599 evalskip = funcnest ? SKIPFUNC : SKIPFILE;
3600 return argv[1] ? number(argv[1]) : exitstatus;
3605 falsecmd(int argc, char **argv)
3612 truecmd(int argc, char **argv)
3619 execcmd(int argc, char **argv)
3622 iflag = 0; /* exit on error */
3625 shellexec(argv + 1, pathval(), 0);
3634 * When commands are first encountered, they are entered in a hash table.
3635 * This ensures that a full path search will not have to be done for them
3636 * on each invocation.
3638 * We should investigate converting to a linear search, even though that
3639 * would make the command name "hash" a misnomer.
3642 #define CMDTABLESIZE 31 /* should be prime */
3643 #define ARB 1 /* actual size determined at run time */
3648 struct tblentry *next; /* next entry in hash chain */
3649 union param param; /* definition of builtin function */
3650 short cmdtype; /* index identifying command */
3651 char rehash; /* if set, cd done since entry created */
3652 char cmdname[ARB]; /* name of command */
3656 static struct tblentry *cmdtable[CMDTABLESIZE];
3657 static int builtinloc = -1; /* index in path of %builtin, or -1 */
3660 static void tryexec(char *, char **, char **);
3661 static void clearcmdentry(int);
3662 static struct tblentry *cmdlookup(const char *, int);
3663 static void delete_cmd_entry(void);
3667 * Exec a program. Never returns. If you change this routine, you may
3668 * have to change the find_command routine as well.
3672 shellexec(char **argv, const char *path, int idx)
3680 envp = environment();
3681 if (strchr(argv[0], '/') != NULL
3682 #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
3683 || find_applet_by_name(argv[0])
3686 tryexec(argv[0], argv, envp);
3690 while ((cmdname = padvance(&path, argv[0])) != NULL) {
3691 if (--idx < 0 && pathopt == NULL) {
3692 tryexec(cmdname, argv, envp);
3693 if (errno != ENOENT && errno != ENOTDIR)
3700 /* Map to POSIX errors */
3712 exitstatus = exerrno;
3713 TRACE(("shellexec failed for %s, errno %d, suppressint %d\n",
3714 argv[0], e, suppressint ));
3715 exerror(EXEXEC, "%s: %s", argv[0], errmsg(e, E_EXEC));
3721 tryexec(char *cmd, char **argv, char **envp)
3724 #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
3725 if(find_applet_by_name(cmd) != NULL) {
3726 /* re-exec ourselves with the new arguments */
3727 execve("/proc/self/exe",argv,envp);
3728 /* If proc isn't mounted, try hardcoded path to busybox binary*/
3729 execve("/bin/busybox",argv,envp);
3730 /* If they called chroot or otherwise made the binary no longer
3731 * executable, fall through */
3738 execve(cmd, argv, envp);
3739 } while (errno == EINTR);
3741 execve(cmd, argv, envp);
3745 } else if (errno == ENOEXEC) {
3749 for (ap = argv; *ap; ap++)
3751 ap = new = ckmalloc((ap - argv + 2) * sizeof(char *));
3753 *ap = cmd = (char *)DEFAULT_SHELL;
3756 while ((*ap++ = *argv++))
3766 * Do a path search. The variable path (passed by reference) should be
3767 * set to the start of the path before the first call; padvance will update
3768 * this value as it proceeds. Successive calls to padvance will return
3769 * the possible path expansions in sequence. If an option (indicated by
3770 * a percent sign) appears in the path entry then the global variable
3771 * pathopt will be set to point to it; otherwise pathopt will be set to
3776 padvance(const char **path, const char *name)
3786 for (p = start ; *p && *p != ':' && *p != '%' ; p++);
3787 len = p - start + strlen(name) + 2; /* "2" is for '/' and '\0' */
3788 while (stackblocksize() < len)
3792 memcpy(q, start, p - start);
3800 while (*p && *p != ':') p++;
3806 return stalloc(len);
3810 /*** Command hashing code ***/
3813 printentry(struct tblentry *cmdp)
3819 idx = cmdp->param.index;
3822 name = padvance(&path, cmdp->cmdname);
3824 } while (--idx >= 0);
3825 out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
3830 hashcmd(int argc, char **argv)
3832 struct tblentry **pp;
3833 struct tblentry *cmdp;
3835 struct cmdentry entry;
3838 while ((c = nextopt("r")) != '\0') {
3842 if (*argptr == NULL) {
3843 for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
3844 for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
3845 if (cmdp->cmdtype == CMDNORMAL)
3852 while ((name = *argptr) != NULL) {
3853 if ((cmdp = cmdlookup(name, 0)) != NULL
3854 && (cmdp->cmdtype == CMDNORMAL
3855 || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0)))
3857 find_command(name, &entry, DO_ERR, pathval());
3858 if (entry.cmdtype == CMDUNKNOWN)
3867 * Resolve a command name. If you change this routine, you may have to
3868 * change the shellexec routine as well.
3872 find_command(char *name, struct cmdentry *entry, int act, const char *path)
3874 struct tblentry *cmdp;
3881 struct builtincmd *bcmd;
3883 /* If name contains a slash, don't use PATH or hash table */
3884 if (strchr(name, '/') != NULL) {
3885 entry->u.index = -1;
3887 while (stat(name, &statb) < 0) {
3892 entry->cmdtype = CMDUNKNOWN;
3896 entry->cmdtype = CMDNORMAL;
3900 #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
3901 if (find_applet_by_name(name)) {
3902 entry->cmdtype = CMDNORMAL;
3903 entry->u.index = -1;
3908 updatetbl = (path == pathval());
3911 if (strstr(path, "%builtin") != NULL)
3915 /* If name is in the table, check answer will be ok */
3916 if ((cmdp = cmdlookup(name, 0)) != NULL) {
3919 switch (cmdp->cmdtype) {
3937 } else if (cmdp->rehash == 0)
3938 /* if not invalidated by cd, we're done */
3942 /* If %builtin not in path, check for builtin next */
3943 bcmd = find_builtin(name);
3944 if (bcmd && (IS_BUILTIN_REGULAR(bcmd) || (
3945 act & DO_ALTPATH ? !(act & DO_ALTBLTIN) : builtinloc <= 0
3947 goto builtin_success;
3949 /* We have to search path. */
3950 prev = -1; /* where to start */
3951 if (cmdp && cmdp->rehash) { /* doing a rehash */
3952 if (cmdp->cmdtype == CMDBUILTIN)
3955 prev = cmdp->param.index;
3961 while ((fullname = padvance(&path, name)) != NULL) {
3962 stunalloc(fullname);
3965 if (prefix(pathopt, "builtin")) {
3967 goto builtin_success;
3969 } else if (!(act & DO_NOFUNC) &&
3970 prefix(pathopt, "func")) {
3973 /* ignore unimplemented options */
3977 /* if rehash, don't redo absolute path names */
3978 if (fullname[0] == '/' && idx <= prev) {
3981 TRACE(("searchexec \"%s\": no change\n", name));
3984 while (stat(fullname, &statb) < 0) {
3989 if (errno != ENOENT && errno != ENOTDIR)
3993 e = EACCES; /* if we fail, this will be the error */
3994 if (!S_ISREG(statb.st_mode))
3996 if (pathopt) { /* this is a %func directory */
3997 stalloc(strlen(fullname) + 1);
3998 readcmdfile(fullname);
3999 if ((cmdp = cmdlookup(name, 0)) == NULL ||
4000 cmdp->cmdtype != CMDFUNCTION)
4001 sh_error("%s not defined in %s", name, fullname);
4002 stunalloc(fullname);
4005 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
4007 entry->cmdtype = CMDNORMAL;
4008 entry->u.index = idx;
4012 cmdp = cmdlookup(name, 1);
4013 cmdp->cmdtype = CMDNORMAL;
4014 cmdp->param.index = idx;
4019 /* We failed. If there was an entry for this command, delete it */
4020 if (cmdp && updatetbl)
4023 sh_warnx("%s: %s", name, errmsg(e, E_EXEC));
4024 entry->cmdtype = CMDUNKNOWN;
4029 entry->cmdtype = CMDBUILTIN;
4030 entry->u.cmd = bcmd;
4034 cmdp = cmdlookup(name, 1);
4035 cmdp->cmdtype = CMDBUILTIN;
4036 cmdp->param.cmd = bcmd;
4040 entry->cmdtype = cmdp->cmdtype;
4041 entry->u = cmdp->param;
4046 * Wrapper around strcmp for qsort/bsearch/...
4048 static int pstrcmp(const void *a, const void *b)
4050 return strcmp((const char *) a, (*(const char *const *) b) + 1);
4054 * Search the table of builtin commands.
4057 static struct builtincmd *
4058 find_builtin(const char *name)
4060 struct builtincmd *bp;
4063 name, builtincmd, NUMBUILTINS, sizeof(struct builtincmd),
4072 * Called when a cd is done. Marks all commands so the next time they
4073 * are executed they will be rehashed.
4079 struct tblentry **pp;
4080 struct tblentry *cmdp;
4082 for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
4083 for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
4084 if (cmdp->cmdtype == CMDNORMAL || (
4085 cmdp->cmdtype == CMDBUILTIN &&
4086 !(IS_BUILTIN_REGULAR(cmdp->param.cmd)) &&
4097 * Fix command hash table when PATH changed.
4098 * Called before PATH is changed. The argument is the new value of PATH;
4099 * pathval() still returns the old value at this point.
4100 * Called with interrupts off.
4104 changepath(const char *newval)
4106 const char *old, *new;
4113 firstchange = 9999; /* assume no change */
4119 if ((*old == '\0' && *new == ':')
4120 || (*old == ':' && *new == '\0'))
4122 old = new; /* ignore subsequent differences */
4126 if (*new == '%' && idx_bltin < 0 && prefix(new + 1, "builtin"))
4133 if (builtinloc < 0 && idx_bltin >= 0)
4134 builtinloc = idx_bltin; /* zap builtins */
4135 if (builtinloc >= 0 && idx_bltin < 0)
4137 clearcmdentry(firstchange);
4138 builtinloc = idx_bltin;
4143 * Clear out command entries. The argument specifies the first entry in
4144 * PATH which has changed.
4148 clearcmdentry(int firstchange)
4150 struct tblentry **tblp;
4151 struct tblentry **pp;
4152 struct tblentry *cmdp;
4155 for (tblp = cmdtable ; tblp < &cmdtable[CMDTABLESIZE] ; tblp++) {
4157 while ((cmdp = *pp) != NULL) {
4158 if ((cmdp->cmdtype == CMDNORMAL &&
4159 cmdp->param.index >= firstchange)
4160 || (cmdp->cmdtype == CMDBUILTIN &&
4161 builtinloc >= firstchange)) {
4175 * Locate a command in the command hash table. If "add" is nonzero,
4176 * add the command to the table if it is not already present. The
4177 * variable "lastcmdentry" is set to point to the address of the link
4178 * pointing to the entry, so that delete_cmd_entry can delete the
4181 * Interrupts must be off if called with add != 0.
4184 static struct tblentry **lastcmdentry;
4187 static struct tblentry *
4188 cmdlookup(const char *name, int add)
4190 unsigned int hashval;
4192 struct tblentry *cmdp;
4193 struct tblentry **pp;
4196 hashval = (unsigned char)*p << 4;
4198 hashval += (unsigned char)*p++;
4200 pp = &cmdtable[hashval % CMDTABLESIZE];
4201 for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
4202 if (equal(cmdp->cmdname, name))
4206 if (add && cmdp == NULL) {
4207 cmdp = *pp = ckmalloc(sizeof (struct tblentry) - ARB
4208 + strlen(name) + 1);
4210 cmdp->cmdtype = CMDUNKNOWN;
4211 strcpy(cmdp->cmdname, name);
4218 * Delete the command entry returned on the last lookup.
4222 delete_cmd_entry(void)
4224 struct tblentry *cmdp;
4227 cmdp = *lastcmdentry;
4228 *lastcmdentry = cmdp->next;
4229 if (cmdp->cmdtype == CMDFUNCTION)
4230 freefunc(cmdp->param.func);
4237 * Add a new command entry, replacing any existing command entry for
4238 * the same name - except special builtins.
4242 addcmdentry(char *name, struct cmdentry *entry)
4244 struct tblentry *cmdp;
4246 cmdp = cmdlookup(name, 1);
4247 if (cmdp->cmdtype == CMDFUNCTION) {
4248 freefunc(cmdp->param.func);
4250 cmdp->cmdtype = entry->cmdtype;
4251 cmdp->param = entry->u;
4256 * Make a copy of a parse tree.
4259 static inline struct funcnode *
4260 copyfunc(union node *n)
4265 funcblocksize = offsetof(struct funcnode, n);
4268 blocksize = funcblocksize;
4269 f = ckmalloc(blocksize + funcstringsize);
4270 funcblock = (char *) f + offsetof(struct funcnode, n);
4271 funcstring = (char *) f + blocksize;
4278 * Define a shell function.
4282 defun(char *name, union node *func)
4284 struct cmdentry entry;
4287 entry.cmdtype = CMDFUNCTION;
4288 entry.u.func = copyfunc(func);
4289 addcmdentry(name, &entry);
4295 * Delete a function if it exists.
4299 unsetfunc(const char *name)
4301 struct tblentry *cmdp;
4303 if ((cmdp = cmdlookup(name, 0)) != NULL &&
4304 cmdp->cmdtype == CMDFUNCTION)
4309 * Locate and print what a word is...
4313 #ifdef CONFIG_ASH_CMDCMD
4315 describe_command(char *command, int describe_command_verbose)
4317 #define describe_command_verbose 1
4319 describe_command(char *command)
4322 struct cmdentry entry;
4323 struct tblentry *cmdp;
4324 #ifdef CONFIG_ASH_ALIAS
4325 const struct alias *ap;
4327 const char *path = pathval();
4329 if (describe_command_verbose) {
4333 /* First look at the keywords */
4334 if (findkwd(command)) {
4335 out1str(describe_command_verbose ? " is a shell keyword" : command);
4339 #ifdef CONFIG_ASH_ALIAS
4340 /* Then look at the aliases */
4341 if ((ap = lookupalias(command, 0)) != NULL) {
4342 if (describe_command_verbose) {
4343 out1fmt(" is an alias for %s", ap->val);
4352 /* Then check if it is a tracked alias */
4353 if ((cmdp = cmdlookup(command, 0)) != NULL) {
4354 entry.cmdtype = cmdp->cmdtype;
4355 entry.u = cmdp->param;
4357 /* Finally use brute force */
4358 find_command(command, &entry, DO_ABS, path);
4361 switch (entry.cmdtype) {
4363 int j = entry.u.index;
4369 p = padvance(&path, command);
4373 if (describe_command_verbose) {
4375 (cmdp ? " a tracked alias for" : nullstr), p
4384 if (describe_command_verbose) {
4385 out1str(" is a shell function");
4392 if (describe_command_verbose) {
4393 out1fmt(" is a %sshell builtin",
4394 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
4395 "special " : nullstr
4403 if (describe_command_verbose) {
4404 out1str(": not found\n");
4410 outstr("\n", stdout);
4415 typecmd(int argc, char **argv)
4420 for (i = 1; i < argc; i++) {
4421 #ifdef CONFIG_ASH_CMDCMD
4422 err |= describe_command(argv[i], 1);
4424 err |= describe_command(argv[i]);
4430 #ifdef CONFIG_ASH_CMDCMD
4432 commandcmd(int argc, char **argv)
4440 while ((c = nextopt("pvV")) != '\0')
4442 verify |= VERIFY_VERBOSE;
4444 verify |= VERIFY_BRIEF;
4450 return describe_command(*argptr, verify - VERIFY_BRIEF);
4459 * Routines to expand arguments to commands. We have to deal with
4460 * backquotes, shell variables, and file metacharacters.
4466 #define RMESCAPE_ALLOC 0x1 /* Allocate a new string */
4467 #define RMESCAPE_GLOB 0x2 /* Add backslashes for glob */
4468 #define RMESCAPE_QUOTED 0x4 /* Remove CTLESC unless in quotes */
4469 #define RMESCAPE_GROW 0x8 /* Grow strings instead of stalloc */
4470 #define RMESCAPE_HEAP 0x10 /* Malloc strings instead of stalloc */
4473 * Structure specifying which parts of the string should be searched
4474 * for IFS characters.
4478 struct ifsregion *next; /* next region in list */
4479 int begoff; /* offset of start of region */
4480 int endoff; /* offset of end of region */
4481 int nulonly; /* search for nul bytes only */
4484 /* output of current string */
4485 static char *expdest;
4486 /* list of back quote expressions */
4487 static struct nodelist *argbackq;
4488 /* first struct in list of ifs regions */
4489 static struct ifsregion ifsfirst;
4490 /* last struct in list */
4491 static struct ifsregion *ifslastp;
4492 /* holds expanded arg list */
4493 static struct arglist exparg;
4495 static void argstr(char *, int);
4496 static char *exptilde(char *, char *, int);
4497 static void expbackq(union node *, int, int);
4498 static const char *subevalvar(char *, char *, int, int, int, int, int);
4499 static char *evalvar(char *, int);
4500 static void strtodest(const char *, int, int);
4501 static void memtodest(const char *p, size_t len, int syntax, int quotes);
4502 static ssize_t varvalue(char *, int, int);
4503 static void recordregion(int, int, int);
4504 static void removerecordregions(int);
4505 static void ifsbreakup(char *, struct arglist *);
4506 static void ifsfree(void);
4507 static void expandmeta(struct strlist *, int);
4508 static int patmatch(char *, const char *);
4510 static int cvtnum(arith_t);
4511 static size_t esclen(const char *, const char *);
4512 static char *scanleft(char *, char *, char *, char *, int, int);
4513 static char *scanright(char *, char *, char *, char *, int, int);
4514 static void varunset(const char *, const char *, const char *, int)
4518 #define pmatch(a, b) !fnmatch((a), (b), 0)
4520 * Prepare a pattern for a expmeta (internal glob(3)) call.
4522 * Returns an stalloced string.
4525 static inline char *
4526 preglob(const char *pattern, int quoted, int flag) {
4527 flag |= RMESCAPE_GLOB;
4529 flag |= RMESCAPE_QUOTED;
4531 return _rmescapes((char *)pattern, flag);
4536 esclen(const char *start, const char *p) {
4539 while (p > start && *--p == CTLESC) {
4547 * Expand shell variables and backquotes inside a here document.
4551 expandhere(union node *arg, int fd)
4554 expandarg(arg, (struct arglist *)NULL, 0);
4555 bb_full_write(fd, stackblock(), expdest - (char *)stackblock());
4560 * Perform variable substitution and command substitution on an argument,
4561 * placing the resulting list of arguments in arglist. If EXP_FULL is true,
4562 * perform splitting and file name expansion. When arglist is NULL, perform
4563 * here document expansion.
4567 expandarg(union node *arg, struct arglist *arglist, int flag)
4572 argbackq = arg->narg.backquote;
4573 STARTSTACKSTR(expdest);
4574 ifsfirst.next = NULL;
4576 argstr(arg->narg.text, flag);
4577 p = _STPUTC('\0', expdest);
4579 if (arglist == NULL) {
4580 return; /* here document expanded */
4582 p = grabstackstr(p);
4583 exparg.lastp = &exparg.list;
4587 if (flag & EXP_FULL) {
4588 ifsbreakup(p, &exparg);
4589 *exparg.lastp = NULL;
4590 exparg.lastp = &exparg.list;
4591 expandmeta(exparg.list, flag);
4593 if (flag & EXP_REDIR) /*XXX - for now, just remove escapes */
4595 sp = (struct strlist *)stalloc(sizeof (struct strlist));
4598 exparg.lastp = &sp->next;
4602 *exparg.lastp = NULL;
4604 *arglist->lastp = exparg.list;
4605 arglist->lastp = exparg.lastp;
4611 * Perform variable and command substitution. If EXP_FULL is set, output CTLESC
4612 * characters to allow for further processing. Otherwise treat
4613 * $@ like $* since no splitting will be performed.
4617 argstr(char *p, int flag)
4619 static const char spclchars[] = {
4627 CTLBACKQ | CTLQUOTE,
4628 #ifdef CONFIG_ASH_MATH_SUPPORT
4633 const char *reject = spclchars;
4635 int quotes = flag & (EXP_FULL | EXP_CASE); /* do CTLESC */
4636 int breakall = flag & EXP_WORD;
4641 if (!(flag & EXP_VARTILDE)) {
4643 } else if (flag & EXP_VARTILDE2) {
4648 if (flag & EXP_TILDE) {
4654 if (*q == CTLESC && (flag & EXP_QWORD))
4657 p = exptilde(p, q, flag);
4660 startloc = expdest - (char *)stackblock();
4662 length += strcspn(p + length, reject);
4664 if (c && (!(c & 0x80)
4665 #ifdef CONFIG_ASH_MATH_SUPPORT
4669 /* c == '=' || c == ':' || c == CTLENDARI */
4674 expdest = stnputs(p, length, expdest);
4675 newloc = expdest - (char *)stackblock();
4676 if (breakall && !inquotes && newloc > startloc) {
4677 recordregion(startloc, newloc, 0);
4688 if (flag & EXP_VARTILDE2) {
4692 flag |= EXP_VARTILDE2;
4697 * sort of a hack - expand tildes in variable
4698 * assignments (after the first '=' and after ':'s).
4707 case CTLENDVAR: /* ??? */
4710 /* "$@" syntax adherence hack */
4713 !memcmp(p, dolatstr, DOLATSTRLEN) &&
4714 (p[4] == CTLQUOTEMARK || (
4715 p[4] == CTLENDVAR &&
4716 p[5] == CTLQUOTEMARK
4719 p = evalvar(p + 1, flag) + 1;
4722 inquotes = !inquotes;
4735 p = evalvar(p, flag);
4739 case CTLBACKQ|CTLQUOTE:
4740 expbackq(argbackq->n, c, quotes);
4741 argbackq = argbackq->next;
4743 #ifdef CONFIG_ASH_MATH_SUPPORT
4756 exptilde(char *startp, char *p, int flag)
4762 int quotes = flag & (EXP_FULL | EXP_CASE);
4767 while ((c = *++p) != '\0') {
4774 if (flag & EXP_VARTILDE)
4784 if (*name == '\0') {
4785 home = lookupvar(homestr);
4787 if ((pw = getpwnam(name)) == NULL)
4791 if (!home || !*home)
4794 startloc = expdest - (char *)stackblock();
4795 strtodest(home, SQSYNTAX, quotes);
4796 recordregion(startloc, expdest - (char *)stackblock(), 0);
4805 removerecordregions(int endoff)
4807 if (ifslastp == NULL)
4810 if (ifsfirst.endoff > endoff) {
4811 while (ifsfirst.next != NULL) {
4812 struct ifsregion *ifsp;
4814 ifsp = ifsfirst.next->next;
4815 ckfree(ifsfirst.next);
4816 ifsfirst.next = ifsp;
4819 if (ifsfirst.begoff > endoff)
4822 ifslastp = &ifsfirst;
4823 ifsfirst.endoff = endoff;
4828 ifslastp = &ifsfirst;
4829 while (ifslastp->next && ifslastp->next->begoff < endoff)
4830 ifslastp=ifslastp->next;
4831 while (ifslastp->next != NULL) {
4832 struct ifsregion *ifsp;
4834 ifsp = ifslastp->next->next;
4835 ckfree(ifslastp->next);
4836 ifslastp->next = ifsp;
4839 if (ifslastp->endoff > endoff)
4840 ifslastp->endoff = endoff;
4844 #ifdef CONFIG_ASH_MATH_SUPPORT
4846 * Expand arithmetic expression. Backup to start of expression,
4847 * evaluate, place result in (backed up) result, adjust string position.
4860 * This routine is slightly over-complicated for
4861 * efficiency. Next we scan backwards looking for the
4862 * start of arithmetic.
4864 start = stackblock();
4871 while (*p != CTLARI) {
4875 sh_error("missing CTLARI (shouldn't happen)");
4880 esc = esclen(start, p);
4890 removerecordregions(begoff);
4899 len = cvtnum(dash_arith(p + 2));
4902 recordregion(begoff, begoff + len, 0);
4907 * Expand stuff in backwards quotes.
4911 expbackq(union node *cmd, int quoted, int quotes)
4919 int syntax = quoted? DQSYNTAX : BASESYNTAX;
4920 struct stackmark smark;
4923 setstackmark(&smark);
4925 startloc = dest - (char *)stackblock();
4927 evalbackcmd(cmd, (struct backcmd *) &in);
4928 popstackmark(&smark);
4935 memtodest(p, i, syntax, quotes);
4939 i = safe_read(in.fd, buf, sizeof buf);
4940 TRACE(("expbackq: read returns %d\n", i));
4950 back_exitstatus = waitforjob(in.jp);
4954 /* Eat all trailing newlines */
4956 for (; dest > (char *)stackblock() && dest[-1] == '\n';)
4961 recordregion(startloc, dest - (char *)stackblock(), 0);
4962 TRACE(("evalbackq: size=%d: \"%.*s\"\n",
4963 (dest - (char *)stackblock()) - startloc,
4964 (dest - (char *)stackblock()) - startloc,
4965 stackblock() + startloc));
4970 scanleft(char *startp, char *rmesc, char *rmescend, char *str, int quotes,
4981 const char *s = loc2;
4987 match = pmatch(str, s);
4991 if (quotes && *loc == CTLESC)
5001 scanright(char *startp, char *rmesc, char *rmescend, char *str, int quotes,
5008 for (loc = str - 1, loc2 = rmescend; loc >= startp; loc2--) {
5011 const char *s = loc2;
5016 match = pmatch(str, s);
5023 esc = esclen(startp, loc);
5035 subevalvar(char *p, char *str, int strloc, int subtype, int startloc, int varflags, int quotes)
5039 int saveherefd = herefd;
5040 struct nodelist *saveargbackq = argbackq;
5042 char *rmesc, *rmescend;
5044 char *(*scan)(char *, char *, char *, char *, int , int);
5047 argstr(p, subtype != VSASSIGN && subtype != VSQUESTION ? EXP_CASE : 0);
5048 STPUTC('\0', expdest);
5049 herefd = saveherefd;
5050 argbackq = saveargbackq;
5051 startp = stackblock() + startloc;
5055 setvar(str, startp, 0);
5056 amount = startp - expdest;
5057 STADJUST(amount, expdest);
5061 varunset(p, str, startp, varflags);
5065 subtype -= VSTRIMRIGHT;
5067 if (subtype < 0 || subtype > 3)
5072 rmescend = stackblock() + strloc;
5074 rmesc = _rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW);
5075 if (rmesc != startp) {
5077 startp = stackblock() + startloc;
5081 str = stackblock() + strloc;
5082 preglob(str, varflags & VSQUOTE, 0);
5084 /* zero = subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX */
5085 zero = subtype >> 1;
5086 /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
5087 scan = (subtype & 1) ^ zero ? scanleft : scanright;
5089 loc = scan(startp, rmesc, rmescend, str, quotes, zero);
5092 memmove(startp, loc, str - loc);
5093 loc = startp + (str - loc) - 1;
5096 amount = loc - expdest;
5097 STADJUST(amount, expdest);
5104 * Expand a variable, and return a pointer to the next character in the
5108 evalvar(char *p, int flag)
5121 quotes = flag & (EXP_FULL | EXP_CASE);
5123 subtype = varflags & VSTYPE;
5124 quoted = varflags & VSQUOTE;
5126 easy = (!quoted || (*var == '@' && shellparam.nparam));
5127 startloc = expdest - (char *)stackblock();
5128 p = strchr(p, '=') + 1;
5131 varlen = varvalue(var, varflags, flag);
5132 if (varflags & VSNUL)
5135 if (subtype == VSPLUS) {
5136 varlen = -1 - varlen;
5140 if (subtype == VSMINUS) {
5144 p, flag | EXP_TILDE |
5145 (quoted ? EXP_QWORD : EXP_WORD)
5154 if (subtype == VSASSIGN || subtype == VSQUESTION) {
5156 if (subevalvar(p, var, 0, subtype, startloc,
5160 * Remove any recorded regions beyond
5163 removerecordregions(startloc);
5173 if (varlen < 0 && uflag)
5174 varunset(p, var, 0, 0);
5176 if (subtype == VSLENGTH) {
5177 cvtnum(varlen > 0 ? varlen : 0);
5181 if (subtype == VSNORMAL) {
5185 recordregion(startloc, expdest - (char *)stackblock(), quoted);
5194 case VSTRIMRIGHTMAX:
5203 * Terminate the string and start recording the pattern
5206 STPUTC('\0', expdest);
5207 patloc = expdest - (char *)stackblock();
5208 if (subevalvar(p, NULL, patloc, subtype,
5209 startloc, varflags, quotes) == 0) {
5210 int amount = expdest - (
5211 (char *)stackblock() + patloc - 1
5213 STADJUST(-amount, expdest);
5215 /* Remove any recorded regions beyond start of variable */
5216 removerecordregions(startloc);
5221 if (subtype != VSNORMAL) { /* skip to end of alternative */
5224 if ((c = *p++) == CTLESC)
5226 else if (c == CTLBACKQ || c == (CTLBACKQ|CTLQUOTE)) {
5228 argbackq = argbackq->next;
5229 } else if (c == CTLVAR) {
5230 if ((*p++ & VSTYPE) != VSNORMAL)
5232 } else if (c == CTLENDVAR) {
5243 * Put a string on the stack.
5247 memtodest(const char *p, size_t len, int syntax, int quotes) {
5250 q = makestrspace(len * 2, q);
5253 int c = SC2INT(*p++);
5256 if (quotes && (SIT(c, syntax) == CCTL || SIT(c, syntax) == CBACK))
5266 strtodest(const char *p, int syntax, int quotes)
5268 memtodest(p, strlen(p), syntax, quotes);
5273 * Add the value of a specialized variable to the stack string.
5277 varvalue(char *name, int varflags, int flags)
5287 int quoted = varflags & VSQUOTE;
5288 int subtype = varflags & VSTYPE;
5289 int quotes = flags & (EXP_FULL | EXP_CASE);
5291 if (quoted && (flags & EXP_FULL))
5292 sep = 1 << CHAR_BIT;
5294 syntax = quoted ? DQSYNTAX : BASESYNTAX;
5303 num = shellparam.nparam;
5313 p = makestrspace(NOPTS, expdest);
5314 for (i = NOPTS - 1; i >= 0; i--) {
5316 USTPUTC(optletters(i), p);
5327 sep = ifsset() ? SC2INT(ifsval()[0]) : ' ';
5328 if (quotes && (SIT(sep, syntax) == CCTL || SIT(sep, syntax) == CBACK))
5331 if (!(ap = shellparam.p))
5333 while ((p = *ap++)) {
5336 partlen = strlen(p);
5339 if (!(subtype == VSPLUS || subtype == VSLENGTH))
5340 memtodest(p, partlen, syntax, quotes);
5346 if (subtype == VSPLUS || subtype == VSLENGTH) {
5368 if (num < 0 || num > shellparam.nparam)
5370 p = num ? shellparam.p[num - 1] : arg0;
5373 p = lookupvar(name);
5379 if (!(subtype == VSPLUS || subtype == VSLENGTH))
5380 memtodest(p, len, syntax, quotes);
5384 if (subtype == VSPLUS || subtype == VSLENGTH)
5385 STADJUST(-len, expdest);
5391 * Record the fact that we have to scan this region of the
5392 * string for IFS characters.
5396 recordregion(int start, int end, int nulonly)
5398 struct ifsregion *ifsp;
5400 if (ifslastp == NULL) {
5404 ifsp = (struct ifsregion *)ckmalloc(sizeof (struct ifsregion));
5406 ifslastp->next = ifsp;
5410 ifslastp->begoff = start;
5411 ifslastp->endoff = end;
5412 ifslastp->nulonly = nulonly;
5417 * Break the argument string into pieces based upon IFS and add the
5418 * strings to the argument list. The regions of the string to be
5419 * searched for IFS characters have been stored by recordregion.
5422 ifsbreakup(char *string, struct arglist *arglist)
5424 struct ifsregion *ifsp;
5429 const char *ifs, *realifs;
5435 if (ifslastp != NULL) {
5438 realifs = ifsset() ? ifsval() : defifs;
5441 p = string + ifsp->begoff;
5442 nulonly = ifsp->nulonly;
5443 ifs = nulonly ? nullstr : realifs;
5445 while (p < string + ifsp->endoff) {
5449 if (strchr(ifs, *p)) {
5451 ifsspc = (strchr(defifs, *p) != NULL);
5452 /* Ignore IFS whitespace at start */
5453 if (q == start && ifsspc) {
5459 sp = (struct strlist *)stalloc(sizeof *sp);
5461 *arglist->lastp = sp;
5462 arglist->lastp = &sp->next;
5466 if (p >= string + ifsp->endoff) {
5472 if (strchr(ifs, *p) == NULL ) {
5475 } else if (strchr(defifs, *p) == NULL) {
5491 } while ((ifsp = ifsp->next) != NULL);
5500 sp = (struct strlist *)stalloc(sizeof *sp);
5502 *arglist->lastp = sp;
5503 arglist->lastp = &sp->next;
5509 struct ifsregion *p;
5514 struct ifsregion *ifsp;
5520 ifsfirst.next = NULL;
5524 static void expmeta(char *, char *);
5525 static struct strlist *expsort(struct strlist *);
5526 static struct strlist *msort(struct strlist *, int);
5528 static char *expdir;
5532 expandmeta(struct strlist *str, int flag)
5534 static const char metachars[] = {
5537 /* TODO - EXP_REDIR */
5540 struct strlist **savelastp;
5546 if (!strpbrk(str->text, metachars))
5548 savelastp = exparg.lastp;
5551 p = preglob(str->text, 0, RMESCAPE_ALLOC | RMESCAPE_HEAP);
5553 int i = strlen(str->text);
5554 expdir = ckmalloc(i < 2048 ? 2048 : i); /* XXX */
5562 if (exparg.lastp == savelastp) {
5567 *exparg.lastp = str;
5568 rmescapes(str->text);
5569 exparg.lastp = &str->next;
5571 *exparg.lastp = NULL;
5572 *savelastp = sp = expsort(*savelastp);
5573 while (sp->next != NULL)
5575 exparg.lastp = &sp->next;
5582 * Add a file name to the list.
5586 addfname(const char *name)
5590 sp = (struct strlist *)stalloc(sizeof *sp);
5591 sp->text = sstrdup(name);
5593 exparg.lastp = &sp->next;
5598 * Do metacharacter (i.e. *, ?, [...]) expansion.
5602 expmeta(char *enddir, char *name)
5617 for (p = name; *p; p++) {
5618 if (*p == '*' || *p == '?')
5620 else if (*p == '[') {
5627 if (*q == '/' || *q == '\0')
5634 } else if (*p == '\\')
5636 else if (*p == '/') {
5643 if (metaflag == 0) { /* we've reached the end of the file name */
5644 if (enddir != expdir)
5652 if (metaflag == 0 || lstat(expdir, &statb) >= 0)
5663 } while (p < start);
5665 if (enddir == expdir) {
5667 } else if (enddir == expdir + 1 && *expdir == '/') {
5673 if ((dirp = opendir(cp)) == NULL)
5675 if (enddir != expdir)
5677 if (*endname == 0) {
5689 while (! intpending && (dp = readdir(dirp)) != NULL) {
5690 if (dp->d_name[0] == '.' && ! matchdot)
5692 if (pmatch(start, dp->d_name)) {
5694 scopy(dp->d_name, enddir);
5697 for (p = enddir, cp = dp->d_name;
5698 (*p++ = *cp++) != '\0';)
5701 expmeta(p, endname);
5711 * Sort the results of file name expansion. It calculates the number of
5712 * strings to sort and then calls msort (short for merge sort) to do the
5716 static struct strlist *
5717 expsort(struct strlist *str)
5723 for (sp = str ; sp ; sp = sp->next)
5725 return msort(str, len);
5729 static struct strlist *
5730 msort(struct strlist *list, int len)
5732 struct strlist *p, *q = NULL;
5733 struct strlist **lpp;
5741 for (n = half ; --n >= 0 ; ) {
5745 q->next = NULL; /* terminate first half of list */
5746 q = msort(list, half); /* sort first half of list */
5747 p = msort(p, len - half); /* sort second half */
5750 #ifdef CONFIG_LOCALE_SUPPORT
5751 if (strcoll(p->text, q->text) < 0)
5753 if (strcmp(p->text, q->text) < 0)
5758 if ((p = *lpp) == NULL) {
5765 if ((q = *lpp) == NULL) {
5776 * Returns true if the pattern matches the string.
5780 patmatch(char *pattern, const char *string)
5782 return pmatch(preglob(pattern, 0, 0), string);
5787 * Remove any CTLESC characters from a string.
5791 _rmescapes(char *str, int flag)
5794 static const char qchars[] = { CTLESC, CTLQUOTEMARK, 0 };
5799 p = strpbrk(str, qchars);
5805 if (flag & RMESCAPE_ALLOC) {
5806 size_t len = p - str;
5807 size_t fulllen = len + strlen(p) + 1;
5809 if (flag & RMESCAPE_GROW) {
5810 r = makestrspace(fulllen, expdest);
5811 } else if (flag & RMESCAPE_HEAP) {
5812 r = ckmalloc(fulllen);
5814 r = stalloc(fulllen);
5818 q = mempcpy(q, str, len);
5821 inquotes = (flag & RMESCAPE_QUOTED) ^ RMESCAPE_QUOTED;
5822 globbing = flag & RMESCAPE_GLOB;
5823 notescaped = globbing;
5825 if (*p == CTLQUOTEMARK) {
5826 inquotes = ~inquotes;
5828 notescaped = globbing;
5832 /* naked back slash */
5838 if (notescaped && inquotes && *p != '/') {
5842 notescaped = globbing;
5847 if (flag & RMESCAPE_GROW) {
5849 STADJUST(q - r + 1, expdest);
5856 * See if a pattern matches in a case statement.
5860 casematch(union node *pattern, char *val)
5862 struct stackmark smark;
5865 setstackmark(&smark);
5866 argbackq = pattern->narg.backquote;
5867 STARTSTACKSTR(expdest);
5869 argstr(pattern->narg.text, EXP_TILDE | EXP_CASE);
5870 STACKSTRNUL(expdest);
5871 result = patmatch(stackblock(), val);
5872 popstackmark(&smark);
5885 expdest = makestrspace(32, expdest);
5886 #ifdef CONFIG_ASH_MATH_SUPPORT_64
5887 len = fmtstr(expdest, 32, "%lld", (long long) num);
5889 len = fmtstr(expdest, 32, "%ld", num);
5891 STADJUST(len, expdest);
5896 varunset(const char *end, const char *var, const char *umsg, int varflags)
5902 msg = "parameter not set";
5904 if (*end == CTLENDVAR) {
5905 if (varflags & VSNUL)
5910 sh_error("%.*s: %s%s", end - var - 1, var, msg, tail);
5917 * This implements the input routines used by the parser.
5920 #define EOF_NLEFT -99 /* value of parsenleft when EOF pushed back */
5922 static void pushfile(void);
5925 * Read a character from the script, returning PEOF on end of file.
5926 * Nul characters in the input are silently discarded.
5930 #define pgetc_as_macro() (--parsenleft >= 0? SC2INT(*parsenextc++) : preadbuffer())
5932 #ifdef CONFIG_ASH_OPTIMIZE_FOR_SIZE
5933 #define pgetc_macro() pgetc()
5937 return pgetc_as_macro();
5940 #define pgetc_macro() pgetc_as_macro()
5944 return pgetc_macro();
5950 * Same as pgetc(), but ignores PEOA.
5952 #ifdef CONFIG_ASH_ALIAS
5953 static int pgetc2(void)
5959 } while (c == PEOA);
5963 static inline int pgetc2(void)
5965 return pgetc_macro();
5970 * Read a line from the script.
5973 static inline char *
5974 pfgets(char *line, int len)
5980 while (--nleft > 0) {
5997 #ifdef CONFIG_FEATURE_COMMAND_EDITING
5998 #ifdef CONFIG_ASH_EXPAND_PRMT
5999 static char *cmdedit_prompt;
6001 static const char *cmdedit_prompt;
6003 static inline void putprompt(const char *s)
6005 #ifdef CONFIG_ASH_EXPAND_PRMT
6006 free(cmdedit_prompt);
6007 cmdedit_prompt = bb_xstrdup(s);
6013 static inline void putprompt(const char *s)
6023 char *buf = parsefile->buf;
6027 #ifdef CONFIG_FEATURE_COMMAND_EDITING
6028 if (!iflag || parsefile->fd)
6029 nr = safe_read(parsefile->fd, buf, BUFSIZ - 1);
6031 #ifdef CONFIG_FEATURE_COMMAND_TAB_COMPLETION
6032 cmdedit_path_lookup = pathval();
6034 nr = cmdedit_read_input((char *) cmdedit_prompt, buf);
6036 /* Ctrl+C presend */
6045 if(nr < 0 && errno == 0) {
6046 /* Ctrl+D presend */
6051 nr = safe_read(parsefile->fd, buf, BUFSIZ - 1);
6055 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
6056 int flags = fcntl(0, F_GETFL, 0);
6057 if (flags >= 0 && flags & O_NONBLOCK) {
6058 flags &=~ O_NONBLOCK;
6059 if (fcntl(0, F_SETFL, flags) >= 0) {
6060 out2str("sh: turning off NDELAY mode\n");
6070 * Refill the input buffer and return the next input character:
6072 * 1) If a string was pushed back on the input, pop it;
6073 * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading
6074 * from a string so we can't refill the buffer, return EOF.
6075 * 3) If the is more stuff in this buffer, use it else call read to fill it.
6076 * 4) Process input up to the next newline, deleting nul characters.
6086 while (parsefile->strpush) {
6087 #ifdef CONFIG_ASH_ALIAS
6088 if (parsenleft == -1 && parsefile->strpush->ap &&
6089 parsenextc[-1] != ' ' && parsenextc[-1] != '\t') {
6094 if (--parsenleft >= 0)
6095 return SC2INT(*parsenextc++);
6097 if (parsenleft == EOF_NLEFT || parsefile->buf == NULL)
6104 if ((more = preadfd()) <= 0) {
6105 parselleft = parsenleft = EOF_NLEFT;
6112 /* delete nul characters */
6120 memmove(q, q + 1, more);
6124 parsenleft = q - parsenextc - 1;
6130 parsenleft = q - parsenextc - 1;
6142 out2str(parsenextc);
6147 return SC2INT(*parsenextc++);
6151 * Undo the last call to pgetc. Only one character may be pushed back.
6152 * PEOF may be pushed back.
6163 * Push a string back onto the input at this current parsefile level.
6164 * We handle aliases this way.
6167 pushstring(char *s, void *ap)
6174 /*dprintf("*** calling pushstring: %s, %d\n", s, len);*/
6175 if (parsefile->strpush) {
6176 sp = ckmalloc(sizeof (struct strpush));
6177 sp->prev = parsefile->strpush;
6178 parsefile->strpush = sp;
6180 sp = parsefile->strpush = &(parsefile->basestrpush);
6181 sp->prevstring = parsenextc;
6182 sp->prevnleft = parsenleft;
6183 #ifdef CONFIG_ASH_ALIAS
6184 sp->ap = (struct alias *)ap;
6186 ((struct alias *)ap)->flag |= ALIASINUSE;
6198 struct strpush *sp = parsefile->strpush;
6201 #ifdef CONFIG_ASH_ALIAS
6203 if (parsenextc[-1] == ' ' || parsenextc[-1] == '\t') {
6204 checkkwd |= CHKALIAS;
6206 if (sp->string != sp->ap->val) {
6209 sp->ap->flag &= ~ALIASINUSE;
6210 if (sp->ap->flag & ALIASDEAD) {
6211 unalias(sp->ap->name);
6215 parsenextc = sp->prevstring;
6216 parsenleft = sp->prevnleft;
6217 /*dprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/
6218 parsefile->strpush = sp->prev;
6219 if (sp != &(parsefile->basestrpush))
6225 * Set the input to take input from a file. If push is set, push the
6226 * old input onto the stack first.
6230 setinputfile(const char *fname, int flags)
6236 if ((fd = open(fname, O_RDONLY)) < 0) {
6237 if (flags & INPUT_NOFILE_OK)
6239 sh_error("Can't open %s", fname);
6242 fd2 = copyfd(fd, 10);
6245 sh_error("Out of file descriptors");
6248 setinputfd(fd, flags & INPUT_PUSH_FILE);
6256 * Like setinputfile, but takes an open file descriptor. Call this with
6261 setinputfd(int fd, int push)
6263 (void) fcntl(fd, F_SETFD, FD_CLOEXEC);
6269 if (parsefile->buf == NULL)
6270 parsefile->buf = ckmalloc(IBUFSIZ);
6271 parselleft = parsenleft = 0;
6277 * Like setinputfile, but takes input from a string.
6281 setinputstring(char *string)
6285 parsenextc = string;
6286 parsenleft = strlen(string);
6287 parsefile->buf = NULL;
6294 * To handle the "." command, a stack of input files is used. Pushfile
6295 * adds a new entry to the stack and popfile restores the previous level.
6301 struct parsefile *pf;
6303 parsefile->nleft = parsenleft;
6304 parsefile->lleft = parselleft;
6305 parsefile->nextc = parsenextc;
6306 parsefile->linno = plinno;
6307 pf = (struct parsefile *)ckmalloc(sizeof (struct parsefile));
6308 pf->prev = parsefile;
6311 pf->basestrpush.prev = NULL;
6319 struct parsefile *pf = parsefile;
6328 parsefile = pf->prev;
6330 parsenleft = parsefile->nleft;
6331 parselleft = parsefile->lleft;
6332 parsenextc = parsefile->nextc;
6333 plinno = parsefile->linno;
6339 * Return to top level.
6345 while (parsefile != &basepf)
6351 * Close the file(s) that the shell is reading commands from. Called
6352 * after a fork is done.
6359 if (parsefile->fd > 0) {
6360 close(parsefile->fd);
6367 /* mode flags for set_curjob */
6368 #define CUR_DELETE 2
6369 #define CUR_RUNNING 1
6370 #define CUR_STOPPED 0
6372 /* mode flags for dowait */
6373 #define DOWAIT_NORMAL 0
6374 #define DOWAIT_BLOCK 1
6377 static struct job *jobtab;
6379 static unsigned njobs;
6381 /* pgrp of shell on invocation */
6382 static int initialpgrp;
6383 static int ttyfd = -1;
6386 static struct job *curjob;
6387 /* number of presumed living untracked jobs */
6390 static void set_curjob(struct job *, unsigned);
6392 static int restartjob(struct job *, int);
6393 static void xtcsetpgrp(int, pid_t);
6394 static char *commandtext(union node *);
6395 static void cmdlist(union node *, int);
6396 static void cmdtxt(union node *);
6397 static void cmdputs(const char *);
6398 static void showpipe(struct job *, FILE *);
6400 static int sprint_status(char *, int, int);
6401 static void freejob(struct job *);
6402 static struct job *getjob(const char *, int);
6403 static struct job *growjobtab(void);
6404 static void forkchild(struct job *, union node *, int);
6405 static void forkparent(struct job *, union node *, int, pid_t);
6406 static int dowait(int, struct job *);
6407 static int getstatus(struct job *);
6410 set_curjob(struct job *jp, unsigned mode)
6413 struct job **jpp, **curp;
6415 /* first remove from list */
6416 jpp = curp = &curjob;
6421 jpp = &jp1->prev_job;
6423 *jpp = jp1->prev_job;
6425 /* Then re-insert in correct position */
6433 /* job being deleted */
6436 /* newly created job or backgrounded job,
6437 put after all stopped jobs. */
6441 if (!jp1 || jp1->state != JOBSTOPPED)
6444 jpp = &jp1->prev_job;
6450 /* newly stopped job - becomes curjob */
6451 jp->prev_job = *jpp;
6459 * Turn job control on and off.
6461 * Note: This code assumes that the third arg to ioctl is a character
6462 * pointer, which is true on Berkeley systems but not System V. Since
6463 * System V doesn't have job control yet, this isn't a problem now.
6465 * Called with interrupts off.
6474 if (on == jobctl || rootshell == 0)
6478 ofd = fd = open(_PATH_TTY, O_RDWR);
6481 while (!isatty(fd) && --fd >= 0)
6484 fd = fcntl(fd, F_DUPFD, 10);
6488 fcntl(fd, F_SETFD, FD_CLOEXEC);
6489 do { /* while we are in the background */
6490 if ((pgrp = tcgetpgrp(fd)) < 0) {
6492 sh_warnx("can't access tty; job control turned off");
6496 if (pgrp == getpgrp())
6507 xtcsetpgrp(fd, pgrp);
6509 /* turning job control off */
6512 xtcsetpgrp(fd, pgrp);
6526 killcmd(int argc, char **argv)
6537 "Usage: kill [-s sigspec | -signum | -sigspec] [pid | job]... or\n"
6538 "kill -l [exitstatus]"
6542 if (**++argv == '-') {
6543 signo = decode_signal(*argv + 1, 1);
6547 while ((c = nextopt("ls:")) != '\0')
6557 signo = decode_signal(optionarg, 1);
6560 "invalid signal number or name: %s",
6571 if (!list && signo < 0)
6574 if ((signo < 0 || !*argv) ^ list) {
6582 for (i = 1; i < NSIG; i++) {
6583 name = u_signal_names(0, &i, 1);
6585 out1fmt(snlfmt, name);
6589 name = u_signal_names(*argptr, &signo, -1);
6591 out1fmt(snlfmt, name);
6593 sh_error("invalid signal number or exit status: %s", *argptr);
6599 if (**argv == '%') {
6600 jp = getjob(*argv, 0);
6601 pid = -jp->ps[0].pid;
6603 pid = **argv == '-' ?
6604 -number(*argv + 1) : number(*argv);
6606 if (kill(pid, signo) != 0) {
6607 sh_warnx("(%d) - %m", pid);
6616 #if defined(JOBS) || defined(DEBUG)
6618 jobno(const struct job *jp)
6620 return jp - jobtab + 1;
6626 fgcmd(int argc, char **argv)
6633 mode = (**argv == 'f') ? FORK_FG : FORK_BG;
6638 jp = getjob(*argv, 1);
6639 if (mode == FORK_BG) {
6640 set_curjob(jp, CUR_RUNNING);
6641 fprintf(out, "[%d] ", jobno(jp));
6643 outstr(jp->ps->cmd, out);
6645 retval = restartjob(jp, mode);
6646 } while (*argv && *++argv);
6650 static int bgcmd(int, char **) __attribute__((__alias__("fgcmd")));
6654 restartjob(struct job *jp, int mode)
6656 struct procstat *ps;
6662 if (jp->state == JOBDONE)
6664 jp->state = JOBRUNNING;
6666 if (mode == FORK_FG)
6667 xtcsetpgrp(ttyfd, pgid);
6668 killpg(pgid, SIGCONT);
6672 if (WIFSTOPPED(ps->status)) {
6675 } while (ps++, --i);
6677 status = (mode == FORK_FG) ? waitforjob(jp) : 0;
6684 sprint_status(char *s, int status, int sigonly)
6690 if (!WIFEXITED(status)) {
6692 if (WIFSTOPPED(status))
6693 st = WSTOPSIG(status);
6696 st = WTERMSIG(status);
6698 if (st == SIGINT || st == SIGPIPE)
6701 if (WIFSTOPPED(status))
6706 col = fmtstr(s, 32, strsignal(st));
6707 if (WCOREDUMP(status)) {
6708 col += fmtstr(s + col, 16, " (core dumped)");
6710 } else if (!sigonly) {
6711 st = WEXITSTATUS(status);
6713 col = fmtstr(s, 16, "Done(%d)", st);
6715 col = fmtstr(s, 16, "Done");
6724 showjob(FILE *out, struct job *jp, int mode)
6726 struct procstat *ps;
6727 struct procstat *psend;
6734 if (mode & SHOW_PGID) {
6735 /* just output process (group) id of pipeline */
6736 fprintf(out, "%d\n", ps->pid);
6740 col = fmtstr(s, 16, "[%d] ", jobno(jp));
6745 else if (curjob && jp == curjob->prev_job)
6748 if (mode & SHOW_PID)
6749 col += fmtstr(s + col, 16, "%d ", ps->pid);
6751 psend = ps + jp->nprocs;
6753 if (jp->state == JOBRUNNING) {
6754 scopy("Running", s + col);
6755 col += strlen("Running");
6757 int status = psend[-1].status;
6759 if (jp->state == JOBSTOPPED)
6760 status = jp->stopstatus;
6762 col += sprint_status(s + col, status, 0);
6768 /* for each process */
6769 col = fmtstr(s, 48, " |\n%*c%d ", indent, ' ', ps->pid) - 3;
6772 fprintf(out, "%s%*c%s",
6773 s, 33 - col >= 0 ? 33 - col : 0, ' ', ps->cmd
6775 if (!(mode & SHOW_PID)) {
6779 if (++ps == psend) {
6780 outcslow('\n', out);
6787 if (jp->state == JOBDONE) {
6788 TRACE(("showjob: freeing job %d\n", jobno(jp)));
6795 jobscmd(int argc, char **argv)
6801 while ((m = nextopt("lp")))
6811 showjob(out, getjob(*argv,0), mode);
6814 showjobs(out, mode);
6821 * Print a list of jobs. If "change" is nonzero, only print jobs whose
6822 * statuses have changed since the last call to showjobs.
6826 showjobs(FILE *out, int mode)
6830 TRACE(("showjobs(%x) called\n", mode));
6832 /* If not even one one job changed, there is nothing to do */
6833 while (dowait(DOWAIT_NORMAL, NULL) > 0)
6836 for (jp = curjob; jp; jp = jp->prev_job) {
6837 if (!(mode & SHOW_CHANGED) || jp->changed)
6838 showjob(out, jp, mode);
6844 * Mark a job structure as unused.
6848 freejob(struct job *jp)
6850 struct procstat *ps;
6854 for (i = jp->nprocs, ps = jp->ps ; --i >= 0 ; ps++) {
6855 if (ps->cmd != nullstr)
6858 if (jp->ps != &jp->ps0)
6861 set_curjob(jp, CUR_DELETE);
6867 waitcmd(int argc, char **argv)
6880 /* wait for all jobs */
6885 /* no running procs */
6888 if (jp->state == JOBRUNNING)
6893 dowait(DOWAIT_BLOCK, 0);
6899 if (**argv != '%') {
6900 pid_t pid = number(*argv);
6904 if (job->ps[job->nprocs - 1].pid == pid)
6906 job = job->prev_job;
6912 job = getjob(*argv, 0);
6913 /* loop until process terminated or stopped */
6914 while (job->state == JOBRUNNING)
6915 dowait(DOWAIT_BLOCK, 0);
6917 retval = getstatus(job);
6928 * Convert a job name to a job structure.
6932 getjob(const char *name, int getctl)
6936 const char *err_msg = "No such job: %s";
6940 char *(*match)(const char *, const char *);
6955 if (c == '+' || c == '%') {
6957 err_msg = "No current job";
6959 } else if (c == '-') {
6962 err_msg = "No previous job";
6973 jp = jobtab + num - 1;
6990 if (match(jp->ps[0].cmd, p)) {
6994 err_msg = "%s: ambiguous";
7001 err_msg = "job %s not created under job control";
7002 if (getctl && jp->jobctl == 0)
7007 sh_error(err_msg, name);
7012 * Return a new job structure.
7013 * Called with interrupts off.
7017 makejob(union node *node, int nprocs)
7022 for (i = njobs, jp = jobtab ; ; jp++) {
7029 if (jp->state != JOBDONE || !jp->waited)
7038 memset(jp, 0, sizeof(*jp));
7043 jp->prev_job = curjob;
7048 jp->ps = ckmalloc(nprocs * sizeof (struct procstat));
7050 TRACE(("makejob(0x%lx, %d) returns %%%d\n", (long)node, nprocs,
7060 struct job *jp, *jq;
7062 len = njobs * sizeof(*jp);
7064 jp = ckrealloc(jq, len + 4 * sizeof(*jp));
7066 offset = (char *)jp - (char *)jq;
7068 /* Relocate pointers */
7071 jq = (struct job *)((char *)jq + l);
7075 #define joff(p) ((struct job *)((char *)(p) + l))
7076 #define jmove(p) (p) = (void *)((char *)(p) + offset)
7077 if (xlikely(joff(jp)->ps == &jq->ps0))
7078 jmove(joff(jp)->ps);
7079 if (joff(jp)->prev_job)
7080 jmove(joff(jp)->prev_job);
7090 jp = (struct job *)((char *)jp + len);
7094 } while (--jq >= jp);
7100 * Fork off a subshell. If we are doing job control, give the subshell its
7101 * own process group. Jp is a job structure that the job is to be added to.
7102 * N is the command that will be evaluated by the child. Both jp and n may
7103 * be NULL. The mode parameter can be one of the following:
7104 * FORK_FG - Fork off a foreground process.
7105 * FORK_BG - Fork off a background process.
7106 * FORK_NOJOB - Like FORK_FG, but don't give the process its own
7107 * process group even if job control is on.
7109 * When job control is turned off, background processes have their standard
7110 * input redirected to /dev/null (except for the second and later processes
7113 * Called with interrupts off.
7117 forkchild(struct job *jp, union node *n, int mode)
7121 TRACE(("Child shell %d\n", getpid()));
7128 /* do job control only in root shell */
7130 if (mode != FORK_NOJOB && jp->jobctl && !oldlvl) {
7133 if (jp->nprocs == 0)
7136 pgrp = jp->ps[0].pid;
7137 /* This can fail because we are doing it in the parent also */
7138 (void)setpgid(0, pgrp);
7139 if (mode == FORK_FG)
7140 xtcsetpgrp(ttyfd, pgrp);
7145 if (mode == FORK_BG) {
7148 if (jp->nprocs == 0) {
7150 if (open(bb_dev_null, O_RDONLY) != 0)
7151 sh_error("Can't open %s", bb_dev_null);
7154 if (!oldlvl && iflag) {
7159 for (jp = curjob; jp; jp = jp->prev_job)
7165 forkparent(struct job *jp, union node *n, int mode, pid_t pid)
7167 TRACE(("In parent shell: child = %d\n", pid));
7169 while (jobless && dowait(DOWAIT_NORMAL, 0) > 0);
7174 if (mode != FORK_NOJOB && jp->jobctl) {
7177 if (jp->nprocs == 0)
7180 pgrp = jp->ps[0].pid;
7181 /* This can fail because we are doing it in the child also */
7182 (void)setpgid(pid, pgrp);
7185 if (mode == FORK_BG) {
7186 backgndpid = pid; /* set $! */
7187 set_curjob(jp, CUR_RUNNING);
7190 struct procstat *ps = &jp->ps[jp->nprocs++];
7196 ps->cmd = commandtext(n);
7202 forkshell(struct job *jp, union node *n, int mode)
7206 TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode));
7209 TRACE(("Fork failed, errno=%d", errno));
7212 sh_error("Cannot fork");
7215 forkchild(jp, n, mode);
7217 forkparent(jp, n, mode, pid);
7222 * Wait for job to finish.
7224 * Under job control we have the problem that while a child process is
7225 * running interrupts generated by the user are sent to the child but not
7226 * to the shell. This means that an infinite loop started by an inter-
7227 * active user may be hard to kill. With job control turned off, an
7228 * interactive user may place an interactive program inside a loop. If
7229 * the interactive program catches interrupts, the user doesn't want
7230 * these interrupts to also abort the loop. The approach we take here
7231 * is to have the shell ignore interrupt signals while waiting for a
7232 * foreground process to terminate, and then send itself an interrupt
7233 * signal if the child process was terminated by an interrupt signal.
7234 * Unfortunately, some programs want to do a bit of cleanup and then
7235 * exit on interrupt; unless these processes terminate themselves by
7236 * sending a signal to themselves (instead of calling exit) they will
7237 * confuse this approach.
7239 * Called with interrupts off.
7243 waitforjob(struct job *jp)
7247 TRACE(("waitforjob(%%%d) called\n", jobno(jp)));
7248 while (jp->state == JOBRUNNING) {
7249 dowait(DOWAIT_BLOCK, jp);
7254 xtcsetpgrp(ttyfd, rootpid);
7256 * This is truly gross.
7257 * If we're doing job control, then we did a TIOCSPGRP which
7258 * caused us (the shell) to no longer be in the controlling
7259 * session -- so we wouldn't have seen any ^C/SIGINT. So, we
7260 * intuit from the subprocess exit status whether a SIGINT
7261 * occurred, and if so interrupt ourselves. Yuck. - mycroft
7266 if (jp->state == JOBDONE)
7274 * Do a wait system call. If job control is compiled in, we accept
7275 * stopped processes. If block is zero, we return a value of zero
7276 * rather than blocking.
7278 * System V doesn't have a non-blocking wait system call. It does
7279 * have a SIGCLD signal that is sent to a process when one of it's
7280 * children dies. The obvious way to use SIGCLD would be to install
7281 * a handler for SIGCLD which simply bumped a counter when a SIGCLD
7282 * was received, and have waitproc bump another counter when it got
7283 * the status of a process. Waitproc would then know that a wait
7284 * system call would not block if the two counters were different.
7285 * This approach doesn't work because if a process has children that
7286 * have not been waited for, System V will send it a SIGCLD when it
7287 * installs a signal handler for SIGCLD. What this means is that when
7288 * a child exits, the shell will be sent SIGCLD signals continuously
7289 * until is runs out of stack space, unless it does a wait call before
7290 * restoring the signal handler. The code below takes advantage of
7291 * this (mis)feature by installing a signal handler for SIGCLD and
7292 * then checking to see whether it was called. If there are any
7293 * children to be waited for, it will be.
7295 * If neither SYSV nor BSD is defined, we don't implement nonblocking
7296 * waits at all. In this case, the user will not be informed when
7297 * a background process until the next time she runs a real program
7298 * (as opposed to running a builtin command or just typing return),
7299 * and the jobs command may give out of date information.
7303 waitproc(int block, int *status)
7313 return wait3(status, flags, (struct rusage *)NULL);
7317 * Wait for a process to terminate.
7321 dowait(int block, struct job *job)
7326 struct job *thisjob;
7329 TRACE(("dowait(%d) called\n", block));
7330 pid = waitproc(block, &status);
7331 TRACE(("wait returns pid %d, status=%d\n", pid, status));
7336 for (jp = curjob; jp; jp = jp->prev_job) {
7337 struct procstat *sp;
7338 struct procstat *spend;
7339 if (jp->state == JOBDONE)
7342 spend = jp->ps + jp->nprocs;
7345 if (sp->pid == pid) {
7346 TRACE(("Job %d: changing status of proc %d from 0x%x to 0x%x\n", jobno(jp), pid, sp->status, status));
7347 sp->status = status;
7350 if (sp->status == -1)
7353 if (state == JOBRUNNING)
7355 if (WIFSTOPPED(sp->status)) {
7356 jp->stopstatus = sp->status;
7360 } while (++sp < spend);
7365 if (!WIFSTOPPED(status))
7372 if (state != JOBRUNNING) {
7373 thisjob->changed = 1;
7375 if (thisjob->state != state) {
7376 TRACE(("Job %d: changing state from %d to %d\n", jobno(thisjob), thisjob->state, state));
7377 thisjob->state = state;
7379 if (state == JOBSTOPPED) {
7380 set_curjob(thisjob, CUR_STOPPED);
7389 if (thisjob && thisjob == job) {
7393 len = sprint_status(s, status, 1);
7405 * return 1 if there are stopped jobs, otherwise 0
7418 if (jp && jp->state == JOBSTOPPED) {
7419 out2str("You have stopped jobs.\n");
7429 * Return a string identifying a command (to be printed by the
7434 static char *cmdnextc;
7437 commandtext(union node *n)
7441 STARTSTACKSTR(cmdnextc);
7443 name = stackblock();
7444 TRACE(("commandtext: name %p, end %p\n\t\"%s\"\n",
7445 name, cmdnextc, cmdnextc));
7446 return savestr(name);
7450 cmdtxt(union node *n)
7453 struct nodelist *lp;
7465 lp = n->npipe.cmdlist;
7483 cmdtxt(n->nbinary.ch1);
7499 cmdtxt(n->nif.test);
7502 if (n->nif.elsepart) {
7505 n = n->nif.elsepart;
7521 cmdtxt(n->nbinary.ch1);
7531 cmdputs(n->nfor.var);
7533 cmdlist(n->nfor.args, 1);
7538 cmdputs(n->narg.text);
7542 cmdlist(n->ncmd.args, 1);
7543 cmdlist(n->ncmd.redirect, 0);
7556 cmdputs(n->ncase.expr->narg.text);
7558 for (np = n->ncase.cases; np; np = np->nclist.next) {
7559 cmdtxt(np->nclist.pattern);
7561 cmdtxt(np->nclist.body);
7587 s[0] = n->nfile.fd + '0';
7591 if (n->type == NTOFD || n->type == NFROMFD) {
7592 s[0] = n->ndup.dupfd + '0';
7603 cmdlist(union node *np, int sep)
7605 for (; np; np = np->narg.next) {
7609 if (sep && np->narg.next)
7615 cmdputs(const char *s)
7617 const char *p, *str;
7618 char c, cc[2] = " ";
7622 static const char vstype[VSTYPE + 1][4] = {
7623 "", "}", "-", "+", "?", "=",
7624 "%", "%%", "#", "##"
7626 nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc);
7628 while ((c = *p++) != 0) {
7636 if ((subtype & VSTYPE) == VSLENGTH)
7640 if (!(subtype & VSQUOTE) != !(quoted & 1)) {
7647 str = "\"}" + !(quoted & 1);
7654 case CTLBACKQ+CTLQUOTE:
7657 #ifdef CONFIG_ASH_MATH_SUPPORT
7672 if ((subtype & VSTYPE) != VSNORMAL)
7674 str = vstype[subtype & VSTYPE];
7675 if (subtype & VSNUL)
7684 /* These can only happen inside quotes */
7697 while ((c = *str++)) {
7702 USTPUTC('"', nextc);
7710 showpipe(struct job *jp, FILE *out)
7712 struct procstat *sp;
7713 struct procstat *spend;
7715 spend = jp->ps + jp->nprocs;
7716 for (sp = jp->ps + 1; sp < spend; sp++)
7717 fprintf(out, " | %s", sp->cmd);
7718 outcslow('\n', out);
7723 xtcsetpgrp(int fd, pid_t pgrp)
7725 if (tcsetpgrp(fd, pgrp))
7726 sh_error("Cannot set tty process group (%m)");
7731 getstatus(struct job *job) {
7735 status = job->ps[job->nprocs - 1].status;
7736 retval = WEXITSTATUS(status);
7737 if (!WIFEXITED(status)) {
7739 retval = WSTOPSIG(status);
7740 if (!WIFSTOPPED(status))
7743 /* XXX: limits number of signals */
7744 retval = WTERMSIG(status);
7746 if (retval == SIGINT)
7752 TRACE(("getstatus: job %d, nproc %d, status %x, retval %x\n",
7753 jobno(job), job->nprocs, status, retval));
7757 #ifdef CONFIG_ASH_MAIL
7761 * Routines to check for mail. (Perhaps make part of main.c?)
7764 #define MAXMBOXES 10
7766 /* times of mailboxes */
7767 static time_t mailtime[MAXMBOXES];
7768 /* Set if MAIL or MAILPATH is changed. */
7769 static int mail_var_path_changed;
7774 * Print appropriate message(s) if mail has arrived.
7775 * If mail_var_path_changed is set,
7776 * then the value of MAIL has mail_var_path_changed,
7777 * so we just update the values.
7787 struct stackmark smark;
7790 setstackmark(&smark);
7791 mpath = mpathset() ? mpathval() : mailval();
7792 for (mtp = mailtime; mtp < mailtime + MAXMBOXES; mtp++) {
7793 p = padvance(&mpath, nullstr);
7798 for (q = p ; *q ; q++);
7803 q[-1] = '\0'; /* delete trailing '/' */
7804 if (stat(p, &statb) < 0) {
7808 if (!mail_var_path_changed && statb.st_mtime != *mtp) {
7811 pathopt ? pathopt : "you have mail"
7814 *mtp = statb.st_mtime;
7816 mail_var_path_changed = 0;
7817 popstackmark(&smark);
7822 changemail(const char *val)
7824 mail_var_path_changed++;
7827 #endif /* CONFIG_ASH_MAIL */
7833 static short profile_buf[16384];
7837 static int isloginsh;
7839 static void read_profile(const char *);
7842 * Main routine. We initialize things, parse the arguments, execute
7843 * profiles if we're a login shell, and then call cmdloop to execute
7844 * commands. The setjmp call sets up the location to jump to when an
7845 * exception occurs. When an exception occurs the variable "state"
7846 * is used to figure out how far we had gotten.
7850 ash_main(int argc, char **argv)
7854 struct jmploc jmploc;
7855 struct stackmark smark;
7858 dash_errno = __errno_location();
7862 monitor(4, etext, profile_buf, sizeof profile_buf, 50);
7865 if (setjmp(jmploc.loc)) {
7875 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl)
7879 outcslow('\n', stderr);
7881 popstackmark(&smark);
7882 FORCEINTON; /* enable interrupts */
7895 trputs("Shell args: "); trargs(argv);
7899 #ifdef CONFIG_ASH_RANDOM_SUPPORT
7900 rseed = rootpid + ((time_t)time((time_t *)0));
7903 setstackmark(&smark);
7904 procargs(argc, argv);
7905 #ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
7907 const char *hp = lookupvar("HISTFILE");
7910 hp = lookupvar("HOME");
7912 char *defhp = concat_path_file(hp, ".ash_history");
7913 setvar("HISTFILE", defhp, 0);
7919 if (argv[0] && argv[0][0] == '-')
7923 read_profile("/etc/profile");
7926 read_profile(".profile");
7932 getuid() == geteuid() && getgid() == getegid() &&
7936 if ((shinit = lookupvar("ENV")) != NULL && *shinit != '\0') {
7937 read_profile(shinit);
7943 evalstring(minusc, 0);
7945 if (sflag || minusc == NULL) {
7946 #ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
7948 const char *hp = lookupvar("HISTFILE");
7951 load_history ( hp );
7954 state4: /* XXX ??? - why isn't this before the "if" statement */
7962 extern void _mcleanup(void);
7972 * Read and execute commands. "Top" is nonzero for the top level command
7973 * loop; it turns on prompting if the shell is interactive.
7980 struct stackmark smark;
7984 TRACE(("cmdloop(%d) called\n", top));
7988 setstackmark(&smark);
7991 showjobs(stderr, SHOW_CHANGED);
7996 #ifdef CONFIG_ASH_MAIL
8000 n = parsecmd(inter);
8001 /* showtree(n); DEBUG */
8003 if (!top || numeof >= 50)
8005 if (!stoppedjobs()) {
8008 out2str("\nUse \"exit\" to leave shell.\n");
8011 } else if (nflag == 0) {
8012 job_warning = (job_warning == 2) ? 1 : 0;
8016 popstackmark(&smark);
8021 return skip & SKIPEVAL;
8030 * Read /etc/profile or .profile. Return on error.
8034 read_profile(const char *name)
8038 if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
8050 * Read a file containing shell functions.
8054 readcmdfile(char *name)
8056 setinputfile(name, INPUT_PUSH_FILE);
8063 * Take commands from a file. To be compatible we should do a path
8064 * search for the file, which is necessary to find sub-commands.
8067 static inline char *
8068 find_dot_file(char *name)
8071 const char *path = pathval();
8074 /* don't try this for absolute or relative paths */
8075 if (strchr(name, '/'))
8078 while ((fullname = padvance(&path, name)) != NULL) {
8079 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
8081 * Don't bother freeing here, since it will
8082 * be freed by the caller.
8086 stunalloc(fullname);
8089 /* not found in the PATH */
8090 sh_error(not_found_msg, name);
8094 static int dotcmd(int argc, char **argv)
8097 volatile struct shparam saveparam;
8100 for (sp = cmdenviron; sp; sp = sp->next)
8101 setvareq(bb_xstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
8103 if (argc >= 2) { /* That's what SVR2 does */
8106 fullname = find_dot_file(argv[1]);
8109 saveparam = shellparam;
8110 shellparam.malloc = 0;
8111 shellparam.nparam = argc - 2;
8112 shellparam.p = argv + 2;
8115 setinputfile(fullname, INPUT_PUSH_FILE);
8116 commandname = fullname;
8121 freeparam(&shellparam);
8122 shellparam = saveparam;
8124 status = exitstatus;
8131 exitcmd(int argc, char **argv)
8136 exitstatus = number(argv[1]);
8141 #ifdef CONFIG_ASH_BUILTIN_ECHO
8143 echocmd(int argc, char **argv)
8145 return bb_echo(argc, argv);
8151 * Same for malloc, realloc, but returns an error when out of space.
8155 ckrealloc(pointer p, size_t nbytes)
8157 p = realloc(p, nbytes);
8159 sh_error(bb_msg_memory_exhausted);
8164 ckmalloc(size_t nbytes)
8166 return ckrealloc(NULL, nbytes);
8170 * Make a copy of a string in safe storage.
8174 savestr(const char *s)
8176 char *p = strdup(s);
8178 sh_error(bb_msg_memory_exhausted);
8184 * Parse trees for commands are allocated in lifo order, so we use a stack
8185 * to make this more efficient, and also to avoid all sorts of exception
8186 * handling code to handle interrupts in the middle of a parse.
8188 * The size 504 was chosen because the Ultrix malloc handles that size
8194 stalloc(size_t nbytes)
8199 aligned = SHELL_ALIGN(nbytes);
8200 if (aligned > stacknleft) {
8203 struct stack_block *sp;
8205 blocksize = aligned;
8206 if (blocksize < MINSIZE)
8207 blocksize = MINSIZE;
8208 len = sizeof(struct stack_block) - MINSIZE + blocksize;
8209 if (len < blocksize)
8210 sh_error(bb_msg_memory_exhausted);
8214 stacknxt = sp->space;
8215 stacknleft = blocksize;
8216 sstrend = stacknxt + blocksize;
8221 stacknxt += aligned;
8222 stacknleft -= aligned;
8228 stunalloc(pointer p)
8231 if (!p || (stacknxt < (char *)p) || ((char *)p < stackp->space)) {
8232 write(2, "stunalloc\n", 10);
8236 stacknleft += stacknxt - (char *)p;
8242 setstackmark(struct stackmark *mark)
8244 mark->stackp = stackp;
8245 mark->stacknxt = stacknxt;
8246 mark->stacknleft = stacknleft;
8247 mark->marknext = markp;
8253 popstackmark(struct stackmark *mark)
8255 struct stack_block *sp;
8258 markp = mark->marknext;
8259 while (stackp != mark->stackp) {
8264 stacknxt = mark->stacknxt;
8265 stacknleft = mark->stacknleft;
8266 sstrend = mark->stacknxt + mark->stacknleft;
8272 * When the parser reads in a string, it wants to stick the string on the
8273 * stack and only adjust the stack pointer when it knows how big the
8274 * string is. Stackblock (defined in stack.h) returns a pointer to a block
8275 * of space on top of the stack and stackblocklen returns the length of
8276 * this block. Growstackblock will grow this space by at least one byte,
8277 * possibly moving it (like realloc). Grabstackblock actually allocates the
8278 * part of the block that has been used.
8282 growstackblock(void)
8286 newlen = stacknleft * 2;
8287 if (newlen < stacknleft)
8288 sh_error(bb_msg_memory_exhausted);
8292 if (stacknxt == stackp->space && stackp != &stackbase) {
8293 struct stack_block *oldstackp;
8294 struct stackmark *xmark;
8295 struct stack_block *sp;
8296 struct stack_block *prevstackp;
8302 prevstackp = sp->prev;
8303 grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
8304 sp = ckrealloc((pointer)sp, grosslen);
8305 sp->prev = prevstackp;
8307 stacknxt = sp->space;
8308 stacknleft = newlen;
8309 sstrend = sp->space + newlen;
8312 * Stack marks pointing to the start of the old block
8313 * must be relocated to point to the new block
8316 while (xmark != NULL && xmark->stackp == oldstackp) {
8317 xmark->stackp = stackp;
8318 xmark->stacknxt = stacknxt;
8319 xmark->stacknleft = stacknleft;
8320 xmark = xmark->marknext;
8324 char *oldspace = stacknxt;
8325 int oldlen = stacknleft;
8326 char *p = stalloc(newlen);
8328 /* free the space we just allocated */
8329 stacknxt = memcpy(p, oldspace, oldlen);
8330 stacknleft += newlen;
8335 grabstackblock(size_t len)
8337 len = SHELL_ALIGN(len);
8343 * The following routines are somewhat easier to use than the above.
8344 * The user declares a variable of type STACKSTR, which may be declared
8345 * to be a register. The macro STARTSTACKSTR initializes things. Then
8346 * the user uses the macro STPUTC to add characters to the string. In
8347 * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
8348 * grown as necessary. When the user is done, she can just leave the
8349 * string there and refer to it using stackblock(). Or she can allocate
8350 * the space for it using grabstackstr(). If it is necessary to allow
8351 * someone else to use the stack temporarily and then continue to grow
8352 * the string, the user should use grabstack to allocate the space, and
8353 * then call ungrabstr(p) to return to the previous mode of operation.
8355 * USTPUTC is like STPUTC except that it doesn't check for overflow.
8356 * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
8357 * is space for at least one character.
8363 size_t len = stackblocksize();
8364 if (herefd >= 0 && len >= 1024) {
8365 bb_full_write(herefd, stackblock(), len);
8366 return stackblock();
8369 return stackblock() + len;
8373 * Called from CHECKSTRSPACE.
8377 makestrspace(size_t newlen, char *p)
8379 size_t len = p - stacknxt;
8380 size_t size = stackblocksize();
8385 size = stackblocksize();
8387 if (nleft >= newlen)
8391 return stackblock() + len;
8395 stnputs(const char *s, size_t n, char *p)
8397 p = makestrspace(n, p);
8398 p = mempcpy(p, s, n);
8403 stputs(const char *s, char *p)
8405 return stnputs(s, strlen(s), p);
8413 * number(s) Convert a string of digits to an integer.
8414 * is_number(s) Return true if s is a string of digits.
8418 * prefix -- see if pfx is a prefix of string.
8422 prefix(const char *string, const char *pfx)
8425 if (*pfx++ != *string++)
8428 return (char *) string;
8433 * Convert a string of digits to an integer, printing an error message on
8438 number(const char *s)
8442 sh_error(illnum, s);
8448 * Check for a valid number. This should be elsewhere.
8452 is_number(const char *p)
8457 } while (*++p != '\0');
8463 * Produce a possibly single quoted string suitable as input to the shell.
8464 * The return string is allocated on the stack.
8468 single_quote(const char *s) {
8477 len = strchrnul(s, '\'') - s;
8479 q = p = makestrspace(len + 3, p);
8482 q = mempcpy(q, s, len);
8488 len = strspn(s, "'");
8492 q = p = makestrspace(len + 3, p);
8495 q = mempcpy(q, s, len);
8504 return stackblock();
8508 * Like strdup but works with the ash stack.
8512 sstrdup(const char *p)
8514 size_t len = strlen(p) + 1;
8515 return memcpy(stalloc(len), p, len);
8520 calcsize(union node *n)
8524 funcblocksize += nodesize[n->type];
8527 calcsize(n->ncmd.redirect);
8528 calcsize(n->ncmd.args);
8529 calcsize(n->ncmd.assign);
8532 sizenodelist(n->npipe.cmdlist);
8537 calcsize(n->nredir.redirect);
8538 calcsize(n->nredir.n);
8545 calcsize(n->nbinary.ch2);
8546 calcsize(n->nbinary.ch1);
8549 calcsize(n->nif.elsepart);
8550 calcsize(n->nif.ifpart);
8551 calcsize(n->nif.test);
8554 funcstringsize += strlen(n->nfor.var) + 1;
8555 calcsize(n->nfor.body);
8556 calcsize(n->nfor.args);
8559 calcsize(n->ncase.cases);
8560 calcsize(n->ncase.expr);
8563 calcsize(n->nclist.body);
8564 calcsize(n->nclist.pattern);
8565 calcsize(n->nclist.next);
8569 sizenodelist(n->narg.backquote);
8570 funcstringsize += strlen(n->narg.text) + 1;
8571 calcsize(n->narg.next);
8578 calcsize(n->nfile.fname);
8579 calcsize(n->nfile.next);
8583 calcsize(n->ndup.vname);
8584 calcsize(n->ndup.next);
8588 calcsize(n->nhere.doc);
8589 calcsize(n->nhere.next);
8592 calcsize(n->nnot.com);
8599 sizenodelist(struct nodelist *lp)
8602 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
8610 copynode(union node *n)
8617 funcblock = (char *) funcblock + nodesize[n->type];
8620 new->ncmd.redirect = copynode(n->ncmd.redirect);
8621 new->ncmd.args = copynode(n->ncmd.args);
8622 new->ncmd.assign = copynode(n->ncmd.assign);
8625 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
8626 new->npipe.backgnd = n->npipe.backgnd;
8631 new->nredir.redirect = copynode(n->nredir.redirect);
8632 new->nredir.n = copynode(n->nredir.n);
8639 new->nbinary.ch2 = copynode(n->nbinary.ch2);
8640 new->nbinary.ch1 = copynode(n->nbinary.ch1);
8643 new->nif.elsepart = copynode(n->nif.elsepart);
8644 new->nif.ifpart = copynode(n->nif.ifpart);
8645 new->nif.test = copynode(n->nif.test);
8648 new->nfor.var = nodesavestr(n->nfor.var);
8649 new->nfor.body = copynode(n->nfor.body);
8650 new->nfor.args = copynode(n->nfor.args);
8653 new->ncase.cases = copynode(n->ncase.cases);
8654 new->ncase.expr = copynode(n->ncase.expr);
8657 new->nclist.body = copynode(n->nclist.body);
8658 new->nclist.pattern = copynode(n->nclist.pattern);
8659 new->nclist.next = copynode(n->nclist.next);
8663 new->narg.backquote = copynodelist(n->narg.backquote);
8664 new->narg.text = nodesavestr(n->narg.text);
8665 new->narg.next = copynode(n->narg.next);
8672 new->nfile.fname = copynode(n->nfile.fname);
8673 new->nfile.fd = n->nfile.fd;
8674 new->nfile.next = copynode(n->nfile.next);
8678 new->ndup.vname = copynode(n->ndup.vname);
8679 new->ndup.dupfd = n->ndup.dupfd;
8680 new->ndup.fd = n->ndup.fd;
8681 new->ndup.next = copynode(n->ndup.next);
8685 new->nhere.doc = copynode(n->nhere.doc);
8686 new->nhere.fd = n->nhere.fd;
8687 new->nhere.next = copynode(n->nhere.next);
8690 new->nnot.com = copynode(n->nnot.com);
8693 new->type = n->type;
8698 static struct nodelist *
8699 copynodelist(struct nodelist *lp)
8701 struct nodelist *start;
8702 struct nodelist **lpp;
8707 funcblock = (char *) funcblock +
8708 SHELL_ALIGN(sizeof(struct nodelist));
8709 (*lpp)->n = copynode(lp->n);
8711 lpp = &(*lpp)->next;
8719 nodesavestr(char *s)
8721 char *rtn = funcstring;
8723 funcstring = stpcpy(funcstring, s) + 1;
8729 * Free a parse tree.
8733 freefunc(struct funcnode *f)
8735 if (f && --f->count < 0)
8740 static void options(int);
8741 static void setoption(int, int);
8745 * Process the shell command line arguments.
8749 procargs(int argc, char **argv)
8752 const char *xminusc;
8759 for (i = 0; i < NOPTS; i++)
8765 if (*xargv == NULL) {
8767 sh_error("-c requires an argument");
8770 if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
8774 for (i = 0; i < NOPTS; i++)
8775 if (optlist[i] == 2)
8780 /* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
8785 } else if (!sflag) {
8786 setinputfile(*xargv, 0);
8792 shellparam.p = xargv;
8793 #ifdef CONFIG_ASH_GETOPTS
8794 shellparam.optind = 1;
8795 shellparam.optoff = -1;
8797 /* assert(shellparam.malloc == 0 && shellparam.nparam == 0); */
8799 shellparam.nparam++;
8812 setinteractive(iflag);
8818 minus_o(char *name, int val)
8823 out1str("Current option settings\n");
8824 for (i = 0; i < NOPTS; i++)
8825 out1fmt("%-16s%s\n", optnames(i),
8826 optlist[i] ? "on" : "off");
8828 for (i = 0; i < NOPTS; i++)
8829 if (equal(name, optnames(i))) {
8833 sh_error("Illegal option -o %s", name);
8838 * Process shell options. The global variable argptr contains a pointer
8839 * to the argument list; we advance it past the options.
8843 options(int cmdline)
8851 while ((p = *argptr) != NULL) {
8853 if ((c = *p++) == '-') {
8855 if (p[0] == '\0' || (p[0] == '-' && p[1] == '\0')) {
8857 /* "-" means turn off -x and -v */
8860 /* "--" means reset params */
8861 else if (*argptr == NULL)
8864 break; /* "-" or "--" terminates options */
8866 } else if (c == '+') {
8872 while ((c = *p++) != '\0') {
8873 if (c == 'c' && cmdline) {
8874 minusc = p; /* command is after shell args*/
8875 } else if (c == 'o') {
8876 minus_o(*argptr, val);
8879 } else if (cmdline && (c == '-')) { // long options
8880 if (strcmp(p, "login") == 0)
8892 setoption(int flag, int val)
8896 for (i = 0; i < NOPTS; i++)
8897 if (optletters(i) == flag) {
8901 sh_error("Illegal option -%c", flag);
8908 * Set the shell parameters.
8912 setparam(char **argv)
8918 for (nparam = 0 ; argv[nparam] ; nparam++);
8919 ap = newparam = ckmalloc((nparam + 1) * sizeof *ap);
8921 *ap++ = savestr(*argv++);
8924 freeparam(&shellparam);
8925 shellparam.malloc = 1;
8926 shellparam.nparam = nparam;
8927 shellparam.p = newparam;
8928 #ifdef CONFIG_ASH_GETOPTS
8929 shellparam.optind = 1;
8930 shellparam.optoff = -1;
8936 * Free the list of positional parameters.
8940 freeparam(volatile struct shparam *param)
8944 if (param->malloc) {
8945 for (ap = param->p ; *ap ; ap++)
8954 * The shift builtin command.
8958 shiftcmd(int argc, char **argv)
8965 n = number(argv[1]);
8966 if (n > shellparam.nparam)
8967 sh_error("can't shift that many");
8969 shellparam.nparam -= n;
8970 for (ap1 = shellparam.p ; --n >= 0 ; ap1++) {
8971 if (shellparam.malloc)
8975 while ((*ap2++ = *ap1++) != NULL);
8976 #ifdef CONFIG_ASH_GETOPTS
8977 shellparam.optind = 1;
8978 shellparam.optoff = -1;
8987 * The set command builtin.
8991 setcmd(int argc, char **argv)
8994 return showvars(nullstr, 0, VUNSET);
8998 if (*argptr != NULL) {
9006 #ifdef CONFIG_ASH_GETOPTS
9011 shellparam.optind = number(value);
9012 shellparam.optoff = -1;
9016 #ifdef CONFIG_LOCALE_SUPPORT
9017 static void change_lc_all(const char *value)
9019 if (value != 0 && *value != 0)
9020 setlocale(LC_ALL, value);
9023 static void change_lc_ctype(const char *value)
9025 if (value != 0 && *value != 0)
9026 setlocale(LC_CTYPE, value);
9031 #ifdef CONFIG_ASH_RANDOM_SUPPORT
9032 /* Roughly copied from bash.. */
9033 static void change_random(const char *value)
9036 /* "get", generate */
9039 rseed = rseed * 1103515245 + 12345;
9040 sprintf(buf, "%d", (unsigned int)((rseed & 32767)));
9041 /* set without recursion */
9042 setvar(vrandom.text, buf, VNOFUNC);
9043 vrandom.flags &= ~VNOFUNC;
9046 rseed = strtoul(value, (char **)NULL, 10);
9052 #ifdef CONFIG_ASH_GETOPTS
9054 getopts(char *optstr, char *optvar, char **optfirst, int *param_optind, int *optoff)
9063 if(*param_optind < 1)
9065 optnext = optfirst + *param_optind - 1;
9067 if (*param_optind <= 1 || *optoff < 0 || strlen(optnext[-1]) < *optoff)
9070 p = optnext[-1] + *optoff;
9071 if (p == NULL || *p == '\0') {
9072 /* Current word is done, advance */
9074 if (p == NULL || *p != '-' || *++p == '\0') {
9081 if (p[0] == '-' && p[1] == '\0') /* check for "--" */
9086 for (q = optstr; *q != c; ) {
9088 if (optstr[0] == ':') {
9091 err |= setvarsafe("OPTARG", s, 0);
9093 fprintf(stderr, "Illegal option -%c\n", c);
9094 (void) unsetvar("OPTARG");
9104 if (*p == '\0' && (p = *optnext) == NULL) {
9105 if (optstr[0] == ':') {
9108 err |= setvarsafe("OPTARG", s, 0);
9111 fprintf(stderr, "No arg for -%c option\n", c);
9112 (void) unsetvar("OPTARG");
9120 err |= setvarsafe("OPTARG", p, 0);
9123 err |= setvarsafe("OPTARG", nullstr, 0);
9126 *optoff = p ? p - *(optnext - 1) : -1;
9127 *param_optind = optnext - optfirst + 1;
9128 fmtstr(s, sizeof(s), "%d", *param_optind);
9129 err |= setvarsafe("OPTIND", s, VNOFUNC);
9132 err |= setvarsafe(optvar, s, 0);
9143 * The getopts builtin. Shellparam.optnext points to the next argument
9144 * to be processed. Shellparam.optptr points to the next character to
9145 * be processed in the current argument. If shellparam.optnext is NULL,
9146 * then it's the first time getopts has been called.
9150 getoptscmd(int argc, char **argv)
9155 sh_error("Usage: getopts optstring var [arg]");
9156 else if (argc == 3) {
9157 optbase = shellparam.p;
9158 if (shellparam.optind > shellparam.nparam + 1) {
9159 shellparam.optind = 1;
9160 shellparam.optoff = -1;
9165 if (shellparam.optind > argc - 2) {
9166 shellparam.optind = 1;
9167 shellparam.optoff = -1;
9171 return getopts(argv[1], argv[2], optbase, &shellparam.optind,
9172 &shellparam.optoff);
9174 #endif /* CONFIG_ASH_GETOPTS */
9177 * XXX - should get rid of. have all builtins use getopt(3). the
9178 * library getopt must have the BSD extension static variable "optreset"
9179 * otherwise it can't be used within the shell safely.
9181 * Standard option processing (a la getopt) for builtin routines. The
9182 * only argument that is passed to nextopt is the option string; the
9183 * other arguments are unnecessary. It return the character, or '\0' on
9188 nextopt(const char *optstring)
9194 if ((p = optptr) == NULL || *p == '\0') {
9196 if (p == NULL || *p != '-' || *++p == '\0')
9199 if (p[0] == '-' && p[1] == '\0') /* check for "--" */
9203 for (q = optstring ; *q != c ; ) {
9205 sh_error("Illegal option -%c", c);
9210 if (*p == '\0' && (p = *argptr++) == NULL)
9211 sh_error("No arg for -%c option", c);
9223 outstr(const char *p, FILE *file)
9248 outcslow(int c, FILE *dest)
9258 out1fmt(const char *fmt, ...)
9265 r = vprintf(fmt, ap);
9273 fmtstr(char *outbuf, size_t length, const char *fmt, ...)
9280 ret = vsnprintf(outbuf, length, fmt, ap);
9292 * Shell command parser.
9295 #define EOFMARKLEN 79
9299 struct heredoc *next; /* next here document in list */
9300 union node *here; /* redirection node */
9301 char *eofmark; /* string indicating end of input */
9302 int striptabs; /* if set, strip leading tabs */
9307 static struct heredoc *heredoclist; /* list of here documents to read */
9310 static union node *list(int);
9311 static union node *andor(void);
9312 static union node *pipeline(void);
9313 static union node *command(void);
9314 static union node *simplecmd(void);
9315 static union node *makename(void);
9316 static void parsefname(void);
9317 static void parseheredoc(void);
9318 static char peektoken(void);
9319 static int readtoken(void);
9320 static int xxreadtoken(void);
9321 static int readtoken1(int firstc, int syntax, char *eofmark, int striptabs);
9322 static int noexpand(char *);
9323 static void synexpect(int) ATTRIBUTE_NORETURN;
9324 static void synerror(const char *) ATTRIBUTE_NORETURN;
9325 static void setprompt(int);
9331 * Read and parse a command. Returns NEOF on end of file. (NULL is a
9332 * valid parse tree indicating a blank line.)
9336 parsecmd(int interact)
9341 doprompt = interact;
9343 setprompt(doprompt);
9358 union node *n1, *n2, *n3;
9361 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9362 if (nlflag == 2 && peektoken())
9368 if (tok == TBACKGND) {
9369 if (n2->type == NPIPE) {
9370 n2->npipe.backgnd = 1;
9372 if (n2->type != NREDIR) {
9373 n3 = stalloc(sizeof(struct nredir));
9375 n3->nredir.redirect = NULL;
9378 n2->type = NBACKGND;
9385 n3 = (union node *)stalloc(sizeof (struct nbinary));
9387 n3->nbinary.ch1 = n1;
9388 n3->nbinary.ch2 = n2;
9404 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9412 pungetc(); /* push back EOF on input */
9428 union node *n1, *n2, *n3;
9433 if ((t = readtoken()) == TAND) {
9435 } else if (t == TOR) {
9441 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9443 n3 = (union node *)stalloc(sizeof (struct nbinary));
9445 n3->nbinary.ch1 = n1;
9446 n3->nbinary.ch2 = n2;
9456 union node *n1, *n2, *pipenode;
9457 struct nodelist *lp, *prev;
9461 TRACE(("pipeline: entered\n"));
9462 if (readtoken() == TNOT) {
9464 checkkwd = CHKKWD | CHKALIAS;
9468 if (readtoken() == TPIPE) {
9469 pipenode = (union node *)stalloc(sizeof (struct npipe));
9470 pipenode->type = NPIPE;
9471 pipenode->npipe.backgnd = 0;
9472 lp = (struct nodelist *)stalloc(sizeof (struct nodelist));
9473 pipenode->npipe.cmdlist = lp;
9477 lp = (struct nodelist *)stalloc(sizeof (struct nodelist));
9478 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9481 } while (readtoken() == TPIPE);
9487 n2 = (union node *)stalloc(sizeof (struct nnot));
9500 union node *n1, *n2;
9501 union node *ap, **app;
9502 union node *cp, **cpp;
9503 union node *redir, **rpp;
9510 switch (readtoken()) {
9515 n1 = (union node *)stalloc(sizeof (struct nif));
9517 n1->nif.test = list(0);
9518 if (readtoken() != TTHEN)
9520 n1->nif.ifpart = list(0);
9522 while (readtoken() == TELIF) {
9523 n2->nif.elsepart = (union node *)stalloc(sizeof (struct nif));
9524 n2 = n2->nif.elsepart;
9526 n2->nif.test = list(0);
9527 if (readtoken() != TTHEN)
9529 n2->nif.ifpart = list(0);
9531 if (lasttoken == TELSE)
9532 n2->nif.elsepart = list(0);
9534 n2->nif.elsepart = NULL;
9542 n1 = (union node *)stalloc(sizeof (struct nbinary));
9543 n1->type = (lasttoken == TWHILE)? NWHILE : NUNTIL;
9544 n1->nbinary.ch1 = list(0);
9545 if ((got=readtoken()) != TDO) {
9546 TRACE(("expecting DO got %s %s\n", tokname(got), got == TWORD ? wordtext : ""));
9549 n1->nbinary.ch2 = list(0);
9554 if (readtoken() != TWORD || quoteflag || ! goodname(wordtext))
9555 synerror("Bad for loop variable");
9556 n1 = (union node *)stalloc(sizeof (struct nfor));
9558 n1->nfor.var = wordtext;
9559 checkkwd = CHKKWD | CHKALIAS;
9560 if (readtoken() == TIN) {
9562 while (readtoken() == TWORD) {
9563 n2 = (union node *)stalloc(sizeof (struct narg));
9565 n2->narg.text = wordtext;
9566 n2->narg.backquote = backquotelist;
9568 app = &n2->narg.next;
9572 if (lasttoken != TNL && lasttoken != TSEMI)
9575 n2 = (union node *)stalloc(sizeof (struct narg));
9577 n2->narg.text = (char *)dolatstr;
9578 n2->narg.backquote = NULL;
9579 n2->narg.next = NULL;
9582 * Newline or semicolon here is optional (but note
9583 * that the original Bourne shell only allowed NL).
9585 if (lasttoken != TNL && lasttoken != TSEMI)
9588 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9589 if (readtoken() != TDO)
9591 n1->nfor.body = list(0);
9595 n1 = (union node *)stalloc(sizeof (struct ncase));
9597 if (readtoken() != TWORD)
9599 n1->ncase.expr = n2 = (union node *)stalloc(sizeof (struct narg));
9601 n2->narg.text = wordtext;
9602 n2->narg.backquote = backquotelist;
9603 n2->narg.next = NULL;
9605 checkkwd = CHKKWD | CHKALIAS;
9606 } while (readtoken() == TNL);
9607 if (lasttoken != TIN)
9609 cpp = &n1->ncase.cases;
9611 checkkwd = CHKNL | CHKKWD;
9614 if (lasttoken == TLP)
9616 *cpp = cp = (union node *)stalloc(sizeof (struct nclist));
9618 app = &cp->nclist.pattern;
9620 *app = ap = (union node *)stalloc(sizeof (struct narg));
9622 ap->narg.text = wordtext;
9623 ap->narg.backquote = backquotelist;
9624 if (readtoken() != TPIPE)
9626 app = &ap->narg.next;
9629 ap->narg.next = NULL;
9630 if (lasttoken != TRP)
9632 cp->nclist.body = list(2);
9634 cpp = &cp->nclist.next;
9636 checkkwd = CHKNL | CHKKWD;
9637 if ((t = readtoken()) != TESAC) {
9639 synexpect(TENDCASE);
9647 n1 = (union node *)stalloc(sizeof (struct nredir));
9648 n1->type = NSUBSHELL;
9649 n1->nredir.n = list(0);
9650 n1->nredir.redirect = NULL;
9663 if (readtoken() != t)
9667 /* Now check for redirection which may follow command */
9668 checkkwd = CHKKWD | CHKALIAS;
9670 while (readtoken() == TREDIR) {
9671 *rpp = n2 = redirnode;
9672 rpp = &n2->nfile.next;
9678 if (n1->type != NSUBSHELL) {
9679 n2 = (union node *)stalloc(sizeof (struct nredir));
9684 n1->nredir.redirect = redir;
9693 union node *args, **app;
9694 union node *n = NULL;
9695 union node *vars, **vpp;
9696 union node **rpp, *redir;
9706 savecheckkwd = CHKALIAS;
9708 checkkwd = savecheckkwd;
9709 switch (readtoken()) {
9711 n = (union node *)stalloc(sizeof (struct narg));
9713 n->narg.text = wordtext;
9714 n->narg.backquote = backquotelist;
9715 if (savecheckkwd && isassignment(wordtext)) {
9717 vpp = &n->narg.next;
9720 app = &n->narg.next;
9725 *rpp = n = redirnode;
9726 rpp = &n->nfile.next;
9727 parsefname(); /* read name of redirection file */
9731 args && app == &args->narg.next &&
9734 struct builtincmd *bcmd;
9737 /* We have a function */
9738 if (readtoken() != TRP)
9740 name = n->narg.text;
9742 !goodname(name) || (
9743 (bcmd = find_builtin(name)) &&
9744 IS_BUILTIN_SPECIAL(bcmd)
9747 synerror("Bad function name");
9749 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9750 n->narg.next = command();
9763 n = (union node *)stalloc(sizeof (struct ncmd));
9765 n->ncmd.args = args;
9766 n->ncmd.assign = vars;
9767 n->ncmd.redirect = redir;
9776 n = (union node *)stalloc(sizeof (struct narg));
9778 n->narg.next = NULL;
9779 n->narg.text = wordtext;
9780 n->narg.backquote = backquotelist;
9784 void fixredir(union node *n, const char *text, int err)
9786 TRACE(("Fix redir %s %d\n", text, err));
9788 n->ndup.vname = NULL;
9790 if (is_digit(text[0]) && text[1] == '\0')
9791 n->ndup.dupfd = digit_val(text[0]);
9792 else if (text[0] == '-' && text[1] == '\0')
9797 synerror("Bad fd number");
9799 n->ndup.vname = makename();
9807 union node *n = redirnode;
9809 if (readtoken() != TWORD)
9811 if (n->type == NHERE) {
9812 struct heredoc *here = heredoc;
9818 TRACE(("Here document %d\n", n->type));
9819 if (! noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)
9820 synerror("Illegal eof marker for << redirection");
9821 rmescapes(wordtext);
9822 here->eofmark = wordtext;
9824 if (heredoclist == NULL)
9827 for (p = heredoclist ; p->next ; p = p->next);
9830 } else if (n->type == NTOFD || n->type == NFROMFD) {
9831 fixredir(n, wordtext, 0);
9833 n->nfile.fname = makename();
9839 * Input any here documents.
9845 struct heredoc *here;
9855 readtoken1(pgetc(), here->here->type == NHERE? SQSYNTAX : DQSYNTAX,
9856 here->eofmark, here->striptabs);
9857 n = (union node *)stalloc(sizeof (struct narg));
9858 n->narg.type = NARG;
9859 n->narg.next = NULL;
9860 n->narg.text = wordtext;
9861 n->narg.backquote = backquotelist;
9862 here->here->nhere.doc = n;
9867 static char peektoken(void)
9873 return tokname_array[t][0];
9881 int alreadyseen = tokpushback;
9884 #ifdef CONFIG_ASH_ALIAS
9893 if (checkkwd & CHKNL) {
9900 if (t != TWORD || quoteflag) {
9905 * check for keywords
9907 if (checkkwd & CHKKWD) {
9908 const char *const *pp;
9910 if ((pp = findkwd(wordtext))) {
9911 lasttoken = t = pp - tokname_array;
9912 TRACE(("keyword %s recognized\n", tokname(t)));
9917 if (checkkwd & CHKALIAS) {
9918 #ifdef CONFIG_ASH_ALIAS
9920 if ((ap = lookupalias(wordtext, 1)) != NULL) {
9922 pushstring(ap->val, ap);
9932 TRACE(("token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
9934 TRACE(("reread token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
9941 * Read the next input token.
9942 * If the token is a word, we set backquotelist to the list of cmds in
9943 * backquotes. We set quoteflag to true if any part of the word was
9945 * If the token is TREDIR, then we set redirnode to a structure containing
9947 * In all cases, the variable startlinno is set to the number of the line
9948 * on which the token starts.
9950 * [Change comment: here documents and internal procedures]
9951 * [Readtoken shouldn't have any arguments. Perhaps we should make the
9952 * word parsing code into a separate routine. In this case, readtoken
9953 * doesn't need to have any internal procedures, but parseword does.
9954 * We could also make parseoperator in essence the main routine, and
9955 * have parseword (readtoken1?) handle both words and redirection.]
9958 #define NEW_xxreadtoken
9959 #ifdef NEW_xxreadtoken
9961 /* singles must be first! */
9962 static const char xxreadtoken_chars[7] = { '\n', '(', ')', '&', '|', ';', 0 };
9964 static const char xxreadtoken_tokens[] = {
9965 TNL, TLP, TRP, /* only single occurrence allowed */
9966 TBACKGND, TPIPE, TSEMI, /* if single occurrence */
9967 TEOF, /* corresponds to trailing nul */
9968 TAND, TOR, TENDCASE, /* if double occurrence */
9971 #define xxreadtoken_doubles \
9972 (sizeof(xxreadtoken_tokens) - sizeof(xxreadtoken_chars))
9973 #define xxreadtoken_singles \
9974 (sizeof(xxreadtoken_chars) - xxreadtoken_doubles - 1)
9976 static int xxreadtoken()
9987 startlinno = plinno;
9988 for (;;) { /* until token or start of word found */
9991 if ((c != ' ') && (c != '\t')
9992 #ifdef CONFIG_ASH_ALIAS
9997 while ((c = pgetc()) != '\n' && c != PEOF);
9999 } else if (c == '\\') {
10000 if (pgetc() != '\n') {
10004 startlinno = ++plinno;
10009 = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
10014 needprompt = doprompt;
10017 p = strchr(xxreadtoken_chars, c);
10020 return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
10023 if (p - xxreadtoken_chars >= xxreadtoken_singles) {
10024 if (pgetc() == *p) { /* double occurrence? */
10025 p += xxreadtoken_doubles + 1;
10032 return lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
10040 #define RETURN(token) return lasttoken = token
10054 startlinno = plinno;
10055 for (;;) { /* until token or start of word found */
10058 case ' ': case '\t':
10059 #ifdef CONFIG_ASH_ALIAS
10064 while ((c = pgetc()) != '\n' && c != PEOF);
10068 if (pgetc() == '\n') {
10069 startlinno = ++plinno;
10078 needprompt = doprompt;
10083 if (pgetc() == '&')
10088 if (pgetc() == '|')
10093 if (pgetc() == ';')
10106 return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
10109 #endif /* NEW_xxreadtoken */
10113 * If eofmark is NULL, read a word or a redirection symbol. If eofmark
10114 * is not NULL, read a here document. In the latter case, eofmark is the
10115 * word which marks the end of the document and striptabs is true if
10116 * leading tabs should be stripped from the document. The argument firstc
10117 * is the first character of the input token or document.
10119 * Because C does not have internal subroutines, I have simulated them
10120 * using goto's to implement the subroutine linkage. The following macros
10121 * will run code that appears at the end of readtoken1.
10124 #define CHECKEND() {goto checkend; checkend_return:;}
10125 #define PARSEREDIR() {goto parseredir; parseredir_return:;}
10126 #define PARSESUB() {goto parsesub; parsesub_return:;}
10127 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
10128 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
10129 #define PARSEARITH() {goto parsearith; parsearith_return:;}
10132 readtoken1(int firstc, int syntax, char *eofmark, int striptabs)
10137 char line[EOFMARKLEN + 1];
10138 struct nodelist *bqlist = 0;
10141 int varnest = 0; /* levels of variables expansion */
10142 int arinest = 0; /* levels of arithmetic expansion */
10143 int parenlevel = 0; /* levels of parens in arithmetic */
10144 int dqvarnest = 0; /* levels of variables expansion within double quotes */
10146 int prevsyntax = 0; /* syntax before arithmetic */
10148 /* Avoid longjmp clobbering */
10154 (void) &parenlevel;
10157 (void) &prevsyntax;
10161 startlinno = plinno;
10163 if (syntax == DQSYNTAX)
10172 STARTSTACKSTR(out);
10173 loop: { /* for each line, until end of word */
10174 CHECKEND(); /* set c to PEOF if at end of here document */
10175 for (;;) { /* until end of line or end of word */
10176 CHECKSTRSPACE(4, out); /* permit 4 calls to USTPUTC */
10177 switch(SIT(c, syntax)) {
10178 case CNL: /* '\n' */
10179 if (syntax == BASESYNTAX)
10180 goto endword; /* exit outer loop */
10186 goto loop; /* continue outer loop */
10191 if (eofmark == NULL || dblquote)
10192 USTPUTC(CTLESC, out);
10195 case CBACK: /* backslash */
10198 USTPUTC(CTLESC, out);
10199 USTPUTC('\\', out);
10201 } else if (c == '\n') {
10206 c != '\\' && c != '`' &&
10211 USTPUTC(CTLESC, out);
10212 USTPUTC('\\', out);
10214 if (SIT(c, SQSYNTAX) == CCTL)
10215 USTPUTC(CTLESC, out);
10223 if (eofmark == NULL) {
10224 USTPUTC(CTLQUOTEMARK, out);
10232 if (eofmark != NULL && arinest == 0 &&
10236 if (dqvarnest == 0) {
10237 syntax = BASESYNTAX;
10244 case CVAR: /* '$' */
10245 PARSESUB(); /* parse substitution */
10247 case CENDVAR: /* '}' */
10250 if (dqvarnest > 0) {
10253 USTPUTC(CTLENDVAR, out);
10258 #ifdef CONFIG_ASH_MATH_SUPPORT
10259 case CLP: /* '(' in arithmetic */
10263 case CRP: /* ')' in arithmetic */
10264 if (parenlevel > 0) {
10268 if (pgetc() == ')') {
10269 if (--arinest == 0) {
10270 USTPUTC(CTLENDARI, out);
10271 syntax = prevsyntax;
10272 if (syntax == DQSYNTAX)
10280 * unbalanced parens
10281 * (don't 2nd guess - no error)
10289 case CBQUOTE: /* '`' */
10293 goto endword; /* exit outer loop */
10298 goto endword; /* exit outer loop */
10299 #ifdef CONFIG_ASH_ALIAS
10309 #ifdef CONFIG_ASH_MATH_SUPPORT
10310 if (syntax == ARISYNTAX)
10311 synerror("Missing '))'");
10313 if (syntax != BASESYNTAX && ! parsebackquote && eofmark == NULL)
10314 synerror("Unterminated quoted string");
10315 if (varnest != 0) {
10316 startlinno = plinno;
10318 synerror("Missing '}'");
10320 USTPUTC('\0', out);
10321 len = out - (char *)stackblock();
10322 out = stackblock();
10323 if (eofmark == NULL) {
10324 if ((c == '>' || c == '<')
10327 && (*out == '\0' || is_digit(*out))) {
10329 return lasttoken = TREDIR;
10334 quoteflag = quotef;
10335 backquotelist = bqlist;
10336 grabstackblock(len);
10338 return lasttoken = TWORD;
10339 /* end of readtoken routine */
10344 * Check to see whether we are at the end of the here document. When this
10345 * is called, c is set to the first character of the next input line. If
10346 * we are at the end of the here document, this routine sets the c to PEOF.
10351 #ifdef CONFIG_ASH_ALIAS
10357 while (c == '\t') {
10361 if (c == *eofmark) {
10362 if (pfgets(line, sizeof line) != NULL) {
10366 for (q = eofmark + 1 ; *q && *p == *q ; p++, q++);
10367 if (*p == '\n' && *q == '\0') {
10370 needprompt = doprompt;
10372 pushstring(line, NULL);
10377 goto checkend_return;
10382 * Parse a redirection operator. The variable "out" points to a string
10383 * specifying the fd to be redirected. The variable "c" contains the
10384 * first character of the redirection operator.
10391 np = (union node *)stalloc(sizeof (struct nfile));
10396 np->type = NAPPEND;
10398 np->type = NCLOBBER;
10405 } else { /* c == '<' */
10407 switch (c = pgetc()) {
10409 if (sizeof (struct nfile) != sizeof (struct nhere)) {
10410 np = (union node *)stalloc(sizeof (struct nhere));
10414 heredoc = (struct heredoc *)stalloc(sizeof (struct heredoc));
10415 heredoc->here = np;
10416 if ((c = pgetc()) == '-') {
10417 heredoc->striptabs = 1;
10419 heredoc->striptabs = 0;
10425 np->type = NFROMFD;
10429 np->type = NFROMTO;
10439 np->nfile.fd = digit_val(fd);
10441 goto parseredir_return;
10446 * Parse a substitution. At this point, we have read the dollar sign
10447 * and nothing else.
10455 static const char types[] = "}-+?=";
10459 c <= PEOA_OR_PEOF ||
10460 (c != '(' && c != '{' && !is_name(c) && !is_special(c))
10464 } else if (c == '(') { /* $(command) or $((arith)) */
10465 if (pgetc() == '(') {
10466 #ifdef CONFIG_ASH_MATH_SUPPORT
10469 synerror("We unsupport $((arith))");
10476 USTPUTC(CTLVAR, out);
10477 typeloc = out - (char *)stackblock();
10478 USTPUTC(VSNORMAL, out);
10479 subtype = VSNORMAL;
10483 if ((c = pgetc()) == '}')
10486 subtype = VSLENGTH;
10491 if (c > PEOA_OR_PEOF && is_name(c)) {
10495 } while (c > PEOA_OR_PEOF && is_in_name(c));
10496 } else if (is_digit(c)) {
10500 } while (is_digit(c));
10502 else if (is_special(c)) {
10507 badsub: synerror("Bad substitution");
10511 if (subtype == 0) {
10518 p = strchr(types, c);
10521 subtype = p - types + VSNORMAL;
10527 subtype = c == '#' ? VSTRIMLEFT :
10540 if (dblquote || arinest)
10542 *((char *)stackblock() + typeloc) = subtype | flags;
10543 if (subtype != VSNORMAL) {
10545 if (dblquote || arinest) {
10550 goto parsesub_return;
10555 * Called to parse command substitutions. Newstyle is set if the command
10556 * is enclosed inside $(...); nlpp is a pointer to the head of the linked
10557 * list of commands (passed by reference), and savelen is the number of
10558 * characters on the top of the stack which must be preserved.
10562 struct nodelist **nlpp;
10565 char *volatile str;
10566 struct jmploc jmploc;
10567 struct jmploc *volatile savehandler;
10569 int saveprompt = 0;
10571 (void) &saveprompt;
10574 savepbq = parsebackquote;
10575 if (setjmp(jmploc.loc)) {
10578 parsebackquote = 0;
10579 handler = savehandler;
10580 longjmp(handler->loc, 1);
10584 savelen = out - (char *)stackblock();
10586 str = ckmalloc(savelen);
10587 memcpy(str, stackblock(), savelen);
10589 savehandler = handler;
10593 /* We must read until the closing backquote, giving special
10594 treatment to some slashes, and then push the string and
10595 reread it as input, interpreting it normally. */
10602 STARTSTACKSTR(pout);
10607 switch (pc = pgetc()) {
10612 if ((pc = pgetc()) == '\n') {
10617 * If eating a newline, avoid putting
10618 * the newline into the new character
10619 * stream (via the STPUTC after the
10624 if (pc != '\\' && pc != '`' && pc != '$'
10625 && (!dblquote || pc != '"'))
10626 STPUTC('\\', pout);
10627 if (pc > PEOA_OR_PEOF) {
10633 #ifdef CONFIG_ASH_ALIAS
10636 startlinno = plinno;
10637 synerror("EOF in backquote substitution");
10641 needprompt = doprompt;
10650 STPUTC('\0', pout);
10651 psavelen = pout - (char *)stackblock();
10652 if (psavelen > 0) {
10653 pstr = grabstackstr(pout);
10654 setinputstring(pstr);
10659 nlpp = &(*nlpp)->next;
10660 *nlpp = (struct nodelist *)stalloc(sizeof (struct nodelist));
10661 (*nlpp)->next = NULL;
10662 parsebackquote = oldstyle;
10665 saveprompt = doprompt;
10672 doprompt = saveprompt;
10674 if (readtoken() != TRP)
10681 * Start reading from old file again, ignoring any pushed back
10682 * tokens left from the backquote parsing
10687 while (stackblocksize() <= savelen)
10689 STARTSTACKSTR(out);
10691 memcpy(out, str, savelen);
10692 STADJUST(savelen, out);
10698 parsebackquote = savepbq;
10699 handler = savehandler;
10700 if (arinest || dblquote)
10701 USTPUTC(CTLBACKQ | CTLQUOTE, out);
10703 USTPUTC(CTLBACKQ, out);
10705 goto parsebackq_oldreturn;
10707 goto parsebackq_newreturn;
10710 #ifdef CONFIG_ASH_MATH_SUPPORT
10712 * Parse an arithmetic expansion (indicate start of one and set state)
10716 if (++arinest == 1) {
10717 prevsyntax = syntax;
10718 syntax = ARISYNTAX;
10719 USTPUTC(CTLARI, out);
10726 * we collapse embedded arithmetic expansion to
10727 * parenthesis, which should be equivalent
10731 goto parsearith_return;
10735 } /* end of readtoken */
10740 * Returns true if the text contains nothing to expand (no dollar signs
10745 noexpand(char *text)
10751 while ((c = *p++) != '\0') {
10752 if (c == CTLQUOTEMARK)
10756 else if (SIT(c, BASESYNTAX) == CCTL)
10764 * Return of a legal variable name (a letter or underscore followed by zero or
10765 * more letters, underscores, and digits).
10769 endofname(const char *name)
10777 if (! is_in_name(*p))
10785 * Called when an unexpected token is read during the parse. The argument
10786 * is the token that is expected, or -1 if more than one type of token can
10787 * occur at this point.
10790 static void synexpect(int token)
10795 l = sprintf(msg, "%s unexpected", tokname(lasttoken));
10797 sprintf(msg + l, " (expecting %s)", tokname(token));
10803 synerror(const char *msg)
10805 sh_error("Syntax error: %s", msg);
10811 * called by editline -- any expansions to the prompt
10812 * should be added here.
10815 #ifdef CONFIG_ASH_EXPAND_PRMT
10816 static const char *
10817 expandstr(const char *ps)
10821 /* XXX Fix (char *) cast. */
10822 setinputstring((char *)ps);
10823 readtoken1(pgetc(), DQSYNTAX, nullstr, 0);
10826 n.narg.type = NARG;
10827 n.narg.next = NULL;
10828 n.narg.text = wordtext;
10829 n.narg.backquote = backquotelist;
10831 expandarg(&n, NULL, 0);
10832 return stackblock();
10836 static void setprompt(int whichprompt)
10838 const char *prompt;
10839 #ifdef CONFIG_ASH_EXPAND_PRMT
10840 struct stackmark smark;
10845 switch (whichprompt) {
10855 #ifdef CONFIG_ASH_EXPAND_PRMT
10856 setstackmark(&smark);
10857 stalloc(stackblocksize());
10859 putprompt(expandstr(prompt));
10860 #ifdef CONFIG_ASH_EXPAND_PRMT
10861 popstackmark(&smark);
10866 static const char *const *findkwd(const char *s)
10868 return bsearch(s, tokname_array + KWDOFFSET,
10869 (sizeof(tokname_array) / sizeof(const char *)) - KWDOFFSET,
10870 sizeof(const char *), pstrcmp);
10876 * Code for dealing with input/output redirection.
10879 #define EMPTY -2 /* marks an unused slot in redirtab */
10881 # define PIPESIZE 4096 /* amount of buffering in a pipe */
10883 # define PIPESIZE PIPE_BUF
10887 * Open a file in noclobber mode.
10888 * The code was copied from bash.
10891 noclobberopen(const char *fname)
10894 struct stat finfo, finfo2;
10897 * If the file exists and is a regular file, return an error
10900 r = stat(fname, &finfo);
10901 if (r == 0 && S_ISREG(finfo.st_mode)) {
10907 * If the file was not present (r != 0), make sure we open it
10908 * exclusively so that if it is created before we open it, our open
10909 * will fail. Make sure that we do not truncate an existing file.
10910 * Note that we don't turn on O_EXCL unless the stat failed -- if the
10911 * file was not a regular file, we leave O_EXCL off.
10914 return open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
10915 fd = open(fname, O_WRONLY|O_CREAT, 0666);
10917 /* If the open failed, return the file descriptor right away. */
10922 * OK, the open succeeded, but the file may have been changed from a
10923 * non-regular file to a regular file between the stat and the open.
10924 * We are assuming that the O_EXCL open handles the case where FILENAME
10925 * did not exist and is symlinked to an existing file between the stat
10930 * If we can open it and fstat the file descriptor, and neither check
10931 * revealed that it was a regular file, and the file has not been
10932 * replaced, return the file descriptor.
10934 if (fstat(fd, &finfo2) == 0 && !S_ISREG(finfo2.st_mode) &&
10935 finfo.st_dev == finfo2.st_dev && finfo.st_ino == finfo2.st_ino)
10938 /* The file has been replaced. badness. */
10945 * Handle here documents. Normally we fork off a process to write the
10946 * data to a pipe. If the document is short, we can stuff the data in
10947 * the pipe without forking.
10951 openhere(union node *redir)
10957 sh_error("Pipe call failed");
10958 if (redir->type == NHERE) {
10959 len = strlen(redir->nhere.doc->narg.text);
10960 if (len <= PIPESIZE) {
10961 bb_full_write(pip[1], redir->nhere.doc->narg.text, len);
10965 if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
10967 signal(SIGINT, SIG_IGN);
10968 signal(SIGQUIT, SIG_IGN);
10969 signal(SIGHUP, SIG_IGN);
10971 signal(SIGTSTP, SIG_IGN);
10973 signal(SIGPIPE, SIG_DFL);
10974 if (redir->type == NHERE)
10975 bb_full_write(pip[1], redir->nhere.doc->narg.text, len);
10977 expandhere(redir->nhere.doc, pip[1]);
10986 openredirect(union node *redir)
10991 switch (redir->nfile.type) {
10993 fname = redir->nfile.expfname;
10994 if ((f = open(fname, O_RDONLY)) < 0)
10998 fname = redir->nfile.expfname;
10999 if ((f = open(fname, O_RDWR|O_CREAT|O_TRUNC, 0666)) < 0)
11003 /* Take care of noclobber mode. */
11005 fname = redir->nfile.expfname;
11006 if ((f = noclobberopen(fname)) < 0)
11012 fname = redir->nfile.expfname;
11013 if ((f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0)
11017 fname = redir->nfile.expfname;
11018 if ((f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666)) < 0)
11025 /* Fall through to eliminate warning. */
11032 f = openhere(redir);
11038 sh_error("cannot create %s: %s", fname, errmsg(errno, E_CREAT));
11040 sh_error("cannot open %s: %s", fname, errmsg(errno, E_OPEN));
11044 dupredirect(union node *redir, int f)
11046 int fd = redir->nfile.fd;
11048 if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
11049 if (redir->ndup.dupfd >= 0) { /* if not ">&-" */
11050 copyfd(redir->ndup.dupfd, fd);
11063 * Process a list of redirection commands. If the REDIR_PUSH flag is set,
11064 * old file descriptors are stashed away so that the redirection can be
11065 * undone by calling popredir. If the REDIR_BACKQ flag is set, then the
11066 * standard output, and the standard error if it becomes a duplicate of
11067 * stdout, is saved in memory.
11071 redirect(union node *redir, int flags)
11074 struct redirtab *sv;
11085 if (flags & REDIR_PUSH) {
11086 struct redirtab *q;
11087 q = ckmalloc(sizeof (struct redirtab));
11088 q->next = redirlist;
11090 q->nullredirs = nullredirs - 1;
11091 for (i = 0 ; i < 10 ; i++)
11092 q->renamed[i] = EMPTY;
11099 if ((n->nfile.type == NTOFD || n->nfile.type == NFROMFD) &&
11100 n->ndup.dupfd == fd)
11101 continue; /* redirect from/to same file descriptor */
11103 newfd = openredirect(n);
11106 if (sv && *(p = &sv->renamed[fd]) == EMPTY) {
11107 i = fcntl(fd, F_DUPFD, 10);
11114 sh_error("%d: %m", fd);
11124 dupredirect(n, newfd);
11125 } while ((n = n->nfile.next));
11127 if (flags & REDIR_SAVEFD2 && sv && sv->renamed[2] >= 0)
11128 preverrout_fd = sv->renamed[2];
11133 * Undo the effects of the last redirection.
11139 struct redirtab *rp;
11142 if (--nullredirs >= 0)
11146 for (i = 0 ; i < 10 ; i++) {
11147 if (rp->renamed[i] != EMPTY) {
11150 copyfd(rp->renamed[i], i);
11152 close(rp->renamed[i]);
11155 redirlist = rp->next;
11156 nullredirs = rp->nullredirs;
11162 * Undo all redirections. Called on error or interrupt.
11166 * Discard all saved file descriptors.
11170 clearredir(int drop)
11182 * Copy a file descriptor to be >= to. Returns -1
11183 * if the source file descriptor is closed, EMPTY if there are no unused
11184 * file descriptors left.
11188 copyfd(int from, int to)
11192 newfd = fcntl(from, F_DUPFD, to);
11194 if (errno == EMFILE)
11197 sh_error("%d: %m", from);
11204 redirectsafe(union node *redir, int flags)
11207 volatile int saveint;
11208 struct jmploc *volatile savehandler = handler;
11209 struct jmploc jmploc;
11212 if (!(err = setjmp(jmploc.loc) * 2)) {
11214 redirect(redir, flags);
11216 handler = savehandler;
11217 if (err && exception != EXERROR)
11218 longjmp(handler->loc, 1);
11219 RESTOREINT(saveint);
11226 static void shtree(union node *, int, char *, FILE*);
11227 static void shcmd(union node *, FILE *);
11228 static void sharg(union node *, FILE *);
11229 static void indent(int, char *, FILE *);
11230 static void trstring(char *);
11234 showtree(union node *n)
11236 trputs("showtree called\n");
11237 shtree(n, 1, NULL, stdout);
11242 shtree(union node *n, int ind, char *pfx, FILE *fp)
11244 struct nodelist *lp;
11250 indent(ind, pfx, fp);
11261 shtree(n->nbinary.ch1, ind, NULL, fp);
11264 shtree(n->nbinary.ch2, ind, NULL, fp);
11272 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
11277 if (n->npipe.backgnd)
11283 fprintf(fp, "<node type %d>", n->type);
11292 shcmd(union node *cmd, FILE *fp)
11300 for (np = cmd->ncmd.args ; np ; np = np->narg.next) {
11306 for (np = cmd->ncmd.redirect ; np ; np = np->nfile.next) {
11309 switch (np->nfile.type) {
11310 case NTO: s = ">"; dftfd = 1; break;
11311 case NCLOBBER: s = ">|"; dftfd = 1; break;
11312 case NAPPEND: s = ">>"; dftfd = 1; break;
11313 case NTOFD: s = ">&"; dftfd = 1; break;
11314 case NFROM: s = "<"; dftfd = 0; break;
11315 case NFROMFD: s = "<&"; dftfd = 0; break;
11316 case NFROMTO: s = "<>"; dftfd = 0; break;
11317 default: s = "*error*"; dftfd = 0; break;
11319 if (np->nfile.fd != dftfd)
11320 fprintf(fp, "%d", np->nfile.fd);
11322 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
11323 fprintf(fp, "%d", np->ndup.dupfd);
11325 sharg(np->nfile.fname, fp);
11334 sharg(union node *arg, FILE *fp)
11337 struct nodelist *bqlist;
11340 if (arg->type != NARG) {
11341 out1fmt("<node type %d>\n", arg->type);
11344 bqlist = arg->narg.backquote;
11345 for (p = arg->narg.text ; *p ; p++) {
11354 if (subtype == VSLENGTH)
11360 if (subtype & VSNUL)
11363 switch (subtype & VSTYPE) {
11382 case VSTRIMLEFTMAX:
11389 case VSTRIMRIGHTMAX:
11396 out1fmt("<subtype %d>", subtype);
11403 case CTLBACKQ|CTLQUOTE:
11406 shtree(bqlist->n, -1, NULL, fp);
11418 indent(int amount, char *pfx, FILE *fp)
11422 for (i = 0 ; i < amount ; i++) {
11423 if (pfx && i == amount - 1)
11444 putc(c, tracefile);
11448 trace(const char *fmt, ...)
11455 (void) vfprintf(tracefile, fmt, va);
11460 tracev(const char *fmt, va_list va)
11464 (void) vfprintf(tracefile, fmt, va);
11469 trputs(const char *s)
11473 fputs(s, tracefile);
11485 putc('"', tracefile);
11486 for (p = s ; *p ; p++) {
11488 case '\n': c = 'n'; goto backslash;
11489 case '\t': c = 't'; goto backslash;
11490 case '\r': c = 'r'; goto backslash;
11491 case '"': c = '"'; goto backslash;
11492 case '\\': c = '\\'; goto backslash;
11493 case CTLESC: c = 'e'; goto backslash;
11494 case CTLVAR: c = 'v'; goto backslash;
11495 case CTLVAR+CTLQUOTE: c = 'V'; goto backslash;
11496 case CTLBACKQ: c = 'q'; goto backslash;
11497 case CTLBACKQ+CTLQUOTE: c = 'Q'; goto backslash;
11498 backslash: putc('\\', tracefile);
11499 putc(c, tracefile);
11502 if (*p >= ' ' && *p <= '~')
11503 putc(*p, tracefile);
11505 putc('\\', tracefile);
11506 putc(*p >> 6 & 03, tracefile);
11507 putc(*p >> 3 & 07, tracefile);
11508 putc(*p & 07, tracefile);
11513 putc('"', tracefile);
11525 putc(' ', tracefile);
11527 putc('\n', tracefile);
11543 /* leave open because libedit might be using it */
11546 scopy("./trace", s);
11548 if (!freopen(s, "a", tracefile)) {
11549 fprintf(stderr, "Can't re-open %s\n", s);
11554 if ((tracefile = fopen(s, "a")) == NULL) {
11555 fprintf(stderr, "Can't open %s\n", s);
11561 if ((flags = fcntl(fileno(tracefile), F_GETFL, 0)) >= 0)
11562 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
11564 setlinebuf(tracefile);
11565 fputs("\nTracing started.\n", tracefile);
11573 * Sigmode records the current value of the signal handlers for the various
11574 * modes. A value of zero means that the current handler is not known.
11575 * S_HARD_IGN indicates that the signal was ignored on entry to the shell,
11578 #define S_DFL 1 /* default signal handling (SIG_DFL) */
11579 #define S_CATCH 2 /* signal is caught */
11580 #define S_IGN 3 /* signal is ignored (SIG_IGN) */
11581 #define S_HARD_IGN 4 /* signal is ignored permenantly */
11582 #define S_RESET 5 /* temporary - to reset a hard ignored sig */
11587 * The trap builtin.
11591 trapcmd(int argc, char **argv)
11600 for (signo = 0 ; signo < NSIG ; signo++) {
11601 if (trap[signo] != NULL) {
11604 sn = u_signal_names(0, &signo, 0);
11607 out1fmt("trap -- %s %s\n",
11608 single_quote(trap[signo]), sn);
11618 if ((signo = decode_signal(*ap, 0)) < 0)
11619 sh_error("%s: bad trap", *ap);
11622 if (action[0] == '-' && action[1] == '\0')
11625 action = savestr(action);
11628 ckfree(trap[signo]);
11629 trap[signo] = action;
11640 * Clear traps on a fork.
11648 for (tp = trap ; tp < &trap[NSIG] ; tp++) {
11649 if (*tp && **tp) { /* trap not NULL or SIG_IGN */
11653 if (tp != &trap[0])
11654 setsignal(tp - trap);
11662 * Set the signal handler for the specified signal. The routine figures
11663 * out what it should be set to.
11667 setsignal(int signo)
11671 struct sigaction act;
11673 if ((t = trap[signo]) == NULL)
11675 else if (*t != '\0')
11679 if (rootshell && action == S_DFL) {
11682 if (iflag || minusc || sflag == 0)
11705 t = &sigmode[signo - 1];
11709 * current setting unknown
11711 if (sigaction(signo, 0, &act) == -1) {
11713 * Pretend it worked; maybe we should give a warning
11714 * here, but other shells don't. We don't alter
11715 * sigmode, so that we retry every time.
11719 if (act.sa_handler == SIG_IGN) {
11720 if (mflag && (signo == SIGTSTP ||
11721 signo == SIGTTIN || signo == SIGTTOU)) {
11722 tsig = S_IGN; /* don't hard ignore these */
11726 tsig = S_RESET; /* force to be set */
11729 if (tsig == S_HARD_IGN || tsig == action)
11733 act.sa_handler = onsig;
11736 act.sa_handler = SIG_IGN;
11739 act.sa_handler = SIG_DFL;
11743 sigfillset(&act.sa_mask);
11744 sigaction(signo, &act, 0);
11752 ignoresig(int signo)
11754 if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
11755 signal(signo, SIG_IGN);
11757 sigmode[signo - 1] = S_HARD_IGN;
11768 gotsig[signo - 1] = 1;
11769 pendingsigs = signo;
11771 if (exsig || (signo == SIGINT && !trap[SIGINT])) {
11780 * Called to execute a trap. Perhaps we should avoid entering new trap
11781 * handlers while we are executing a trap handler.
11793 savestatus = exitstatus;
11797 for (i = 0, q = gotsig; i < NSIG - 1; i++, q++) {
11805 skip = evalstring(p, SKIPEVAL);
11806 exitstatus = savestatus;
11816 * Controls whether the shell is interactive or not.
11820 setinteractive(int on)
11822 static int is_interactive;
11824 if (++on == is_interactive)
11826 is_interactive = on;
11828 setsignal(SIGQUIT);
11829 setsignal(SIGTERM);
11830 #ifndef CONFIG_FEATURE_SH_EXTRA_QUIET
11831 if(is_interactive > 1) {
11832 /* Looks like they want an interactive shell */
11833 static int do_banner;
11837 "\n\n%s Built-in shell (ash)\n"
11838 "Enter 'help' for a list of built-in commands.\n\n",
11847 #ifndef CONFIG_FEATURE_SH_EXTRA_QUIET
11848 /*** List the available builtins ***/
11850 static int helpcmd(int argc, char **argv)
11854 out1fmt("\nBuilt-in commands:\n-------------------\n");
11855 for (col = 0, i = 0; i < NUMBUILTINS; i++) {
11856 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
11857 builtincmd[i].name + 1);
11863 #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
11865 extern const struct BB_applet applets[];
11866 extern const size_t NUM_APPLETS;
11868 for (i = 0; i < NUM_APPLETS; i++) {
11870 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), applets[i].name);
11879 return EXIT_SUCCESS;
11881 #endif /* CONFIG_FEATURE_SH_EXTRA_QUIET */
11884 * Called to exit the shell.
11894 status = exitstatus;
11895 TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
11896 if (setjmp(loc.loc)) {
11897 if (exception == EXEXIT)
11902 if ((p = trap[0])) {
11908 #ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
11909 if (iflag && rootshell) {
11910 const char *hp = lookupvar("HISTFILE");
11913 save_history ( hp );
11921 static int decode_signal(const char *string, int minsig)
11924 const char *name = u_signal_names(string, &signo, minsig);
11926 return name ? signo : -1;
11931 static struct var *vartab[VTABSIZE];
11933 static int vpcmp(const void *, const void *);
11934 static struct var **findvar(struct var **, const char *);
11937 * Initialize the variable symbol tables and import the environment
11941 #ifdef CONFIG_ASH_GETOPTS
11943 * Safe version of setvar, returns 1 on success 0 on failure.
11947 setvarsafe(const char *name, const char *val, int flags)
11950 volatile int saveint;
11951 struct jmploc *volatile savehandler = handler;
11952 struct jmploc jmploc;
11955 if (setjmp(jmploc.loc))
11959 setvar(name, val, flags);
11962 handler = savehandler;
11963 RESTOREINT(saveint);
11969 * Set the value of a variable. The flags argument is ored with the
11970 * flags of the variable. If val is NULL, the variable is unset.
11974 setvar(const char *name, const char *val, int flags)
11981 q = endofname(name);
11982 p = strchrnul(q, '=');
11983 namelen = p - name;
11984 if (!namelen || p != q)
11985 sh_error("%.*s: bad variable name", namelen, name);
11990 vallen = strlen(val);
11993 p = mempcpy(nameeq = ckmalloc(namelen + vallen + 2), name, namelen);
11996 p = mempcpy(p, val, vallen);
11999 setvareq(nameeq, flags | VNOSAVE);
12005 * Same as setvar except that the variable and value are passed in
12006 * the first argument as name=value. Since the first argument will
12007 * be actually stored in the table, it should not be a string that
12009 * Called with interrupts off.
12013 setvareq(char *s, int flags)
12015 struct var *vp, **vpp;
12018 flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
12019 vp = *findvar(vpp, s);
12021 if ((vp->flags & (VREADONLY|VDYNAMIC)) == VREADONLY) {
12024 if (flags & VNOSAVE)
12027 sh_error("%.*s: is read only", strchrnul(n, '=') - n, n);
12030 if (flags & VNOSET)
12033 if (vp->func && (flags & VNOFUNC) == 0)
12034 (*vp->func)(strchrnul(s, '=') + 1);
12036 if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
12039 flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET);
12041 if (flags & VNOSET)
12044 vp = ckmalloc(sizeof (*vp));
12049 if (!(flags & (VTEXTFIXED|VSTACK|VNOSAVE)))
12057 * Process a linked list of variable assignments.
12061 listsetvar(struct strlist *list_set_var, int flags)
12063 struct strlist *lp = list_set_var;
12069 setvareq(lp->text, flags);
12070 } while ((lp = lp->next));
12076 * Find the value of a variable. Returns NULL if not set.
12080 lookupvar(const char *name)
12084 if ((v = *findvar(hashvar(name), name))) {
12087 * Dynamic variables are implemented roughly the same way they are
12088 * in bash. Namely, they're "special" so long as they aren't unset.
12089 * As soon as they're unset, they're no longer dynamic, and dynamic
12090 * lookup will no longer happen at that point. -- PFM.
12092 if((v->flags & VDYNAMIC))
12095 if(!(v->flags & VUNSET))
12096 return strchrnul(v->text, '=') + 1;
12104 * Search the environment of a builtin command.
12108 bltinlookup(const char *name)
12110 struct strlist *sp;
12112 for (sp = cmdenviron ; sp ; sp = sp->next) {
12113 if (varequal(sp->text, name))
12114 return strchrnul(sp->text, '=') + 1;
12116 return lookupvar(name);
12121 * Generate a list of variables satisfying the given conditions.
12125 listvars(int on, int off, char ***end)
12136 for (vp = *vpp ; vp ; vp = vp->next)
12137 if ((vp->flags & mask) == on) {
12138 if (ep == stackstrend())
12139 ep = growstackstr();
12140 *ep++ = (char *) vp->text;
12142 } while (++vpp < vartab + VTABSIZE);
12143 if (ep == stackstrend())
12144 ep = growstackstr();
12148 return grabstackstr(ep);
12153 * POSIX requires that 'set' (but not export or readonly) output the
12154 * variables in lexicographic order - by the locale's collating order (sigh).
12155 * Maybe we could keep them in an ordered balanced binary tree
12156 * instead of hashed lists.
12157 * For now just roll 'em through qsort for printing...
12161 showvars(const char *sep_prefix, int on, int off)
12164 char **ep, **epend;
12166 ep = listvars(on, off, &epend);
12167 qsort(ep, epend - ep, sizeof(char *), vpcmp);
12169 sep = *sep_prefix ? spcstr : sep_prefix;
12171 for (; ep < epend; ep++) {
12175 p = strchrnul(*ep, '=');
12178 q = single_quote(++p);
12180 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
12189 * The export and readonly commands.
12193 exportcmd(int argc, char **argv)
12199 int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT;
12202 notp = nextopt("p") - 'p';
12203 if (notp && ((name = *(aptr = argptr)))) {
12205 if ((p = strchr(name, '=')) != NULL) {
12208 if ((vp = *findvar(hashvar(name), name))) {
12213 setvar(name, p, flag);
12214 } while ((name = *++aptr) != NULL);
12216 showvars(argv[0], flag, 0);
12223 * Make a variable a local variable. When a variable is made local, it's
12224 * value and flags are saved in a localvar structure. The saved values
12225 * will be restored when the shell function returns. We handle the name
12226 * "-" as a special case.
12230 mklocal(char *name)
12232 struct localvar *lvp;
12237 lvp = ckmalloc(sizeof (struct localvar));
12238 if (name[0] == '-' && name[1] == '\0') {
12240 p = ckmalloc(sizeof(optlist));
12241 lvp->text = memcpy(p, optlist, sizeof(optlist));
12246 vpp = hashvar(name);
12247 vp = *findvar(vpp, name);
12248 eq = strchr(name, '=');
12251 setvareq(name, VSTRFIXED);
12253 setvar(name, NULL, VSTRFIXED);
12254 vp = *vpp; /* the new variable */
12255 lvp->flags = VUNSET;
12257 lvp->text = vp->text;
12258 lvp->flags = vp->flags;
12259 vp->flags |= VSTRFIXED|VTEXTFIXED;
12265 lvp->next = localvars;
12271 * The "local" command.
12275 localcmd(int argc, char **argv)
12280 while ((name = *argv++) != NULL) {
12288 * Called after a function returns.
12289 * Interrupts must be off.
12295 struct localvar *lvp;
12298 while ((lvp = localvars) != NULL) {
12299 localvars = lvp->next;
12301 TRACE(("poplocalvar %s", vp ? vp->text : "-"));
12302 if (vp == NULL) { /* $- saved */
12303 memcpy(optlist, lvp->text, sizeof(optlist));
12306 } else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
12307 unsetvar(vp->text);
12310 (*vp->func)(strchrnul(lvp->text, '=') + 1);
12311 if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
12313 vp->flags = lvp->flags;
12314 vp->text = lvp->text;
12322 * The unset builtin command. We unset the function before we unset the
12323 * variable to allow a function to be unset when there is a readonly variable
12324 * with the same name.
12328 unsetcmd(int argc, char **argv)
12335 while ((i = nextopt("vf")) != '\0') {
12339 for (ap = argptr; *ap ; ap++) {
12354 * Unset the specified variable.
12358 unsetvar(const char *s)
12364 vpp = findvar(hashvar(s), s);
12368 int flags = vp->flags;
12371 if (flags & VREADONLY)
12374 vp->flags &= ~VDYNAMIC;
12376 if (flags & VUNSET)
12378 if ((flags & VSTRFIXED) == 0) {
12380 if ((flags & (VTEXTFIXED|VSTACK)) == 0)
12387 vp->flags &= ~VEXPORT;
12400 * Find the appropriate entry in the hash table from the name.
12403 static struct var **
12404 hashvar(const char *p)
12406 unsigned int hashval;
12408 hashval = ((unsigned char) *p) << 4;
12409 while (*p && *p != '=')
12410 hashval += (unsigned char) *p++;
12411 return &vartab[hashval % VTABSIZE];
12417 * Compares two strings up to the first = or '\0'. The first
12418 * string must be terminated by '='; the second may be terminated by
12419 * either '=' or '\0'.
12423 varcmp(const char *p, const char *q)
12427 while ((c = *p) == (d = *q)) {
12428 if (!c || c == '=')
12442 vpcmp(const void *a, const void *b)
12444 return varcmp(*(const char **)a, *(const char **)b);
12447 static struct var **
12448 findvar(struct var **vpp, const char *name)
12450 for (; *vpp; vpp = &(*vpp)->next) {
12451 if (varequal((*vpp)->text, name)) {
12459 #include <sys/times.h>
12461 static const unsigned char timescmd_str[] = {
12462 ' ', offsetof(struct tms, tms_utime),
12463 '\n', offsetof(struct tms, tms_stime),
12464 ' ', offsetof(struct tms, tms_cutime),
12465 '\n', offsetof(struct tms, tms_cstime),
12469 static int timescmd(int ac, char **av)
12471 long int clk_tck, s, t;
12472 const unsigned char *p;
12475 clk_tck = sysconf(_SC_CLK_TCK);
12480 t = *(clock_t *)(((char *) &buf) + p[1]);
12482 out1fmt("%ldm%ld.%.3lds%c",
12484 ((t - s * clk_tck) * 1000) / clk_tck,
12486 } while (*(p += 2));
12491 #ifdef CONFIG_ASH_MATH_SUPPORT
12493 dash_arith(const char *s)
12499 result = arith(s, &errcode);
12502 sh_error("exponent less than 0");
12503 else if (errcode == -2)
12504 sh_error("divide by zero");
12505 else if (errcode == -5)
12506 sh_error("expression recursion loop detected");
12517 * The let builtin. partial stolen from GNU Bash, the Bourne Again SHell.
12518 * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
12520 * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
12524 letcmd(int argc, char **argv)
12531 sh_error("expression expected");
12532 for (ap = argv + 1; *ap; ap++) {
12533 i = dash_arith(*ap);
12538 #endif /* CONFIG_ASH_MATH_SUPPORT */
12543 * Miscellaneous builtins.
12549 #if __GLIBC__ == 2 && __GLIBC_MINOR__ < 1
12550 typedef enum __rlimit_resource rlim_t;
12556 * The read builtin. The -e option causes backslashes to escape the
12557 * following character.
12559 * This uses unbuffered input, which may be avoidable in some cases.
12563 readcmd(int argc, char **argv)
12575 #if defined(CONFIG_ASH_READ_NCHARS)
12579 struct termios tty, old_tty;
12581 #if defined(CONFIG_ASH_READ_TIMEOUT)
12585 ts.tv_sec = ts.tv_usec = 0;
12590 #if defined(CONFIG_ASH_READ_NCHARS) && defined(CONFIG_ASH_READ_TIMEOUT)
12591 while ((i = nextopt("p:rt:n:s")) != '\0')
12592 #elif defined(CONFIG_ASH_READ_NCHARS)
12593 while ((i = nextopt("p:rn:s")) != '\0')
12594 #elif defined(CONFIG_ASH_READ_TIMEOUT)
12595 while ((i = nextopt("p:rt:")) != '\0')
12597 while ((i = nextopt("p:r")) != '\0')
12602 prompt = optionarg;
12604 #if defined(CONFIG_ASH_READ_NCHARS)
12606 nchars = strtol(optionarg, &p, 10);
12608 sh_error("invalid count");
12609 nch_flag = (nchars > 0);
12615 #if defined(CONFIG_ASH_READ_TIMEOUT)
12617 ts.tv_sec = strtol(optionarg, &p, 10);
12623 ts.tv_usec = strtol(p, &p2, 10);
12625 sh_error("invalid timeout");
12627 /* normalize to usec */
12629 sh_error("invalid timeout");
12630 while (scale++ < 6)
12634 sh_error("invalid timeout");
12636 if ( ! ts.tv_sec && ! ts.tv_usec)
12637 sh_error("invalid timeout");
12647 if (prompt && isatty(0)) {
12650 if (*(ap = argptr) == NULL)
12651 sh_error("arg count");
12652 if ((ifs = bltinlookup("IFS")) == NULL)
12654 #if defined(CONFIG_ASH_READ_NCHARS)
12655 if (nch_flag || silent) {
12656 tcgetattr(0, &tty);
12659 tty.c_lflag &= ~ICANON;
12660 tty.c_cc[VMIN] = nchars;
12663 tty.c_lflag &= ~(ECHO|ECHOK|ECHONL);
12666 tcsetattr(0, TCSANOW, &tty);
12669 #if defined(CONFIG_ASH_READ_TIMEOUT)
12670 if (ts.tv_sec || ts.tv_usec) {
12674 i = select (FD_SETSIZE, &set, NULL, NULL, &ts);
12676 #if defined(CONFIG_ASH_READ_NCHARS)
12678 tcsetattr(0, TCSANOW, &old_tty);
12688 #if defined(CONFIG_ASH_READ_NCHARS)
12689 while (!nch_flag || nchars--)
12694 if (read(0, &c, 1) != 1) {
12706 if (!rflag && c == '\\') {
12712 if (startword && *ifs == ' ' && strchr(ifs, c)) {
12716 if (ap[1] != NULL && strchr(ifs, c) != NULL) {
12718 setvar(*ap, stackblock(), 0);
12727 #if defined(CONFIG_ASH_READ_NCHARS)
12728 if (nch_flag || silent)
12729 tcsetattr(0, TCSANOW, &old_tty);
12733 /* Remove trailing blanks */
12734 while ((char *)stackblock() <= --p && strchr(ifs, *p) != NULL)
12736 setvar(*ap, stackblock(), 0);
12737 while (*++ap != NULL)
12738 setvar(*ap, nullstr, 0);
12743 static int umaskcmd(int argc, char **argv)
12745 static const char permuser[3] = "ugo";
12746 static const char permmode[3] = "rwx";
12747 static const short int permmask[] = {
12748 S_IRUSR, S_IWUSR, S_IXUSR,
12749 S_IRGRP, S_IWGRP, S_IXGRP,
12750 S_IROTH, S_IWOTH, S_IXOTH
12756 int symbolic_mode = 0;
12758 while (nextopt("S") != '\0') {
12767 if ((ap = *argptr) == NULL) {
12768 if (symbolic_mode) {
12772 for (i = 0; i < 3; i++) {
12775 *p++ = permuser[i];
12777 for (j = 0; j < 3; j++) {
12778 if ((mask & permmask[3 * i + j]) == 0) {
12779 *p++ = permmode[j];
12787 out1fmt("%.4o\n", mask);
12790 if (is_digit((unsigned char) *ap)) {
12793 if (*ap >= '8' || *ap < '0')
12794 sh_error(illnum, argv[1]);
12795 mask = (mask << 3) + (*ap - '0');
12796 } while (*++ap != '\0');
12799 mask = ~mask & 0777;
12800 if (!bb_parse_mode(ap, &mask)) {
12801 sh_error("Illegal mode: %s", ap);
12803 umask(~mask & 0777);
12812 * This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and
12813 * Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with
12814 * ash by J.T. Conklin.
12822 int factor; /* multiply by to get rlim_{cur,max} values */
12826 static const struct limits limits[] = {
12828 { "time(seconds)", RLIMIT_CPU, 1, 't' },
12830 #ifdef RLIMIT_FSIZE
12831 { "file(blocks)", RLIMIT_FSIZE, 512, 'f' },
12834 { "data(kbytes)", RLIMIT_DATA, 1024, 'd' },
12836 #ifdef RLIMIT_STACK
12837 { "stack(kbytes)", RLIMIT_STACK, 1024, 's' },
12840 { "coredump(blocks)", RLIMIT_CORE, 512, 'c' },
12843 { "memory(kbytes)", RLIMIT_RSS, 1024, 'm' },
12845 #ifdef RLIMIT_MEMLOCK
12846 { "locked memory(kbytes)", RLIMIT_MEMLOCK, 1024, 'l' },
12848 #ifdef RLIMIT_NPROC
12849 { "process", RLIMIT_NPROC, 1, 'p' },
12851 #ifdef RLIMIT_NOFILE
12852 { "nofiles", RLIMIT_NOFILE, 1, 'n' },
12855 { "vmemory(kbytes)", RLIMIT_AS, 1024, 'v' },
12857 #ifdef RLIMIT_LOCKS
12858 { "locks", RLIMIT_LOCKS, 1, 'w' },
12860 { (char *) 0, 0, 0, '\0' }
12863 enum limtype { SOFT = 0x1, HARD = 0x2 };
12865 static void printlim(enum limtype how, const struct rlimit *limit,
12866 const struct limits *l)
12870 val = limit->rlim_max;
12872 val = limit->rlim_cur;
12874 if (val == RLIM_INFINITY)
12875 out1fmt("unlimited\n");
12878 out1fmt("%lld\n", (long long) val);
12883 ulimitcmd(int argc, char **argv)
12887 enum limtype how = SOFT | HARD;
12888 const struct limits *l;
12891 struct rlimit limit;
12894 while ((optc = nextopt("HSa"
12898 #ifdef RLIMIT_FSIZE
12904 #ifdef RLIMIT_STACK
12913 #ifdef RLIMIT_MEMLOCK
12916 #ifdef RLIMIT_NPROC
12919 #ifdef RLIMIT_NOFILE
12925 #ifdef RLIMIT_LOCKS
12943 for (l = limits; l->option != what; l++)
12946 set = *argptr ? 1 : 0;
12950 if (all || argptr[1])
12951 sh_error("too many arguments");
12952 if (strncmp(p, "unlimited\n", 9) == 0)
12953 val = RLIM_INFINITY;
12957 while ((c = *p++) >= '0' && c <= '9')
12959 val = (val * 10) + (long)(c - '0');
12960 if (val < (rlim_t) 0)
12964 sh_error("bad number");
12969 for (l = limits; l->name; l++) {
12970 getrlimit(l->cmd, &limit);
12971 out1fmt("%-20s ", l->name);
12972 printlim(how, &limit, l);
12977 getrlimit(l->cmd, &limit);
12980 limit.rlim_max = val;
12982 limit.rlim_cur = val;
12983 if (setrlimit(l->cmd, &limit) < 0)
12984 sh_error("error setting limit (%m)");
12986 printlim(how, &limit, l);
12992 #ifdef CONFIG_ASH_MATH_SUPPORT
12994 /* Copyright (c) 2001 Aaron Lehmann <aaronl@vitelus.com>
12996 Permission is hereby granted, free of charge, to any person obtaining
12997 a copy of this software and associated documentation files (the
12998 "Software"), to deal in the Software without restriction, including
12999 without limitation the rights to use, copy, modify, merge, publish,
13000 distribute, sublicense, and/or sell copies of the Software, and to
13001 permit persons to whom the Software is furnished to do so, subject to
13002 the following conditions:
13004 The above copyright notice and this permission notice shall be
13005 included in all copies or substantial portions of the Software.
13007 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13008 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
13009 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
13010 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
13011 CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
13012 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
13013 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
13016 /* This is my infix parser/evaluator. It is optimized for size, intended
13017 * as a replacement for yacc-based parsers. However, it may well be faster
13018 * than a comparable parser written in yacc. The supported operators are
13019 * listed in #defines below. Parens, order of operations, and error handling
13020 * are supported. This code is thread safe. The exact expression format should
13021 * be that which POSIX specifies for shells. */
13023 /* The code uses a simple two-stack algorithm. See
13024 * http://www.onthenet.com.au/~grahamis/int2008/week02/lect02.html
13025 * for a detailed explanation of the infix-to-postfix algorithm on which
13026 * this is based (this code differs in that it applies operators immediately
13027 * to the stack instead of adding them to a queue to end up with an
13030 /* To use the routine, call it with an expression string and error return
13034 * Aug 24, 2001 Manuel Novoa III
13036 * Reduced the generated code size by about 30% (i386) and fixed several bugs.
13038 * 1) In arith_apply():
13039 * a) Cached values of *numptr and &(numptr[-1]).
13040 * b) Removed redundant test for zero denominator.
13043 * a) Eliminated redundant code for processing operator tokens by moving
13044 * to a table-based implementation. Also folded handling of parens
13046 * b) Combined all 3 loops which called arith_apply to reduce generated
13047 * code size at the cost of speed.
13049 * 3) The following expressions were treated as valid by the original code:
13050 * 1() , 0! , 1 ( *3 ) .
13051 * These bugs have been fixed by internally enclosing the expression in
13052 * parens and then checking that all binary ops and right parens are
13053 * preceded by a valid expression (NUM_TOKEN).
13055 * Note: It may be desirable to replace Aaron's test for whitespace with
13056 * ctype's isspace() if it is used by another busybox applet or if additional
13057 * whitespace chars should be considered. Look below the "#include"s for a
13058 * precompiler test.
13062 * Aug 26, 2001 Manuel Novoa III
13064 * Return 0 for null expressions. Pointed out by Vladimir Oleynik.
13066 * Merge in Aaron's comments previously posted to the busybox list,
13067 * modified slightly to take account of my changes to the code.
13072 * (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
13074 * - allow access to variable,
13075 * used recursive find value indirection (c=2*2; a="c"; $((a+=2)) produce 6)
13076 * - realize assign syntax (VAR=expr, +=, *= etc)
13077 * - realize exponentiation (** operator)
13078 * - realize comma separated - expr, expr
13079 * - realise ++expr --expr expr++ expr--
13080 * - realise expr ? expr : expr (but, second expr calculate always)
13081 * - allow hexadecimal and octal numbers
13082 * - was restored loses XOR operator
13083 * - remove one goto label, added three ;-)
13084 * - protect $((num num)) as true zero expr (Manuel`s error)
13085 * - always use special isspace(), see comment from bash ;-)
13089 #define arith_isspace(arithval) \
13090 (arithval == ' ' || arithval == '\n' || arithval == '\t')
13093 typedef unsigned char operator;
13095 /* An operator's token id is a bit of a bitfield. The lower 5 bits are the
13096 * precedence, and 3 high bits are an ID unique across operators of that
13097 * precedence. The ID portion is so that multiple operators can have the
13098 * same precedence, ensuring that the leftmost one is evaluated first.
13099 * Consider * and /. */
13101 #define tok_decl(prec,id) (((id)<<5)|(prec))
13102 #define PREC(op) ((op) & 0x1F)
13104 #define TOK_LPAREN tok_decl(0,0)
13106 #define TOK_COMMA tok_decl(1,0)
13108 #define TOK_ASSIGN tok_decl(2,0)
13109 #define TOK_AND_ASSIGN tok_decl(2,1)
13110 #define TOK_OR_ASSIGN tok_decl(2,2)
13111 #define TOK_XOR_ASSIGN tok_decl(2,3)
13112 #define TOK_PLUS_ASSIGN tok_decl(2,4)
13113 #define TOK_MINUS_ASSIGN tok_decl(2,5)
13114 #define TOK_LSHIFT_ASSIGN tok_decl(2,6)
13115 #define TOK_RSHIFT_ASSIGN tok_decl(2,7)
13117 #define TOK_MUL_ASSIGN tok_decl(3,0)
13118 #define TOK_DIV_ASSIGN tok_decl(3,1)
13119 #define TOK_REM_ASSIGN tok_decl(3,2)
13121 /* all assign is right associativity and precedence eq, but (7+3)<<5 > 256 */
13122 #define convert_prec_is_assing(prec) do { if(prec == 3) prec = 2; } while(0)
13124 /* conditional is right associativity too */
13125 #define TOK_CONDITIONAL tok_decl(4,0)
13126 #define TOK_CONDITIONAL_SEP tok_decl(4,1)
13128 #define TOK_OR tok_decl(5,0)
13130 #define TOK_AND tok_decl(6,0)
13132 #define TOK_BOR tok_decl(7,0)
13134 #define TOK_BXOR tok_decl(8,0)
13136 #define TOK_BAND tok_decl(9,0)
13138 #define TOK_EQ tok_decl(10,0)
13139 #define TOK_NE tok_decl(10,1)
13141 #define TOK_LT tok_decl(11,0)
13142 #define TOK_GT tok_decl(11,1)
13143 #define TOK_GE tok_decl(11,2)
13144 #define TOK_LE tok_decl(11,3)
13146 #define TOK_LSHIFT tok_decl(12,0)
13147 #define TOK_RSHIFT tok_decl(12,1)
13149 #define TOK_ADD tok_decl(13,0)
13150 #define TOK_SUB tok_decl(13,1)
13152 #define TOK_MUL tok_decl(14,0)
13153 #define TOK_DIV tok_decl(14,1)
13154 #define TOK_REM tok_decl(14,2)
13156 /* exponent is right associativity */
13157 #define TOK_EXPONENT tok_decl(15,1)
13159 /* For now unary operators. */
13160 #define UNARYPREC 16
13161 #define TOK_BNOT tok_decl(UNARYPREC,0)
13162 #define TOK_NOT tok_decl(UNARYPREC,1)
13164 #define TOK_UMINUS tok_decl(UNARYPREC+1,0)
13165 #define TOK_UPLUS tok_decl(UNARYPREC+1,1)
13167 #define PREC_PRE (UNARYPREC+2)
13169 #define TOK_PRE_INC tok_decl(PREC_PRE, 0)
13170 #define TOK_PRE_DEC tok_decl(PREC_PRE, 1)
13172 #define PREC_POST (UNARYPREC+3)
13174 #define TOK_POST_INC tok_decl(PREC_POST, 0)
13175 #define TOK_POST_DEC tok_decl(PREC_POST, 1)
13177 #define SPEC_PREC (UNARYPREC+4)
13179 #define TOK_NUM tok_decl(SPEC_PREC, 0)
13180 #define TOK_RPAREN tok_decl(SPEC_PREC, 1)
13182 #define NUMPTR (*numstackptr)
13184 static inline int tok_have_assign(operator op)
13186 operator prec = PREC(op);
13188 convert_prec_is_assing(prec);
13189 return (prec == PREC(TOK_ASSIGN) ||
13190 prec == PREC_PRE || prec == PREC_POST);
13193 static inline int is_right_associativity(operator prec)
13195 return (prec == PREC(TOK_ASSIGN) || prec == PREC(TOK_EXPONENT) ||
13196 prec == PREC(TOK_CONDITIONAL));
13200 typedef struct ARITCH_VAR_NUM {
13202 arith_t contidional_second_val;
13203 char contidional_second_val_initialized;
13204 char *var; /* if NULL then is regular number,
13205 else is variable name */
13209 typedef struct CHK_VAR_RECURSIVE_LOOPED {
13211 struct CHK_VAR_RECURSIVE_LOOPED *next;
13212 } chk_var_recursive_looped_t;
13214 static chk_var_recursive_looped_t *prev_chk_var_recursive;
13217 static int arith_lookup_val(v_n_t *t)
13220 const char * p = lookupvar(t->var);
13225 /* recursive try as expression */
13226 chk_var_recursive_looped_t *cur;
13227 chk_var_recursive_looped_t cur_save;
13229 for(cur = prev_chk_var_recursive; cur; cur = cur->next) {
13230 if(strcmp(cur->var, t->var) == 0) {
13231 /* expression recursion loop detected */
13235 /* save current lookuped var name */
13236 cur = prev_chk_var_recursive;
13237 cur_save.var = t->var;
13238 cur_save.next = cur;
13239 prev_chk_var_recursive = &cur_save;
13241 t->val = arith (p, &errcode);
13242 /* restore previous ptr after recursiving */
13243 prev_chk_var_recursive = cur;
13246 /* allow undefined var as 0 */
13253 /* "applying" a token means performing it on the top elements on the integer
13254 * stack. For a unary operator it will only change the top element, but a
13255 * binary operator will pop two arguments and push a result */
13257 arith_apply(operator op, v_n_t *numstack, v_n_t **numstackptr)
13260 arith_t numptr_val, rez;
13261 int ret_arith_lookup_val;
13263 if (NUMPTR == numstack) goto err; /* There is no operator that can work
13264 without arguments */
13265 numptr_m1 = NUMPTR - 1;
13267 /* check operand is var with noninteger value */
13268 ret_arith_lookup_val = arith_lookup_val(numptr_m1);
13269 if(ret_arith_lookup_val)
13270 return ret_arith_lookup_val;
13272 rez = numptr_m1->val;
13273 if (op == TOK_UMINUS)
13275 else if (op == TOK_NOT)
13277 else if (op == TOK_BNOT)
13279 else if (op == TOK_POST_INC || op == TOK_PRE_INC)
13281 else if (op == TOK_POST_DEC || op == TOK_PRE_DEC)
13283 else if (op != TOK_UPLUS) {
13284 /* Binary operators */
13286 /* check and binary operators need two arguments */
13287 if (numptr_m1 == numstack) goto err;
13289 /* ... and they pop one */
13292 if (op == TOK_CONDITIONAL) {
13293 if(! numptr_m1->contidional_second_val_initialized) {
13294 /* protect $((expr1 ? expr2)) without ": expr" */
13297 rez = numptr_m1->contidional_second_val;
13298 } else if(numptr_m1->contidional_second_val_initialized) {
13299 /* protect $((expr1 : expr2)) without "expr ? " */
13302 numptr_m1 = NUMPTR - 1;
13303 if(op != TOK_ASSIGN) {
13304 /* check operand is var with noninteger value for not '=' */
13305 ret_arith_lookup_val = arith_lookup_val(numptr_m1);
13306 if(ret_arith_lookup_val)
13307 return ret_arith_lookup_val;
13309 if (op == TOK_CONDITIONAL) {
13310 numptr_m1->contidional_second_val = rez;
13312 rez = numptr_m1->val;
13313 if (op == TOK_BOR || op == TOK_OR_ASSIGN)
13315 else if (op == TOK_OR)
13316 rez = numptr_val || rez;
13317 else if (op == TOK_BAND || op == TOK_AND_ASSIGN)
13319 else if (op == TOK_BXOR || op == TOK_XOR_ASSIGN)
13321 else if (op == TOK_AND)
13322 rez = rez && numptr_val;
13323 else if (op == TOK_EQ)
13324 rez = (rez == numptr_val);
13325 else if (op == TOK_NE)
13326 rez = (rez != numptr_val);
13327 else if (op == TOK_GE)
13328 rez = (rez >= numptr_val);
13329 else if (op == TOK_RSHIFT || op == TOK_RSHIFT_ASSIGN)
13330 rez >>= numptr_val;
13331 else if (op == TOK_LSHIFT || op == TOK_LSHIFT_ASSIGN)
13332 rez <<= numptr_val;
13333 else if (op == TOK_GT)
13334 rez = (rez > numptr_val);
13335 else if (op == TOK_LT)
13336 rez = (rez < numptr_val);
13337 else if (op == TOK_LE)
13338 rez = (rez <= numptr_val);
13339 else if (op == TOK_MUL || op == TOK_MUL_ASSIGN)
13341 else if (op == TOK_ADD || op == TOK_PLUS_ASSIGN)
13343 else if (op == TOK_SUB || op == TOK_MINUS_ASSIGN)
13345 else if (op == TOK_ASSIGN || op == TOK_COMMA)
13347 else if (op == TOK_CONDITIONAL_SEP) {
13348 if (numptr_m1 == numstack) {
13349 /* protect $((expr : expr)) without "expr ? " */
13352 numptr_m1->contidional_second_val_initialized = op;
13353 numptr_m1->contidional_second_val = numptr_val;
13355 else if (op == TOK_CONDITIONAL) {
13357 numptr_val : numptr_m1->contidional_second_val;
13359 else if(op == TOK_EXPONENT) {
13361 return -3; /* exponent less than 0 */
13366 while(numptr_val--)
13371 else if(numptr_val==0) /* zero divisor check */
13373 else if (op == TOK_DIV || op == TOK_DIV_ASSIGN)
13375 else if (op == TOK_REM || op == TOK_REM_ASSIGN)
13378 if(tok_have_assign(op)) {
13381 if(numptr_m1->var == NULL) {
13385 /* save to shell variable */
13386 #ifdef CONFIG_ASH_MATH_SUPPORT_64
13387 snprintf(buf, sizeof(buf), "%lld", arith_t_type rez);
13389 snprintf(buf, sizeof(buf), "%ld", arith_t_type rez);
13391 setvar(numptr_m1->var, buf, 0);
13392 /* after saving, make previous value for v++ or v-- */
13393 if(op == TOK_POST_INC)
13395 else if(op == TOK_POST_DEC)
13398 numptr_m1->val = rez;
13399 /* protect geting var value, is number now */
13400 numptr_m1->var = NULL;
13405 /* longest must first */
13406 static const char op_tokens[] = {
13407 '<','<','=',0, TOK_LSHIFT_ASSIGN,
13408 '>','>','=',0, TOK_RSHIFT_ASSIGN,
13409 '<','<', 0, TOK_LSHIFT,
13410 '>','>', 0, TOK_RSHIFT,
13411 '|','|', 0, TOK_OR,
13412 '&','&', 0, TOK_AND,
13413 '!','=', 0, TOK_NE,
13414 '<','=', 0, TOK_LE,
13415 '>','=', 0, TOK_GE,
13416 '=','=', 0, TOK_EQ,
13417 '|','=', 0, TOK_OR_ASSIGN,
13418 '&','=', 0, TOK_AND_ASSIGN,
13419 '*','=', 0, TOK_MUL_ASSIGN,
13420 '/','=', 0, TOK_DIV_ASSIGN,
13421 '%','=', 0, TOK_REM_ASSIGN,
13422 '+','=', 0, TOK_PLUS_ASSIGN,
13423 '-','=', 0, TOK_MINUS_ASSIGN,
13424 '-','-', 0, TOK_POST_DEC,
13425 '^','=', 0, TOK_XOR_ASSIGN,
13426 '+','+', 0, TOK_POST_INC,
13427 '*','*', 0, TOK_EXPONENT,
13431 '=', 0, TOK_ASSIGN,
13443 '?', 0, TOK_CONDITIONAL,
13444 ':', 0, TOK_CONDITIONAL_SEP,
13445 ')', 0, TOK_RPAREN,
13446 '(', 0, TOK_LPAREN,
13450 #define endexpression &op_tokens[sizeof(op_tokens)-7]
13453 static arith_t arith (const char *expr, int *perrcode)
13455 register char arithval; /* Current character under analysis */
13456 operator lasttok, op;
13459 const char *p = endexpression;
13462 size_t datasizes = strlen(expr) + 2;
13464 /* Stack of integers */
13465 /* The proof that there can be no more than strlen(startbuf)/2+1 integers
13466 * in any given correct or incorrect expression is left as an exercise to
13468 v_n_t *numstack = alloca(((datasizes)/2)*sizeof(v_n_t)),
13469 *numstackptr = numstack;
13470 /* Stack of operator tokens */
13471 operator *stack = alloca((datasizes) * sizeof(operator)),
13474 *stackptr++ = lasttok = TOK_LPAREN; /* start off with a left paren */
13475 *perrcode = errcode = 0;
13478 if ((arithval = *expr) == 0) {
13479 if (p == endexpression) {
13480 /* Null expression. */
13484 /* This is only reached after all tokens have been extracted from the
13485 * input stream. If there are still tokens on the operator stack, they
13486 * are to be applied in order. At the end, there should be a final
13487 * result on the integer stack */
13489 if (expr != endexpression + 1) {
13490 /* If we haven't done so already, */
13491 /* append a closing right paren */
13492 expr = endexpression;
13493 /* and let the loop process it. */
13496 /* At this point, we're done with the expression. */
13497 if (numstackptr != numstack+1) {
13498 /* ... but if there isn't, it's bad */
13500 return (*perrcode = -1);
13502 if(numstack->var) {
13503 /* expression is $((var)) only, lookup now */
13504 errcode = arith_lookup_val(numstack);
13507 *perrcode = errcode;
13508 return numstack->val;
13510 /* Continue processing the expression. */
13511 if (arith_isspace(arithval)) {
13512 /* Skip whitespace */
13515 if((p = endofname(expr)) != expr) {
13516 size_t var_name_size = (p-expr) + 1; /* trailing zero */
13518 numstackptr->var = alloca(var_name_size);
13519 safe_strncpy(numstackptr->var, expr, var_name_size);
13522 numstackptr->contidional_second_val_initialized = 0;
13526 } else if (is_digit(arithval)) {
13527 numstackptr->var = NULL;
13528 #ifdef CONFIG_ASH_MATH_SUPPORT_64
13529 numstackptr->val = strtoll(expr, (char **) &expr, 0);
13531 numstackptr->val = strtol(expr, (char **) &expr, 0);
13535 for(p = op_tokens; ; p++) {
13539 /* strange operator not found */
13542 for(o = expr; *p && *o == *p; p++)
13549 /* skip tail uncompared token */
13552 /* skip zero delim */
13557 /* post grammar: a++ reduce to num */
13558 if(lasttok == TOK_POST_INC || lasttok == TOK_POST_DEC)
13561 /* Plus and minus are binary (not unary) _only_ if the last
13562 * token was as number, or a right paren (which pretends to be
13563 * a number, since it evaluates to one). Think about it.
13564 * It makes sense. */
13565 if (lasttok != TOK_NUM) {
13581 /* We don't want a unary operator to cause recursive descent on the
13582 * stack, because there can be many in a row and it could cause an
13583 * operator to be evaluated before its argument is pushed onto the
13584 * integer stack. */
13585 /* But for binary operators, "apply" everything on the operator
13586 * stack until we find an operator with a lesser priority than the
13587 * one we have just extracted. */
13588 /* Left paren is given the lowest priority so it will never be
13589 * "applied" in this way.
13590 * if associativity is right and priority eq, applied also skip
13593 if ((prec > 0 && prec < UNARYPREC) || prec == SPEC_PREC) {
13594 /* not left paren or unary */
13595 if (lasttok != TOK_NUM) {
13596 /* binary op must be preceded by a num */
13599 while (stackptr != stack) {
13600 if (op == TOK_RPAREN) {
13601 /* The algorithm employed here is simple: while we don't
13602 * hit an open paren nor the bottom of the stack, pop
13603 * tokens and apply them */
13604 if (stackptr[-1] == TOK_LPAREN) {
13606 /* Any operator directly after a */
13608 /* close paren should consider itself binary */
13612 operator prev_prec = PREC(stackptr[-1]);
13614 convert_prec_is_assing(prec);
13615 convert_prec_is_assing(prev_prec);
13616 if (prev_prec < prec)
13618 /* check right assoc */
13619 if(prev_prec == prec && is_right_associativity(prec))
13622 errcode = arith_apply(*--stackptr, numstack, &numstackptr);
13623 if(errcode) goto ret;
13625 if (op == TOK_RPAREN) {
13630 /* Push this operator to the stack and remember it. */
13631 *stackptr++ = lasttok = op;
13638 #endif /* CONFIG_ASH_MATH_SUPPORT */
13642 const char *bb_applet_name = "debug stuff usage";
13643 int main(int argc, char **argv)
13645 return ash_main(argc, argv);
13650 * Copyright (c) 1989, 1991, 1993, 1994
13651 * The Regents of the University of California. All rights reserved.
13653 * This code is derived from software contributed to Berkeley by
13654 * Kenneth Almquist.
13656 * Redistribution and use in source and binary forms, with or without
13657 * modification, are permitted provided that the following conditions
13659 * 1. Redistributions of source code must retain the above copyright
13660 * notice, this list of conditions and the following disclaimer.
13661 * 2. Redistributions in binary form must reproduce the above copyright
13662 * notice, this list of conditions and the following disclaimer in the
13663 * documentation and/or other materials provided with the distribution.
13664 * 3. Neither the name of the University nor the names of its contributors
13665 * may be used to endorse or promote products derived from this software
13666 * without specific prior written permission.
13668 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
13669 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
13670 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
13671 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
13672 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
13673 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
13674 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13675 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
13676 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
13677 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF