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.
57 #include <sys/types.h>
58 #include <sys/ioctl.h>
59 #include <sys/param.h>
60 #include <sys/resource.h>
80 /*#include <stdint.h>*/
86 #ifdef CONFIG_ASH_JOB_CONTROL
92 #if JOBS || defined(CONFIG_ASH_READ_NCHARS)
100 static int *dash_errno;
102 #define errno (*dash_errno)
105 #if defined(__uClinux__)
106 #error "Do not even bother, ash will not run on uClinux"
110 #define _DIAGASSERT(assert_expr) assert(assert_expr)
112 #define _DIAGASSERT(assert_expr)
116 #ifdef CONFIG_ASH_ALIAS
129 static struct alias *lookupalias(const char *, int);
130 static int aliascmd(int, char **);
131 static int unaliascmd(int, char **);
132 static void rmaliases(void);
133 static int unalias(const char *);
134 static void printalias(const struct alias *);
140 static void setpwd(const char *, int);
146 * Types of operations (passed to the errmsg routine).
150 static const char not_found_msg[] = "%s: not found";
153 #define E_OPEN "No such file" /* opening a file */
154 #define E_CREAT "Directory nonexistent" /* creating a file */
155 #define E_EXEC not_found_msg+4 /* executing a program */
158 * We enclose jmp_buf in a structure so that we can declare pointers to
159 * jump locations. The global variable handler contains the location to
160 * jump to when an exception occurs, and the global variable exception
161 * contains a code identifying the exception. To implement nested
162 * exception handlers, the user should save the value of handler on entry
163 * to an inner scope, set handler to point to a jmploc structure for the
164 * inner scope, and restore handler on exit from the scope.
171 static struct jmploc *handler;
172 static int exception;
173 static volatile int suppressint;
174 static volatile sig_atomic_t intpending;
177 #define EXINT 0 /* SIGINT received */
178 #define EXERROR 1 /* a generic error */
179 #define EXSHELLPROC 2 /* execute a shell procedure */
180 #define EXEXEC 3 /* command execution failed */
181 #define EXEXIT 4 /* exit the shell */
182 #define EXSIG 5 /* trapped signal in wait(1) */
185 /* do we generate EXSIG events */
187 /* last pending signal */
188 static volatile sig_atomic_t pendingsigs;
191 * These macros allow the user to suspend the handling of interrupt signals
192 * over a period of time. This is similar to SIGHOLD to or sigblock, but
193 * much more efficient and portable. (But hacking the kernel is so much
194 * more fun than worrying about efficiency and portability. :-))
197 #define xbarrier() ({ __asm__ __volatile__ ("": : :"memory"); })
204 #define SAVEINT(v) ((v) = suppressint)
205 #define RESTOREINT(v) \
208 if ((suppressint = (v)) == 0 && intpending) onint(); \
219 /* EXSIG is turned off by evalbltin(). */
222 static void exraise(int) ATTRIBUTE_NORETURN;
223 static void onint(void) ATTRIBUTE_NORETURN;
225 static void sh_error(const char *, ...) ATTRIBUTE_NORETURN;
226 static void exerror(int, const char *, ...) ATTRIBUTE_NORETURN;
228 static void sh_warnx(const char *, ...);
230 #ifdef CONFIG_ASH_OPTIMIZE_FOR_SIZE
233 if (--suppressint == 0 && intpending) {
237 #define INTON inton()
238 static void forceinton(void)
244 #define FORCEINTON forceinton()
249 if (--suppressint == 0 && intpending) onint(); \
256 if (intpending) onint(); \
259 #endif /* CONFIG_ASH_OPTIMIZE_FOR_SIZE */
264 struct strlist *next;
270 struct strlist *list;
271 struct strlist **lastp;
277 #define EXP_FULL 0x1 /* perform word splitting & file globbing */
278 #define EXP_TILDE 0x2 /* do normal tilde expansion */
279 #define EXP_VARTILDE 0x4 /* expand tildes in an assignment */
280 #define EXP_REDIR 0x8 /* file glob for a redirection (1 match only) */
281 #define EXP_CASE 0x10 /* keeps quotes around for CASE pattern */
282 #define EXP_RECORD 0x20 /* need to record arguments for ifs breakup */
283 #define EXP_VARTILDE2 0x40 /* expand tildes after colons only */
284 #define EXP_WORD 0x80 /* expand word in parameter expansion */
285 #define EXP_QWORD 0x100 /* expand word in quoted parameter expansion */
289 static void expandarg(union node *, struct arglist *, int);
290 #define rmescapes(p) _rmescapes((p), 0)
291 static char *_rmescapes(char *, int);
292 static int casematch(union node *, char *);
294 #ifdef CONFIG_ASH_MATH_SUPPORT
295 static void expari(int);
300 static char *commandname; /* currently executing command */
301 static struct strlist *cmdenviron; /* environment for builtin command */
302 static int exitstatus; /* exit status of last command */
303 static int back_exitstatus; /* exit status of backquoted command */
306 struct backcmd { /* result of evalbackcmd */
307 int fd; /* file descriptor to read from */
308 char *buf; /* buffer */
309 int nleft; /* number of chars in buffer */
310 struct job *jp; /* job structure for command */
314 * This file was generated by the mknodes program.
350 union node *redirect;
357 struct nodelist *cmdlist;
364 union node *redirect;
379 union node *elsepart;
410 struct nodelist *backquote;
450 struct nredir nredir;
451 struct nbinary nbinary;
455 struct nclist nclist;
465 struct nodelist *next;
476 static void freefunc(struct funcnode *);
479 /* control characters in argument strings */
480 #define CTL_FIRST '\201' /* first 'special' character */
481 #define CTLESC '\201' /* escape next character */
482 #define CTLVAR '\202' /* variable defn */
483 #define CTLENDVAR '\203'
484 #define CTLBACKQ '\204'
485 #define CTLQUOTE 01 /* ored with CTLBACKQ code if in quotes */
486 /* CTLBACKQ | CTLQUOTE == '\205' */
487 #define CTLARI '\206' /* arithmetic expression */
488 #define CTLENDARI '\207'
489 #define CTLQUOTEMARK '\210'
490 #define CTL_LAST '\210' /* last 'special' character */
492 /* variable substitution byte (follows CTLVAR) */
493 #define VSTYPE 0x0f /* type of variable substitution */
494 #define VSNUL 0x10 /* colon--treat the empty string as unset */
495 #define VSQUOTE 0x80 /* inside double quotes--suppress splitting */
497 /* values of VSTYPE field */
498 #define VSNORMAL 0x1 /* normal variable: $var or ${var} */
499 #define VSMINUS 0x2 /* ${var-text} */
500 #define VSPLUS 0x3 /* ${var+text} */
501 #define VSQUESTION 0x4 /* ${var?message} */
502 #define VSASSIGN 0x5 /* ${var=text} */
503 #define VSTRIMRIGHT 0x6 /* ${var%pattern} */
504 #define VSTRIMRIGHTMAX 0x7 /* ${var%%pattern} */
505 #define VSTRIMLEFT 0x8 /* ${var#pattern} */
506 #define VSTRIMLEFTMAX 0x9 /* ${var##pattern} */
507 #define VSLENGTH 0xa /* ${#var} */
509 /* values of checkkwd variable */
514 #define IBUFSIZ (BUFSIZ + 1)
517 * NEOF is returned by parsecmd when it encounters an end of file. It
518 * must be distinct from NULL, so we use the address of a variable that
519 * happens to be handy.
521 static int plinno = 1; /* input line number */
523 /* number of characters left in input buffer */
524 static int parsenleft; /* copy of parsefile->nleft */
525 static int parselleft; /* copy of parsefile->lleft */
527 /* next character in input buffer */
528 static char *parsenextc; /* copy of parsefile->nextc */
531 struct strpush *prev; /* preceding string on stack */
534 #ifdef CONFIG_ASH_ALIAS
535 struct alias *ap; /* if push was associated with an alias */
537 char *string; /* remember the string since it may change */
541 struct parsefile *prev; /* preceding file on stack */
542 int linno; /* current line */
543 int fd; /* file descriptor (or -1 if string) */
544 int nleft; /* number of chars left in this line */
545 int lleft; /* number of chars left in this buffer */
546 char *nextc; /* next char in buffer */
547 char *buf; /* input buffer */
548 struct strpush *strpush; /* for pushing strings at this level */
549 struct strpush basestrpush; /* so pushing one is fast */
552 static struct parsefile basepf; /* top level input file */
553 #define basebuf bb_common_bufsiz1 /* buffer for top level input file */
554 static struct parsefile *parsefile = &basepf; /* current input file */
557 static int tokpushback; /* last token pushed back */
558 #define NEOF ((union node *)&tokpushback)
559 static int parsebackquote; /* nonzero if we are inside backquotes */
560 static int doprompt; /* if set, prompt the user */
561 static int needprompt; /* true if interactive and at start of line */
562 static int lasttoken; /* last token read */
563 static char *wordtext; /* text of last word returned by readtoken */
565 static struct nodelist *backquotelist;
566 static union node *redirnode;
567 static struct heredoc *heredoc;
568 static int quoteflag; /* set if (part of) last token was quoted */
569 static int startlinno; /* line # where last token started */
571 static union node *parsecmd(int);
572 static void fixredir(union node *, const char *, int);
573 static const char *const *findkwd(const char *);
574 static char *endofname(const char *);
578 typedef void *pointer;
580 static char nullstr[1]; /* zero length string */
581 static const char spcstr[] = " ";
582 static const char snlfmt[] = "%s\n";
583 static const char dolatstr[] = { CTLVAR, VSNORMAL|VSQUOTE, '@', '=', '\0' };
584 static const char illnum[] = "Illegal number: %s";
585 static const char homestr[] = "HOME";
588 #define TRACE(param) trace param
589 #define TRACEV(param) tracev param
592 #define TRACEV(param)
595 #if !defined(__GNUC__) || (__GNUC__ == 2 && __GNUC_MINOR__ < 96)
596 #define __builtin_expect(x, expected_value) (x)
599 #define xlikely(x) __builtin_expect((x),1)
614 #define TENDBQUOTE 12
632 /* first char is indicating which tokens mark the end of a list */
633 static const char *const tokname_array[] = {
648 /* the following are keywords */
667 static const char *tokname(int tok)
673 sprintf(buf + (tok >= TSEMI), "%s%c",
674 tokname_array[tok] + 1, (tok >= TSEMI ? '"' : 0));
681 * Most machines require the value returned from malloc to be aligned
682 * in some way. The following macro will get this right on many machines.
685 #define SHELL_SIZE (sizeof(union {int i; char *cp; double d; }) - 1)
687 * It appears that grabstackstr() will barf with such alignments
688 * because stalloc() will return a string allocated in a new stackblock.
690 #define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE)
693 * This file was generated by the mksyntax program.
698 #define CWORD 0 /* character is nothing special */
699 #define CNL 1 /* newline character */
700 #define CBACK 2 /* a backslash character */
701 #define CSQUOTE 3 /* single quote */
702 #define CDQUOTE 4 /* double quote */
703 #define CENDQUOTE 5 /* a terminating quote */
704 #define CBQUOTE 6 /* backwards single quote */
705 #define CVAR 7 /* a dollar sign */
706 #define CENDVAR 8 /* a '}' character */
707 #define CLP 9 /* a left paren in arithmetic */
708 #define CRP 10 /* a right paren in arithmetic */
709 #define CENDFILE 11 /* end of file */
710 #define CCTL 12 /* like CWORD, except it must be escaped */
711 #define CSPCL 13 /* these terminate a word */
712 #define CIGN 14 /* character should be ignored */
714 #ifdef CONFIG_ASH_ALIAS
718 #define PEOA_OR_PEOF PEOA
722 #define PEOA_OR_PEOF PEOF
725 #define is_digit(c) ((unsigned)((c) - '0') <= 9)
726 #define is_name(c) ((c) == '_' || isalpha((unsigned char)(c)))
727 #define is_in_name(c) ((c) == '_' || isalnum((unsigned char)(c)))
729 /* C99 say: "char" declaration may be signed or unsigned default */
730 #define SC2INT(chr2may_be_negative_int) (int)((signed char)chr2may_be_negative_int)
733 * is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
734 * (assuming ascii char codes, as the original implementation did)
736 #define is_special(c) \
737 ( (((unsigned int)c) - 33 < 32) \
738 && ((0xc1ff920dUL >> (((unsigned int)c) - 33)) & 1))
740 #define digit_val(c) ((c) - '0')
743 * This file was generated by the mksyntax program.
746 #ifdef CONFIG_ASH_OPTIMIZE_FOR_SIZE
747 #define USE_SIT_FUNCTION
750 /* number syntax index */
751 #define BASESYNTAX 0 /* not in quotes */
752 #define DQSYNTAX 1 /* in double quotes */
753 #define SQSYNTAX 2 /* in single quotes */
754 #define ARISYNTAX 3 /* in arithmetic */
756 #ifdef CONFIG_ASH_MATH_SUPPORT
757 static const char S_I_T[][4] = {
758 #ifdef CONFIG_ASH_ALIAS
759 {CSPCL, CIGN, CIGN, CIGN}, /* 0, PEOA */
761 {CSPCL, CWORD, CWORD, CWORD}, /* 1, ' ' */
762 {CNL, CNL, CNL, CNL}, /* 2, \n */
763 {CWORD, CCTL, CCTL, CWORD}, /* 3, !*-/:=?[]~ */
764 {CDQUOTE, CENDQUOTE, CWORD, CWORD}, /* 4, '"' */
765 {CVAR, CVAR, CWORD, CVAR}, /* 5, $ */
766 {CSQUOTE, CWORD, CENDQUOTE, CWORD}, /* 6, "'" */
767 {CSPCL, CWORD, CWORD, CLP}, /* 7, ( */
768 {CSPCL, CWORD, CWORD, CRP}, /* 8, ) */
769 {CBACK, CBACK, CCTL, CBACK}, /* 9, \ */
770 {CBQUOTE, CBQUOTE, CWORD, CBQUOTE}, /* 10, ` */
771 {CENDVAR, CENDVAR, CWORD, CENDVAR}, /* 11, } */
772 #ifndef USE_SIT_FUNCTION
773 {CENDFILE, CENDFILE, CENDFILE, CENDFILE}, /* 12, PEOF */
774 {CWORD, CWORD, CWORD, CWORD}, /* 13, 0-9A-Za-z */
775 {CCTL, CCTL, CCTL, CCTL} /* 14, CTLESC ... */
779 static const char S_I_T[][3] = {
780 #ifdef CONFIG_ASH_ALIAS
781 {CSPCL, CIGN, CIGN}, /* 0, PEOA */
783 {CSPCL, CWORD, CWORD}, /* 1, ' ' */
784 {CNL, CNL, CNL}, /* 2, \n */
785 {CWORD, CCTL, CCTL}, /* 3, !*-/:=?[]~ */
786 {CDQUOTE, CENDQUOTE, CWORD}, /* 4, '"' */
787 {CVAR, CVAR, CWORD}, /* 5, $ */
788 {CSQUOTE, CWORD, CENDQUOTE}, /* 6, "'" */
789 {CSPCL, CWORD, CWORD}, /* 7, ( */
790 {CSPCL, CWORD, CWORD}, /* 8, ) */
791 {CBACK, CBACK, CCTL}, /* 9, \ */
792 {CBQUOTE, CBQUOTE, CWORD}, /* 10, ` */
793 {CENDVAR, CENDVAR, CWORD}, /* 11, } */
794 #ifndef USE_SIT_FUNCTION
795 {CENDFILE, CENDFILE, CENDFILE}, /* 12, PEOF */
796 {CWORD, CWORD, CWORD}, /* 13, 0-9A-Za-z */
797 {CCTL, CCTL, CCTL} /* 14, CTLESC ... */
800 #endif /* CONFIG_ASH_MATH_SUPPORT */
802 #ifdef USE_SIT_FUNCTION
804 #define U_C(c) ((unsigned char)(c))
806 static int SIT(int c, int syntax)
808 static const char spec_symbls[] = "\t\n !\"$&'()*-/:;<=>?[\\]`|}~";
809 #ifdef CONFIG_ASH_ALIAS
810 static const char syntax_index_table[] = {
811 1, 2, 1, 3, 4, 5, 1, 6, /* "\t\n !\"$&'" */
812 7, 8, 3, 3, 3, 3, 1, 1, /* "()*-/:;<" */
813 3, 1, 3, 3, 9, 3, 10, 1, /* "=>?[\\]`|" */
817 static const char syntax_index_table[] = {
818 0, 1, 0, 2, 3, 4, 0, 5, /* "\t\n !\"$&'" */
819 6, 7, 2, 2, 2, 2, 0, 0, /* "()*-/:;<" */
820 2, 0, 2, 2, 8, 2, 9, 0, /* "=>?[\\]`|" */
827 if (c == PEOF) /* 2^8+2 */
829 #ifdef CONFIG_ASH_ALIAS
830 if (c == PEOA) /* 2^8+1 */
834 if (U_C(c) >= U_C(CTLESC) && U_C(c) <= U_C(CTLQUOTEMARK))
837 s = strchr(spec_symbls, c);
838 if (s == 0 || *s == 0)
840 indx = syntax_index_table[(s - spec_symbls)];
842 return S_I_T[indx][syntax];
845 #else /* USE_SIT_FUNCTION */
847 #define SIT(c, syntax) S_I_T[(int)syntax_index_table[((int)c)+SYNBASE]][syntax]
849 #ifdef CONFIG_ASH_ALIAS
850 #define CSPCL_CIGN_CIGN_CIGN 0
851 #define CSPCL_CWORD_CWORD_CWORD 1
852 #define CNL_CNL_CNL_CNL 2
853 #define CWORD_CCTL_CCTL_CWORD 3
854 #define CDQUOTE_CENDQUOTE_CWORD_CWORD 4
855 #define CVAR_CVAR_CWORD_CVAR 5
856 #define CSQUOTE_CWORD_CENDQUOTE_CWORD 6
857 #define CSPCL_CWORD_CWORD_CLP 7
858 #define CSPCL_CWORD_CWORD_CRP 8
859 #define CBACK_CBACK_CCTL_CBACK 9
860 #define CBQUOTE_CBQUOTE_CWORD_CBQUOTE 10
861 #define CENDVAR_CENDVAR_CWORD_CENDVAR 11
862 #define CENDFILE_CENDFILE_CENDFILE_CENDFILE 12
863 #define CWORD_CWORD_CWORD_CWORD 13
864 #define CCTL_CCTL_CCTL_CCTL 14
866 #define CSPCL_CWORD_CWORD_CWORD 0
867 #define CNL_CNL_CNL_CNL 1
868 #define CWORD_CCTL_CCTL_CWORD 2
869 #define CDQUOTE_CENDQUOTE_CWORD_CWORD 3
870 #define CVAR_CVAR_CWORD_CVAR 4
871 #define CSQUOTE_CWORD_CENDQUOTE_CWORD 5
872 #define CSPCL_CWORD_CWORD_CLP 6
873 #define CSPCL_CWORD_CWORD_CRP 7
874 #define CBACK_CBACK_CCTL_CBACK 8
875 #define CBQUOTE_CBQUOTE_CWORD_CBQUOTE 9
876 #define CENDVAR_CENDVAR_CWORD_CENDVAR 10
877 #define CENDFILE_CENDFILE_CENDFILE_CENDFILE 11
878 #define CWORD_CWORD_CWORD_CWORD 12
879 #define CCTL_CCTL_CCTL_CCTL 13
882 static const char syntax_index_table[258] = {
883 /* BASESYNTAX_DQSYNTAX_SQSYNTAX_ARISYNTAX */
884 /* 0 PEOF */ CENDFILE_CENDFILE_CENDFILE_CENDFILE,
885 #ifdef CONFIG_ASH_ALIAS
886 /* 1 PEOA */ CSPCL_CIGN_CIGN_CIGN,
888 /* 2 -128 0x80 */ CWORD_CWORD_CWORD_CWORD,
889 /* 3 -127 CTLESC */ CCTL_CCTL_CCTL_CCTL,
890 /* 4 -126 CTLVAR */ CCTL_CCTL_CCTL_CCTL,
891 /* 5 -125 CTLENDVAR */ CCTL_CCTL_CCTL_CCTL,
892 /* 6 -124 CTLBACKQ */ CCTL_CCTL_CCTL_CCTL,
893 /* 7 -123 CTLQUOTE */ CCTL_CCTL_CCTL_CCTL,
894 /* 8 -122 CTLARI */ CCTL_CCTL_CCTL_CCTL,
895 /* 9 -121 CTLENDARI */ CCTL_CCTL_CCTL_CCTL,
896 /* 10 -120 CTLQUOTEMARK */ CCTL_CCTL_CCTL_CCTL,
897 /* 11 -119 */ CWORD_CWORD_CWORD_CWORD,
898 /* 12 -118 */ CWORD_CWORD_CWORD_CWORD,
899 /* 13 -117 */ CWORD_CWORD_CWORD_CWORD,
900 /* 14 -116 */ CWORD_CWORD_CWORD_CWORD,
901 /* 15 -115 */ CWORD_CWORD_CWORD_CWORD,
902 /* 16 -114 */ CWORD_CWORD_CWORD_CWORD,
903 /* 17 -113 */ CWORD_CWORD_CWORD_CWORD,
904 /* 18 -112 */ CWORD_CWORD_CWORD_CWORD,
905 /* 19 -111 */ CWORD_CWORD_CWORD_CWORD,
906 /* 20 -110 */ CWORD_CWORD_CWORD_CWORD,
907 /* 21 -109 */ CWORD_CWORD_CWORD_CWORD,
908 /* 22 -108 */ CWORD_CWORD_CWORD_CWORD,
909 /* 23 -107 */ CWORD_CWORD_CWORD_CWORD,
910 /* 24 -106 */ CWORD_CWORD_CWORD_CWORD,
911 /* 25 -105 */ CWORD_CWORD_CWORD_CWORD,
912 /* 26 -104 */ CWORD_CWORD_CWORD_CWORD,
913 /* 27 -103 */ CWORD_CWORD_CWORD_CWORD,
914 /* 28 -102 */ CWORD_CWORD_CWORD_CWORD,
915 /* 29 -101 */ CWORD_CWORD_CWORD_CWORD,
916 /* 30 -100 */ CWORD_CWORD_CWORD_CWORD,
917 /* 31 -99 */ CWORD_CWORD_CWORD_CWORD,
918 /* 32 -98 */ CWORD_CWORD_CWORD_CWORD,
919 /* 33 -97 */ CWORD_CWORD_CWORD_CWORD,
920 /* 34 -96 */ CWORD_CWORD_CWORD_CWORD,
921 /* 35 -95 */ CWORD_CWORD_CWORD_CWORD,
922 /* 36 -94 */ CWORD_CWORD_CWORD_CWORD,
923 /* 37 -93 */ CWORD_CWORD_CWORD_CWORD,
924 /* 38 -92 */ CWORD_CWORD_CWORD_CWORD,
925 /* 39 -91 */ CWORD_CWORD_CWORD_CWORD,
926 /* 40 -90 */ CWORD_CWORD_CWORD_CWORD,
927 /* 41 -89 */ CWORD_CWORD_CWORD_CWORD,
928 /* 42 -88 */ CWORD_CWORD_CWORD_CWORD,
929 /* 43 -87 */ CWORD_CWORD_CWORD_CWORD,
930 /* 44 -86 */ CWORD_CWORD_CWORD_CWORD,
931 /* 45 -85 */ CWORD_CWORD_CWORD_CWORD,
932 /* 46 -84 */ CWORD_CWORD_CWORD_CWORD,
933 /* 47 -83 */ CWORD_CWORD_CWORD_CWORD,
934 /* 48 -82 */ CWORD_CWORD_CWORD_CWORD,
935 /* 49 -81 */ CWORD_CWORD_CWORD_CWORD,
936 /* 50 -80 */ CWORD_CWORD_CWORD_CWORD,
937 /* 51 -79 */ CWORD_CWORD_CWORD_CWORD,
938 /* 52 -78 */ CWORD_CWORD_CWORD_CWORD,
939 /* 53 -77 */ CWORD_CWORD_CWORD_CWORD,
940 /* 54 -76 */ CWORD_CWORD_CWORD_CWORD,
941 /* 55 -75 */ CWORD_CWORD_CWORD_CWORD,
942 /* 56 -74 */ CWORD_CWORD_CWORD_CWORD,
943 /* 57 -73 */ CWORD_CWORD_CWORD_CWORD,
944 /* 58 -72 */ CWORD_CWORD_CWORD_CWORD,
945 /* 59 -71 */ CWORD_CWORD_CWORD_CWORD,
946 /* 60 -70 */ CWORD_CWORD_CWORD_CWORD,
947 /* 61 -69 */ CWORD_CWORD_CWORD_CWORD,
948 /* 62 -68 */ CWORD_CWORD_CWORD_CWORD,
949 /* 63 -67 */ CWORD_CWORD_CWORD_CWORD,
950 /* 64 -66 */ CWORD_CWORD_CWORD_CWORD,
951 /* 65 -65 */ CWORD_CWORD_CWORD_CWORD,
952 /* 66 -64 */ CWORD_CWORD_CWORD_CWORD,
953 /* 67 -63 */ CWORD_CWORD_CWORD_CWORD,
954 /* 68 -62 */ CWORD_CWORD_CWORD_CWORD,
955 /* 69 -61 */ CWORD_CWORD_CWORD_CWORD,
956 /* 70 -60 */ CWORD_CWORD_CWORD_CWORD,
957 /* 71 -59 */ CWORD_CWORD_CWORD_CWORD,
958 /* 72 -58 */ CWORD_CWORD_CWORD_CWORD,
959 /* 73 -57 */ CWORD_CWORD_CWORD_CWORD,
960 /* 74 -56 */ CWORD_CWORD_CWORD_CWORD,
961 /* 75 -55 */ CWORD_CWORD_CWORD_CWORD,
962 /* 76 -54 */ CWORD_CWORD_CWORD_CWORD,
963 /* 77 -53 */ CWORD_CWORD_CWORD_CWORD,
964 /* 78 -52 */ CWORD_CWORD_CWORD_CWORD,
965 /* 79 -51 */ CWORD_CWORD_CWORD_CWORD,
966 /* 80 -50 */ CWORD_CWORD_CWORD_CWORD,
967 /* 81 -49 */ CWORD_CWORD_CWORD_CWORD,
968 /* 82 -48 */ CWORD_CWORD_CWORD_CWORD,
969 /* 83 -47 */ CWORD_CWORD_CWORD_CWORD,
970 /* 84 -46 */ CWORD_CWORD_CWORD_CWORD,
971 /* 85 -45 */ CWORD_CWORD_CWORD_CWORD,
972 /* 86 -44 */ CWORD_CWORD_CWORD_CWORD,
973 /* 87 -43 */ CWORD_CWORD_CWORD_CWORD,
974 /* 88 -42 */ CWORD_CWORD_CWORD_CWORD,
975 /* 89 -41 */ CWORD_CWORD_CWORD_CWORD,
976 /* 90 -40 */ CWORD_CWORD_CWORD_CWORD,
977 /* 91 -39 */ CWORD_CWORD_CWORD_CWORD,
978 /* 92 -38 */ CWORD_CWORD_CWORD_CWORD,
979 /* 93 -37 */ CWORD_CWORD_CWORD_CWORD,
980 /* 94 -36 */ CWORD_CWORD_CWORD_CWORD,
981 /* 95 -35 */ CWORD_CWORD_CWORD_CWORD,
982 /* 96 -34 */ CWORD_CWORD_CWORD_CWORD,
983 /* 97 -33 */ CWORD_CWORD_CWORD_CWORD,
984 /* 98 -32 */ CWORD_CWORD_CWORD_CWORD,
985 /* 99 -31 */ CWORD_CWORD_CWORD_CWORD,
986 /* 100 -30 */ CWORD_CWORD_CWORD_CWORD,
987 /* 101 -29 */ CWORD_CWORD_CWORD_CWORD,
988 /* 102 -28 */ CWORD_CWORD_CWORD_CWORD,
989 /* 103 -27 */ CWORD_CWORD_CWORD_CWORD,
990 /* 104 -26 */ CWORD_CWORD_CWORD_CWORD,
991 /* 105 -25 */ CWORD_CWORD_CWORD_CWORD,
992 /* 106 -24 */ CWORD_CWORD_CWORD_CWORD,
993 /* 107 -23 */ CWORD_CWORD_CWORD_CWORD,
994 /* 108 -22 */ CWORD_CWORD_CWORD_CWORD,
995 /* 109 -21 */ CWORD_CWORD_CWORD_CWORD,
996 /* 110 -20 */ CWORD_CWORD_CWORD_CWORD,
997 /* 111 -19 */ CWORD_CWORD_CWORD_CWORD,
998 /* 112 -18 */ CWORD_CWORD_CWORD_CWORD,
999 /* 113 -17 */ CWORD_CWORD_CWORD_CWORD,
1000 /* 114 -16 */ CWORD_CWORD_CWORD_CWORD,
1001 /* 115 -15 */ CWORD_CWORD_CWORD_CWORD,
1002 /* 116 -14 */ CWORD_CWORD_CWORD_CWORD,
1003 /* 117 -13 */ CWORD_CWORD_CWORD_CWORD,
1004 /* 118 -12 */ CWORD_CWORD_CWORD_CWORD,
1005 /* 119 -11 */ CWORD_CWORD_CWORD_CWORD,
1006 /* 120 -10 */ CWORD_CWORD_CWORD_CWORD,
1007 /* 121 -9 */ CWORD_CWORD_CWORD_CWORD,
1008 /* 122 -8 */ CWORD_CWORD_CWORD_CWORD,
1009 /* 123 -7 */ CWORD_CWORD_CWORD_CWORD,
1010 /* 124 -6 */ CWORD_CWORD_CWORD_CWORD,
1011 /* 125 -5 */ CWORD_CWORD_CWORD_CWORD,
1012 /* 126 -4 */ CWORD_CWORD_CWORD_CWORD,
1013 /* 127 -3 */ CWORD_CWORD_CWORD_CWORD,
1014 /* 128 -2 */ CWORD_CWORD_CWORD_CWORD,
1015 /* 129 -1 */ CWORD_CWORD_CWORD_CWORD,
1016 /* 130 0 */ CWORD_CWORD_CWORD_CWORD,
1017 /* 131 1 */ CWORD_CWORD_CWORD_CWORD,
1018 /* 132 2 */ CWORD_CWORD_CWORD_CWORD,
1019 /* 133 3 */ CWORD_CWORD_CWORD_CWORD,
1020 /* 134 4 */ CWORD_CWORD_CWORD_CWORD,
1021 /* 135 5 */ CWORD_CWORD_CWORD_CWORD,
1022 /* 136 6 */ CWORD_CWORD_CWORD_CWORD,
1023 /* 137 7 */ CWORD_CWORD_CWORD_CWORD,
1024 /* 138 8 */ CWORD_CWORD_CWORD_CWORD,
1025 /* 139 9 "\t" */ CSPCL_CWORD_CWORD_CWORD,
1026 /* 140 10 "\n" */ CNL_CNL_CNL_CNL,
1027 /* 141 11 */ CWORD_CWORD_CWORD_CWORD,
1028 /* 142 12 */ CWORD_CWORD_CWORD_CWORD,
1029 /* 143 13 */ CWORD_CWORD_CWORD_CWORD,
1030 /* 144 14 */ CWORD_CWORD_CWORD_CWORD,
1031 /* 145 15 */ CWORD_CWORD_CWORD_CWORD,
1032 /* 146 16 */ CWORD_CWORD_CWORD_CWORD,
1033 /* 147 17 */ CWORD_CWORD_CWORD_CWORD,
1034 /* 148 18 */ CWORD_CWORD_CWORD_CWORD,
1035 /* 149 19 */ CWORD_CWORD_CWORD_CWORD,
1036 /* 150 20 */ CWORD_CWORD_CWORD_CWORD,
1037 /* 151 21 */ CWORD_CWORD_CWORD_CWORD,
1038 /* 152 22 */ CWORD_CWORD_CWORD_CWORD,
1039 /* 153 23 */ CWORD_CWORD_CWORD_CWORD,
1040 /* 154 24 */ CWORD_CWORD_CWORD_CWORD,
1041 /* 155 25 */ CWORD_CWORD_CWORD_CWORD,
1042 /* 156 26 */ CWORD_CWORD_CWORD_CWORD,
1043 /* 157 27 */ CWORD_CWORD_CWORD_CWORD,
1044 /* 158 28 */ CWORD_CWORD_CWORD_CWORD,
1045 /* 159 29 */ CWORD_CWORD_CWORD_CWORD,
1046 /* 160 30 */ CWORD_CWORD_CWORD_CWORD,
1047 /* 161 31 */ CWORD_CWORD_CWORD_CWORD,
1048 /* 162 32 " " */ CSPCL_CWORD_CWORD_CWORD,
1049 /* 163 33 "!" */ CWORD_CCTL_CCTL_CWORD,
1050 /* 164 34 """ */ CDQUOTE_CENDQUOTE_CWORD_CWORD,
1051 /* 165 35 "#" */ CWORD_CWORD_CWORD_CWORD,
1052 /* 166 36 "$" */ CVAR_CVAR_CWORD_CVAR,
1053 /* 167 37 "%" */ CWORD_CWORD_CWORD_CWORD,
1054 /* 168 38 "&" */ CSPCL_CWORD_CWORD_CWORD,
1055 /* 169 39 "'" */ CSQUOTE_CWORD_CENDQUOTE_CWORD,
1056 /* 170 40 "(" */ CSPCL_CWORD_CWORD_CLP,
1057 /* 171 41 ")" */ CSPCL_CWORD_CWORD_CRP,
1058 /* 172 42 "*" */ CWORD_CCTL_CCTL_CWORD,
1059 /* 173 43 "+" */ CWORD_CWORD_CWORD_CWORD,
1060 /* 174 44 "," */ CWORD_CWORD_CWORD_CWORD,
1061 /* 175 45 "-" */ CWORD_CCTL_CCTL_CWORD,
1062 /* 176 46 "." */ CWORD_CWORD_CWORD_CWORD,
1063 /* 177 47 "/" */ CWORD_CCTL_CCTL_CWORD,
1064 /* 178 48 "0" */ CWORD_CWORD_CWORD_CWORD,
1065 /* 179 49 "1" */ CWORD_CWORD_CWORD_CWORD,
1066 /* 180 50 "2" */ CWORD_CWORD_CWORD_CWORD,
1067 /* 181 51 "3" */ CWORD_CWORD_CWORD_CWORD,
1068 /* 182 52 "4" */ CWORD_CWORD_CWORD_CWORD,
1069 /* 183 53 "5" */ CWORD_CWORD_CWORD_CWORD,
1070 /* 184 54 "6" */ CWORD_CWORD_CWORD_CWORD,
1071 /* 185 55 "7" */ CWORD_CWORD_CWORD_CWORD,
1072 /* 186 56 "8" */ CWORD_CWORD_CWORD_CWORD,
1073 /* 187 57 "9" */ CWORD_CWORD_CWORD_CWORD,
1074 /* 188 58 ":" */ CWORD_CCTL_CCTL_CWORD,
1075 /* 189 59 ";" */ CSPCL_CWORD_CWORD_CWORD,
1076 /* 190 60 "<" */ CSPCL_CWORD_CWORD_CWORD,
1077 /* 191 61 "=" */ CWORD_CCTL_CCTL_CWORD,
1078 /* 192 62 ">" */ CSPCL_CWORD_CWORD_CWORD,
1079 /* 193 63 "?" */ CWORD_CCTL_CCTL_CWORD,
1080 /* 194 64 "@" */ CWORD_CWORD_CWORD_CWORD,
1081 /* 195 65 "A" */ CWORD_CWORD_CWORD_CWORD,
1082 /* 196 66 "B" */ CWORD_CWORD_CWORD_CWORD,
1083 /* 197 67 "C" */ CWORD_CWORD_CWORD_CWORD,
1084 /* 198 68 "D" */ CWORD_CWORD_CWORD_CWORD,
1085 /* 199 69 "E" */ CWORD_CWORD_CWORD_CWORD,
1086 /* 200 70 "F" */ CWORD_CWORD_CWORD_CWORD,
1087 /* 201 71 "G" */ CWORD_CWORD_CWORD_CWORD,
1088 /* 202 72 "H" */ CWORD_CWORD_CWORD_CWORD,
1089 /* 203 73 "I" */ CWORD_CWORD_CWORD_CWORD,
1090 /* 204 74 "J" */ CWORD_CWORD_CWORD_CWORD,
1091 /* 205 75 "K" */ CWORD_CWORD_CWORD_CWORD,
1092 /* 206 76 "L" */ CWORD_CWORD_CWORD_CWORD,
1093 /* 207 77 "M" */ CWORD_CWORD_CWORD_CWORD,
1094 /* 208 78 "N" */ CWORD_CWORD_CWORD_CWORD,
1095 /* 209 79 "O" */ CWORD_CWORD_CWORD_CWORD,
1096 /* 210 80 "P" */ CWORD_CWORD_CWORD_CWORD,
1097 /* 211 81 "Q" */ CWORD_CWORD_CWORD_CWORD,
1098 /* 212 82 "R" */ CWORD_CWORD_CWORD_CWORD,
1099 /* 213 83 "S" */ CWORD_CWORD_CWORD_CWORD,
1100 /* 214 84 "T" */ CWORD_CWORD_CWORD_CWORD,
1101 /* 215 85 "U" */ CWORD_CWORD_CWORD_CWORD,
1102 /* 216 86 "V" */ CWORD_CWORD_CWORD_CWORD,
1103 /* 217 87 "W" */ CWORD_CWORD_CWORD_CWORD,
1104 /* 218 88 "X" */ CWORD_CWORD_CWORD_CWORD,
1105 /* 219 89 "Y" */ CWORD_CWORD_CWORD_CWORD,
1106 /* 220 90 "Z" */ CWORD_CWORD_CWORD_CWORD,
1107 /* 221 91 "[" */ CWORD_CCTL_CCTL_CWORD,
1108 /* 222 92 "\" */ CBACK_CBACK_CCTL_CBACK,
1109 /* 223 93 "]" */ CWORD_CCTL_CCTL_CWORD,
1110 /* 224 94 "^" */ CWORD_CWORD_CWORD_CWORD,
1111 /* 225 95 "_" */ CWORD_CWORD_CWORD_CWORD,
1112 /* 226 96 "`" */ CBQUOTE_CBQUOTE_CWORD_CBQUOTE,
1113 /* 227 97 "a" */ CWORD_CWORD_CWORD_CWORD,
1114 /* 228 98 "b" */ CWORD_CWORD_CWORD_CWORD,
1115 /* 229 99 "c" */ CWORD_CWORD_CWORD_CWORD,
1116 /* 230 100 "d" */ CWORD_CWORD_CWORD_CWORD,
1117 /* 231 101 "e" */ CWORD_CWORD_CWORD_CWORD,
1118 /* 232 102 "f" */ CWORD_CWORD_CWORD_CWORD,
1119 /* 233 103 "g" */ CWORD_CWORD_CWORD_CWORD,
1120 /* 234 104 "h" */ CWORD_CWORD_CWORD_CWORD,
1121 /* 235 105 "i" */ CWORD_CWORD_CWORD_CWORD,
1122 /* 236 106 "j" */ CWORD_CWORD_CWORD_CWORD,
1123 /* 237 107 "k" */ CWORD_CWORD_CWORD_CWORD,
1124 /* 238 108 "l" */ CWORD_CWORD_CWORD_CWORD,
1125 /* 239 109 "m" */ CWORD_CWORD_CWORD_CWORD,
1126 /* 240 110 "n" */ CWORD_CWORD_CWORD_CWORD,
1127 /* 241 111 "o" */ CWORD_CWORD_CWORD_CWORD,
1128 /* 242 112 "p" */ CWORD_CWORD_CWORD_CWORD,
1129 /* 243 113 "q" */ CWORD_CWORD_CWORD_CWORD,
1130 /* 244 114 "r" */ CWORD_CWORD_CWORD_CWORD,
1131 /* 245 115 "s" */ CWORD_CWORD_CWORD_CWORD,
1132 /* 246 116 "t" */ CWORD_CWORD_CWORD_CWORD,
1133 /* 247 117 "u" */ CWORD_CWORD_CWORD_CWORD,
1134 /* 248 118 "v" */ CWORD_CWORD_CWORD_CWORD,
1135 /* 249 119 "w" */ CWORD_CWORD_CWORD_CWORD,
1136 /* 250 120 "x" */ CWORD_CWORD_CWORD_CWORD,
1137 /* 251 121 "y" */ CWORD_CWORD_CWORD_CWORD,
1138 /* 252 122 "z" */ CWORD_CWORD_CWORD_CWORD,
1139 /* 253 123 "{" */ CWORD_CWORD_CWORD_CWORD,
1140 /* 254 124 "|" */ CSPCL_CWORD_CWORD_CWORD,
1141 /* 255 125 "}" */ CENDVAR_CENDVAR_CWORD_CENDVAR,
1142 /* 256 126 "~" */ CWORD_CCTL_CCTL_CWORD,
1143 /* 257 127 */ CWORD_CWORD_CWORD_CWORD,
1146 #endif /* USE_SIT_FUNCTION */
1153 static int funcblocksize; /* size of structures in function */
1154 static int funcstringsize; /* size of strings in node */
1155 static pointer funcblock; /* block to allocate function from */
1156 static char *funcstring; /* block to allocate strings from */
1158 static const short nodesize[26] = {
1159 SHELL_ALIGN(sizeof (struct ncmd)),
1160 SHELL_ALIGN(sizeof (struct npipe)),
1161 SHELL_ALIGN(sizeof (struct nredir)),
1162 SHELL_ALIGN(sizeof (struct nredir)),
1163 SHELL_ALIGN(sizeof (struct nredir)),
1164 SHELL_ALIGN(sizeof (struct nbinary)),
1165 SHELL_ALIGN(sizeof (struct nbinary)),
1166 SHELL_ALIGN(sizeof (struct nbinary)),
1167 SHELL_ALIGN(sizeof (struct nif)),
1168 SHELL_ALIGN(sizeof (struct nbinary)),
1169 SHELL_ALIGN(sizeof (struct nbinary)),
1170 SHELL_ALIGN(sizeof (struct nfor)),
1171 SHELL_ALIGN(sizeof (struct ncase)),
1172 SHELL_ALIGN(sizeof (struct nclist)),
1173 SHELL_ALIGN(sizeof (struct narg)),
1174 SHELL_ALIGN(sizeof (struct narg)),
1175 SHELL_ALIGN(sizeof (struct nfile)),
1176 SHELL_ALIGN(sizeof (struct nfile)),
1177 SHELL_ALIGN(sizeof (struct nfile)),
1178 SHELL_ALIGN(sizeof (struct nfile)),
1179 SHELL_ALIGN(sizeof (struct nfile)),
1180 SHELL_ALIGN(sizeof (struct ndup)),
1181 SHELL_ALIGN(sizeof (struct ndup)),
1182 SHELL_ALIGN(sizeof (struct nhere)),
1183 SHELL_ALIGN(sizeof (struct nhere)),
1184 SHELL_ALIGN(sizeof (struct nnot)),
1188 static void calcsize(union node *);
1189 static void sizenodelist(struct nodelist *);
1190 static union node *copynode(union node *);
1191 static struct nodelist *copynodelist(struct nodelist *);
1192 static char *nodesavestr(char *);
1195 static int evalstring(char *, int mask);
1196 union node; /* BLETCH for ansi C */
1197 static void evaltree(union node *, int);
1198 static void evalbackcmd(union node *, struct backcmd *);
1200 static int evalskip; /* set if we are skipping commands */
1201 static int skipcount; /* number of levels to skip */
1202 static int funcnest; /* depth of function calls */
1204 /* reasons for skipping commands (see comment on breakcmd routine) */
1205 #define SKIPBREAK (1 << 0)
1206 #define SKIPCONT (1 << 1)
1207 #define SKIPFUNC (1 << 2)
1208 #define SKIPFILE (1 << 3)
1209 #define SKIPEVAL (1 << 4)
1212 * This file was generated by the mkbuiltins program.
1216 static int bgcmd(int, char **);
1218 static int breakcmd(int, char **);
1219 static int cdcmd(int, char **);
1220 #ifdef CONFIG_ASH_CMDCMD
1221 static int commandcmd(int, char **);
1223 static int dotcmd(int, char **);
1224 static int evalcmd(int, char **);
1225 #ifdef CONFIG_ASH_BUILTIN_ECHO
1226 static int echocmd(int, char **);
1228 #ifdef CONFIG_ASH_BUILTIN_TEST
1229 static int testcmd(int, char **);
1231 static int execcmd(int, char **);
1232 static int exitcmd(int, char **);
1233 static int exportcmd(int, char **);
1234 static int falsecmd(int, char **);
1236 static int fgcmd(int, char **);
1238 #ifdef CONFIG_ASH_GETOPTS
1239 static int getoptscmd(int, char **);
1241 static int hashcmd(int, char **);
1242 #ifndef CONFIG_FEATURE_SH_EXTRA_QUIET
1243 static int helpcmd(int argc, char **argv);
1246 static int jobscmd(int, char **);
1248 #ifdef CONFIG_ASH_MATH_SUPPORT
1249 static int letcmd(int, char **);
1251 static int localcmd(int, char **);
1252 static int pwdcmd(int, char **);
1253 static int readcmd(int, char **);
1254 static int returncmd(int, char **);
1255 static int setcmd(int, char **);
1256 static int shiftcmd(int, char **);
1257 static int timescmd(int, char **);
1258 static int trapcmd(int, char **);
1259 static int truecmd(int, char **);
1260 static int typecmd(int, char **);
1261 static int umaskcmd(int, char **);
1262 static int unsetcmd(int, char **);
1263 static int waitcmd(int, char **);
1264 static int ulimitcmd(int, char **);
1266 static int killcmd(int, char **);
1271 #ifdef CONFIG_ASH_MAIL
1272 static void chkmail(void);
1273 static void changemail(const char *);
1278 /* values of cmdtype */
1279 #define CMDUNKNOWN -1 /* no entry in table for command */
1280 #define CMDNORMAL 0 /* command is an executable program */
1281 #define CMDFUNCTION 1 /* command is a shell function */
1282 #define CMDBUILTIN 2 /* command is a shell builtin */
1286 int (*builtin)(int, char **);
1287 /* unsigned flags; */
1291 #define COMMANDCMD (builtincmd + 5 + \
1292 2 * ENABLE_ASH_BUILTIN_TEST + \
1293 ENABLE_ASH_ALIAS + \
1294 ENABLE_ASH_JOB_CONTROL)
1295 #define EXECCMD (builtincmd + 7 + \
1296 2 * ENABLE_ASH_BUILTIN_TEST + \
1297 ENABLE_ASH_ALIAS + \
1298 ENABLE_ASH_JOB_CONTROL + \
1299 ENABLE_ASH_CMDCMD + \
1300 ENABLE_ASH_BUILTIN_ECHO)
1302 #define BUILTIN_NOSPEC "0"
1303 #define BUILTIN_SPECIAL "1"
1304 #define BUILTIN_REGULAR "2"
1305 #define BUILTIN_SPEC_REG "3"
1306 #define BUILTIN_ASSIGN "4"
1307 #define BUILTIN_SPEC_ASSG "5"
1308 #define BUILTIN_REG_ASSG "6"
1309 #define BUILTIN_SPEC_REG_ASSG "7"
1311 #define IS_BUILTIN_SPECIAL(builtincmd) ((builtincmd)->name[0] & 1)
1312 #define IS_BUILTIN_REGULAR(builtincmd) ((builtincmd)->name[0] & 2)
1313 #define IS_BUILTIN_ASSIGN(builtincmd) ((builtincmd)->name[0] & 4)
1315 /* make sure to keep these in proper order since it is searched via bsearch() */
1316 static const struct builtincmd builtincmd[] = {
1317 { BUILTIN_SPEC_REG ".", dotcmd },
1318 { BUILTIN_SPEC_REG ":", truecmd },
1319 #ifdef CONFIG_ASH_BUILTIN_TEST
1320 { BUILTIN_REGULAR "[", testcmd },
1321 { BUILTIN_REGULAR "[[", testcmd },
1323 #ifdef CONFIG_ASH_ALIAS
1324 { BUILTIN_REG_ASSG "alias", aliascmd },
1327 { BUILTIN_REGULAR "bg", bgcmd },
1329 { BUILTIN_SPEC_REG "break", breakcmd },
1330 { BUILTIN_REGULAR "cd", cdcmd },
1331 { BUILTIN_NOSPEC "chdir", cdcmd },
1332 #ifdef CONFIG_ASH_CMDCMD
1333 { BUILTIN_REGULAR "command", commandcmd },
1335 { BUILTIN_SPEC_REG "continue", breakcmd },
1336 #ifdef CONFIG_ASH_BUILTIN_ECHO
1337 { BUILTIN_REGULAR "echo", echocmd },
1339 { BUILTIN_SPEC_REG "eval", evalcmd },
1340 { BUILTIN_SPEC_REG "exec", execcmd },
1341 { BUILTIN_SPEC_REG "exit", exitcmd },
1342 { BUILTIN_SPEC_REG_ASSG "export", exportcmd },
1343 { BUILTIN_REGULAR "false", falsecmd },
1345 { BUILTIN_REGULAR "fg", fgcmd },
1347 #ifdef CONFIG_ASH_GETOPTS
1348 { BUILTIN_REGULAR "getopts", getoptscmd },
1350 { BUILTIN_NOSPEC "hash", hashcmd },
1351 #ifndef CONFIG_FEATURE_SH_EXTRA_QUIET
1352 { BUILTIN_NOSPEC "help", helpcmd },
1355 { BUILTIN_REGULAR "jobs", jobscmd },
1356 { BUILTIN_REGULAR "kill", killcmd },
1358 #ifdef CONFIG_ASH_MATH_SUPPORT
1359 { BUILTIN_NOSPEC "let", letcmd },
1361 { BUILTIN_ASSIGN "local", localcmd },
1362 { BUILTIN_NOSPEC "pwd", pwdcmd },
1363 { BUILTIN_REGULAR "read", readcmd },
1364 { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd },
1365 { BUILTIN_SPEC_REG "return", returncmd },
1366 { BUILTIN_SPEC_REG "set", setcmd },
1367 { BUILTIN_SPEC_REG "shift", shiftcmd },
1368 { BUILTIN_SPEC_REG "source", dotcmd },
1369 #ifdef CONFIG_ASH_BUILTIN_TEST
1370 { BUILTIN_REGULAR "test", testcmd },
1372 { BUILTIN_SPEC_REG "times", timescmd },
1373 { BUILTIN_SPEC_REG "trap", trapcmd },
1374 { BUILTIN_REGULAR "true", truecmd },
1375 { BUILTIN_NOSPEC "type", typecmd },
1376 { BUILTIN_NOSPEC "ulimit", ulimitcmd },
1377 { BUILTIN_REGULAR "umask", umaskcmd },
1378 #ifdef CONFIG_ASH_ALIAS
1379 { BUILTIN_REGULAR "unalias", unaliascmd },
1381 { BUILTIN_SPEC_REG "unset", unsetcmd },
1382 { BUILTIN_REGULAR "wait", waitcmd },
1385 #define NUMBUILTINS (sizeof (builtincmd) / sizeof (struct builtincmd) )
1393 const struct builtincmd *cmd;
1394 struct funcnode *func;
1399 /* action to find_command() */
1400 #define DO_ERR 0x01 /* prints errors */
1401 #define DO_ABS 0x02 /* checks absolute paths */
1402 #define DO_NOFUNC 0x04 /* don't return shell functions, for command */
1403 #define DO_ALTPATH 0x08 /* using alternate path */
1404 #define DO_ALTBLTIN 0x20 /* %builtin in alt. path */
1406 static const char *pathopt; /* set by padvance */
1408 static void shellexec(char **, const char *, int)
1410 static char *padvance(const char **, const char *);
1411 static void find_command(char *, struct cmdentry *, int, const char *);
1412 static struct builtincmd *find_builtin(const char *);
1413 static void hashcd(void);
1414 static void changepath(const char *);
1415 static void defun(char *, union node *);
1416 static void unsetfunc(const char *);
1418 #ifdef CONFIG_ASH_MATH_SUPPORT_64
1419 typedef int64_t arith_t;
1420 #define arith_t_type (long long)
1422 typedef long arith_t;
1423 #define arith_t_type (long)
1426 #ifdef CONFIG_ASH_MATH_SUPPORT
1427 static arith_t dash_arith(const char *);
1428 static arith_t arith(const char *expr, int *perrcode);
1431 #ifdef CONFIG_ASH_RANDOM_SUPPORT
1432 static unsigned long rseed;
1433 static void change_random(const char *);
1434 # ifndef DYNAMIC_VAR
1435 # define DYNAMIC_VAR
1441 static void reset(void);
1450 #define VEXPORT 0x01 /* variable is exported */
1451 #define VREADONLY 0x02 /* variable cannot be modified */
1452 #define VSTRFIXED 0x04 /* variable struct is statically allocated */
1453 #define VTEXTFIXED 0x08 /* text is statically allocated */
1454 #define VSTACK 0x10 /* text is allocated on the stack */
1455 #define VUNSET 0x20 /* the variable is not set */
1456 #define VNOFUNC 0x40 /* don't call the callback function */
1457 #define VNOSET 0x80 /* do not set variable - just readonly test */
1458 #define VNOSAVE 0x100 /* when text is on the heap before setvareq */
1460 # define VDYNAMIC 0x200 /* dynamic variable */
1466 struct var *next; /* next entry in hash list */
1467 int flags; /* flags are defined above */
1468 const char *text; /* name=value */
1469 void (*func)(const char *); /* function to be called when */
1470 /* the variable gets set/unset */
1474 struct localvar *next; /* next local variable in list */
1475 struct var *vp; /* the variable that was made local */
1476 int flags; /* saved flags */
1477 const char *text; /* saved text */
1481 static struct localvar *localvars;
1487 #ifdef CONFIG_ASH_GETOPTS
1488 static void getoptsreset(const char *);
1491 #ifdef CONFIG_LOCALE_SUPPORT
1493 static void change_lc_all(const char *value);
1494 static void change_lc_ctype(const char *value);
1500 static const char defpathvar[] = "PATH=/usr/local/bin:/usr/bin:/sbin:/bin";
1502 static const char defifsvar[] = "IFS= \t\n";
1503 #define defifs (defifsvar + 4)
1505 static const char defifs[] = " \t\n";
1509 static struct var varinit[] = {
1511 { 0, VSTRFIXED|VTEXTFIXED, defifsvar, 0 },
1513 { 0, VSTRFIXED|VTEXTFIXED|VUNSET, "IFS\0", 0 },
1516 #ifdef CONFIG_ASH_MAIL
1517 { 0, VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL\0", changemail },
1518 { 0, VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH\0", changemail },
1521 { 0, VSTRFIXED|VTEXTFIXED, defpathvar, changepath },
1522 { 0, VSTRFIXED|VTEXTFIXED, "PS1=$ ", 0 },
1523 { 0, VSTRFIXED|VTEXTFIXED, "PS2=> ", 0 },
1524 { 0, VSTRFIXED|VTEXTFIXED, "PS4=+ ", 0 },
1525 #ifdef CONFIG_ASH_GETOPTS
1526 { 0, VSTRFIXED|VTEXTFIXED, "OPTIND=1", getoptsreset },
1528 #ifdef CONFIG_ASH_RANDOM_SUPPORT
1529 {0, VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM\0", change_random },
1531 #ifdef CONFIG_LOCALE_SUPPORT
1532 {0, VSTRFIXED | VTEXTFIXED | VUNSET, "LC_ALL\0", change_lc_all },
1533 {0, VSTRFIXED | VTEXTFIXED | VUNSET, "LC_CTYPE\0", change_lc_ctype },
1535 #ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
1536 {0, VSTRFIXED | VTEXTFIXED | VUNSET, "HISTFILE\0", NULL },
1540 #define vifs varinit[0]
1541 #ifdef CONFIG_ASH_MAIL
1542 #define vmail (&vifs)[1]
1543 #define vmpath (&vmail)[1]
1547 #define vpath (&vmpath)[1]
1548 #define vps1 (&vpath)[1]
1549 #define vps2 (&vps1)[1]
1550 #define vps4 (&vps2)[1]
1551 #define voptind (&vps4)[1]
1552 #ifdef CONFIG_ASH_GETOPTS
1553 #define vrandom (&voptind)[1]
1555 #define vrandom (&vps4)[1]
1557 #define defpath (defpathvar + 5)
1560 * The following macros access the values of the above variables.
1561 * They have to skip over the name. They return the null string
1562 * for unset variables.
1565 #define ifsval() (vifs.text + 4)
1566 #define ifsset() ((vifs.flags & VUNSET) == 0)
1567 #define mailval() (vmail.text + 5)
1568 #define mpathval() (vmpath.text + 9)
1569 #define pathval() (vpath.text + 5)
1570 #define ps1val() (vps1.text + 4)
1571 #define ps2val() (vps2.text + 4)
1572 #define ps4val() (vps4.text + 4)
1573 #define optindval() (voptind.text + 7)
1575 #define mpathset() ((vmpath.flags & VUNSET) == 0)
1577 static void setvar(const char *, const char *, int);
1578 static void setvareq(char *, int);
1579 static void listsetvar(struct strlist *, int);
1580 static char *lookupvar(const char *);
1581 static char *bltinlookup(const char *);
1582 static char **listvars(int, int, char ***);
1583 #define environment() listvars(VEXPORT, VUNSET, 0)
1584 static int showvars(const char *, int, int);
1585 static void poplocalvars(void);
1586 static int unsetvar(const char *);
1587 #ifdef CONFIG_ASH_GETOPTS
1588 static int setvarsafe(const char *, const char *, int);
1590 static int varcmp(const char *, const char *);
1591 static struct var **hashvar(const char *);
1594 static inline int varequal(const char *a, const char *b) {
1595 return !varcmp(a, b);
1599 static int loopnest; /* current loop nesting level */
1602 * The parsefile structure pointed to by the global variable parsefile
1603 * contains information about the current file being read.
1608 struct redirtab *next;
1613 static struct redirtab *redirlist;
1614 static int nullredirs;
1616 extern char **environ;
1621 static void outstr(const char *, FILE *);
1622 static void outcslow(int, FILE *);
1623 static void flushall(void);
1624 static void flusherr(void);
1625 static int out1fmt(const char *, ...)
1626 __attribute__((__format__(__printf__,1,2)));
1627 static int fmtstr(char *, size_t, const char *, ...)
1628 __attribute__((__format__(__printf__,3,4)));
1630 static int preverrout_fd; /* save fd2 before print debug if xflag is set. */
1633 static void out1str(const char *p)
1638 static void out2str(const char *p)
1645 * Initialization code.
1649 * This routine initializes the builtin variables.
1660 * PS1 depends on uid
1662 #if defined(CONFIG_FEATURE_COMMAND_EDITING) && defined(CONFIG_FEATURE_SH_FANCY_PROMPT)
1663 vps1.text = "PS1=\\w \\$ ";
1666 vps1.text = "PS1=# ";
1669 end = vp + sizeof(varinit) / sizeof(varinit[0]);
1671 vpp = hashvar(vp->text);
1674 } while (++vp < end);
1683 basepf.nextc = basepf.buf = basebuf;
1688 signal(SIGCHLD, SIG_DFL);
1696 struct stat st1, st2;
1699 for (envp = environ ; envp && *envp ; envp++) {
1700 if (strchr(*envp, '=')) {
1701 setvareq(*envp, VEXPORT|VTEXTFIXED);
1705 snprintf(ppid, sizeof(ppid), "%d", (int) getppid());
1706 setvar("PPID", ppid, 0);
1708 p = lookupvar("PWD");
1710 if (*p != '/' || stat(p, &st1) || stat(".", &st2) ||
1711 st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino)
1717 /* PEOF (the end of file marker) */
1720 INPUT_PUSH_FILE = 1,
1721 INPUT_NOFILE_OK = 2,
1725 * The input line number. Input.c just defines this variable, and saves
1726 * and restores it when files are pushed and popped. The user of this
1727 * package must set its value.
1730 static int pgetc(void);
1731 static int pgetc2(void);
1732 static int preadbuffer(void);
1733 static void pungetc(void);
1734 static void pushstring(char *, void *);
1735 static void popstring(void);
1736 static void setinputfd(int, int);
1737 static void setinputstring(char *);
1738 static void popfile(void);
1739 static void popallfiles(void);
1740 static void closescript(void);
1746 /* Mode argument to forkshell. Don't change FORK_FG or FORK_BG. */
1749 #define FORK_NOJOB 2
1751 /* mode flags for showjob(s) */
1752 #define SHOW_PGID 0x01 /* only show pgid - for jobs -p */
1753 #define SHOW_PID 0x04 /* include process pid */
1754 #define SHOW_CHANGED 0x08 /* only jobs whose state has changed */
1758 * A job structure contains information about a job. A job is either a
1759 * single process or a set of processes contained in a pipeline. In the
1760 * latter case, pidlist will be non-NULL, and will point to a -1 terminated
1765 pid_t pid; /* process id */
1766 int status; /* last process status from wait() */
1767 char *cmd; /* text of command being run */
1771 struct procstat ps0; /* status of process */
1772 struct procstat *ps; /* status or processes when more than one */
1774 int stopstatus; /* status of a stopped job */
1777 nprocs: 16, /* number of processes */
1779 #define JOBRUNNING 0 /* at least one proc running */
1780 #define JOBSTOPPED 1 /* all procs are stopped */
1781 #define JOBDONE 2 /* all procs are completed */
1783 sigint: 1, /* job was killed by SIGINT */
1784 jobctl: 1, /* job running under job control */
1786 waited: 1, /* true if this entry has been waited for */
1787 used: 1, /* true if this entry is in used */
1788 changed: 1; /* true if status has changed */
1789 struct job *prev_job; /* previous job */
1792 static pid_t backgndpid; /* pid of last background process */
1793 static int job_warning; /* user was warned about stopped jobs */
1795 static int jobctl; /* true if doing job control */
1798 static struct job *makejob(union node *, int);
1799 static int forkshell(struct job *, union node *, int);
1800 static int waitforjob(struct job *);
1801 static int stoppedjobs(void);
1804 #define setjobctl(on) /* do nothing */
1806 static void setjobctl(int);
1807 static void showjobs(FILE *, int);
1813 /* pid of main shell */
1815 /* shell level: 0 for the main shell, 1 for its children, and so on */
1817 #define rootshell (!shlvl)
1819 static void readcmdfile(char *);
1820 static int cmdloop(int);
1826 struct stack_block *stackp;
1829 struct stackmark *marknext;
1832 /* minimum size of a block */
1833 #define MINSIZE SHELL_ALIGN(504)
1835 struct stack_block {
1836 struct stack_block *prev;
1837 char space[MINSIZE];
1840 static struct stack_block stackbase;
1841 static struct stack_block *stackp = &stackbase;
1842 static struct stackmark *markp;
1843 static char *stacknxt = stackbase.space;
1844 static size_t stacknleft = MINSIZE;
1845 static char *sstrend = stackbase.space + MINSIZE;
1846 static int herefd = -1;
1849 static pointer ckmalloc(size_t);
1850 static pointer ckrealloc(pointer, size_t);
1851 static char *savestr(const char *);
1852 static pointer stalloc(size_t);
1853 static void stunalloc(pointer);
1854 static void setstackmark(struct stackmark *);
1855 static void popstackmark(struct stackmark *);
1856 static void growstackblock(void);
1857 static void *growstackstr(void);
1858 static char *makestrspace(size_t, char *);
1859 static char *stnputs(const char *, size_t, char *);
1860 static char *stputs(const char *, char *);
1863 static inline char *_STPUTC(int c, char *p) {
1870 #define stackblock() ((void *)stacknxt)
1871 #define stackblocksize() stacknleft
1872 #define STARTSTACKSTR(p) ((p) = stackblock())
1873 #define STPUTC(c, p) ((p) = _STPUTC((c), (p)))
1874 #define CHECKSTRSPACE(n, p) \
1878 size_t m = sstrend - q; \
1880 (p) = makestrspace(l, q); \
1883 #define USTPUTC(c, p) (*p++ = (c))
1884 #define STACKSTRNUL(p) ((p) == sstrend? (p = growstackstr(), *p = '\0') : (*p = '\0'))
1885 #define STUNPUTC(p) (--p)
1886 #define STTOPC(p) p[-1]
1887 #define STADJUST(amount, p) (p += (amount))
1889 #define grabstackstr(p) stalloc((char *)(p) - (char *)stackblock())
1890 #define ungrabstackstr(s, p) stunalloc((s))
1891 #define stackstrend() ((void *)sstrend)
1893 #define ckfree(p) free((pointer)(p))
1898 #define DOLATSTRLEN 4
1900 static char *prefix(const char *, const char *);
1901 static int number(const char *);
1902 static int is_number(const char *);
1903 static char *single_quote(const char *);
1904 static char *sstrdup(const char *);
1906 #define equal(s1, s2) (strcmp(s1, s2) == 0)
1907 #define scopy(s1, s2) ((void)strcpy(s2, s1))
1912 int nparam; /* # of positional parameters (without $0) */
1913 unsigned char malloc; /* if parameter list dynamically allocated */
1914 char **p; /* parameter list */
1915 #ifdef CONFIG_ASH_GETOPTS
1916 int optind; /* next parameter to be processed by getopts */
1917 int optoff; /* used by getopts */
1922 #define eflag optlist[0]
1923 #define fflag optlist[1]
1924 #define Iflag optlist[2]
1925 #define iflag optlist[3]
1926 #define mflag optlist[4]
1927 #define nflag optlist[5]
1928 #define sflag optlist[6]
1929 #define xflag optlist[7]
1930 #define vflag optlist[8]
1931 #define Cflag optlist[9]
1932 #define aflag optlist[10]
1933 #define bflag optlist[11]
1934 #define uflag optlist[12]
1935 #define viflag optlist[13]
1938 #define nolog optlist[14]
1939 #define debug optlist[15]
1942 #ifndef CONFIG_FEATURE_COMMAND_EDITING_VI
1943 #define setvimode(on) viflag = 0 /* forcibly keep the option off */
1949 static const char *const optletters_optnames[] = {
1970 #define optletters(n) optletters_optnames[(n)][0]
1971 #define optnames(n) (&optletters_optnames[(n)][1])
1973 #define NOPTS (sizeof(optletters_optnames)/sizeof(optletters_optnames[0]))
1975 static char optlist[NOPTS];
1978 static char *arg0; /* value of $0 */
1979 static struct shparam shellparam; /* $@ current positional parameters */
1980 static char **argptr; /* argument list for builtin commands */
1981 static char *optionarg; /* set by nextopt (like getopt) */
1982 static char *optptr; /* used by nextopt */
1984 static char *minusc; /* argument to -c option */
1987 static void procargs(int, char **);
1988 static void optschanged(void);
1989 static void setparam(char **);
1990 static void freeparam(volatile struct shparam *);
1991 static int shiftcmd(int, char **);
1992 static int setcmd(int, char **);
1993 static int nextopt(const char *);
1997 /* flags passed to redirect */
1998 #define REDIR_PUSH 01 /* save previous values of file descriptors */
1999 #define REDIR_SAVEFD2 03 /* set preverrout */
2002 static void redirect(union node *, int);
2003 static void popredir(int);
2004 static void clearredir(int);
2005 static int copyfd(int, int);
2006 static int redirectsafe(union node *, int);
2012 static void showtree(union node *);
2013 static void trace(const char *, ...);
2014 static void tracev(const char *, va_list);
2015 static void trargs(char **);
2016 static void trputc(int);
2017 static void trputs(const char *);
2018 static void opentrace(void);
2024 /* trap handler commands */
2025 static char *trap[NSIG];
2026 /* current value of signal */
2027 static char sigmode[NSIG - 1];
2028 /* indicates specified signal received */
2029 static char gotsig[NSIG - 1];
2031 static void clear_traps(void);
2032 static void setsignal(int);
2033 static void ignoresig(int);
2034 static void onsig(int);
2035 static int dotrap(void);
2036 static void setinteractive(int);
2037 static void exitshell(void) ATTRIBUTE_NORETURN;
2040 * This routine is called when an error or an interrupt occurs in an
2041 * interactive shell and control is returned to the main command loop.
2055 parselleft = parsenleft = 0; /* clear input buffer */
2059 /* from parser.c: */
2072 #ifdef CONFIG_ASH_ALIAS
2073 static struct alias *atab[ATABSIZE];
2075 static void setalias(const char *, const char *);
2076 static struct alias *freealias(struct alias *);
2077 static struct alias **__lookupalias(const char *);
2080 setalias(const char *name, const char *val)
2082 struct alias *ap, **app;
2084 app = __lookupalias(name);
2088 if (!(ap->flag & ALIASINUSE)) {
2091 ap->val = savestr(val);
2092 ap->flag &= ~ALIASDEAD;
2095 ap = ckmalloc(sizeof (struct alias));
2096 ap->name = savestr(name);
2097 ap->val = savestr(val);
2106 unalias(const char *name)
2110 app = __lookupalias(name);
2114 *app = freealias(*app);
2125 struct alias *ap, **app;
2129 for (i = 0; i < ATABSIZE; i++) {
2131 for (ap = *app; ap; ap = *app) {
2132 *app = freealias(*app);
2141 static struct alias *
2142 lookupalias(const char *name, int check)
2144 struct alias *ap = *__lookupalias(name);
2146 if (check && ap && (ap->flag & ALIASINUSE))
2152 * TODO - sort output
2155 aliascmd(int argc, char **argv)
2164 for (i = 0; i < ATABSIZE; i++)
2165 for (ap = atab[i]; ap; ap = ap->next) {
2170 while ((n = *++argv) != NULL) {
2171 if ((v = strchr(n+1, '=')) == NULL) { /* n+1: funny ksh stuff */
2172 if ((ap = *__lookupalias(n)) == NULL) {
2173 fprintf(stderr, "%s: %s not found\n", "alias", n);
2187 unaliascmd(int argc, char **argv)
2191 while ((i = nextopt("a")) != '\0') {
2197 for (i = 0; *argptr; argptr++) {
2198 if (unalias(*argptr)) {
2199 fprintf(stderr, "%s: %s not found\n", "unalias", *argptr);
2207 static struct alias *
2208 freealias(struct alias *ap) {
2211 if (ap->flag & ALIASINUSE) {
2212 ap->flag |= ALIASDEAD;
2224 printalias(const struct alias *ap) {
2225 out1fmt("%s=%s\n", ap->name, single_quote(ap->val));
2228 static struct alias **
2229 __lookupalias(const char *name) {
2230 unsigned int hashval;
2237 ch = (unsigned char)*p;
2241 ch = (unsigned char)*++p;
2243 app = &atab[hashval % ATABSIZE];
2245 for (; *app; app = &(*app)->next) {
2246 if (equal(name, (*app)->name)) {
2253 #endif /* CONFIG_ASH_ALIAS */
2259 * The cd and pwd commands.
2262 #define CD_PHYSICAL 1
2265 static int docd(const char *, int);
2266 static int cdopt(void);
2268 static char *curdir = nullstr; /* current working directory */
2269 static char *physdir = nullstr; /* physical working directory */
2278 while ((i = nextopt("LP"))) {
2280 flags ^= CD_PHYSICAL;
2289 cdcmd(int argc, char **argv)
2301 dest = bltinlookup(homestr);
2302 else if (dest[0] == '-' && dest[1] == '\0') {
2303 dest = bltinlookup("OLDPWD");
2325 if (!(path = bltinlookup("CDPATH"))) {
2333 p = padvance(&path, dest);
2334 if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
2338 if (!docd(p, flags))
2343 sh_error("can't cd to %s", dest);
2346 if (flags & CD_PRINT)
2347 out1fmt(snlfmt, curdir);
2353 * Update curdir (the name of the current directory) in response to a
2357 static inline const char *
2358 updatepwd(const char *dir)
2365 cdcomppath = sstrdup(dir);
2368 if (curdir == nullstr)
2370 new = stputs(curdir, new);
2372 new = makestrspace(strlen(dir) + 2, new);
2373 lim = stackblock() + 1;
2377 if (new > lim && *lim == '/')
2382 if (dir[1] == '/' && dir[2] != '/') {
2388 p = strtok(cdcomppath, "/");
2392 if (p[1] == '.' && p[2] == '\0') {
2399 } else if (p[1] == '\0')
2403 new = stputs(p, new);
2411 return stackblock();
2415 * Actually do the chdir. We also call hashcd to let the routines in exec.c
2416 * know that the current directory has changed.
2420 docd(const char *dest, int flags)
2422 const char *dir = 0;
2425 TRACE(("docd(\"%s\", %d) called\n", dest, flags));
2428 if (!(flags & CD_PHYSICAL)) {
2429 dir = updatepwd(dest);
2444 * Find out what the current directory is. If we already know the current
2445 * directory, this routine returns immediately.
2447 static inline char *
2450 char *dir = getcwd(0, 0);
2451 return dir ? dir : nullstr;
2455 pwdcmd(int argc, char **argv)
2458 const char *dir = curdir;
2462 if (physdir == nullstr)
2466 out1fmt(snlfmt, dir);
2471 setpwd(const char *val, int setold)
2475 oldcur = dir = curdir;
2478 setvar("OLDPWD", oldcur, VEXPORT);
2481 if (physdir != nullstr) {
2482 if (physdir != oldcur)
2486 if (oldcur == val || !val) {
2493 if (oldcur != dir && oldcur != nullstr) {
2498 setvar("PWD", dir, VEXPORT);
2504 * Errors and exceptions.
2508 * Code to handle exceptions in C.
2513 static void exverror(int, const char *, va_list)
2517 * Called to raise an exception. Since C doesn't include exceptions, we
2518 * just do a longjmp to the exception handler. The type of exception is
2519 * stored in the global variable "exception".
2526 if (handler == NULL)
2532 longjmp(handler->loc, 1);
2537 * Called from trap.c when a SIGINT is received. (If the user specifies
2538 * that SIGINT is to be trapped or ignored using the trap builtin, then
2539 * this routine is not called.) Suppressint is nonzero when interrupts
2540 * are held using the INTOFF macro. (The test for iflag is just
2541 * defensive programming.)
2550 if (gotsig[SIGINT - 1] && !trap[SIGINT]) {
2551 if (!(rootshell && iflag)) {
2552 signal(SIGINT, SIG_DFL);
2562 exvwarning(const char *msg, va_list ap)
2567 fprintf(errs, "%s: ", arg0);
2569 const char *fmt = (!iflag || parsefile->fd) ?
2570 "%s: %d: " : "%s: ";
2571 fprintf(errs, fmt, commandname, startlinno);
2573 vfprintf(errs, msg, ap);
2574 outcslow('\n', errs);
2578 * Exverror is called to raise the error exception. If the second argument
2579 * is not NULL then error prints an error message using printf style
2580 * formatting. It then raises the error exception.
2583 exverror(int cond, const char *msg, va_list ap)
2587 TRACE(("exverror(%d, \"", cond));
2589 TRACE(("\") pid=%d\n", getpid()));
2591 TRACE(("exverror(%d, NULL) pid=%d\n", cond, getpid()));
2594 exvwarning(msg, ap);
2603 sh_error(const char *msg, ...)
2608 exverror(EXERROR, msg, ap);
2615 exerror(int cond, const char *msg, ...)
2620 exverror(cond, msg, ap);
2626 * error/warning routines for external builtins
2630 sh_warnx(const char *fmt, ...)
2635 exvwarning(fmt, ap);
2641 * Return a string describing an error. The returned string may be a
2642 * pointer to a static buffer that will be overwritten on the next call.
2643 * Action describes the operation that got the error.
2647 errmsg(int e, const char *em)
2649 if(e == ENOENT || e == ENOTDIR) {
2660 * Evaluate a command.
2663 /* flags in argument to evaltree */
2664 #define EV_EXIT 01 /* exit after evaluating tree */
2665 #define EV_TESTED 02 /* exit status is checked; ignore -e flag */
2666 #define EV_BACKCMD 04 /* command executing within back quotes */
2669 static void evalloop(union node *, int);
2670 static void evalfor(union node *, int);
2671 static void evalcase(union node *, int);
2672 static void evalsubshell(union node *, int);
2673 static void expredir(union node *);
2674 static void evalpipe(union node *, int);
2675 static void evalcommand(union node *, int);
2676 static int evalbltin(const struct builtincmd *, int, char **);
2677 static int evalfun(struct funcnode *, int, char **, int);
2678 static void prehash(union node *);
2679 static int bltincmd(int, char **);
2682 static const struct builtincmd bltin = {
2688 * Called to reset things after an exception.
2696 evalcmd(int argc, char **argv)
2705 STARTSTACKSTR(concat);
2708 concat = stputs(p, concat);
2709 if ((p = *ap++) == NULL)
2711 STPUTC(' ', concat);
2713 STPUTC('\0', concat);
2714 p = grabstackstr(concat);
2716 evalstring(p, ~SKIPEVAL);
2724 * Execute a command or commands contained in a string.
2728 evalstring(char *s, int mask)
2731 struct stackmark smark;
2735 setstackmark(&smark);
2738 while ((n = parsecmd(0)) != NEOF) {
2740 popstackmark(&smark);
2755 * Evaluate a parse tree. The value is left in the global variable
2760 evaltree(union node *n, int flags)
2763 void (*evalfn)(union node *, int);
2767 TRACE(("evaltree(NULL) called\n"));
2770 TRACE(("pid %d, evaltree(%p: %d, %d) called\n",
2771 getpid(), n, n->type, flags));
2775 out1fmt("Node type = %d\n", n->type);
2780 evaltree(n->nnot.com, EV_TESTED);
2781 status = !exitstatus;
2784 expredir(n->nredir.redirect);
2785 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
2787 evaltree(n->nredir.n, flags & EV_TESTED);
2788 status = exitstatus;
2793 evalfn = evalcommand;
2795 if (eflag && !(flags & EV_TESTED))
2807 evalfn = evalsubshell;
2819 #error NAND + 1 != NOR
2821 #if NOR + 1 != NSEMI
2822 #error NOR + 1 != NSEMI
2824 isor = n->type - NAND;
2827 (flags | ((isor >> 1) - 1)) & EV_TESTED
2829 if (!exitstatus == isor)
2841 evaltree(n->nif.test, EV_TESTED);
2844 if (exitstatus == 0) {
2847 } else if (n->nif.elsepart) {
2848 n = n->nif.elsepart;
2853 defun(n->narg.text, n->narg.next);
2857 exitstatus = status;
2861 if ((checkexit & exitstatus))
2862 evalskip |= SKIPEVAL;
2863 else if (pendingsigs && dotrap())
2866 if (flags & EV_EXIT) {
2873 #if !defined(__alpha__) || (defined(__GNUC__) && __GNUC__ >= 3)
2876 void evaltreenr(union node *, int) __attribute__ ((alias("evaltree"),__noreturn__));
2880 evalloop(union node *n, int flags)
2890 evaltree(n->nbinary.ch1, EV_TESTED);
2892 skipping: if (evalskip == SKIPCONT && --skipcount <= 0) {
2896 if (evalskip == SKIPBREAK && --skipcount <= 0)
2901 if (n->type != NWHILE)
2905 evaltree(n->nbinary.ch2, flags);
2906 status = exitstatus;
2911 exitstatus = status;
2917 evalfor(union node *n, int flags)
2919 struct arglist arglist;
2922 struct stackmark smark;
2924 setstackmark(&smark);
2925 arglist.lastp = &arglist.list;
2926 for (argp = n->nfor.args ; argp ; argp = argp->narg.next) {
2927 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE | EXP_RECORD);
2932 *arglist.lastp = NULL;
2937 for (sp = arglist.list ; sp ; sp = sp->next) {
2938 setvar(n->nfor.var, sp->text, 0);
2939 evaltree(n->nfor.body, flags);
2941 if (evalskip == SKIPCONT && --skipcount <= 0) {
2945 if (evalskip == SKIPBREAK && --skipcount <= 0)
2952 popstackmark(&smark);
2958 evalcase(union node *n, int flags)
2962 struct arglist arglist;
2963 struct stackmark smark;
2965 setstackmark(&smark);
2966 arglist.lastp = &arglist.list;
2967 expandarg(n->ncase.expr, &arglist, EXP_TILDE);
2969 for (cp = n->ncase.cases ; cp && evalskip == 0 ; cp = cp->nclist.next) {
2970 for (patp = cp->nclist.pattern ; patp ; patp = patp->narg.next) {
2971 if (casematch(patp, arglist.list->text)) {
2972 if (evalskip == 0) {
2973 evaltree(cp->nclist.body, flags);
2980 popstackmark(&smark);
2986 * Kick off a subshell to evaluate a tree.
2990 evalsubshell(union node *n, int flags)
2993 int backgnd = (n->type == NBACKGND);
2996 expredir(n->nredir.redirect);
2997 if (!backgnd && flags & EV_EXIT && !trap[0])
3001 if (forkshell(jp, n, backgnd) == 0) {
3005 flags &=~ EV_TESTED;
3007 redirect(n->nredir.redirect, 0);
3008 evaltreenr(n->nredir.n, flags);
3013 status = waitforjob(jp);
3014 exitstatus = status;
3021 * Compute the names of the files in a redirection list.
3025 expredir(union node *n)
3029 for (redir = n ; redir ; redir = redir->nfile.next) {
3031 fn.lastp = &fn.list;
3032 switch (redir->type) {
3038 expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
3039 redir->nfile.expfname = fn.list->text;
3043 if (redir->ndup.vname) {
3044 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
3045 fixredir(redir, fn.list->text, 1);
3055 * Evaluate a pipeline. All the processes in the pipeline are children
3056 * of the process creating the pipeline. (This differs from some versions
3057 * of the shell, which make the last process in a pipeline the parent
3062 evalpipe(union node *n, int flags)
3065 struct nodelist *lp;
3070 TRACE(("evalpipe(0x%lx) called\n", (long)n));
3072 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next)
3076 jp = makejob(n, pipelen);
3078 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
3082 if (pipe(pip) < 0) {
3084 sh_error("Pipe call failed");
3087 if (forkshell(jp, lp->n, n->npipe.backgnd) == 0) {
3100 evaltreenr(lp->n, flags);
3108 if (n->npipe.backgnd == 0) {
3109 exitstatus = waitforjob(jp);
3110 TRACE(("evalpipe: job done exit status %d\n", exitstatus));
3118 * Execute a command inside back quotes. If it's a builtin command, we
3119 * want to save its output in a block obtained from malloc. Otherwise
3120 * we fork off a subprocess and get the output of the command via a pipe.
3121 * Should be called with interrupts off.
3125 evalbackcmd(union node *n, struct backcmd *result)
3137 saveherefd = herefd;
3145 sh_error("Pipe call failed");
3147 if (forkshell(jp, n, FORK_NOJOB) == 0) {
3156 evaltreenr(n, EV_EXIT);
3160 result->fd = pip[0];
3163 herefd = saveherefd;
3165 TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
3166 result->fd, result->buf, result->nleft, result->jp));
3169 #ifdef CONFIG_ASH_CMDCMD
3170 static inline char **
3171 parse_command_args(char **argv, const char **path)
3183 if (c == '-' && !*cp) {
3193 /* run 'typecmd' for other options */
3196 } while ((c = *cp++));
3203 isassignment(const char *p)
3205 const char *q = endofname(p);
3211 #ifdef CONFIG_ASH_EXPAND_PRMT
3212 static const char *expandstr(const char *ps);
3214 #define expandstr(s) s
3218 * Execute a simple command.
3222 evalcommand(union node *cmd, int flags)
3224 struct stackmark smark;
3226 struct arglist arglist;
3227 struct arglist varlist;
3230 const struct strlist *sp;
3231 struct cmdentry cmdentry;
3239 struct builtincmd *bcmd;
3240 int pseudovarflag = 0;
3242 /* First expand the arguments. */
3243 TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
3244 setstackmark(&smark);
3245 back_exitstatus = 0;
3247 cmdentry.cmdtype = CMDBUILTIN;
3248 cmdentry.u.cmd = &bltin;
3249 varlist.lastp = &varlist.list;
3250 *varlist.lastp = NULL;
3251 arglist.lastp = &arglist.list;
3252 *arglist.lastp = NULL;
3257 bcmd = find_builtin(cmd->ncmd.args->narg.text);
3258 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
3261 for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
3262 struct strlist **spp;
3264 spp = arglist.lastp;
3265 if (pseudovarflag && isassignment(argp->narg.text))
3266 expandarg(argp, &arglist, EXP_VARTILDE);
3268 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
3270 for (sp = *spp; sp; sp = sp->next)
3274 argv = nargv = stalloc(sizeof (char *) * (argc + 1));
3275 for (sp = arglist.list ; sp ; sp = sp->next) {
3276 TRACE(("evalcommand arg: %s\n", sp->text));
3277 *nargv++ = sp->text;
3282 if (iflag && funcnest == 0 && argc > 0)
3283 lastarg = nargv[-1];
3286 expredir(cmd->ncmd.redirect);
3287 status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH|REDIR_SAVEFD2);
3290 for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
3291 struct strlist **spp;
3294 spp = varlist.lastp;
3295 expandarg(argp, &varlist, EXP_VARTILDE);
3298 * Modify the command lookup path, if a PATH= assignment
3302 if (varequal(p, path))
3306 /* Print the command if xflag is set. */
3309 const char *p = " %s";
3312 dprintf(preverrout_fd, p, expandstr(ps4val()));
3315 for(n = 0; n < 2; n++) {
3317 dprintf(preverrout_fd, p, sp->text);
3325 full_write(preverrout_fd, "\n", 1);
3331 /* Now locate the command. */
3333 const char *oldpath;
3334 int cmd_flag = DO_ERR;
3339 find_command(argv[0], &cmdentry, cmd_flag, path);
3340 if (cmdentry.cmdtype == CMDUNKNOWN) {
3346 /* implement bltin and command here */
3347 if (cmdentry.cmdtype != CMDBUILTIN)
3350 spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
3351 if (cmdentry.u.cmd == EXECCMD)
3353 #ifdef CONFIG_ASH_CMDCMD
3354 if (cmdentry.u.cmd == COMMANDCMD) {
3357 nargv = parse_command_args(argv, &path);
3360 argc -= nargv - argv;
3362 cmd_flag |= DO_NOFUNC;
3370 /* We have a redirection error. */
3374 exitstatus = status;
3378 /* Execute the command. */
3379 switch (cmdentry.cmdtype) {
3381 /* Fork off a child process if necessary. */
3382 if (!(flags & EV_EXIT) || trap[0]) {
3384 jp = makejob(cmd, 1);
3385 if (forkshell(jp, cmd, FORK_FG) != 0) {
3386 exitstatus = waitforjob(jp);
3392 listsetvar(varlist.list, VEXPORT|VSTACK);
3393 shellexec(argv, path, cmdentry.u.index);
3397 cmdenviron = varlist.list;
3399 struct strlist *list = cmdenviron;
3401 if (spclbltin > 0 || argc == 0) {
3403 if (cmd_is_exec && argc > 1)
3406 listsetvar(list, i);
3408 if (evalbltin(cmdentry.u.cmd, argc, argv)) {
3423 exit_status = j + 128;
3424 exitstatus = exit_status;
3426 if (i == EXINT || spclbltin > 0) {
3428 longjmp(handler->loc, 1);
3435 listsetvar(varlist.list, 0);
3436 if (evalfun(cmdentry.u.func, argc, argv, flags))
3442 popredir(cmd_is_exec);
3444 /* dsl: I think this is intended to be used to support
3445 * '_' in 'vi' command mode during line editing...
3446 * However I implemented that within libedit itself.
3448 setvar("_", lastarg, 0);
3449 popstackmark(&smark);
3453 evalbltin(const struct builtincmd *cmd, int argc, char **argv) {
3454 char *volatile savecmdname;
3455 struct jmploc *volatile savehandler;
3456 struct jmploc jmploc;
3459 savecmdname = commandname;
3460 if ((i = setjmp(jmploc.loc)))
3462 savehandler = handler;
3464 commandname = argv[0];
3466 optptr = NULL; /* initialize nextopt */
3467 exitstatus = (*cmd->builtin)(argc, argv);
3470 exitstatus |= ferror(stdout);
3472 commandname = savecmdname;
3474 handler = savehandler;
3480 evalfun(struct funcnode *func, int argc, char **argv, int flags)
3482 volatile struct shparam saveparam;
3483 struct localvar *volatile savelocalvars;
3484 struct jmploc *volatile savehandler;
3485 struct jmploc jmploc;
3488 saveparam = shellparam;
3489 savelocalvars = localvars;
3490 if ((e = setjmp(jmploc.loc))) {
3494 savehandler = handler;
3497 shellparam.malloc = 0;
3501 shellparam.nparam = argc - 1;
3502 shellparam.p = argv + 1;
3503 #ifdef CONFIG_ASH_GETOPTS
3504 shellparam.optind = 1;
3505 shellparam.optoff = -1;
3507 evaltree(&func->n, flags & EV_TESTED);
3513 localvars = savelocalvars;
3514 freeparam(&shellparam);
3515 shellparam = saveparam;
3516 handler = savehandler;
3518 evalskip &= ~SKIPFUNC;
3524 goodname(const char *p)
3526 return !*endofname(p);
3530 * Search for a command. This is called before we fork so that the
3531 * location of the command will be available in the parent as well as
3532 * the child. The check for "goodname" is an overly conservative
3533 * check that the name will not be subject to expansion.
3537 prehash(union node *n)
3539 struct cmdentry entry;
3541 if (n->type == NCMD && n->ncmd.args)
3542 if (goodname(n->ncmd.args->narg.text))
3543 find_command(n->ncmd.args->narg.text, &entry, 0,
3550 * Builtin commands. Builtin commands whose functions are closely
3551 * tied to evaluation are implemented here.
3559 bltincmd(int argc, char **argv)
3562 * Preserve exitstatus of a previous possible redirection
3565 return back_exitstatus;
3570 * Handle break and continue commands. Break, continue, and return are
3571 * all handled by setting the evalskip flag. The evaluation routines
3572 * above all check this flag, and if it is set they start skipping
3573 * commands rather than executing them. The variable skipcount is
3574 * the number of loops to break/continue, or the number of function
3575 * levels to return. (The latter is always 1.) It should probably
3576 * be an error to break out of more loops than exist, but it isn't
3577 * in the standard shell so we don't make it one here.
3581 breakcmd(int argc, char **argv)
3583 int n = argc > 1 ? number(argv[1]) : 1;
3586 sh_error(illnum, argv[1]);
3590 evalskip = (**argv == 'c')? SKIPCONT : SKIPBREAK;
3598 * The return command.
3602 returncmd(int argc, char **argv)
3605 * If called outside a function, do what ksh does;
3606 * skip the rest of the file.
3608 evalskip = funcnest ? SKIPFUNC : SKIPFILE;
3609 return argv[1] ? number(argv[1]) : exitstatus;
3614 falsecmd(int argc, char **argv)
3621 truecmd(int argc, char **argv)
3628 execcmd(int argc, char **argv)
3631 iflag = 0; /* exit on error */
3634 shellexec(argv + 1, pathval(), 0);
3643 * When commands are first encountered, they are entered in a hash table.
3644 * This ensures that a full path search will not have to be done for them
3645 * on each invocation.
3647 * We should investigate converting to a linear search, even though that
3648 * would make the command name "hash" a misnomer.
3651 #define CMDTABLESIZE 31 /* should be prime */
3652 #define ARB 1 /* actual size determined at run time */
3657 struct tblentry *next; /* next entry in hash chain */
3658 union param param; /* definition of builtin function */
3659 short cmdtype; /* index identifying command */
3660 char rehash; /* if set, cd done since entry created */
3661 char cmdname[ARB]; /* name of command */
3665 static struct tblentry *cmdtable[CMDTABLESIZE];
3666 static int builtinloc = -1; /* index in path of %builtin, or -1 */
3669 static void tryexec(char *, char **, char **);
3670 static void clearcmdentry(int);
3671 static struct tblentry *cmdlookup(const char *, int);
3672 static void delete_cmd_entry(void);
3676 * Exec a program. Never returns. If you change this routine, you may
3677 * have to change the find_command routine as well.
3681 shellexec(char **argv, const char *path, int idx)
3689 envp = environment();
3690 if (strchr(argv[0], '/') != NULL
3691 #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
3692 || find_applet_by_name(argv[0])
3695 tryexec(argv[0], argv, envp);
3699 while ((cmdname = padvance(&path, argv[0])) != NULL) {
3700 if (--idx < 0 && pathopt == NULL) {
3701 tryexec(cmdname, argv, envp);
3702 if (errno != ENOENT && errno != ENOTDIR)
3709 /* Map to POSIX errors */
3721 exitstatus = exerrno;
3722 TRACE(("shellexec failed for %s, errno %d, suppressint %d\n",
3723 argv[0], e, suppressint ));
3724 exerror(EXEXEC, "%s: %s", argv[0], errmsg(e, E_EXEC));
3730 tryexec(char *cmd, char **argv, char **envp)
3733 #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
3734 if(find_applet_by_name(cmd) != NULL) {
3735 /* re-exec ourselves with the new arguments */
3736 execve(CONFIG_BUSYBOX_EXEC_PATH,argv,envp);
3737 /* If they called chroot or otherwise made the binary no longer
3738 * executable, fall through */
3745 execve(cmd, argv, envp);
3746 } while (errno == EINTR);
3748 execve(cmd, argv, envp);
3752 } else if (errno == ENOEXEC) {
3756 for (ap = argv; *ap; ap++)
3758 ap = new = ckmalloc((ap - argv + 2) * sizeof(char *));
3760 *ap = cmd = (char *)DEFAULT_SHELL;
3763 while ((*ap++ = *argv++))
3773 * Do a path search. The variable path (passed by reference) should be
3774 * set to the start of the path before the first call; padvance will update
3775 * this value as it proceeds. Successive calls to padvance will return
3776 * the possible path expansions in sequence. If an option (indicated by
3777 * a percent sign) appears in the path entry then the global variable
3778 * pathopt will be set to point to it; otherwise pathopt will be set to
3783 padvance(const char **path, const char *name)
3793 for (p = start ; *p && *p != ':' && *p != '%' ; p++);
3794 len = p - start + strlen(name) + 2; /* "2" is for '/' and '\0' */
3795 while (stackblocksize() < len)
3799 memcpy(q, start, p - start);
3807 while (*p && *p != ':') p++;
3813 return stalloc(len);
3817 /*** Command hashing code ***/
3820 printentry(struct tblentry *cmdp)
3826 idx = cmdp->param.index;
3829 name = padvance(&path, cmdp->cmdname);
3831 } while (--idx >= 0);
3832 out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
3837 hashcmd(int argc, char **argv)
3839 struct tblentry **pp;
3840 struct tblentry *cmdp;
3842 struct cmdentry entry;
3845 while ((c = nextopt("r")) != '\0') {
3849 if (*argptr == NULL) {
3850 for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
3851 for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
3852 if (cmdp->cmdtype == CMDNORMAL)
3859 while ((name = *argptr) != NULL) {
3860 if ((cmdp = cmdlookup(name, 0)) != NULL
3861 && (cmdp->cmdtype == CMDNORMAL
3862 || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0)))
3864 find_command(name, &entry, DO_ERR, pathval());
3865 if (entry.cmdtype == CMDUNKNOWN)
3874 * Resolve a command name. If you change this routine, you may have to
3875 * change the shellexec routine as well.
3879 find_command(char *name, struct cmdentry *entry, int act, const char *path)
3881 struct tblentry *cmdp;
3888 struct builtincmd *bcmd;
3890 /* If name contains a slash, don't use PATH or hash table */
3891 if (strchr(name, '/') != NULL) {
3892 entry->u.index = -1;
3894 while (stat(name, &statb) < 0) {
3899 entry->cmdtype = CMDUNKNOWN;
3903 entry->cmdtype = CMDNORMAL;
3907 #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
3908 if (find_applet_by_name(name)) {
3909 entry->cmdtype = CMDNORMAL;
3910 entry->u.index = -1;
3915 updatetbl = (path == pathval());
3918 if (strstr(path, "%builtin") != NULL)
3922 /* If name is in the table, check answer will be ok */
3923 if ((cmdp = cmdlookup(name, 0)) != NULL) {
3926 switch (cmdp->cmdtype) {
3944 } else if (cmdp->rehash == 0)
3945 /* if not invalidated by cd, we're done */
3949 /* If %builtin not in path, check for builtin next */
3950 bcmd = find_builtin(name);
3951 if (bcmd && (IS_BUILTIN_REGULAR(bcmd) || (
3952 act & DO_ALTPATH ? !(act & DO_ALTBLTIN) : builtinloc <= 0
3954 goto builtin_success;
3956 /* We have to search path. */
3957 prev = -1; /* where to start */
3958 if (cmdp && cmdp->rehash) { /* doing a rehash */
3959 if (cmdp->cmdtype == CMDBUILTIN)
3962 prev = cmdp->param.index;
3968 while ((fullname = padvance(&path, name)) != NULL) {
3969 stunalloc(fullname);
3972 if (prefix(pathopt, "builtin")) {
3974 goto builtin_success;
3976 } else if (!(act & DO_NOFUNC) &&
3977 prefix(pathopt, "func")) {
3980 /* ignore unimplemented options */
3984 /* if rehash, don't redo absolute path names */
3985 if (fullname[0] == '/' && idx <= prev) {
3988 TRACE(("searchexec \"%s\": no change\n", name));
3991 while (stat(fullname, &statb) < 0) {
3996 if (errno != ENOENT && errno != ENOTDIR)
4000 e = EACCES; /* if we fail, this will be the error */
4001 if (!S_ISREG(statb.st_mode))
4003 if (pathopt) { /* this is a %func directory */
4004 stalloc(strlen(fullname) + 1);
4005 readcmdfile(fullname);
4006 if ((cmdp = cmdlookup(name, 0)) == NULL ||
4007 cmdp->cmdtype != CMDFUNCTION)
4008 sh_error("%s not defined in %s", name, fullname);
4009 stunalloc(fullname);
4012 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
4014 entry->cmdtype = CMDNORMAL;
4015 entry->u.index = idx;
4019 cmdp = cmdlookup(name, 1);
4020 cmdp->cmdtype = CMDNORMAL;
4021 cmdp->param.index = idx;
4026 /* We failed. If there was an entry for this command, delete it */
4027 if (cmdp && updatetbl)
4030 sh_warnx("%s: %s", name, errmsg(e, E_EXEC));
4031 entry->cmdtype = CMDUNKNOWN;
4036 entry->cmdtype = CMDBUILTIN;
4037 entry->u.cmd = bcmd;
4041 cmdp = cmdlookup(name, 1);
4042 cmdp->cmdtype = CMDBUILTIN;
4043 cmdp->param.cmd = bcmd;
4047 entry->cmdtype = cmdp->cmdtype;
4048 entry->u = cmdp->param;
4053 * Wrapper around strcmp for qsort/bsearch/...
4055 static int pstrcmp(const void *a, const void *b)
4057 return strcmp((const char *) a, (*(const char *const *) b) + 1);
4061 * Search the table of builtin commands.
4064 static struct builtincmd *
4065 find_builtin(const char *name)
4067 struct builtincmd *bp;
4070 name, builtincmd, NUMBUILTINS, sizeof(struct builtincmd),
4079 * Called when a cd is done. Marks all commands so the next time they
4080 * are executed they will be rehashed.
4086 struct tblentry **pp;
4087 struct tblentry *cmdp;
4089 for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
4090 for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
4091 if (cmdp->cmdtype == CMDNORMAL || (
4092 cmdp->cmdtype == CMDBUILTIN &&
4093 !(IS_BUILTIN_REGULAR(cmdp->param.cmd)) &&
4104 * Fix command hash table when PATH changed.
4105 * Called before PATH is changed. The argument is the new value of PATH;
4106 * pathval() still returns the old value at this point.
4107 * Called with interrupts off.
4111 changepath(const char *newval)
4113 const char *old, *new;
4120 firstchange = 9999; /* assume no change */
4126 if ((*old == '\0' && *new == ':')
4127 || (*old == ':' && *new == '\0'))
4129 old = new; /* ignore subsequent differences */
4133 if (*new == '%' && idx_bltin < 0 && prefix(new + 1, "builtin"))
4140 if (builtinloc < 0 && idx_bltin >= 0)
4141 builtinloc = idx_bltin; /* zap builtins */
4142 if (builtinloc >= 0 && idx_bltin < 0)
4144 clearcmdentry(firstchange);
4145 builtinloc = idx_bltin;
4150 * Clear out command entries. The argument specifies the first entry in
4151 * PATH which has changed.
4155 clearcmdentry(int firstchange)
4157 struct tblentry **tblp;
4158 struct tblentry **pp;
4159 struct tblentry *cmdp;
4162 for (tblp = cmdtable ; tblp < &cmdtable[CMDTABLESIZE] ; tblp++) {
4164 while ((cmdp = *pp) != NULL) {
4165 if ((cmdp->cmdtype == CMDNORMAL &&
4166 cmdp->param.index >= firstchange)
4167 || (cmdp->cmdtype == CMDBUILTIN &&
4168 builtinloc >= firstchange)) {
4182 * Locate a command in the command hash table. If "add" is nonzero,
4183 * add the command to the table if it is not already present. The
4184 * variable "lastcmdentry" is set to point to the address of the link
4185 * pointing to the entry, so that delete_cmd_entry can delete the
4188 * Interrupts must be off if called with add != 0.
4191 static struct tblentry **lastcmdentry;
4194 static struct tblentry *
4195 cmdlookup(const char *name, int add)
4197 unsigned int hashval;
4199 struct tblentry *cmdp;
4200 struct tblentry **pp;
4203 hashval = (unsigned char)*p << 4;
4205 hashval += (unsigned char)*p++;
4207 pp = &cmdtable[hashval % CMDTABLESIZE];
4208 for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
4209 if (equal(cmdp->cmdname, name))
4213 if (add && cmdp == NULL) {
4214 cmdp = *pp = ckmalloc(sizeof (struct tblentry) - ARB
4215 + strlen(name) + 1);
4217 cmdp->cmdtype = CMDUNKNOWN;
4218 strcpy(cmdp->cmdname, name);
4225 * Delete the command entry returned on the last lookup.
4229 delete_cmd_entry(void)
4231 struct tblentry *cmdp;
4234 cmdp = *lastcmdentry;
4235 *lastcmdentry = cmdp->next;
4236 if (cmdp->cmdtype == CMDFUNCTION)
4237 freefunc(cmdp->param.func);
4244 * Add a new command entry, replacing any existing command entry for
4245 * the same name - except special builtins.
4249 addcmdentry(char *name, struct cmdentry *entry)
4251 struct tblentry *cmdp;
4253 cmdp = cmdlookup(name, 1);
4254 if (cmdp->cmdtype == CMDFUNCTION) {
4255 freefunc(cmdp->param.func);
4257 cmdp->cmdtype = entry->cmdtype;
4258 cmdp->param = entry->u;
4263 * Make a copy of a parse tree.
4266 static inline struct funcnode *
4267 copyfunc(union node *n)
4272 funcblocksize = offsetof(struct funcnode, n);
4275 blocksize = funcblocksize;
4276 f = ckmalloc(blocksize + funcstringsize);
4277 funcblock = (char *) f + offsetof(struct funcnode, n);
4278 funcstring = (char *) f + blocksize;
4285 * Define a shell function.
4289 defun(char *name, union node *func)
4291 struct cmdentry entry;
4294 entry.cmdtype = CMDFUNCTION;
4295 entry.u.func = copyfunc(func);
4296 addcmdentry(name, &entry);
4302 * Delete a function if it exists.
4306 unsetfunc(const char *name)
4308 struct tblentry *cmdp;
4310 if ((cmdp = cmdlookup(name, 0)) != NULL &&
4311 cmdp->cmdtype == CMDFUNCTION)
4316 * Locate and print what a word is...
4320 #ifdef CONFIG_ASH_CMDCMD
4322 describe_command(char *command, int describe_command_verbose)
4324 #define describe_command_verbose 1
4326 describe_command(char *command)
4329 struct cmdentry entry;
4330 struct tblentry *cmdp;
4331 #ifdef CONFIG_ASH_ALIAS
4332 const struct alias *ap;
4334 const char *path = pathval();
4336 if (describe_command_verbose) {
4340 /* First look at the keywords */
4341 if (findkwd(command)) {
4342 out1str(describe_command_verbose ? " is a shell keyword" : command);
4346 #ifdef CONFIG_ASH_ALIAS
4347 /* Then look at the aliases */
4348 if ((ap = lookupalias(command, 0)) != NULL) {
4349 if (describe_command_verbose) {
4350 out1fmt(" is an alias for %s", ap->val);
4359 /* Then check if it is a tracked alias */
4360 if ((cmdp = cmdlookup(command, 0)) != NULL) {
4361 entry.cmdtype = cmdp->cmdtype;
4362 entry.u = cmdp->param;
4364 /* Finally use brute force */
4365 find_command(command, &entry, DO_ABS, path);
4368 switch (entry.cmdtype) {
4370 int j = entry.u.index;
4376 p = padvance(&path, command);
4380 if (describe_command_verbose) {
4382 (cmdp ? " a tracked alias for" : nullstr), p
4391 if (describe_command_verbose) {
4392 out1str(" is a shell function");
4399 if (describe_command_verbose) {
4400 out1fmt(" is a %sshell builtin",
4401 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
4402 "special " : nullstr
4410 if (describe_command_verbose) {
4411 out1str(": not found\n");
4417 outstr("\n", stdout);
4422 typecmd(int argc, char **argv)
4427 for (i = 1; i < argc; i++) {
4428 #ifdef CONFIG_ASH_CMDCMD
4429 err |= describe_command(argv[i], 1);
4431 err |= describe_command(argv[i]);
4437 #ifdef CONFIG_ASH_CMDCMD
4439 commandcmd(int argc, char **argv)
4447 while ((c = nextopt("pvV")) != '\0')
4449 verify |= VERIFY_VERBOSE;
4451 verify |= VERIFY_BRIEF;
4457 return describe_command(*argptr, verify - VERIFY_BRIEF);
4466 * Routines to expand arguments to commands. We have to deal with
4467 * backquotes, shell variables, and file metacharacters.
4473 #define RMESCAPE_ALLOC 0x1 /* Allocate a new string */
4474 #define RMESCAPE_GLOB 0x2 /* Add backslashes for glob */
4475 #define RMESCAPE_QUOTED 0x4 /* Remove CTLESC unless in quotes */
4476 #define RMESCAPE_GROW 0x8 /* Grow strings instead of stalloc */
4477 #define RMESCAPE_HEAP 0x10 /* Malloc strings instead of stalloc */
4480 * Structure specifying which parts of the string should be searched
4481 * for IFS characters.
4485 struct ifsregion *next; /* next region in list */
4486 int begoff; /* offset of start of region */
4487 int endoff; /* offset of end of region */
4488 int nulonly; /* search for nul bytes only */
4491 /* output of current string */
4492 static char *expdest;
4493 /* list of back quote expressions */
4494 static struct nodelist *argbackq;
4495 /* first struct in list of ifs regions */
4496 static struct ifsregion ifsfirst;
4497 /* last struct in list */
4498 static struct ifsregion *ifslastp;
4499 /* holds expanded arg list */
4500 static struct arglist exparg;
4502 static void argstr(char *, int);
4503 static char *exptilde(char *, char *, int);
4504 static void expbackq(union node *, int, int);
4505 static const char *subevalvar(char *, char *, int, int, int, int, int);
4506 static char *evalvar(char *, int);
4507 static void strtodest(const char *, int, int);
4508 static void memtodest(const char *p, size_t len, int syntax, int quotes);
4509 static ssize_t varvalue(char *, int, int);
4510 static void recordregion(int, int, int);
4511 static void removerecordregions(int);
4512 static void ifsbreakup(char *, struct arglist *);
4513 static void ifsfree(void);
4514 static void expandmeta(struct strlist *, int);
4515 static int patmatch(char *, const char *);
4517 static int cvtnum(arith_t);
4518 static size_t esclen(const char *, const char *);
4519 static char *scanleft(char *, char *, char *, char *, int, int);
4520 static char *scanright(char *, char *, char *, char *, int, int);
4521 static void varunset(const char *, const char *, const char *, int)
4525 #define pmatch(a, b) !fnmatch((a), (b), 0)
4527 * Prepare a pattern for a expmeta (internal glob(3)) call.
4529 * Returns an stalloced string.
4532 static inline char *
4533 preglob(const char *pattern, int quoted, int flag) {
4534 flag |= RMESCAPE_GLOB;
4536 flag |= RMESCAPE_QUOTED;
4538 return _rmescapes((char *)pattern, flag);
4543 esclen(const char *start, const char *p) {
4546 while (p > start && *--p == CTLESC) {
4554 * Expand shell variables and backquotes inside a here document.
4558 expandhere(union node *arg, int fd)
4561 expandarg(arg, (struct arglist *)NULL, 0);
4562 full_write(fd, stackblock(), expdest - (char *)stackblock());
4567 * Perform variable substitution and command substitution on an argument,
4568 * placing the resulting list of arguments in arglist. If EXP_FULL is true,
4569 * perform splitting and file name expansion. When arglist is NULL, perform
4570 * here document expansion.
4574 expandarg(union node *arg, struct arglist *arglist, int flag)
4579 argbackq = arg->narg.backquote;
4580 STARTSTACKSTR(expdest);
4581 ifsfirst.next = NULL;
4583 argstr(arg->narg.text, flag);
4584 p = _STPUTC('\0', expdest);
4586 if (arglist == NULL) {
4587 return; /* here document expanded */
4589 p = grabstackstr(p);
4590 exparg.lastp = &exparg.list;
4594 if (flag & EXP_FULL) {
4595 ifsbreakup(p, &exparg);
4596 *exparg.lastp = NULL;
4597 exparg.lastp = &exparg.list;
4598 expandmeta(exparg.list, flag);
4600 if (flag & EXP_REDIR) /*XXX - for now, just remove escapes */
4602 sp = (struct strlist *)stalloc(sizeof (struct strlist));
4605 exparg.lastp = &sp->next;
4609 *exparg.lastp = NULL;
4611 *arglist->lastp = exparg.list;
4612 arglist->lastp = exparg.lastp;
4618 * Perform variable and command substitution. If EXP_FULL is set, output CTLESC
4619 * characters to allow for further processing. Otherwise treat
4620 * $@ like $* since no splitting will be performed.
4624 argstr(char *p, int flag)
4626 static const char spclchars[] = {
4634 CTLBACKQ | CTLQUOTE,
4635 #ifdef CONFIG_ASH_MATH_SUPPORT
4640 const char *reject = spclchars;
4642 int quotes = flag & (EXP_FULL | EXP_CASE); /* do CTLESC */
4643 int breakall = flag & EXP_WORD;
4648 if (!(flag & EXP_VARTILDE)) {
4650 } else if (flag & EXP_VARTILDE2) {
4655 if (flag & EXP_TILDE) {
4661 if (*q == CTLESC && (flag & EXP_QWORD))
4664 p = exptilde(p, q, flag);
4667 startloc = expdest - (char *)stackblock();
4669 length += strcspn(p + length, reject);
4671 if (c && (!(c & 0x80)
4672 #ifdef CONFIG_ASH_MATH_SUPPORT
4676 /* c == '=' || c == ':' || c == CTLENDARI */
4681 expdest = stnputs(p, length, expdest);
4682 newloc = expdest - (char *)stackblock();
4683 if (breakall && !inquotes && newloc > startloc) {
4684 recordregion(startloc, newloc, 0);
4695 if (flag & EXP_VARTILDE2) {
4699 flag |= EXP_VARTILDE2;
4704 * sort of a hack - expand tildes in variable
4705 * assignments (after the first '=' and after ':'s).
4714 case CTLENDVAR: /* ??? */
4717 /* "$@" syntax adherence hack */
4720 !memcmp(p, dolatstr, DOLATSTRLEN) &&
4721 (p[4] == CTLQUOTEMARK || (
4722 p[4] == CTLENDVAR &&
4723 p[5] == CTLQUOTEMARK
4726 p = evalvar(p + 1, flag) + 1;
4729 inquotes = !inquotes;
4742 p = evalvar(p, flag);
4746 case CTLBACKQ|CTLQUOTE:
4747 expbackq(argbackq->n, c, quotes);
4748 argbackq = argbackq->next;
4750 #ifdef CONFIG_ASH_MATH_SUPPORT
4763 exptilde(char *startp, char *p, int flag)
4769 int quotes = flag & (EXP_FULL | EXP_CASE);
4774 while ((c = *++p) != '\0') {
4781 if (flag & EXP_VARTILDE)
4791 if (*name == '\0') {
4792 home = lookupvar(homestr);
4794 if ((pw = getpwnam(name)) == NULL)
4798 if (!home || !*home)
4801 startloc = expdest - (char *)stackblock();
4802 strtodest(home, SQSYNTAX, quotes);
4803 recordregion(startloc, expdest - (char *)stackblock(), 0);
4812 removerecordregions(int endoff)
4814 if (ifslastp == NULL)
4817 if (ifsfirst.endoff > endoff) {
4818 while (ifsfirst.next != NULL) {
4819 struct ifsregion *ifsp;
4821 ifsp = ifsfirst.next->next;
4822 ckfree(ifsfirst.next);
4823 ifsfirst.next = ifsp;
4826 if (ifsfirst.begoff > endoff)
4829 ifslastp = &ifsfirst;
4830 ifsfirst.endoff = endoff;
4835 ifslastp = &ifsfirst;
4836 while (ifslastp->next && ifslastp->next->begoff < endoff)
4837 ifslastp=ifslastp->next;
4838 while (ifslastp->next != NULL) {
4839 struct ifsregion *ifsp;
4841 ifsp = ifslastp->next->next;
4842 ckfree(ifslastp->next);
4843 ifslastp->next = ifsp;
4846 if (ifslastp->endoff > endoff)
4847 ifslastp->endoff = endoff;
4851 #ifdef CONFIG_ASH_MATH_SUPPORT
4853 * Expand arithmetic expression. Backup to start of expression,
4854 * evaluate, place result in (backed up) result, adjust string position.
4867 * This routine is slightly over-complicated for
4868 * efficiency. Next we scan backwards looking for the
4869 * start of arithmetic.
4871 start = stackblock();
4878 while (*p != CTLARI) {
4882 sh_error("missing CTLARI (shouldn't happen)");
4887 esc = esclen(start, p);
4897 removerecordregions(begoff);
4906 len = cvtnum(dash_arith(p + 2));
4909 recordregion(begoff, begoff + len, 0);
4914 * Expand stuff in backwards quotes.
4918 expbackq(union node *cmd, int quoted, int quotes)
4926 int syntax = quoted? DQSYNTAX : BASESYNTAX;
4927 struct stackmark smark;
4930 setstackmark(&smark);
4932 startloc = dest - (char *)stackblock();
4934 evalbackcmd(cmd, (struct backcmd *) &in);
4935 popstackmark(&smark);
4942 memtodest(p, i, syntax, quotes);
4946 i = safe_read(in.fd, buf, sizeof buf);
4947 TRACE(("expbackq: read returns %d\n", i));
4957 back_exitstatus = waitforjob(in.jp);
4961 /* Eat all trailing newlines */
4963 for (; dest > (char *)stackblock() && dest[-1] == '\n';)
4968 recordregion(startloc, dest - (char *)stackblock(), 0);
4969 TRACE(("evalbackq: size=%d: \"%.*s\"\n",
4970 (dest - (char *)stackblock()) - startloc,
4971 (dest - (char *)stackblock()) - startloc,
4972 stackblock() + startloc));
4977 scanleft(char *startp, char *rmesc, char *rmescend, char *str, int quotes,
4988 const char *s = loc2;
4994 match = pmatch(str, s);
4998 if (quotes && *loc == CTLESC)
5008 scanright(char *startp, char *rmesc, char *rmescend, char *str, int quotes,
5015 for (loc = str - 1, loc2 = rmescend; loc >= startp; loc2--) {
5018 const char *s = loc2;
5023 match = pmatch(str, s);
5030 esc = esclen(startp, loc);
5042 subevalvar(char *p, char *str, int strloc, int subtype, int startloc, int varflags, int quotes)
5046 int saveherefd = herefd;
5047 struct nodelist *saveargbackq = argbackq;
5049 char *rmesc, *rmescend;
5051 char *(*scan)(char *, char *, char *, char *, int , int);
5054 argstr(p, subtype != VSASSIGN && subtype != VSQUESTION ? EXP_CASE : 0);
5055 STPUTC('\0', expdest);
5056 herefd = saveherefd;
5057 argbackq = saveargbackq;
5058 startp = stackblock() + startloc;
5062 setvar(str, startp, 0);
5063 amount = startp - expdest;
5064 STADJUST(amount, expdest);
5068 varunset(p, str, startp, varflags);
5072 subtype -= VSTRIMRIGHT;
5074 if (subtype < 0 || subtype > 3)
5079 rmescend = stackblock() + strloc;
5081 rmesc = _rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW);
5082 if (rmesc != startp) {
5084 startp = stackblock() + startloc;
5088 str = stackblock() + strloc;
5089 preglob(str, varflags & VSQUOTE, 0);
5091 /* zero = subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX */
5092 zero = subtype >> 1;
5093 /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
5094 scan = (subtype & 1) ^ zero ? scanleft : scanright;
5096 loc = scan(startp, rmesc, rmescend, str, quotes, zero);
5099 memmove(startp, loc, str - loc);
5100 loc = startp + (str - loc) - 1;
5103 amount = loc - expdest;
5104 STADJUST(amount, expdest);
5111 * Expand a variable, and return a pointer to the next character in the
5115 evalvar(char *p, int flag)
5128 quotes = flag & (EXP_FULL | EXP_CASE);
5130 subtype = varflags & VSTYPE;
5131 quoted = varflags & VSQUOTE;
5133 easy = (!quoted || (*var == '@' && shellparam.nparam));
5134 startloc = expdest - (char *)stackblock();
5135 p = strchr(p, '=') + 1;
5138 varlen = varvalue(var, varflags, flag);
5139 if (varflags & VSNUL)
5142 if (subtype == VSPLUS) {
5143 varlen = -1 - varlen;
5147 if (subtype == VSMINUS) {
5151 p, flag | EXP_TILDE |
5152 (quoted ? EXP_QWORD : EXP_WORD)
5161 if (subtype == VSASSIGN || subtype == VSQUESTION) {
5163 if (subevalvar(p, var, 0, subtype, startloc,
5167 * Remove any recorded regions beyond
5170 removerecordregions(startloc);
5180 if (varlen < 0 && uflag)
5181 varunset(p, var, 0, 0);
5183 if (subtype == VSLENGTH) {
5184 cvtnum(varlen > 0 ? varlen : 0);
5188 if (subtype == VSNORMAL) {
5192 recordregion(startloc, expdest - (char *)stackblock(), quoted);
5201 case VSTRIMRIGHTMAX:
5210 * Terminate the string and start recording the pattern
5213 STPUTC('\0', expdest);
5214 patloc = expdest - (char *)stackblock();
5215 if (subevalvar(p, NULL, patloc, subtype,
5216 startloc, varflags, quotes) == 0) {
5217 int amount = expdest - (
5218 (char *)stackblock() + patloc - 1
5220 STADJUST(-amount, expdest);
5222 /* Remove any recorded regions beyond start of variable */
5223 removerecordregions(startloc);
5228 if (subtype != VSNORMAL) { /* skip to end of alternative */
5231 if ((c = *p++) == CTLESC)
5233 else if (c == CTLBACKQ || c == (CTLBACKQ|CTLQUOTE)) {
5235 argbackq = argbackq->next;
5236 } else if (c == CTLVAR) {
5237 if ((*p++ & VSTYPE) != VSNORMAL)
5239 } else if (c == CTLENDVAR) {
5250 * Put a string on the stack.
5254 memtodest(const char *p, size_t len, int syntax, int quotes) {
5257 q = makestrspace(len * 2, q);
5260 int c = SC2INT(*p++);
5263 if (quotes && (SIT(c, syntax) == CCTL || SIT(c, syntax) == CBACK))
5273 strtodest(const char *p, int syntax, int quotes)
5275 memtodest(p, strlen(p), syntax, quotes);
5280 * Add the value of a specialized variable to the stack string.
5284 varvalue(char *name, int varflags, int flags)
5294 int quoted = varflags & VSQUOTE;
5295 int subtype = varflags & VSTYPE;
5296 int quotes = flags & (EXP_FULL | EXP_CASE);
5298 if (quoted && (flags & EXP_FULL))
5299 sep = 1 << CHAR_BIT;
5301 syntax = quoted ? DQSYNTAX : BASESYNTAX;
5310 num = shellparam.nparam;
5320 p = makestrspace(NOPTS, expdest);
5321 for (i = NOPTS - 1; i >= 0; i--) {
5323 USTPUTC(optletters(i), p);
5334 sep = ifsset() ? SC2INT(ifsval()[0]) : ' ';
5335 if (quotes && (SIT(sep, syntax) == CCTL || SIT(sep, syntax) == CBACK))
5338 if (!(ap = shellparam.p))
5340 while ((p = *ap++)) {
5343 partlen = strlen(p);
5346 if (!(subtype == VSPLUS || subtype == VSLENGTH))
5347 memtodest(p, partlen, syntax, quotes);
5353 if (subtype == VSPLUS || subtype == VSLENGTH) {
5375 if (num < 0 || num > shellparam.nparam)
5377 p = num ? shellparam.p[num - 1] : arg0;
5380 p = lookupvar(name);
5386 if (!(subtype == VSPLUS || subtype == VSLENGTH))
5387 memtodest(p, len, syntax, quotes);
5391 if (subtype == VSPLUS || subtype == VSLENGTH)
5392 STADJUST(-len, expdest);
5398 * Record the fact that we have to scan this region of the
5399 * string for IFS characters.
5403 recordregion(int start, int end, int nulonly)
5405 struct ifsregion *ifsp;
5407 if (ifslastp == NULL) {
5411 ifsp = (struct ifsregion *)ckmalloc(sizeof (struct ifsregion));
5413 ifslastp->next = ifsp;
5417 ifslastp->begoff = start;
5418 ifslastp->endoff = end;
5419 ifslastp->nulonly = nulonly;
5424 * Break the argument string into pieces based upon IFS and add the
5425 * strings to the argument list. The regions of the string to be
5426 * searched for IFS characters have been stored by recordregion.
5429 ifsbreakup(char *string, struct arglist *arglist)
5431 struct ifsregion *ifsp;
5436 const char *ifs, *realifs;
5442 if (ifslastp != NULL) {
5445 realifs = ifsset() ? ifsval() : defifs;
5448 p = string + ifsp->begoff;
5449 nulonly = ifsp->nulonly;
5450 ifs = nulonly ? nullstr : realifs;
5452 while (p < string + ifsp->endoff) {
5456 if (strchr(ifs, *p)) {
5458 ifsspc = (strchr(defifs, *p) != NULL);
5459 /* Ignore IFS whitespace at start */
5460 if (q == start && ifsspc) {
5466 sp = (struct strlist *)stalloc(sizeof *sp);
5468 *arglist->lastp = sp;
5469 arglist->lastp = &sp->next;
5473 if (p >= string + ifsp->endoff) {
5479 if (strchr(ifs, *p) == NULL ) {
5482 } else if (strchr(defifs, *p) == NULL) {
5498 } while ((ifsp = ifsp->next) != NULL);
5507 sp = (struct strlist *)stalloc(sizeof *sp);
5509 *arglist->lastp = sp;
5510 arglist->lastp = &sp->next;
5516 struct ifsregion *p;
5521 struct ifsregion *ifsp;
5527 ifsfirst.next = NULL;
5531 static void expmeta(char *, char *);
5532 static struct strlist *expsort(struct strlist *);
5533 static struct strlist *msort(struct strlist *, int);
5535 static char *expdir;
5539 expandmeta(struct strlist *str, int flag)
5541 static const char metachars[] = {
5544 /* TODO - EXP_REDIR */
5547 struct strlist **savelastp;
5553 if (!strpbrk(str->text, metachars))
5555 savelastp = exparg.lastp;
5558 p = preglob(str->text, 0, RMESCAPE_ALLOC | RMESCAPE_HEAP);
5560 int i = strlen(str->text);
5561 expdir = ckmalloc(i < 2048 ? 2048 : i); /* XXX */
5569 if (exparg.lastp == savelastp) {
5574 *exparg.lastp = str;
5575 rmescapes(str->text);
5576 exparg.lastp = &str->next;
5578 *exparg.lastp = NULL;
5579 *savelastp = sp = expsort(*savelastp);
5580 while (sp->next != NULL)
5582 exparg.lastp = &sp->next;
5589 * Add a file name to the list.
5593 addfname(const char *name)
5597 sp = (struct strlist *)stalloc(sizeof *sp);
5598 sp->text = sstrdup(name);
5600 exparg.lastp = &sp->next;
5605 * Do metacharacter (i.e. *, ?, [...]) expansion.
5609 expmeta(char *enddir, char *name)
5624 for (p = name; *p; p++) {
5625 if (*p == '*' || *p == '?')
5627 else if (*p == '[') {
5634 if (*q == '/' || *q == '\0')
5641 } else if (*p == '\\')
5643 else if (*p == '/') {
5650 if (metaflag == 0) { /* we've reached the end of the file name */
5651 if (enddir != expdir)
5659 if (metaflag == 0 || lstat(expdir, &statb) >= 0)
5670 } while (p < start);
5672 if (enddir == expdir) {
5674 } else if (enddir == expdir + 1 && *expdir == '/') {
5680 if ((dirp = opendir(cp)) == NULL)
5682 if (enddir != expdir)
5684 if (*endname == 0) {
5696 while (! intpending && (dp = readdir(dirp)) != NULL) {
5697 if (dp->d_name[0] == '.' && ! matchdot)
5699 if (pmatch(start, dp->d_name)) {
5701 scopy(dp->d_name, enddir);
5704 for (p = enddir, cp = dp->d_name;
5705 (*p++ = *cp++) != '\0';)
5708 expmeta(p, endname);
5718 * Sort the results of file name expansion. It calculates the number of
5719 * strings to sort and then calls msort (short for merge sort) to do the
5723 static struct strlist *
5724 expsort(struct strlist *str)
5730 for (sp = str ; sp ; sp = sp->next)
5732 return msort(str, len);
5736 static struct strlist *
5737 msort(struct strlist *list, int len)
5739 struct strlist *p, *q = NULL;
5740 struct strlist **lpp;
5748 for (n = half ; --n >= 0 ; ) {
5752 q->next = NULL; /* terminate first half of list */
5753 q = msort(list, half); /* sort first half of list */
5754 p = msort(p, len - half); /* sort second half */
5757 #ifdef CONFIG_LOCALE_SUPPORT
5758 if (strcoll(p->text, q->text) < 0)
5760 if (strcmp(p->text, q->text) < 0)
5765 if ((p = *lpp) == NULL) {
5772 if ((q = *lpp) == NULL) {
5783 * Returns true if the pattern matches the string.
5787 patmatch(char *pattern, const char *string)
5789 return pmatch(preglob(pattern, 0, 0), string);
5794 * Remove any CTLESC characters from a string.
5798 _rmescapes(char *str, int flag)
5801 static const char qchars[] = { CTLESC, CTLQUOTEMARK, 0 };
5806 p = strpbrk(str, qchars);
5812 if (flag & RMESCAPE_ALLOC) {
5813 size_t len = p - str;
5814 size_t fulllen = len + strlen(p) + 1;
5816 if (flag & RMESCAPE_GROW) {
5817 r = makestrspace(fulllen, expdest);
5818 } else if (flag & RMESCAPE_HEAP) {
5819 r = ckmalloc(fulllen);
5821 r = stalloc(fulllen);
5825 q = mempcpy(q, str, len);
5828 inquotes = (flag & RMESCAPE_QUOTED) ^ RMESCAPE_QUOTED;
5829 globbing = flag & RMESCAPE_GLOB;
5830 notescaped = globbing;
5832 if (*p == CTLQUOTEMARK) {
5833 inquotes = ~inquotes;
5835 notescaped = globbing;
5839 /* naked back slash */
5845 if (notescaped && inquotes && *p != '/') {
5849 notescaped = globbing;
5854 if (flag & RMESCAPE_GROW) {
5856 STADJUST(q - r + 1, expdest);
5863 * See if a pattern matches in a case statement.
5867 casematch(union node *pattern, char *val)
5869 struct stackmark smark;
5872 setstackmark(&smark);
5873 argbackq = pattern->narg.backquote;
5874 STARTSTACKSTR(expdest);
5876 argstr(pattern->narg.text, EXP_TILDE | EXP_CASE);
5877 STACKSTRNUL(expdest);
5878 result = patmatch(stackblock(), val);
5879 popstackmark(&smark);
5892 expdest = makestrspace(32, expdest);
5893 #ifdef CONFIG_ASH_MATH_SUPPORT_64
5894 len = fmtstr(expdest, 32, "%lld", (long long) num);
5896 len = fmtstr(expdest, 32, "%ld", num);
5898 STADJUST(len, expdest);
5903 varunset(const char *end, const char *var, const char *umsg, int varflags)
5909 msg = "parameter not set";
5911 if (*end == CTLENDVAR) {
5912 if (varflags & VSNUL)
5917 sh_error("%.*s: %s%s", end - var - 1, var, msg, tail);
5924 * This implements the input routines used by the parser.
5927 #define EOF_NLEFT -99 /* value of parsenleft when EOF pushed back */
5929 static void pushfile(void);
5932 * Read a character from the script, returning PEOF on end of file.
5933 * Nul characters in the input are silently discarded.
5937 #define pgetc_as_macro() (--parsenleft >= 0? SC2INT(*parsenextc++) : preadbuffer())
5939 #ifdef CONFIG_ASH_OPTIMIZE_FOR_SIZE
5940 #define pgetc_macro() pgetc()
5944 return pgetc_as_macro();
5947 #define pgetc_macro() pgetc_as_macro()
5951 return pgetc_macro();
5957 * Same as pgetc(), but ignores PEOA.
5959 #ifdef CONFIG_ASH_ALIAS
5960 static int pgetc2(void)
5966 } while (c == PEOA);
5970 static inline int pgetc2(void)
5972 return pgetc_macro();
5977 * Read a line from the script.
5980 static inline char *
5981 pfgets(char *line, int len)
5987 while (--nleft > 0) {
6004 #ifdef CONFIG_FEATURE_COMMAND_EDITING
6005 #ifdef CONFIG_ASH_EXPAND_PRMT
6006 static char *cmdedit_prompt;
6008 static const char *cmdedit_prompt;
6010 static inline void putprompt(const char *s)
6012 #ifdef CONFIG_ASH_EXPAND_PRMT
6013 free(cmdedit_prompt);
6014 cmdedit_prompt = bb_xstrdup(s);
6020 static inline void putprompt(const char *s)
6030 char *buf = parsefile->buf;
6034 #ifdef CONFIG_FEATURE_COMMAND_EDITING
6035 if (!iflag || parsefile->fd)
6036 nr = safe_read(parsefile->fd, buf, BUFSIZ - 1);
6038 #ifdef CONFIG_FEATURE_COMMAND_TAB_COMPLETION
6039 cmdedit_path_lookup = pathval();
6041 nr = cmdedit_read_input((char *) cmdedit_prompt, buf);
6043 /* Ctrl+C presend */
6052 if(nr < 0 && errno == 0) {
6053 /* Ctrl+D presend */
6058 nr = safe_read(parsefile->fd, buf, BUFSIZ - 1);
6062 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
6063 int flags = fcntl(0, F_GETFL, 0);
6064 if (flags >= 0 && flags & O_NONBLOCK) {
6065 flags &=~ O_NONBLOCK;
6066 if (fcntl(0, F_SETFL, flags) >= 0) {
6067 out2str("sh: turning off NDELAY mode\n");
6077 * Refill the input buffer and return the next input character:
6079 * 1) If a string was pushed back on the input, pop it;
6080 * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading
6081 * from a string so we can't refill the buffer, return EOF.
6082 * 3) If the is more stuff in this buffer, use it else call read to fill it.
6083 * 4) Process input up to the next newline, deleting nul characters.
6093 while (parsefile->strpush) {
6094 #ifdef CONFIG_ASH_ALIAS
6095 if (parsenleft == -1 && parsefile->strpush->ap &&
6096 parsenextc[-1] != ' ' && parsenextc[-1] != '\t') {
6101 if (--parsenleft >= 0)
6102 return SC2INT(*parsenextc++);
6104 if (parsenleft == EOF_NLEFT || parsefile->buf == NULL)
6111 if ((more = preadfd()) <= 0) {
6112 parselleft = parsenleft = EOF_NLEFT;
6119 /* delete nul characters */
6127 memmove(q, q + 1, more);
6131 parsenleft = q - parsenextc - 1;
6137 parsenleft = q - parsenextc - 1;
6149 out2str(parsenextc);
6154 return SC2INT(*parsenextc++);
6158 * Undo the last call to pgetc. Only one character may be pushed back.
6159 * PEOF may be pushed back.
6170 * Push a string back onto the input at this current parsefile level.
6171 * We handle aliases this way.
6174 pushstring(char *s, void *ap)
6181 /*dprintf("*** calling pushstring: %s, %d\n", s, len);*/
6182 if (parsefile->strpush) {
6183 sp = ckmalloc(sizeof (struct strpush));
6184 sp->prev = parsefile->strpush;
6185 parsefile->strpush = sp;
6187 sp = parsefile->strpush = &(parsefile->basestrpush);
6188 sp->prevstring = parsenextc;
6189 sp->prevnleft = parsenleft;
6190 #ifdef CONFIG_ASH_ALIAS
6191 sp->ap = (struct alias *)ap;
6193 ((struct alias *)ap)->flag |= ALIASINUSE;
6205 struct strpush *sp = parsefile->strpush;
6208 #ifdef CONFIG_ASH_ALIAS
6210 if (parsenextc[-1] == ' ' || parsenextc[-1] == '\t') {
6211 checkkwd |= CHKALIAS;
6213 if (sp->string != sp->ap->val) {
6216 sp->ap->flag &= ~ALIASINUSE;
6217 if (sp->ap->flag & ALIASDEAD) {
6218 unalias(sp->ap->name);
6222 parsenextc = sp->prevstring;
6223 parsenleft = sp->prevnleft;
6224 /*dprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/
6225 parsefile->strpush = sp->prev;
6226 if (sp != &(parsefile->basestrpush))
6232 * Set the input to take input from a file. If push is set, push the
6233 * old input onto the stack first.
6237 setinputfile(const char *fname, int flags)
6243 if ((fd = open(fname, O_RDONLY)) < 0) {
6244 if (flags & INPUT_NOFILE_OK)
6246 sh_error("Can't open %s", fname);
6249 fd2 = copyfd(fd, 10);
6252 sh_error("Out of file descriptors");
6255 setinputfd(fd, flags & INPUT_PUSH_FILE);
6263 * Like setinputfile, but takes an open file descriptor. Call this with
6268 setinputfd(int fd, int push)
6270 (void) fcntl(fd, F_SETFD, FD_CLOEXEC);
6276 if (parsefile->buf == NULL)
6277 parsefile->buf = ckmalloc(IBUFSIZ);
6278 parselleft = parsenleft = 0;
6284 * Like setinputfile, but takes input from a string.
6288 setinputstring(char *string)
6292 parsenextc = string;
6293 parsenleft = strlen(string);
6294 parsefile->buf = NULL;
6301 * To handle the "." command, a stack of input files is used. Pushfile
6302 * adds a new entry to the stack and popfile restores the previous level.
6308 struct parsefile *pf;
6310 parsefile->nleft = parsenleft;
6311 parsefile->lleft = parselleft;
6312 parsefile->nextc = parsenextc;
6313 parsefile->linno = plinno;
6314 pf = (struct parsefile *)ckmalloc(sizeof (struct parsefile));
6315 pf->prev = parsefile;
6318 pf->basestrpush.prev = NULL;
6326 struct parsefile *pf = parsefile;
6335 parsefile = pf->prev;
6337 parsenleft = parsefile->nleft;
6338 parselleft = parsefile->lleft;
6339 parsenextc = parsefile->nextc;
6340 plinno = parsefile->linno;
6346 * Return to top level.
6352 while (parsefile != &basepf)
6358 * Close the file(s) that the shell is reading commands from. Called
6359 * after a fork is done.
6366 if (parsefile->fd > 0) {
6367 close(parsefile->fd);
6374 /* mode flags for set_curjob */
6375 #define CUR_DELETE 2
6376 #define CUR_RUNNING 1
6377 #define CUR_STOPPED 0
6379 /* mode flags for dowait */
6380 #define DOWAIT_NORMAL 0
6381 #define DOWAIT_BLOCK 1
6384 static struct job *jobtab;
6386 static unsigned njobs;
6388 /* pgrp of shell on invocation */
6389 static int initialpgrp;
6390 static int ttyfd = -1;
6393 static struct job *curjob;
6394 /* number of presumed living untracked jobs */
6397 static void set_curjob(struct job *, unsigned);
6399 static int restartjob(struct job *, int);
6400 static void xtcsetpgrp(int, pid_t);
6401 static char *commandtext(union node *);
6402 static void cmdlist(union node *, int);
6403 static void cmdtxt(union node *);
6404 static void cmdputs(const char *);
6405 static void showpipe(struct job *, FILE *);
6407 static int sprint_status(char *, int, int);
6408 static void freejob(struct job *);
6409 static struct job *getjob(const char *, int);
6410 static struct job *growjobtab(void);
6411 static void forkchild(struct job *, union node *, int);
6412 static void forkparent(struct job *, union node *, int, pid_t);
6413 static int dowait(int, struct job *);
6414 static int getstatus(struct job *);
6417 set_curjob(struct job *jp, unsigned mode)
6420 struct job **jpp, **curp;
6422 /* first remove from list */
6423 jpp = curp = &curjob;
6428 jpp = &jp1->prev_job;
6430 *jpp = jp1->prev_job;
6432 /* Then re-insert in correct position */
6440 /* job being deleted */
6443 /* newly created job or backgrounded job,
6444 put after all stopped jobs. */
6448 if (!jp1 || jp1->state != JOBSTOPPED)
6451 jpp = &jp1->prev_job;
6457 /* newly stopped job - becomes curjob */
6458 jp->prev_job = *jpp;
6466 * Turn job control on and off.
6468 * Note: This code assumes that the third arg to ioctl is a character
6469 * pointer, which is true on Berkeley systems but not System V. Since
6470 * System V doesn't have job control yet, this isn't a problem now.
6472 * Called with interrupts off.
6481 if (on == jobctl || rootshell == 0)
6485 ofd = fd = open(_PATH_TTY, O_RDWR);
6488 while (!isatty(fd) && --fd >= 0)
6491 fd = fcntl(fd, F_DUPFD, 10);
6495 fcntl(fd, F_SETFD, FD_CLOEXEC);
6496 do { /* while we are in the background */
6497 if ((pgrp = tcgetpgrp(fd)) < 0) {
6499 sh_warnx("can't access tty; job control turned off");
6503 if (pgrp == getpgrp())
6514 xtcsetpgrp(fd, pgrp);
6516 /* turning job control off */
6519 xtcsetpgrp(fd, pgrp);
6533 killcmd(int argc, char **argv)
6544 "Usage: kill [-s sigspec | -signum | -sigspec] [pid | job]... or\n"
6545 "kill -l [exitstatus]"
6549 if (**++argv == '-') {
6550 signo = get_signum(*argv + 1);
6554 while ((c = nextopt("ls:")) != '\0')
6564 signo = get_signum(optionarg);
6567 "invalid signal number or name: %s",
6578 if (!list && signo < 0)
6581 if ((signo < 0 || !*argv) ^ list) {
6589 for (i = 1; i < NSIG; i++) {
6590 name = get_signame(i);
6592 out1fmt(snlfmt, name);
6596 name = get_signame(signo);
6598 out1fmt(snlfmt, name);
6600 sh_error("invalid signal number or exit status: %s", *argptr);
6606 if (**argv == '%') {
6607 jp = getjob(*argv, 0);
6608 pid = -jp->ps[0].pid;
6610 pid = **argv == '-' ?
6611 -number(*argv + 1) : number(*argv);
6613 if (kill(pid, signo) != 0) {
6614 sh_warnx("(%d) - %m", pid);
6623 #if defined(JOBS) || defined(DEBUG)
6625 jobno(const struct job *jp)
6627 return jp - jobtab + 1;
6633 fgcmd(int argc, char **argv)
6640 mode = (**argv == 'f') ? FORK_FG : FORK_BG;
6645 jp = getjob(*argv, 1);
6646 if (mode == FORK_BG) {
6647 set_curjob(jp, CUR_RUNNING);
6648 fprintf(out, "[%d] ", jobno(jp));
6650 outstr(jp->ps->cmd, out);
6652 retval = restartjob(jp, mode);
6653 } while (*argv && *++argv);
6657 static int bgcmd(int, char **) __attribute__((__alias__("fgcmd")));
6661 restartjob(struct job *jp, int mode)
6663 struct procstat *ps;
6669 if (jp->state == JOBDONE)
6671 jp->state = JOBRUNNING;
6673 if (mode == FORK_FG)
6674 xtcsetpgrp(ttyfd, pgid);
6675 killpg(pgid, SIGCONT);
6679 if (WIFSTOPPED(ps->status)) {
6682 } while (ps++, --i);
6684 status = (mode == FORK_FG) ? waitforjob(jp) : 0;
6691 sprint_status(char *s, int status, int sigonly)
6697 if (!WIFEXITED(status)) {
6699 if (WIFSTOPPED(status))
6700 st = WSTOPSIG(status);
6703 st = WTERMSIG(status);
6705 if (st == SIGINT || st == SIGPIPE)
6708 if (WIFSTOPPED(status))
6713 col = fmtstr(s, 32, strsignal(st));
6714 if (WCOREDUMP(status)) {
6715 col += fmtstr(s + col, 16, " (core dumped)");
6717 } else if (!sigonly) {
6718 st = WEXITSTATUS(status);
6720 col = fmtstr(s, 16, "Done(%d)", st);
6722 col = fmtstr(s, 16, "Done");
6731 showjob(FILE *out, struct job *jp, int mode)
6733 struct procstat *ps;
6734 struct procstat *psend;
6741 if (mode & SHOW_PGID) {
6742 /* just output process (group) id of pipeline */
6743 fprintf(out, "%d\n", ps->pid);
6747 col = fmtstr(s, 16, "[%d] ", jobno(jp));
6752 else if (curjob && jp == curjob->prev_job)
6755 if (mode & SHOW_PID)
6756 col += fmtstr(s + col, 16, "%d ", ps->pid);
6758 psend = ps + jp->nprocs;
6760 if (jp->state == JOBRUNNING) {
6761 scopy("Running", s + col);
6762 col += strlen("Running");
6764 int status = psend[-1].status;
6766 if (jp->state == JOBSTOPPED)
6767 status = jp->stopstatus;
6769 col += sprint_status(s + col, status, 0);
6775 /* for each process */
6776 col = fmtstr(s, 48, " |\n%*c%d ", indent, ' ', ps->pid) - 3;
6779 fprintf(out, "%s%*c%s",
6780 s, 33 - col >= 0 ? 33 - col : 0, ' ', ps->cmd
6782 if (!(mode & SHOW_PID)) {
6786 if (++ps == psend) {
6787 outcslow('\n', out);
6794 if (jp->state == JOBDONE) {
6795 TRACE(("showjob: freeing job %d\n", jobno(jp)));
6802 jobscmd(int argc, char **argv)
6808 while ((m = nextopt("lp")))
6818 showjob(out, getjob(*argv,0), mode);
6821 showjobs(out, mode);
6828 * Print a list of jobs. If "change" is nonzero, only print jobs whose
6829 * statuses have changed since the last call to showjobs.
6833 showjobs(FILE *out, int mode)
6837 TRACE(("showjobs(%x) called\n", mode));
6839 /* If not even one one job changed, there is nothing to do */
6840 while (dowait(DOWAIT_NORMAL, NULL) > 0)
6843 for (jp = curjob; jp; jp = jp->prev_job) {
6844 if (!(mode & SHOW_CHANGED) || jp->changed)
6845 showjob(out, jp, mode);
6851 * Mark a job structure as unused.
6855 freejob(struct job *jp)
6857 struct procstat *ps;
6861 for (i = jp->nprocs, ps = jp->ps ; --i >= 0 ; ps++) {
6862 if (ps->cmd != nullstr)
6865 if (jp->ps != &jp->ps0)
6868 set_curjob(jp, CUR_DELETE);
6874 waitcmd(int argc, char **argv)
6887 /* wait for all jobs */
6892 /* no running procs */
6895 if (jp->state == JOBRUNNING)
6900 dowait(DOWAIT_BLOCK, 0);
6906 if (**argv != '%') {
6907 pid_t pid = number(*argv);
6911 if (job->ps[job->nprocs - 1].pid == pid)
6913 job = job->prev_job;
6919 job = getjob(*argv, 0);
6920 /* loop until process terminated or stopped */
6921 while (job->state == JOBRUNNING)
6922 dowait(DOWAIT_BLOCK, 0);
6924 retval = getstatus(job);
6935 * Convert a job name to a job structure.
6939 getjob(const char *name, int getctl)
6943 const char *err_msg = "No such job: %s";
6947 char *(*match)(const char *, const char *);
6962 if (c == '+' || c == '%') {
6964 err_msg = "No current job";
6966 } else if (c == '-') {
6969 err_msg = "No previous job";
6980 jp = jobtab + num - 1;
6997 if (match(jp->ps[0].cmd, p)) {
7001 err_msg = "%s: ambiguous";
7008 err_msg = "job %s not created under job control";
7009 if (getctl && jp->jobctl == 0)
7014 sh_error(err_msg, name);
7019 * Return a new job structure.
7020 * Called with interrupts off.
7024 makejob(union node *node, int nprocs)
7029 for (i = njobs, jp = jobtab ; ; jp++) {
7036 if (jp->state != JOBDONE || !jp->waited)
7045 memset(jp, 0, sizeof(*jp));
7050 jp->prev_job = curjob;
7055 jp->ps = ckmalloc(nprocs * sizeof (struct procstat));
7057 TRACE(("makejob(0x%lx, %d) returns %%%d\n", (long)node, nprocs,
7067 struct job *jp, *jq;
7069 len = njobs * sizeof(*jp);
7071 jp = ckrealloc(jq, len + 4 * sizeof(*jp));
7073 offset = (char *)jp - (char *)jq;
7075 /* Relocate pointers */
7078 jq = (struct job *)((char *)jq + l);
7082 #define joff(p) ((struct job *)((char *)(p) + l))
7083 #define jmove(p) (p) = (void *)((char *)(p) + offset)
7084 if (xlikely(joff(jp)->ps == &jq->ps0))
7085 jmove(joff(jp)->ps);
7086 if (joff(jp)->prev_job)
7087 jmove(joff(jp)->prev_job);
7097 jp = (struct job *)((char *)jp + len);
7101 } while (--jq >= jp);
7107 * Fork off a subshell. If we are doing job control, give the subshell its
7108 * own process group. Jp is a job structure that the job is to be added to.
7109 * N is the command that will be evaluated by the child. Both jp and n may
7110 * be NULL. The mode parameter can be one of the following:
7111 * FORK_FG - Fork off a foreground process.
7112 * FORK_BG - Fork off a background process.
7113 * FORK_NOJOB - Like FORK_FG, but don't give the process its own
7114 * process group even if job control is on.
7116 * When job control is turned off, background processes have their standard
7117 * input redirected to /dev/null (except for the second and later processes
7120 * Called with interrupts off.
7124 forkchild(struct job *jp, union node *n, int mode)
7128 TRACE(("Child shell %d\n", getpid()));
7135 /* do job control only in root shell */
7137 if (mode != FORK_NOJOB && jp->jobctl && !oldlvl) {
7140 if (jp->nprocs == 0)
7143 pgrp = jp->ps[0].pid;
7144 /* This can fail because we are doing it in the parent also */
7145 (void)setpgid(0, pgrp);
7146 if (mode == FORK_FG)
7147 xtcsetpgrp(ttyfd, pgrp);
7152 if (mode == FORK_BG) {
7155 if (jp->nprocs == 0) {
7157 if (open(bb_dev_null, O_RDONLY) != 0)
7158 sh_error("Can't open %s", bb_dev_null);
7161 if (!oldlvl && iflag) {
7166 for (jp = curjob; jp; jp = jp->prev_job)
7172 forkparent(struct job *jp, union node *n, int mode, pid_t pid)
7174 TRACE(("In parent shell: child = %d\n", pid));
7176 while (jobless && dowait(DOWAIT_NORMAL, 0) > 0);
7181 if (mode != FORK_NOJOB && jp->jobctl) {
7184 if (jp->nprocs == 0)
7187 pgrp = jp->ps[0].pid;
7188 /* This can fail because we are doing it in the child also */
7189 (void)setpgid(pid, pgrp);
7192 if (mode == FORK_BG) {
7193 backgndpid = pid; /* set $! */
7194 set_curjob(jp, CUR_RUNNING);
7197 struct procstat *ps = &jp->ps[jp->nprocs++];
7203 ps->cmd = commandtext(n);
7209 forkshell(struct job *jp, union node *n, int mode)
7213 TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode));
7216 TRACE(("Fork failed, errno=%d", errno));
7219 sh_error("Cannot fork");
7222 forkchild(jp, n, mode);
7224 forkparent(jp, n, mode, pid);
7229 * Wait for job to finish.
7231 * Under job control we have the problem that while a child process is
7232 * running interrupts generated by the user are sent to the child but not
7233 * to the shell. This means that an infinite loop started by an inter-
7234 * active user may be hard to kill. With job control turned off, an
7235 * interactive user may place an interactive program inside a loop. If
7236 * the interactive program catches interrupts, the user doesn't want
7237 * these interrupts to also abort the loop. The approach we take here
7238 * is to have the shell ignore interrupt signals while waiting for a
7239 * foreground process to terminate, and then send itself an interrupt
7240 * signal if the child process was terminated by an interrupt signal.
7241 * Unfortunately, some programs want to do a bit of cleanup and then
7242 * exit on interrupt; unless these processes terminate themselves by
7243 * sending a signal to themselves (instead of calling exit) they will
7244 * confuse this approach.
7246 * Called with interrupts off.
7250 waitforjob(struct job *jp)
7254 TRACE(("waitforjob(%%%d) called\n", jobno(jp)));
7255 while (jp->state == JOBRUNNING) {
7256 dowait(DOWAIT_BLOCK, jp);
7261 xtcsetpgrp(ttyfd, rootpid);
7263 * This is truly gross.
7264 * If we're doing job control, then we did a TIOCSPGRP which
7265 * caused us (the shell) to no longer be in the controlling
7266 * session -- so we wouldn't have seen any ^C/SIGINT. So, we
7267 * intuit from the subprocess exit status whether a SIGINT
7268 * occurred, and if so interrupt ourselves. Yuck. - mycroft
7273 if (jp->state == JOBDONE)
7281 * Do a wait system call. If job control is compiled in, we accept
7282 * stopped processes. If block is zero, we return a value of zero
7283 * rather than blocking.
7285 * System V doesn't have a non-blocking wait system call. It does
7286 * have a SIGCLD signal that is sent to a process when one of it's
7287 * children dies. The obvious way to use SIGCLD would be to install
7288 * a handler for SIGCLD which simply bumped a counter when a SIGCLD
7289 * was received, and have waitproc bump another counter when it got
7290 * the status of a process. Waitproc would then know that a wait
7291 * system call would not block if the two counters were different.
7292 * This approach doesn't work because if a process has children that
7293 * have not been waited for, System V will send it a SIGCLD when it
7294 * installs a signal handler for SIGCLD. What this means is that when
7295 * a child exits, the shell will be sent SIGCLD signals continuously
7296 * until is runs out of stack space, unless it does a wait call before
7297 * restoring the signal handler. The code below takes advantage of
7298 * this (mis)feature by installing a signal handler for SIGCLD and
7299 * then checking to see whether it was called. If there are any
7300 * children to be waited for, it will be.
7302 * If neither SYSV nor BSD is defined, we don't implement nonblocking
7303 * waits at all. In this case, the user will not be informed when
7304 * a background process until the next time she runs a real program
7305 * (as opposed to running a builtin command or just typing return),
7306 * and the jobs command may give out of date information.
7310 waitproc(int block, int *status)
7320 return wait3(status, flags, (struct rusage *)NULL);
7324 * Wait for a process to terminate.
7328 dowait(int block, struct job *job)
7333 struct job *thisjob;
7336 TRACE(("dowait(%d) called\n", block));
7337 pid = waitproc(block, &status);
7338 TRACE(("wait returns pid %d, status=%d\n", pid, status));
7343 for (jp = curjob; jp; jp = jp->prev_job) {
7344 struct procstat *sp;
7345 struct procstat *spend;
7346 if (jp->state == JOBDONE)
7349 spend = jp->ps + jp->nprocs;
7352 if (sp->pid == pid) {
7353 TRACE(("Job %d: changing status of proc %d from 0x%x to 0x%x\n", jobno(jp), pid, sp->status, status));
7354 sp->status = status;
7357 if (sp->status == -1)
7360 if (state == JOBRUNNING)
7362 if (WIFSTOPPED(sp->status)) {
7363 jp->stopstatus = sp->status;
7367 } while (++sp < spend);
7372 if (!WIFSTOPPED(status))
7379 if (state != JOBRUNNING) {
7380 thisjob->changed = 1;
7382 if (thisjob->state != state) {
7383 TRACE(("Job %d: changing state from %d to %d\n", jobno(thisjob), thisjob->state, state));
7384 thisjob->state = state;
7386 if (state == JOBSTOPPED) {
7387 set_curjob(thisjob, CUR_STOPPED);
7396 if (thisjob && thisjob == job) {
7400 len = sprint_status(s, status, 1);
7412 * return 1 if there are stopped jobs, otherwise 0
7425 if (jp && jp->state == JOBSTOPPED) {
7426 out2str("You have stopped jobs.\n");
7436 * Return a string identifying a command (to be printed by the
7441 static char *cmdnextc;
7444 commandtext(union node *n)
7448 STARTSTACKSTR(cmdnextc);
7450 name = stackblock();
7451 TRACE(("commandtext: name %p, end %p\n\t\"%s\"\n",
7452 name, cmdnextc, cmdnextc));
7453 return savestr(name);
7457 cmdtxt(union node *n)
7460 struct nodelist *lp;
7472 lp = n->npipe.cmdlist;
7490 cmdtxt(n->nbinary.ch1);
7506 cmdtxt(n->nif.test);
7509 if (n->nif.elsepart) {
7512 n = n->nif.elsepart;
7528 cmdtxt(n->nbinary.ch1);
7538 cmdputs(n->nfor.var);
7540 cmdlist(n->nfor.args, 1);
7545 cmdputs(n->narg.text);
7549 cmdlist(n->ncmd.args, 1);
7550 cmdlist(n->ncmd.redirect, 0);
7563 cmdputs(n->ncase.expr->narg.text);
7565 for (np = n->ncase.cases; np; np = np->nclist.next) {
7566 cmdtxt(np->nclist.pattern);
7568 cmdtxt(np->nclist.body);
7594 s[0] = n->nfile.fd + '0';
7598 if (n->type == NTOFD || n->type == NFROMFD) {
7599 s[0] = n->ndup.dupfd + '0';
7610 cmdlist(union node *np, int sep)
7612 for (; np; np = np->narg.next) {
7616 if (sep && np->narg.next)
7622 cmdputs(const char *s)
7624 const char *p, *str;
7625 char c, cc[2] = " ";
7629 static const char vstype[VSTYPE + 1][4] = {
7630 "", "}", "-", "+", "?", "=",
7631 "%", "%%", "#", "##"
7633 nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc);
7635 while ((c = *p++) != 0) {
7643 if ((subtype & VSTYPE) == VSLENGTH)
7647 if (!(subtype & VSQUOTE) != !(quoted & 1)) {
7654 str = "\"}" + !(quoted & 1);
7661 case CTLBACKQ+CTLQUOTE:
7664 #ifdef CONFIG_ASH_MATH_SUPPORT
7679 if ((subtype & VSTYPE) != VSNORMAL)
7681 str = vstype[subtype & VSTYPE];
7682 if (subtype & VSNUL)
7691 /* These can only happen inside quotes */
7704 while ((c = *str++)) {
7709 USTPUTC('"', nextc);
7717 showpipe(struct job *jp, FILE *out)
7719 struct procstat *sp;
7720 struct procstat *spend;
7722 spend = jp->ps + jp->nprocs;
7723 for (sp = jp->ps + 1; sp < spend; sp++)
7724 fprintf(out, " | %s", sp->cmd);
7725 outcslow('\n', out);
7730 xtcsetpgrp(int fd, pid_t pgrp)
7732 if (tcsetpgrp(fd, pgrp))
7733 sh_error("Cannot set tty process group (%m)");
7738 getstatus(struct job *job) {
7742 status = job->ps[job->nprocs - 1].status;
7743 retval = WEXITSTATUS(status);
7744 if (!WIFEXITED(status)) {
7746 retval = WSTOPSIG(status);
7747 if (!WIFSTOPPED(status))
7750 /* XXX: limits number of signals */
7751 retval = WTERMSIG(status);
7753 if (retval == SIGINT)
7759 TRACE(("getstatus: job %d, nproc %d, status %x, retval %x\n",
7760 jobno(job), job->nprocs, status, retval));
7764 #ifdef CONFIG_ASH_MAIL
7768 * Routines to check for mail. (Perhaps make part of main.c?)
7771 #define MAXMBOXES 10
7773 /* times of mailboxes */
7774 static time_t mailtime[MAXMBOXES];
7775 /* Set if MAIL or MAILPATH is changed. */
7776 static int mail_var_path_changed;
7781 * Print appropriate message(s) if mail has arrived.
7782 * If mail_var_path_changed is set,
7783 * then the value of MAIL has mail_var_path_changed,
7784 * so we just update the values.
7794 struct stackmark smark;
7797 setstackmark(&smark);
7798 mpath = mpathset() ? mpathval() : mailval();
7799 for (mtp = mailtime; mtp < mailtime + MAXMBOXES; mtp++) {
7800 p = padvance(&mpath, nullstr);
7805 for (q = p ; *q ; q++);
7810 q[-1] = '\0'; /* delete trailing '/' */
7811 if (stat(p, &statb) < 0) {
7815 if (!mail_var_path_changed && statb.st_mtime != *mtp) {
7818 pathopt ? pathopt : "you have mail"
7821 *mtp = statb.st_mtime;
7823 mail_var_path_changed = 0;
7824 popstackmark(&smark);
7829 changemail(const char *val)
7831 mail_var_path_changed++;
7834 #endif /* CONFIG_ASH_MAIL */
7840 static short profile_buf[16384];
7844 static int isloginsh;
7846 static void read_profile(const char *);
7849 * Main routine. We initialize things, parse the arguments, execute
7850 * profiles if we're a login shell, and then call cmdloop to execute
7851 * commands. The setjmp call sets up the location to jump to when an
7852 * exception occurs. When an exception occurs the variable "state"
7853 * is used to figure out how far we had gotten.
7857 ash_main(int argc, char **argv)
7861 struct jmploc jmploc;
7862 struct stackmark smark;
7865 dash_errno = __errno_location();
7869 monitor(4, etext, profile_buf, sizeof profile_buf, 50);
7872 if (setjmp(jmploc.loc)) {
7882 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl)
7886 outcslow('\n', stderr);
7888 popstackmark(&smark);
7889 FORCEINTON; /* enable interrupts */
7902 trputs("Shell args: "); trargs(argv);
7906 #ifdef CONFIG_ASH_RANDOM_SUPPORT
7907 rseed = rootpid + ((time_t)time((time_t *)0));
7910 setstackmark(&smark);
7911 procargs(argc, argv);
7912 #ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
7914 const char *hp = lookupvar("HISTFILE");
7917 hp = lookupvar("HOME");
7919 char *defhp = concat_path_file(hp, ".ash_history");
7920 setvar("HISTFILE", defhp, 0);
7926 if (argv[0] && argv[0][0] == '-')
7930 read_profile("/etc/profile");
7933 read_profile(".profile");
7939 getuid() == geteuid() && getgid() == getegid() &&
7943 if ((shinit = lookupvar("ENV")) != NULL && *shinit != '\0') {
7944 read_profile(shinit);
7950 evalstring(minusc, 0);
7952 if (sflag || minusc == NULL) {
7953 #ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
7955 const char *hp = lookupvar("HISTFILE");
7958 load_history ( hp );
7961 state4: /* XXX ??? - why isn't this before the "if" statement */
7969 extern void _mcleanup(void);
7979 * Read and execute commands. "Top" is nonzero for the top level command
7980 * loop; it turns on prompting if the shell is interactive.
7987 struct stackmark smark;
7991 TRACE(("cmdloop(%d) called\n", top));
7995 setstackmark(&smark);
7998 showjobs(stderr, SHOW_CHANGED);
8003 #ifdef CONFIG_ASH_MAIL
8007 n = parsecmd(inter);
8008 /* showtree(n); DEBUG */
8010 if (!top || numeof >= 50)
8012 if (!stoppedjobs()) {
8015 out2str("\nUse \"exit\" to leave shell.\n");
8018 } else if (nflag == 0) {
8019 job_warning = (job_warning == 2) ? 1 : 0;
8023 popstackmark(&smark);
8028 return skip & SKIPEVAL;
8037 * Read /etc/profile or .profile. Return on error.
8041 read_profile(const char *name)
8045 if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
8057 * Read a file containing shell functions.
8061 readcmdfile(char *name)
8063 setinputfile(name, INPUT_PUSH_FILE);
8070 * Take commands from a file. To be compatible we should do a path
8071 * search for the file, which is necessary to find sub-commands.
8074 static inline char *
8075 find_dot_file(char *name)
8078 const char *path = pathval();
8081 /* don't try this for absolute or relative paths */
8082 if (strchr(name, '/'))
8085 while ((fullname = padvance(&path, name)) != NULL) {
8086 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
8088 * Don't bother freeing here, since it will
8089 * be freed by the caller.
8093 stunalloc(fullname);
8096 /* not found in the PATH */
8097 sh_error(not_found_msg, name);
8101 static int dotcmd(int argc, char **argv)
8104 volatile struct shparam saveparam;
8107 for (sp = cmdenviron; sp; sp = sp->next)
8108 setvareq(bb_xstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
8110 if (argc >= 2) { /* That's what SVR2 does */
8113 fullname = find_dot_file(argv[1]);
8116 saveparam = shellparam;
8117 shellparam.malloc = 0;
8118 shellparam.nparam = argc - 2;
8119 shellparam.p = argv + 2;
8122 setinputfile(fullname, INPUT_PUSH_FILE);
8123 commandname = fullname;
8128 freeparam(&shellparam);
8129 shellparam = saveparam;
8131 status = exitstatus;
8138 exitcmd(int argc, char **argv)
8143 exitstatus = number(argv[1]);
8148 #ifdef CONFIG_ASH_BUILTIN_ECHO
8150 echocmd(int argc, char **argv)
8152 return bb_echo(argc, argv);
8156 #ifdef CONFIG_ASH_BUILTIN_TEST
8158 testcmd(int argc, char **argv)
8160 return bb_test(argc, argv);
8167 * Same for malloc, realloc, but returns an error when out of space.
8171 ckrealloc(pointer p, size_t nbytes)
8173 p = realloc(p, nbytes);
8175 sh_error(bb_msg_memory_exhausted);
8180 ckmalloc(size_t nbytes)
8182 return ckrealloc(NULL, nbytes);
8186 * Make a copy of a string in safe storage.
8190 savestr(const char *s)
8192 char *p = strdup(s);
8194 sh_error(bb_msg_memory_exhausted);
8200 * Parse trees for commands are allocated in lifo order, so we use a stack
8201 * to make this more efficient, and also to avoid all sorts of exception
8202 * handling code to handle interrupts in the middle of a parse.
8204 * The size 504 was chosen because the Ultrix malloc handles that size
8210 stalloc(size_t nbytes)
8215 aligned = SHELL_ALIGN(nbytes);
8216 if (aligned > stacknleft) {
8219 struct stack_block *sp;
8221 blocksize = aligned;
8222 if (blocksize < MINSIZE)
8223 blocksize = MINSIZE;
8224 len = sizeof(struct stack_block) - MINSIZE + blocksize;
8225 if (len < blocksize)
8226 sh_error(bb_msg_memory_exhausted);
8230 stacknxt = sp->space;
8231 stacknleft = blocksize;
8232 sstrend = stacknxt + blocksize;
8237 stacknxt += aligned;
8238 stacknleft -= aligned;
8244 stunalloc(pointer p)
8247 if (!p || (stacknxt < (char *)p) || ((char *)p < stackp->space)) {
8248 write(2, "stunalloc\n", 10);
8252 stacknleft += stacknxt - (char *)p;
8258 setstackmark(struct stackmark *mark)
8260 mark->stackp = stackp;
8261 mark->stacknxt = stacknxt;
8262 mark->stacknleft = stacknleft;
8263 mark->marknext = markp;
8269 popstackmark(struct stackmark *mark)
8271 struct stack_block *sp;
8274 markp = mark->marknext;
8275 while (stackp != mark->stackp) {
8280 stacknxt = mark->stacknxt;
8281 stacknleft = mark->stacknleft;
8282 sstrend = mark->stacknxt + mark->stacknleft;
8288 * When the parser reads in a string, it wants to stick the string on the
8289 * stack and only adjust the stack pointer when it knows how big the
8290 * string is. Stackblock (defined in stack.h) returns a pointer to a block
8291 * of space on top of the stack and stackblocklen returns the length of
8292 * this block. Growstackblock will grow this space by at least one byte,
8293 * possibly moving it (like realloc). Grabstackblock actually allocates the
8294 * part of the block that has been used.
8298 growstackblock(void)
8302 newlen = stacknleft * 2;
8303 if (newlen < stacknleft)
8304 sh_error(bb_msg_memory_exhausted);
8308 if (stacknxt == stackp->space && stackp != &stackbase) {
8309 struct stack_block *oldstackp;
8310 struct stackmark *xmark;
8311 struct stack_block *sp;
8312 struct stack_block *prevstackp;
8318 prevstackp = sp->prev;
8319 grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
8320 sp = ckrealloc((pointer)sp, grosslen);
8321 sp->prev = prevstackp;
8323 stacknxt = sp->space;
8324 stacknleft = newlen;
8325 sstrend = sp->space + newlen;
8328 * Stack marks pointing to the start of the old block
8329 * must be relocated to point to the new block
8332 while (xmark != NULL && xmark->stackp == oldstackp) {
8333 xmark->stackp = stackp;
8334 xmark->stacknxt = stacknxt;
8335 xmark->stacknleft = stacknleft;
8336 xmark = xmark->marknext;
8340 char *oldspace = stacknxt;
8341 int oldlen = stacknleft;
8342 char *p = stalloc(newlen);
8344 /* free the space we just allocated */
8345 stacknxt = memcpy(p, oldspace, oldlen);
8346 stacknleft += newlen;
8351 grabstackblock(size_t len)
8353 len = SHELL_ALIGN(len);
8359 * The following routines are somewhat easier to use than the above.
8360 * The user declares a variable of type STACKSTR, which may be declared
8361 * to be a register. The macro STARTSTACKSTR initializes things. Then
8362 * the user uses the macro STPUTC to add characters to the string. In
8363 * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
8364 * grown as necessary. When the user is done, she can just leave the
8365 * string there and refer to it using stackblock(). Or she can allocate
8366 * the space for it using grabstackstr(). If it is necessary to allow
8367 * someone else to use the stack temporarily and then continue to grow
8368 * the string, the user should use grabstack to allocate the space, and
8369 * then call ungrabstr(p) to return to the previous mode of operation.
8371 * USTPUTC is like STPUTC except that it doesn't check for overflow.
8372 * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
8373 * is space for at least one character.
8379 size_t len = stackblocksize();
8380 if (herefd >= 0 && len >= 1024) {
8381 full_write(herefd, stackblock(), len);
8382 return stackblock();
8385 return stackblock() + len;
8389 * Called from CHECKSTRSPACE.
8393 makestrspace(size_t newlen, char *p)
8395 size_t len = p - stacknxt;
8396 size_t size = stackblocksize();
8401 size = stackblocksize();
8403 if (nleft >= newlen)
8407 return stackblock() + len;
8411 stnputs(const char *s, size_t n, char *p)
8413 p = makestrspace(n, p);
8414 p = mempcpy(p, s, n);
8419 stputs(const char *s, char *p)
8421 return stnputs(s, strlen(s), p);
8429 * number(s) Convert a string of digits to an integer.
8430 * is_number(s) Return true if s is a string of digits.
8434 * prefix -- see if pfx is a prefix of string.
8438 prefix(const char *string, const char *pfx)
8441 if (*pfx++ != *string++)
8444 return (char *) string;
8449 * Convert a string of digits to an integer, printing an error message on
8454 number(const char *s)
8458 sh_error(illnum, s);
8464 * Check for a valid number. This should be elsewhere.
8468 is_number(const char *p)
8473 } while (*++p != '\0');
8479 * Produce a possibly single quoted string suitable as input to the shell.
8480 * The return string is allocated on the stack.
8484 single_quote(const char *s) {
8493 len = strchrnul(s, '\'') - s;
8495 q = p = makestrspace(len + 3, p);
8498 q = mempcpy(q, s, len);
8504 len = strspn(s, "'");
8508 q = p = makestrspace(len + 3, p);
8511 q = mempcpy(q, s, len);
8520 return stackblock();
8524 * Like strdup but works with the ash stack.
8528 sstrdup(const char *p)
8530 size_t len = strlen(p) + 1;
8531 return memcpy(stalloc(len), p, len);
8536 calcsize(union node *n)
8540 funcblocksize += nodesize[n->type];
8543 calcsize(n->ncmd.redirect);
8544 calcsize(n->ncmd.args);
8545 calcsize(n->ncmd.assign);
8548 sizenodelist(n->npipe.cmdlist);
8553 calcsize(n->nredir.redirect);
8554 calcsize(n->nredir.n);
8561 calcsize(n->nbinary.ch2);
8562 calcsize(n->nbinary.ch1);
8565 calcsize(n->nif.elsepart);
8566 calcsize(n->nif.ifpart);
8567 calcsize(n->nif.test);
8570 funcstringsize += strlen(n->nfor.var) + 1;
8571 calcsize(n->nfor.body);
8572 calcsize(n->nfor.args);
8575 calcsize(n->ncase.cases);
8576 calcsize(n->ncase.expr);
8579 calcsize(n->nclist.body);
8580 calcsize(n->nclist.pattern);
8581 calcsize(n->nclist.next);
8585 sizenodelist(n->narg.backquote);
8586 funcstringsize += strlen(n->narg.text) + 1;
8587 calcsize(n->narg.next);
8594 calcsize(n->nfile.fname);
8595 calcsize(n->nfile.next);
8599 calcsize(n->ndup.vname);
8600 calcsize(n->ndup.next);
8604 calcsize(n->nhere.doc);
8605 calcsize(n->nhere.next);
8608 calcsize(n->nnot.com);
8615 sizenodelist(struct nodelist *lp)
8618 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
8626 copynode(union node *n)
8633 funcblock = (char *) funcblock + nodesize[n->type];
8636 new->ncmd.redirect = copynode(n->ncmd.redirect);
8637 new->ncmd.args = copynode(n->ncmd.args);
8638 new->ncmd.assign = copynode(n->ncmd.assign);
8641 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
8642 new->npipe.backgnd = n->npipe.backgnd;
8647 new->nredir.redirect = copynode(n->nredir.redirect);
8648 new->nredir.n = copynode(n->nredir.n);
8655 new->nbinary.ch2 = copynode(n->nbinary.ch2);
8656 new->nbinary.ch1 = copynode(n->nbinary.ch1);
8659 new->nif.elsepart = copynode(n->nif.elsepart);
8660 new->nif.ifpart = copynode(n->nif.ifpart);
8661 new->nif.test = copynode(n->nif.test);
8664 new->nfor.var = nodesavestr(n->nfor.var);
8665 new->nfor.body = copynode(n->nfor.body);
8666 new->nfor.args = copynode(n->nfor.args);
8669 new->ncase.cases = copynode(n->ncase.cases);
8670 new->ncase.expr = copynode(n->ncase.expr);
8673 new->nclist.body = copynode(n->nclist.body);
8674 new->nclist.pattern = copynode(n->nclist.pattern);
8675 new->nclist.next = copynode(n->nclist.next);
8679 new->narg.backquote = copynodelist(n->narg.backquote);
8680 new->narg.text = nodesavestr(n->narg.text);
8681 new->narg.next = copynode(n->narg.next);
8688 new->nfile.fname = copynode(n->nfile.fname);
8689 new->nfile.fd = n->nfile.fd;
8690 new->nfile.next = copynode(n->nfile.next);
8694 new->ndup.vname = copynode(n->ndup.vname);
8695 new->ndup.dupfd = n->ndup.dupfd;
8696 new->ndup.fd = n->ndup.fd;
8697 new->ndup.next = copynode(n->ndup.next);
8701 new->nhere.doc = copynode(n->nhere.doc);
8702 new->nhere.fd = n->nhere.fd;
8703 new->nhere.next = copynode(n->nhere.next);
8706 new->nnot.com = copynode(n->nnot.com);
8709 new->type = n->type;
8714 static struct nodelist *
8715 copynodelist(struct nodelist *lp)
8717 struct nodelist *start;
8718 struct nodelist **lpp;
8723 funcblock = (char *) funcblock +
8724 SHELL_ALIGN(sizeof(struct nodelist));
8725 (*lpp)->n = copynode(lp->n);
8727 lpp = &(*lpp)->next;
8735 nodesavestr(char *s)
8737 char *rtn = funcstring;
8739 funcstring = stpcpy(funcstring, s) + 1;
8745 * Free a parse tree.
8749 freefunc(struct funcnode *f)
8751 if (f && --f->count < 0)
8756 static void options(int);
8757 static void setoption(int, int);
8761 * Process the shell command line arguments.
8765 procargs(int argc, char **argv)
8768 const char *xminusc;
8775 for (i = 0; i < NOPTS; i++)
8781 if (*xargv == NULL) {
8783 sh_error(bb_msg_requires_arg, "-c");
8786 if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
8790 for (i = 0; i < NOPTS; i++)
8791 if (optlist[i] == 2)
8796 /* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
8801 } else if (!sflag) {
8802 setinputfile(*xargv, 0);
8808 shellparam.p = xargv;
8809 #ifdef CONFIG_ASH_GETOPTS
8810 shellparam.optind = 1;
8811 shellparam.optoff = -1;
8813 /* assert(shellparam.malloc == 0 && shellparam.nparam == 0); */
8815 shellparam.nparam++;
8828 setinteractive(iflag);
8834 minus_o(char *name, int val)
8839 out1str("Current option settings\n");
8840 for (i = 0; i < NOPTS; i++)
8841 out1fmt("%-16s%s\n", optnames(i),
8842 optlist[i] ? "on" : "off");
8844 for (i = 0; i < NOPTS; i++)
8845 if (equal(name, optnames(i))) {
8849 sh_error("Illegal option -o %s", name);
8854 * Process shell options. The global variable argptr contains a pointer
8855 * to the argument list; we advance it past the options.
8859 options(int cmdline)
8867 while ((p = *argptr) != NULL) {
8869 if ((c = *p++) == '-') {
8871 if (p[0] == '\0' || (p[0] == '-' && p[1] == '\0')) {
8873 /* "-" means turn off -x and -v */
8876 /* "--" means reset params */
8877 else if (*argptr == NULL)
8880 break; /* "-" or "--" terminates options */
8882 } else if (c == '+') {
8888 while ((c = *p++) != '\0') {
8889 if (c == 'c' && cmdline) {
8890 minusc = p; /* command is after shell args*/
8891 } else if (c == 'o') {
8892 minus_o(*argptr, val);
8895 } else if (cmdline && (c == '-')) { // long options
8896 if (strcmp(p, "login") == 0)
8908 setoption(int flag, int val)
8912 for (i = 0; i < NOPTS; i++)
8913 if (optletters(i) == flag) {
8917 sh_error("Illegal option -%c", flag);
8924 * Set the shell parameters.
8928 setparam(char **argv)
8934 for (nparam = 0 ; argv[nparam] ; nparam++);
8935 ap = newparam = ckmalloc((nparam + 1) * sizeof *ap);
8937 *ap++ = savestr(*argv++);
8940 freeparam(&shellparam);
8941 shellparam.malloc = 1;
8942 shellparam.nparam = nparam;
8943 shellparam.p = newparam;
8944 #ifdef CONFIG_ASH_GETOPTS
8945 shellparam.optind = 1;
8946 shellparam.optoff = -1;
8952 * Free the list of positional parameters.
8956 freeparam(volatile struct shparam *param)
8960 if (param->malloc) {
8961 for (ap = param->p ; *ap ; ap++)
8970 * The shift builtin command.
8974 shiftcmd(int argc, char **argv)
8981 n = number(argv[1]);
8982 if (n > shellparam.nparam)
8983 sh_error("can't shift that many");
8985 shellparam.nparam -= n;
8986 for (ap1 = shellparam.p ; --n >= 0 ; ap1++) {
8987 if (shellparam.malloc)
8991 while ((*ap2++ = *ap1++) != NULL);
8992 #ifdef CONFIG_ASH_GETOPTS
8993 shellparam.optind = 1;
8994 shellparam.optoff = -1;
9003 * The set command builtin.
9007 setcmd(int argc, char **argv)
9010 return showvars(nullstr, 0, VUNSET);
9014 if (*argptr != NULL) {
9022 #ifdef CONFIG_ASH_GETOPTS
9024 getoptsreset(const char *value)
9026 shellparam.optind = number(value);
9027 shellparam.optoff = -1;
9031 #ifdef CONFIG_LOCALE_SUPPORT
9032 static void change_lc_all(const char *value)
9034 if (value != 0 && *value != 0)
9035 setlocale(LC_ALL, value);
9038 static void change_lc_ctype(const char *value)
9040 if (value != 0 && *value != 0)
9041 setlocale(LC_CTYPE, value);
9046 #ifdef CONFIG_ASH_RANDOM_SUPPORT
9047 /* Roughly copied from bash.. */
9048 static void change_random(const char *value)
9051 /* "get", generate */
9054 rseed = rseed * 1103515245 + 12345;
9055 sprintf(buf, "%d", (unsigned int)((rseed & 32767)));
9056 /* set without recursion */
9057 setvar(vrandom.text, buf, VNOFUNC);
9058 vrandom.flags &= ~VNOFUNC;
9061 rseed = strtoul(value, (char **)NULL, 10);
9067 #ifdef CONFIG_ASH_GETOPTS
9069 getopts(char *optstr, char *optvar, char **optfirst, int *param_optind, int *optoff)
9078 if(*param_optind < 1)
9080 optnext = optfirst + *param_optind - 1;
9082 if (*param_optind <= 1 || *optoff < 0 || strlen(optnext[-1]) < *optoff)
9085 p = optnext[-1] + *optoff;
9086 if (p == NULL || *p == '\0') {
9087 /* Current word is done, advance */
9089 if (p == NULL || *p != '-' || *++p == '\0') {
9096 if (p[0] == '-' && p[1] == '\0') /* check for "--" */
9101 for (q = optstr; *q != c; ) {
9103 if (optstr[0] == ':') {
9106 err |= setvarsafe("OPTARG", s, 0);
9108 fprintf(stderr, "Illegal option -%c\n", c);
9109 (void) unsetvar("OPTARG");
9119 if (*p == '\0' && (p = *optnext) == NULL) {
9120 if (optstr[0] == ':') {
9123 err |= setvarsafe("OPTARG", s, 0);
9126 fprintf(stderr, "No arg for -%c option\n", c);
9127 (void) unsetvar("OPTARG");
9135 err |= setvarsafe("OPTARG", p, 0);
9138 err |= setvarsafe("OPTARG", nullstr, 0);
9141 *optoff = p ? p - *(optnext - 1) : -1;
9142 *param_optind = optnext - optfirst + 1;
9143 fmtstr(s, sizeof(s), "%d", *param_optind);
9144 err |= setvarsafe("OPTIND", s, VNOFUNC);
9147 err |= setvarsafe(optvar, s, 0);
9158 * The getopts builtin. Shellparam.optnext points to the next argument
9159 * to be processed. Shellparam.optptr points to the next character to
9160 * be processed in the current argument. If shellparam.optnext is NULL,
9161 * then it's the first time getopts has been called.
9165 getoptscmd(int argc, char **argv)
9170 sh_error("Usage: getopts optstring var [arg]");
9171 else if (argc == 3) {
9172 optbase = shellparam.p;
9173 if (shellparam.optind > shellparam.nparam + 1) {
9174 shellparam.optind = 1;
9175 shellparam.optoff = -1;
9180 if (shellparam.optind > argc - 2) {
9181 shellparam.optind = 1;
9182 shellparam.optoff = -1;
9186 return getopts(argv[1], argv[2], optbase, &shellparam.optind,
9187 &shellparam.optoff);
9189 #endif /* CONFIG_ASH_GETOPTS */
9192 * XXX - should get rid of. have all builtins use getopt(3). the
9193 * library getopt must have the BSD extension static variable "optreset"
9194 * otherwise it can't be used within the shell safely.
9196 * Standard option processing (a la getopt) for builtin routines. The
9197 * only argument that is passed to nextopt is the option string; the
9198 * other arguments are unnecessary. It return the character, or '\0' on
9203 nextopt(const char *optstring)
9209 if ((p = optptr) == NULL || *p == '\0') {
9211 if (p == NULL || *p != '-' || *++p == '\0')
9214 if (p[0] == '-' && p[1] == '\0') /* check for "--" */
9218 for (q = optstring ; *q != c ; ) {
9220 sh_error("Illegal option -%c", c);
9225 if (*p == '\0' && (p = *argptr++) == NULL)
9226 sh_error("No arg for -%c option", c);
9238 outstr(const char *p, FILE *file)
9263 outcslow(int c, FILE *dest)
9273 out1fmt(const char *fmt, ...)
9280 r = vprintf(fmt, ap);
9288 fmtstr(char *outbuf, size_t length, const char *fmt, ...)
9295 ret = vsnprintf(outbuf, length, fmt, ap);
9307 * Shell command parser.
9310 #define EOFMARKLEN 79
9314 struct heredoc *next; /* next here document in list */
9315 union node *here; /* redirection node */
9316 char *eofmark; /* string indicating end of input */
9317 int striptabs; /* if set, strip leading tabs */
9322 static struct heredoc *heredoclist; /* list of here documents to read */
9325 static union node *list(int);
9326 static union node *andor(void);
9327 static union node *pipeline(void);
9328 static union node *command(void);
9329 static union node *simplecmd(void);
9330 static union node *makename(void);
9331 static void parsefname(void);
9332 static void parseheredoc(void);
9333 static char peektoken(void);
9334 static int readtoken(void);
9335 static int xxreadtoken(void);
9336 static int readtoken1(int firstc, int syntax, char *eofmark, int striptabs);
9337 static int noexpand(char *);
9338 static void synexpect(int) ATTRIBUTE_NORETURN;
9339 static void synerror(const char *) ATTRIBUTE_NORETURN;
9340 static void setprompt(int);
9346 * Read and parse a command. Returns NEOF on end of file. (NULL is a
9347 * valid parse tree indicating a blank line.)
9351 parsecmd(int interact)
9356 doprompt = interact;
9358 setprompt(doprompt);
9373 union node *n1, *n2, *n3;
9376 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9377 if (nlflag == 2 && peektoken())
9383 if (tok == TBACKGND) {
9384 if (n2->type == NPIPE) {
9385 n2->npipe.backgnd = 1;
9387 if (n2->type != NREDIR) {
9388 n3 = stalloc(sizeof(struct nredir));
9390 n3->nredir.redirect = NULL;
9393 n2->type = NBACKGND;
9400 n3 = (union node *)stalloc(sizeof (struct nbinary));
9402 n3->nbinary.ch1 = n1;
9403 n3->nbinary.ch2 = n2;
9419 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9427 pungetc(); /* push back EOF on input */
9443 union node *n1, *n2, *n3;
9448 if ((t = readtoken()) == TAND) {
9450 } else if (t == TOR) {
9456 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9458 n3 = (union node *)stalloc(sizeof (struct nbinary));
9460 n3->nbinary.ch1 = n1;
9461 n3->nbinary.ch2 = n2;
9471 union node *n1, *n2, *pipenode;
9472 struct nodelist *lp, *prev;
9476 TRACE(("pipeline: entered\n"));
9477 if (readtoken() == TNOT) {
9479 checkkwd = CHKKWD | CHKALIAS;
9483 if (readtoken() == TPIPE) {
9484 pipenode = (union node *)stalloc(sizeof (struct npipe));
9485 pipenode->type = NPIPE;
9486 pipenode->npipe.backgnd = 0;
9487 lp = (struct nodelist *)stalloc(sizeof (struct nodelist));
9488 pipenode->npipe.cmdlist = lp;
9492 lp = (struct nodelist *)stalloc(sizeof (struct nodelist));
9493 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9496 } while (readtoken() == TPIPE);
9502 n2 = (union node *)stalloc(sizeof (struct nnot));
9515 union node *n1, *n2;
9516 union node *ap, **app;
9517 union node *cp, **cpp;
9518 union node *redir, **rpp;
9525 switch (readtoken()) {
9530 n1 = (union node *)stalloc(sizeof (struct nif));
9532 n1->nif.test = list(0);
9533 if (readtoken() != TTHEN)
9535 n1->nif.ifpart = list(0);
9537 while (readtoken() == TELIF) {
9538 n2->nif.elsepart = (union node *)stalloc(sizeof (struct nif));
9539 n2 = n2->nif.elsepart;
9541 n2->nif.test = list(0);
9542 if (readtoken() != TTHEN)
9544 n2->nif.ifpart = list(0);
9546 if (lasttoken == TELSE)
9547 n2->nif.elsepart = list(0);
9549 n2->nif.elsepart = NULL;
9557 n1 = (union node *)stalloc(sizeof (struct nbinary));
9558 n1->type = (lasttoken == TWHILE)? NWHILE : NUNTIL;
9559 n1->nbinary.ch1 = list(0);
9560 if ((got=readtoken()) != TDO) {
9561 TRACE(("expecting DO got %s %s\n", tokname(got), got == TWORD ? wordtext : ""));
9564 n1->nbinary.ch2 = list(0);
9569 if (readtoken() != TWORD || quoteflag || ! goodname(wordtext))
9570 synerror("Bad for loop variable");
9571 n1 = (union node *)stalloc(sizeof (struct nfor));
9573 n1->nfor.var = wordtext;
9574 checkkwd = CHKKWD | CHKALIAS;
9575 if (readtoken() == TIN) {
9577 while (readtoken() == TWORD) {
9578 n2 = (union node *)stalloc(sizeof (struct narg));
9580 n2->narg.text = wordtext;
9581 n2->narg.backquote = backquotelist;
9583 app = &n2->narg.next;
9587 if (lasttoken != TNL && lasttoken != TSEMI)
9590 n2 = (union node *)stalloc(sizeof (struct narg));
9592 n2->narg.text = (char *)dolatstr;
9593 n2->narg.backquote = NULL;
9594 n2->narg.next = NULL;
9597 * Newline or semicolon here is optional (but note
9598 * that the original Bourne shell only allowed NL).
9600 if (lasttoken != TNL && lasttoken != TSEMI)
9603 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9604 if (readtoken() != TDO)
9606 n1->nfor.body = list(0);
9610 n1 = (union node *)stalloc(sizeof (struct ncase));
9612 if (readtoken() != TWORD)
9614 n1->ncase.expr = n2 = (union node *)stalloc(sizeof (struct narg));
9616 n2->narg.text = wordtext;
9617 n2->narg.backquote = backquotelist;
9618 n2->narg.next = NULL;
9620 checkkwd = CHKKWD | CHKALIAS;
9621 } while (readtoken() == TNL);
9622 if (lasttoken != TIN)
9624 cpp = &n1->ncase.cases;
9626 checkkwd = CHKNL | CHKKWD;
9629 if (lasttoken == TLP)
9631 *cpp = cp = (union node *)stalloc(sizeof (struct nclist));
9633 app = &cp->nclist.pattern;
9635 *app = ap = (union node *)stalloc(sizeof (struct narg));
9637 ap->narg.text = wordtext;
9638 ap->narg.backquote = backquotelist;
9639 if (readtoken() != TPIPE)
9641 app = &ap->narg.next;
9644 ap->narg.next = NULL;
9645 if (lasttoken != TRP)
9647 cp->nclist.body = list(2);
9649 cpp = &cp->nclist.next;
9651 checkkwd = CHKNL | CHKKWD;
9652 if ((t = readtoken()) != TESAC) {
9654 synexpect(TENDCASE);
9662 n1 = (union node *)stalloc(sizeof (struct nredir));
9663 n1->type = NSUBSHELL;
9664 n1->nredir.n = list(0);
9665 n1->nredir.redirect = NULL;
9678 if (readtoken() != t)
9682 /* Now check for redirection which may follow command */
9683 checkkwd = CHKKWD | CHKALIAS;
9685 while (readtoken() == TREDIR) {
9686 *rpp = n2 = redirnode;
9687 rpp = &n2->nfile.next;
9693 if (n1->type != NSUBSHELL) {
9694 n2 = (union node *)stalloc(sizeof (struct nredir));
9699 n1->nredir.redirect = redir;
9708 union node *args, **app;
9709 union node *n = NULL;
9710 union node *vars, **vpp;
9711 union node **rpp, *redir;
9721 savecheckkwd = CHKALIAS;
9723 checkkwd = savecheckkwd;
9724 switch (readtoken()) {
9726 n = (union node *)stalloc(sizeof (struct narg));
9728 n->narg.text = wordtext;
9729 n->narg.backquote = backquotelist;
9730 if (savecheckkwd && isassignment(wordtext)) {
9732 vpp = &n->narg.next;
9735 app = &n->narg.next;
9740 *rpp = n = redirnode;
9741 rpp = &n->nfile.next;
9742 parsefname(); /* read name of redirection file */
9746 args && app == &args->narg.next &&
9749 struct builtincmd *bcmd;
9752 /* We have a function */
9753 if (readtoken() != TRP)
9755 name = n->narg.text;
9757 !goodname(name) || (
9758 (bcmd = find_builtin(name)) &&
9759 IS_BUILTIN_SPECIAL(bcmd)
9762 synerror("Bad function name");
9764 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9765 n->narg.next = command();
9778 n = (union node *)stalloc(sizeof (struct ncmd));
9780 n->ncmd.args = args;
9781 n->ncmd.assign = vars;
9782 n->ncmd.redirect = redir;
9791 n = (union node *)stalloc(sizeof (struct narg));
9793 n->narg.next = NULL;
9794 n->narg.text = wordtext;
9795 n->narg.backquote = backquotelist;
9799 void fixredir(union node *n, const char *text, int err)
9801 TRACE(("Fix redir %s %d\n", text, err));
9803 n->ndup.vname = NULL;
9805 if (is_digit(text[0]) && text[1] == '\0')
9806 n->ndup.dupfd = digit_val(text[0]);
9807 else if (text[0] == '-' && text[1] == '\0')
9812 synerror("Bad fd number");
9814 n->ndup.vname = makename();
9822 union node *n = redirnode;
9824 if (readtoken() != TWORD)
9826 if (n->type == NHERE) {
9827 struct heredoc *here = heredoc;
9833 TRACE(("Here document %d\n", n->type));
9834 if (! noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)
9835 synerror("Illegal eof marker for << redirection");
9836 rmescapes(wordtext);
9837 here->eofmark = wordtext;
9839 if (heredoclist == NULL)
9842 for (p = heredoclist ; p->next ; p = p->next);
9845 } else if (n->type == NTOFD || n->type == NFROMFD) {
9846 fixredir(n, wordtext, 0);
9848 n->nfile.fname = makename();
9854 * Input any here documents.
9860 struct heredoc *here;
9870 readtoken1(pgetc(), here->here->type == NHERE? SQSYNTAX : DQSYNTAX,
9871 here->eofmark, here->striptabs);
9872 n = (union node *)stalloc(sizeof (struct narg));
9873 n->narg.type = NARG;
9874 n->narg.next = NULL;
9875 n->narg.text = wordtext;
9876 n->narg.backquote = backquotelist;
9877 here->here->nhere.doc = n;
9882 static char peektoken(void)
9888 return tokname_array[t][0];
9896 int alreadyseen = tokpushback;
9899 #ifdef CONFIG_ASH_ALIAS
9908 if (checkkwd & CHKNL) {
9915 if (t != TWORD || quoteflag) {
9920 * check for keywords
9922 if (checkkwd & CHKKWD) {
9923 const char *const *pp;
9925 if ((pp = findkwd(wordtext))) {
9926 lasttoken = t = pp - tokname_array;
9927 TRACE(("keyword %s recognized\n", tokname(t)));
9932 if (checkkwd & CHKALIAS) {
9933 #ifdef CONFIG_ASH_ALIAS
9935 if ((ap = lookupalias(wordtext, 1)) != NULL) {
9937 pushstring(ap->val, ap);
9947 TRACE(("token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
9949 TRACE(("reread token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
9956 * Read the next input token.
9957 * If the token is a word, we set backquotelist to the list of cmds in
9958 * backquotes. We set quoteflag to true if any part of the word was
9960 * If the token is TREDIR, then we set redirnode to a structure containing
9962 * In all cases, the variable startlinno is set to the number of the line
9963 * on which the token starts.
9965 * [Change comment: here documents and internal procedures]
9966 * [Readtoken shouldn't have any arguments. Perhaps we should make the
9967 * word parsing code into a separate routine. In this case, readtoken
9968 * doesn't need to have any internal procedures, but parseword does.
9969 * We could also make parseoperator in essence the main routine, and
9970 * have parseword (readtoken1?) handle both words and redirection.]
9973 #define NEW_xxreadtoken
9974 #ifdef NEW_xxreadtoken
9976 /* singles must be first! */
9977 static const char xxreadtoken_chars[7] = { '\n', '(', ')', '&', '|', ';', 0 };
9979 static const char xxreadtoken_tokens[] = {
9980 TNL, TLP, TRP, /* only single occurrence allowed */
9981 TBACKGND, TPIPE, TSEMI, /* if single occurrence */
9982 TEOF, /* corresponds to trailing nul */
9983 TAND, TOR, TENDCASE, /* if double occurrence */
9986 #define xxreadtoken_doubles \
9987 (sizeof(xxreadtoken_tokens) - sizeof(xxreadtoken_chars))
9988 #define xxreadtoken_singles \
9989 (sizeof(xxreadtoken_chars) - xxreadtoken_doubles - 1)
9991 static int xxreadtoken(void)
10002 startlinno = plinno;
10003 for (;;) { /* until token or start of word found */
10006 if ((c != ' ') && (c != '\t')
10007 #ifdef CONFIG_ASH_ALIAS
10012 while ((c = pgetc()) != '\n' && c != PEOF);
10014 } else if (c == '\\') {
10015 if (pgetc() != '\n') {
10019 startlinno = ++plinno;
10024 = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
10029 needprompt = doprompt;
10032 p = strchr(xxreadtoken_chars, c);
10035 return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
10038 if (p - xxreadtoken_chars >= xxreadtoken_singles) {
10039 if (pgetc() == *p) { /* double occurrence? */
10040 p += xxreadtoken_doubles + 1;
10047 return lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
10055 #define RETURN(token) return lasttoken = token
10069 startlinno = plinno;
10070 for (;;) { /* until token or start of word found */
10073 case ' ': case '\t':
10074 #ifdef CONFIG_ASH_ALIAS
10079 while ((c = pgetc()) != '\n' && c != PEOF);
10083 if (pgetc() == '\n') {
10084 startlinno = ++plinno;
10093 needprompt = doprompt;
10098 if (pgetc() == '&')
10103 if (pgetc() == '|')
10108 if (pgetc() == ';')
10121 return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
10124 #endif /* NEW_xxreadtoken */
10128 * If eofmark is NULL, read a word or a redirection symbol. If eofmark
10129 * is not NULL, read a here document. In the latter case, eofmark is the
10130 * word which marks the end of the document and striptabs is true if
10131 * leading tabs should be stripped from the document. The argument firstc
10132 * is the first character of the input token or document.
10134 * Because C does not have internal subroutines, I have simulated them
10135 * using goto's to implement the subroutine linkage. The following macros
10136 * will run code that appears at the end of readtoken1.
10139 #define CHECKEND() {goto checkend; checkend_return:;}
10140 #define PARSEREDIR() {goto parseredir; parseredir_return:;}
10141 #define PARSESUB() {goto parsesub; parsesub_return:;}
10142 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
10143 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
10144 #define PARSEARITH() {goto parsearith; parsearith_return:;}
10147 readtoken1(int firstc, int syntax, char *eofmark, int striptabs)
10152 char line[EOFMARKLEN + 1];
10153 struct nodelist *bqlist = 0;
10156 int varnest = 0; /* levels of variables expansion */
10157 int arinest = 0; /* levels of arithmetic expansion */
10158 int parenlevel = 0; /* levels of parens in arithmetic */
10159 int dqvarnest = 0; /* levels of variables expansion within double quotes */
10161 int prevsyntax = 0; /* syntax before arithmetic */
10163 /* Avoid longjmp clobbering */
10169 (void) &parenlevel;
10172 (void) &prevsyntax;
10176 startlinno = plinno;
10178 if (syntax == DQSYNTAX)
10187 STARTSTACKSTR(out);
10188 loop: { /* for each line, until end of word */
10189 CHECKEND(); /* set c to PEOF if at end of here document */
10190 for (;;) { /* until end of line or end of word */
10191 CHECKSTRSPACE(4, out); /* permit 4 calls to USTPUTC */
10192 switch(SIT(c, syntax)) {
10193 case CNL: /* '\n' */
10194 if (syntax == BASESYNTAX)
10195 goto endword; /* exit outer loop */
10201 goto loop; /* continue outer loop */
10206 if (eofmark == NULL || dblquote)
10207 USTPUTC(CTLESC, out);
10210 case CBACK: /* backslash */
10213 USTPUTC(CTLESC, out);
10214 USTPUTC('\\', out);
10216 } else if (c == '\n') {
10221 c != '\\' && c != '`' &&
10226 USTPUTC(CTLESC, out);
10227 USTPUTC('\\', out);
10229 if (SIT(c, SQSYNTAX) == CCTL)
10230 USTPUTC(CTLESC, out);
10238 if (eofmark == NULL) {
10239 USTPUTC(CTLQUOTEMARK, out);
10247 if (eofmark != NULL && arinest == 0 &&
10251 if (dqvarnest == 0) {
10252 syntax = BASESYNTAX;
10259 case CVAR: /* '$' */
10260 PARSESUB(); /* parse substitution */
10262 case CENDVAR: /* '}' */
10265 if (dqvarnest > 0) {
10268 USTPUTC(CTLENDVAR, out);
10273 #ifdef CONFIG_ASH_MATH_SUPPORT
10274 case CLP: /* '(' in arithmetic */
10278 case CRP: /* ')' in arithmetic */
10279 if (parenlevel > 0) {
10283 if (pgetc() == ')') {
10284 if (--arinest == 0) {
10285 USTPUTC(CTLENDARI, out);
10286 syntax = prevsyntax;
10287 if (syntax == DQSYNTAX)
10295 * unbalanced parens
10296 * (don't 2nd guess - no error)
10304 case CBQUOTE: /* '`' */
10308 goto endword; /* exit outer loop */
10313 goto endword; /* exit outer loop */
10314 #ifdef CONFIG_ASH_ALIAS
10324 #ifdef CONFIG_ASH_MATH_SUPPORT
10325 if (syntax == ARISYNTAX)
10326 synerror("Missing '))'");
10328 if (syntax != BASESYNTAX && ! parsebackquote && eofmark == NULL)
10329 synerror("Unterminated quoted string");
10330 if (varnest != 0) {
10331 startlinno = plinno;
10333 synerror("Missing '}'");
10335 USTPUTC('\0', out);
10336 len = out - (char *)stackblock();
10337 out = stackblock();
10338 if (eofmark == NULL) {
10339 if ((c == '>' || c == '<')
10342 && (*out == '\0' || is_digit(*out))) {
10344 return lasttoken = TREDIR;
10349 quoteflag = quotef;
10350 backquotelist = bqlist;
10351 grabstackblock(len);
10353 return lasttoken = TWORD;
10354 /* end of readtoken routine */
10359 * Check to see whether we are at the end of the here document. When this
10360 * is called, c is set to the first character of the next input line. If
10361 * we are at the end of the here document, this routine sets the c to PEOF.
10366 #ifdef CONFIG_ASH_ALIAS
10372 while (c == '\t') {
10376 if (c == *eofmark) {
10377 if (pfgets(line, sizeof line) != NULL) {
10381 for (q = eofmark + 1 ; *q && *p == *q ; p++, q++);
10382 if (*p == '\n' && *q == '\0') {
10385 needprompt = doprompt;
10387 pushstring(line, NULL);
10392 goto checkend_return;
10397 * Parse a redirection operator. The variable "out" points to a string
10398 * specifying the fd to be redirected. The variable "c" contains the
10399 * first character of the redirection operator.
10406 np = (union node *)stalloc(sizeof (struct nfile));
10411 np->type = NAPPEND;
10413 np->type = NCLOBBER;
10420 } else { /* c == '<' */
10422 switch (c = pgetc()) {
10424 if (sizeof (struct nfile) != sizeof (struct nhere)) {
10425 np = (union node *)stalloc(sizeof (struct nhere));
10429 heredoc = (struct heredoc *)stalloc(sizeof (struct heredoc));
10430 heredoc->here = np;
10431 if ((c = pgetc()) == '-') {
10432 heredoc->striptabs = 1;
10434 heredoc->striptabs = 0;
10440 np->type = NFROMFD;
10444 np->type = NFROMTO;
10454 np->nfile.fd = digit_val(fd);
10456 goto parseredir_return;
10461 * Parse a substitution. At this point, we have read the dollar sign
10462 * and nothing else.
10470 static const char types[] = "}-+?=";
10474 c <= PEOA_OR_PEOF ||
10475 (c != '(' && c != '{' && !is_name(c) && !is_special(c))
10479 } else if (c == '(') { /* $(command) or $((arith)) */
10480 if (pgetc() == '(') {
10481 #ifdef CONFIG_ASH_MATH_SUPPORT
10484 synerror("We unsupport $((arith))");
10491 USTPUTC(CTLVAR, out);
10492 typeloc = out - (char *)stackblock();
10493 USTPUTC(VSNORMAL, out);
10494 subtype = VSNORMAL;
10498 if ((c = pgetc()) == '}')
10501 subtype = VSLENGTH;
10506 if (c > PEOA_OR_PEOF && is_name(c)) {
10510 } while (c > PEOA_OR_PEOF && is_in_name(c));
10511 } else if (is_digit(c)) {
10515 } while (is_digit(c));
10517 else if (is_special(c)) {
10522 badsub: synerror("Bad substitution");
10526 if (subtype == 0) {
10533 p = strchr(types, c);
10536 subtype = p - types + VSNORMAL;
10542 subtype = c == '#' ? VSTRIMLEFT :
10555 if (dblquote || arinest)
10557 *((char *)stackblock() + typeloc) = subtype | flags;
10558 if (subtype != VSNORMAL) {
10560 if (dblquote || arinest) {
10565 goto parsesub_return;
10570 * Called to parse command substitutions. Newstyle is set if the command
10571 * is enclosed inside $(...); nlpp is a pointer to the head of the linked
10572 * list of commands (passed by reference), and savelen is the number of
10573 * characters on the top of the stack which must be preserved.
10577 struct nodelist **nlpp;
10580 char *volatile str;
10581 struct jmploc jmploc;
10582 struct jmploc *volatile savehandler;
10584 int saveprompt = 0;
10586 (void) &saveprompt;
10589 savepbq = parsebackquote;
10590 if (setjmp(jmploc.loc)) {
10593 parsebackquote = 0;
10594 handler = savehandler;
10595 longjmp(handler->loc, 1);
10599 savelen = out - (char *)stackblock();
10601 str = ckmalloc(savelen);
10602 memcpy(str, stackblock(), savelen);
10604 savehandler = handler;
10608 /* We must read until the closing backquote, giving special
10609 treatment to some slashes, and then push the string and
10610 reread it as input, interpreting it normally. */
10617 STARTSTACKSTR(pout);
10622 switch (pc = pgetc()) {
10627 if ((pc = pgetc()) == '\n') {
10632 * If eating a newline, avoid putting
10633 * the newline into the new character
10634 * stream (via the STPUTC after the
10639 if (pc != '\\' && pc != '`' && pc != '$'
10640 && (!dblquote || pc != '"'))
10641 STPUTC('\\', pout);
10642 if (pc > PEOA_OR_PEOF) {
10648 #ifdef CONFIG_ASH_ALIAS
10651 startlinno = plinno;
10652 synerror("EOF in backquote substitution");
10656 needprompt = doprompt;
10665 STPUTC('\0', pout);
10666 psavelen = pout - (char *)stackblock();
10667 if (psavelen > 0) {
10668 pstr = grabstackstr(pout);
10669 setinputstring(pstr);
10674 nlpp = &(*nlpp)->next;
10675 *nlpp = (struct nodelist *)stalloc(sizeof (struct nodelist));
10676 (*nlpp)->next = NULL;
10677 parsebackquote = oldstyle;
10680 saveprompt = doprompt;
10687 doprompt = saveprompt;
10689 if (readtoken() != TRP)
10696 * Start reading from old file again, ignoring any pushed back
10697 * tokens left from the backquote parsing
10702 while (stackblocksize() <= savelen)
10704 STARTSTACKSTR(out);
10706 memcpy(out, str, savelen);
10707 STADJUST(savelen, out);
10713 parsebackquote = savepbq;
10714 handler = savehandler;
10715 if (arinest || dblquote)
10716 USTPUTC(CTLBACKQ | CTLQUOTE, out);
10718 USTPUTC(CTLBACKQ, out);
10720 goto parsebackq_oldreturn;
10722 goto parsebackq_newreturn;
10725 #ifdef CONFIG_ASH_MATH_SUPPORT
10727 * Parse an arithmetic expansion (indicate start of one and set state)
10731 if (++arinest == 1) {
10732 prevsyntax = syntax;
10733 syntax = ARISYNTAX;
10734 USTPUTC(CTLARI, out);
10741 * we collapse embedded arithmetic expansion to
10742 * parenthesis, which should be equivalent
10746 goto parsearith_return;
10750 } /* end of readtoken */
10755 * Returns true if the text contains nothing to expand (no dollar signs
10760 noexpand(char *text)
10766 while ((c = *p++) != '\0') {
10767 if (c == CTLQUOTEMARK)
10771 else if (SIT(c, BASESYNTAX) == CCTL)
10779 * Return of a legal variable name (a letter or underscore followed by zero or
10780 * more letters, underscores, and digits).
10784 endofname(const char *name)
10792 if (! is_in_name(*p))
10800 * Called when an unexpected token is read during the parse. The argument
10801 * is the token that is expected, or -1 if more than one type of token can
10802 * occur at this point.
10805 static void synexpect(int token)
10810 l = sprintf(msg, "%s unexpected", tokname(lasttoken));
10812 sprintf(msg + l, " (expecting %s)", tokname(token));
10818 synerror(const char *msg)
10820 sh_error("Syntax error: %s", msg);
10826 * called by editline -- any expansions to the prompt
10827 * should be added here.
10830 #ifdef CONFIG_ASH_EXPAND_PRMT
10831 static const char *
10832 expandstr(const char *ps)
10836 /* XXX Fix (char *) cast. */
10837 setinputstring((char *)ps);
10838 readtoken1(pgetc(), DQSYNTAX, nullstr, 0);
10841 n.narg.type = NARG;
10842 n.narg.next = NULL;
10843 n.narg.text = wordtext;
10844 n.narg.backquote = backquotelist;
10846 expandarg(&n, NULL, 0);
10847 return stackblock();
10851 static void setprompt(int whichprompt)
10853 const char *prompt;
10854 #ifdef CONFIG_ASH_EXPAND_PRMT
10855 struct stackmark smark;
10860 switch (whichprompt) {
10870 #ifdef CONFIG_ASH_EXPAND_PRMT
10871 setstackmark(&smark);
10872 stalloc(stackblocksize());
10874 putprompt(expandstr(prompt));
10875 #ifdef CONFIG_ASH_EXPAND_PRMT
10876 popstackmark(&smark);
10881 static const char *const *findkwd(const char *s)
10883 return bsearch(s, tokname_array + KWDOFFSET,
10884 (sizeof(tokname_array) / sizeof(const char *)) - KWDOFFSET,
10885 sizeof(const char *), pstrcmp);
10891 * Code for dealing with input/output redirection.
10894 #define EMPTY -2 /* marks an unused slot in redirtab */
10896 # define PIPESIZE 4096 /* amount of buffering in a pipe */
10898 # define PIPESIZE PIPE_BUF
10902 * Open a file in noclobber mode.
10903 * The code was copied from bash.
10906 noclobberopen(const char *fname)
10909 struct stat finfo, finfo2;
10912 * If the file exists and is a regular file, return an error
10915 r = stat(fname, &finfo);
10916 if (r == 0 && S_ISREG(finfo.st_mode)) {
10922 * If the file was not present (r != 0), make sure we open it
10923 * exclusively so that if it is created before we open it, our open
10924 * will fail. Make sure that we do not truncate an existing file.
10925 * Note that we don't turn on O_EXCL unless the stat failed -- if the
10926 * file was not a regular file, we leave O_EXCL off.
10929 return open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
10930 fd = open(fname, O_WRONLY|O_CREAT, 0666);
10932 /* If the open failed, return the file descriptor right away. */
10937 * OK, the open succeeded, but the file may have been changed from a
10938 * non-regular file to a regular file between the stat and the open.
10939 * We are assuming that the O_EXCL open handles the case where FILENAME
10940 * did not exist and is symlinked to an existing file between the stat
10945 * If we can open it and fstat the file descriptor, and neither check
10946 * revealed that it was a regular file, and the file has not been
10947 * replaced, return the file descriptor.
10949 if (fstat(fd, &finfo2) == 0 && !S_ISREG(finfo2.st_mode) &&
10950 finfo.st_dev == finfo2.st_dev && finfo.st_ino == finfo2.st_ino)
10953 /* The file has been replaced. badness. */
10960 * Handle here documents. Normally we fork off a process to write the
10961 * data to a pipe. If the document is short, we can stuff the data in
10962 * the pipe without forking.
10966 openhere(union node *redir)
10972 sh_error("Pipe call failed");
10973 if (redir->type == NHERE) {
10974 len = strlen(redir->nhere.doc->narg.text);
10975 if (len <= PIPESIZE) {
10976 full_write(pip[1], redir->nhere.doc->narg.text, len);
10980 if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
10982 signal(SIGINT, SIG_IGN);
10983 signal(SIGQUIT, SIG_IGN);
10984 signal(SIGHUP, SIG_IGN);
10986 signal(SIGTSTP, SIG_IGN);
10988 signal(SIGPIPE, SIG_DFL);
10989 if (redir->type == NHERE)
10990 full_write(pip[1], redir->nhere.doc->narg.text, len);
10992 expandhere(redir->nhere.doc, pip[1]);
11001 openredirect(union node *redir)
11006 switch (redir->nfile.type) {
11008 fname = redir->nfile.expfname;
11009 if ((f = open(fname, O_RDONLY)) < 0)
11013 fname = redir->nfile.expfname;
11014 if ((f = open(fname, O_RDWR|O_CREAT|O_TRUNC, 0666)) < 0)
11018 /* Take care of noclobber mode. */
11020 fname = redir->nfile.expfname;
11021 if ((f = noclobberopen(fname)) < 0)
11027 fname = redir->nfile.expfname;
11028 if ((f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0)
11032 fname = redir->nfile.expfname;
11033 if ((f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666)) < 0)
11040 /* Fall through to eliminate warning. */
11047 f = openhere(redir);
11053 sh_error("cannot create %s: %s", fname, errmsg(errno, E_CREAT));
11055 sh_error("cannot open %s: %s", fname, errmsg(errno, E_OPEN));
11059 dupredirect(union node *redir, int f)
11061 int fd = redir->nfile.fd;
11063 if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
11064 if (redir->ndup.dupfd >= 0) { /* if not ">&-" */
11065 copyfd(redir->ndup.dupfd, fd);
11078 * Process a list of redirection commands. If the REDIR_PUSH flag is set,
11079 * old file descriptors are stashed away so that the redirection can be
11080 * undone by calling popredir. If the REDIR_BACKQ flag is set, then the
11081 * standard output, and the standard error if it becomes a duplicate of
11082 * stdout, is saved in memory.
11086 redirect(union node *redir, int flags)
11089 struct redirtab *sv;
11100 if (flags & REDIR_PUSH) {
11101 struct redirtab *q;
11102 q = ckmalloc(sizeof (struct redirtab));
11103 q->next = redirlist;
11105 q->nullredirs = nullredirs - 1;
11106 for (i = 0 ; i < 10 ; i++)
11107 q->renamed[i] = EMPTY;
11114 if ((n->nfile.type == NTOFD || n->nfile.type == NFROMFD) &&
11115 n->ndup.dupfd == fd)
11116 continue; /* redirect from/to same file descriptor */
11118 newfd = openredirect(n);
11121 if (sv && *(p = &sv->renamed[fd]) == EMPTY) {
11122 i = fcntl(fd, F_DUPFD, 10);
11129 sh_error("%d: %m", fd);
11139 dupredirect(n, newfd);
11140 } while ((n = n->nfile.next));
11142 if (flags & REDIR_SAVEFD2 && sv && sv->renamed[2] >= 0)
11143 preverrout_fd = sv->renamed[2];
11148 * Undo the effects of the last redirection.
11154 struct redirtab *rp;
11157 if (--nullredirs >= 0)
11161 for (i = 0 ; i < 10 ; i++) {
11162 if (rp->renamed[i] != EMPTY) {
11165 copyfd(rp->renamed[i], i);
11167 close(rp->renamed[i]);
11170 redirlist = rp->next;
11171 nullredirs = rp->nullredirs;
11177 * Undo all redirections. Called on error or interrupt.
11181 * Discard all saved file descriptors.
11185 clearredir(int drop)
11197 * Copy a file descriptor to be >= to. Returns -1
11198 * if the source file descriptor is closed, EMPTY if there are no unused
11199 * file descriptors left.
11203 copyfd(int from, int to)
11207 newfd = fcntl(from, F_DUPFD, to);
11209 if (errno == EMFILE)
11212 sh_error("%d: %m", from);
11219 redirectsafe(union node *redir, int flags)
11222 volatile int saveint;
11223 struct jmploc *volatile savehandler = handler;
11224 struct jmploc jmploc;
11227 if (!(err = setjmp(jmploc.loc) * 2)) {
11229 redirect(redir, flags);
11231 handler = savehandler;
11232 if (err && exception != EXERROR)
11233 longjmp(handler->loc, 1);
11234 RESTOREINT(saveint);
11241 static void shtree(union node *, int, char *, FILE*);
11242 static void shcmd(union node *, FILE *);
11243 static void sharg(union node *, FILE *);
11244 static void indent(int, char *, FILE *);
11245 static void trstring(char *);
11249 showtree(union node *n)
11251 trputs("showtree called\n");
11252 shtree(n, 1, NULL, stdout);
11257 shtree(union node *n, int ind, char *pfx, FILE *fp)
11259 struct nodelist *lp;
11265 indent(ind, pfx, fp);
11276 shtree(n->nbinary.ch1, ind, NULL, fp);
11279 shtree(n->nbinary.ch2, ind, NULL, fp);
11287 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
11292 if (n->npipe.backgnd)
11298 fprintf(fp, "<node type %d>", n->type);
11307 shcmd(union node *cmd, FILE *fp)
11315 for (np = cmd->ncmd.args ; np ; np = np->narg.next) {
11321 for (np = cmd->ncmd.redirect ; np ; np = np->nfile.next) {
11324 switch (np->nfile.type) {
11325 case NTO: s = ">"; dftfd = 1; break;
11326 case NCLOBBER: s = ">|"; dftfd = 1; break;
11327 case NAPPEND: s = ">>"; dftfd = 1; break;
11328 case NTOFD: s = ">&"; dftfd = 1; break;
11329 case NFROM: s = "<"; dftfd = 0; break;
11330 case NFROMFD: s = "<&"; dftfd = 0; break;
11331 case NFROMTO: s = "<>"; dftfd = 0; break;
11332 default: s = "*error*"; dftfd = 0; break;
11334 if (np->nfile.fd != dftfd)
11335 fprintf(fp, "%d", np->nfile.fd);
11337 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
11338 fprintf(fp, "%d", np->ndup.dupfd);
11340 sharg(np->nfile.fname, fp);
11349 sharg(union node *arg, FILE *fp)
11352 struct nodelist *bqlist;
11355 if (arg->type != NARG) {
11356 out1fmt("<node type %d>\n", arg->type);
11359 bqlist = arg->narg.backquote;
11360 for (p = arg->narg.text ; *p ; p++) {
11369 if (subtype == VSLENGTH)
11375 if (subtype & VSNUL)
11378 switch (subtype & VSTYPE) {
11397 case VSTRIMLEFTMAX:
11404 case VSTRIMRIGHTMAX:
11411 out1fmt("<subtype %d>", subtype);
11418 case CTLBACKQ|CTLQUOTE:
11421 shtree(bqlist->n, -1, NULL, fp);
11433 indent(int amount, char *pfx, FILE *fp)
11437 for (i = 0 ; i < amount ; i++) {
11438 if (pfx && i == amount - 1)
11459 putc(c, tracefile);
11463 trace(const char *fmt, ...)
11470 (void) vfprintf(tracefile, fmt, va);
11475 tracev(const char *fmt, va_list va)
11479 (void) vfprintf(tracefile, fmt, va);
11484 trputs(const char *s)
11488 fputs(s, tracefile);
11500 putc('"', tracefile);
11501 for (p = s ; *p ; p++) {
11503 case '\n': c = 'n'; goto backslash;
11504 case '\t': c = 't'; goto backslash;
11505 case '\r': c = 'r'; goto backslash;
11506 case '"': c = '"'; goto backslash;
11507 case '\\': c = '\\'; goto backslash;
11508 case CTLESC: c = 'e'; goto backslash;
11509 case CTLVAR: c = 'v'; goto backslash;
11510 case CTLVAR+CTLQUOTE: c = 'V'; goto backslash;
11511 case CTLBACKQ: c = 'q'; goto backslash;
11512 case CTLBACKQ+CTLQUOTE: c = 'Q'; goto backslash;
11513 backslash: putc('\\', tracefile);
11514 putc(c, tracefile);
11517 if (*p >= ' ' && *p <= '~')
11518 putc(*p, tracefile);
11520 putc('\\', tracefile);
11521 putc(*p >> 6 & 03, tracefile);
11522 putc(*p >> 3 & 07, tracefile);
11523 putc(*p & 07, tracefile);
11528 putc('"', tracefile);
11540 putc(' ', tracefile);
11542 putc('\n', tracefile);
11558 /* leave open because libedit might be using it */
11561 scopy("./trace", s);
11563 if (!freopen(s, "a", tracefile)) {
11564 fprintf(stderr, "Can't re-open %s\n", s);
11569 if ((tracefile = fopen(s, "a")) == NULL) {
11570 fprintf(stderr, "Can't open %s\n", s);
11576 if ((flags = fcntl(fileno(tracefile), F_GETFL, 0)) >= 0)
11577 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
11579 setlinebuf(tracefile);
11580 fputs("\nTracing started.\n", tracefile);
11588 * Sigmode records the current value of the signal handlers for the various
11589 * modes. A value of zero means that the current handler is not known.
11590 * S_HARD_IGN indicates that the signal was ignored on entry to the shell,
11593 #define S_DFL 1 /* default signal handling (SIG_DFL) */
11594 #define S_CATCH 2 /* signal is caught */
11595 #define S_IGN 3 /* signal is ignored (SIG_IGN) */
11596 #define S_HARD_IGN 4 /* signal is ignored permenantly */
11597 #define S_RESET 5 /* temporary - to reset a hard ignored sig */
11602 * The trap builtin.
11606 trapcmd(int argc, char **argv)
11615 for (signo = 0 ; signo < NSIG ; signo++) {
11616 if (trap[signo] != NULL) {
11619 sn = get_signame(signo);
11620 out1fmt("trap -- %s %s\n",
11621 single_quote(trap[signo]), sn);
11631 if ((signo = get_signum(*ap)) < 0)
11632 sh_error("%s: bad trap", *ap);
11635 if (action[0] == '-' && action[1] == '\0')
11638 action = savestr(action);
11641 ckfree(trap[signo]);
11642 trap[signo] = action;
11653 * Clear traps on a fork.
11661 for (tp = trap ; tp < &trap[NSIG] ; tp++) {
11662 if (*tp && **tp) { /* trap not NULL or SIG_IGN */
11666 if (tp != &trap[0])
11667 setsignal(tp - trap);
11675 * Set the signal handler for the specified signal. The routine figures
11676 * out what it should be set to.
11680 setsignal(int signo)
11684 struct sigaction act;
11686 if ((t = trap[signo]) == NULL)
11688 else if (*t != '\0')
11692 if (rootshell && action == S_DFL) {
11695 if (iflag || minusc || sflag == 0)
11718 t = &sigmode[signo - 1];
11722 * current setting unknown
11724 if (sigaction(signo, 0, &act) == -1) {
11726 * Pretend it worked; maybe we should give a warning
11727 * here, but other shells don't. We don't alter
11728 * sigmode, so that we retry every time.
11732 if (act.sa_handler == SIG_IGN) {
11733 if (mflag && (signo == SIGTSTP ||
11734 signo == SIGTTIN || signo == SIGTTOU)) {
11735 tsig = S_IGN; /* don't hard ignore these */
11739 tsig = S_RESET; /* force to be set */
11742 if (tsig == S_HARD_IGN || tsig == action)
11746 act.sa_handler = onsig;
11749 act.sa_handler = SIG_IGN;
11752 act.sa_handler = SIG_DFL;
11756 sigfillset(&act.sa_mask);
11757 sigaction(signo, &act, 0);
11765 ignoresig(int signo)
11767 if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
11768 signal(signo, SIG_IGN);
11770 sigmode[signo - 1] = S_HARD_IGN;
11781 gotsig[signo - 1] = 1;
11782 pendingsigs = signo;
11784 if (exsig || (signo == SIGINT && !trap[SIGINT])) {
11793 * Called to execute a trap. Perhaps we should avoid entering new trap
11794 * handlers while we are executing a trap handler.
11806 savestatus = exitstatus;
11810 for (i = 0, q = gotsig; i < NSIG - 1; i++, q++) {
11818 skip = evalstring(p, SKIPEVAL);
11819 exitstatus = savestatus;
11829 * Controls whether the shell is interactive or not.
11833 setinteractive(int on)
11835 static int is_interactive;
11837 if (++on == is_interactive)
11839 is_interactive = on;
11841 setsignal(SIGQUIT);
11842 setsignal(SIGTERM);
11843 #ifndef CONFIG_FEATURE_SH_EXTRA_QUIET
11844 if(is_interactive > 1) {
11845 /* Looks like they want an interactive shell */
11846 static int do_banner;
11850 "\n\n%s Built-in shell (ash)\n"
11851 "Enter 'help' for a list of built-in commands.\n\n",
11860 #ifndef CONFIG_FEATURE_SH_EXTRA_QUIET
11861 /*** List the available builtins ***/
11863 static int helpcmd(int argc, char **argv)
11867 out1fmt("\nBuilt-in commands:\n-------------------\n");
11868 for (col = 0, i = 0; i < NUMBUILTINS; i++) {
11869 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
11870 builtincmd[i].name + 1);
11876 #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
11878 extern const struct BB_applet applets[];
11879 extern const size_t NUM_APPLETS;
11881 for (i = 0; i < NUM_APPLETS; i++) {
11883 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), applets[i].name);
11892 return EXIT_SUCCESS;
11894 #endif /* CONFIG_FEATURE_SH_EXTRA_QUIET */
11897 * Called to exit the shell.
11907 status = exitstatus;
11908 TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
11909 if (setjmp(loc.loc)) {
11910 if (exception == EXEXIT)
11915 if ((p = trap[0])) {
11921 #ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
11922 if (iflag && rootshell) {
11923 const char *hp = lookupvar("HISTFILE");
11926 save_history ( hp );
11936 static struct var *vartab[VTABSIZE];
11938 static int vpcmp(const void *, const void *);
11939 static struct var **findvar(struct var **, const char *);
11942 * Initialize the variable symbol tables and import the environment
11946 #ifdef CONFIG_ASH_GETOPTS
11948 * Safe version of setvar, returns 1 on success 0 on failure.
11952 setvarsafe(const char *name, const char *val, int flags)
11955 volatile int saveint;
11956 struct jmploc *volatile savehandler = handler;
11957 struct jmploc jmploc;
11960 if (setjmp(jmploc.loc))
11964 setvar(name, val, flags);
11967 handler = savehandler;
11968 RESTOREINT(saveint);
11974 * Set the value of a variable. The flags argument is ored with the
11975 * flags of the variable. If val is NULL, the variable is unset.
11979 setvar(const char *name, const char *val, int flags)
11986 q = endofname(name);
11987 p = strchrnul(q, '=');
11988 namelen = p - name;
11989 if (!namelen || p != q)
11990 sh_error("%.*s: bad variable name", namelen, name);
11995 vallen = strlen(val);
11998 p = mempcpy(nameeq = ckmalloc(namelen + vallen + 2), name, namelen);
12001 p = mempcpy(p, val, vallen);
12004 setvareq(nameeq, flags | VNOSAVE);
12010 * Same as setvar except that the variable and value are passed in
12011 * the first argument as name=value. Since the first argument will
12012 * be actually stored in the table, it should not be a string that
12014 * Called with interrupts off.
12018 setvareq(char *s, int flags)
12020 struct var *vp, **vpp;
12023 flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
12024 vp = *findvar(vpp, s);
12026 if ((vp->flags & (VREADONLY|VDYNAMIC)) == VREADONLY) {
12029 if (flags & VNOSAVE)
12032 sh_error("%.*s: is read only", strchrnul(n, '=') - n, n);
12035 if (flags & VNOSET)
12038 if (vp->func && (flags & VNOFUNC) == 0)
12039 (*vp->func)(strchrnul(s, '=') + 1);
12041 if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
12044 flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET);
12046 if (flags & VNOSET)
12049 vp = ckmalloc(sizeof (*vp));
12054 if (!(flags & (VTEXTFIXED|VSTACK|VNOSAVE)))
12062 * Process a linked list of variable assignments.
12066 listsetvar(struct strlist *list_set_var, int flags)
12068 struct strlist *lp = list_set_var;
12074 setvareq(lp->text, flags);
12075 } while ((lp = lp->next));
12081 * Find the value of a variable. Returns NULL if not set.
12085 lookupvar(const char *name)
12089 if ((v = *findvar(hashvar(name), name))) {
12092 * Dynamic variables are implemented roughly the same way they are
12093 * in bash. Namely, they're "special" so long as they aren't unset.
12094 * As soon as they're unset, they're no longer dynamic, and dynamic
12095 * lookup will no longer happen at that point. -- PFM.
12097 if((v->flags & VDYNAMIC))
12100 if(!(v->flags & VUNSET))
12101 return strchrnul(v->text, '=') + 1;
12109 * Search the environment of a builtin command.
12113 bltinlookup(const char *name)
12115 struct strlist *sp;
12117 for (sp = cmdenviron ; sp ; sp = sp->next) {
12118 if (varequal(sp->text, name))
12119 return strchrnul(sp->text, '=') + 1;
12121 return lookupvar(name);
12126 * Generate a list of variables satisfying the given conditions.
12130 listvars(int on, int off, char ***end)
12141 for (vp = *vpp ; vp ; vp = vp->next)
12142 if ((vp->flags & mask) == on) {
12143 if (ep == stackstrend())
12144 ep = growstackstr();
12145 *ep++ = (char *) vp->text;
12147 } while (++vpp < vartab + VTABSIZE);
12148 if (ep == stackstrend())
12149 ep = growstackstr();
12153 return grabstackstr(ep);
12158 * POSIX requires that 'set' (but not export or readonly) output the
12159 * variables in lexicographic order - by the locale's collating order (sigh).
12160 * Maybe we could keep them in an ordered balanced binary tree
12161 * instead of hashed lists.
12162 * For now just roll 'em through qsort for printing...
12166 showvars(const char *sep_prefix, int on, int off)
12169 char **ep, **epend;
12171 ep = listvars(on, off, &epend);
12172 qsort(ep, epend - ep, sizeof(char *), vpcmp);
12174 sep = *sep_prefix ? spcstr : sep_prefix;
12176 for (; ep < epend; ep++) {
12180 p = strchrnul(*ep, '=');
12183 q = single_quote(++p);
12185 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
12194 * The export and readonly commands.
12198 exportcmd(int argc, char **argv)
12204 int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT;
12207 notp = nextopt("p") - 'p';
12208 if (notp && ((name = *(aptr = argptr)))) {
12210 if ((p = strchr(name, '=')) != NULL) {
12213 if ((vp = *findvar(hashvar(name), name))) {
12218 setvar(name, p, flag);
12219 } while ((name = *++aptr) != NULL);
12221 showvars(argv[0], flag, 0);
12228 * Make a variable a local variable. When a variable is made local, it's
12229 * value and flags are saved in a localvar structure. The saved values
12230 * will be restored when the shell function returns. We handle the name
12231 * "-" as a special case.
12235 mklocal(char *name)
12237 struct localvar *lvp;
12242 lvp = ckmalloc(sizeof (struct localvar));
12243 if (name[0] == '-' && name[1] == '\0') {
12245 p = ckmalloc(sizeof(optlist));
12246 lvp->text = memcpy(p, optlist, sizeof(optlist));
12251 vpp = hashvar(name);
12252 vp = *findvar(vpp, name);
12253 eq = strchr(name, '=');
12256 setvareq(name, VSTRFIXED);
12258 setvar(name, NULL, VSTRFIXED);
12259 vp = *vpp; /* the new variable */
12260 lvp->flags = VUNSET;
12262 lvp->text = vp->text;
12263 lvp->flags = vp->flags;
12264 vp->flags |= VSTRFIXED|VTEXTFIXED;
12270 lvp->next = localvars;
12276 * The "local" command.
12280 localcmd(int argc, char **argv)
12285 while ((name = *argv++) != NULL) {
12293 * Called after a function returns.
12294 * Interrupts must be off.
12300 struct localvar *lvp;
12303 while ((lvp = localvars) != NULL) {
12304 localvars = lvp->next;
12306 TRACE(("poplocalvar %s", vp ? vp->text : "-"));
12307 if (vp == NULL) { /* $- saved */
12308 memcpy(optlist, lvp->text, sizeof(optlist));
12311 } else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
12312 unsetvar(vp->text);
12315 (*vp->func)(strchrnul(lvp->text, '=') + 1);
12316 if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
12318 vp->flags = lvp->flags;
12319 vp->text = lvp->text;
12327 * The unset builtin command. We unset the function before we unset the
12328 * variable to allow a function to be unset when there is a readonly variable
12329 * with the same name.
12333 unsetcmd(int argc, char **argv)
12340 while ((i = nextopt("vf")) != '\0') {
12344 for (ap = argptr; *ap ; ap++) {
12359 * Unset the specified variable.
12363 unsetvar(const char *s)
12369 vpp = findvar(hashvar(s), s);
12373 int flags = vp->flags;
12376 if (flags & VREADONLY)
12379 vp->flags &= ~VDYNAMIC;
12381 if (flags & VUNSET)
12383 if ((flags & VSTRFIXED) == 0) {
12385 if ((flags & (VTEXTFIXED|VSTACK)) == 0)
12392 vp->flags &= ~VEXPORT;
12405 * Find the appropriate entry in the hash table from the name.
12408 static struct var **
12409 hashvar(const char *p)
12411 unsigned int hashval;
12413 hashval = ((unsigned char) *p) << 4;
12414 while (*p && *p != '=')
12415 hashval += (unsigned char) *p++;
12416 return &vartab[hashval % VTABSIZE];
12422 * Compares two strings up to the first = or '\0'. The first
12423 * string must be terminated by '='; the second may be terminated by
12424 * either '=' or '\0'.
12428 varcmp(const char *p, const char *q)
12432 while ((c = *p) == (d = *q)) {
12433 if (!c || c == '=')
12447 vpcmp(const void *a, const void *b)
12449 return varcmp(*(const char **)a, *(const char **)b);
12452 static struct var **
12453 findvar(struct var **vpp, const char *name)
12455 for (; *vpp; vpp = &(*vpp)->next) {
12456 if (varequal((*vpp)->text, name)) {
12464 #include <sys/times.h>
12466 static const unsigned char timescmd_str[] = {
12467 ' ', offsetof(struct tms, tms_utime),
12468 '\n', offsetof(struct tms, tms_stime),
12469 ' ', offsetof(struct tms, tms_cutime),
12470 '\n', offsetof(struct tms, tms_cstime),
12474 static int timescmd(int ac, char **av)
12476 long int clk_tck, s, t;
12477 const unsigned char *p;
12480 clk_tck = sysconf(_SC_CLK_TCK);
12485 t = *(clock_t *)(((char *) &buf) + p[1]);
12487 out1fmt("%ldm%ld.%.3lds%c",
12489 ((t - s * clk_tck) * 1000) / clk_tck,
12491 } while (*(p += 2));
12496 #ifdef CONFIG_ASH_MATH_SUPPORT
12498 dash_arith(const char *s)
12504 result = arith(s, &errcode);
12507 sh_error("exponent less than 0");
12508 else if (errcode == -2)
12509 sh_error("divide by zero");
12510 else if (errcode == -5)
12511 sh_error("expression recursion loop detected");
12522 * The let builtin. partial stolen from GNU Bash, the Bourne Again SHell.
12523 * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
12525 * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
12529 letcmd(int argc, char **argv)
12536 sh_error("expression expected");
12537 for (ap = argv + 1; *ap; ap++) {
12538 i = dash_arith(*ap);
12543 #endif /* CONFIG_ASH_MATH_SUPPORT */
12548 * Miscellaneous builtins.
12554 #if __GLIBC__ == 2 && __GLIBC_MINOR__ < 1
12555 typedef enum __rlimit_resource rlim_t;
12561 * The read builtin. The -e option causes backslashes to escape the
12562 * following character.
12564 * This uses unbuffered input, which may be avoidable in some cases.
12568 readcmd(int argc, char **argv)
12580 #if defined(CONFIG_ASH_READ_NCHARS)
12584 struct termios tty, old_tty;
12586 #if defined(CONFIG_ASH_READ_TIMEOUT)
12590 ts.tv_sec = ts.tv_usec = 0;
12595 #if defined(CONFIG_ASH_READ_NCHARS) && defined(CONFIG_ASH_READ_TIMEOUT)
12596 while ((i = nextopt("p:rt:n:s")) != '\0')
12597 #elif defined(CONFIG_ASH_READ_NCHARS)
12598 while ((i = nextopt("p:rn:s")) != '\0')
12599 #elif defined(CONFIG_ASH_READ_TIMEOUT)
12600 while ((i = nextopt("p:rt:")) != '\0')
12602 while ((i = nextopt("p:r")) != '\0')
12607 prompt = optionarg;
12609 #if defined(CONFIG_ASH_READ_NCHARS)
12611 nchars = strtol(optionarg, &p, 10);
12613 sh_error("invalid count");
12614 nch_flag = (nchars > 0);
12620 #if defined(CONFIG_ASH_READ_TIMEOUT)
12622 ts.tv_sec = strtol(optionarg, &p, 10);
12628 ts.tv_usec = strtol(p, &p2, 10);
12630 sh_error("invalid timeout");
12632 /* normalize to usec */
12634 sh_error("invalid timeout");
12635 while (scale++ < 6)
12639 sh_error("invalid timeout");
12641 if ( ! ts.tv_sec && ! ts.tv_usec)
12642 sh_error("invalid timeout");
12652 if (prompt && isatty(0)) {
12655 if (*(ap = argptr) == NULL)
12656 sh_error("arg count");
12657 if ((ifs = bltinlookup("IFS")) == NULL)
12659 #if defined(CONFIG_ASH_READ_NCHARS)
12660 if (nch_flag || silent) {
12661 tcgetattr(0, &tty);
12664 tty.c_lflag &= ~ICANON;
12665 tty.c_cc[VMIN] = nchars;
12668 tty.c_lflag &= ~(ECHO|ECHOK|ECHONL);
12671 tcsetattr(0, TCSANOW, &tty);
12674 #if defined(CONFIG_ASH_READ_TIMEOUT)
12675 if (ts.tv_sec || ts.tv_usec) {
12679 i = select (FD_SETSIZE, &set, NULL, NULL, &ts);
12681 #if defined(CONFIG_ASH_READ_NCHARS)
12683 tcsetattr(0, TCSANOW, &old_tty);
12693 #if defined(CONFIG_ASH_READ_NCHARS)
12694 while (!nch_flag || nchars--)
12699 if (read(0, &c, 1) != 1) {
12711 if (!rflag && c == '\\') {
12717 if (startword && *ifs == ' ' && strchr(ifs, c)) {
12721 if (ap[1] != NULL && strchr(ifs, c) != NULL) {
12723 setvar(*ap, stackblock(), 0);
12732 #if defined(CONFIG_ASH_READ_NCHARS)
12733 if (nch_flag || silent)
12734 tcsetattr(0, TCSANOW, &old_tty);
12738 /* Remove trailing blanks */
12739 while ((char *)stackblock() <= --p && strchr(ifs, *p) != NULL)
12741 setvar(*ap, stackblock(), 0);
12742 while (*++ap != NULL)
12743 setvar(*ap, nullstr, 0);
12748 static int umaskcmd(int argc, char **argv)
12750 static const char permuser[3] = "ugo";
12751 static const char permmode[3] = "rwx";
12752 static const short int permmask[] = {
12753 S_IRUSR, S_IWUSR, S_IXUSR,
12754 S_IRGRP, S_IWGRP, S_IXGRP,
12755 S_IROTH, S_IWOTH, S_IXOTH
12761 int symbolic_mode = 0;
12763 while (nextopt("S") != '\0') {
12772 if ((ap = *argptr) == NULL) {
12773 if (symbolic_mode) {
12777 for (i = 0; i < 3; i++) {
12780 *p++ = permuser[i];
12782 for (j = 0; j < 3; j++) {
12783 if ((mask & permmask[3 * i + j]) == 0) {
12784 *p++ = permmode[j];
12792 out1fmt("%.4o\n", mask);
12795 if (is_digit((unsigned char) *ap)) {
12798 if (*ap >= '8' || *ap < '0')
12799 sh_error(illnum, argv[1]);
12800 mask = (mask << 3) + (*ap - '0');
12801 } while (*++ap != '\0');
12804 mask = ~mask & 0777;
12805 if (!bb_parse_mode(ap, &mask)) {
12806 sh_error("Illegal mode: %s", ap);
12808 umask(~mask & 0777);
12817 * This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and
12818 * Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with
12819 * ash by J.T. Conklin.
12827 int factor; /* multiply by to get rlim_{cur,max} values */
12831 static const struct limits limits[] = {
12833 { "time(seconds)", RLIMIT_CPU, 1, 't' },
12835 #ifdef RLIMIT_FSIZE
12836 { "file(blocks)", RLIMIT_FSIZE, 512, 'f' },
12839 { "data(kbytes)", RLIMIT_DATA, 1024, 'd' },
12841 #ifdef RLIMIT_STACK
12842 { "stack(kbytes)", RLIMIT_STACK, 1024, 's' },
12845 { "coredump(blocks)", RLIMIT_CORE, 512, 'c' },
12848 { "memory(kbytes)", RLIMIT_RSS, 1024, 'm' },
12850 #ifdef RLIMIT_MEMLOCK
12851 { "locked memory(kbytes)", RLIMIT_MEMLOCK, 1024, 'l' },
12853 #ifdef RLIMIT_NPROC
12854 { "process", RLIMIT_NPROC, 1, 'p' },
12856 #ifdef RLIMIT_NOFILE
12857 { "nofiles", RLIMIT_NOFILE, 1, 'n' },
12860 { "vmemory(kbytes)", RLIMIT_AS, 1024, 'v' },
12862 #ifdef RLIMIT_LOCKS
12863 { "locks", RLIMIT_LOCKS, 1, 'w' },
12865 { (char *) 0, 0, 0, '\0' }
12868 enum limtype { SOFT = 0x1, HARD = 0x2 };
12870 static void printlim(enum limtype how, const struct rlimit *limit,
12871 const struct limits *l)
12875 val = limit->rlim_max;
12877 val = limit->rlim_cur;
12879 if (val == RLIM_INFINITY)
12880 out1fmt("unlimited\n");
12883 out1fmt("%lld\n", (long long) val);
12888 ulimitcmd(int argc, char **argv)
12892 enum limtype how = SOFT | HARD;
12893 const struct limits *l;
12896 struct rlimit limit;
12899 while ((optc = nextopt("HSa"
12903 #ifdef RLIMIT_FSIZE
12909 #ifdef RLIMIT_STACK
12918 #ifdef RLIMIT_MEMLOCK
12921 #ifdef RLIMIT_NPROC
12924 #ifdef RLIMIT_NOFILE
12930 #ifdef RLIMIT_LOCKS
12948 for (l = limits; l->option != what; l++)
12951 set = *argptr ? 1 : 0;
12955 if (all || argptr[1])
12956 sh_error("too many arguments");
12957 if (strncmp(p, "unlimited\n", 9) == 0)
12958 val = RLIM_INFINITY;
12962 while ((c = *p++) >= '0' && c <= '9')
12964 val = (val * 10) + (long)(c - '0');
12965 if (val < (rlim_t) 0)
12969 sh_error("bad number");
12974 for (l = limits; l->name; l++) {
12975 getrlimit(l->cmd, &limit);
12976 out1fmt("%-20s ", l->name);
12977 printlim(how, &limit, l);
12982 getrlimit(l->cmd, &limit);
12985 limit.rlim_max = val;
12987 limit.rlim_cur = val;
12988 if (setrlimit(l->cmd, &limit) < 0)
12989 sh_error("error setting limit (%m)");
12991 printlim(how, &limit, l);
12997 #ifdef CONFIG_ASH_MATH_SUPPORT
12999 /* Copyright (c) 2001 Aaron Lehmann <aaronl@vitelus.com>
13001 Permission is hereby granted, free of charge, to any person obtaining
13002 a copy of this software and associated documentation files (the
13003 "Software"), to deal in the Software without restriction, including
13004 without limitation the rights to use, copy, modify, merge, publish,
13005 distribute, sublicense, and/or sell copies of the Software, and to
13006 permit persons to whom the Software is furnished to do so, subject to
13007 the following conditions:
13009 The above copyright notice and this permission notice shall be
13010 included in all copies or substantial portions of the Software.
13012 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13013 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
13014 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
13015 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
13016 CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
13017 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
13018 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
13021 /* This is my infix parser/evaluator. It is optimized for size, intended
13022 * as a replacement for yacc-based parsers. However, it may well be faster
13023 * than a comparable parser written in yacc. The supported operators are
13024 * listed in #defines below. Parens, order of operations, and error handling
13025 * are supported. This code is thread safe. The exact expression format should
13026 * be that which POSIX specifies for shells. */
13028 /* The code uses a simple two-stack algorithm. See
13029 * http://www.onthenet.com.au/~grahamis/int2008/week02/lect02.html
13030 * for a detailed explanation of the infix-to-postfix algorithm on which
13031 * this is based (this code differs in that it applies operators immediately
13032 * to the stack instead of adding them to a queue to end up with an
13035 /* To use the routine, call it with an expression string and error return
13039 * Aug 24, 2001 Manuel Novoa III
13041 * Reduced the generated code size by about 30% (i386) and fixed several bugs.
13043 * 1) In arith_apply():
13044 * a) Cached values of *numptr and &(numptr[-1]).
13045 * b) Removed redundant test for zero denominator.
13048 * a) Eliminated redundant code for processing operator tokens by moving
13049 * to a table-based implementation. Also folded handling of parens
13051 * b) Combined all 3 loops which called arith_apply to reduce generated
13052 * code size at the cost of speed.
13054 * 3) The following expressions were treated as valid by the original code:
13055 * 1() , 0! , 1 ( *3 ) .
13056 * These bugs have been fixed by internally enclosing the expression in
13057 * parens and then checking that all binary ops and right parens are
13058 * preceded by a valid expression (NUM_TOKEN).
13060 * Note: It may be desirable to replace Aaron's test for whitespace with
13061 * ctype's isspace() if it is used by another busybox applet or if additional
13062 * whitespace chars should be considered. Look below the "#include"s for a
13063 * precompiler test.
13067 * Aug 26, 2001 Manuel Novoa III
13069 * Return 0 for null expressions. Pointed out by Vladimir Oleynik.
13071 * Merge in Aaron's comments previously posted to the busybox list,
13072 * modified slightly to take account of my changes to the code.
13077 * (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
13079 * - allow access to variable,
13080 * used recursive find value indirection (c=2*2; a="c"; $((a+=2)) produce 6)
13081 * - realize assign syntax (VAR=expr, +=, *= etc)
13082 * - realize exponentiation (** operator)
13083 * - realize comma separated - expr, expr
13084 * - realise ++expr --expr expr++ expr--
13085 * - realise expr ? expr : expr (but, second expr calculate always)
13086 * - allow hexadecimal and octal numbers
13087 * - was restored loses XOR operator
13088 * - remove one goto label, added three ;-)
13089 * - protect $((num num)) as true zero expr (Manuel`s error)
13090 * - always use special isspace(), see comment from bash ;-)
13094 #define arith_isspace(arithval) \
13095 (arithval == ' ' || arithval == '\n' || arithval == '\t')
13098 typedef unsigned char operator;
13100 /* An operator's token id is a bit of a bitfield. The lower 5 bits are the
13101 * precedence, and 3 high bits are an ID unique across operators of that
13102 * precedence. The ID portion is so that multiple operators can have the
13103 * same precedence, ensuring that the leftmost one is evaluated first.
13104 * Consider * and /. */
13106 #define tok_decl(prec,id) (((id)<<5)|(prec))
13107 #define PREC(op) ((op) & 0x1F)
13109 #define TOK_LPAREN tok_decl(0,0)
13111 #define TOK_COMMA tok_decl(1,0)
13113 #define TOK_ASSIGN tok_decl(2,0)
13114 #define TOK_AND_ASSIGN tok_decl(2,1)
13115 #define TOK_OR_ASSIGN tok_decl(2,2)
13116 #define TOK_XOR_ASSIGN tok_decl(2,3)
13117 #define TOK_PLUS_ASSIGN tok_decl(2,4)
13118 #define TOK_MINUS_ASSIGN tok_decl(2,5)
13119 #define TOK_LSHIFT_ASSIGN tok_decl(2,6)
13120 #define TOK_RSHIFT_ASSIGN tok_decl(2,7)
13122 #define TOK_MUL_ASSIGN tok_decl(3,0)
13123 #define TOK_DIV_ASSIGN tok_decl(3,1)
13124 #define TOK_REM_ASSIGN tok_decl(3,2)
13126 /* all assign is right associativity and precedence eq, but (7+3)<<5 > 256 */
13127 #define convert_prec_is_assing(prec) do { if(prec == 3) prec = 2; } while(0)
13129 /* conditional is right associativity too */
13130 #define TOK_CONDITIONAL tok_decl(4,0)
13131 #define TOK_CONDITIONAL_SEP tok_decl(4,1)
13133 #define TOK_OR tok_decl(5,0)
13135 #define TOK_AND tok_decl(6,0)
13137 #define TOK_BOR tok_decl(7,0)
13139 #define TOK_BXOR tok_decl(8,0)
13141 #define TOK_BAND tok_decl(9,0)
13143 #define TOK_EQ tok_decl(10,0)
13144 #define TOK_NE tok_decl(10,1)
13146 #define TOK_LT tok_decl(11,0)
13147 #define TOK_GT tok_decl(11,1)
13148 #define TOK_GE tok_decl(11,2)
13149 #define TOK_LE tok_decl(11,3)
13151 #define TOK_LSHIFT tok_decl(12,0)
13152 #define TOK_RSHIFT tok_decl(12,1)
13154 #define TOK_ADD tok_decl(13,0)
13155 #define TOK_SUB tok_decl(13,1)
13157 #define TOK_MUL tok_decl(14,0)
13158 #define TOK_DIV tok_decl(14,1)
13159 #define TOK_REM tok_decl(14,2)
13161 /* exponent is right associativity */
13162 #define TOK_EXPONENT tok_decl(15,1)
13164 /* For now unary operators. */
13165 #define UNARYPREC 16
13166 #define TOK_BNOT tok_decl(UNARYPREC,0)
13167 #define TOK_NOT tok_decl(UNARYPREC,1)
13169 #define TOK_UMINUS tok_decl(UNARYPREC+1,0)
13170 #define TOK_UPLUS tok_decl(UNARYPREC+1,1)
13172 #define PREC_PRE (UNARYPREC+2)
13174 #define TOK_PRE_INC tok_decl(PREC_PRE, 0)
13175 #define TOK_PRE_DEC tok_decl(PREC_PRE, 1)
13177 #define PREC_POST (UNARYPREC+3)
13179 #define TOK_POST_INC tok_decl(PREC_POST, 0)
13180 #define TOK_POST_DEC tok_decl(PREC_POST, 1)
13182 #define SPEC_PREC (UNARYPREC+4)
13184 #define TOK_NUM tok_decl(SPEC_PREC, 0)
13185 #define TOK_RPAREN tok_decl(SPEC_PREC, 1)
13187 #define NUMPTR (*numstackptr)
13189 static inline int tok_have_assign(operator op)
13191 operator prec = PREC(op);
13193 convert_prec_is_assing(prec);
13194 return (prec == PREC(TOK_ASSIGN) ||
13195 prec == PREC_PRE || prec == PREC_POST);
13198 static inline int is_right_associativity(operator prec)
13200 return (prec == PREC(TOK_ASSIGN) || prec == PREC(TOK_EXPONENT) ||
13201 prec == PREC(TOK_CONDITIONAL));
13205 typedef struct ARITCH_VAR_NUM {
13207 arith_t contidional_second_val;
13208 char contidional_second_val_initialized;
13209 char *var; /* if NULL then is regular number,
13210 else is variable name */
13214 typedef struct CHK_VAR_RECURSIVE_LOOPED {
13216 struct CHK_VAR_RECURSIVE_LOOPED *next;
13217 } chk_var_recursive_looped_t;
13219 static chk_var_recursive_looped_t *prev_chk_var_recursive;
13222 static int arith_lookup_val(v_n_t *t)
13225 const char * p = lookupvar(t->var);
13230 /* recursive try as expression */
13231 chk_var_recursive_looped_t *cur;
13232 chk_var_recursive_looped_t cur_save;
13234 for(cur = prev_chk_var_recursive; cur; cur = cur->next) {
13235 if(strcmp(cur->var, t->var) == 0) {
13236 /* expression recursion loop detected */
13240 /* save current lookuped var name */
13241 cur = prev_chk_var_recursive;
13242 cur_save.var = t->var;
13243 cur_save.next = cur;
13244 prev_chk_var_recursive = &cur_save;
13246 t->val = arith (p, &errcode);
13247 /* restore previous ptr after recursiving */
13248 prev_chk_var_recursive = cur;
13251 /* allow undefined var as 0 */
13258 /* "applying" a token means performing it on the top elements on the integer
13259 * stack. For a unary operator it will only change the top element, but a
13260 * binary operator will pop two arguments and push a result */
13262 arith_apply(operator op, v_n_t *numstack, v_n_t **numstackptr)
13265 arith_t numptr_val, rez;
13266 int ret_arith_lookup_val;
13268 if (NUMPTR == numstack) goto err; /* There is no operator that can work
13269 without arguments */
13270 numptr_m1 = NUMPTR - 1;
13272 /* check operand is var with noninteger value */
13273 ret_arith_lookup_val = arith_lookup_val(numptr_m1);
13274 if(ret_arith_lookup_val)
13275 return ret_arith_lookup_val;
13277 rez = numptr_m1->val;
13278 if (op == TOK_UMINUS)
13280 else if (op == TOK_NOT)
13282 else if (op == TOK_BNOT)
13284 else if (op == TOK_POST_INC || op == TOK_PRE_INC)
13286 else if (op == TOK_POST_DEC || op == TOK_PRE_DEC)
13288 else if (op != TOK_UPLUS) {
13289 /* Binary operators */
13291 /* check and binary operators need two arguments */
13292 if (numptr_m1 == numstack) goto err;
13294 /* ... and they pop one */
13297 if (op == TOK_CONDITIONAL) {
13298 if(! numptr_m1->contidional_second_val_initialized) {
13299 /* protect $((expr1 ? expr2)) without ": expr" */
13302 rez = numptr_m1->contidional_second_val;
13303 } else if(numptr_m1->contidional_second_val_initialized) {
13304 /* protect $((expr1 : expr2)) without "expr ? " */
13307 numptr_m1 = NUMPTR - 1;
13308 if(op != TOK_ASSIGN) {
13309 /* check operand is var with noninteger value for not '=' */
13310 ret_arith_lookup_val = arith_lookup_val(numptr_m1);
13311 if(ret_arith_lookup_val)
13312 return ret_arith_lookup_val;
13314 if (op == TOK_CONDITIONAL) {
13315 numptr_m1->contidional_second_val = rez;
13317 rez = numptr_m1->val;
13318 if (op == TOK_BOR || op == TOK_OR_ASSIGN)
13320 else if (op == TOK_OR)
13321 rez = numptr_val || rez;
13322 else if (op == TOK_BAND || op == TOK_AND_ASSIGN)
13324 else if (op == TOK_BXOR || op == TOK_XOR_ASSIGN)
13326 else if (op == TOK_AND)
13327 rez = rez && numptr_val;
13328 else if (op == TOK_EQ)
13329 rez = (rez == numptr_val);
13330 else if (op == TOK_NE)
13331 rez = (rez != numptr_val);
13332 else if (op == TOK_GE)
13333 rez = (rez >= numptr_val);
13334 else if (op == TOK_RSHIFT || op == TOK_RSHIFT_ASSIGN)
13335 rez >>= numptr_val;
13336 else if (op == TOK_LSHIFT || op == TOK_LSHIFT_ASSIGN)
13337 rez <<= numptr_val;
13338 else if (op == TOK_GT)
13339 rez = (rez > numptr_val);
13340 else if (op == TOK_LT)
13341 rez = (rez < numptr_val);
13342 else if (op == TOK_LE)
13343 rez = (rez <= numptr_val);
13344 else if (op == TOK_MUL || op == TOK_MUL_ASSIGN)
13346 else if (op == TOK_ADD || op == TOK_PLUS_ASSIGN)
13348 else if (op == TOK_SUB || op == TOK_MINUS_ASSIGN)
13350 else if (op == TOK_ASSIGN || op == TOK_COMMA)
13352 else if (op == TOK_CONDITIONAL_SEP) {
13353 if (numptr_m1 == numstack) {
13354 /* protect $((expr : expr)) without "expr ? " */
13357 numptr_m1->contidional_second_val_initialized = op;
13358 numptr_m1->contidional_second_val = numptr_val;
13360 else if (op == TOK_CONDITIONAL) {
13362 numptr_val : numptr_m1->contidional_second_val;
13364 else if(op == TOK_EXPONENT) {
13366 return -3; /* exponent less than 0 */
13371 while(numptr_val--)
13376 else if(numptr_val==0) /* zero divisor check */
13378 else if (op == TOK_DIV || op == TOK_DIV_ASSIGN)
13380 else if (op == TOK_REM || op == TOK_REM_ASSIGN)
13383 if(tok_have_assign(op)) {
13386 if(numptr_m1->var == NULL) {
13390 /* save to shell variable */
13391 #ifdef CONFIG_ASH_MATH_SUPPORT_64
13392 snprintf(buf, sizeof(buf), "%lld", arith_t_type rez);
13394 snprintf(buf, sizeof(buf), "%ld", arith_t_type rez);
13396 setvar(numptr_m1->var, buf, 0);
13397 /* after saving, make previous value for v++ or v-- */
13398 if(op == TOK_POST_INC)
13400 else if(op == TOK_POST_DEC)
13403 numptr_m1->val = rez;
13404 /* protect geting var value, is number now */
13405 numptr_m1->var = NULL;
13410 /* longest must first */
13411 static const char op_tokens[] = {
13412 '<','<','=',0, TOK_LSHIFT_ASSIGN,
13413 '>','>','=',0, TOK_RSHIFT_ASSIGN,
13414 '<','<', 0, TOK_LSHIFT,
13415 '>','>', 0, TOK_RSHIFT,
13416 '|','|', 0, TOK_OR,
13417 '&','&', 0, TOK_AND,
13418 '!','=', 0, TOK_NE,
13419 '<','=', 0, TOK_LE,
13420 '>','=', 0, TOK_GE,
13421 '=','=', 0, TOK_EQ,
13422 '|','=', 0, TOK_OR_ASSIGN,
13423 '&','=', 0, TOK_AND_ASSIGN,
13424 '*','=', 0, TOK_MUL_ASSIGN,
13425 '/','=', 0, TOK_DIV_ASSIGN,
13426 '%','=', 0, TOK_REM_ASSIGN,
13427 '+','=', 0, TOK_PLUS_ASSIGN,
13428 '-','=', 0, TOK_MINUS_ASSIGN,
13429 '-','-', 0, TOK_POST_DEC,
13430 '^','=', 0, TOK_XOR_ASSIGN,
13431 '+','+', 0, TOK_POST_INC,
13432 '*','*', 0, TOK_EXPONENT,
13436 '=', 0, TOK_ASSIGN,
13448 '?', 0, TOK_CONDITIONAL,
13449 ':', 0, TOK_CONDITIONAL_SEP,
13450 ')', 0, TOK_RPAREN,
13451 '(', 0, TOK_LPAREN,
13455 #define endexpression &op_tokens[sizeof(op_tokens)-7]
13458 static arith_t arith (const char *expr, int *perrcode)
13460 char arithval; /* Current character under analysis */
13461 operator lasttok, op;
13464 const char *p = endexpression;
13467 size_t datasizes = strlen(expr) + 2;
13469 /* Stack of integers */
13470 /* The proof that there can be no more than strlen(startbuf)/2+1 integers
13471 * in any given correct or incorrect expression is left as an exercise to
13473 v_n_t *numstack = alloca(((datasizes)/2)*sizeof(v_n_t)),
13474 *numstackptr = numstack;
13475 /* Stack of operator tokens */
13476 operator *stack = alloca((datasizes) * sizeof(operator)),
13479 *stackptr++ = lasttok = TOK_LPAREN; /* start off with a left paren */
13480 *perrcode = errcode = 0;
13483 if ((arithval = *expr) == 0) {
13484 if (p == endexpression) {
13485 /* Null expression. */
13489 /* This is only reached after all tokens have been extracted from the
13490 * input stream. If there are still tokens on the operator stack, they
13491 * are to be applied in order. At the end, there should be a final
13492 * result on the integer stack */
13494 if (expr != endexpression + 1) {
13495 /* If we haven't done so already, */
13496 /* append a closing right paren */
13497 expr = endexpression;
13498 /* and let the loop process it. */
13501 /* At this point, we're done with the expression. */
13502 if (numstackptr != numstack+1) {
13503 /* ... but if there isn't, it's bad */
13505 return (*perrcode = -1);
13507 if(numstack->var) {
13508 /* expression is $((var)) only, lookup now */
13509 errcode = arith_lookup_val(numstack);
13512 *perrcode = errcode;
13513 return numstack->val;
13515 /* Continue processing the expression. */
13516 if (arith_isspace(arithval)) {
13517 /* Skip whitespace */
13520 if((p = endofname(expr)) != expr) {
13521 size_t var_name_size = (p-expr) + 1; /* trailing zero */
13523 numstackptr->var = alloca(var_name_size);
13524 safe_strncpy(numstackptr->var, expr, var_name_size);
13527 numstackptr->contidional_second_val_initialized = 0;
13531 } else if (is_digit(arithval)) {
13532 numstackptr->var = NULL;
13533 #ifdef CONFIG_ASH_MATH_SUPPORT_64
13534 numstackptr->val = strtoll(expr, (char **) &expr, 0);
13536 numstackptr->val = strtol(expr, (char **) &expr, 0);
13540 for(p = op_tokens; ; p++) {
13544 /* strange operator not found */
13547 for(o = expr; *p && *o == *p; p++)
13554 /* skip tail uncompared token */
13557 /* skip zero delim */
13562 /* post grammar: a++ reduce to num */
13563 if(lasttok == TOK_POST_INC || lasttok == TOK_POST_DEC)
13566 /* Plus and minus are binary (not unary) _only_ if the last
13567 * token was as number, or a right paren (which pretends to be
13568 * a number, since it evaluates to one). Think about it.
13569 * It makes sense. */
13570 if (lasttok != TOK_NUM) {
13586 /* We don't want a unary operator to cause recursive descent on the
13587 * stack, because there can be many in a row and it could cause an
13588 * operator to be evaluated before its argument is pushed onto the
13589 * integer stack. */
13590 /* But for binary operators, "apply" everything on the operator
13591 * stack until we find an operator with a lesser priority than the
13592 * one we have just extracted. */
13593 /* Left paren is given the lowest priority so it will never be
13594 * "applied" in this way.
13595 * if associativity is right and priority eq, applied also skip
13598 if ((prec > 0 && prec < UNARYPREC) || prec == SPEC_PREC) {
13599 /* not left paren or unary */
13600 if (lasttok != TOK_NUM) {
13601 /* binary op must be preceded by a num */
13604 while (stackptr != stack) {
13605 if (op == TOK_RPAREN) {
13606 /* The algorithm employed here is simple: while we don't
13607 * hit an open paren nor the bottom of the stack, pop
13608 * tokens and apply them */
13609 if (stackptr[-1] == TOK_LPAREN) {
13611 /* Any operator directly after a */
13613 /* close paren should consider itself binary */
13617 operator prev_prec = PREC(stackptr[-1]);
13619 convert_prec_is_assing(prec);
13620 convert_prec_is_assing(prev_prec);
13621 if (prev_prec < prec)
13623 /* check right assoc */
13624 if(prev_prec == prec && is_right_associativity(prec))
13627 errcode = arith_apply(*--stackptr, numstack, &numstackptr);
13628 if(errcode) goto ret;
13630 if (op == TOK_RPAREN) {
13635 /* Push this operator to the stack and remember it. */
13636 *stackptr++ = lasttok = op;
13643 #endif /* CONFIG_ASH_MATH_SUPPORT */
13647 const char *bb_applet_name = "debug stuff usage";
13648 int main(int argc, char **argv)
13650 return ash_main(argc, argv);
13655 * Copyright (c) 1989, 1991, 1993, 1994
13656 * The Regents of the University of California. All rights reserved.
13658 * This code is derived from software contributed to Berkeley by
13659 * Kenneth Almquist.
13661 * Redistribution and use in source and binary forms, with or without
13662 * modification, are permitted provided that the following conditions
13664 * 1. Redistributions of source code must retain the above copyright
13665 * notice, this list of conditions and the following disclaimer.
13666 * 2. Redistributions in binary form must reproduce the above copyright
13667 * notice, this list of conditions and the following disclaimer in the
13668 * documentation and/or other materials provided with the distribution.
13669 * 3. Neither the name of the University nor the names of its contributors
13670 * may be used to endorse or promote products derived from this software
13671 * without specific prior written permission.
13673 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
13674 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
13675 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
13676 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
13677 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
13678 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
13679 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13680 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
13681 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
13682 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF