1 /* vi: set sw=4 ts=4: */
3 * ash shell port for busybox
5 * Copyright (c) 1989, 1991, 1993, 1994
6 * The Regents of the University of California. All rights reserved.
8 * Copyright (c) 1997-2005 Herbert Xu <herbert@gondor.apana.org.au>
9 * was re-ported from NetBSD and debianized.
12 * This code is derived from software contributed to Berkeley by
15 * Licensed under the GPL v2 or later, see the file LICENSE in this tarball.
17 * Original BSD copyright notice is retained at the end of this file.
21 * rewrite arith.y to micro stack based cryptic algorithm by
22 * Copyright (c) 2001 Aaron Lehmann <aaronl@vitelus.com>
24 * Modified by Paul Mundt <lethal@linux-sh.org> (c) 2004 to support
27 * Modified by Vladimir Oleynik <dzo@simtreas.ru> (c) 2001-2005 to be
28 * used in busybox and size optimizations,
29 * rewrote arith (see notes to this), added locale support,
30 * rewrote dynamic variables.
36 * The follow should be set to reflect the type of system you have:
37 * JOBS -> 1 if you have Berkeley job control, 0 otherwise.
38 * define SYSV if you are running under System V.
39 * define DEBUG=1 to compile in debugging ('set -o debug' to turn on)
40 * define DEBUG=2 to compile in and turn on debugging.
42 * When debugging is on, debugging info will be written to ./trace and
43 * a quit signal will generate a core dump.
56 #include <sys/types.h>
57 #include <sys/ioctl.h>
58 #include <sys/param.h>
59 #include <sys/resource.h>
88 #ifdef CONFIG_ASH_JOB_CONTROL
94 #if JOBS || defined(CONFIG_ASH_READ_NCHARS)
102 static int *dash_errno;
104 #define errno (*dash_errno)
107 #if defined(__uClinux__)
108 #error "Do not even bother, ash will not run on uClinux"
112 #define _DIAGASSERT(assert_expr) assert(assert_expr)
114 #define _DIAGASSERT(assert_expr)
118 #ifdef CONFIG_ASH_ALIAS
131 static struct alias *lookupalias(const char *, int);
132 static int aliascmd(int, char **);
133 static int unaliascmd(int, char **);
134 static void rmaliases(void);
135 static int unalias(const char *);
136 static void printalias(const struct alias *);
142 static void setpwd(const char *, int);
148 * Types of operations (passed to the errmsg routine).
152 static const char not_found_msg[] = "%s: not found";
155 #define E_OPEN "No such file" /* opening a file */
156 #define E_CREAT "Directory nonexistent" /* creating a file */
157 #define E_EXEC not_found_msg+4 /* executing a program */
160 * We enclose jmp_buf in a structure so that we can declare pointers to
161 * jump locations. The global variable handler contains the location to
162 * jump to when an exception occurs, and the global variable exception
163 * contains a code identifying the exception. To implement nested
164 * exception handlers, the user should save the value of handler on entry
165 * to an inner scope, set handler to point to a jmploc structure for the
166 * inner scope, and restore handler on exit from the scope.
173 static struct jmploc *handler;
174 static int exception;
175 static volatile int suppressint;
176 static volatile sig_atomic_t intpending;
179 #define EXINT 0 /* SIGINT received */
180 #define EXERROR 1 /* a generic error */
181 #define EXSHELLPROC 2 /* execute a shell procedure */
182 #define EXEXEC 3 /* command execution failed */
183 #define EXEXIT 4 /* exit the shell */
184 #define EXSIG 5 /* trapped signal in wait(1) */
187 /* do we generate EXSIG events */
189 /* last pending signal */
190 static volatile sig_atomic_t pendingsigs;
193 * These macros allow the user to suspend the handling of interrupt signals
194 * over a period of time. This is similar to SIGHOLD to or sigblock, but
195 * much more efficient and portable. (But hacking the kernel is so much
196 * more fun than worrying about efficiency and portability. :-))
199 #define xbarrier() ({ __asm__ __volatile__ ("": : :"memory"); })
206 #define SAVEINT(v) ((v) = suppressint)
207 #define RESTOREINT(v) \
210 if ((suppressint = (v)) == 0 && intpending) onint(); \
221 /* EXSIG is turned off by evalbltin(). */
224 static void exraise(int) ATTRIBUTE_NORETURN;
225 static void onint(void) ATTRIBUTE_NORETURN;
227 static void sh_error(const char *, ...) ATTRIBUTE_NORETURN;
228 static void exerror(int, const char *, ...) ATTRIBUTE_NORETURN;
230 static void sh_warnx(const char *, ...);
232 #ifdef CONFIG_ASH_OPTIMIZE_FOR_SIZE
235 if (--suppressint == 0 && intpending) {
239 #define INTON inton()
240 static void forceinton(void)
246 #define FORCEINTON forceinton()
251 if (--suppressint == 0 && intpending) onint(); \
258 if (intpending) onint(); \
261 #endif /* CONFIG_ASH_OPTIMIZE_FOR_SIZE */
266 struct strlist *next;
272 struct strlist *list;
273 struct strlist **lastp;
279 #define EXP_FULL 0x1 /* perform word splitting & file globbing */
280 #define EXP_TILDE 0x2 /* do normal tilde expansion */
281 #define EXP_VARTILDE 0x4 /* expand tildes in an assignment */
282 #define EXP_REDIR 0x8 /* file glob for a redirection (1 match only) */
283 #define EXP_CASE 0x10 /* keeps quotes around for CASE pattern */
284 #define EXP_RECORD 0x20 /* need to record arguments for ifs breakup */
285 #define EXP_VARTILDE2 0x40 /* expand tildes after colons only */
286 #define EXP_WORD 0x80 /* expand word in parameter expansion */
287 #define EXP_QWORD 0x100 /* expand word in quoted parameter expansion */
291 static void expandarg(union node *, struct arglist *, int);
292 #define rmescapes(p) _rmescapes((p), 0)
293 static char *_rmescapes(char *, int);
294 static int casematch(union node *, char *);
296 #ifdef CONFIG_ASH_MATH_SUPPORT
297 static void expari(int);
302 static char *commandname; /* currently executing command */
303 static struct strlist *cmdenviron; /* environment for builtin command */
304 static int exitstatus; /* exit status of last command */
305 static int back_exitstatus; /* exit status of backquoted command */
308 struct backcmd { /* result of evalbackcmd */
309 int fd; /* file descriptor to read from */
310 char *buf; /* buffer */
311 int nleft; /* number of chars in buffer */
312 struct job *jp; /* job structure for command */
316 * This file was generated by the mknodes program.
352 union node *redirect;
359 struct nodelist *cmdlist;
366 union node *redirect;
381 union node *elsepart;
412 struct nodelist *backquote;
452 struct nredir nredir;
453 struct nbinary nbinary;
457 struct nclist nclist;
467 struct nodelist *next;
478 static void freefunc(struct funcnode *);
481 /* control characters in argument strings */
482 #define CTL_FIRST '\201' /* first 'special' character */
483 #define CTLESC '\201' /* escape next character */
484 #define CTLVAR '\202' /* variable defn */
485 #define CTLENDVAR '\203'
486 #define CTLBACKQ '\204'
487 #define CTLQUOTE 01 /* ored with CTLBACKQ code if in quotes */
488 /* CTLBACKQ | CTLQUOTE == '\205' */
489 #define CTLARI '\206' /* arithmetic expression */
490 #define CTLENDARI '\207'
491 #define CTLQUOTEMARK '\210'
492 #define CTL_LAST '\210' /* last 'special' character */
494 /* variable substitution byte (follows CTLVAR) */
495 #define VSTYPE 0x0f /* type of variable substitution */
496 #define VSNUL 0x10 /* colon--treat the empty string as unset */
497 #define VSQUOTE 0x80 /* inside double quotes--suppress splitting */
499 /* values of VSTYPE field */
500 #define VSNORMAL 0x1 /* normal variable: $var or ${var} */
501 #define VSMINUS 0x2 /* ${var-text} */
502 #define VSPLUS 0x3 /* ${var+text} */
503 #define VSQUESTION 0x4 /* ${var?message} */
504 #define VSASSIGN 0x5 /* ${var=text} */
505 #define VSTRIMRIGHT 0x6 /* ${var%pattern} */
506 #define VSTRIMRIGHTMAX 0x7 /* ${var%%pattern} */
507 #define VSTRIMLEFT 0x8 /* ${var#pattern} */
508 #define VSTRIMLEFTMAX 0x9 /* ${var##pattern} */
509 #define VSLENGTH 0xa /* ${#var} */
511 /* values of checkkwd variable */
516 #define IBUFSIZ (BUFSIZ + 1)
519 * NEOF is returned by parsecmd when it encounters an end of file. It
520 * must be distinct from NULL, so we use the address of a variable that
521 * happens to be handy.
523 static int plinno = 1; /* input line number */
525 /* number of characters left in input buffer */
526 static int parsenleft; /* copy of parsefile->nleft */
527 static int parselleft; /* copy of parsefile->lleft */
529 /* next character in input buffer */
530 static char *parsenextc; /* copy of parsefile->nextc */
533 struct strpush *prev; /* preceding string on stack */
536 #ifdef CONFIG_ASH_ALIAS
537 struct alias *ap; /* if push was associated with an alias */
539 char *string; /* remember the string since it may change */
543 struct parsefile *prev; /* preceding file on stack */
544 int linno; /* current line */
545 int fd; /* file descriptor (or -1 if string) */
546 int nleft; /* number of chars left in this line */
547 int lleft; /* number of chars left in this buffer */
548 char *nextc; /* next char in buffer */
549 char *buf; /* input buffer */
550 struct strpush *strpush; /* for pushing strings at this level */
551 struct strpush basestrpush; /* so pushing one is fast */
554 static struct parsefile basepf; /* top level input file */
555 #define basebuf bb_common_bufsiz1 /* buffer for top level input file */
556 static struct parsefile *parsefile = &basepf; /* current input file */
559 static int tokpushback; /* last token pushed back */
560 #define NEOF ((union node *)&tokpushback)
561 static int parsebackquote; /* nonzero if we are inside backquotes */
562 static int doprompt; /* if set, prompt the user */
563 static int needprompt; /* true if interactive and at start of line */
564 static int lasttoken; /* last token read */
565 static char *wordtext; /* text of last word returned by readtoken */
567 static struct nodelist *backquotelist;
568 static union node *redirnode;
569 static struct heredoc *heredoc;
570 static int quoteflag; /* set if (part of) last token was quoted */
571 static int startlinno; /* line # where last token started */
573 static union node *parsecmd(int);
574 static void fixredir(union node *, const char *, int);
575 static const char *const *findkwd(const char *);
576 static char *endofname(const char *);
580 typedef void *pointer;
582 static char nullstr[1]; /* zero length string */
583 static const char spcstr[] = " ";
584 static const char snlfmt[] = "%s\n";
585 static const char dolatstr[] = { CTLVAR, VSNORMAL|VSQUOTE, '@', '=', '\0' };
586 static const char illnum[] = "Illegal number: %s";
587 static const char homestr[] = "HOME";
590 #define TRACE(param) trace param
591 #define TRACEV(param) tracev param
594 #define TRACEV(param)
597 #if !defined(__GNUC__) || (__GNUC__ == 2 && __GNUC_MINOR__ < 96)
598 #define __builtin_expect(x, expected_value) (x)
601 #define xlikely(x) __builtin_expect((x),1)
616 #define TENDBQUOTE 12
634 /* first char is indicating which tokens mark the end of a list */
635 static const char *const tokname_array[] = {
650 /* the following are keywords */
669 static const char *tokname(int tok)
675 sprintf(buf + (tok >= TSEMI), "%s%c",
676 tokname_array[tok] + 1, (tok >= TSEMI ? '"' : 0));
683 * Most machines require the value returned from malloc to be aligned
684 * in some way. The following macro will get this right on many machines.
687 #define SHELL_SIZE (sizeof(union {int i; char *cp; double d; }) - 1)
689 * It appears that grabstackstr() will barf with such alignments
690 * because stalloc() will return a string allocated in a new stackblock.
692 #define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE)
695 * This file was generated by the mksyntax program.
700 #define CWORD 0 /* character is nothing special */
701 #define CNL 1 /* newline character */
702 #define CBACK 2 /* a backslash character */
703 #define CSQUOTE 3 /* single quote */
704 #define CDQUOTE 4 /* double quote */
705 #define CENDQUOTE 5 /* a terminating quote */
706 #define CBQUOTE 6 /* backwards single quote */
707 #define CVAR 7 /* a dollar sign */
708 #define CENDVAR 8 /* a '}' character */
709 #define CLP 9 /* a left paren in arithmetic */
710 #define CRP 10 /* a right paren in arithmetic */
711 #define CENDFILE 11 /* end of file */
712 #define CCTL 12 /* like CWORD, except it must be escaped */
713 #define CSPCL 13 /* these terminate a word */
714 #define CIGN 14 /* character should be ignored */
716 #ifdef CONFIG_ASH_ALIAS
720 #define PEOA_OR_PEOF PEOA
724 #define PEOA_OR_PEOF PEOF
727 #define is_digit(c) ((unsigned)((c) - '0') <= 9)
728 #define is_name(c) ((c) == '_' || isalpha((unsigned char)(c)))
729 #define is_in_name(c) ((c) == '_' || isalnum((unsigned char)(c)))
731 /* C99 say: "char" declaration may be signed or unsigned default */
732 #define SC2INT(chr2may_be_negative_int) (int)((signed char)chr2may_be_negative_int)
735 * is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
736 * (assuming ascii char codes, as the original implementation did)
738 #define is_special(c) \
739 ( (((unsigned int)c) - 33 < 32) \
740 && ((0xc1ff920dUL >> (((unsigned int)c) - 33)) & 1))
742 #define digit_val(c) ((c) - '0')
745 * This file was generated by the mksyntax program.
748 #ifdef CONFIG_ASH_OPTIMIZE_FOR_SIZE
749 #define USE_SIT_FUNCTION
752 /* number syntax index */
753 #define BASESYNTAX 0 /* not in quotes */
754 #define DQSYNTAX 1 /* in double quotes */
755 #define SQSYNTAX 2 /* in single quotes */
756 #define ARISYNTAX 3 /* in arithmetic */
758 #ifdef CONFIG_ASH_MATH_SUPPORT
759 static const char S_I_T[][4] = {
760 #ifdef CONFIG_ASH_ALIAS
761 {CSPCL, CIGN, CIGN, CIGN}, /* 0, PEOA */
763 {CSPCL, CWORD, CWORD, CWORD}, /* 1, ' ' */
764 {CNL, CNL, CNL, CNL}, /* 2, \n */
765 {CWORD, CCTL, CCTL, CWORD}, /* 3, !*-/:=?[]~ */
766 {CDQUOTE, CENDQUOTE, CWORD, CWORD}, /* 4, '"' */
767 {CVAR, CVAR, CWORD, CVAR}, /* 5, $ */
768 {CSQUOTE, CWORD, CENDQUOTE, CWORD}, /* 6, "'" */
769 {CSPCL, CWORD, CWORD, CLP}, /* 7, ( */
770 {CSPCL, CWORD, CWORD, CRP}, /* 8, ) */
771 {CBACK, CBACK, CCTL, CBACK}, /* 9, \ */
772 {CBQUOTE, CBQUOTE, CWORD, CBQUOTE}, /* 10, ` */
773 {CENDVAR, CENDVAR, CWORD, CENDVAR}, /* 11, } */
774 #ifndef USE_SIT_FUNCTION
775 {CENDFILE, CENDFILE, CENDFILE, CENDFILE}, /* 12, PEOF */
776 {CWORD, CWORD, CWORD, CWORD}, /* 13, 0-9A-Za-z */
777 {CCTL, CCTL, CCTL, CCTL} /* 14, CTLESC ... */
781 static const char S_I_T[][3] = {
782 #ifdef CONFIG_ASH_ALIAS
783 {CSPCL, CIGN, CIGN}, /* 0, PEOA */
785 {CSPCL, CWORD, CWORD}, /* 1, ' ' */
786 {CNL, CNL, CNL}, /* 2, \n */
787 {CWORD, CCTL, CCTL}, /* 3, !*-/:=?[]~ */
788 {CDQUOTE, CENDQUOTE, CWORD}, /* 4, '"' */
789 {CVAR, CVAR, CWORD}, /* 5, $ */
790 {CSQUOTE, CWORD, CENDQUOTE}, /* 6, "'" */
791 {CSPCL, CWORD, CWORD}, /* 7, ( */
792 {CSPCL, CWORD, CWORD}, /* 8, ) */
793 {CBACK, CBACK, CCTL}, /* 9, \ */
794 {CBQUOTE, CBQUOTE, CWORD}, /* 10, ` */
795 {CENDVAR, CENDVAR, CWORD}, /* 11, } */
796 #ifndef USE_SIT_FUNCTION
797 {CENDFILE, CENDFILE, CENDFILE}, /* 12, PEOF */
798 {CWORD, CWORD, CWORD}, /* 13, 0-9A-Za-z */
799 {CCTL, CCTL, CCTL} /* 14, CTLESC ... */
802 #endif /* CONFIG_ASH_MATH_SUPPORT */
804 #ifdef USE_SIT_FUNCTION
806 #define U_C(c) ((unsigned char)(c))
808 static int SIT(int c, int syntax)
810 static const char spec_symbls[] = "\t\n !\"$&'()*-/:;<=>?[\\]`|}~";
811 #ifdef CONFIG_ASH_ALIAS
812 static const char syntax_index_table[] = {
813 1, 2, 1, 3, 4, 5, 1, 6, /* "\t\n !\"$&'" */
814 7, 8, 3, 3, 3, 3, 1, 1, /* "()*-/:;<" */
815 3, 1, 3, 3, 9, 3, 10, 1, /* "=>?[\\]`|" */
819 static const char syntax_index_table[] = {
820 0, 1, 0, 2, 3, 4, 0, 5, /* "\t\n !\"$&'" */
821 6, 7, 2, 2, 2, 2, 0, 0, /* "()*-/:;<" */
822 2, 0, 2, 2, 8, 2, 9, 0, /* "=>?[\\]`|" */
829 if (c == PEOF) /* 2^8+2 */
831 #ifdef CONFIG_ASH_ALIAS
832 if (c == PEOA) /* 2^8+1 */
836 if (U_C(c) >= U_C(CTLESC) && U_C(c) <= U_C(CTLQUOTEMARK))
839 s = strchr(spec_symbls, c);
840 if (s == 0 || *s == 0)
842 indx = syntax_index_table[(s - spec_symbls)];
844 return S_I_T[indx][syntax];
847 #else /* USE_SIT_FUNCTION */
849 #define SIT(c, syntax) S_I_T[(int)syntax_index_table[((int)c)+SYNBASE]][syntax]
851 #ifdef CONFIG_ASH_ALIAS
852 #define CSPCL_CIGN_CIGN_CIGN 0
853 #define CSPCL_CWORD_CWORD_CWORD 1
854 #define CNL_CNL_CNL_CNL 2
855 #define CWORD_CCTL_CCTL_CWORD 3
856 #define CDQUOTE_CENDQUOTE_CWORD_CWORD 4
857 #define CVAR_CVAR_CWORD_CVAR 5
858 #define CSQUOTE_CWORD_CENDQUOTE_CWORD 6
859 #define CSPCL_CWORD_CWORD_CLP 7
860 #define CSPCL_CWORD_CWORD_CRP 8
861 #define CBACK_CBACK_CCTL_CBACK 9
862 #define CBQUOTE_CBQUOTE_CWORD_CBQUOTE 10
863 #define CENDVAR_CENDVAR_CWORD_CENDVAR 11
864 #define CENDFILE_CENDFILE_CENDFILE_CENDFILE 12
865 #define CWORD_CWORD_CWORD_CWORD 13
866 #define CCTL_CCTL_CCTL_CCTL 14
868 #define CSPCL_CWORD_CWORD_CWORD 0
869 #define CNL_CNL_CNL_CNL 1
870 #define CWORD_CCTL_CCTL_CWORD 2
871 #define CDQUOTE_CENDQUOTE_CWORD_CWORD 3
872 #define CVAR_CVAR_CWORD_CVAR 4
873 #define CSQUOTE_CWORD_CENDQUOTE_CWORD 5
874 #define CSPCL_CWORD_CWORD_CLP 6
875 #define CSPCL_CWORD_CWORD_CRP 7
876 #define CBACK_CBACK_CCTL_CBACK 8
877 #define CBQUOTE_CBQUOTE_CWORD_CBQUOTE 9
878 #define CENDVAR_CENDVAR_CWORD_CENDVAR 10
879 #define CENDFILE_CENDFILE_CENDFILE_CENDFILE 11
880 #define CWORD_CWORD_CWORD_CWORD 12
881 #define CCTL_CCTL_CCTL_CCTL 13
884 static const char syntax_index_table[258] = {
885 /* BASESYNTAX_DQSYNTAX_SQSYNTAX_ARISYNTAX */
886 /* 0 PEOF */ CENDFILE_CENDFILE_CENDFILE_CENDFILE,
887 #ifdef CONFIG_ASH_ALIAS
888 /* 1 PEOA */ CSPCL_CIGN_CIGN_CIGN,
890 /* 2 -128 0x80 */ CWORD_CWORD_CWORD_CWORD,
891 /* 3 -127 CTLESC */ CCTL_CCTL_CCTL_CCTL,
892 /* 4 -126 CTLVAR */ CCTL_CCTL_CCTL_CCTL,
893 /* 5 -125 CTLENDVAR */ CCTL_CCTL_CCTL_CCTL,
894 /* 6 -124 CTLBACKQ */ CCTL_CCTL_CCTL_CCTL,
895 /* 7 -123 CTLQUOTE */ CCTL_CCTL_CCTL_CCTL,
896 /* 8 -122 CTLARI */ CCTL_CCTL_CCTL_CCTL,
897 /* 9 -121 CTLENDARI */ CCTL_CCTL_CCTL_CCTL,
898 /* 10 -120 CTLQUOTEMARK */ CCTL_CCTL_CCTL_CCTL,
899 /* 11 -119 */ CWORD_CWORD_CWORD_CWORD,
900 /* 12 -118 */ CWORD_CWORD_CWORD_CWORD,
901 /* 13 -117 */ CWORD_CWORD_CWORD_CWORD,
902 /* 14 -116 */ CWORD_CWORD_CWORD_CWORD,
903 /* 15 -115 */ CWORD_CWORD_CWORD_CWORD,
904 /* 16 -114 */ CWORD_CWORD_CWORD_CWORD,
905 /* 17 -113 */ CWORD_CWORD_CWORD_CWORD,
906 /* 18 -112 */ CWORD_CWORD_CWORD_CWORD,
907 /* 19 -111 */ CWORD_CWORD_CWORD_CWORD,
908 /* 20 -110 */ CWORD_CWORD_CWORD_CWORD,
909 /* 21 -109 */ CWORD_CWORD_CWORD_CWORD,
910 /* 22 -108 */ CWORD_CWORD_CWORD_CWORD,
911 /* 23 -107 */ CWORD_CWORD_CWORD_CWORD,
912 /* 24 -106 */ CWORD_CWORD_CWORD_CWORD,
913 /* 25 -105 */ CWORD_CWORD_CWORD_CWORD,
914 /* 26 -104 */ CWORD_CWORD_CWORD_CWORD,
915 /* 27 -103 */ CWORD_CWORD_CWORD_CWORD,
916 /* 28 -102 */ CWORD_CWORD_CWORD_CWORD,
917 /* 29 -101 */ CWORD_CWORD_CWORD_CWORD,
918 /* 30 -100 */ CWORD_CWORD_CWORD_CWORD,
919 /* 31 -99 */ CWORD_CWORD_CWORD_CWORD,
920 /* 32 -98 */ CWORD_CWORD_CWORD_CWORD,
921 /* 33 -97 */ CWORD_CWORD_CWORD_CWORD,
922 /* 34 -96 */ CWORD_CWORD_CWORD_CWORD,
923 /* 35 -95 */ CWORD_CWORD_CWORD_CWORD,
924 /* 36 -94 */ CWORD_CWORD_CWORD_CWORD,
925 /* 37 -93 */ CWORD_CWORD_CWORD_CWORD,
926 /* 38 -92 */ CWORD_CWORD_CWORD_CWORD,
927 /* 39 -91 */ CWORD_CWORD_CWORD_CWORD,
928 /* 40 -90 */ CWORD_CWORD_CWORD_CWORD,
929 /* 41 -89 */ CWORD_CWORD_CWORD_CWORD,
930 /* 42 -88 */ CWORD_CWORD_CWORD_CWORD,
931 /* 43 -87 */ CWORD_CWORD_CWORD_CWORD,
932 /* 44 -86 */ CWORD_CWORD_CWORD_CWORD,
933 /* 45 -85 */ CWORD_CWORD_CWORD_CWORD,
934 /* 46 -84 */ CWORD_CWORD_CWORD_CWORD,
935 /* 47 -83 */ CWORD_CWORD_CWORD_CWORD,
936 /* 48 -82 */ CWORD_CWORD_CWORD_CWORD,
937 /* 49 -81 */ CWORD_CWORD_CWORD_CWORD,
938 /* 50 -80 */ CWORD_CWORD_CWORD_CWORD,
939 /* 51 -79 */ CWORD_CWORD_CWORD_CWORD,
940 /* 52 -78 */ CWORD_CWORD_CWORD_CWORD,
941 /* 53 -77 */ CWORD_CWORD_CWORD_CWORD,
942 /* 54 -76 */ CWORD_CWORD_CWORD_CWORD,
943 /* 55 -75 */ CWORD_CWORD_CWORD_CWORD,
944 /* 56 -74 */ CWORD_CWORD_CWORD_CWORD,
945 /* 57 -73 */ CWORD_CWORD_CWORD_CWORD,
946 /* 58 -72 */ CWORD_CWORD_CWORD_CWORD,
947 /* 59 -71 */ CWORD_CWORD_CWORD_CWORD,
948 /* 60 -70 */ CWORD_CWORD_CWORD_CWORD,
949 /* 61 -69 */ CWORD_CWORD_CWORD_CWORD,
950 /* 62 -68 */ CWORD_CWORD_CWORD_CWORD,
951 /* 63 -67 */ CWORD_CWORD_CWORD_CWORD,
952 /* 64 -66 */ CWORD_CWORD_CWORD_CWORD,
953 /* 65 -65 */ CWORD_CWORD_CWORD_CWORD,
954 /* 66 -64 */ CWORD_CWORD_CWORD_CWORD,
955 /* 67 -63 */ CWORD_CWORD_CWORD_CWORD,
956 /* 68 -62 */ CWORD_CWORD_CWORD_CWORD,
957 /* 69 -61 */ CWORD_CWORD_CWORD_CWORD,
958 /* 70 -60 */ CWORD_CWORD_CWORD_CWORD,
959 /* 71 -59 */ CWORD_CWORD_CWORD_CWORD,
960 /* 72 -58 */ CWORD_CWORD_CWORD_CWORD,
961 /* 73 -57 */ CWORD_CWORD_CWORD_CWORD,
962 /* 74 -56 */ CWORD_CWORD_CWORD_CWORD,
963 /* 75 -55 */ CWORD_CWORD_CWORD_CWORD,
964 /* 76 -54 */ CWORD_CWORD_CWORD_CWORD,
965 /* 77 -53 */ CWORD_CWORD_CWORD_CWORD,
966 /* 78 -52 */ CWORD_CWORD_CWORD_CWORD,
967 /* 79 -51 */ CWORD_CWORD_CWORD_CWORD,
968 /* 80 -50 */ CWORD_CWORD_CWORD_CWORD,
969 /* 81 -49 */ CWORD_CWORD_CWORD_CWORD,
970 /* 82 -48 */ CWORD_CWORD_CWORD_CWORD,
971 /* 83 -47 */ CWORD_CWORD_CWORD_CWORD,
972 /* 84 -46 */ CWORD_CWORD_CWORD_CWORD,
973 /* 85 -45 */ CWORD_CWORD_CWORD_CWORD,
974 /* 86 -44 */ CWORD_CWORD_CWORD_CWORD,
975 /* 87 -43 */ CWORD_CWORD_CWORD_CWORD,
976 /* 88 -42 */ CWORD_CWORD_CWORD_CWORD,
977 /* 89 -41 */ CWORD_CWORD_CWORD_CWORD,
978 /* 90 -40 */ CWORD_CWORD_CWORD_CWORD,
979 /* 91 -39 */ CWORD_CWORD_CWORD_CWORD,
980 /* 92 -38 */ CWORD_CWORD_CWORD_CWORD,
981 /* 93 -37 */ CWORD_CWORD_CWORD_CWORD,
982 /* 94 -36 */ CWORD_CWORD_CWORD_CWORD,
983 /* 95 -35 */ CWORD_CWORD_CWORD_CWORD,
984 /* 96 -34 */ CWORD_CWORD_CWORD_CWORD,
985 /* 97 -33 */ CWORD_CWORD_CWORD_CWORD,
986 /* 98 -32 */ CWORD_CWORD_CWORD_CWORD,
987 /* 99 -31 */ CWORD_CWORD_CWORD_CWORD,
988 /* 100 -30 */ CWORD_CWORD_CWORD_CWORD,
989 /* 101 -29 */ CWORD_CWORD_CWORD_CWORD,
990 /* 102 -28 */ CWORD_CWORD_CWORD_CWORD,
991 /* 103 -27 */ CWORD_CWORD_CWORD_CWORD,
992 /* 104 -26 */ CWORD_CWORD_CWORD_CWORD,
993 /* 105 -25 */ CWORD_CWORD_CWORD_CWORD,
994 /* 106 -24 */ CWORD_CWORD_CWORD_CWORD,
995 /* 107 -23 */ CWORD_CWORD_CWORD_CWORD,
996 /* 108 -22 */ CWORD_CWORD_CWORD_CWORD,
997 /* 109 -21 */ CWORD_CWORD_CWORD_CWORD,
998 /* 110 -20 */ CWORD_CWORD_CWORD_CWORD,
999 /* 111 -19 */ CWORD_CWORD_CWORD_CWORD,
1000 /* 112 -18 */ CWORD_CWORD_CWORD_CWORD,
1001 /* 113 -17 */ CWORD_CWORD_CWORD_CWORD,
1002 /* 114 -16 */ CWORD_CWORD_CWORD_CWORD,
1003 /* 115 -15 */ CWORD_CWORD_CWORD_CWORD,
1004 /* 116 -14 */ CWORD_CWORD_CWORD_CWORD,
1005 /* 117 -13 */ CWORD_CWORD_CWORD_CWORD,
1006 /* 118 -12 */ CWORD_CWORD_CWORD_CWORD,
1007 /* 119 -11 */ CWORD_CWORD_CWORD_CWORD,
1008 /* 120 -10 */ CWORD_CWORD_CWORD_CWORD,
1009 /* 121 -9 */ CWORD_CWORD_CWORD_CWORD,
1010 /* 122 -8 */ CWORD_CWORD_CWORD_CWORD,
1011 /* 123 -7 */ CWORD_CWORD_CWORD_CWORD,
1012 /* 124 -6 */ CWORD_CWORD_CWORD_CWORD,
1013 /* 125 -5 */ CWORD_CWORD_CWORD_CWORD,
1014 /* 126 -4 */ CWORD_CWORD_CWORD_CWORD,
1015 /* 127 -3 */ CWORD_CWORD_CWORD_CWORD,
1016 /* 128 -2 */ CWORD_CWORD_CWORD_CWORD,
1017 /* 129 -1 */ CWORD_CWORD_CWORD_CWORD,
1018 /* 130 0 */ CWORD_CWORD_CWORD_CWORD,
1019 /* 131 1 */ CWORD_CWORD_CWORD_CWORD,
1020 /* 132 2 */ CWORD_CWORD_CWORD_CWORD,
1021 /* 133 3 */ CWORD_CWORD_CWORD_CWORD,
1022 /* 134 4 */ CWORD_CWORD_CWORD_CWORD,
1023 /* 135 5 */ CWORD_CWORD_CWORD_CWORD,
1024 /* 136 6 */ CWORD_CWORD_CWORD_CWORD,
1025 /* 137 7 */ CWORD_CWORD_CWORD_CWORD,
1026 /* 138 8 */ CWORD_CWORD_CWORD_CWORD,
1027 /* 139 9 "\t" */ CSPCL_CWORD_CWORD_CWORD,
1028 /* 140 10 "\n" */ CNL_CNL_CNL_CNL,
1029 /* 141 11 */ CWORD_CWORD_CWORD_CWORD,
1030 /* 142 12 */ CWORD_CWORD_CWORD_CWORD,
1031 /* 143 13 */ CWORD_CWORD_CWORD_CWORD,
1032 /* 144 14 */ CWORD_CWORD_CWORD_CWORD,
1033 /* 145 15 */ CWORD_CWORD_CWORD_CWORD,
1034 /* 146 16 */ CWORD_CWORD_CWORD_CWORD,
1035 /* 147 17 */ CWORD_CWORD_CWORD_CWORD,
1036 /* 148 18 */ CWORD_CWORD_CWORD_CWORD,
1037 /* 149 19 */ CWORD_CWORD_CWORD_CWORD,
1038 /* 150 20 */ CWORD_CWORD_CWORD_CWORD,
1039 /* 151 21 */ CWORD_CWORD_CWORD_CWORD,
1040 /* 152 22 */ CWORD_CWORD_CWORD_CWORD,
1041 /* 153 23 */ CWORD_CWORD_CWORD_CWORD,
1042 /* 154 24 */ CWORD_CWORD_CWORD_CWORD,
1043 /* 155 25 */ CWORD_CWORD_CWORD_CWORD,
1044 /* 156 26 */ CWORD_CWORD_CWORD_CWORD,
1045 /* 157 27 */ CWORD_CWORD_CWORD_CWORD,
1046 /* 158 28 */ CWORD_CWORD_CWORD_CWORD,
1047 /* 159 29 */ CWORD_CWORD_CWORD_CWORD,
1048 /* 160 30 */ CWORD_CWORD_CWORD_CWORD,
1049 /* 161 31 */ CWORD_CWORD_CWORD_CWORD,
1050 /* 162 32 " " */ CSPCL_CWORD_CWORD_CWORD,
1051 /* 163 33 "!" */ CWORD_CCTL_CCTL_CWORD,
1052 /* 164 34 """ */ CDQUOTE_CENDQUOTE_CWORD_CWORD,
1053 /* 165 35 "#" */ CWORD_CWORD_CWORD_CWORD,
1054 /* 166 36 "$" */ CVAR_CVAR_CWORD_CVAR,
1055 /* 167 37 "%" */ CWORD_CWORD_CWORD_CWORD,
1056 /* 168 38 "&" */ CSPCL_CWORD_CWORD_CWORD,
1057 /* 169 39 "'" */ CSQUOTE_CWORD_CENDQUOTE_CWORD,
1058 /* 170 40 "(" */ CSPCL_CWORD_CWORD_CLP,
1059 /* 171 41 ")" */ CSPCL_CWORD_CWORD_CRP,
1060 /* 172 42 "*" */ CWORD_CCTL_CCTL_CWORD,
1061 /* 173 43 "+" */ CWORD_CWORD_CWORD_CWORD,
1062 /* 174 44 "," */ CWORD_CWORD_CWORD_CWORD,
1063 /* 175 45 "-" */ CWORD_CCTL_CCTL_CWORD,
1064 /* 176 46 "." */ CWORD_CWORD_CWORD_CWORD,
1065 /* 177 47 "/" */ CWORD_CCTL_CCTL_CWORD,
1066 /* 178 48 "0" */ CWORD_CWORD_CWORD_CWORD,
1067 /* 179 49 "1" */ CWORD_CWORD_CWORD_CWORD,
1068 /* 180 50 "2" */ CWORD_CWORD_CWORD_CWORD,
1069 /* 181 51 "3" */ CWORD_CWORD_CWORD_CWORD,
1070 /* 182 52 "4" */ CWORD_CWORD_CWORD_CWORD,
1071 /* 183 53 "5" */ CWORD_CWORD_CWORD_CWORD,
1072 /* 184 54 "6" */ CWORD_CWORD_CWORD_CWORD,
1073 /* 185 55 "7" */ CWORD_CWORD_CWORD_CWORD,
1074 /* 186 56 "8" */ CWORD_CWORD_CWORD_CWORD,
1075 /* 187 57 "9" */ CWORD_CWORD_CWORD_CWORD,
1076 /* 188 58 ":" */ CWORD_CCTL_CCTL_CWORD,
1077 /* 189 59 ";" */ CSPCL_CWORD_CWORD_CWORD,
1078 /* 190 60 "<" */ CSPCL_CWORD_CWORD_CWORD,
1079 /* 191 61 "=" */ CWORD_CCTL_CCTL_CWORD,
1080 /* 192 62 ">" */ CSPCL_CWORD_CWORD_CWORD,
1081 /* 193 63 "?" */ CWORD_CCTL_CCTL_CWORD,
1082 /* 194 64 "@" */ CWORD_CWORD_CWORD_CWORD,
1083 /* 195 65 "A" */ CWORD_CWORD_CWORD_CWORD,
1084 /* 196 66 "B" */ CWORD_CWORD_CWORD_CWORD,
1085 /* 197 67 "C" */ CWORD_CWORD_CWORD_CWORD,
1086 /* 198 68 "D" */ CWORD_CWORD_CWORD_CWORD,
1087 /* 199 69 "E" */ CWORD_CWORD_CWORD_CWORD,
1088 /* 200 70 "F" */ CWORD_CWORD_CWORD_CWORD,
1089 /* 201 71 "G" */ CWORD_CWORD_CWORD_CWORD,
1090 /* 202 72 "H" */ CWORD_CWORD_CWORD_CWORD,
1091 /* 203 73 "I" */ CWORD_CWORD_CWORD_CWORD,
1092 /* 204 74 "J" */ CWORD_CWORD_CWORD_CWORD,
1093 /* 205 75 "K" */ CWORD_CWORD_CWORD_CWORD,
1094 /* 206 76 "L" */ CWORD_CWORD_CWORD_CWORD,
1095 /* 207 77 "M" */ CWORD_CWORD_CWORD_CWORD,
1096 /* 208 78 "N" */ CWORD_CWORD_CWORD_CWORD,
1097 /* 209 79 "O" */ CWORD_CWORD_CWORD_CWORD,
1098 /* 210 80 "P" */ CWORD_CWORD_CWORD_CWORD,
1099 /* 211 81 "Q" */ CWORD_CWORD_CWORD_CWORD,
1100 /* 212 82 "R" */ CWORD_CWORD_CWORD_CWORD,
1101 /* 213 83 "S" */ CWORD_CWORD_CWORD_CWORD,
1102 /* 214 84 "T" */ CWORD_CWORD_CWORD_CWORD,
1103 /* 215 85 "U" */ CWORD_CWORD_CWORD_CWORD,
1104 /* 216 86 "V" */ CWORD_CWORD_CWORD_CWORD,
1105 /* 217 87 "W" */ CWORD_CWORD_CWORD_CWORD,
1106 /* 218 88 "X" */ CWORD_CWORD_CWORD_CWORD,
1107 /* 219 89 "Y" */ CWORD_CWORD_CWORD_CWORD,
1108 /* 220 90 "Z" */ CWORD_CWORD_CWORD_CWORD,
1109 /* 221 91 "[" */ CWORD_CCTL_CCTL_CWORD,
1110 /* 222 92 "\" */ CBACK_CBACK_CCTL_CBACK,
1111 /* 223 93 "]" */ CWORD_CCTL_CCTL_CWORD,
1112 /* 224 94 "^" */ CWORD_CWORD_CWORD_CWORD,
1113 /* 225 95 "_" */ CWORD_CWORD_CWORD_CWORD,
1114 /* 226 96 "`" */ CBQUOTE_CBQUOTE_CWORD_CBQUOTE,
1115 /* 227 97 "a" */ CWORD_CWORD_CWORD_CWORD,
1116 /* 228 98 "b" */ CWORD_CWORD_CWORD_CWORD,
1117 /* 229 99 "c" */ CWORD_CWORD_CWORD_CWORD,
1118 /* 230 100 "d" */ CWORD_CWORD_CWORD_CWORD,
1119 /* 231 101 "e" */ CWORD_CWORD_CWORD_CWORD,
1120 /* 232 102 "f" */ CWORD_CWORD_CWORD_CWORD,
1121 /* 233 103 "g" */ CWORD_CWORD_CWORD_CWORD,
1122 /* 234 104 "h" */ CWORD_CWORD_CWORD_CWORD,
1123 /* 235 105 "i" */ CWORD_CWORD_CWORD_CWORD,
1124 /* 236 106 "j" */ CWORD_CWORD_CWORD_CWORD,
1125 /* 237 107 "k" */ CWORD_CWORD_CWORD_CWORD,
1126 /* 238 108 "l" */ CWORD_CWORD_CWORD_CWORD,
1127 /* 239 109 "m" */ CWORD_CWORD_CWORD_CWORD,
1128 /* 240 110 "n" */ CWORD_CWORD_CWORD_CWORD,
1129 /* 241 111 "o" */ CWORD_CWORD_CWORD_CWORD,
1130 /* 242 112 "p" */ CWORD_CWORD_CWORD_CWORD,
1131 /* 243 113 "q" */ CWORD_CWORD_CWORD_CWORD,
1132 /* 244 114 "r" */ CWORD_CWORD_CWORD_CWORD,
1133 /* 245 115 "s" */ CWORD_CWORD_CWORD_CWORD,
1134 /* 246 116 "t" */ CWORD_CWORD_CWORD_CWORD,
1135 /* 247 117 "u" */ CWORD_CWORD_CWORD_CWORD,
1136 /* 248 118 "v" */ CWORD_CWORD_CWORD_CWORD,
1137 /* 249 119 "w" */ CWORD_CWORD_CWORD_CWORD,
1138 /* 250 120 "x" */ CWORD_CWORD_CWORD_CWORD,
1139 /* 251 121 "y" */ CWORD_CWORD_CWORD_CWORD,
1140 /* 252 122 "z" */ CWORD_CWORD_CWORD_CWORD,
1141 /* 253 123 "{" */ CWORD_CWORD_CWORD_CWORD,
1142 /* 254 124 "|" */ CSPCL_CWORD_CWORD_CWORD,
1143 /* 255 125 "}" */ CENDVAR_CENDVAR_CWORD_CENDVAR,
1144 /* 256 126 "~" */ CWORD_CCTL_CCTL_CWORD,
1145 /* 257 127 */ CWORD_CWORD_CWORD_CWORD,
1148 #endif /* USE_SIT_FUNCTION */
1155 static int funcblocksize; /* size of structures in function */
1156 static int funcstringsize; /* size of strings in node */
1157 static pointer funcblock; /* block to allocate function from */
1158 static char *funcstring; /* block to allocate strings from */
1160 static const short nodesize[26] = {
1161 SHELL_ALIGN(sizeof (struct ncmd)),
1162 SHELL_ALIGN(sizeof (struct npipe)),
1163 SHELL_ALIGN(sizeof (struct nredir)),
1164 SHELL_ALIGN(sizeof (struct nredir)),
1165 SHELL_ALIGN(sizeof (struct nredir)),
1166 SHELL_ALIGN(sizeof (struct nbinary)),
1167 SHELL_ALIGN(sizeof (struct nbinary)),
1168 SHELL_ALIGN(sizeof (struct nbinary)),
1169 SHELL_ALIGN(sizeof (struct nif)),
1170 SHELL_ALIGN(sizeof (struct nbinary)),
1171 SHELL_ALIGN(sizeof (struct nbinary)),
1172 SHELL_ALIGN(sizeof (struct nfor)),
1173 SHELL_ALIGN(sizeof (struct ncase)),
1174 SHELL_ALIGN(sizeof (struct nclist)),
1175 SHELL_ALIGN(sizeof (struct narg)),
1176 SHELL_ALIGN(sizeof (struct narg)),
1177 SHELL_ALIGN(sizeof (struct nfile)),
1178 SHELL_ALIGN(sizeof (struct nfile)),
1179 SHELL_ALIGN(sizeof (struct nfile)),
1180 SHELL_ALIGN(sizeof (struct nfile)),
1181 SHELL_ALIGN(sizeof (struct nfile)),
1182 SHELL_ALIGN(sizeof (struct ndup)),
1183 SHELL_ALIGN(sizeof (struct ndup)),
1184 SHELL_ALIGN(sizeof (struct nhere)),
1185 SHELL_ALIGN(sizeof (struct nhere)),
1186 SHELL_ALIGN(sizeof (struct nnot)),
1190 static void calcsize(union node *);
1191 static void sizenodelist(struct nodelist *);
1192 static union node *copynode(union node *);
1193 static struct nodelist *copynodelist(struct nodelist *);
1194 static char *nodesavestr(char *);
1197 static int evalstring(char *, int mask);
1198 union node; /* BLETCH for ansi C */
1199 static void evaltree(union node *, int);
1200 static void evalbackcmd(union node *, struct backcmd *);
1202 static int evalskip; /* set if we are skipping commands */
1203 static int skipcount; /* number of levels to skip */
1204 static int funcnest; /* depth of function calls */
1206 /* reasons for skipping commands (see comment on breakcmd routine) */
1207 #define SKIPBREAK (1 << 0)
1208 #define SKIPCONT (1 << 1)
1209 #define SKIPFUNC (1 << 2)
1210 #define SKIPFILE (1 << 3)
1211 #define SKIPEVAL (1 << 4)
1214 * This file was generated by the mkbuiltins program.
1218 static int bgcmd(int, char **);
1220 static int breakcmd(int, char **);
1221 static int cdcmd(int, char **);
1222 #ifdef CONFIG_ASH_CMDCMD
1223 static int commandcmd(int, char **);
1225 static int dotcmd(int, char **);
1226 static int evalcmd(int, char **);
1227 #ifdef CONFIG_ASH_BUILTIN_ECHO
1228 static int echocmd(int, char **);
1230 static int execcmd(int, char **);
1231 static int exitcmd(int, char **);
1232 static int exportcmd(int, char **);
1233 static int falsecmd(int, char **);
1235 static int fgcmd(int, char **);
1237 #ifdef CONFIG_ASH_GETOPTS
1238 static int getoptscmd(int, char **);
1240 static int hashcmd(int, char **);
1241 #ifndef CONFIG_FEATURE_SH_EXTRA_QUIET
1242 static int helpcmd(int argc, char **argv);
1245 static int jobscmd(int, char **);
1247 #ifdef CONFIG_ASH_MATH_SUPPORT
1248 static int letcmd(int, char **);
1250 static int localcmd(int, char **);
1251 static int pwdcmd(int, char **);
1252 static int readcmd(int, char **);
1253 static int returncmd(int, char **);
1254 static int setcmd(int, char **);
1255 static int shiftcmd(int, char **);
1256 static int timescmd(int, char **);
1257 static int trapcmd(int, char **);
1258 static int truecmd(int, char **);
1259 static int typecmd(int, char **);
1260 static int umaskcmd(int, char **);
1261 static int unsetcmd(int, char **);
1262 static int waitcmd(int, char **);
1263 static int ulimitcmd(int, char **);
1265 static int killcmd(int, char **);
1270 #ifdef CONFIG_ASH_MAIL
1271 static void chkmail(void);
1272 static void changemail(const char *);
1277 /* values of cmdtype */
1278 #define CMDUNKNOWN -1 /* no entry in table for command */
1279 #define CMDNORMAL 0 /* command is an executable program */
1280 #define CMDFUNCTION 1 /* command is a shell function */
1281 #define CMDBUILTIN 2 /* command is a shell builtin */
1285 int (*builtin)(int, char **);
1286 /* unsigned flags; */
1290 #define COMMANDCMD (builtincmd + 5 + \
1291 ENABLE_ASH_ALIAS + ENABLE_ASH_JOB_CONTROL)
1292 #define EXECCMD (builtincmd + 7 + \
1293 ENABLE_ASH_CMDCMD + ENABLE_ASH_ALIAS + \
1294 ENABLE_ASH_BUILTIN_ECHO + ENABLE_ASH_JOB_CONTROL)
1296 #define BUILTIN_NOSPEC "0"
1297 #define BUILTIN_SPECIAL "1"
1298 #define BUILTIN_REGULAR "2"
1299 #define BUILTIN_SPEC_REG "3"
1300 #define BUILTIN_ASSIGN "4"
1301 #define BUILTIN_SPEC_ASSG "5"
1302 #define BUILTIN_REG_ASSG "6"
1303 #define BUILTIN_SPEC_REG_ASSG "7"
1305 #define IS_BUILTIN_SPECIAL(builtincmd) ((builtincmd)->name[0] & 1)
1306 #define IS_BUILTIN_REGULAR(builtincmd) ((builtincmd)->name[0] & 2)
1307 #define IS_BUILTIN_ASSIGN(builtincmd) ((builtincmd)->name[0] & 4)
1309 static const struct builtincmd builtincmd[] = {
1310 { BUILTIN_SPEC_REG ".", dotcmd },
1311 { BUILTIN_SPEC_REG ":", truecmd },
1312 #ifdef CONFIG_ASH_ALIAS
1313 { BUILTIN_REG_ASSG "alias", aliascmd },
1316 { BUILTIN_REGULAR "bg", bgcmd },
1318 { BUILTIN_SPEC_REG "break", breakcmd },
1319 { BUILTIN_REGULAR "cd", cdcmd },
1320 { BUILTIN_NOSPEC "chdir", cdcmd },
1321 #ifdef CONFIG_ASH_CMDCMD
1322 { BUILTIN_REGULAR "command", commandcmd },
1324 { BUILTIN_SPEC_REG "continue", breakcmd },
1325 #ifdef CONFIG_ASH_BUILTIN_ECHO
1326 { BUILTIN_REGULAR "echo", echocmd },
1328 { BUILTIN_SPEC_REG "eval", evalcmd },
1329 { BUILTIN_SPEC_REG "exec", execcmd },
1330 { BUILTIN_SPEC_REG "exit", exitcmd },
1331 { BUILTIN_SPEC_REG_ASSG "export", exportcmd },
1332 { BUILTIN_REGULAR "false", falsecmd },
1334 { BUILTIN_REGULAR "fg", fgcmd },
1336 #ifdef CONFIG_ASH_GETOPTS
1337 { BUILTIN_REGULAR "getopts", getoptscmd },
1339 { BUILTIN_NOSPEC "hash", hashcmd },
1340 #ifndef CONFIG_FEATURE_SH_EXTRA_QUIET
1341 { BUILTIN_NOSPEC "help", helpcmd },
1344 { BUILTIN_REGULAR "jobs", jobscmd },
1345 { BUILTIN_REGULAR "kill", killcmd },
1347 #ifdef CONFIG_ASH_MATH_SUPPORT
1348 { BUILTIN_NOSPEC "let", letcmd },
1350 { BUILTIN_ASSIGN "local", localcmd },
1351 { BUILTIN_NOSPEC "pwd", pwdcmd },
1352 { BUILTIN_REGULAR "read", readcmd },
1353 { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd },
1354 { BUILTIN_SPEC_REG "return", returncmd },
1355 { BUILTIN_SPEC_REG "set", setcmd },
1356 { BUILTIN_SPEC_REG "shift", shiftcmd },
1357 { BUILTIN_SPEC_REG "times", timescmd },
1358 { BUILTIN_SPEC_REG "trap", trapcmd },
1359 { BUILTIN_REGULAR "true", truecmd },
1360 { BUILTIN_NOSPEC "type", typecmd },
1361 { BUILTIN_NOSPEC "ulimit", ulimitcmd },
1362 { BUILTIN_REGULAR "umask", umaskcmd },
1363 #ifdef CONFIG_ASH_ALIAS
1364 { BUILTIN_REGULAR "unalias", unaliascmd },
1366 { BUILTIN_SPEC_REG "unset", unsetcmd },
1367 { BUILTIN_REGULAR "wait", waitcmd },
1370 #define NUMBUILTINS (sizeof (builtincmd) / sizeof (struct builtincmd) )
1378 const struct builtincmd *cmd;
1379 struct funcnode *func;
1384 /* action to find_command() */
1385 #define DO_ERR 0x01 /* prints errors */
1386 #define DO_ABS 0x02 /* checks absolute paths */
1387 #define DO_NOFUNC 0x04 /* don't return shell functions, for command */
1388 #define DO_ALTPATH 0x08 /* using alternate path */
1389 #define DO_ALTBLTIN 0x20 /* %builtin in alt. path */
1391 static const char *pathopt; /* set by padvance */
1393 static void shellexec(char **, const char *, int)
1395 static char *padvance(const char **, const char *);
1396 static void find_command(char *, struct cmdentry *, int, const char *);
1397 static struct builtincmd *find_builtin(const char *);
1398 static void hashcd(void);
1399 static void changepath(const char *);
1400 static void defun(char *, union node *);
1401 static void unsetfunc(const char *);
1403 #ifdef CONFIG_ASH_MATH_SUPPORT_64
1404 typedef int64_t arith_t;
1405 #define arith_t_type (long long)
1407 typedef long arith_t;
1408 #define arith_t_type (long)
1411 #ifdef CONFIG_ASH_MATH_SUPPORT
1412 static arith_t dash_arith(const char *);
1413 static arith_t arith(const char *expr, int *perrcode);
1416 #ifdef CONFIG_ASH_RANDOM_SUPPORT
1417 static unsigned long rseed;
1418 static void change_random(const char *);
1419 # ifndef DYNAMIC_VAR
1420 # define DYNAMIC_VAR
1426 static void reset(void);
1435 #define VEXPORT 0x01 /* variable is exported */
1436 #define VREADONLY 0x02 /* variable cannot be modified */
1437 #define VSTRFIXED 0x04 /* variable struct is statically allocated */
1438 #define VTEXTFIXED 0x08 /* text is statically allocated */
1439 #define VSTACK 0x10 /* text is allocated on the stack */
1440 #define VUNSET 0x20 /* the variable is not set */
1441 #define VNOFUNC 0x40 /* don't call the callback function */
1442 #define VNOSET 0x80 /* do not set variable - just readonly test */
1443 #define VNOSAVE 0x100 /* when text is on the heap before setvareq */
1445 # define VDYNAMIC 0x200 /* dynamic variable */
1451 struct var *next; /* next entry in hash list */
1452 int flags; /* flags are defined above */
1453 const char *text; /* name=value */
1454 void (*func)(const char *); /* function to be called when */
1455 /* the variable gets set/unset */
1459 struct localvar *next; /* next local variable in list */
1460 struct var *vp; /* the variable that was made local */
1461 int flags; /* saved flags */
1462 const char *text; /* saved text */
1466 static struct localvar *localvars;
1472 #ifdef CONFIG_ASH_GETOPTS
1473 static void getoptsreset(const char *);
1476 #ifdef CONFIG_LOCALE_SUPPORT
1478 static void change_lc_all(const char *value);
1479 static void change_lc_ctype(const char *value);
1485 static const char defpathvar[] = "PATH=/usr/local/bin:/usr/bin:/sbin:/bin";
1487 static const char defifsvar[] = "IFS= \t\n";
1488 #define defifs (defifsvar + 4)
1490 static const char defifs[] = " \t\n";
1494 static struct var varinit[] = {
1496 { 0, VSTRFIXED|VTEXTFIXED, defifsvar, 0 },
1498 { 0, VSTRFIXED|VTEXTFIXED|VUNSET, "IFS\0", 0 },
1501 #ifdef CONFIG_ASH_MAIL
1502 { 0, VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL\0", changemail },
1503 { 0, VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH\0", changemail },
1506 { 0, VSTRFIXED|VTEXTFIXED, defpathvar, changepath },
1507 { 0, VSTRFIXED|VTEXTFIXED, "PS1=$ ", 0 },
1508 { 0, VSTRFIXED|VTEXTFIXED, "PS2=> ", 0 },
1509 { 0, VSTRFIXED|VTEXTFIXED, "PS4=+ ", 0 },
1510 #ifdef CONFIG_ASH_GETOPTS
1511 { 0, VSTRFIXED|VTEXTFIXED, "OPTIND=1", getoptsreset },
1513 #ifdef CONFIG_ASH_RANDOM_SUPPORT
1514 {0, VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM\0", change_random },
1516 #ifdef CONFIG_LOCALE_SUPPORT
1517 {0, VSTRFIXED | VTEXTFIXED | VUNSET, "LC_ALL\0", change_lc_all },
1518 {0, VSTRFIXED | VTEXTFIXED | VUNSET, "LC_CTYPE\0", change_lc_ctype },
1520 #ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
1521 {0, VSTRFIXED | VTEXTFIXED | VUNSET, "HISTFILE\0", NULL },
1525 #define vifs varinit[0]
1526 #ifdef CONFIG_ASH_MAIL
1527 #define vmail (&vifs)[1]
1528 #define vmpath (&vmail)[1]
1532 #define vpath (&vmpath)[1]
1533 #define vps1 (&vpath)[1]
1534 #define vps2 (&vps1)[1]
1535 #define vps4 (&vps2)[1]
1536 #define voptind (&vps4)[1]
1537 #ifdef CONFIG_ASH_GETOPTS
1538 #define vrandom (&voptind)[1]
1540 #define vrandom (&vps4)[1]
1542 #define defpath (defpathvar + 5)
1545 * The following macros access the values of the above variables.
1546 * They have to skip over the name. They return the null string
1547 * for unset variables.
1550 #define ifsval() (vifs.text + 4)
1551 #define ifsset() ((vifs.flags & VUNSET) == 0)
1552 #define mailval() (vmail.text + 5)
1553 #define mpathval() (vmpath.text + 9)
1554 #define pathval() (vpath.text + 5)
1555 #define ps1val() (vps1.text + 4)
1556 #define ps2val() (vps2.text + 4)
1557 #define ps4val() (vps4.text + 4)
1558 #define optindval() (voptind.text + 7)
1560 #define mpathset() ((vmpath.flags & VUNSET) == 0)
1562 static void setvar(const char *, const char *, int);
1563 static void setvareq(char *, int);
1564 static void listsetvar(struct strlist *, int);
1565 static char *lookupvar(const char *);
1566 static char *bltinlookup(const char *);
1567 static char **listvars(int, int, char ***);
1568 #define environment() listvars(VEXPORT, VUNSET, 0)
1569 static int showvars(const char *, int, int);
1570 static void poplocalvars(void);
1571 static int unsetvar(const char *);
1572 #ifdef CONFIG_ASH_GETOPTS
1573 static int setvarsafe(const char *, const char *, int);
1575 static int varcmp(const char *, const char *);
1576 static struct var **hashvar(const char *);
1579 static inline int varequal(const char *a, const char *b) {
1580 return !varcmp(a, b);
1584 static int loopnest; /* current loop nesting level */
1587 * The parsefile structure pointed to by the global variable parsefile
1588 * contains information about the current file being read.
1593 struct redirtab *next;
1598 static struct redirtab *redirlist;
1599 static int nullredirs;
1601 extern char **environ;
1606 static void outstr(const char *, FILE *);
1607 static void outcslow(int, FILE *);
1608 static void flushall(void);
1609 static void flusherr(void);
1610 static int out1fmt(const char *, ...)
1611 __attribute__((__format__(__printf__,1,2)));
1612 static int fmtstr(char *, size_t, const char *, ...)
1613 __attribute__((__format__(__printf__,3,4)));
1615 static int preverrout_fd; /* save fd2 before print debug if xflag is set. */
1618 static void out1str(const char *p)
1623 static void out2str(const char *p)
1630 * Initialization code.
1634 * This routine initializes the builtin variables.
1645 * PS1 depends on uid
1647 #if defined(CONFIG_FEATURE_COMMAND_EDITING) && defined(CONFIG_FEATURE_SH_FANCY_PROMPT)
1648 vps1.text = "PS1=\\w \\$ ";
1651 vps1.text = "PS1=# ";
1654 end = vp + sizeof(varinit) / sizeof(varinit[0]);
1656 vpp = hashvar(vp->text);
1659 } while (++vp < end);
1668 basepf.nextc = basepf.buf = basebuf;
1673 signal(SIGCHLD, SIG_DFL);
1681 struct stat st1, st2;
1684 for (envp = environ ; envp && *envp ; envp++) {
1685 if (strchr(*envp, '=')) {
1686 setvareq(*envp, VEXPORT|VTEXTFIXED);
1690 snprintf(ppid, sizeof(ppid), "%d", (int) getppid());
1691 setvar("PPID", ppid, 0);
1693 p = lookupvar("PWD");
1695 if (*p != '/' || stat(p, &st1) || stat(".", &st2) ||
1696 st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino)
1702 /* PEOF (the end of file marker) */
1705 INPUT_PUSH_FILE = 1,
1706 INPUT_NOFILE_OK = 2,
1710 * The input line number. Input.c just defines this variable, and saves
1711 * and restores it when files are pushed and popped. The user of this
1712 * package must set its value.
1715 static int pgetc(void);
1716 static int pgetc2(void);
1717 static int preadbuffer(void);
1718 static void pungetc(void);
1719 static void pushstring(char *, void *);
1720 static void popstring(void);
1721 static void setinputfd(int, int);
1722 static void setinputstring(char *);
1723 static void popfile(void);
1724 static void popallfiles(void);
1725 static void closescript(void);
1731 /* Mode argument to forkshell. Don't change FORK_FG or FORK_BG. */
1734 #define FORK_NOJOB 2
1736 /* mode flags for showjob(s) */
1737 #define SHOW_PGID 0x01 /* only show pgid - for jobs -p */
1738 #define SHOW_PID 0x04 /* include process pid */
1739 #define SHOW_CHANGED 0x08 /* only jobs whose state has changed */
1743 * A job structure contains information about a job. A job is either a
1744 * single process or a set of processes contained in a pipeline. In the
1745 * latter case, pidlist will be non-NULL, and will point to a -1 terminated
1750 pid_t pid; /* process id */
1751 int status; /* last process status from wait() */
1752 char *cmd; /* text of command being run */
1756 struct procstat ps0; /* status of process */
1757 struct procstat *ps; /* status or processes when more than one */
1759 int stopstatus; /* status of a stopped job */
1762 nprocs: 16, /* number of processes */
1764 #define JOBRUNNING 0 /* at least one proc running */
1765 #define JOBSTOPPED 1 /* all procs are stopped */
1766 #define JOBDONE 2 /* all procs are completed */
1768 sigint: 1, /* job was killed by SIGINT */
1769 jobctl: 1, /* job running under job control */
1771 waited: 1, /* true if this entry has been waited for */
1772 used: 1, /* true if this entry is in used */
1773 changed: 1; /* true if status has changed */
1774 struct job *prev_job; /* previous job */
1777 static pid_t backgndpid; /* pid of last background process */
1778 static int job_warning; /* user was warned about stopped jobs */
1780 static int jobctl; /* true if doing job control */
1783 static struct job *makejob(union node *, int);
1784 static int forkshell(struct job *, union node *, int);
1785 static int waitforjob(struct job *);
1786 static int stoppedjobs(void);
1789 #define setjobctl(on) /* do nothing */
1791 static void setjobctl(int);
1792 static void showjobs(FILE *, int);
1798 /* pid of main shell */
1800 /* shell level: 0 for the main shell, 1 for its children, and so on */
1802 #define rootshell (!shlvl)
1804 static void readcmdfile(char *);
1805 static int cmdloop(int);
1811 struct stack_block *stackp;
1814 struct stackmark *marknext;
1817 /* minimum size of a block */
1818 #define MINSIZE SHELL_ALIGN(504)
1820 struct stack_block {
1821 struct stack_block *prev;
1822 char space[MINSIZE];
1825 static struct stack_block stackbase;
1826 static struct stack_block *stackp = &stackbase;
1827 static struct stackmark *markp;
1828 static char *stacknxt = stackbase.space;
1829 static size_t stacknleft = MINSIZE;
1830 static char *sstrend = stackbase.space + MINSIZE;
1831 static int herefd = -1;
1834 static pointer ckmalloc(size_t);
1835 static pointer ckrealloc(pointer, size_t);
1836 static char *savestr(const char *);
1837 static pointer stalloc(size_t);
1838 static void stunalloc(pointer);
1839 static void setstackmark(struct stackmark *);
1840 static void popstackmark(struct stackmark *);
1841 static void growstackblock(void);
1842 static void *growstackstr(void);
1843 static char *makestrspace(size_t, char *);
1844 static char *stnputs(const char *, size_t, char *);
1845 static char *stputs(const char *, char *);
1848 static inline char *_STPUTC(int c, char *p) {
1855 #define stackblock() ((void *)stacknxt)
1856 #define stackblocksize() stacknleft
1857 #define STARTSTACKSTR(p) ((p) = stackblock())
1858 #define STPUTC(c, p) ((p) = _STPUTC((c), (p)))
1859 #define CHECKSTRSPACE(n, p) \
1863 size_t m = sstrend - q; \
1865 (p) = makestrspace(l, q); \
1868 #define USTPUTC(c, p) (*p++ = (c))
1869 #define STACKSTRNUL(p) ((p) == sstrend? (p = growstackstr(), *p = '\0') : (*p = '\0'))
1870 #define STUNPUTC(p) (--p)
1871 #define STTOPC(p) p[-1]
1872 #define STADJUST(amount, p) (p += (amount))
1874 #define grabstackstr(p) stalloc((char *)(p) - (char *)stackblock())
1875 #define ungrabstackstr(s, p) stunalloc((s))
1876 #define stackstrend() ((void *)sstrend)
1878 #define ckfree(p) free((pointer)(p))
1883 #define DOLATSTRLEN 4
1885 static char *prefix(const char *, const char *);
1886 static int number(const char *);
1887 static int is_number(const char *);
1888 static char *single_quote(const char *);
1889 static char *sstrdup(const char *);
1891 #define equal(s1, s2) (strcmp(s1, s2) == 0)
1892 #define scopy(s1, s2) ((void)strcpy(s2, s1))
1897 int nparam; /* # of positional parameters (without $0) */
1898 unsigned char malloc; /* if parameter list dynamically allocated */
1899 char **p; /* parameter list */
1900 #ifdef CONFIG_ASH_GETOPTS
1901 int optind; /* next parameter to be processed by getopts */
1902 int optoff; /* used by getopts */
1907 #define eflag optlist[0]
1908 #define fflag optlist[1]
1909 #define Iflag optlist[2]
1910 #define iflag optlist[3]
1911 #define mflag optlist[4]
1912 #define nflag optlist[5]
1913 #define sflag optlist[6]
1914 #define xflag optlist[7]
1915 #define vflag optlist[8]
1916 #define Cflag optlist[9]
1917 #define aflag optlist[10]
1918 #define bflag optlist[11]
1919 #define uflag optlist[12]
1920 #define viflag optlist[13]
1923 #define nolog optlist[14]
1924 #define debug optlist[15]
1927 #ifndef CONFIG_FEATURE_COMMAND_EDITING_VI
1928 #define setvimode(on) viflag = 0 /* forcibly keep the option off */
1934 static const char *const optletters_optnames[] = {
1955 #define optletters(n) optletters_optnames[(n)][0]
1956 #define optnames(n) (&optletters_optnames[(n)][1])
1958 #define NOPTS (sizeof(optletters_optnames)/sizeof(optletters_optnames[0]))
1960 static char optlist[NOPTS];
1963 static char *arg0; /* value of $0 */
1964 static struct shparam shellparam; /* $@ current positional parameters */
1965 static char **argptr; /* argument list for builtin commands */
1966 static char *optionarg; /* set by nextopt (like getopt) */
1967 static char *optptr; /* used by nextopt */
1969 static char *minusc; /* argument to -c option */
1972 static void procargs(int, char **);
1973 static void optschanged(void);
1974 static void setparam(char **);
1975 static void freeparam(volatile struct shparam *);
1976 static int shiftcmd(int, char **);
1977 static int setcmd(int, char **);
1978 static int nextopt(const char *);
1982 /* flags passed to redirect */
1983 #define REDIR_PUSH 01 /* save previous values of file descriptors */
1984 #define REDIR_SAVEFD2 03 /* set preverrout */
1987 static void redirect(union node *, int);
1988 static void popredir(int);
1989 static void clearredir(int);
1990 static int copyfd(int, int);
1991 static int redirectsafe(union node *, int);
1997 static void showtree(union node *);
1998 static void trace(const char *, ...);
1999 static void tracev(const char *, va_list);
2000 static void trargs(char **);
2001 static void trputc(int);
2002 static void trputs(const char *);
2003 static void opentrace(void);
2009 /* trap handler commands */
2010 static char *trap[NSIG];
2011 /* current value of signal */
2012 static char sigmode[NSIG - 1];
2013 /* indicates specified signal received */
2014 static char gotsig[NSIG - 1];
2016 static void clear_traps(void);
2017 static void setsignal(int);
2018 static void ignoresig(int);
2019 static void onsig(int);
2020 static int dotrap(void);
2021 static void setinteractive(int);
2022 static void exitshell(void) ATTRIBUTE_NORETURN;
2023 static int decode_signal(const char *, int);
2026 * This routine is called when an error or an interrupt occurs in an
2027 * interactive shell and control is returned to the main command loop.
2041 parselleft = parsenleft = 0; /* clear input buffer */
2045 /* from parser.c: */
2058 #ifdef CONFIG_ASH_ALIAS
2059 static struct alias *atab[ATABSIZE];
2061 static void setalias(const char *, const char *);
2062 static struct alias *freealias(struct alias *);
2063 static struct alias **__lookupalias(const char *);
2066 setalias(const char *name, const char *val)
2068 struct alias *ap, **app;
2070 app = __lookupalias(name);
2074 if (!(ap->flag & ALIASINUSE)) {
2077 ap->val = savestr(val);
2078 ap->flag &= ~ALIASDEAD;
2081 ap = ckmalloc(sizeof (struct alias));
2082 ap->name = savestr(name);
2083 ap->val = savestr(val);
2092 unalias(const char *name)
2096 app = __lookupalias(name);
2100 *app = freealias(*app);
2111 struct alias *ap, **app;
2115 for (i = 0; i < ATABSIZE; i++) {
2117 for (ap = *app; ap; ap = *app) {
2118 *app = freealias(*app);
2127 static struct alias *
2128 lookupalias(const char *name, int check)
2130 struct alias *ap = *__lookupalias(name);
2132 if (check && ap && (ap->flag & ALIASINUSE))
2138 * TODO - sort output
2141 aliascmd(int argc, char **argv)
2150 for (i = 0; i < ATABSIZE; i++)
2151 for (ap = atab[i]; ap; ap = ap->next) {
2156 while ((n = *++argv) != NULL) {
2157 if ((v = strchr(n+1, '=')) == NULL) { /* n+1: funny ksh stuff */
2158 if ((ap = *__lookupalias(n)) == NULL) {
2159 fprintf(stderr, "%s: %s not found\n", "alias", n);
2173 unaliascmd(int argc, char **argv)
2177 while ((i = nextopt("a")) != '\0') {
2183 for (i = 0; *argptr; argptr++) {
2184 if (unalias(*argptr)) {
2185 fprintf(stderr, "%s: %s not found\n", "unalias", *argptr);
2193 static struct alias *
2194 freealias(struct alias *ap) {
2197 if (ap->flag & ALIASINUSE) {
2198 ap->flag |= ALIASDEAD;
2210 printalias(const struct alias *ap) {
2211 out1fmt("%s=%s\n", ap->name, single_quote(ap->val));
2214 static struct alias **
2215 __lookupalias(const char *name) {
2216 unsigned int hashval;
2223 ch = (unsigned char)*p;
2227 ch = (unsigned char)*++p;
2229 app = &atab[hashval % ATABSIZE];
2231 for (; *app; app = &(*app)->next) {
2232 if (equal(name, (*app)->name)) {
2239 #endif /* CONFIG_ASH_ALIAS */
2245 * The cd and pwd commands.
2248 #define CD_PHYSICAL 1
2251 static int docd(const char *, int);
2252 static int cdopt(void);
2254 static char *curdir = nullstr; /* current working directory */
2255 static char *physdir = nullstr; /* physical working directory */
2264 while ((i = nextopt("LP"))) {
2266 flags ^= CD_PHYSICAL;
2275 cdcmd(int argc, char **argv)
2287 dest = bltinlookup(homestr);
2288 else if (dest[0] == '-' && dest[1] == '\0') {
2289 dest = bltinlookup("OLDPWD");
2311 if (!(path = bltinlookup("CDPATH"))) {
2319 p = padvance(&path, dest);
2320 if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
2324 if (!docd(p, flags))
2329 sh_error("can't cd to %s", dest);
2332 if (flags & CD_PRINT)
2333 out1fmt(snlfmt, curdir);
2339 * Update curdir (the name of the current directory) in response to a
2343 static inline const char *
2344 updatepwd(const char *dir)
2351 cdcomppath = sstrdup(dir);
2354 if (curdir == nullstr)
2356 new = stputs(curdir, new);
2358 new = makestrspace(strlen(dir) + 2, new);
2359 lim = stackblock() + 1;
2363 if (new > lim && *lim == '/')
2368 if (dir[1] == '/' && dir[2] != '/') {
2374 p = strtok(cdcomppath, "/");
2378 if (p[1] == '.' && p[2] == '\0') {
2385 } else if (p[1] == '\0')
2389 new = stputs(p, new);
2397 return stackblock();
2401 * Actually do the chdir. We also call hashcd to let the routines in exec.c
2402 * know that the current directory has changed.
2406 docd(const char *dest, int flags)
2408 const char *dir = 0;
2411 TRACE(("docd(\"%s\", %d) called\n", dest, flags));
2414 if (!(flags & CD_PHYSICAL)) {
2415 dir = updatepwd(dest);
2430 * Find out what the current directory is. If we already know the current
2431 * directory, this routine returns immediately.
2433 static inline char *
2436 char *dir = getcwd(0, 0);
2437 return dir ? dir : nullstr;
2441 pwdcmd(int argc, char **argv)
2444 const char *dir = curdir;
2448 if (physdir == nullstr)
2452 out1fmt(snlfmt, dir);
2457 setpwd(const char *val, int setold)
2461 oldcur = dir = curdir;
2464 setvar("OLDPWD", oldcur, VEXPORT);
2467 if (physdir != nullstr) {
2468 if (physdir != oldcur)
2472 if (oldcur == val || !val) {
2479 if (oldcur != dir && oldcur != nullstr) {
2484 setvar("PWD", dir, VEXPORT);
2490 * Errors and exceptions.
2494 * Code to handle exceptions in C.
2499 static void exverror(int, const char *, va_list)
2503 * Called to raise an exception. Since C doesn't include exceptions, we
2504 * just do a longjmp to the exception handler. The type of exception is
2505 * stored in the global variable "exception".
2512 if (handler == NULL)
2518 longjmp(handler->loc, 1);
2523 * Called from trap.c when a SIGINT is received. (If the user specifies
2524 * that SIGINT is to be trapped or ignored using the trap builtin, then
2525 * this routine is not called.) Suppressint is nonzero when interrupts
2526 * are held using the INTOFF macro. (The test for iflag is just
2527 * defensive programming.)
2536 /* comment by vodz: its strange for me, this programm don`t use other
2541 if (gotsig[SIGINT - 1] && !trap[SIGINT]) {
2542 if (!(rootshell && iflag)) {
2543 signal(SIGINT, SIG_DFL);
2553 exvwarning(const char *msg, va_list ap)
2558 fprintf(errs, "%s: ", arg0);
2560 const char *fmt = (!iflag || parsefile->fd) ?
2561 "%s: %d: " : "%s: ";
2562 fprintf(errs, fmt, commandname, startlinno);
2564 vfprintf(errs, msg, ap);
2565 outcslow('\n', errs);
2569 * Exverror is called to raise the error exception. If the second argument
2570 * is not NULL then error prints an error message using printf style
2571 * formatting. It then raises the error exception.
2574 exverror(int cond, const char *msg, va_list ap)
2578 TRACE(("exverror(%d, \"", cond));
2580 TRACE(("\") pid=%d\n", getpid()));
2582 TRACE(("exverror(%d, NULL) pid=%d\n", cond, getpid()));
2585 exvwarning(msg, ap);
2594 sh_error(const char *msg, ...)
2599 exverror(EXERROR, msg, ap);
2606 exerror(int cond, const char *msg, ...)
2611 exverror(cond, msg, ap);
2617 * error/warning routines for external builtins
2621 sh_warnx(const char *fmt, ...)
2626 exvwarning(fmt, ap);
2632 * Return a string describing an error. The returned string may be a
2633 * pointer to a static buffer that will be overwritten on the next call.
2634 * Action describes the operation that got the error.
2638 errmsg(int e, const char *em)
2640 if(e == ENOENT || e == ENOTDIR) {
2651 * Evaluate a command.
2654 /* flags in argument to evaltree */
2655 #define EV_EXIT 01 /* exit after evaluating tree */
2656 #define EV_TESTED 02 /* exit status is checked; ignore -e flag */
2657 #define EV_BACKCMD 04 /* command executing within back quotes */
2660 static void evalloop(union node *, int);
2661 static void evalfor(union node *, int);
2662 static void evalcase(union node *, int);
2663 static void evalsubshell(union node *, int);
2664 static void expredir(union node *);
2665 static void evalpipe(union node *, int);
2666 static void evalcommand(union node *, int);
2667 static int evalbltin(const struct builtincmd *, int, char **);
2668 static int evalfun(struct funcnode *, int, char **, int);
2669 static void prehash(union node *);
2670 static int bltincmd(int, char **);
2673 static const struct builtincmd bltin = {
2679 * Called to reset things after an exception.
2687 evalcmd(int argc, char **argv)
2696 STARTSTACKSTR(concat);
2699 concat = stputs(p, concat);
2700 if ((p = *ap++) == NULL)
2702 STPUTC(' ', concat);
2704 STPUTC('\0', concat);
2705 p = grabstackstr(concat);
2707 evalstring(p, ~SKIPEVAL);
2715 * Execute a command or commands contained in a string.
2719 evalstring(char *s, int mask)
2722 struct stackmark smark;
2726 setstackmark(&smark);
2729 while ((n = parsecmd(0)) != NEOF) {
2731 popstackmark(&smark);
2746 * Evaluate a parse tree. The value is left in the global variable
2751 evaltree(union node *n, int flags)
2754 void (*evalfn)(union node *, int);
2758 TRACE(("evaltree(NULL) called\n"));
2761 TRACE(("pid %d, evaltree(%p: %d, %d) called\n",
2762 getpid(), n, n->type, flags));
2766 out1fmt("Node type = %d\n", n->type);
2771 evaltree(n->nnot.com, EV_TESTED);
2772 status = !exitstatus;
2775 expredir(n->nredir.redirect);
2776 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
2778 evaltree(n->nredir.n, flags & EV_TESTED);
2779 status = exitstatus;
2784 evalfn = evalcommand;
2786 if (eflag && !(flags & EV_TESTED))
2798 evalfn = evalsubshell;
2810 #error NAND + 1 != NOR
2812 #if NOR + 1 != NSEMI
2813 #error NOR + 1 != NSEMI
2815 isor = n->type - NAND;
2818 (flags | ((isor >> 1) - 1)) & EV_TESTED
2820 if (!exitstatus == isor)
2832 evaltree(n->nif.test, EV_TESTED);
2835 if (exitstatus == 0) {
2838 } else if (n->nif.elsepart) {
2839 n = n->nif.elsepart;
2844 defun(n->narg.text, n->narg.next);
2848 exitstatus = status;
2852 if ((checkexit & exitstatus))
2853 evalskip |= SKIPEVAL;
2854 else if (pendingsigs && dotrap())
2857 if (flags & EV_EXIT) {
2864 #if !defined(__alpha__) || (defined(__GNUC__) && __GNUC__ >= 3)
2867 void evaltreenr(union node *, int) __attribute__ ((alias("evaltree"),__noreturn__));
2871 evalloop(union node *n, int flags)
2881 evaltree(n->nbinary.ch1, EV_TESTED);
2883 skipping: if (evalskip == SKIPCONT && --skipcount <= 0) {
2887 if (evalskip == SKIPBREAK && --skipcount <= 0)
2892 if (n->type != NWHILE)
2896 evaltree(n->nbinary.ch2, flags);
2897 status = exitstatus;
2902 exitstatus = status;
2908 evalfor(union node *n, int flags)
2910 struct arglist arglist;
2913 struct stackmark smark;
2915 setstackmark(&smark);
2916 arglist.lastp = &arglist.list;
2917 for (argp = n->nfor.args ; argp ; argp = argp->narg.next) {
2918 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE | EXP_RECORD);
2923 *arglist.lastp = NULL;
2928 for (sp = arglist.list ; sp ; sp = sp->next) {
2929 setvar(n->nfor.var, sp->text, 0);
2930 evaltree(n->nfor.body, flags);
2932 if (evalskip == SKIPCONT && --skipcount <= 0) {
2936 if (evalskip == SKIPBREAK && --skipcount <= 0)
2943 popstackmark(&smark);
2949 evalcase(union node *n, int flags)
2953 struct arglist arglist;
2954 struct stackmark smark;
2956 setstackmark(&smark);
2957 arglist.lastp = &arglist.list;
2958 expandarg(n->ncase.expr, &arglist, EXP_TILDE);
2960 for (cp = n->ncase.cases ; cp && evalskip == 0 ; cp = cp->nclist.next) {
2961 for (patp = cp->nclist.pattern ; patp ; patp = patp->narg.next) {
2962 if (casematch(patp, arglist.list->text)) {
2963 if (evalskip == 0) {
2964 evaltree(cp->nclist.body, flags);
2971 popstackmark(&smark);
2977 * Kick off a subshell to evaluate a tree.
2981 evalsubshell(union node *n, int flags)
2984 int backgnd = (n->type == NBACKGND);
2987 expredir(n->nredir.redirect);
2988 if (!backgnd && flags & EV_EXIT && !trap[0])
2992 if (forkshell(jp, n, backgnd) == 0) {
2996 flags &=~ EV_TESTED;
2998 redirect(n->nredir.redirect, 0);
2999 evaltreenr(n->nredir.n, flags);
3004 status = waitforjob(jp);
3005 exitstatus = status;
3012 * Compute the names of the files in a redirection list.
3016 expredir(union node *n)
3020 for (redir = n ; redir ; redir = redir->nfile.next) {
3022 fn.lastp = &fn.list;
3023 switch (redir->type) {
3029 expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
3030 redir->nfile.expfname = fn.list->text;
3034 if (redir->ndup.vname) {
3035 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
3036 fixredir(redir, fn.list->text, 1);
3046 * Evaluate a pipeline. All the processes in the pipeline are children
3047 * of the process creating the pipeline. (This differs from some versions
3048 * of the shell, which make the last process in a pipeline the parent
3053 evalpipe(union node *n, int flags)
3056 struct nodelist *lp;
3061 TRACE(("evalpipe(0x%lx) called\n", (long)n));
3063 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next)
3067 jp = makejob(n, pipelen);
3069 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
3073 if (pipe(pip) < 0) {
3075 sh_error("Pipe call failed");
3078 if (forkshell(jp, lp->n, n->npipe.backgnd) == 0) {
3091 evaltreenr(lp->n, flags);
3099 if (n->npipe.backgnd == 0) {
3100 exitstatus = waitforjob(jp);
3101 TRACE(("evalpipe: job done exit status %d\n", exitstatus));
3109 * Execute a command inside back quotes. If it's a builtin command, we
3110 * want to save its output in a block obtained from malloc. Otherwise
3111 * we fork off a subprocess and get the output of the command via a pipe.
3112 * Should be called with interrupts off.
3116 evalbackcmd(union node *n, struct backcmd *result)
3128 saveherefd = herefd;
3136 sh_error("Pipe call failed");
3138 if (forkshell(jp, n, FORK_NOJOB) == 0) {
3147 evaltreenr(n, EV_EXIT);
3151 result->fd = pip[0];
3154 herefd = saveherefd;
3156 TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
3157 result->fd, result->buf, result->nleft, result->jp));
3160 #ifdef CONFIG_ASH_CMDCMD
3161 static inline char **
3162 parse_command_args(char **argv, const char **path)
3174 if (c == '-' && !*cp) {
3184 /* run 'typecmd' for other options */
3187 } while ((c = *cp++));
3194 isassignment(const char *p)
3196 const char *q = endofname(p);
3202 #ifdef CONFIG_ASH_EXPAND_PRMT
3203 static const char *expandstr(const char *ps);
3205 #define expandstr(s) s
3209 * Execute a simple command.
3213 evalcommand(union node *cmd, int flags)
3215 struct stackmark smark;
3217 struct arglist arglist;
3218 struct arglist varlist;
3221 const struct strlist *sp;
3222 struct cmdentry cmdentry;
3230 struct builtincmd *bcmd;
3231 int pseudovarflag = 0;
3233 /* First expand the arguments. */
3234 TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
3235 setstackmark(&smark);
3236 back_exitstatus = 0;
3238 cmdentry.cmdtype = CMDBUILTIN;
3239 cmdentry.u.cmd = &bltin;
3240 varlist.lastp = &varlist.list;
3241 *varlist.lastp = NULL;
3242 arglist.lastp = &arglist.list;
3243 *arglist.lastp = NULL;
3248 bcmd = find_builtin(cmd->ncmd.args->narg.text);
3249 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
3252 for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
3253 struct strlist **spp;
3255 spp = arglist.lastp;
3256 if (pseudovarflag && isassignment(argp->narg.text))
3257 expandarg(argp, &arglist, EXP_VARTILDE);
3259 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
3261 for (sp = *spp; sp; sp = sp->next)
3265 argv = nargv = stalloc(sizeof (char *) * (argc + 1));
3266 for (sp = arglist.list ; sp ; sp = sp->next) {
3267 TRACE(("evalcommand arg: %s\n", sp->text));
3268 *nargv++ = sp->text;
3273 if (iflag && funcnest == 0 && argc > 0)
3274 lastarg = nargv[-1];
3277 expredir(cmd->ncmd.redirect);
3278 status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH|REDIR_SAVEFD2);
3281 for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
3282 struct strlist **spp;
3285 spp = varlist.lastp;
3286 expandarg(argp, &varlist, EXP_VARTILDE);
3289 * Modify the command lookup path, if a PATH= assignment
3293 if (varequal(p, path))
3297 /* Print the command if xflag is set. */
3300 const char *p = " %s";
3303 dprintf(preverrout_fd, p, expandstr(ps4val()));
3306 for(n = 0; n < 2; n++) {
3308 dprintf(preverrout_fd, p, sp->text);
3316 bb_full_write(preverrout_fd, "\n", 1);
3322 /* Now locate the command. */
3324 const char *oldpath;
3325 int cmd_flag = DO_ERR;
3330 find_command(argv[0], &cmdentry, cmd_flag, path);
3331 if (cmdentry.cmdtype == CMDUNKNOWN) {
3337 /* implement bltin and command here */
3338 if (cmdentry.cmdtype != CMDBUILTIN)
3341 spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
3342 if (cmdentry.u.cmd == EXECCMD)
3344 #ifdef CONFIG_ASH_CMDCMD
3345 if (cmdentry.u.cmd == COMMANDCMD) {
3348 nargv = parse_command_args(argv, &path);
3351 argc -= nargv - argv;
3353 cmd_flag |= DO_NOFUNC;
3361 /* We have a redirection error. */
3365 exitstatus = status;
3369 /* Execute the command. */
3370 switch (cmdentry.cmdtype) {
3372 /* Fork off a child process if necessary. */
3373 if (!(flags & EV_EXIT) || trap[0]) {
3375 jp = makejob(cmd, 1);
3376 if (forkshell(jp, cmd, FORK_FG) != 0) {
3377 exitstatus = waitforjob(jp);
3383 listsetvar(varlist.list, VEXPORT|VSTACK);
3384 shellexec(argv, path, cmdentry.u.index);
3388 cmdenviron = varlist.list;
3390 struct strlist *list = cmdenviron;
3392 if (spclbltin > 0 || argc == 0) {
3394 if (cmd_is_exec && argc > 1)
3397 listsetvar(list, i);
3399 if (evalbltin(cmdentry.u.cmd, argc, argv)) {
3414 exit_status = j + 128;
3415 exitstatus = exit_status;
3417 if (i == EXINT || spclbltin > 0) {
3419 longjmp(handler->loc, 1);
3426 listsetvar(varlist.list, 0);
3427 if (evalfun(cmdentry.u.func, argc, argv, flags))
3433 popredir(cmd_is_exec);
3435 /* dsl: I think this is intended to be used to support
3436 * '_' in 'vi' command mode during line editing...
3437 * However I implemented that within libedit itself.
3439 setvar("_", lastarg, 0);
3440 popstackmark(&smark);
3444 evalbltin(const struct builtincmd *cmd, int argc, char **argv) {
3445 char *volatile savecmdname;
3446 struct jmploc *volatile savehandler;
3447 struct jmploc jmploc;
3450 savecmdname = commandname;
3451 if ((i = setjmp(jmploc.loc)))
3453 savehandler = handler;
3455 commandname = argv[0];
3457 optptr = NULL; /* initialize nextopt */
3458 exitstatus = (*cmd->builtin)(argc, argv);
3461 exitstatus |= ferror(stdout);
3462 commandname = savecmdname;
3464 handler = savehandler;
3470 evalfun(struct funcnode *func, int argc, char **argv, int flags)
3472 volatile struct shparam saveparam;
3473 struct localvar *volatile savelocalvars;
3474 struct jmploc *volatile savehandler;
3475 struct jmploc jmploc;
3478 saveparam = shellparam;
3479 savelocalvars = localvars;
3480 if ((e = setjmp(jmploc.loc))) {
3484 savehandler = handler;
3487 shellparam.malloc = 0;
3491 shellparam.nparam = argc - 1;
3492 shellparam.p = argv + 1;
3493 #ifdef CONFIG_ASH_GETOPTS
3494 shellparam.optind = 1;
3495 shellparam.optoff = -1;
3497 evaltree(&func->n, flags & EV_TESTED);
3503 localvars = savelocalvars;
3504 freeparam(&shellparam);
3505 shellparam = saveparam;
3506 handler = savehandler;
3508 evalskip &= ~SKIPFUNC;
3514 goodname(const char *p)
3516 return !*endofname(p);
3520 * Search for a command. This is called before we fork so that the
3521 * location of the command will be available in the parent as well as
3522 * the child. The check for "goodname" is an overly conservative
3523 * check that the name will not be subject to expansion.
3527 prehash(union node *n)
3529 struct cmdentry entry;
3531 if (n->type == NCMD && n->ncmd.args)
3532 if (goodname(n->ncmd.args->narg.text))
3533 find_command(n->ncmd.args->narg.text, &entry, 0,
3540 * Builtin commands. Builtin commands whose functions are closely
3541 * tied to evaluation are implemented here.
3549 bltincmd(int argc, char **argv)
3552 * Preserve exitstatus of a previous possible redirection
3555 return back_exitstatus;
3560 * Handle break and continue commands. Break, continue, and return are
3561 * all handled by setting the evalskip flag. The evaluation routines
3562 * above all check this flag, and if it is set they start skipping
3563 * commands rather than executing them. The variable skipcount is
3564 * the number of loops to break/continue, or the number of function
3565 * levels to return. (The latter is always 1.) It should probably
3566 * be an error to break out of more loops than exist, but it isn't
3567 * in the standard shell so we don't make it one here.
3571 breakcmd(int argc, char **argv)
3573 int n = argc > 1 ? number(argv[1]) : 1;
3576 sh_error(illnum, argv[1]);
3580 evalskip = (**argv == 'c')? SKIPCONT : SKIPBREAK;
3588 * The return command.
3592 returncmd(int argc, char **argv)
3595 * If called outside a function, do what ksh does;
3596 * skip the rest of the file.
3598 evalskip = funcnest ? SKIPFUNC : SKIPFILE;
3599 return argv[1] ? number(argv[1]) : exitstatus;
3604 falsecmd(int argc, char **argv)
3611 truecmd(int argc, char **argv)
3618 execcmd(int argc, char **argv)
3621 iflag = 0; /* exit on error */
3624 shellexec(argv + 1, pathval(), 0);
3633 * When commands are first encountered, they are entered in a hash table.
3634 * This ensures that a full path search will not have to be done for them
3635 * on each invocation.
3637 * We should investigate converting to a linear search, even though that
3638 * would make the command name "hash" a misnomer.
3641 #define CMDTABLESIZE 31 /* should be prime */
3642 #define ARB 1 /* actual size determined at run time */
3647 struct tblentry *next; /* next entry in hash chain */
3648 union param param; /* definition of builtin function */
3649 short cmdtype; /* index identifying command */
3650 char rehash; /* if set, cd done since entry created */
3651 char cmdname[ARB]; /* name of command */
3655 static struct tblentry *cmdtable[CMDTABLESIZE];
3656 static int builtinloc = -1; /* index in path of %builtin, or -1 */
3659 static void tryexec(char *, char **, char **);
3660 static void clearcmdentry(int);
3661 static struct tblentry *cmdlookup(const char *, int);
3662 static void delete_cmd_entry(void);
3666 * Exec a program. Never returns. If you change this routine, you may
3667 * have to change the find_command routine as well.
3671 shellexec(char **argv, const char *path, int idx)
3679 envp = environment();
3680 if (strchr(argv[0], '/') != NULL
3681 #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
3682 || find_applet_by_name(argv[0])
3685 tryexec(argv[0], argv, envp);
3689 while ((cmdname = padvance(&path, argv[0])) != NULL) {
3690 if (--idx < 0 && pathopt == NULL) {
3691 tryexec(cmdname, argv, envp);
3692 if (errno != ENOENT && errno != ENOTDIR)
3699 /* Map to POSIX errors */
3711 exitstatus = exerrno;
3712 TRACE(("shellexec failed for %s, errno %d, suppressint %d\n",
3713 argv[0], e, suppressint ));
3714 exerror(EXEXEC, "%s: %s", argv[0], errmsg(e, E_EXEC));
3720 tryexec(char *cmd, char **argv, char **envp)
3723 #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
3724 if(find_applet_by_name(cmd) != NULL) {
3725 /* re-exec ourselves with the new arguments */
3726 execve("/proc/self/exe",argv,envp);
3727 /* If proc isn't mounted, try hardcoded path to busybox binary*/
3728 execve("/bin/busybox",argv,envp);
3729 /* If they called chroot or otherwise made the binary no longer
3730 * executable, fall through */
3737 execve(cmd, argv, envp);
3738 } while (errno == EINTR);
3740 execve(cmd, argv, envp);
3744 } else if (errno == ENOEXEC) {
3748 for (ap = argv; *ap; ap++)
3750 ap = new = ckmalloc((ap - argv + 2) * sizeof(char *));
3752 *ap = cmd = (char *)DEFAULT_SHELL;
3755 while ((*ap++ = *argv++))
3765 * Do a path search. The variable path (passed by reference) should be
3766 * set to the start of the path before the first call; padvance will update
3767 * this value as it proceeds. Successive calls to padvance will return
3768 * the possible path expansions in sequence. If an option (indicated by
3769 * a percent sign) appears in the path entry then the global variable
3770 * pathopt will be set to point to it; otherwise pathopt will be set to
3775 padvance(const char **path, const char *name)
3785 for (p = start ; *p && *p != ':' && *p != '%' ; p++);
3786 len = p - start + strlen(name) + 2; /* "2" is for '/' and '\0' */
3787 while (stackblocksize() < len)
3791 memcpy(q, start, p - start);
3799 while (*p && *p != ':') p++;
3805 return stalloc(len);
3809 /*** Command hashing code ***/
3812 printentry(struct tblentry *cmdp)
3818 idx = cmdp->param.index;
3821 name = padvance(&path, cmdp->cmdname);
3823 } while (--idx >= 0);
3824 out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
3829 hashcmd(int argc, char **argv)
3831 struct tblentry **pp;
3832 struct tblentry *cmdp;
3834 struct cmdentry entry;
3837 while ((c = nextopt("r")) != '\0') {
3841 if (*argptr == NULL) {
3842 for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
3843 for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
3844 if (cmdp->cmdtype == CMDNORMAL)
3851 while ((name = *argptr) != NULL) {
3852 if ((cmdp = cmdlookup(name, 0)) != NULL
3853 && (cmdp->cmdtype == CMDNORMAL
3854 || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0)))
3856 find_command(name, &entry, DO_ERR, pathval());
3857 if (entry.cmdtype == CMDUNKNOWN)
3866 * Resolve a command name. If you change this routine, you may have to
3867 * change the shellexec routine as well.
3871 find_command(char *name, struct cmdentry *entry, int act, const char *path)
3873 struct tblentry *cmdp;
3880 struct builtincmd *bcmd;
3882 /* If name contains a slash, don't use PATH or hash table */
3883 if (strchr(name, '/') != NULL) {
3884 entry->u.index = -1;
3886 while (stat(name, &statb) < 0) {
3891 entry->cmdtype = CMDUNKNOWN;
3895 entry->cmdtype = CMDNORMAL;
3899 #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
3900 if (find_applet_by_name(name)) {
3901 entry->cmdtype = CMDNORMAL;
3902 entry->u.index = -1;
3907 updatetbl = (path == pathval());
3910 if (strstr(path, "%builtin") != NULL)
3914 /* If name is in the table, check answer will be ok */
3915 if ((cmdp = cmdlookup(name, 0)) != NULL) {
3918 switch (cmdp->cmdtype) {
3936 } else if (cmdp->rehash == 0)
3937 /* if not invalidated by cd, we're done */
3941 /* If %builtin not in path, check for builtin next */
3942 bcmd = find_builtin(name);
3943 if (bcmd && (IS_BUILTIN_REGULAR(bcmd) || (
3944 act & DO_ALTPATH ? !(act & DO_ALTBLTIN) : builtinloc <= 0
3946 goto builtin_success;
3948 /* We have to search path. */
3949 prev = -1; /* where to start */
3950 if (cmdp && cmdp->rehash) { /* doing a rehash */
3951 if (cmdp->cmdtype == CMDBUILTIN)
3954 prev = cmdp->param.index;
3960 while ((fullname = padvance(&path, name)) != NULL) {
3961 stunalloc(fullname);
3964 if (prefix(pathopt, "builtin")) {
3966 goto builtin_success;
3968 } else if (!(act & DO_NOFUNC) &&
3969 prefix(pathopt, "func")) {
3972 /* ignore unimplemented options */
3976 /* if rehash, don't redo absolute path names */
3977 if (fullname[0] == '/' && idx <= prev) {
3980 TRACE(("searchexec \"%s\": no change\n", name));
3983 while (stat(fullname, &statb) < 0) {
3988 if (errno != ENOENT && errno != ENOTDIR)
3992 e = EACCES; /* if we fail, this will be the error */
3993 if (!S_ISREG(statb.st_mode))
3995 if (pathopt) { /* this is a %func directory */
3996 stalloc(strlen(fullname) + 1);
3997 readcmdfile(fullname);
3998 if ((cmdp = cmdlookup(name, 0)) == NULL ||
3999 cmdp->cmdtype != CMDFUNCTION)
4000 sh_error("%s not defined in %s", name, fullname);
4001 stunalloc(fullname);
4004 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
4006 entry->cmdtype = CMDNORMAL;
4007 entry->u.index = idx;
4011 cmdp = cmdlookup(name, 1);
4012 cmdp->cmdtype = CMDNORMAL;
4013 cmdp->param.index = idx;
4018 /* We failed. If there was an entry for this command, delete it */
4019 if (cmdp && updatetbl)
4022 sh_warnx("%s: %s", name, errmsg(e, E_EXEC));
4023 entry->cmdtype = CMDUNKNOWN;
4028 entry->cmdtype = CMDBUILTIN;
4029 entry->u.cmd = bcmd;
4033 cmdp = cmdlookup(name, 1);
4034 cmdp->cmdtype = CMDBUILTIN;
4035 cmdp->param.cmd = bcmd;
4039 entry->cmdtype = cmdp->cmdtype;
4040 entry->u = cmdp->param;
4045 * Wrapper around strcmp for qsort/bsearch/...
4047 static int pstrcmp(const void *a, const void *b)
4049 return strcmp((const char *) a, (*(const char *const *) b) + 1);
4053 * Search the table of builtin commands.
4056 static struct builtincmd *
4057 find_builtin(const char *name)
4059 struct builtincmd *bp;
4062 name, builtincmd, NUMBUILTINS, sizeof(struct builtincmd),
4071 * Called when a cd is done. Marks all commands so the next time they
4072 * are executed they will be rehashed.
4078 struct tblentry **pp;
4079 struct tblentry *cmdp;
4081 for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
4082 for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
4083 if (cmdp->cmdtype == CMDNORMAL || (
4084 cmdp->cmdtype == CMDBUILTIN &&
4085 !(IS_BUILTIN_REGULAR(cmdp->param.cmd)) &&
4096 * Fix command hash table when PATH changed.
4097 * Called before PATH is changed. The argument is the new value of PATH;
4098 * pathval() still returns the old value at this point.
4099 * Called with interrupts off.
4103 changepath(const char *newval)
4105 const char *old, *new;
4112 firstchange = 9999; /* assume no change */
4118 if ((*old == '\0' && *new == ':')
4119 || (*old == ':' && *new == '\0'))
4121 old = new; /* ignore subsequent differences */
4125 if (*new == '%' && idx_bltin < 0 && prefix(new + 1, "builtin"))
4132 if (builtinloc < 0 && idx_bltin >= 0)
4133 builtinloc = idx_bltin; /* zap builtins */
4134 if (builtinloc >= 0 && idx_bltin < 0)
4136 clearcmdentry(firstchange);
4137 builtinloc = idx_bltin;
4142 * Clear out command entries. The argument specifies the first entry in
4143 * PATH which has changed.
4147 clearcmdentry(int firstchange)
4149 struct tblentry **tblp;
4150 struct tblentry **pp;
4151 struct tblentry *cmdp;
4154 for (tblp = cmdtable ; tblp < &cmdtable[CMDTABLESIZE] ; tblp++) {
4156 while ((cmdp = *pp) != NULL) {
4157 if ((cmdp->cmdtype == CMDNORMAL &&
4158 cmdp->param.index >= firstchange)
4159 || (cmdp->cmdtype == CMDBUILTIN &&
4160 builtinloc >= firstchange)) {
4174 * Locate a command in the command hash table. If "add" is nonzero,
4175 * add the command to the table if it is not already present. The
4176 * variable "lastcmdentry" is set to point to the address of the link
4177 * pointing to the entry, so that delete_cmd_entry can delete the
4180 * Interrupts must be off if called with add != 0.
4183 static struct tblentry **lastcmdentry;
4186 static struct tblentry *
4187 cmdlookup(const char *name, int add)
4189 unsigned int hashval;
4191 struct tblentry *cmdp;
4192 struct tblentry **pp;
4195 hashval = (unsigned char)*p << 4;
4197 hashval += (unsigned char)*p++;
4199 pp = &cmdtable[hashval % CMDTABLESIZE];
4200 for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
4201 if (equal(cmdp->cmdname, name))
4205 if (add && cmdp == NULL) {
4206 cmdp = *pp = ckmalloc(sizeof (struct tblentry) - ARB
4207 + strlen(name) + 1);
4209 cmdp->cmdtype = CMDUNKNOWN;
4210 strcpy(cmdp->cmdname, name);
4217 * Delete the command entry returned on the last lookup.
4221 delete_cmd_entry(void)
4223 struct tblentry *cmdp;
4226 cmdp = *lastcmdentry;
4227 *lastcmdentry = cmdp->next;
4228 if (cmdp->cmdtype == CMDFUNCTION)
4229 freefunc(cmdp->param.func);
4236 * Add a new command entry, replacing any existing command entry for
4237 * the same name - except special builtins.
4241 addcmdentry(char *name, struct cmdentry *entry)
4243 struct tblentry *cmdp;
4245 cmdp = cmdlookup(name, 1);
4246 if (cmdp->cmdtype == CMDFUNCTION) {
4247 freefunc(cmdp->param.func);
4249 cmdp->cmdtype = entry->cmdtype;
4250 cmdp->param = entry->u;
4255 * Make a copy of a parse tree.
4258 static inline struct funcnode *
4259 copyfunc(union node *n)
4264 funcblocksize = offsetof(struct funcnode, n);
4267 blocksize = funcblocksize;
4268 f = ckmalloc(blocksize + funcstringsize);
4269 funcblock = (char *) f + offsetof(struct funcnode, n);
4270 funcstring = (char *) f + blocksize;
4277 * Define a shell function.
4281 defun(char *name, union node *func)
4283 struct cmdentry entry;
4286 entry.cmdtype = CMDFUNCTION;
4287 entry.u.func = copyfunc(func);
4288 addcmdentry(name, &entry);
4294 * Delete a function if it exists.
4298 unsetfunc(const char *name)
4300 struct tblentry *cmdp;
4302 if ((cmdp = cmdlookup(name, 0)) != NULL &&
4303 cmdp->cmdtype == CMDFUNCTION)
4308 * Locate and print what a word is...
4312 #ifdef CONFIG_ASH_CMDCMD
4314 describe_command(char *command, int describe_command_verbose)
4316 #define describe_command_verbose 1
4318 describe_command(char *command)
4321 struct cmdentry entry;
4322 struct tblentry *cmdp;
4323 #ifdef CONFIG_ASH_ALIAS
4324 const struct alias *ap;
4326 const char *path = pathval();
4328 if (describe_command_verbose) {
4332 /* First look at the keywords */
4333 if (findkwd(command)) {
4334 out1str(describe_command_verbose ? " is a shell keyword" : command);
4338 #ifdef CONFIG_ASH_ALIAS
4339 /* Then look at the aliases */
4340 if ((ap = lookupalias(command, 0)) != NULL) {
4341 if (describe_command_verbose) {
4342 out1fmt(" is an alias for %s", ap->val);
4351 /* Then check if it is a tracked alias */
4352 if ((cmdp = cmdlookup(command, 0)) != NULL) {
4353 entry.cmdtype = cmdp->cmdtype;
4354 entry.u = cmdp->param;
4356 /* Finally use brute force */
4357 find_command(command, &entry, DO_ABS, path);
4360 switch (entry.cmdtype) {
4362 int j = entry.u.index;
4368 p = padvance(&path, command);
4372 if (describe_command_verbose) {
4374 (cmdp ? " a tracked alias for" : nullstr), p
4383 if (describe_command_verbose) {
4384 out1str(" is a shell function");
4391 if (describe_command_verbose) {
4392 out1fmt(" is a %sshell builtin",
4393 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
4394 "special " : nullstr
4402 if (describe_command_verbose) {
4403 out1str(": not found\n");
4409 outstr("\n", stdout);
4414 typecmd(int argc, char **argv)
4419 for (i = 1; i < argc; i++) {
4420 #ifdef CONFIG_ASH_CMDCMD
4421 err |= describe_command(argv[i], 1);
4423 err |= describe_command(argv[i]);
4429 #ifdef CONFIG_ASH_CMDCMD
4431 commandcmd(int argc, char **argv)
4439 while ((c = nextopt("pvV")) != '\0')
4441 verify |= VERIFY_VERBOSE;
4443 verify |= VERIFY_BRIEF;
4449 return describe_command(*argptr, verify - VERIFY_BRIEF);
4458 * Routines to expand arguments to commands. We have to deal with
4459 * backquotes, shell variables, and file metacharacters.
4465 #define RMESCAPE_ALLOC 0x1 /* Allocate a new string */
4466 #define RMESCAPE_GLOB 0x2 /* Add backslashes for glob */
4467 #define RMESCAPE_QUOTED 0x4 /* Remove CTLESC unless in quotes */
4468 #define RMESCAPE_GROW 0x8 /* Grow strings instead of stalloc */
4469 #define RMESCAPE_HEAP 0x10 /* Malloc strings instead of stalloc */
4472 * Structure specifying which parts of the string should be searched
4473 * for IFS characters.
4477 struct ifsregion *next; /* next region in list */
4478 int begoff; /* offset of start of region */
4479 int endoff; /* offset of end of region */
4480 int nulonly; /* search for nul bytes only */
4483 /* output of current string */
4484 static char *expdest;
4485 /* list of back quote expressions */
4486 static struct nodelist *argbackq;
4487 /* first struct in list of ifs regions */
4488 static struct ifsregion ifsfirst;
4489 /* last struct in list */
4490 static struct ifsregion *ifslastp;
4491 /* holds expanded arg list */
4492 static struct arglist exparg;
4494 static void argstr(char *, int);
4495 static char *exptilde(char *, char *, int);
4496 static void expbackq(union node *, int, int);
4497 static const char *subevalvar(char *, char *, int, int, int, int, int);
4498 static char *evalvar(char *, int);
4499 static void strtodest(const char *, int, int);
4500 static void memtodest(const char *p, size_t len, int syntax, int quotes);
4501 static ssize_t varvalue(char *, int, int);
4502 static void recordregion(int, int, int);
4503 static void removerecordregions(int);
4504 static void ifsbreakup(char *, struct arglist *);
4505 static void ifsfree(void);
4506 static void expandmeta(struct strlist *, int);
4507 static int patmatch(char *, const char *);
4509 static int cvtnum(arith_t);
4510 static size_t esclen(const char *, const char *);
4511 static char *scanleft(char *, char *, char *, char *, int, int);
4512 static char *scanright(char *, char *, char *, char *, int, int);
4513 static void varunset(const char *, const char *, const char *, int)
4517 #define pmatch(a, b) !fnmatch((a), (b), 0)
4519 * Prepare a pattern for a expmeta (internal glob(3)) call.
4521 * Returns an stalloced string.
4524 static inline char *
4525 preglob(const char *pattern, int quoted, int flag) {
4526 flag |= RMESCAPE_GLOB;
4528 flag |= RMESCAPE_QUOTED;
4530 return _rmescapes((char *)pattern, flag);
4535 esclen(const char *start, const char *p) {
4538 while (p > start && *--p == CTLESC) {
4546 * Expand shell variables and backquotes inside a here document.
4550 expandhere(union node *arg, int fd)
4553 expandarg(arg, (struct arglist *)NULL, 0);
4554 bb_full_write(fd, stackblock(), expdest - (char *)stackblock());
4559 * Perform variable substitution and command substitution on an argument,
4560 * placing the resulting list of arguments in arglist. If EXP_FULL is true,
4561 * perform splitting and file name expansion. When arglist is NULL, perform
4562 * here document expansion.
4566 expandarg(union node *arg, struct arglist *arglist, int flag)
4571 argbackq = arg->narg.backquote;
4572 STARTSTACKSTR(expdest);
4573 ifsfirst.next = NULL;
4575 argstr(arg->narg.text, flag);
4576 p = _STPUTC('\0', expdest);
4578 if (arglist == NULL) {
4579 return; /* here document expanded */
4581 p = grabstackstr(p);
4582 exparg.lastp = &exparg.list;
4586 if (flag & EXP_FULL) {
4587 ifsbreakup(p, &exparg);
4588 *exparg.lastp = NULL;
4589 exparg.lastp = &exparg.list;
4590 expandmeta(exparg.list, flag);
4592 if (flag & EXP_REDIR) /*XXX - for now, just remove escapes */
4594 sp = (struct strlist *)stalloc(sizeof (struct strlist));
4597 exparg.lastp = &sp->next;
4601 *exparg.lastp = NULL;
4603 *arglist->lastp = exparg.list;
4604 arglist->lastp = exparg.lastp;
4610 * Perform variable and command substitution. If EXP_FULL is set, output CTLESC
4611 * characters to allow for further processing. Otherwise treat
4612 * $@ like $* since no splitting will be performed.
4616 argstr(char *p, int flag)
4618 static const char spclchars[] = {
4626 CTLBACKQ | CTLQUOTE,
4627 #ifdef CONFIG_ASH_MATH_SUPPORT
4632 const char *reject = spclchars;
4634 int quotes = flag & (EXP_FULL | EXP_CASE); /* do CTLESC */
4635 int breakall = flag & EXP_WORD;
4640 if (!(flag & EXP_VARTILDE)) {
4642 } else if (flag & EXP_VARTILDE2) {
4647 if (flag & EXP_TILDE) {
4653 if (*q == CTLESC && (flag & EXP_QWORD))
4656 p = exptilde(p, q, flag);
4659 startloc = expdest - (char *)stackblock();
4661 length += strcspn(p + length, reject);
4663 if (c && (!(c & 0x80)
4664 #ifdef CONFIG_ASH_MATH_SUPPORT
4668 /* c == '=' || c == ':' || c == CTLENDARI */
4673 expdest = stnputs(p, length, expdest);
4674 newloc = expdest - (char *)stackblock();
4675 if (breakall && !inquotes && newloc > startloc) {
4676 recordregion(startloc, newloc, 0);
4687 if (flag & EXP_VARTILDE2) {
4691 flag |= EXP_VARTILDE2;
4696 * sort of a hack - expand tildes in variable
4697 * assignments (after the first '=' and after ':'s).
4706 case CTLENDVAR: /* ??? */
4709 /* "$@" syntax adherence hack */
4712 !memcmp(p, dolatstr, DOLATSTRLEN) &&
4713 (p[4] == CTLQUOTEMARK || (
4714 p[4] == CTLENDVAR &&
4715 p[5] == CTLQUOTEMARK
4718 p = evalvar(p + 1, flag) + 1;
4721 inquotes = !inquotes;
4734 p = evalvar(p, flag);
4738 case CTLBACKQ|CTLQUOTE:
4739 expbackq(argbackq->n, c, quotes);
4740 argbackq = argbackq->next;
4742 #ifdef CONFIG_ASH_MATH_SUPPORT
4755 exptilde(char *startp, char *p, int flag)
4761 int quotes = flag & (EXP_FULL | EXP_CASE);
4766 while ((c = *++p) != '\0') {
4773 if (flag & EXP_VARTILDE)
4783 if (*name == '\0') {
4784 home = lookupvar(homestr);
4786 if ((pw = getpwnam(name)) == NULL)
4790 if (!home || !*home)
4793 startloc = expdest - (char *)stackblock();
4794 strtodest(home, SQSYNTAX, quotes);
4795 recordregion(startloc, expdest - (char *)stackblock(), 0);
4804 removerecordregions(int endoff)
4806 if (ifslastp == NULL)
4809 if (ifsfirst.endoff > endoff) {
4810 while (ifsfirst.next != NULL) {
4811 struct ifsregion *ifsp;
4813 ifsp = ifsfirst.next->next;
4814 ckfree(ifsfirst.next);
4815 ifsfirst.next = ifsp;
4818 if (ifsfirst.begoff > endoff)
4821 ifslastp = &ifsfirst;
4822 ifsfirst.endoff = endoff;
4827 ifslastp = &ifsfirst;
4828 while (ifslastp->next && ifslastp->next->begoff < endoff)
4829 ifslastp=ifslastp->next;
4830 while (ifslastp->next != NULL) {
4831 struct ifsregion *ifsp;
4833 ifsp = ifslastp->next->next;
4834 ckfree(ifslastp->next);
4835 ifslastp->next = ifsp;
4838 if (ifslastp->endoff > endoff)
4839 ifslastp->endoff = endoff;
4843 #ifdef CONFIG_ASH_MATH_SUPPORT
4845 * Expand arithmetic expression. Backup to start of expression,
4846 * evaluate, place result in (backed up) result, adjust string position.
4859 * This routine is slightly over-complicated for
4860 * efficiency. Next we scan backwards looking for the
4861 * start of arithmetic.
4863 start = stackblock();
4870 while (*p != CTLARI) {
4874 sh_error("missing CTLARI (shouldn't happen)");
4879 esc = esclen(start, p);
4889 removerecordregions(begoff);
4898 len = cvtnum(dash_arith(p + 2));
4901 recordregion(begoff, begoff + len, 0);
4906 * Expand stuff in backwards quotes.
4910 expbackq(union node *cmd, int quoted, int quotes)
4918 int syntax = quoted? DQSYNTAX : BASESYNTAX;
4919 struct stackmark smark;
4922 setstackmark(&smark);
4924 startloc = dest - (char *)stackblock();
4926 evalbackcmd(cmd, (struct backcmd *) &in);
4927 popstackmark(&smark);
4934 memtodest(p, i, syntax, quotes);
4938 i = safe_read(in.fd, buf, sizeof buf);
4939 TRACE(("expbackq: read returns %d\n", i));
4949 back_exitstatus = waitforjob(in.jp);
4953 /* Eat all trailing newlines */
4955 for (; dest > (char *)stackblock() && dest[-1] == '\n';)
4960 recordregion(startloc, dest - (char *)stackblock(), 0);
4961 TRACE(("evalbackq: size=%d: \"%.*s\"\n",
4962 (dest - (char *)stackblock()) - startloc,
4963 (dest - (char *)stackblock()) - startloc,
4964 stackblock() + startloc));
4969 scanleft(char *startp, char *rmesc, char *rmescend, char *str, int quotes,
4980 const char *s = loc2;
4986 match = pmatch(str, s);
4990 if (quotes && *loc == CTLESC)
5000 scanright(char *startp, char *rmesc, char *rmescend, char *str, int quotes,
5007 for (loc = str - 1, loc2 = rmescend; loc >= startp; loc2--) {
5010 const char *s = loc2;
5015 match = pmatch(str, s);
5022 esc = esclen(startp, loc);
5034 subevalvar(char *p, char *str, int strloc, int subtype, int startloc, int varflags, int quotes)
5038 int saveherefd = herefd;
5039 struct nodelist *saveargbackq = argbackq;
5041 char *rmesc, *rmescend;
5043 char *(*scan)(char *, char *, char *, char *, int , int);
5046 argstr(p, subtype != VSASSIGN && subtype != VSQUESTION ? EXP_CASE : 0);
5047 STPUTC('\0', expdest);
5048 herefd = saveherefd;
5049 argbackq = saveargbackq;
5050 startp = stackblock() + startloc;
5054 setvar(str, startp, 0);
5055 amount = startp - expdest;
5056 STADJUST(amount, expdest);
5060 varunset(p, str, startp, varflags);
5064 subtype -= VSTRIMRIGHT;
5066 if (subtype < 0 || subtype > 3)
5071 rmescend = stackblock() + strloc;
5073 rmesc = _rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW);
5074 if (rmesc != startp) {
5076 startp = stackblock() + startloc;
5080 str = stackblock() + strloc;
5081 preglob(str, varflags & VSQUOTE, 0);
5083 /* zero = subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX */
5084 zero = subtype >> 1;
5085 /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
5086 scan = (subtype & 1) ^ zero ? scanleft : scanright;
5088 loc = scan(startp, rmesc, rmescend, str, quotes, zero);
5091 memmove(startp, loc, str - loc);
5092 loc = startp + (str - loc) - 1;
5095 amount = loc - expdest;
5096 STADJUST(amount, expdest);
5103 * Expand a variable, and return a pointer to the next character in the
5107 evalvar(char *p, int flag)
5120 quotes = flag & (EXP_FULL | EXP_CASE);
5122 subtype = varflags & VSTYPE;
5123 quoted = varflags & VSQUOTE;
5125 easy = (!quoted || (*var == '@' && shellparam.nparam));
5126 startloc = expdest - (char *)stackblock();
5127 p = strchr(p, '=') + 1;
5130 varlen = varvalue(var, varflags, flag);
5131 if (varflags & VSNUL)
5134 if (subtype == VSPLUS) {
5135 varlen = -1 - varlen;
5139 if (subtype == VSMINUS) {
5143 p, flag | EXP_TILDE |
5144 (quoted ? EXP_QWORD : EXP_WORD)
5153 if (subtype == VSASSIGN || subtype == VSQUESTION) {
5155 if (subevalvar(p, var, 0, subtype, startloc,
5159 * Remove any recorded regions beyond
5162 removerecordregions(startloc);
5172 if (varlen < 0 && uflag)
5173 varunset(p, var, 0, 0);
5175 if (subtype == VSLENGTH) {
5176 cvtnum(varlen > 0 ? varlen : 0);
5180 if (subtype == VSNORMAL) {
5184 recordregion(startloc, expdest - (char *)stackblock(), quoted);
5193 case VSTRIMRIGHTMAX:
5202 * Terminate the string and start recording the pattern
5205 STPUTC('\0', expdest);
5206 patloc = expdest - (char *)stackblock();
5207 if (subevalvar(p, NULL, patloc, subtype,
5208 startloc, varflags, quotes) == 0) {
5209 int amount = expdest - (
5210 (char *)stackblock() + patloc - 1
5212 STADJUST(-amount, expdest);
5214 /* Remove any recorded regions beyond start of variable */
5215 removerecordregions(startloc);
5220 if (subtype != VSNORMAL) { /* skip to end of alternative */
5223 if ((c = *p++) == CTLESC)
5225 else if (c == CTLBACKQ || c == (CTLBACKQ|CTLQUOTE)) {
5227 argbackq = argbackq->next;
5228 } else if (c == CTLVAR) {
5229 if ((*p++ & VSTYPE) != VSNORMAL)
5231 } else if (c == CTLENDVAR) {
5242 * Put a string on the stack.
5246 memtodest(const char *p, size_t len, int syntax, int quotes) {
5249 q = makestrspace(len * 2, q);
5252 int c = SC2INT(*p++);
5255 if (quotes && (SIT(c, syntax) == CCTL || SIT(c, syntax) == CBACK))
5265 strtodest(const char *p, int syntax, int quotes)
5267 memtodest(p, strlen(p), syntax, quotes);
5272 * Add the value of a specialized variable to the stack string.
5276 varvalue(char *name, int varflags, int flags)
5286 int quoted = varflags & VSQUOTE;
5287 int subtype = varflags & VSTYPE;
5288 int quotes = flags & (EXP_FULL | EXP_CASE);
5290 if (quoted && (flags & EXP_FULL))
5291 sep = 1 << CHAR_BIT;
5293 syntax = quoted ? DQSYNTAX : BASESYNTAX;
5302 num = shellparam.nparam;
5312 p = makestrspace(NOPTS, expdest);
5313 for (i = NOPTS - 1; i >= 0; i--) {
5315 USTPUTC(optletters(i), p);
5326 sep = ifsset() ? SC2INT(ifsval()[0]) : ' ';
5327 if (quotes && (SIT(sep, syntax) == CCTL || SIT(sep, syntax) == CBACK))
5330 if (!(ap = shellparam.p))
5332 while ((p = *ap++)) {
5335 partlen = strlen(p);
5338 if (!(subtype == VSPLUS || subtype == VSLENGTH))
5339 memtodest(p, partlen, syntax, quotes);
5345 if (subtype == VSPLUS || subtype == VSLENGTH) {
5367 if (num < 0 || num > shellparam.nparam)
5369 p = num ? shellparam.p[num - 1] : arg0;
5372 p = lookupvar(name);
5378 if (!(subtype == VSPLUS || subtype == VSLENGTH))
5379 memtodest(p, len, syntax, quotes);
5383 if (subtype == VSPLUS || subtype == VSLENGTH)
5384 STADJUST(-len, expdest);
5390 * Record the fact that we have to scan this region of the
5391 * string for IFS characters.
5395 recordregion(int start, int end, int nulonly)
5397 struct ifsregion *ifsp;
5399 if (ifslastp == NULL) {
5403 ifsp = (struct ifsregion *)ckmalloc(sizeof (struct ifsregion));
5405 ifslastp->next = ifsp;
5409 ifslastp->begoff = start;
5410 ifslastp->endoff = end;
5411 ifslastp->nulonly = nulonly;
5416 * Break the argument string into pieces based upon IFS and add the
5417 * strings to the argument list. The regions of the string to be
5418 * searched for IFS characters have been stored by recordregion.
5421 ifsbreakup(char *string, struct arglist *arglist)
5423 struct ifsregion *ifsp;
5428 const char *ifs, *realifs;
5434 if (ifslastp != NULL) {
5437 realifs = ifsset() ? ifsval() : defifs;
5440 p = string + ifsp->begoff;
5441 nulonly = ifsp->nulonly;
5442 ifs = nulonly ? nullstr : realifs;
5444 while (p < string + ifsp->endoff) {
5448 if (strchr(ifs, *p)) {
5450 ifsspc = (strchr(defifs, *p) != NULL);
5451 /* Ignore IFS whitespace at start */
5452 if (q == start && ifsspc) {
5458 sp = (struct strlist *)stalloc(sizeof *sp);
5460 *arglist->lastp = sp;
5461 arglist->lastp = &sp->next;
5465 if (p >= string + ifsp->endoff) {
5471 if (strchr(ifs, *p) == NULL ) {
5474 } else if (strchr(defifs, *p) == NULL) {
5490 } while ((ifsp = ifsp->next) != NULL);
5499 sp = (struct strlist *)stalloc(sizeof *sp);
5501 *arglist->lastp = sp;
5502 arglist->lastp = &sp->next;
5508 struct ifsregion *p;
5513 struct ifsregion *ifsp;
5519 ifsfirst.next = NULL;
5523 static void expmeta(char *, char *);
5524 static struct strlist *expsort(struct strlist *);
5525 static struct strlist *msort(struct strlist *, int);
5527 static char *expdir;
5531 expandmeta(struct strlist *str, int flag)
5533 static const char metachars[] = {
5536 /* TODO - EXP_REDIR */
5539 struct strlist **savelastp;
5545 if (!strpbrk(str->text, metachars))
5547 savelastp = exparg.lastp;
5550 p = preglob(str->text, 0, RMESCAPE_ALLOC | RMESCAPE_HEAP);
5552 int i = strlen(str->text);
5553 expdir = ckmalloc(i < 2048 ? 2048 : i); /* XXX */
5561 if (exparg.lastp == savelastp) {
5566 *exparg.lastp = str;
5567 rmescapes(str->text);
5568 exparg.lastp = &str->next;
5570 *exparg.lastp = NULL;
5571 *savelastp = sp = expsort(*savelastp);
5572 while (sp->next != NULL)
5574 exparg.lastp = &sp->next;
5581 * Add a file name to the list.
5585 addfname(const char *name)
5589 sp = (struct strlist *)stalloc(sizeof *sp);
5590 sp->text = sstrdup(name);
5592 exparg.lastp = &sp->next;
5597 * Do metacharacter (i.e. *, ?, [...]) expansion.
5601 expmeta(char *enddir, char *name)
5616 for (p = name; *p; p++) {
5617 if (*p == '*' || *p == '?')
5619 else if (*p == '[') {
5626 if (*q == '/' || *q == '\0')
5633 } else if (*p == '\\')
5635 else if (*p == '/') {
5642 if (metaflag == 0) { /* we've reached the end of the file name */
5643 if (enddir != expdir)
5651 if (metaflag == 0 || lstat(expdir, &statb) >= 0)
5662 } while (p < start);
5664 if (enddir == expdir) {
5666 } else if (enddir == expdir + 1 && *expdir == '/') {
5672 if ((dirp = opendir(cp)) == NULL)
5674 if (enddir != expdir)
5676 if (*endname == 0) {
5688 while (! intpending && (dp = readdir(dirp)) != NULL) {
5689 if (dp->d_name[0] == '.' && ! matchdot)
5691 if (pmatch(start, dp->d_name)) {
5693 scopy(dp->d_name, enddir);
5696 for (p = enddir, cp = dp->d_name;
5697 (*p++ = *cp++) != '\0';)
5700 expmeta(p, endname);
5710 * Sort the results of file name expansion. It calculates the number of
5711 * strings to sort and then calls msort (short for merge sort) to do the
5715 static struct strlist *
5716 expsort(struct strlist *str)
5722 for (sp = str ; sp ; sp = sp->next)
5724 return msort(str, len);
5728 static struct strlist *
5729 msort(struct strlist *list, int len)
5731 struct strlist *p, *q = NULL;
5732 struct strlist **lpp;
5740 for (n = half ; --n >= 0 ; ) {
5744 q->next = NULL; /* terminate first half of list */
5745 q = msort(list, half); /* sort first half of list */
5746 p = msort(p, len - half); /* sort second half */
5749 #ifdef CONFIG_LOCALE_SUPPORT
5750 if (strcoll(p->text, q->text) < 0)
5752 if (strcmp(p->text, q->text) < 0)
5757 if ((p = *lpp) == NULL) {
5764 if ((q = *lpp) == NULL) {
5775 * Returns true if the pattern matches the string.
5779 patmatch(char *pattern, const char *string)
5781 return pmatch(preglob(pattern, 0, 0), string);
5786 * Remove any CTLESC characters from a string.
5790 _rmescapes(char *str, int flag)
5793 static const char qchars[] = { CTLESC, CTLQUOTEMARK, 0 };
5798 p = strpbrk(str, qchars);
5804 if (flag & RMESCAPE_ALLOC) {
5805 size_t len = p - str;
5806 size_t fulllen = len + strlen(p) + 1;
5808 if (flag & RMESCAPE_GROW) {
5809 r = makestrspace(fulllen, expdest);
5810 } else if (flag & RMESCAPE_HEAP) {
5811 r = ckmalloc(fulllen);
5813 r = stalloc(fulllen);
5817 q = mempcpy(q, str, len);
5820 inquotes = (flag & RMESCAPE_QUOTED) ^ RMESCAPE_QUOTED;
5821 globbing = flag & RMESCAPE_GLOB;
5822 notescaped = globbing;
5824 if (*p == CTLQUOTEMARK) {
5825 inquotes = ~inquotes;
5827 notescaped = globbing;
5831 /* naked back slash */
5837 if (notescaped && inquotes && *p != '/') {
5841 notescaped = globbing;
5846 if (flag & RMESCAPE_GROW) {
5848 STADJUST(q - r + 1, expdest);
5855 * See if a pattern matches in a case statement.
5859 casematch(union node *pattern, char *val)
5861 struct stackmark smark;
5864 setstackmark(&smark);
5865 argbackq = pattern->narg.backquote;
5866 STARTSTACKSTR(expdest);
5868 argstr(pattern->narg.text, EXP_TILDE | EXP_CASE);
5869 STACKSTRNUL(expdest);
5870 result = patmatch(stackblock(), val);
5871 popstackmark(&smark);
5884 expdest = makestrspace(32, expdest);
5885 #ifdef CONFIG_ASH_MATH_SUPPORT_64
5886 len = fmtstr(expdest, 32, "%lld", (long long) num);
5888 len = fmtstr(expdest, 32, "%ld", num);
5890 STADJUST(len, expdest);
5895 varunset(const char *end, const char *var, const char *umsg, int varflags)
5901 msg = "parameter not set";
5903 if (*end == CTLENDVAR) {
5904 if (varflags & VSNUL)
5909 sh_error("%.*s: %s%s", end - var - 1, var, msg, tail);
5916 * This implements the input routines used by the parser.
5919 #define EOF_NLEFT -99 /* value of parsenleft when EOF pushed back */
5921 static void pushfile(void);
5924 * Read a character from the script, returning PEOF on end of file.
5925 * Nul characters in the input are silently discarded.
5929 #define pgetc_as_macro() (--parsenleft >= 0? SC2INT(*parsenextc++) : preadbuffer())
5931 #ifdef CONFIG_ASH_OPTIMIZE_FOR_SIZE
5932 #define pgetc_macro() pgetc()
5936 return pgetc_as_macro();
5939 #define pgetc_macro() pgetc_as_macro()
5943 return pgetc_macro();
5949 * Same as pgetc(), but ignores PEOA.
5951 #ifdef CONFIG_ASH_ALIAS
5952 static int pgetc2(void)
5958 } while (c == PEOA);
5962 static inline int pgetc2(void)
5964 return pgetc_macro();
5969 * Read a line from the script.
5972 static inline char *
5973 pfgets(char *line, int len)
5979 while (--nleft > 0) {
5996 #ifdef CONFIG_FEATURE_COMMAND_EDITING
5997 #ifdef CONFIG_ASH_EXPAND_PRMT
5998 static char *cmdedit_prompt;
6000 static const char *cmdedit_prompt;
6002 static inline void putprompt(const char *s)
6004 #ifdef CONFIG_ASH_EXPAND_PRMT
6005 free(cmdedit_prompt);
6006 cmdedit_prompt = bb_xstrdup(s);
6012 static inline void putprompt(const char *s)
6022 char *buf = parsefile->buf;
6026 #ifdef CONFIG_FEATURE_COMMAND_EDITING
6027 if (!iflag || parsefile->fd)
6028 nr = safe_read(parsefile->fd, buf, BUFSIZ - 1);
6030 #ifdef CONFIG_FEATURE_COMMAND_TAB_COMPLETION
6031 cmdedit_path_lookup = pathval();
6033 nr = cmdedit_read_input((char *) cmdedit_prompt, buf);
6035 /* Ctrl+C presend */
6044 if(nr < 0 && errno == 0) {
6045 /* Ctrl+D presend */
6050 nr = safe_read(parsefile->fd, buf, BUFSIZ - 1);
6054 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
6055 int flags = fcntl(0, F_GETFL, 0);
6056 if (flags >= 0 && flags & O_NONBLOCK) {
6057 flags &=~ O_NONBLOCK;
6058 if (fcntl(0, F_SETFL, flags) >= 0) {
6059 out2str("sh: turning off NDELAY mode\n");
6069 * Refill the input buffer and return the next input character:
6071 * 1) If a string was pushed back on the input, pop it;
6072 * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading
6073 * from a string so we can't refill the buffer, return EOF.
6074 * 3) If the is more stuff in this buffer, use it else call read to fill it.
6075 * 4) Process input up to the next newline, deleting nul characters.
6085 while (parsefile->strpush) {
6086 #ifdef CONFIG_ASH_ALIAS
6087 if (parsenleft == -1 && parsefile->strpush->ap &&
6088 parsenextc[-1] != ' ' && parsenextc[-1] != '\t') {
6093 if (--parsenleft >= 0)
6094 return SC2INT(*parsenextc++);
6096 if (parsenleft == EOF_NLEFT || parsefile->buf == NULL)
6103 if ((more = preadfd()) <= 0) {
6104 parselleft = parsenleft = EOF_NLEFT;
6111 /* delete nul characters */
6119 memmove(q, q + 1, more);
6123 parsenleft = q - parsenextc - 1;
6129 parsenleft = q - parsenextc - 1;
6141 out2str(parsenextc);
6146 return SC2INT(*parsenextc++);
6150 * Undo the last call to pgetc. Only one character may be pushed back.
6151 * PEOF may be pushed back.
6162 * Push a string back onto the input at this current parsefile level.
6163 * We handle aliases this way.
6166 pushstring(char *s, void *ap)
6173 /*dprintf("*** calling pushstring: %s, %d\n", s, len);*/
6174 if (parsefile->strpush) {
6175 sp = ckmalloc(sizeof (struct strpush));
6176 sp->prev = parsefile->strpush;
6177 parsefile->strpush = sp;
6179 sp = parsefile->strpush = &(parsefile->basestrpush);
6180 sp->prevstring = parsenextc;
6181 sp->prevnleft = parsenleft;
6182 #ifdef CONFIG_ASH_ALIAS
6183 sp->ap = (struct alias *)ap;
6185 ((struct alias *)ap)->flag |= ALIASINUSE;
6197 struct strpush *sp = parsefile->strpush;
6200 #ifdef CONFIG_ASH_ALIAS
6202 if (parsenextc[-1] == ' ' || parsenextc[-1] == '\t') {
6203 checkkwd |= CHKALIAS;
6205 if (sp->string != sp->ap->val) {
6208 sp->ap->flag &= ~ALIASINUSE;
6209 if (sp->ap->flag & ALIASDEAD) {
6210 unalias(sp->ap->name);
6214 parsenextc = sp->prevstring;
6215 parsenleft = sp->prevnleft;
6216 /*dprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/
6217 parsefile->strpush = sp->prev;
6218 if (sp != &(parsefile->basestrpush))
6224 * Set the input to take input from a file. If push is set, push the
6225 * old input onto the stack first.
6229 setinputfile(const char *fname, int flags)
6235 if ((fd = open(fname, O_RDONLY)) < 0) {
6236 if (flags & INPUT_NOFILE_OK)
6238 sh_error("Can't open %s", fname);
6241 fd2 = copyfd(fd, 10);
6244 sh_error("Out of file descriptors");
6247 setinputfd(fd, flags & INPUT_PUSH_FILE);
6255 * Like setinputfile, but takes an open file descriptor. Call this with
6260 setinputfd(int fd, int push)
6262 (void) fcntl(fd, F_SETFD, FD_CLOEXEC);
6268 if (parsefile->buf == NULL)
6269 parsefile->buf = ckmalloc(IBUFSIZ);
6270 parselleft = parsenleft = 0;
6276 * Like setinputfile, but takes input from a string.
6280 setinputstring(char *string)
6284 parsenextc = string;
6285 parsenleft = strlen(string);
6286 parsefile->buf = NULL;
6293 * To handle the "." command, a stack of input files is used. Pushfile
6294 * adds a new entry to the stack and popfile restores the previous level.
6300 struct parsefile *pf;
6302 parsefile->nleft = parsenleft;
6303 parsefile->lleft = parselleft;
6304 parsefile->nextc = parsenextc;
6305 parsefile->linno = plinno;
6306 pf = (struct parsefile *)ckmalloc(sizeof (struct parsefile));
6307 pf->prev = parsefile;
6310 pf->basestrpush.prev = NULL;
6318 struct parsefile *pf = parsefile;
6327 parsefile = pf->prev;
6329 parsenleft = parsefile->nleft;
6330 parselleft = parsefile->lleft;
6331 parsenextc = parsefile->nextc;
6332 plinno = parsefile->linno;
6338 * Return to top level.
6344 while (parsefile != &basepf)
6350 * Close the file(s) that the shell is reading commands from. Called
6351 * after a fork is done.
6358 if (parsefile->fd > 0) {
6359 close(parsefile->fd);
6366 /* mode flags for set_curjob */
6367 #define CUR_DELETE 2
6368 #define CUR_RUNNING 1
6369 #define CUR_STOPPED 0
6371 /* mode flags for dowait */
6372 #define DOWAIT_NORMAL 0
6373 #define DOWAIT_BLOCK 1
6376 static struct job *jobtab;
6378 static unsigned njobs;
6380 /* pgrp of shell on invocation */
6381 static int initialpgrp;
6382 static int ttyfd = -1;
6385 static struct job *curjob;
6386 /* number of presumed living untracked jobs */
6389 static void set_curjob(struct job *, unsigned);
6391 static int restartjob(struct job *, int);
6392 static void xtcsetpgrp(int, pid_t);
6393 static char *commandtext(union node *);
6394 static void cmdlist(union node *, int);
6395 static void cmdtxt(union node *);
6396 static void cmdputs(const char *);
6397 static void showpipe(struct job *, FILE *);
6399 static int sprint_status(char *, int, int);
6400 static void freejob(struct job *);
6401 static struct job *getjob(const char *, int);
6402 static struct job *growjobtab(void);
6403 static void forkchild(struct job *, union node *, int);
6404 static void forkparent(struct job *, union node *, int, pid_t);
6405 static int dowait(int, struct job *);
6406 static int getstatus(struct job *);
6409 set_curjob(struct job *jp, unsigned mode)
6412 struct job **jpp, **curp;
6414 /* first remove from list */
6415 jpp = curp = &curjob;
6420 jpp = &jp1->prev_job;
6422 *jpp = jp1->prev_job;
6424 /* Then re-insert in correct position */
6432 /* job being deleted */
6435 /* newly created job or backgrounded job,
6436 put after all stopped jobs. */
6440 if (!jp1 || jp1->state != JOBSTOPPED)
6443 jpp = &jp1->prev_job;
6449 /* newly stopped job - becomes curjob */
6450 jp->prev_job = *jpp;
6458 * Turn job control on and off.
6460 * Note: This code assumes that the third arg to ioctl is a character
6461 * pointer, which is true on Berkeley systems but not System V. Since
6462 * System V doesn't have job control yet, this isn't a problem now.
6464 * Called with interrupts off.
6473 if (on == jobctl || rootshell == 0)
6477 ofd = fd = open(_PATH_TTY, O_RDWR);
6480 while (!isatty(fd) && --fd >= 0)
6483 fd = fcntl(fd, F_DUPFD, 10);
6487 fcntl(fd, F_SETFD, FD_CLOEXEC);
6488 do { /* while we are in the background */
6489 if ((pgrp = tcgetpgrp(fd)) < 0) {
6491 sh_warnx("can't access tty; job control turned off");
6495 if (pgrp == getpgrp())
6506 xtcsetpgrp(fd, pgrp);
6508 /* turning job control off */
6511 xtcsetpgrp(fd, pgrp);
6525 killcmd(int argc, char **argv)
6536 "Usage: kill [-s sigspec | -signum | -sigspec] [pid | job]... or\n"
6537 "kill -l [exitstatus]"
6541 if (**++argv == '-') {
6542 signo = decode_signal(*argv + 1, 1);
6546 while ((c = nextopt("ls:")) != '\0')
6556 signo = decode_signal(optionarg, 1);
6559 "invalid signal number or name: %s",
6570 if (!list && signo < 0)
6573 if ((signo < 0 || !*argv) ^ list) {
6581 for (i = 1; i < NSIG; i++) {
6582 name = u_signal_names(0, &i, 1);
6584 out1fmt(snlfmt, name);
6588 name = u_signal_names(*argptr, &signo, -1);
6590 out1fmt(snlfmt, name);
6592 sh_error("invalid signal number or exit status: %s", *argptr);
6598 if (**argv == '%') {
6599 jp = getjob(*argv, 0);
6600 pid = -jp->ps[0].pid;
6602 pid = **argv == '-' ?
6603 -number(*argv + 1) : number(*argv);
6605 if (kill(pid, signo) != 0) {
6606 sh_warnx("(%d) - %m", pid);
6615 #if defined(JOBS) || defined(DEBUG)
6617 jobno(const struct job *jp)
6619 return jp - jobtab + 1;
6625 fgcmd(int argc, char **argv)
6632 mode = (**argv == 'f') ? FORK_FG : FORK_BG;
6637 jp = getjob(*argv, 1);
6638 if (mode == FORK_BG) {
6639 set_curjob(jp, CUR_RUNNING);
6640 fprintf(out, "[%d] ", jobno(jp));
6642 outstr(jp->ps->cmd, out);
6644 retval = restartjob(jp, mode);
6645 } while (*argv && *++argv);
6649 static int bgcmd(int, char **) __attribute__((__alias__("fgcmd")));
6653 restartjob(struct job *jp, int mode)
6655 struct procstat *ps;
6661 if (jp->state == JOBDONE)
6663 jp->state = JOBRUNNING;
6665 if (mode == FORK_FG)
6666 xtcsetpgrp(ttyfd, pgid);
6667 killpg(pgid, SIGCONT);
6671 if (WIFSTOPPED(ps->status)) {
6674 } while (ps++, --i);
6676 status = (mode == FORK_FG) ? waitforjob(jp) : 0;
6683 sprint_status(char *s, int status, int sigonly)
6689 if (!WIFEXITED(status)) {
6691 if (WIFSTOPPED(status))
6692 st = WSTOPSIG(status);
6695 st = WTERMSIG(status);
6697 if (st == SIGINT || st == SIGPIPE)
6700 if (WIFSTOPPED(status))
6705 col = fmtstr(s, 32, strsignal(st));
6706 if (WCOREDUMP(status)) {
6707 col += fmtstr(s + col, 16, " (core dumped)");
6709 } else if (!sigonly) {
6710 st = WEXITSTATUS(status);
6712 col = fmtstr(s, 16, "Done(%d)", st);
6714 col = fmtstr(s, 16, "Done");
6723 showjob(FILE *out, struct job *jp, int mode)
6725 struct procstat *ps;
6726 struct procstat *psend;
6733 if (mode & SHOW_PGID) {
6734 /* just output process (group) id of pipeline */
6735 fprintf(out, "%d\n", ps->pid);
6739 col = fmtstr(s, 16, "[%d] ", jobno(jp));
6744 else if (curjob && jp == curjob->prev_job)
6747 if (mode & SHOW_PID)
6748 col += fmtstr(s + col, 16, "%d ", ps->pid);
6750 psend = ps + jp->nprocs;
6752 if (jp->state == JOBRUNNING) {
6753 scopy("Running", s + col);
6754 col += strlen("Running");
6756 int status = psend[-1].status;
6758 if (jp->state == JOBSTOPPED)
6759 status = jp->stopstatus;
6761 col += sprint_status(s + col, status, 0);
6767 /* for each process */
6768 col = fmtstr(s, 48, " |\n%*c%d ", indent, ' ', ps->pid) - 3;
6771 fprintf(out, "%s%*c%s",
6772 s, 33 - col >= 0 ? 33 - col : 0, ' ', ps->cmd
6774 if (!(mode & SHOW_PID)) {
6778 if (++ps == psend) {
6779 outcslow('\n', out);
6786 if (jp->state == JOBDONE) {
6787 TRACE(("showjob: freeing job %d\n", jobno(jp)));
6794 jobscmd(int argc, char **argv)
6800 while ((m = nextopt("lp")))
6810 showjob(out, getjob(*argv,0), mode);
6813 showjobs(out, mode);
6820 * Print a list of jobs. If "change" is nonzero, only print jobs whose
6821 * statuses have changed since the last call to showjobs.
6825 showjobs(FILE *out, int mode)
6829 TRACE(("showjobs(%x) called\n", mode));
6831 /* If not even one one job changed, there is nothing to do */
6832 while (dowait(DOWAIT_NORMAL, NULL) > 0)
6835 for (jp = curjob; jp; jp = jp->prev_job) {
6836 if (!(mode & SHOW_CHANGED) || jp->changed)
6837 showjob(out, jp, mode);
6843 * Mark a job structure as unused.
6847 freejob(struct job *jp)
6849 struct procstat *ps;
6853 for (i = jp->nprocs, ps = jp->ps ; --i >= 0 ; ps++) {
6854 if (ps->cmd != nullstr)
6857 if (jp->ps != &jp->ps0)
6860 set_curjob(jp, CUR_DELETE);
6866 waitcmd(int argc, char **argv)
6879 /* wait for all jobs */
6884 /* no running procs */
6887 if (jp->state == JOBRUNNING)
6892 dowait(DOWAIT_BLOCK, 0);
6898 if (**argv != '%') {
6899 pid_t pid = number(*argv);
6903 if (job->ps[job->nprocs - 1].pid == pid)
6905 job = job->prev_job;
6911 job = getjob(*argv, 0);
6912 /* loop until process terminated or stopped */
6913 while (job->state == JOBRUNNING)
6914 dowait(DOWAIT_BLOCK, 0);
6916 retval = getstatus(job);
6927 * Convert a job name to a job structure.
6931 getjob(const char *name, int getctl)
6935 const char *err_msg = "No such job: %s";
6939 char *(*match)(const char *, const char *);
6954 if (c == '+' || c == '%') {
6956 err_msg = "No current job";
6958 } else if (c == '-') {
6961 err_msg = "No previous job";
6972 jp = jobtab + num - 1;
6989 if (match(jp->ps[0].cmd, p)) {
6993 err_msg = "%s: ambiguous";
7000 err_msg = "job %s not created under job control";
7001 if (getctl && jp->jobctl == 0)
7006 sh_error(err_msg, name);
7011 * Return a new job structure.
7012 * Called with interrupts off.
7016 makejob(union node *node, int nprocs)
7021 for (i = njobs, jp = jobtab ; ; jp++) {
7028 if (jp->state != JOBDONE || !jp->waited)
7037 memset(jp, 0, sizeof(*jp));
7042 jp->prev_job = curjob;
7047 jp->ps = ckmalloc(nprocs * sizeof (struct procstat));
7049 TRACE(("makejob(0x%lx, %d) returns %%%d\n", (long)node, nprocs,
7059 struct job *jp, *jq;
7061 len = njobs * sizeof(*jp);
7063 jp = ckrealloc(jq, len + 4 * sizeof(*jp));
7065 offset = (char *)jp - (char *)jq;
7067 /* Relocate pointers */
7070 jq = (struct job *)((char *)jq + l);
7074 #define joff(p) ((struct job *)((char *)(p) + l))
7075 #define jmove(p) (p) = (void *)((char *)(p) + offset)
7076 if (xlikely(joff(jp)->ps == &jq->ps0))
7077 jmove(joff(jp)->ps);
7078 if (joff(jp)->prev_job)
7079 jmove(joff(jp)->prev_job);
7089 jp = (struct job *)((char *)jp + len);
7093 } while (--jq >= jp);
7099 * Fork off a subshell. If we are doing job control, give the subshell its
7100 * own process group. Jp is a job structure that the job is to be added to.
7101 * N is the command that will be evaluated by the child. Both jp and n may
7102 * be NULL. The mode parameter can be one of the following:
7103 * FORK_FG - Fork off a foreground process.
7104 * FORK_BG - Fork off a background process.
7105 * FORK_NOJOB - Like FORK_FG, but don't give the process its own
7106 * process group even if job control is on.
7108 * When job control is turned off, background processes have their standard
7109 * input redirected to /dev/null (except for the second and later processes
7112 * Called with interrupts off.
7116 forkchild(struct job *jp, union node *n, int mode)
7120 TRACE(("Child shell %d\n", getpid()));
7127 /* do job control only in root shell */
7129 if (mode != FORK_NOJOB && jp->jobctl && !oldlvl) {
7132 if (jp->nprocs == 0)
7135 pgrp = jp->ps[0].pid;
7136 /* This can fail because we are doing it in the parent also */
7137 (void)setpgid(0, pgrp);
7138 if (mode == FORK_FG)
7139 xtcsetpgrp(ttyfd, pgrp);
7144 if (mode == FORK_BG) {
7147 if (jp->nprocs == 0) {
7149 if (open(_PATH_DEVNULL, O_RDONLY) != 0)
7150 sh_error("Can't open %s", _PATH_DEVNULL);
7153 if (!oldlvl && iflag) {
7158 for (jp = curjob; jp; jp = jp->prev_job)
7164 forkparent(struct job *jp, union node *n, int mode, pid_t pid)
7166 TRACE(("In parent shell: child = %d\n", pid));
7168 while (jobless && dowait(DOWAIT_NORMAL, 0) > 0);
7173 if (mode != FORK_NOJOB && jp->jobctl) {
7176 if (jp->nprocs == 0)
7179 pgrp = jp->ps[0].pid;
7180 /* This can fail because we are doing it in the child also */
7181 (void)setpgid(pid, pgrp);
7184 if (mode == FORK_BG) {
7185 backgndpid = pid; /* set $! */
7186 set_curjob(jp, CUR_RUNNING);
7189 struct procstat *ps = &jp->ps[jp->nprocs++];
7195 ps->cmd = commandtext(n);
7201 forkshell(struct job *jp, union node *n, int mode)
7205 TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode));
7208 TRACE(("Fork failed, errno=%d", errno));
7211 sh_error("Cannot fork");
7214 forkchild(jp, n, mode);
7216 forkparent(jp, n, mode, pid);
7221 * Wait for job to finish.
7223 * Under job control we have the problem that while a child process is
7224 * running interrupts generated by the user are sent to the child but not
7225 * to the shell. This means that an infinite loop started by an inter-
7226 * active user may be hard to kill. With job control turned off, an
7227 * interactive user may place an interactive program inside a loop. If
7228 * the interactive program catches interrupts, the user doesn't want
7229 * these interrupts to also abort the loop. The approach we take here
7230 * is to have the shell ignore interrupt signals while waiting for a
7231 * foreground process to terminate, and then send itself an interrupt
7232 * signal if the child process was terminated by an interrupt signal.
7233 * Unfortunately, some programs want to do a bit of cleanup and then
7234 * exit on interrupt; unless these processes terminate themselves by
7235 * sending a signal to themselves (instead of calling exit) they will
7236 * confuse this approach.
7238 * Called with interrupts off.
7242 waitforjob(struct job *jp)
7246 TRACE(("waitforjob(%%%d) called\n", jobno(jp)));
7247 while (jp->state == JOBRUNNING) {
7248 dowait(DOWAIT_BLOCK, jp);
7253 xtcsetpgrp(ttyfd, rootpid);
7255 * This is truly gross.
7256 * If we're doing job control, then we did a TIOCSPGRP which
7257 * caused us (the shell) to no longer be in the controlling
7258 * session -- so we wouldn't have seen any ^C/SIGINT. So, we
7259 * intuit from the subprocess exit status whether a SIGINT
7260 * occurred, and if so interrupt ourselves. Yuck. - mycroft
7265 if (jp->state == JOBDONE)
7273 * Do a wait system call. If job control is compiled in, we accept
7274 * stopped processes. If block is zero, we return a value of zero
7275 * rather than blocking.
7277 * System V doesn't have a non-blocking wait system call. It does
7278 * have a SIGCLD signal that is sent to a process when one of it's
7279 * children dies. The obvious way to use SIGCLD would be to install
7280 * a handler for SIGCLD which simply bumped a counter when a SIGCLD
7281 * was received, and have waitproc bump another counter when it got
7282 * the status of a process. Waitproc would then know that a wait
7283 * system call would not block if the two counters were different.
7284 * This approach doesn't work because if a process has children that
7285 * have not been waited for, System V will send it a SIGCLD when it
7286 * installs a signal handler for SIGCLD. What this means is that when
7287 * a child exits, the shell will be sent SIGCLD signals continuously
7288 * until is runs out of stack space, unless it does a wait call before
7289 * restoring the signal handler. The code below takes advantage of
7290 * this (mis)feature by installing a signal handler for SIGCLD and
7291 * then checking to see whether it was called. If there are any
7292 * children to be waited for, it will be.
7294 * If neither SYSV nor BSD is defined, we don't implement nonblocking
7295 * waits at all. In this case, the user will not be informed when
7296 * a background process until the next time she runs a real program
7297 * (as opposed to running a builtin command or just typing return),
7298 * and the jobs command may give out of date information.
7302 waitproc(int block, int *status)
7312 return wait3(status, flags, (struct rusage *)NULL);
7316 * Wait for a process to terminate.
7320 dowait(int block, struct job *job)
7325 struct job *thisjob;
7328 TRACE(("dowait(%d) called\n", block));
7329 pid = waitproc(block, &status);
7330 TRACE(("wait returns pid %d, status=%d\n", pid, status));
7335 for (jp = curjob; jp; jp = jp->prev_job) {
7336 struct procstat *sp;
7337 struct procstat *spend;
7338 if (jp->state == JOBDONE)
7341 spend = jp->ps + jp->nprocs;
7344 if (sp->pid == pid) {
7345 TRACE(("Job %d: changing status of proc %d from 0x%x to 0x%x\n", jobno(jp), pid, sp->status, status));
7346 sp->status = status;
7349 if (sp->status == -1)
7352 if (state == JOBRUNNING)
7354 if (WIFSTOPPED(sp->status)) {
7355 jp->stopstatus = sp->status;
7359 } while (++sp < spend);
7364 if (!WIFSTOPPED(status))
7371 if (state != JOBRUNNING) {
7372 thisjob->changed = 1;
7374 if (thisjob->state != state) {
7375 TRACE(("Job %d: changing state from %d to %d\n", jobno(thisjob), thisjob->state, state));
7376 thisjob->state = state;
7378 if (state == JOBSTOPPED) {
7379 set_curjob(thisjob, CUR_STOPPED);
7388 if (thisjob && thisjob == job) {
7392 len = sprint_status(s, status, 1);
7404 * return 1 if there are stopped jobs, otherwise 0
7417 if (jp && jp->state == JOBSTOPPED) {
7418 out2str("You have stopped jobs.\n");
7428 * Return a string identifying a command (to be printed by the
7433 static char *cmdnextc;
7436 commandtext(union node *n)
7440 STARTSTACKSTR(cmdnextc);
7442 name = stackblock();
7443 TRACE(("commandtext: name %p, end %p\n\t\"%s\"\n",
7444 name, cmdnextc, cmdnextc));
7445 return savestr(name);
7449 cmdtxt(union node *n)
7452 struct nodelist *lp;
7464 lp = n->npipe.cmdlist;
7482 cmdtxt(n->nbinary.ch1);
7498 cmdtxt(n->nif.test);
7501 if (n->nif.elsepart) {
7504 n = n->nif.elsepart;
7520 cmdtxt(n->nbinary.ch1);
7530 cmdputs(n->nfor.var);
7532 cmdlist(n->nfor.args, 1);
7537 cmdputs(n->narg.text);
7541 cmdlist(n->ncmd.args, 1);
7542 cmdlist(n->ncmd.redirect, 0);
7555 cmdputs(n->ncase.expr->narg.text);
7557 for (np = n->ncase.cases; np; np = np->nclist.next) {
7558 cmdtxt(np->nclist.pattern);
7560 cmdtxt(np->nclist.body);
7586 s[0] = n->nfile.fd + '0';
7590 if (n->type == NTOFD || n->type == NFROMFD) {
7591 s[0] = n->ndup.dupfd + '0';
7602 cmdlist(union node *np, int sep)
7604 for (; np; np = np->narg.next) {
7608 if (sep && np->narg.next)
7614 cmdputs(const char *s)
7616 const char *p, *str;
7617 char c, cc[2] = " ";
7621 static const char vstype[VSTYPE + 1][4] = {
7622 "", "}", "-", "+", "?", "=",
7623 "%", "%%", "#", "##"
7625 nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc);
7627 while ((c = *p++) != 0) {
7635 if ((subtype & VSTYPE) == VSLENGTH)
7639 if (!(subtype & VSQUOTE) != !(quoted & 1)) {
7646 str = "\"}" + !(quoted & 1);
7653 case CTLBACKQ+CTLQUOTE:
7656 #ifdef CONFIG_ASH_MATH_SUPPORT
7671 if ((subtype & VSTYPE) != VSNORMAL)
7673 str = vstype[subtype & VSTYPE];
7674 if (subtype & VSNUL)
7683 /* These can only happen inside quotes */
7696 while ((c = *str++)) {
7701 USTPUTC('"', nextc);
7709 showpipe(struct job *jp, FILE *out)
7711 struct procstat *sp;
7712 struct procstat *spend;
7714 spend = jp->ps + jp->nprocs;
7715 for (sp = jp->ps + 1; sp < spend; sp++)
7716 fprintf(out, " | %s", sp->cmd);
7717 outcslow('\n', out);
7722 xtcsetpgrp(int fd, pid_t pgrp)
7724 if (tcsetpgrp(fd, pgrp))
7725 sh_error("Cannot set tty process group (%m)");
7730 getstatus(struct job *job) {
7734 status = job->ps[job->nprocs - 1].status;
7735 retval = WEXITSTATUS(status);
7736 if (!WIFEXITED(status)) {
7738 retval = WSTOPSIG(status);
7739 if (!WIFSTOPPED(status))
7742 /* XXX: limits number of signals */
7743 retval = WTERMSIG(status);
7745 if (retval == SIGINT)
7751 TRACE(("getstatus: job %d, nproc %d, status %x, retval %x\n",
7752 jobno(job), job->nprocs, status, retval));
7756 #ifdef CONFIG_ASH_MAIL
7760 * Routines to check for mail. (Perhaps make part of main.c?)
7763 #define MAXMBOXES 10
7765 /* times of mailboxes */
7766 static time_t mailtime[MAXMBOXES];
7767 /* Set if MAIL or MAILPATH is changed. */
7768 static int mail_var_path_changed;
7773 * Print appropriate message(s) if mail has arrived.
7774 * If mail_var_path_changed is set,
7775 * then the value of MAIL has mail_var_path_changed,
7776 * so we just update the values.
7786 struct stackmark smark;
7789 setstackmark(&smark);
7790 mpath = mpathset() ? mpathval() : mailval();
7791 for (mtp = mailtime; mtp < mailtime + MAXMBOXES; mtp++) {
7792 p = padvance(&mpath, nullstr);
7797 for (q = p ; *q ; q++);
7802 q[-1] = '\0'; /* delete trailing '/' */
7803 if (stat(p, &statb) < 0) {
7807 if (!mail_var_path_changed && statb.st_mtime != *mtp) {
7810 pathopt ? pathopt : "you have mail"
7813 *mtp = statb.st_mtime;
7815 mail_var_path_changed = 0;
7816 popstackmark(&smark);
7821 changemail(const char *val)
7823 mail_var_path_changed++;
7826 #endif /* CONFIG_ASH_MAIL */
7832 static short profile_buf[16384];
7836 static int isloginsh;
7838 static void read_profile(const char *);
7841 * Main routine. We initialize things, parse the arguments, execute
7842 * profiles if we're a login shell, and then call cmdloop to execute
7843 * commands. The setjmp call sets up the location to jump to when an
7844 * exception occurs. When an exception occurs the variable "state"
7845 * is used to figure out how far we had gotten.
7849 ash_main(int argc, char **argv)
7853 struct jmploc jmploc;
7854 struct stackmark smark;
7857 dash_errno = __errno_location();
7861 monitor(4, etext, profile_buf, sizeof profile_buf, 50);
7864 if (setjmp(jmploc.loc)) {
7874 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl)
7878 outcslow('\n', stderr);
7880 popstackmark(&smark);
7881 FORCEINTON; /* enable interrupts */
7894 trputs("Shell args: "); trargs(argv);
7898 #ifdef CONFIG_ASH_RANDOM_SUPPORT
7899 rseed = rootpid + ((time_t)time((time_t *)0));
7902 setstackmark(&smark);
7903 procargs(argc, argv);
7904 #ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
7906 const char *hp = lookupvar("HISTFILE");
7909 hp = lookupvar("HOME");
7911 char *defhp = concat_path_file(hp, ".ash_history");
7912 setvar("HISTFILE", defhp, 0);
7918 if (argv[0] && argv[0][0] == '-')
7922 read_profile("/etc/profile");
7925 read_profile(".profile");
7931 getuid() == geteuid() && getgid() == getegid() &&
7935 if ((shinit = lookupvar("ENV")) != NULL && *shinit != '\0') {
7936 read_profile(shinit);
7942 evalstring(minusc, 0);
7944 if (sflag || minusc == NULL) {
7945 #ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
7947 const char *hp = lookupvar("HISTFILE");
7950 load_history ( hp );
7953 state4: /* XXX ??? - why isn't this before the "if" statement */
7961 extern void _mcleanup(void);
7971 * Read and execute commands. "Top" is nonzero for the top level command
7972 * loop; it turns on prompting if the shell is interactive.
7979 struct stackmark smark;
7983 TRACE(("cmdloop(%d) called\n", top));
7987 setstackmark(&smark);
7990 showjobs(stderr, SHOW_CHANGED);
7995 #ifdef CONFIG_ASH_MAIL
7999 n = parsecmd(inter);
8000 /* showtree(n); DEBUG */
8002 if (!top || numeof >= 50)
8004 if (!stoppedjobs()) {
8007 out2str("\nUse \"exit\" to leave shell.\n");
8010 } else if (nflag == 0) {
8011 job_warning = (job_warning == 2) ? 1 : 0;
8015 popstackmark(&smark);
8020 return skip & SKIPEVAL;
8029 * Read /etc/profile or .profile. Return on error.
8033 read_profile(const char *name)
8037 if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
8049 * Read a file containing shell functions.
8053 readcmdfile(char *name)
8055 setinputfile(name, INPUT_PUSH_FILE);
8062 * Take commands from a file. To be compatible we should do a path
8063 * search for the file, which is necessary to find sub-commands.
8066 static inline char *
8067 find_dot_file(char *name)
8070 const char *path = pathval();
8073 /* don't try this for absolute or relative paths */
8074 if (strchr(name, '/'))
8077 while ((fullname = padvance(&path, name)) != NULL) {
8078 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
8080 * Don't bother freeing here, since it will
8081 * be freed by the caller.
8085 stunalloc(fullname);
8088 /* not found in the PATH */
8089 sh_error(not_found_msg, name);
8093 static int dotcmd(int argc, char **argv)
8096 volatile struct shparam saveparam;
8099 for (sp = cmdenviron; sp; sp = sp->next)
8100 setvareq(bb_xstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
8102 if (argc >= 2) { /* That's what SVR2 does */
8105 fullname = find_dot_file(argv[1]);
8108 saveparam = shellparam;
8109 shellparam.malloc = 0;
8110 shellparam.nparam = argc - 2;
8111 shellparam.p = argv + 2;
8114 setinputfile(fullname, INPUT_PUSH_FILE);
8115 commandname = fullname;
8120 freeparam(&shellparam);
8121 shellparam = saveparam;
8123 status = exitstatus;
8130 exitcmd(int argc, char **argv)
8135 exitstatus = number(argv[1]);
8140 #ifdef CONFIG_ASH_BUILTIN_ECHO
8142 echocmd(int argc, char **argv)
8144 return bb_echo(argc, argv);
8150 * Same for malloc, realloc, but returns an error when out of space.
8154 ckrealloc(pointer p, size_t nbytes)
8156 p = realloc(p, nbytes);
8158 sh_error(bb_msg_memory_exhausted);
8163 ckmalloc(size_t nbytes)
8165 return ckrealloc(NULL, nbytes);
8169 * Make a copy of a string in safe storage.
8173 savestr(const char *s)
8175 char *p = strdup(s);
8177 sh_error(bb_msg_memory_exhausted);
8183 * Parse trees for commands are allocated in lifo order, so we use a stack
8184 * to make this more efficient, and also to avoid all sorts of exception
8185 * handling code to handle interrupts in the middle of a parse.
8187 * The size 504 was chosen because the Ultrix malloc handles that size
8193 stalloc(size_t nbytes)
8198 aligned = SHELL_ALIGN(nbytes);
8199 if (aligned > stacknleft) {
8202 struct stack_block *sp;
8204 blocksize = aligned;
8205 if (blocksize < MINSIZE)
8206 blocksize = MINSIZE;
8207 len = sizeof(struct stack_block) - MINSIZE + blocksize;
8208 if (len < blocksize)
8209 sh_error(bb_msg_memory_exhausted);
8213 stacknxt = sp->space;
8214 stacknleft = blocksize;
8215 sstrend = stacknxt + blocksize;
8220 stacknxt += aligned;
8221 stacknleft -= aligned;
8227 stunalloc(pointer p)
8230 if (!p || (stacknxt < (char *)p) || ((char *)p < stackp->space)) {
8231 write(2, "stunalloc\n", 10);
8235 stacknleft += stacknxt - (char *)p;
8241 setstackmark(struct stackmark *mark)
8243 mark->stackp = stackp;
8244 mark->stacknxt = stacknxt;
8245 mark->stacknleft = stacknleft;
8246 mark->marknext = markp;
8252 popstackmark(struct stackmark *mark)
8254 struct stack_block *sp;
8257 markp = mark->marknext;
8258 while (stackp != mark->stackp) {
8263 stacknxt = mark->stacknxt;
8264 stacknleft = mark->stacknleft;
8265 sstrend = mark->stacknxt + mark->stacknleft;
8271 * When the parser reads in a string, it wants to stick the string on the
8272 * stack and only adjust the stack pointer when it knows how big the
8273 * string is. Stackblock (defined in stack.h) returns a pointer to a block
8274 * of space on top of the stack and stackblocklen returns the length of
8275 * this block. Growstackblock will grow this space by at least one byte,
8276 * possibly moving it (like realloc). Grabstackblock actually allocates the
8277 * part of the block that has been used.
8281 growstackblock(void)
8285 newlen = stacknleft * 2;
8286 if (newlen < stacknleft)
8287 sh_error(bb_msg_memory_exhausted);
8291 if (stacknxt == stackp->space && stackp != &stackbase) {
8292 struct stack_block *oldstackp;
8293 struct stackmark *xmark;
8294 struct stack_block *sp;
8295 struct stack_block *prevstackp;
8301 prevstackp = sp->prev;
8302 grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
8303 sp = ckrealloc((pointer)sp, grosslen);
8304 sp->prev = prevstackp;
8306 stacknxt = sp->space;
8307 stacknleft = newlen;
8308 sstrend = sp->space + newlen;
8311 * Stack marks pointing to the start of the old block
8312 * must be relocated to point to the new block
8315 while (xmark != NULL && xmark->stackp == oldstackp) {
8316 xmark->stackp = stackp;
8317 xmark->stacknxt = stacknxt;
8318 xmark->stacknleft = stacknleft;
8319 xmark = xmark->marknext;
8323 char *oldspace = stacknxt;
8324 int oldlen = stacknleft;
8325 char *p = stalloc(newlen);
8327 /* free the space we just allocated */
8328 stacknxt = memcpy(p, oldspace, oldlen);
8329 stacknleft += newlen;
8334 grabstackblock(size_t len)
8336 len = SHELL_ALIGN(len);
8342 * The following routines are somewhat easier to use than the above.
8343 * The user declares a variable of type STACKSTR, which may be declared
8344 * to be a register. The macro STARTSTACKSTR initializes things. Then
8345 * the user uses the macro STPUTC to add characters to the string. In
8346 * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
8347 * grown as necessary. When the user is done, she can just leave the
8348 * string there and refer to it using stackblock(). Or she can allocate
8349 * the space for it using grabstackstr(). If it is necessary to allow
8350 * someone else to use the stack temporarily and then continue to grow
8351 * the string, the user should use grabstack to allocate the space, and
8352 * then call ungrabstr(p) to return to the previous mode of operation.
8354 * USTPUTC is like STPUTC except that it doesn't check for overflow.
8355 * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
8356 * is space for at least one character.
8362 size_t len = stackblocksize();
8363 if (herefd >= 0 && len >= 1024) {
8364 bb_full_write(herefd, stackblock(), len);
8365 return stackblock();
8368 return stackblock() + len;
8372 * Called from CHECKSTRSPACE.
8376 makestrspace(size_t newlen, char *p)
8378 size_t len = p - stacknxt;
8379 size_t size = stackblocksize();
8384 size = stackblocksize();
8386 if (nleft >= newlen)
8390 return stackblock() + len;
8394 stnputs(const char *s, size_t n, char *p)
8396 p = makestrspace(n, p);
8397 p = mempcpy(p, s, n);
8402 stputs(const char *s, char *p)
8404 return stnputs(s, strlen(s), p);
8412 * number(s) Convert a string of digits to an integer.
8413 * is_number(s) Return true if s is a string of digits.
8417 * prefix -- see if pfx is a prefix of string.
8421 prefix(const char *string, const char *pfx)
8424 if (*pfx++ != *string++)
8427 return (char *) string;
8432 * Convert a string of digits to an integer, printing an error message on
8437 number(const char *s)
8441 sh_error(illnum, s);
8447 * Check for a valid number. This should be elsewhere.
8451 is_number(const char *p)
8456 } while (*++p != '\0');
8462 * Produce a possibly single quoted string suitable as input to the shell.
8463 * The return string is allocated on the stack.
8467 single_quote(const char *s) {
8476 len = strchrnul(s, '\'') - s;
8478 q = p = makestrspace(len + 3, p);
8481 q = mempcpy(q, s, len);
8487 len = strspn(s, "'");
8491 q = p = makestrspace(len + 3, p);
8494 q = mempcpy(q, s, len);
8503 return stackblock();
8507 * Like strdup but works with the ash stack.
8511 sstrdup(const char *p)
8513 size_t len = strlen(p) + 1;
8514 return memcpy(stalloc(len), p, len);
8519 calcsize(union node *n)
8523 funcblocksize += nodesize[n->type];
8526 calcsize(n->ncmd.redirect);
8527 calcsize(n->ncmd.args);
8528 calcsize(n->ncmd.assign);
8531 sizenodelist(n->npipe.cmdlist);
8536 calcsize(n->nredir.redirect);
8537 calcsize(n->nredir.n);
8544 calcsize(n->nbinary.ch2);
8545 calcsize(n->nbinary.ch1);
8548 calcsize(n->nif.elsepart);
8549 calcsize(n->nif.ifpart);
8550 calcsize(n->nif.test);
8553 funcstringsize += strlen(n->nfor.var) + 1;
8554 calcsize(n->nfor.body);
8555 calcsize(n->nfor.args);
8558 calcsize(n->ncase.cases);
8559 calcsize(n->ncase.expr);
8562 calcsize(n->nclist.body);
8563 calcsize(n->nclist.pattern);
8564 calcsize(n->nclist.next);
8568 sizenodelist(n->narg.backquote);
8569 funcstringsize += strlen(n->narg.text) + 1;
8570 calcsize(n->narg.next);
8577 calcsize(n->nfile.fname);
8578 calcsize(n->nfile.next);
8582 calcsize(n->ndup.vname);
8583 calcsize(n->ndup.next);
8587 calcsize(n->nhere.doc);
8588 calcsize(n->nhere.next);
8591 calcsize(n->nnot.com);
8598 sizenodelist(struct nodelist *lp)
8601 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
8609 copynode(union node *n)
8616 funcblock = (char *) funcblock + nodesize[n->type];
8619 new->ncmd.redirect = copynode(n->ncmd.redirect);
8620 new->ncmd.args = copynode(n->ncmd.args);
8621 new->ncmd.assign = copynode(n->ncmd.assign);
8624 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
8625 new->npipe.backgnd = n->npipe.backgnd;
8630 new->nredir.redirect = copynode(n->nredir.redirect);
8631 new->nredir.n = copynode(n->nredir.n);
8638 new->nbinary.ch2 = copynode(n->nbinary.ch2);
8639 new->nbinary.ch1 = copynode(n->nbinary.ch1);
8642 new->nif.elsepart = copynode(n->nif.elsepart);
8643 new->nif.ifpart = copynode(n->nif.ifpart);
8644 new->nif.test = copynode(n->nif.test);
8647 new->nfor.var = nodesavestr(n->nfor.var);
8648 new->nfor.body = copynode(n->nfor.body);
8649 new->nfor.args = copynode(n->nfor.args);
8652 new->ncase.cases = copynode(n->ncase.cases);
8653 new->ncase.expr = copynode(n->ncase.expr);
8656 new->nclist.body = copynode(n->nclist.body);
8657 new->nclist.pattern = copynode(n->nclist.pattern);
8658 new->nclist.next = copynode(n->nclist.next);
8662 new->narg.backquote = copynodelist(n->narg.backquote);
8663 new->narg.text = nodesavestr(n->narg.text);
8664 new->narg.next = copynode(n->narg.next);
8671 new->nfile.fname = copynode(n->nfile.fname);
8672 new->nfile.fd = n->nfile.fd;
8673 new->nfile.next = copynode(n->nfile.next);
8677 new->ndup.vname = copynode(n->ndup.vname);
8678 new->ndup.dupfd = n->ndup.dupfd;
8679 new->ndup.fd = n->ndup.fd;
8680 new->ndup.next = copynode(n->ndup.next);
8684 new->nhere.doc = copynode(n->nhere.doc);
8685 new->nhere.fd = n->nhere.fd;
8686 new->nhere.next = copynode(n->nhere.next);
8689 new->nnot.com = copynode(n->nnot.com);
8692 new->type = n->type;
8697 static struct nodelist *
8698 copynodelist(struct nodelist *lp)
8700 struct nodelist *start;
8701 struct nodelist **lpp;
8706 funcblock = (char *) funcblock +
8707 SHELL_ALIGN(sizeof(struct nodelist));
8708 (*lpp)->n = copynode(lp->n);
8710 lpp = &(*lpp)->next;
8718 nodesavestr(char *s)
8720 char *rtn = funcstring;
8722 funcstring = stpcpy(funcstring, s) + 1;
8728 * Free a parse tree.
8732 freefunc(struct funcnode *f)
8734 if (f && --f->count < 0)
8739 static void options(int);
8740 static void setoption(int, int);
8744 * Process the shell command line arguments.
8748 procargs(int argc, char **argv)
8751 const char *xminusc;
8758 for (i = 0; i < NOPTS; i++)
8764 if (*xargv == NULL) {
8766 sh_error("-c requires an argument");
8769 if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
8773 for (i = 0; i < NOPTS; i++)
8774 if (optlist[i] == 2)
8779 /* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
8784 } else if (!sflag) {
8785 setinputfile(*xargv, 0);
8791 shellparam.p = xargv;
8792 #ifdef CONFIG_ASH_GETOPTS
8793 shellparam.optind = 1;
8794 shellparam.optoff = -1;
8796 /* assert(shellparam.malloc == 0 && shellparam.nparam == 0); */
8798 shellparam.nparam++;
8811 setinteractive(iflag);
8817 minus_o(char *name, int val)
8822 out1str("Current option settings\n");
8823 for (i = 0; i < NOPTS; i++)
8824 out1fmt("%-16s%s\n", optnames(i),
8825 optlist[i] ? "on" : "off");
8827 for (i = 0; i < NOPTS; i++)
8828 if (equal(name, optnames(i))) {
8832 sh_error("Illegal option -o %s", name);
8837 * Process shell options. The global variable argptr contains a pointer
8838 * to the argument list; we advance it past the options.
8842 options(int cmdline)
8850 while ((p = *argptr) != NULL) {
8852 if ((c = *p++) == '-') {
8854 if (p[0] == '\0' || (p[0] == '-' && p[1] == '\0')) {
8856 /* "-" means turn off -x and -v */
8859 /* "--" means reset params */
8860 else if (*argptr == NULL)
8863 break; /* "-" or "--" terminates options */
8865 } else if (c == '+') {
8871 while ((c = *p++) != '\0') {
8872 if (c == 'c' && cmdline) {
8873 minusc = p; /* command is after shell args*/
8874 } else if (c == 'o') {
8875 minus_o(*argptr, val);
8878 } else if (cmdline && (c == '-')) { // long options
8879 if (strcmp(p, "login") == 0)
8891 setoption(int flag, int val)
8895 for (i = 0; i < NOPTS; i++)
8896 if (optletters(i) == flag) {
8900 sh_error("Illegal option -%c", flag);
8907 * Set the shell parameters.
8911 setparam(char **argv)
8917 for (nparam = 0 ; argv[nparam] ; nparam++);
8918 ap = newparam = ckmalloc((nparam + 1) * sizeof *ap);
8920 *ap++ = savestr(*argv++);
8923 freeparam(&shellparam);
8924 shellparam.malloc = 1;
8925 shellparam.nparam = nparam;
8926 shellparam.p = newparam;
8927 #ifdef CONFIG_ASH_GETOPTS
8928 shellparam.optind = 1;
8929 shellparam.optoff = -1;
8935 * Free the list of positional parameters.
8939 freeparam(volatile struct shparam *param)
8943 if (param->malloc) {
8944 for (ap = param->p ; *ap ; ap++)
8953 * The shift builtin command.
8957 shiftcmd(int argc, char **argv)
8964 n = number(argv[1]);
8965 if (n > shellparam.nparam)
8966 sh_error("can't shift that many");
8968 shellparam.nparam -= n;
8969 for (ap1 = shellparam.p ; --n >= 0 ; ap1++) {
8970 if (shellparam.malloc)
8974 while ((*ap2++ = *ap1++) != NULL);
8975 #ifdef CONFIG_ASH_GETOPTS
8976 shellparam.optind = 1;
8977 shellparam.optoff = -1;
8986 * The set command builtin.
8990 setcmd(int argc, char **argv)
8993 return showvars(nullstr, 0, VUNSET);
8997 if (*argptr != NULL) {
9005 #ifdef CONFIG_ASH_GETOPTS
9010 shellparam.optind = number(value);
9011 shellparam.optoff = -1;
9015 #ifdef CONFIG_LOCALE_SUPPORT
9016 static void change_lc_all(const char *value)
9018 if (value != 0 && *value != 0)
9019 setlocale(LC_ALL, value);
9022 static void change_lc_ctype(const char *value)
9024 if (value != 0 && *value != 0)
9025 setlocale(LC_CTYPE, value);
9030 #ifdef CONFIG_ASH_RANDOM_SUPPORT
9031 /* Roughly copied from bash.. */
9032 static void change_random(const char *value)
9035 /* "get", generate */
9038 rseed = rseed * 1103515245 + 12345;
9039 sprintf(buf, "%d", (unsigned int)((rseed & 32767)));
9040 /* set without recursion */
9041 setvar(vrandom.text, buf, VNOFUNC);
9042 vrandom.flags &= ~VNOFUNC;
9045 rseed = strtoul(value, (char **)NULL, 10);
9051 #ifdef CONFIG_ASH_GETOPTS
9053 getopts(char *optstr, char *optvar, char **optfirst, int *param_optind, int *optoff)
9062 if(*param_optind < 1)
9064 optnext = optfirst + *param_optind - 1;
9066 if (*param_optind <= 1 || *optoff < 0 || strlen(optnext[-1]) < *optoff)
9069 p = optnext[-1] + *optoff;
9070 if (p == NULL || *p == '\0') {
9071 /* Current word is done, advance */
9073 if (p == NULL || *p != '-' || *++p == '\0') {
9080 if (p[0] == '-' && p[1] == '\0') /* check for "--" */
9085 for (q = optstr; *q != c; ) {
9087 if (optstr[0] == ':') {
9090 err |= setvarsafe("OPTARG", s, 0);
9092 fprintf(stderr, "Illegal option -%c\n", c);
9093 (void) unsetvar("OPTARG");
9103 if (*p == '\0' && (p = *optnext) == NULL) {
9104 if (optstr[0] == ':') {
9107 err |= setvarsafe("OPTARG", s, 0);
9110 fprintf(stderr, "No arg for -%c option\n", c);
9111 (void) unsetvar("OPTARG");
9119 err |= setvarsafe("OPTARG", p, 0);
9122 err |= setvarsafe("OPTARG", nullstr, 0);
9125 *optoff = p ? p - *(optnext - 1) : -1;
9126 *param_optind = optnext - optfirst + 1;
9127 fmtstr(s, sizeof(s), "%d", *param_optind);
9128 err |= setvarsafe("OPTIND", s, VNOFUNC);
9131 err |= setvarsafe(optvar, s, 0);
9142 * The getopts builtin. Shellparam.optnext points to the next argument
9143 * to be processed. Shellparam.optptr points to the next character to
9144 * be processed in the current argument. If shellparam.optnext is NULL,
9145 * then it's the first time getopts has been called.
9149 getoptscmd(int argc, char **argv)
9154 sh_error("Usage: getopts optstring var [arg]");
9155 else if (argc == 3) {
9156 optbase = shellparam.p;
9157 if (shellparam.optind > shellparam.nparam + 1) {
9158 shellparam.optind = 1;
9159 shellparam.optoff = -1;
9164 if (shellparam.optind > argc - 2) {
9165 shellparam.optind = 1;
9166 shellparam.optoff = -1;
9170 return getopts(argv[1], argv[2], optbase, &shellparam.optind,
9171 &shellparam.optoff);
9173 #endif /* CONFIG_ASH_GETOPTS */
9176 * XXX - should get rid of. have all builtins use getopt(3). the
9177 * library getopt must have the BSD extension static variable "optreset"
9178 * otherwise it can't be used within the shell safely.
9180 * Standard option processing (a la getopt) for builtin routines. The
9181 * only argument that is passed to nextopt is the option string; the
9182 * other arguments are unnecessary. It return the character, or '\0' on
9187 nextopt(const char *optstring)
9193 if ((p = optptr) == NULL || *p == '\0') {
9195 if (p == NULL || *p != '-' || *++p == '\0')
9198 if (p[0] == '-' && p[1] == '\0') /* check for "--" */
9202 for (q = optstring ; *q != c ; ) {
9204 sh_error("Illegal option -%c", c);
9209 if (*p == '\0' && (p = *argptr++) == NULL)
9210 sh_error("No arg for -%c option", c);
9222 outstr(const char *p, FILE *file)
9247 outcslow(int c, FILE *dest)
9257 out1fmt(const char *fmt, ...)
9264 r = vprintf(fmt, ap);
9272 fmtstr(char *outbuf, size_t length, const char *fmt, ...)
9279 ret = vsnprintf(outbuf, length, fmt, ap);
9291 * Shell command parser.
9294 #define EOFMARKLEN 79
9298 struct heredoc *next; /* next here document in list */
9299 union node *here; /* redirection node */
9300 char *eofmark; /* string indicating end of input */
9301 int striptabs; /* if set, strip leading tabs */
9306 static struct heredoc *heredoclist; /* list of here documents to read */
9309 static union node *list(int);
9310 static union node *andor(void);
9311 static union node *pipeline(void);
9312 static union node *command(void);
9313 static union node *simplecmd(void);
9314 static union node *makename(void);
9315 static void parsefname(void);
9316 static void parseheredoc(void);
9317 static char peektoken(void);
9318 static int readtoken(void);
9319 static int xxreadtoken(void);
9320 static int readtoken1(int firstc, int syntax, char *eofmark, int striptabs);
9321 static int noexpand(char *);
9322 static void synexpect(int) ATTRIBUTE_NORETURN;
9323 static void synerror(const char *) ATTRIBUTE_NORETURN;
9324 static void setprompt(int);
9330 * Read and parse a command. Returns NEOF on end of file. (NULL is a
9331 * valid parse tree indicating a blank line.)
9335 parsecmd(int interact)
9340 doprompt = interact;
9342 setprompt(doprompt);
9357 union node *n1, *n2, *n3;
9360 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9361 if (nlflag == 2 && peektoken())
9367 if (tok == TBACKGND) {
9368 if (n2->type == NPIPE) {
9369 n2->npipe.backgnd = 1;
9371 if (n2->type != NREDIR) {
9372 n3 = stalloc(sizeof(struct nredir));
9374 n3->nredir.redirect = NULL;
9377 n2->type = NBACKGND;
9384 n3 = (union node *)stalloc(sizeof (struct nbinary));
9386 n3->nbinary.ch1 = n1;
9387 n3->nbinary.ch2 = n2;
9403 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9411 pungetc(); /* push back EOF on input */
9427 union node *n1, *n2, *n3;
9432 if ((t = readtoken()) == TAND) {
9434 } else if (t == TOR) {
9440 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9442 n3 = (union node *)stalloc(sizeof (struct nbinary));
9444 n3->nbinary.ch1 = n1;
9445 n3->nbinary.ch2 = n2;
9455 union node *n1, *n2, *pipenode;
9456 struct nodelist *lp, *prev;
9460 TRACE(("pipeline: entered\n"));
9461 if (readtoken() == TNOT) {
9463 checkkwd = CHKKWD | CHKALIAS;
9467 if (readtoken() == TPIPE) {
9468 pipenode = (union node *)stalloc(sizeof (struct npipe));
9469 pipenode->type = NPIPE;
9470 pipenode->npipe.backgnd = 0;
9471 lp = (struct nodelist *)stalloc(sizeof (struct nodelist));
9472 pipenode->npipe.cmdlist = lp;
9476 lp = (struct nodelist *)stalloc(sizeof (struct nodelist));
9477 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9480 } while (readtoken() == TPIPE);
9486 n2 = (union node *)stalloc(sizeof (struct nnot));
9499 union node *n1, *n2;
9500 union node *ap, **app;
9501 union node *cp, **cpp;
9502 union node *redir, **rpp;
9509 switch (readtoken()) {
9514 n1 = (union node *)stalloc(sizeof (struct nif));
9516 n1->nif.test = list(0);
9517 if (readtoken() != TTHEN)
9519 n1->nif.ifpart = list(0);
9521 while (readtoken() == TELIF) {
9522 n2->nif.elsepart = (union node *)stalloc(sizeof (struct nif));
9523 n2 = n2->nif.elsepart;
9525 n2->nif.test = list(0);
9526 if (readtoken() != TTHEN)
9528 n2->nif.ifpart = list(0);
9530 if (lasttoken == TELSE)
9531 n2->nif.elsepart = list(0);
9533 n2->nif.elsepart = NULL;
9541 n1 = (union node *)stalloc(sizeof (struct nbinary));
9542 n1->type = (lasttoken == TWHILE)? NWHILE : NUNTIL;
9543 n1->nbinary.ch1 = list(0);
9544 if ((got=readtoken()) != TDO) {
9545 TRACE(("expecting DO got %s %s\n", tokname(got), got == TWORD ? wordtext : ""));
9548 n1->nbinary.ch2 = list(0);
9553 if (readtoken() != TWORD || quoteflag || ! goodname(wordtext))
9554 synerror("Bad for loop variable");
9555 n1 = (union node *)stalloc(sizeof (struct nfor));
9557 n1->nfor.var = wordtext;
9558 checkkwd = CHKKWD | CHKALIAS;
9559 if (readtoken() == TIN) {
9561 while (readtoken() == TWORD) {
9562 n2 = (union node *)stalloc(sizeof (struct narg));
9564 n2->narg.text = wordtext;
9565 n2->narg.backquote = backquotelist;
9567 app = &n2->narg.next;
9571 if (lasttoken != TNL && lasttoken != TSEMI)
9574 n2 = (union node *)stalloc(sizeof (struct narg));
9576 n2->narg.text = (char *)dolatstr;
9577 n2->narg.backquote = NULL;
9578 n2->narg.next = NULL;
9581 * Newline or semicolon here is optional (but note
9582 * that the original Bourne shell only allowed NL).
9584 if (lasttoken != TNL && lasttoken != TSEMI)
9587 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9588 if (readtoken() != TDO)
9590 n1->nfor.body = list(0);
9594 n1 = (union node *)stalloc(sizeof (struct ncase));
9596 if (readtoken() != TWORD)
9598 n1->ncase.expr = n2 = (union node *)stalloc(sizeof (struct narg));
9600 n2->narg.text = wordtext;
9601 n2->narg.backquote = backquotelist;
9602 n2->narg.next = NULL;
9604 checkkwd = CHKKWD | CHKALIAS;
9605 } while (readtoken() == TNL);
9606 if (lasttoken != TIN)
9608 cpp = &n1->ncase.cases;
9610 checkkwd = CHKNL | CHKKWD;
9613 if (lasttoken == TLP)
9615 *cpp = cp = (union node *)stalloc(sizeof (struct nclist));
9617 app = &cp->nclist.pattern;
9619 *app = ap = (union node *)stalloc(sizeof (struct narg));
9621 ap->narg.text = wordtext;
9622 ap->narg.backquote = backquotelist;
9623 if (readtoken() != TPIPE)
9625 app = &ap->narg.next;
9628 ap->narg.next = NULL;
9629 if (lasttoken != TRP)
9631 cp->nclist.body = list(2);
9633 cpp = &cp->nclist.next;
9635 checkkwd = CHKNL | CHKKWD;
9636 if ((t = readtoken()) != TESAC) {
9638 synexpect(TENDCASE);
9646 n1 = (union node *)stalloc(sizeof (struct nredir));
9647 n1->type = NSUBSHELL;
9648 n1->nredir.n = list(0);
9649 n1->nredir.redirect = NULL;
9662 if (readtoken() != t)
9666 /* Now check for redirection which may follow command */
9667 checkkwd = CHKKWD | CHKALIAS;
9669 while (readtoken() == TREDIR) {
9670 *rpp = n2 = redirnode;
9671 rpp = &n2->nfile.next;
9677 if (n1->type != NSUBSHELL) {
9678 n2 = (union node *)stalloc(sizeof (struct nredir));
9683 n1->nredir.redirect = redir;
9692 union node *args, **app;
9693 union node *n = NULL;
9694 union node *vars, **vpp;
9695 union node **rpp, *redir;
9705 savecheckkwd = CHKALIAS;
9707 checkkwd = savecheckkwd;
9708 switch (readtoken()) {
9710 n = (union node *)stalloc(sizeof (struct narg));
9712 n->narg.text = wordtext;
9713 n->narg.backquote = backquotelist;
9714 if (savecheckkwd && isassignment(wordtext)) {
9716 vpp = &n->narg.next;
9719 app = &n->narg.next;
9724 *rpp = n = redirnode;
9725 rpp = &n->nfile.next;
9726 parsefname(); /* read name of redirection file */
9730 args && app == &args->narg.next &&
9733 struct builtincmd *bcmd;
9736 /* We have a function */
9737 if (readtoken() != TRP)
9739 name = n->narg.text;
9741 !goodname(name) || (
9742 (bcmd = find_builtin(name)) &&
9743 IS_BUILTIN_SPECIAL(bcmd)
9746 synerror("Bad function name");
9748 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9749 n->narg.next = command();
9762 n = (union node *)stalloc(sizeof (struct ncmd));
9764 n->ncmd.args = args;
9765 n->ncmd.assign = vars;
9766 n->ncmd.redirect = redir;
9775 n = (union node *)stalloc(sizeof (struct narg));
9777 n->narg.next = NULL;
9778 n->narg.text = wordtext;
9779 n->narg.backquote = backquotelist;
9783 void fixredir(union node *n, const char *text, int err)
9785 TRACE(("Fix redir %s %d\n", text, err));
9787 n->ndup.vname = NULL;
9789 if (is_digit(text[0]) && text[1] == '\0')
9790 n->ndup.dupfd = digit_val(text[0]);
9791 else if (text[0] == '-' && text[1] == '\0')
9796 synerror("Bad fd number");
9798 n->ndup.vname = makename();
9806 union node *n = redirnode;
9808 if (readtoken() != TWORD)
9810 if (n->type == NHERE) {
9811 struct heredoc *here = heredoc;
9817 TRACE(("Here document %d\n", n->type));
9818 if (! noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)
9819 synerror("Illegal eof marker for << redirection");
9820 rmescapes(wordtext);
9821 here->eofmark = wordtext;
9823 if (heredoclist == NULL)
9826 for (p = heredoclist ; p->next ; p = p->next);
9829 } else if (n->type == NTOFD || n->type == NFROMFD) {
9830 fixredir(n, wordtext, 0);
9832 n->nfile.fname = makename();
9838 * Input any here documents.
9844 struct heredoc *here;
9854 readtoken1(pgetc(), here->here->type == NHERE? SQSYNTAX : DQSYNTAX,
9855 here->eofmark, here->striptabs);
9856 n = (union node *)stalloc(sizeof (struct narg));
9857 n->narg.type = NARG;
9858 n->narg.next = NULL;
9859 n->narg.text = wordtext;
9860 n->narg.backquote = backquotelist;
9861 here->here->nhere.doc = n;
9866 static char peektoken(void)
9872 return tokname_array[t][0];
9880 int alreadyseen = tokpushback;
9883 #ifdef CONFIG_ASH_ALIAS
9892 if (checkkwd & CHKNL) {
9899 if (t != TWORD || quoteflag) {
9904 * check for keywords
9906 if (checkkwd & CHKKWD) {
9907 const char *const *pp;
9909 if ((pp = findkwd(wordtext))) {
9910 lasttoken = t = pp - tokname_array;
9911 TRACE(("keyword %s recognized\n", tokname(t)));
9916 if (checkkwd & CHKALIAS) {
9917 #ifdef CONFIG_ASH_ALIAS
9919 if ((ap = lookupalias(wordtext, 1)) != NULL) {
9921 pushstring(ap->val, ap);
9931 TRACE(("token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
9933 TRACE(("reread token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
9940 * Read the next input token.
9941 * If the token is a word, we set backquotelist to the list of cmds in
9942 * backquotes. We set quoteflag to true if any part of the word was
9944 * If the token is TREDIR, then we set redirnode to a structure containing
9946 * In all cases, the variable startlinno is set to the number of the line
9947 * on which the token starts.
9949 * [Change comment: here documents and internal procedures]
9950 * [Readtoken shouldn't have any arguments. Perhaps we should make the
9951 * word parsing code into a separate routine. In this case, readtoken
9952 * doesn't need to have any internal procedures, but parseword does.
9953 * We could also make parseoperator in essence the main routine, and
9954 * have parseword (readtoken1?) handle both words and redirection.]
9957 #define NEW_xxreadtoken
9958 #ifdef NEW_xxreadtoken
9960 /* singles must be first! */
9961 static const char xxreadtoken_chars[7] = { '\n', '(', ')', '&', '|', ';', 0 };
9963 static const char xxreadtoken_tokens[] = {
9964 TNL, TLP, TRP, /* only single occurrence allowed */
9965 TBACKGND, TPIPE, TSEMI, /* if single occurrence */
9966 TEOF, /* corresponds to trailing nul */
9967 TAND, TOR, TENDCASE, /* if double occurrence */
9970 #define xxreadtoken_doubles \
9971 (sizeof(xxreadtoken_tokens) - sizeof(xxreadtoken_chars))
9972 #define xxreadtoken_singles \
9973 (sizeof(xxreadtoken_chars) - xxreadtoken_doubles - 1)
9975 static int xxreadtoken()
9986 startlinno = plinno;
9987 for (;;) { /* until token or start of word found */
9990 if ((c != ' ') && (c != '\t')
9991 #ifdef CONFIG_ASH_ALIAS
9996 while ((c = pgetc()) != '\n' && c != PEOF);
9998 } else if (c == '\\') {
9999 if (pgetc() != '\n') {
10003 startlinno = ++plinno;
10008 = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
10013 needprompt = doprompt;
10016 p = strchr(xxreadtoken_chars, c);
10019 return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
10022 if (p - xxreadtoken_chars >= xxreadtoken_singles) {
10023 if (pgetc() == *p) { /* double occurrence? */
10024 p += xxreadtoken_doubles + 1;
10031 return lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
10039 #define RETURN(token) return lasttoken = token
10053 startlinno = plinno;
10054 for (;;) { /* until token or start of word found */
10057 case ' ': case '\t':
10058 #ifdef CONFIG_ASH_ALIAS
10063 while ((c = pgetc()) != '\n' && c != PEOF);
10067 if (pgetc() == '\n') {
10068 startlinno = ++plinno;
10077 needprompt = doprompt;
10082 if (pgetc() == '&')
10087 if (pgetc() == '|')
10092 if (pgetc() == ';')
10105 return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
10108 #endif /* NEW_xxreadtoken */
10112 * If eofmark is NULL, read a word or a redirection symbol. If eofmark
10113 * is not NULL, read a here document. In the latter case, eofmark is the
10114 * word which marks the end of the document and striptabs is true if
10115 * leading tabs should be stripped from the document. The argument firstc
10116 * is the first character of the input token or document.
10118 * Because C does not have internal subroutines, I have simulated them
10119 * using goto's to implement the subroutine linkage. The following macros
10120 * will run code that appears at the end of readtoken1.
10123 #define CHECKEND() {goto checkend; checkend_return:;}
10124 #define PARSEREDIR() {goto parseredir; parseredir_return:;}
10125 #define PARSESUB() {goto parsesub; parsesub_return:;}
10126 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
10127 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
10128 #define PARSEARITH() {goto parsearith; parsearith_return:;}
10131 readtoken1(int firstc, int syntax, char *eofmark, int striptabs)
10136 char line[EOFMARKLEN + 1];
10137 struct nodelist *bqlist = 0;
10140 int varnest = 0; /* levels of variables expansion */
10141 int arinest = 0; /* levels of arithmetic expansion */
10142 int parenlevel = 0; /* levels of parens in arithmetic */
10143 int dqvarnest = 0; /* levels of variables expansion within double quotes */
10145 int prevsyntax = 0; /* syntax before arithmetic */
10147 /* Avoid longjmp clobbering */
10153 (void) &parenlevel;
10156 (void) &prevsyntax;
10160 startlinno = plinno;
10162 if (syntax == DQSYNTAX)
10171 STARTSTACKSTR(out);
10172 loop: { /* for each line, until end of word */
10173 CHECKEND(); /* set c to PEOF if at end of here document */
10174 for (;;) { /* until end of line or end of word */
10175 CHECKSTRSPACE(4, out); /* permit 4 calls to USTPUTC */
10176 switch(SIT(c, syntax)) {
10177 case CNL: /* '\n' */
10178 if (syntax == BASESYNTAX)
10179 goto endword; /* exit outer loop */
10185 goto loop; /* continue outer loop */
10190 if (eofmark == NULL || dblquote)
10191 USTPUTC(CTLESC, out);
10194 case CBACK: /* backslash */
10197 USTPUTC(CTLESC, out);
10198 USTPUTC('\\', out);
10200 } else if (c == '\n') {
10205 c != '\\' && c != '`' &&
10210 USTPUTC(CTLESC, out);
10211 USTPUTC('\\', out);
10213 if (SIT(c, SQSYNTAX) == CCTL)
10214 USTPUTC(CTLESC, out);
10222 if (eofmark == NULL) {
10223 USTPUTC(CTLQUOTEMARK, out);
10231 if (eofmark != NULL && arinest == 0 &&
10235 if (dqvarnest == 0) {
10236 syntax = BASESYNTAX;
10243 case CVAR: /* '$' */
10244 PARSESUB(); /* parse substitution */
10246 case CENDVAR: /* '}' */
10249 if (dqvarnest > 0) {
10252 USTPUTC(CTLENDVAR, out);
10257 #ifdef CONFIG_ASH_MATH_SUPPORT
10258 case CLP: /* '(' in arithmetic */
10262 case CRP: /* ')' in arithmetic */
10263 if (parenlevel > 0) {
10267 if (pgetc() == ')') {
10268 if (--arinest == 0) {
10269 USTPUTC(CTLENDARI, out);
10270 syntax = prevsyntax;
10271 if (syntax == DQSYNTAX)
10279 * unbalanced parens
10280 * (don't 2nd guess - no error)
10288 case CBQUOTE: /* '`' */
10292 goto endword; /* exit outer loop */
10297 goto endword; /* exit outer loop */
10298 #ifdef CONFIG_ASH_ALIAS
10308 #ifdef CONFIG_ASH_MATH_SUPPORT
10309 if (syntax == ARISYNTAX)
10310 synerror("Missing '))'");
10312 if (syntax != BASESYNTAX && ! parsebackquote && eofmark == NULL)
10313 synerror("Unterminated quoted string");
10314 if (varnest != 0) {
10315 startlinno = plinno;
10317 synerror("Missing '}'");
10319 USTPUTC('\0', out);
10320 len = out - (char *)stackblock();
10321 out = stackblock();
10322 if (eofmark == NULL) {
10323 if ((c == '>' || c == '<')
10326 && (*out == '\0' || is_digit(*out))) {
10328 return lasttoken = TREDIR;
10333 quoteflag = quotef;
10334 backquotelist = bqlist;
10335 grabstackblock(len);
10337 return lasttoken = TWORD;
10338 /* end of readtoken routine */
10343 * Check to see whether we are at the end of the here document. When this
10344 * is called, c is set to the first character of the next input line. If
10345 * we are at the end of the here document, this routine sets the c to PEOF.
10350 #ifdef CONFIG_ASH_ALIAS
10356 while (c == '\t') {
10360 if (c == *eofmark) {
10361 if (pfgets(line, sizeof line) != NULL) {
10365 for (q = eofmark + 1 ; *q && *p == *q ; p++, q++);
10366 if (*p == '\n' && *q == '\0') {
10369 needprompt = doprompt;
10371 pushstring(line, NULL);
10376 goto checkend_return;
10381 * Parse a redirection operator. The variable "out" points to a string
10382 * specifying the fd to be redirected. The variable "c" contains the
10383 * first character of the redirection operator.
10390 np = (union node *)stalloc(sizeof (struct nfile));
10395 np->type = NAPPEND;
10397 np->type = NCLOBBER;
10404 } else { /* c == '<' */
10406 switch (c = pgetc()) {
10408 if (sizeof (struct nfile) != sizeof (struct nhere)) {
10409 np = (union node *)stalloc(sizeof (struct nhere));
10413 heredoc = (struct heredoc *)stalloc(sizeof (struct heredoc));
10414 heredoc->here = np;
10415 if ((c = pgetc()) == '-') {
10416 heredoc->striptabs = 1;
10418 heredoc->striptabs = 0;
10424 np->type = NFROMFD;
10428 np->type = NFROMTO;
10438 np->nfile.fd = digit_val(fd);
10440 goto parseredir_return;
10445 * Parse a substitution. At this point, we have read the dollar sign
10446 * and nothing else.
10454 static const char types[] = "}-+?=";
10458 c <= PEOA_OR_PEOF ||
10459 (c != '(' && c != '{' && !is_name(c) && !is_special(c))
10463 } else if (c == '(') { /* $(command) or $((arith)) */
10464 if (pgetc() == '(') {
10465 #ifdef CONFIG_ASH_MATH_SUPPORT
10468 synerror("We unsupport $((arith))");
10475 USTPUTC(CTLVAR, out);
10476 typeloc = out - (char *)stackblock();
10477 USTPUTC(VSNORMAL, out);
10478 subtype = VSNORMAL;
10482 if ((c = pgetc()) == '}')
10485 subtype = VSLENGTH;
10490 if (c > PEOA_OR_PEOF && is_name(c)) {
10494 } while (c > PEOA_OR_PEOF && is_in_name(c));
10495 } else if (is_digit(c)) {
10499 } while (is_digit(c));
10501 else if (is_special(c)) {
10506 badsub: synerror("Bad substitution");
10510 if (subtype == 0) {
10517 p = strchr(types, c);
10520 subtype = p - types + VSNORMAL;
10526 subtype = c == '#' ? VSTRIMLEFT :
10539 if (dblquote || arinest)
10541 *((char *)stackblock() + typeloc) = subtype | flags;
10542 if (subtype != VSNORMAL) {
10544 if (dblquote || arinest) {
10549 goto parsesub_return;
10554 * Called to parse command substitutions. Newstyle is set if the command
10555 * is enclosed inside $(...); nlpp is a pointer to the head of the linked
10556 * list of commands (passed by reference), and savelen is the number of
10557 * characters on the top of the stack which must be preserved.
10561 struct nodelist **nlpp;
10564 char *volatile str;
10565 struct jmploc jmploc;
10566 struct jmploc *volatile savehandler;
10568 int saveprompt = 0;
10570 (void) &saveprompt;
10573 savepbq = parsebackquote;
10574 if (setjmp(jmploc.loc)) {
10577 parsebackquote = 0;
10578 handler = savehandler;
10579 longjmp(handler->loc, 1);
10583 savelen = out - (char *)stackblock();
10585 str = ckmalloc(savelen);
10586 memcpy(str, stackblock(), savelen);
10588 savehandler = handler;
10592 /* We must read until the closing backquote, giving special
10593 treatment to some slashes, and then push the string and
10594 reread it as input, interpreting it normally. */
10601 STARTSTACKSTR(pout);
10606 switch (pc = pgetc()) {
10611 if ((pc = pgetc()) == '\n') {
10616 * If eating a newline, avoid putting
10617 * the newline into the new character
10618 * stream (via the STPUTC after the
10623 if (pc != '\\' && pc != '`' && pc != '$'
10624 && (!dblquote || pc != '"'))
10625 STPUTC('\\', pout);
10626 if (pc > PEOA_OR_PEOF) {
10632 #ifdef CONFIG_ASH_ALIAS
10635 startlinno = plinno;
10636 synerror("EOF in backquote substitution");
10640 needprompt = doprompt;
10649 STPUTC('\0', pout);
10650 psavelen = pout - (char *)stackblock();
10651 if (psavelen > 0) {
10652 pstr = grabstackstr(pout);
10653 setinputstring(pstr);
10658 nlpp = &(*nlpp)->next;
10659 *nlpp = (struct nodelist *)stalloc(sizeof (struct nodelist));
10660 (*nlpp)->next = NULL;
10661 parsebackquote = oldstyle;
10664 saveprompt = doprompt;
10671 doprompt = saveprompt;
10673 if (readtoken() != TRP)
10680 * Start reading from old file again, ignoring any pushed back
10681 * tokens left from the backquote parsing
10686 while (stackblocksize() <= savelen)
10688 STARTSTACKSTR(out);
10690 memcpy(out, str, savelen);
10691 STADJUST(savelen, out);
10697 parsebackquote = savepbq;
10698 handler = savehandler;
10699 if (arinest || dblquote)
10700 USTPUTC(CTLBACKQ | CTLQUOTE, out);
10702 USTPUTC(CTLBACKQ, out);
10704 goto parsebackq_oldreturn;
10706 goto parsebackq_newreturn;
10709 #ifdef CONFIG_ASH_MATH_SUPPORT
10711 * Parse an arithmetic expansion (indicate start of one and set state)
10715 if (++arinest == 1) {
10716 prevsyntax = syntax;
10717 syntax = ARISYNTAX;
10718 USTPUTC(CTLARI, out);
10725 * we collapse embedded arithmetic expansion to
10726 * parenthesis, which should be equivalent
10730 goto parsearith_return;
10734 } /* end of readtoken */
10739 * Returns true if the text contains nothing to expand (no dollar signs
10744 noexpand(char *text)
10750 while ((c = *p++) != '\0') {
10751 if (c == CTLQUOTEMARK)
10755 else if (SIT(c, BASESYNTAX) == CCTL)
10763 * Return of a legal variable name (a letter or underscore followed by zero or
10764 * more letters, underscores, and digits).
10768 endofname(const char *name)
10776 if (! is_in_name(*p))
10784 * Called when an unexpected token is read during the parse. The argument
10785 * is the token that is expected, or -1 if more than one type of token can
10786 * occur at this point.
10789 static void synexpect(int token)
10794 l = sprintf(msg, "%s unexpected", tokname(lasttoken));
10796 sprintf(msg + l, " (expecting %s)", tokname(token));
10802 synerror(const char *msg)
10804 sh_error("Syntax error: %s", msg);
10810 * called by editline -- any expansions to the prompt
10811 * should be added here.
10814 #ifdef CONFIG_ASH_EXPAND_PRMT
10815 static const char *
10816 expandstr(const char *ps)
10820 /* XXX Fix (char *) cast. */
10821 setinputstring((char *)ps);
10822 readtoken1(pgetc(), DQSYNTAX, nullstr, 0);
10825 n.narg.type = NARG;
10826 n.narg.next = NULL;
10827 n.narg.text = wordtext;
10828 n.narg.backquote = backquotelist;
10830 expandarg(&n, NULL, 0);
10831 return stackblock();
10835 static void setprompt(int whichprompt)
10837 const char *prompt;
10838 #ifdef CONFIG_ASH_EXPAND_PRMT
10839 struct stackmark smark;
10844 switch (whichprompt) {
10854 #ifdef CONFIG_ASH_EXPAND_PRMT
10855 setstackmark(&smark);
10856 stalloc(stackblocksize());
10858 putprompt(expandstr(prompt));
10859 #ifdef CONFIG_ASH_EXPAND_PRMT
10860 popstackmark(&smark);
10865 static const char *const *findkwd(const char *s)
10867 return bsearch(s, tokname_array + KWDOFFSET,
10868 (sizeof(tokname_array) / sizeof(const char *)) - KWDOFFSET,
10869 sizeof(const char *), pstrcmp);
10875 * Code for dealing with input/output redirection.
10878 #define EMPTY -2 /* marks an unused slot in redirtab */
10880 # define PIPESIZE 4096 /* amount of buffering in a pipe */
10882 # define PIPESIZE PIPE_BUF
10886 * Open a file in noclobber mode.
10887 * The code was copied from bash.
10890 noclobberopen(const char *fname)
10893 struct stat finfo, finfo2;
10896 * If the file exists and is a regular file, return an error
10899 r = stat(fname, &finfo);
10900 if (r == 0 && S_ISREG(finfo.st_mode)) {
10906 * If the file was not present (r != 0), make sure we open it
10907 * exclusively so that if it is created before we open it, our open
10908 * will fail. Make sure that we do not truncate an existing file.
10909 * Note that we don't turn on O_EXCL unless the stat failed -- if the
10910 * file was not a regular file, we leave O_EXCL off.
10913 return open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
10914 fd = open(fname, O_WRONLY|O_CREAT, 0666);
10916 /* If the open failed, return the file descriptor right away. */
10921 * OK, the open succeeded, but the file may have been changed from a
10922 * non-regular file to a regular file between the stat and the open.
10923 * We are assuming that the O_EXCL open handles the case where FILENAME
10924 * did not exist and is symlinked to an existing file between the stat
10929 * If we can open it and fstat the file descriptor, and neither check
10930 * revealed that it was a regular file, and the file has not been
10931 * replaced, return the file descriptor.
10933 if (fstat(fd, &finfo2) == 0 && !S_ISREG(finfo2.st_mode) &&
10934 finfo.st_dev == finfo2.st_dev && finfo.st_ino == finfo2.st_ino)
10937 /* The file has been replaced. badness. */
10944 * Handle here documents. Normally we fork off a process to write the
10945 * data to a pipe. If the document is short, we can stuff the data in
10946 * the pipe without forking.
10950 openhere(union node *redir)
10956 sh_error("Pipe call failed");
10957 if (redir->type == NHERE) {
10958 len = strlen(redir->nhere.doc->narg.text);
10959 if (len <= PIPESIZE) {
10960 bb_full_write(pip[1], redir->nhere.doc->narg.text, len);
10964 if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
10966 signal(SIGINT, SIG_IGN);
10967 signal(SIGQUIT, SIG_IGN);
10968 signal(SIGHUP, SIG_IGN);
10970 signal(SIGTSTP, SIG_IGN);
10972 signal(SIGPIPE, SIG_DFL);
10973 if (redir->type == NHERE)
10974 bb_full_write(pip[1], redir->nhere.doc->narg.text, len);
10976 expandhere(redir->nhere.doc, pip[1]);
10985 openredirect(union node *redir)
10990 switch (redir->nfile.type) {
10992 fname = redir->nfile.expfname;
10993 if ((f = open(fname, O_RDONLY)) < 0)
10997 fname = redir->nfile.expfname;
10998 if ((f = open(fname, O_RDWR|O_CREAT|O_TRUNC, 0666)) < 0)
11002 /* Take care of noclobber mode. */
11004 fname = redir->nfile.expfname;
11005 if ((f = noclobberopen(fname)) < 0)
11011 fname = redir->nfile.expfname;
11012 if ((f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0)
11016 fname = redir->nfile.expfname;
11017 if ((f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666)) < 0)
11024 /* Fall through to eliminate warning. */
11031 f = openhere(redir);
11037 sh_error("cannot create %s: %s", fname, errmsg(errno, E_CREAT));
11039 sh_error("cannot open %s: %s", fname, errmsg(errno, E_OPEN));
11043 dupredirect(union node *redir, int f)
11045 int fd = redir->nfile.fd;
11047 if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
11048 if (redir->ndup.dupfd >= 0) { /* if not ">&-" */
11049 copyfd(redir->ndup.dupfd, fd);
11062 * Process a list of redirection commands. If the REDIR_PUSH flag is set,
11063 * old file descriptors are stashed away so that the redirection can be
11064 * undone by calling popredir. If the REDIR_BACKQ flag is set, then the
11065 * standard output, and the standard error if it becomes a duplicate of
11066 * stdout, is saved in memory.
11070 redirect(union node *redir, int flags)
11073 struct redirtab *sv;
11084 if (flags & REDIR_PUSH) {
11085 struct redirtab *q;
11086 q = ckmalloc(sizeof (struct redirtab));
11087 q->next = redirlist;
11089 q->nullredirs = nullredirs - 1;
11090 for (i = 0 ; i < 10 ; i++)
11091 q->renamed[i] = EMPTY;
11098 if ((n->nfile.type == NTOFD || n->nfile.type == NFROMFD) &&
11099 n->ndup.dupfd == fd)
11100 continue; /* redirect from/to same file descriptor */
11102 newfd = openredirect(n);
11105 if (sv && *(p = &sv->renamed[fd]) == EMPTY) {
11106 i = fcntl(fd, F_DUPFD, 10);
11113 sh_error("%d: %m", fd);
11123 dupredirect(n, newfd);
11124 } while ((n = n->nfile.next));
11126 if (flags & REDIR_SAVEFD2 && sv && sv->renamed[2] >= 0)
11127 preverrout_fd = sv->renamed[2];
11132 * Undo the effects of the last redirection.
11138 struct redirtab *rp;
11141 if (--nullredirs >= 0)
11145 for (i = 0 ; i < 10 ; i++) {
11146 if (rp->renamed[i] != EMPTY) {
11149 copyfd(rp->renamed[i], i);
11151 close(rp->renamed[i]);
11154 redirlist = rp->next;
11155 nullredirs = rp->nullredirs;
11161 * Undo all redirections. Called on error or interrupt.
11165 * Discard all saved file descriptors.
11169 clearredir(int drop)
11181 * Copy a file descriptor to be >= to. Returns -1
11182 * if the source file descriptor is closed, EMPTY if there are no unused
11183 * file descriptors left.
11187 copyfd(int from, int to)
11191 newfd = fcntl(from, F_DUPFD, to);
11193 if (errno == EMFILE)
11196 sh_error("%d: %m", from);
11203 redirectsafe(union node *redir, int flags)
11206 volatile int saveint;
11207 struct jmploc *volatile savehandler = handler;
11208 struct jmploc jmploc;
11211 if (!(err = setjmp(jmploc.loc) * 2)) {
11213 redirect(redir, flags);
11215 handler = savehandler;
11216 if (err && exception != EXERROR)
11217 longjmp(handler->loc, 1);
11218 RESTOREINT(saveint);
11225 static void shtree(union node *, int, char *, FILE*);
11226 static void shcmd(union node *, FILE *);
11227 static void sharg(union node *, FILE *);
11228 static void indent(int, char *, FILE *);
11229 static void trstring(char *);
11233 showtree(union node *n)
11235 trputs("showtree called\n");
11236 shtree(n, 1, NULL, stdout);
11241 shtree(union node *n, int ind, char *pfx, FILE *fp)
11243 struct nodelist *lp;
11249 indent(ind, pfx, fp);
11260 shtree(n->nbinary.ch1, ind, NULL, fp);
11263 shtree(n->nbinary.ch2, ind, NULL, fp);
11271 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
11276 if (n->npipe.backgnd)
11282 fprintf(fp, "<node type %d>", n->type);
11291 shcmd(union node *cmd, FILE *fp)
11299 for (np = cmd->ncmd.args ; np ; np = np->narg.next) {
11305 for (np = cmd->ncmd.redirect ; np ; np = np->nfile.next) {
11308 switch (np->nfile.type) {
11309 case NTO: s = ">"; dftfd = 1; break;
11310 case NCLOBBER: s = ">|"; dftfd = 1; break;
11311 case NAPPEND: s = ">>"; dftfd = 1; break;
11312 case NTOFD: s = ">&"; dftfd = 1; break;
11313 case NFROM: s = "<"; dftfd = 0; break;
11314 case NFROMFD: s = "<&"; dftfd = 0; break;
11315 case NFROMTO: s = "<>"; dftfd = 0; break;
11316 default: s = "*error*"; dftfd = 0; break;
11318 if (np->nfile.fd != dftfd)
11319 fprintf(fp, "%d", np->nfile.fd);
11321 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
11322 fprintf(fp, "%d", np->ndup.dupfd);
11324 sharg(np->nfile.fname, fp);
11333 sharg(union node *arg, FILE *fp)
11336 struct nodelist *bqlist;
11339 if (arg->type != NARG) {
11340 out1fmt("<node type %d>\n", arg->type);
11343 bqlist = arg->narg.backquote;
11344 for (p = arg->narg.text ; *p ; p++) {
11353 if (subtype == VSLENGTH)
11359 if (subtype & VSNUL)
11362 switch (subtype & VSTYPE) {
11381 case VSTRIMLEFTMAX:
11388 case VSTRIMRIGHTMAX:
11395 out1fmt("<subtype %d>", subtype);
11402 case CTLBACKQ|CTLQUOTE:
11405 shtree(bqlist->n, -1, NULL, fp);
11417 indent(int amount, char *pfx, FILE *fp)
11421 for (i = 0 ; i < amount ; i++) {
11422 if (pfx && i == amount - 1)
11443 putc(c, tracefile);
11447 trace(const char *fmt, ...)
11454 (void) vfprintf(tracefile, fmt, va);
11459 tracev(const char *fmt, va_list va)
11463 (void) vfprintf(tracefile, fmt, va);
11468 trputs(const char *s)
11472 fputs(s, tracefile);
11484 putc('"', tracefile);
11485 for (p = s ; *p ; p++) {
11487 case '\n': c = 'n'; goto backslash;
11488 case '\t': c = 't'; goto backslash;
11489 case '\r': c = 'r'; goto backslash;
11490 case '"': c = '"'; goto backslash;
11491 case '\\': c = '\\'; goto backslash;
11492 case CTLESC: c = 'e'; goto backslash;
11493 case CTLVAR: c = 'v'; goto backslash;
11494 case CTLVAR+CTLQUOTE: c = 'V'; goto backslash;
11495 case CTLBACKQ: c = 'q'; goto backslash;
11496 case CTLBACKQ+CTLQUOTE: c = 'Q'; goto backslash;
11497 backslash: putc('\\', tracefile);
11498 putc(c, tracefile);
11501 if (*p >= ' ' && *p <= '~')
11502 putc(*p, tracefile);
11504 putc('\\', tracefile);
11505 putc(*p >> 6 & 03, tracefile);
11506 putc(*p >> 3 & 07, tracefile);
11507 putc(*p & 07, tracefile);
11512 putc('"', tracefile);
11524 putc(' ', tracefile);
11526 putc('\n', tracefile);
11542 /* leave open because libedit might be using it */
11545 scopy("./trace", s);
11547 if (!freopen(s, "a", tracefile)) {
11548 fprintf(stderr, "Can't re-open %s\n", s);
11553 if ((tracefile = fopen(s, "a")) == NULL) {
11554 fprintf(stderr, "Can't open %s\n", s);
11560 if ((flags = fcntl(fileno(tracefile), F_GETFL, 0)) >= 0)
11561 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
11563 setlinebuf(tracefile);
11564 fputs("\nTracing started.\n", tracefile);
11572 * Sigmode records the current value of the signal handlers for the various
11573 * modes. A value of zero means that the current handler is not known.
11574 * S_HARD_IGN indicates that the signal was ignored on entry to the shell,
11577 #define S_DFL 1 /* default signal handling (SIG_DFL) */
11578 #define S_CATCH 2 /* signal is caught */
11579 #define S_IGN 3 /* signal is ignored (SIG_IGN) */
11580 #define S_HARD_IGN 4 /* signal is ignored permenantly */
11581 #define S_RESET 5 /* temporary - to reset a hard ignored sig */
11586 * The trap builtin.
11590 trapcmd(int argc, char **argv)
11599 for (signo = 0 ; signo < NSIG ; signo++) {
11600 if (trap[signo] != NULL) {
11603 sn = u_signal_names(0, &signo, 0);
11606 out1fmt("trap -- %s %s\n",
11607 single_quote(trap[signo]), sn);
11617 if ((signo = decode_signal(*ap, 0)) < 0)
11618 sh_error("%s: bad trap", *ap);
11621 if (action[0] == '-' && action[1] == '\0')
11624 action = savestr(action);
11627 ckfree(trap[signo]);
11628 trap[signo] = action;
11639 * Clear traps on a fork.
11647 for (tp = trap ; tp < &trap[NSIG] ; tp++) {
11648 if (*tp && **tp) { /* trap not NULL or SIG_IGN */
11652 if (tp != &trap[0])
11653 setsignal(tp - trap);
11661 * Set the signal handler for the specified signal. The routine figures
11662 * out what it should be set to.
11666 setsignal(int signo)
11670 struct sigaction act;
11672 if ((t = trap[signo]) == NULL)
11674 else if (*t != '\0')
11678 if (rootshell && action == S_DFL) {
11681 if (iflag || minusc || sflag == 0)
11704 t = &sigmode[signo - 1];
11708 * current setting unknown
11710 if (sigaction(signo, 0, &act) == -1) {
11712 * Pretend it worked; maybe we should give a warning
11713 * here, but other shells don't. We don't alter
11714 * sigmode, so that we retry every time.
11718 if (act.sa_handler == SIG_IGN) {
11719 if (mflag && (signo == SIGTSTP ||
11720 signo == SIGTTIN || signo == SIGTTOU)) {
11721 tsig = S_IGN; /* don't hard ignore these */
11725 tsig = S_RESET; /* force to be set */
11728 if (tsig == S_HARD_IGN || tsig == action)
11732 act.sa_handler = onsig;
11735 act.sa_handler = SIG_IGN;
11738 act.sa_handler = SIG_DFL;
11742 sigfillset(&act.sa_mask);
11743 sigaction(signo, &act, 0);
11751 ignoresig(int signo)
11753 if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
11754 signal(signo, SIG_IGN);
11756 sigmode[signo - 1] = S_HARD_IGN;
11767 gotsig[signo - 1] = 1;
11768 pendingsigs = signo;
11770 if (exsig || (signo == SIGINT && !trap[SIGINT])) {
11779 * Called to execute a trap. Perhaps we should avoid entering new trap
11780 * handlers while we are executing a trap handler.
11792 savestatus = exitstatus;
11796 for (i = 0, q = gotsig; i < NSIG - 1; i++, q++) {
11804 skip = evalstring(p, SKIPEVAL);
11805 exitstatus = savestatus;
11815 * Controls whether the shell is interactive or not.
11819 setinteractive(int on)
11821 static int is_interactive;
11823 if (++on == is_interactive)
11825 is_interactive = on;
11827 setsignal(SIGQUIT);
11828 setsignal(SIGTERM);
11829 #ifndef CONFIG_FEATURE_SH_EXTRA_QUIET
11830 if(is_interactive > 1) {
11831 /* Looks like they want an interactive shell */
11832 static int do_banner;
11836 "\n\n%s Built-in shell (ash)\n"
11837 "Enter 'help' for a list of built-in commands.\n\n",
11846 #ifndef CONFIG_FEATURE_SH_EXTRA_QUIET
11847 /*** List the available builtins ***/
11849 static int helpcmd(int argc, char **argv)
11853 out1fmt("\nBuilt-in commands:\n-------------------\n");
11854 for (col = 0, i = 0; i < NUMBUILTINS; i++) {
11855 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
11856 builtincmd[i].name + 1);
11862 #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
11864 extern const struct BB_applet applets[];
11865 extern const size_t NUM_APPLETS;
11867 for (i = 0; i < NUM_APPLETS; i++) {
11869 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), applets[i].name);
11878 return EXIT_SUCCESS;
11880 #endif /* CONFIG_FEATURE_SH_EXTRA_QUIET */
11883 * Called to exit the shell.
11893 status = exitstatus;
11894 TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
11895 if (setjmp(loc.loc)) {
11896 if (exception == EXEXIT)
11901 if ((p = trap[0])) {
11907 #ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
11908 if (iflag && rootshell) {
11909 const char *hp = lookupvar("HISTFILE");
11912 save_history ( hp );
11920 static int decode_signal(const char *string, int minsig)
11923 const char *name = u_signal_names(string, &signo, minsig);
11925 return name ? signo : -1;
11930 static struct var *vartab[VTABSIZE];
11932 static int vpcmp(const void *, const void *);
11933 static struct var **findvar(struct var **, const char *);
11936 * Initialize the variable symbol tables and import the environment
11940 #ifdef CONFIG_ASH_GETOPTS
11942 * Safe version of setvar, returns 1 on success 0 on failure.
11946 setvarsafe(const char *name, const char *val, int flags)
11949 volatile int saveint;
11950 struct jmploc *volatile savehandler = handler;
11951 struct jmploc jmploc;
11954 if (setjmp(jmploc.loc))
11958 setvar(name, val, flags);
11961 handler = savehandler;
11962 RESTOREINT(saveint);
11968 * Set the value of a variable. The flags argument is ored with the
11969 * flags of the variable. If val is NULL, the variable is unset.
11973 setvar(const char *name, const char *val, int flags)
11980 q = endofname(name);
11981 p = strchrnul(q, '=');
11982 namelen = p - name;
11983 if (!namelen || p != q)
11984 sh_error("%.*s: bad variable name", namelen, name);
11989 vallen = strlen(val);
11992 p = mempcpy(nameeq = ckmalloc(namelen + vallen + 2), name, namelen);
11995 p = mempcpy(p, val, vallen);
11998 setvareq(nameeq, flags | VNOSAVE);
12004 * Same as setvar except that the variable and value are passed in
12005 * the first argument as name=value. Since the first argument will
12006 * be actually stored in the table, it should not be a string that
12008 * Called with interrupts off.
12012 setvareq(char *s, int flags)
12014 struct var *vp, **vpp;
12017 flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
12018 vp = *findvar(vpp, s);
12020 if ((vp->flags & (VREADONLY|VDYNAMIC)) == VREADONLY) {
12023 if (flags & VNOSAVE)
12026 sh_error("%.*s: is read only", strchrnul(n, '=') - n, n);
12029 if (flags & VNOSET)
12032 if (vp->func && (flags & VNOFUNC) == 0)
12033 (*vp->func)(strchrnul(s, '=') + 1);
12035 if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
12038 flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET);
12040 if (flags & VNOSET)
12043 vp = ckmalloc(sizeof (*vp));
12048 if (!(flags & (VTEXTFIXED|VSTACK|VNOSAVE)))
12056 * Process a linked list of variable assignments.
12060 listsetvar(struct strlist *list_set_var, int flags)
12062 struct strlist *lp = list_set_var;
12068 setvareq(lp->text, flags);
12069 } while ((lp = lp->next));
12075 * Find the value of a variable. Returns NULL if not set.
12079 lookupvar(const char *name)
12083 if ((v = *findvar(hashvar(name), name))) {
12086 * Dynamic variables are implemented roughly the same way they are
12087 * in bash. Namely, they're "special" so long as they aren't unset.
12088 * As soon as they're unset, they're no longer dynamic, and dynamic
12089 * lookup will no longer happen at that point. -- PFM.
12091 if((v->flags & VDYNAMIC))
12094 if(!(v->flags & VUNSET))
12095 return strchrnul(v->text, '=') + 1;
12103 * Search the environment of a builtin command.
12107 bltinlookup(const char *name)
12109 struct strlist *sp;
12111 for (sp = cmdenviron ; sp ; sp = sp->next) {
12112 if (varequal(sp->text, name))
12113 return strchrnul(sp->text, '=') + 1;
12115 return lookupvar(name);
12120 * Generate a list of variables satisfying the given conditions.
12124 listvars(int on, int off, char ***end)
12135 for (vp = *vpp ; vp ; vp = vp->next)
12136 if ((vp->flags & mask) == on) {
12137 if (ep == stackstrend())
12138 ep = growstackstr();
12139 *ep++ = (char *) vp->text;
12141 } while (++vpp < vartab + VTABSIZE);
12142 if (ep == stackstrend())
12143 ep = growstackstr();
12147 return grabstackstr(ep);
12152 * POSIX requires that 'set' (but not export or readonly) output the
12153 * variables in lexicographic order - by the locale's collating order (sigh).
12154 * Maybe we could keep them in an ordered balanced binary tree
12155 * instead of hashed lists.
12156 * For now just roll 'em through qsort for printing...
12160 showvars(const char *sep_prefix, int on, int off)
12163 char **ep, **epend;
12165 ep = listvars(on, off, &epend);
12166 qsort(ep, epend - ep, sizeof(char *), vpcmp);
12168 sep = *sep_prefix ? spcstr : sep_prefix;
12170 for (; ep < epend; ep++) {
12174 p = strchrnul(*ep, '=');
12177 q = single_quote(++p);
12179 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
12188 * The export and readonly commands.
12192 exportcmd(int argc, char **argv)
12198 int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT;
12201 notp = nextopt("p") - 'p';
12202 if (notp && ((name = *(aptr = argptr)))) {
12204 if ((p = strchr(name, '=')) != NULL) {
12207 if ((vp = *findvar(hashvar(name), name))) {
12212 setvar(name, p, flag);
12213 } while ((name = *++aptr) != NULL);
12215 showvars(argv[0], flag, 0);
12222 * Make a variable a local variable. When a variable is made local, it's
12223 * value and flags are saved in a localvar structure. The saved values
12224 * will be restored when the shell function returns. We handle the name
12225 * "-" as a special case.
12229 mklocal(char *name)
12231 struct localvar *lvp;
12236 lvp = ckmalloc(sizeof (struct localvar));
12237 if (name[0] == '-' && name[1] == '\0') {
12239 p = ckmalloc(sizeof(optlist));
12240 lvp->text = memcpy(p, optlist, sizeof(optlist));
12245 vpp = hashvar(name);
12246 vp = *findvar(vpp, name);
12247 eq = strchr(name, '=');
12250 setvareq(name, VSTRFIXED);
12252 setvar(name, NULL, VSTRFIXED);
12253 vp = *vpp; /* the new variable */
12254 lvp->flags = VUNSET;
12256 lvp->text = vp->text;
12257 lvp->flags = vp->flags;
12258 vp->flags |= VSTRFIXED|VTEXTFIXED;
12264 lvp->next = localvars;
12270 * The "local" command.
12274 localcmd(int argc, char **argv)
12279 while ((name = *argv++) != NULL) {
12287 * Called after a function returns.
12288 * Interrupts must be off.
12294 struct localvar *lvp;
12297 while ((lvp = localvars) != NULL) {
12298 localvars = lvp->next;
12300 TRACE(("poplocalvar %s", vp ? vp->text : "-"));
12301 if (vp == NULL) { /* $- saved */
12302 memcpy(optlist, lvp->text, sizeof(optlist));
12305 } else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
12306 unsetvar(vp->text);
12309 (*vp->func)(strchrnul(lvp->text, '=') + 1);
12310 if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
12312 vp->flags = lvp->flags;
12313 vp->text = lvp->text;
12321 * The unset builtin command. We unset the function before we unset the
12322 * variable to allow a function to be unset when there is a readonly variable
12323 * with the same name.
12327 unsetcmd(int argc, char **argv)
12334 while ((i = nextopt("vf")) != '\0') {
12338 for (ap = argptr; *ap ; ap++) {
12353 * Unset the specified variable.
12357 unsetvar(const char *s)
12363 vpp = findvar(hashvar(s), s);
12367 int flags = vp->flags;
12370 if (flags & VREADONLY)
12373 vp->flags &= ~VDYNAMIC;
12375 if (flags & VUNSET)
12377 if ((flags & VSTRFIXED) == 0) {
12379 if ((flags & (VTEXTFIXED|VSTACK)) == 0)
12386 vp->flags &= ~VEXPORT;
12399 * Find the appropriate entry in the hash table from the name.
12402 static struct var **
12403 hashvar(const char *p)
12405 unsigned int hashval;
12407 hashval = ((unsigned char) *p) << 4;
12408 while (*p && *p != '=')
12409 hashval += (unsigned char) *p++;
12410 return &vartab[hashval % VTABSIZE];
12416 * Compares two strings up to the first = or '\0'. The first
12417 * string must be terminated by '='; the second may be terminated by
12418 * either '=' or '\0'.
12422 varcmp(const char *p, const char *q)
12426 while ((c = *p) == (d = *q)) {
12427 if (!c || c == '=')
12441 vpcmp(const void *a, const void *b)
12443 return varcmp(*(const char **)a, *(const char **)b);
12446 static struct var **
12447 findvar(struct var **vpp, const char *name)
12449 for (; *vpp; vpp = &(*vpp)->next) {
12450 if (varequal((*vpp)->text, name)) {
12458 #include <sys/times.h>
12460 static const unsigned char timescmd_str[] = {
12461 ' ', offsetof(struct tms, tms_utime),
12462 '\n', offsetof(struct tms, tms_stime),
12463 ' ', offsetof(struct tms, tms_cutime),
12464 '\n', offsetof(struct tms, tms_cstime),
12468 static int timescmd(int ac, char **av)
12470 long int clk_tck, s, t;
12471 const unsigned char *p;
12474 clk_tck = sysconf(_SC_CLK_TCK);
12479 t = *(clock_t *)(((char *) &buf) + p[1]);
12481 out1fmt("%ldm%ld.%.3lds%c",
12483 ((t - s * clk_tck) * 1000) / clk_tck,
12485 } while (*(p += 2));
12490 #ifdef CONFIG_ASH_MATH_SUPPORT
12492 dash_arith(const char *s)
12498 result = arith(s, &errcode);
12501 sh_error("exponent less than 0");
12502 else if (errcode == -2)
12503 sh_error("divide by zero");
12504 else if (errcode == -5)
12505 sh_error("expression recursion loop detected");
12516 * The let builtin. partial stolen from GNU Bash, the Bourne Again SHell.
12517 * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
12519 * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
12523 letcmd(int argc, char **argv)
12530 sh_error("expression expected");
12531 for (ap = argv + 1; *ap; ap++) {
12532 i = dash_arith(*ap);
12537 #endif /* CONFIG_ASH_MATH_SUPPORT */
12542 * Miscellaneous builtins.
12548 #if __GLIBC__ == 2 && __GLIBC_MINOR__ < 1
12549 typedef enum __rlimit_resource rlim_t;
12555 * The read builtin. The -e option causes backslashes to escape the
12556 * following character.
12558 * This uses unbuffered input, which may be avoidable in some cases.
12562 readcmd(int argc, char **argv)
12574 #if defined(CONFIG_ASH_READ_NCHARS)
12578 struct termios tty, old_tty;
12580 #if defined(CONFIG_ASH_READ_TIMEOUT)
12584 ts.tv_sec = ts.tv_usec = 0;
12589 #if defined(CONFIG_ASH_READ_NCHARS) && defined(CONFIG_ASH_READ_TIMEOUT)
12590 while ((i = nextopt("p:rt:n:s")) != '\0')
12591 #elif defined(CONFIG_ASH_READ_NCHARS)
12592 while ((i = nextopt("p:rn:s")) != '\0')
12593 #elif defined(CONFIG_ASH_READ_TIMEOUT)
12594 while ((i = nextopt("p:rt:")) != '\0')
12596 while ((i = nextopt("p:r")) != '\0')
12601 prompt = optionarg;
12603 #if defined(CONFIG_ASH_READ_NCHARS)
12605 nchars = strtol(optionarg, &p, 10);
12607 sh_error("invalid count");
12608 nch_flag = (nchars > 0);
12614 #if defined(CONFIG_ASH_READ_TIMEOUT)
12616 ts.tv_sec = strtol(optionarg, &p, 10);
12622 ts.tv_usec = strtol(p, &p2, 10);
12624 sh_error("invalid timeout");
12626 /* normalize to usec */
12628 sh_error("invalid timeout");
12629 while (scale++ < 6)
12633 sh_error("invalid timeout");
12635 if ( ! ts.tv_sec && ! ts.tv_usec)
12636 sh_error("invalid timeout");
12646 if (prompt && isatty(0)) {
12649 if (*(ap = argptr) == NULL)
12650 sh_error("arg count");
12651 if ((ifs = bltinlookup("IFS")) == NULL)
12653 #if defined(CONFIG_ASH_READ_NCHARS)
12654 if (nch_flag || silent) {
12655 tcgetattr(0, &tty);
12658 tty.c_lflag &= ~ICANON;
12659 tty.c_cc[VMIN] = nchars;
12662 tty.c_lflag &= ~(ECHO|ECHOK|ECHONL);
12665 tcsetattr(0, TCSANOW, &tty);
12668 #if defined(CONFIG_ASH_READ_TIMEOUT)
12669 if (ts.tv_sec || ts.tv_usec) {
12673 i = select (FD_SETSIZE, &set, NULL, NULL, &ts);
12675 #if defined(CONFIG_ASH_READ_NCHARS)
12677 tcsetattr(0, TCSANOW, &old_tty);
12687 #if defined(CONFIG_ASH_READ_NCHARS)
12688 while (!nch_flag || nchars--)
12693 if (read(0, &c, 1) != 1) {
12705 if (!rflag && c == '\\') {
12711 if (startword && *ifs == ' ' && strchr(ifs, c)) {
12715 if (ap[1] != NULL && strchr(ifs, c) != NULL) {
12717 setvar(*ap, stackblock(), 0);
12726 #if defined(CONFIG_ASH_READ_NCHARS)
12727 if (nch_flag || silent)
12728 tcsetattr(0, TCSANOW, &old_tty);
12732 /* Remove trailing blanks */
12733 while ((char *)stackblock() <= --p && strchr(ifs, *p) != NULL)
12735 setvar(*ap, stackblock(), 0);
12736 while (*++ap != NULL)
12737 setvar(*ap, nullstr, 0);
12742 static int umaskcmd(int argc, char **argv)
12744 static const char permuser[3] = "ugo";
12745 static const char permmode[3] = "rwx";
12746 static const short int permmask[] = {
12747 S_IRUSR, S_IWUSR, S_IXUSR,
12748 S_IRGRP, S_IWGRP, S_IXGRP,
12749 S_IROTH, S_IWOTH, S_IXOTH
12755 int symbolic_mode = 0;
12757 while (nextopt("S") != '\0') {
12766 if ((ap = *argptr) == NULL) {
12767 if (symbolic_mode) {
12771 for (i = 0; i < 3; i++) {
12774 *p++ = permuser[i];
12776 for (j = 0; j < 3; j++) {
12777 if ((mask & permmask[3 * i + j]) == 0) {
12778 *p++ = permmode[j];
12786 out1fmt("%.4o\n", mask);
12789 if (is_digit((unsigned char) *ap)) {
12792 if (*ap >= '8' || *ap < '0')
12793 sh_error(illnum, argv[1]);
12794 mask = (mask << 3) + (*ap - '0');
12795 } while (*++ap != '\0');
12798 mask = ~mask & 0777;
12799 if (!bb_parse_mode(ap, &mask)) {
12800 sh_error("Illegal mode: %s", ap);
12802 umask(~mask & 0777);
12811 * This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and
12812 * Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with
12813 * ash by J.T. Conklin.
12821 int factor; /* multiply by to get rlim_{cur,max} values */
12825 static const struct limits limits[] = {
12827 { "time(seconds)", RLIMIT_CPU, 1, 't' },
12829 #ifdef RLIMIT_FSIZE
12830 { "file(blocks)", RLIMIT_FSIZE, 512, 'f' },
12833 { "data(kbytes)", RLIMIT_DATA, 1024, 'd' },
12835 #ifdef RLIMIT_STACK
12836 { "stack(kbytes)", RLIMIT_STACK, 1024, 's' },
12839 { "coredump(blocks)", RLIMIT_CORE, 512, 'c' },
12842 { "memory(kbytes)", RLIMIT_RSS, 1024, 'm' },
12844 #ifdef RLIMIT_MEMLOCK
12845 { "locked memory(kbytes)", RLIMIT_MEMLOCK, 1024, 'l' },
12847 #ifdef RLIMIT_NPROC
12848 { "process", RLIMIT_NPROC, 1, 'p' },
12850 #ifdef RLIMIT_NOFILE
12851 { "nofiles", RLIMIT_NOFILE, 1, 'n' },
12854 { "vmemory(kbytes)", RLIMIT_AS, 1024, 'v' },
12856 #ifdef RLIMIT_LOCKS
12857 { "locks", RLIMIT_LOCKS, 1, 'w' },
12859 { (char *) 0, 0, 0, '\0' }
12862 enum limtype { SOFT = 0x1, HARD = 0x2 };
12864 static void printlim(enum limtype how, const struct rlimit *limit,
12865 const struct limits *l)
12869 val = limit->rlim_max;
12871 val = limit->rlim_cur;
12873 if (val == RLIM_INFINITY)
12874 out1fmt("unlimited\n");
12877 out1fmt("%lld\n", (long long) val);
12882 ulimitcmd(int argc, char **argv)
12886 enum limtype how = SOFT | HARD;
12887 const struct limits *l;
12890 struct rlimit limit;
12893 while ((optc = nextopt("HSa"
12897 #ifdef RLIMIT_FSIZE
12903 #ifdef RLIMIT_STACK
12912 #ifdef RLIMIT_MEMLOCK
12915 #ifdef RLIMIT_NPROC
12918 #ifdef RLIMIT_NOFILE
12924 #ifdef RLIMIT_LOCKS
12942 for (l = limits; l->option != what; l++)
12945 set = *argptr ? 1 : 0;
12949 if (all || argptr[1])
12950 sh_error("too many arguments");
12951 if (strncmp(p, "unlimited\n", 9) == 0)
12952 val = RLIM_INFINITY;
12956 while ((c = *p++) >= '0' && c <= '9')
12958 val = (val * 10) + (long)(c - '0');
12959 if (val < (rlim_t) 0)
12963 sh_error("bad number");
12968 for (l = limits; l->name; l++) {
12969 getrlimit(l->cmd, &limit);
12970 out1fmt("%-20s ", l->name);
12971 printlim(how, &limit, l);
12976 getrlimit(l->cmd, &limit);
12979 limit.rlim_max = val;
12981 limit.rlim_cur = val;
12982 if (setrlimit(l->cmd, &limit) < 0)
12983 sh_error("error setting limit (%m)");
12985 printlim(how, &limit, l);
12991 #ifdef CONFIG_ASH_MATH_SUPPORT
12993 /* Copyright (c) 2001 Aaron Lehmann <aaronl@vitelus.com>
12995 Permission is hereby granted, free of charge, to any person obtaining
12996 a copy of this software and associated documentation files (the
12997 "Software"), to deal in the Software without restriction, including
12998 without limitation the rights to use, copy, modify, merge, publish,
12999 distribute, sublicense, and/or sell copies of the Software, and to
13000 permit persons to whom the Software is furnished to do so, subject to
13001 the following conditions:
13003 The above copyright notice and this permission notice shall be
13004 included in all copies or substantial portions of the Software.
13006 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13007 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
13008 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
13009 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
13010 CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
13011 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
13012 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
13015 /* This is my infix parser/evaluator. It is optimized for size, intended
13016 * as a replacement for yacc-based parsers. However, it may well be faster
13017 * than a comparable parser written in yacc. The supported operators are
13018 * listed in #defines below. Parens, order of operations, and error handling
13019 * are supported. This code is thread safe. The exact expression format should
13020 * be that which POSIX specifies for shells. */
13022 /* The code uses a simple two-stack algorithm. See
13023 * http://www.onthenet.com.au/~grahamis/int2008/week02/lect02.html
13024 * for a detailed explanation of the infix-to-postfix algorithm on which
13025 * this is based (this code differs in that it applies operators immediately
13026 * to the stack instead of adding them to a queue to end up with an
13029 /* To use the routine, call it with an expression string and error return
13033 * Aug 24, 2001 Manuel Novoa III
13035 * Reduced the generated code size by about 30% (i386) and fixed several bugs.
13037 * 1) In arith_apply():
13038 * a) Cached values of *numptr and &(numptr[-1]).
13039 * b) Removed redundant test for zero denominator.
13042 * a) Eliminated redundant code for processing operator tokens by moving
13043 * to a table-based implementation. Also folded handling of parens
13045 * b) Combined all 3 loops which called arith_apply to reduce generated
13046 * code size at the cost of speed.
13048 * 3) The following expressions were treated as valid by the original code:
13049 * 1() , 0! , 1 ( *3 ) .
13050 * These bugs have been fixed by internally enclosing the expression in
13051 * parens and then checking that all binary ops and right parens are
13052 * preceded by a valid expression (NUM_TOKEN).
13054 * Note: It may be desirable to replace Aaron's test for whitespace with
13055 * ctype's isspace() if it is used by another busybox applet or if additional
13056 * whitespace chars should be considered. Look below the "#include"s for a
13057 * precompiler test.
13061 * Aug 26, 2001 Manuel Novoa III
13063 * Return 0 for null expressions. Pointed out by Vladimir Oleynik.
13065 * Merge in Aaron's comments previously posted to the busybox list,
13066 * modified slightly to take account of my changes to the code.
13071 * (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
13073 * - allow access to variable,
13074 * used recursive find value indirection (c=2*2; a="c"; $((a+=2)) produce 6)
13075 * - realize assign syntax (VAR=expr, +=, *= etc)
13076 * - realize exponentiation (** operator)
13077 * - realize comma separated - expr, expr
13078 * - realise ++expr --expr expr++ expr--
13079 * - realise expr ? expr : expr (but, second expr calculate always)
13080 * - allow hexadecimal and octal numbers
13081 * - was restored loses XOR operator
13082 * - remove one goto label, added three ;-)
13083 * - protect $((num num)) as true zero expr (Manuel`s error)
13084 * - always use special isspace(), see comment from bash ;-)
13088 #define arith_isspace(arithval) \
13089 (arithval == ' ' || arithval == '\n' || arithval == '\t')
13092 typedef unsigned char operator;
13094 /* An operator's token id is a bit of a bitfield. The lower 5 bits are the
13095 * precedence, and 3 high bits are an ID unique across operators of that
13096 * precedence. The ID portion is so that multiple operators can have the
13097 * same precedence, ensuring that the leftmost one is evaluated first.
13098 * Consider * and /. */
13100 #define tok_decl(prec,id) (((id)<<5)|(prec))
13101 #define PREC(op) ((op) & 0x1F)
13103 #define TOK_LPAREN tok_decl(0,0)
13105 #define TOK_COMMA tok_decl(1,0)
13107 #define TOK_ASSIGN tok_decl(2,0)
13108 #define TOK_AND_ASSIGN tok_decl(2,1)
13109 #define TOK_OR_ASSIGN tok_decl(2,2)
13110 #define TOK_XOR_ASSIGN tok_decl(2,3)
13111 #define TOK_PLUS_ASSIGN tok_decl(2,4)
13112 #define TOK_MINUS_ASSIGN tok_decl(2,5)
13113 #define TOK_LSHIFT_ASSIGN tok_decl(2,6)
13114 #define TOK_RSHIFT_ASSIGN tok_decl(2,7)
13116 #define TOK_MUL_ASSIGN tok_decl(3,0)
13117 #define TOK_DIV_ASSIGN tok_decl(3,1)
13118 #define TOK_REM_ASSIGN tok_decl(3,2)
13120 /* all assign is right associativity and precedence eq, but (7+3)<<5 > 256 */
13121 #define convert_prec_is_assing(prec) do { if(prec == 3) prec = 2; } while(0)
13123 /* conditional is right associativity too */
13124 #define TOK_CONDITIONAL tok_decl(4,0)
13125 #define TOK_CONDITIONAL_SEP tok_decl(4,1)
13127 #define TOK_OR tok_decl(5,0)
13129 #define TOK_AND tok_decl(6,0)
13131 #define TOK_BOR tok_decl(7,0)
13133 #define TOK_BXOR tok_decl(8,0)
13135 #define TOK_BAND tok_decl(9,0)
13137 #define TOK_EQ tok_decl(10,0)
13138 #define TOK_NE tok_decl(10,1)
13140 #define TOK_LT tok_decl(11,0)
13141 #define TOK_GT tok_decl(11,1)
13142 #define TOK_GE tok_decl(11,2)
13143 #define TOK_LE tok_decl(11,3)
13145 #define TOK_LSHIFT tok_decl(12,0)
13146 #define TOK_RSHIFT tok_decl(12,1)
13148 #define TOK_ADD tok_decl(13,0)
13149 #define TOK_SUB tok_decl(13,1)
13151 #define TOK_MUL tok_decl(14,0)
13152 #define TOK_DIV tok_decl(14,1)
13153 #define TOK_REM tok_decl(14,2)
13155 /* exponent is right associativity */
13156 #define TOK_EXPONENT tok_decl(15,1)
13158 /* For now unary operators. */
13159 #define UNARYPREC 16
13160 #define TOK_BNOT tok_decl(UNARYPREC,0)
13161 #define TOK_NOT tok_decl(UNARYPREC,1)
13163 #define TOK_UMINUS tok_decl(UNARYPREC+1,0)
13164 #define TOK_UPLUS tok_decl(UNARYPREC+1,1)
13166 #define PREC_PRE (UNARYPREC+2)
13168 #define TOK_PRE_INC tok_decl(PREC_PRE, 0)
13169 #define TOK_PRE_DEC tok_decl(PREC_PRE, 1)
13171 #define PREC_POST (UNARYPREC+3)
13173 #define TOK_POST_INC tok_decl(PREC_POST, 0)
13174 #define TOK_POST_DEC tok_decl(PREC_POST, 1)
13176 #define SPEC_PREC (UNARYPREC+4)
13178 #define TOK_NUM tok_decl(SPEC_PREC, 0)
13179 #define TOK_RPAREN tok_decl(SPEC_PREC, 1)
13181 #define NUMPTR (*numstackptr)
13183 static inline int tok_have_assign(operator op)
13185 operator prec = PREC(op);
13187 convert_prec_is_assing(prec);
13188 return (prec == PREC(TOK_ASSIGN) ||
13189 prec == PREC_PRE || prec == PREC_POST);
13192 static inline int is_right_associativity(operator prec)
13194 return (prec == PREC(TOK_ASSIGN) || prec == PREC(TOK_EXPONENT) ||
13195 prec == PREC(TOK_CONDITIONAL));
13199 typedef struct ARITCH_VAR_NUM {
13201 arith_t contidional_second_val;
13202 char contidional_second_val_initialized;
13203 char *var; /* if NULL then is regular number,
13204 else is variable name */
13208 typedef struct CHK_VAR_RECURSIVE_LOOPED {
13210 struct CHK_VAR_RECURSIVE_LOOPED *next;
13211 } chk_var_recursive_looped_t;
13213 static chk_var_recursive_looped_t *prev_chk_var_recursive;
13216 static int arith_lookup_val(v_n_t *t)
13219 const char * p = lookupvar(t->var);
13224 /* recursive try as expression */
13225 chk_var_recursive_looped_t *cur;
13226 chk_var_recursive_looped_t cur_save;
13228 for(cur = prev_chk_var_recursive; cur; cur = cur->next) {
13229 if(strcmp(cur->var, t->var) == 0) {
13230 /* expression recursion loop detected */
13234 /* save current lookuped var name */
13235 cur = prev_chk_var_recursive;
13236 cur_save.var = t->var;
13237 cur_save.next = cur;
13238 prev_chk_var_recursive = &cur_save;
13240 t->val = arith (p, &errcode);
13241 /* restore previous ptr after recursiving */
13242 prev_chk_var_recursive = cur;
13245 /* allow undefined var as 0 */
13252 /* "applying" a token means performing it on the top elements on the integer
13253 * stack. For a unary operator it will only change the top element, but a
13254 * binary operator will pop two arguments and push a result */
13256 arith_apply(operator op, v_n_t *numstack, v_n_t **numstackptr)
13259 arith_t numptr_val, rez;
13260 int ret_arith_lookup_val;
13262 if (NUMPTR == numstack) goto err; /* There is no operator that can work
13263 without arguments */
13264 numptr_m1 = NUMPTR - 1;
13266 /* check operand is var with noninteger value */
13267 ret_arith_lookup_val = arith_lookup_val(numptr_m1);
13268 if(ret_arith_lookup_val)
13269 return ret_arith_lookup_val;
13271 rez = numptr_m1->val;
13272 if (op == TOK_UMINUS)
13274 else if (op == TOK_NOT)
13276 else if (op == TOK_BNOT)
13278 else if (op == TOK_POST_INC || op == TOK_PRE_INC)
13280 else if (op == TOK_POST_DEC || op == TOK_PRE_DEC)
13282 else if (op != TOK_UPLUS) {
13283 /* Binary operators */
13285 /* check and binary operators need two arguments */
13286 if (numptr_m1 == numstack) goto err;
13288 /* ... and they pop one */
13291 if (op == TOK_CONDITIONAL) {
13292 if(! numptr_m1->contidional_second_val_initialized) {
13293 /* protect $((expr1 ? expr2)) without ": expr" */
13296 rez = numptr_m1->contidional_second_val;
13297 } else if(numptr_m1->contidional_second_val_initialized) {
13298 /* protect $((expr1 : expr2)) without "expr ? " */
13301 numptr_m1 = NUMPTR - 1;
13302 if(op != TOK_ASSIGN) {
13303 /* check operand is var with noninteger value for not '=' */
13304 ret_arith_lookup_val = arith_lookup_val(numptr_m1);
13305 if(ret_arith_lookup_val)
13306 return ret_arith_lookup_val;
13308 if (op == TOK_CONDITIONAL) {
13309 numptr_m1->contidional_second_val = rez;
13311 rez = numptr_m1->val;
13312 if (op == TOK_BOR || op == TOK_OR_ASSIGN)
13314 else if (op == TOK_OR)
13315 rez = numptr_val || rez;
13316 else if (op == TOK_BAND || op == TOK_AND_ASSIGN)
13318 else if (op == TOK_BXOR || op == TOK_XOR_ASSIGN)
13320 else if (op == TOK_AND)
13321 rez = rez && numptr_val;
13322 else if (op == TOK_EQ)
13323 rez = (rez == numptr_val);
13324 else if (op == TOK_NE)
13325 rez = (rez != numptr_val);
13326 else if (op == TOK_GE)
13327 rez = (rez >= numptr_val);
13328 else if (op == TOK_RSHIFT || op == TOK_RSHIFT_ASSIGN)
13329 rez >>= numptr_val;
13330 else if (op == TOK_LSHIFT || op == TOK_LSHIFT_ASSIGN)
13331 rez <<= numptr_val;
13332 else if (op == TOK_GT)
13333 rez = (rez > numptr_val);
13334 else if (op == TOK_LT)
13335 rez = (rez < numptr_val);
13336 else if (op == TOK_LE)
13337 rez = (rez <= numptr_val);
13338 else if (op == TOK_MUL || op == TOK_MUL_ASSIGN)
13340 else if (op == TOK_ADD || op == TOK_PLUS_ASSIGN)
13342 else if (op == TOK_SUB || op == TOK_MINUS_ASSIGN)
13344 else if (op == TOK_ASSIGN || op == TOK_COMMA)
13346 else if (op == TOK_CONDITIONAL_SEP) {
13347 if (numptr_m1 == numstack) {
13348 /* protect $((expr : expr)) without "expr ? " */
13351 numptr_m1->contidional_second_val_initialized = op;
13352 numptr_m1->contidional_second_val = numptr_val;
13354 else if (op == TOK_CONDITIONAL) {
13356 numptr_val : numptr_m1->contidional_second_val;
13358 else if(op == TOK_EXPONENT) {
13360 return -3; /* exponent less than 0 */
13365 while(numptr_val--)
13370 else if(numptr_val==0) /* zero divisor check */
13372 else if (op == TOK_DIV || op == TOK_DIV_ASSIGN)
13374 else if (op == TOK_REM || op == TOK_REM_ASSIGN)
13377 if(tok_have_assign(op)) {
13380 if(numptr_m1->var == NULL) {
13384 /* save to shell variable */
13385 #ifdef CONFIG_ASH_MATH_SUPPORT_64
13386 snprintf(buf, sizeof(buf), "%lld", arith_t_type rez);
13388 snprintf(buf, sizeof(buf), "%ld", arith_t_type rez);
13390 setvar(numptr_m1->var, buf, 0);
13391 /* after saving, make previous value for v++ or v-- */
13392 if(op == TOK_POST_INC)
13394 else if(op == TOK_POST_DEC)
13397 numptr_m1->val = rez;
13398 /* protect geting var value, is number now */
13399 numptr_m1->var = NULL;
13404 /* longest must first */
13405 static const char op_tokens[] = {
13406 '<','<','=',0, TOK_LSHIFT_ASSIGN,
13407 '>','>','=',0, TOK_RSHIFT_ASSIGN,
13408 '<','<', 0, TOK_LSHIFT,
13409 '>','>', 0, TOK_RSHIFT,
13410 '|','|', 0, TOK_OR,
13411 '&','&', 0, TOK_AND,
13412 '!','=', 0, TOK_NE,
13413 '<','=', 0, TOK_LE,
13414 '>','=', 0, TOK_GE,
13415 '=','=', 0, TOK_EQ,
13416 '|','=', 0, TOK_OR_ASSIGN,
13417 '&','=', 0, TOK_AND_ASSIGN,
13418 '*','=', 0, TOK_MUL_ASSIGN,
13419 '/','=', 0, TOK_DIV_ASSIGN,
13420 '%','=', 0, TOK_REM_ASSIGN,
13421 '+','=', 0, TOK_PLUS_ASSIGN,
13422 '-','=', 0, TOK_MINUS_ASSIGN,
13423 '-','-', 0, TOK_POST_DEC,
13424 '^','=', 0, TOK_XOR_ASSIGN,
13425 '+','+', 0, TOK_POST_INC,
13426 '*','*', 0, TOK_EXPONENT,
13430 '=', 0, TOK_ASSIGN,
13442 '?', 0, TOK_CONDITIONAL,
13443 ':', 0, TOK_CONDITIONAL_SEP,
13444 ')', 0, TOK_RPAREN,
13445 '(', 0, TOK_LPAREN,
13449 #define endexpression &op_tokens[sizeof(op_tokens)-7]
13452 static arith_t arith (const char *expr, int *perrcode)
13454 register char arithval; /* Current character under analysis */
13455 operator lasttok, op;
13458 const char *p = endexpression;
13461 size_t datasizes = strlen(expr) + 2;
13463 /* Stack of integers */
13464 /* The proof that there can be no more than strlen(startbuf)/2+1 integers
13465 * in any given correct or incorrect expression is left as an exercise to
13467 v_n_t *numstack = alloca(((datasizes)/2)*sizeof(v_n_t)),
13468 *numstackptr = numstack;
13469 /* Stack of operator tokens */
13470 operator *stack = alloca((datasizes) * sizeof(operator)),
13473 *stackptr++ = lasttok = TOK_LPAREN; /* start off with a left paren */
13474 *perrcode = errcode = 0;
13477 if ((arithval = *expr) == 0) {
13478 if (p == endexpression) {
13479 /* Null expression. */
13483 /* This is only reached after all tokens have been extracted from the
13484 * input stream. If there are still tokens on the operator stack, they
13485 * are to be applied in order. At the end, there should be a final
13486 * result on the integer stack */
13488 if (expr != endexpression + 1) {
13489 /* If we haven't done so already, */
13490 /* append a closing right paren */
13491 expr = endexpression;
13492 /* and let the loop process it. */
13495 /* At this point, we're done with the expression. */
13496 if (numstackptr != numstack+1) {
13497 /* ... but if there isn't, it's bad */
13499 return (*perrcode = -1);
13501 if(numstack->var) {
13502 /* expression is $((var)) only, lookup now */
13503 errcode = arith_lookup_val(numstack);
13506 *perrcode = errcode;
13507 return numstack->val;
13509 /* Continue processing the expression. */
13510 if (arith_isspace(arithval)) {
13511 /* Skip whitespace */
13514 if((p = endofname(expr)) != expr) {
13515 size_t var_name_size = (p-expr) + 1; /* trailing zero */
13517 numstackptr->var = alloca(var_name_size);
13518 safe_strncpy(numstackptr->var, expr, var_name_size);
13521 numstackptr->contidional_second_val_initialized = 0;
13525 } else if (is_digit(arithval)) {
13526 numstackptr->var = NULL;
13527 #ifdef CONFIG_ASH_MATH_SUPPORT_64
13528 numstackptr->val = strtoll(expr, (char **) &expr, 0);
13530 numstackptr->val = strtol(expr, (char **) &expr, 0);
13534 for(p = op_tokens; ; p++) {
13538 /* strange operator not found */
13541 for(o = expr; *p && *o == *p; p++)
13548 /* skip tail uncompared token */
13551 /* skip zero delim */
13556 /* post grammar: a++ reduce to num */
13557 if(lasttok == TOK_POST_INC || lasttok == TOK_POST_DEC)
13560 /* Plus and minus are binary (not unary) _only_ if the last
13561 * token was as number, or a right paren (which pretends to be
13562 * a number, since it evaluates to one). Think about it.
13563 * It makes sense. */
13564 if (lasttok != TOK_NUM) {
13580 /* We don't want a unary operator to cause recursive descent on the
13581 * stack, because there can be many in a row and it could cause an
13582 * operator to be evaluated before its argument is pushed onto the
13583 * integer stack. */
13584 /* But for binary operators, "apply" everything on the operator
13585 * stack until we find an operator with a lesser priority than the
13586 * one we have just extracted. */
13587 /* Left paren is given the lowest priority so it will never be
13588 * "applied" in this way.
13589 * if associativity is right and priority eq, applied also skip
13592 if ((prec > 0 && prec < UNARYPREC) || prec == SPEC_PREC) {
13593 /* not left paren or unary */
13594 if (lasttok != TOK_NUM) {
13595 /* binary op must be preceded by a num */
13598 while (stackptr != stack) {
13599 if (op == TOK_RPAREN) {
13600 /* The algorithm employed here is simple: while we don't
13601 * hit an open paren nor the bottom of the stack, pop
13602 * tokens and apply them */
13603 if (stackptr[-1] == TOK_LPAREN) {
13605 /* Any operator directly after a */
13607 /* close paren should consider itself binary */
13611 operator prev_prec = PREC(stackptr[-1]);
13613 convert_prec_is_assing(prec);
13614 convert_prec_is_assing(prev_prec);
13615 if (prev_prec < prec)
13617 /* check right assoc */
13618 if(prev_prec == prec && is_right_associativity(prec))
13621 errcode = arith_apply(*--stackptr, numstack, &numstackptr);
13622 if(errcode) goto ret;
13624 if (op == TOK_RPAREN) {
13629 /* Push this operator to the stack and remember it. */
13630 *stackptr++ = lasttok = op;
13637 #endif /* CONFIG_ASH_MATH_SUPPORT */
13641 const char *bb_applet_name = "debug stuff usage";
13642 int main(int argc, char **argv)
13644 return ash_main(argc, argv);
13649 * Copyright (c) 1989, 1991, 1993, 1994
13650 * The Regents of the University of California. All rights reserved.
13652 * This code is derived from software contributed to Berkeley by
13653 * Kenneth Almquist.
13655 * Redistribution and use in source and binary forms, with or without
13656 * modification, are permitted provided that the following conditions
13658 * 1. Redistributions of source code must retain the above copyright
13659 * notice, this list of conditions and the following disclaimer.
13660 * 2. Redistributions in binary form must reproduce the above copyright
13661 * notice, this list of conditions and the following disclaimer in the
13662 * documentation and/or other materials provided with the distribution.
13663 * 3. Neither the name of the University nor the names of its contributors
13664 * may be used to endorse or promote products derived from this software
13665 * without specific prior written permission.
13667 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
13668 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
13669 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
13670 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
13671 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
13672 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
13673 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13674 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
13675 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
13676 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF