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) )
1387 static const char *safe_applets[] = {
1388 "[", "test", "echo", "cat",
1389 "ln", "cp", "touch", "mkdir", "rm",
1390 "cut", "hexdump", "awk", "sort",
1391 "find", "xargs", "ls", "dd",
1400 const struct builtincmd *cmd;
1401 struct funcnode *func;
1406 /* action to find_command() */
1407 #define DO_ERR 0x01 /* prints errors */
1408 #define DO_ABS 0x02 /* checks absolute paths */
1409 #define DO_NOFUNC 0x04 /* don't return shell functions, for command */
1410 #define DO_ALTPATH 0x08 /* using alternate path */
1411 #define DO_ALTBLTIN 0x20 /* %builtin in alt. path */
1413 static const char *pathopt; /* set by padvance */
1415 static void shellexec(char **, const char *, int)
1417 static char *padvance(const char **, const char *);
1418 static void find_command(char *, struct cmdentry *, int, const char *);
1419 static struct builtincmd *find_builtin(const char *);
1420 static void hashcd(void);
1421 static void changepath(const char *);
1422 static void defun(char *, union node *);
1423 static void unsetfunc(const char *);
1425 #ifdef CONFIG_ASH_MATH_SUPPORT_64
1426 typedef int64_t arith_t;
1427 #define arith_t_type (long long)
1429 typedef long arith_t;
1430 #define arith_t_type (long)
1433 #ifdef CONFIG_ASH_MATH_SUPPORT
1434 static arith_t dash_arith(const char *);
1435 static arith_t arith(const char *expr, int *perrcode);
1438 #ifdef CONFIG_ASH_RANDOM_SUPPORT
1439 static unsigned long rseed;
1440 static void change_random(const char *);
1441 # ifndef DYNAMIC_VAR
1442 # define DYNAMIC_VAR
1448 static void reset(void);
1457 #define VEXPORT 0x01 /* variable is exported */
1458 #define VREADONLY 0x02 /* variable cannot be modified */
1459 #define VSTRFIXED 0x04 /* variable struct is statically allocated */
1460 #define VTEXTFIXED 0x08 /* text is statically allocated */
1461 #define VSTACK 0x10 /* text is allocated on the stack */
1462 #define VUNSET 0x20 /* the variable is not set */
1463 #define VNOFUNC 0x40 /* don't call the callback function */
1464 #define VNOSET 0x80 /* do not set variable - just readonly test */
1465 #define VNOSAVE 0x100 /* when text is on the heap before setvareq */
1467 # define VDYNAMIC 0x200 /* dynamic variable */
1473 struct var *next; /* next entry in hash list */
1474 int flags; /* flags are defined above */
1475 const char *text; /* name=value */
1476 void (*func)(const char *); /* function to be called when */
1477 /* the variable gets set/unset */
1481 struct localvar *next; /* next local variable in list */
1482 struct var *vp; /* the variable that was made local */
1483 int flags; /* saved flags */
1484 const char *text; /* saved text */
1488 static struct localvar *localvars;
1494 #ifdef CONFIG_ASH_GETOPTS
1495 static void getoptsreset(const char *);
1498 #ifdef CONFIG_LOCALE_SUPPORT
1500 static void change_lc_all(const char *value);
1501 static void change_lc_ctype(const char *value);
1507 static const char defpathvar[] = "PATH=/usr/local/bin:/usr/bin:/sbin:/bin";
1509 static const char defifsvar[] = "IFS= \t\n";
1510 #define defifs (defifsvar + 4)
1512 static const char defifs[] = " \t\n";
1516 static struct var varinit[] = {
1518 { 0, VSTRFIXED|VTEXTFIXED, defifsvar, 0 },
1520 { 0, VSTRFIXED|VTEXTFIXED|VUNSET, "IFS\0", 0 },
1523 #ifdef CONFIG_ASH_MAIL
1524 { 0, VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL\0", changemail },
1525 { 0, VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH\0", changemail },
1528 { 0, VSTRFIXED|VTEXTFIXED, defpathvar, changepath },
1529 { 0, VSTRFIXED|VTEXTFIXED, "PS1=$ ", 0 },
1530 { 0, VSTRFIXED|VTEXTFIXED, "PS2=> ", 0 },
1531 { 0, VSTRFIXED|VTEXTFIXED, "PS4=+ ", 0 },
1532 #ifdef CONFIG_ASH_GETOPTS
1533 { 0, VSTRFIXED|VTEXTFIXED, "OPTIND=1", getoptsreset },
1535 #ifdef CONFIG_ASH_RANDOM_SUPPORT
1536 {0, VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM\0", change_random },
1538 #ifdef CONFIG_LOCALE_SUPPORT
1539 {0, VSTRFIXED | VTEXTFIXED | VUNSET, "LC_ALL\0", change_lc_all },
1540 {0, VSTRFIXED | VTEXTFIXED | VUNSET, "LC_CTYPE\0", change_lc_ctype },
1542 #ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
1543 {0, VSTRFIXED | VTEXTFIXED | VUNSET, "HISTFILE\0", NULL },
1547 #define vifs varinit[0]
1548 #ifdef CONFIG_ASH_MAIL
1549 #define vmail (&vifs)[1]
1550 #define vmpath (&vmail)[1]
1554 #define vpath (&vmpath)[1]
1555 #define vps1 (&vpath)[1]
1556 #define vps2 (&vps1)[1]
1557 #define vps4 (&vps2)[1]
1558 #define voptind (&vps4)[1]
1559 #ifdef CONFIG_ASH_GETOPTS
1560 #define vrandom (&voptind)[1]
1562 #define vrandom (&vps4)[1]
1564 #define defpath (defpathvar + 5)
1567 * The following macros access the values of the above variables.
1568 * They have to skip over the name. They return the null string
1569 * for unset variables.
1572 #define ifsval() (vifs.text + 4)
1573 #define ifsset() ((vifs.flags & VUNSET) == 0)
1574 #define mailval() (vmail.text + 5)
1575 #define mpathval() (vmpath.text + 9)
1576 #define pathval() (vpath.text + 5)
1577 #define ps1val() (vps1.text + 4)
1578 #define ps2val() (vps2.text + 4)
1579 #define ps4val() (vps4.text + 4)
1580 #define optindval() (voptind.text + 7)
1582 #define mpathset() ((vmpath.flags & VUNSET) == 0)
1584 static void setvar(const char *, const char *, int);
1585 static void setvareq(char *, int);
1586 static void listsetvar(struct strlist *, int);
1587 static char *lookupvar(const char *);
1588 static char *bltinlookup(const char *);
1589 static char **listvars(int, int, char ***);
1590 #define environment() listvars(VEXPORT, VUNSET, 0)
1591 static int showvars(const char *, int, int);
1592 static void poplocalvars(void);
1593 static int unsetvar(const char *);
1594 #ifdef CONFIG_ASH_GETOPTS
1595 static int setvarsafe(const char *, const char *, int);
1597 static int varcmp(const char *, const char *);
1598 static struct var **hashvar(const char *);
1601 static int varequal(const char *a, const char *b) {
1602 return !varcmp(a, b);
1606 static int loopnest; /* current loop nesting level */
1609 * The parsefile structure pointed to by the global variable parsefile
1610 * contains information about the current file being read.
1615 struct redirtab *next;
1620 static struct redirtab *redirlist;
1621 static int nullredirs;
1623 extern char **environ;
1628 static void outstr(const char *, FILE *);
1629 static void outcslow(int, FILE *);
1630 static void flushall(void);
1631 static void flusherr(void);
1632 static int out1fmt(const char *, ...)
1633 __attribute__((__format__(__printf__,1,2)));
1634 static int fmtstr(char *, size_t, const char *, ...)
1635 __attribute__((__format__(__printf__,3,4)));
1637 static int preverrout_fd; /* save fd2 before print debug if xflag is set. */
1640 static void out1str(const char *p)
1645 static void out2str(const char *p)
1652 * Initialization code.
1656 * This routine initializes the builtin variables.
1659 static void initvar(void)
1666 * PS1 depends on uid
1668 #if defined(CONFIG_FEATURE_COMMAND_EDITING) && defined(CONFIG_FEATURE_SH_FANCY_PROMPT)
1669 vps1.text = "PS1=\\w \\$ ";
1672 vps1.text = "PS1=# ";
1675 end = vp + sizeof(varinit) / sizeof(varinit[0]);
1677 vpp = hashvar(vp->text);
1680 } while (++vp < end);
1683 static void init(void)
1688 basepf.nextc = basepf.buf = basebuf;
1693 signal(SIGCHLD, SIG_DFL);
1701 struct stat st1, st2;
1704 for (envp = environ ; envp && *envp ; envp++) {
1705 if (strchr(*envp, '=')) {
1706 setvareq(*envp, VEXPORT|VTEXTFIXED);
1710 snprintf(ppid, sizeof(ppid), "%d", (int) getppid());
1711 setvar("PPID", ppid, 0);
1713 p = lookupvar("PWD");
1715 if (*p != '/' || stat(p, &st1) || stat(".", &st2) ||
1716 st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino)
1722 /* PEOF (the end of file marker) */
1725 INPUT_PUSH_FILE = 1,
1726 INPUT_NOFILE_OK = 2,
1730 * The input line number. Input.c just defines this variable, and saves
1731 * and restores it when files are pushed and popped. The user of this
1732 * package must set its value.
1735 static int pgetc(void);
1736 static int pgetc2(void);
1737 static int preadbuffer(void);
1738 static void pungetc(void);
1739 static void pushstring(char *, void *);
1740 static void popstring(void);
1741 static void setinputfd(int, int);
1742 static void setinputstring(char *);
1743 static void popfile(void);
1744 static void popallfiles(void);
1745 static void closescript(void);
1751 /* Mode argument to forkshell. Don't change FORK_FG or FORK_BG. */
1754 #define FORK_NOJOB 2
1756 /* mode flags for showjob(s) */
1757 #define SHOW_PGID 0x01 /* only show pgid - for jobs -p */
1758 #define SHOW_PID 0x04 /* include process pid */
1759 #define SHOW_CHANGED 0x08 /* only jobs whose state has changed */
1763 * A job structure contains information about a job. A job is either a
1764 * single process or a set of processes contained in a pipeline. In the
1765 * latter case, pidlist will be non-NULL, and will point to a -1 terminated
1770 pid_t pid; /* process id */
1771 int status; /* last process status from wait() */
1772 char *cmd; /* text of command being run */
1776 struct procstat ps0; /* status of process */
1777 struct procstat *ps; /* status or processes when more than one */
1779 int stopstatus; /* status of a stopped job */
1782 nprocs: 16, /* number of processes */
1784 #define JOBRUNNING 0 /* at least one proc running */
1785 #define JOBSTOPPED 1 /* all procs are stopped */
1786 #define JOBDONE 2 /* all procs are completed */
1788 sigint: 1, /* job was killed by SIGINT */
1789 jobctl: 1, /* job running under job control */
1791 waited: 1, /* true if this entry has been waited for */
1792 used: 1, /* true if this entry is in used */
1793 changed: 1; /* true if status has changed */
1794 struct job *prev_job; /* previous job */
1797 static pid_t backgndpid; /* pid of last background process */
1798 static int job_warning; /* user was warned about stopped jobs */
1800 static int jobctl; /* true if doing job control */
1803 static struct job *makejob(union node *, int);
1804 static int forkshell(struct job *, union node *, int);
1805 static int waitforjob(struct job *);
1806 static int stoppedjobs(void);
1809 #define setjobctl(on) /* do nothing */
1811 static void setjobctl(int);
1812 static void showjobs(FILE *, int);
1818 /* pid of main shell */
1820 /* shell level: 0 for the main shell, 1 for its children, and so on */
1822 #define rootshell (!shlvl)
1824 static void readcmdfile(char *);
1825 static int cmdloop(int);
1831 struct stack_block *stackp;
1834 struct stackmark *marknext;
1837 /* minimum size of a block */
1838 #define MINSIZE SHELL_ALIGN(504)
1840 struct stack_block {
1841 struct stack_block *prev;
1842 char space[MINSIZE];
1845 static struct stack_block stackbase;
1846 static struct stack_block *stackp = &stackbase;
1847 static struct stackmark *markp;
1848 static char *stacknxt = stackbase.space;
1849 static size_t stacknleft = MINSIZE;
1850 static char *sstrend = stackbase.space + MINSIZE;
1851 static int herefd = -1;
1854 static pointer ckmalloc(size_t);
1855 static pointer ckrealloc(pointer, size_t);
1856 static char *savestr(const char *);
1857 static pointer stalloc(size_t);
1858 static void stunalloc(pointer);
1859 static void setstackmark(struct stackmark *);
1860 static void popstackmark(struct stackmark *);
1861 static void growstackblock(void);
1862 static void *growstackstr(void);
1863 static char *makestrspace(size_t, char *);
1864 static char *stnputs(const char *, size_t, char *);
1865 static char *stputs(const char *, char *);
1868 static char *_STPUTC(int c, char *p) {
1875 #define stackblock() ((void *)stacknxt)
1876 #define stackblocksize() stacknleft
1877 #define STARTSTACKSTR(p) ((p) = stackblock())
1878 #define STPUTC(c, p) ((p) = _STPUTC((c), (p)))
1879 #define CHECKSTRSPACE(n, p) \
1883 size_t m = sstrend - q; \
1885 (p) = makestrspace(l, q); \
1888 #define USTPUTC(c, p) (*p++ = (c))
1889 #define STACKSTRNUL(p) ((p) == sstrend? (p = growstackstr(), *p = '\0') : (*p = '\0'))
1890 #define STUNPUTC(p) (--p)
1891 #define STTOPC(p) p[-1]
1892 #define STADJUST(amount, p) (p += (amount))
1894 #define grabstackstr(p) stalloc((char *)(p) - (char *)stackblock())
1895 #define ungrabstackstr(s, p) stunalloc((s))
1896 #define stackstrend() ((void *)sstrend)
1898 #define ckfree(p) free((pointer)(p))
1903 #define DOLATSTRLEN 4
1905 static char *prefix(const char *, const char *);
1906 static int number(const char *);
1907 static int is_number(const char *);
1908 static char *single_quote(const char *);
1909 static char *sstrdup(const char *);
1911 #define equal(s1, s2) (strcmp(s1, s2) == 0)
1912 #define scopy(s1, s2) ((void)strcpy(s2, s1))
1917 int nparam; /* # of positional parameters (without $0) */
1918 unsigned char malloc; /* if parameter list dynamically allocated */
1919 char **p; /* parameter list */
1920 #ifdef CONFIG_ASH_GETOPTS
1921 int optind; /* next parameter to be processed by getopts */
1922 int optoff; /* used by getopts */
1927 #define eflag optlist[0]
1928 #define fflag optlist[1]
1929 #define Iflag optlist[2]
1930 #define iflag optlist[3]
1931 #define mflag optlist[4]
1932 #define nflag optlist[5]
1933 #define sflag optlist[6]
1934 #define xflag optlist[7]
1935 #define vflag optlist[8]
1936 #define Cflag optlist[9]
1937 #define aflag optlist[10]
1938 #define bflag optlist[11]
1939 #define uflag optlist[12]
1940 #define viflag optlist[13]
1943 #define nolog optlist[14]
1944 #define debug optlist[15]
1947 #ifndef CONFIG_FEATURE_COMMAND_EDITING_VI
1948 #define setvimode(on) viflag = 0 /* forcibly keep the option off */
1954 static const char *const optletters_optnames[] = {
1975 #define optletters(n) optletters_optnames[(n)][0]
1976 #define optnames(n) (&optletters_optnames[(n)][1])
1978 #define NOPTS (sizeof(optletters_optnames)/sizeof(optletters_optnames[0]))
1980 static char optlist[NOPTS];
1983 static char *arg0; /* value of $0 */
1984 static struct shparam shellparam; /* $@ current positional parameters */
1985 static char **argptr; /* argument list for builtin commands */
1986 static char *optionarg; /* set by nextopt (like getopt) */
1987 static char *optptr; /* used by nextopt */
1989 static char *minusc; /* argument to -c option */
1992 static void procargs(int, char **);
1993 static void optschanged(void);
1994 static void setparam(char **);
1995 static void freeparam(volatile struct shparam *);
1996 static int shiftcmd(int, char **);
1997 static int setcmd(int, char **);
1998 static int nextopt(const char *);
2002 /* flags passed to redirect */
2003 #define REDIR_PUSH 01 /* save previous values of file descriptors */
2004 #define REDIR_SAVEFD2 03 /* set preverrout */
2007 static void redirect(union node *, int);
2008 static void popredir(int);
2009 static void clearredir(int);
2010 static int copyfd(int, int);
2011 static int redirectsafe(union node *, int);
2017 static void showtree(union node *);
2018 static void trace(const char *, ...);
2019 static void tracev(const char *, va_list);
2020 static void trargs(char **);
2021 static void trputc(int);
2022 static void trputs(const char *);
2023 static void opentrace(void);
2029 /* trap handler commands */
2030 static char *trap[NSIG];
2031 /* current value of signal */
2032 static char sigmode[NSIG - 1];
2033 /* indicates specified signal received */
2034 static char gotsig[NSIG - 1];
2036 static void clear_traps(void);
2037 static void setsignal(int);
2038 static void ignoresig(int);
2039 static void onsig(int);
2040 static int dotrap(void);
2041 static void setinteractive(int);
2042 static void exitshell(void) ATTRIBUTE_NORETURN;
2045 static int is_safe_applet(char *name)
2047 int n = sizeof(safe_applets) / sizeof(char *);
2049 for (i = 0; i < n; i++)
2050 if (strcmp(safe_applets[i], name) == 0)
2058 * This routine is called when an error or an interrupt occurs in an
2059 * interactive shell and control is returned to the main command loop.
2073 parselleft = parsenleft = 0; /* clear input buffer */
2077 /* from parser.c: */
2090 #ifdef CONFIG_ASH_ALIAS
2091 static struct alias *atab[ATABSIZE];
2093 static void setalias(const char *, const char *);
2094 static struct alias *freealias(struct alias *);
2095 static struct alias **__lookupalias(const char *);
2098 setalias(const char *name, const char *val)
2100 struct alias *ap, **app;
2102 app = __lookupalias(name);
2106 if (!(ap->flag & ALIASINUSE)) {
2109 ap->val = savestr(val);
2110 ap->flag &= ~ALIASDEAD;
2113 ap = ckmalloc(sizeof (struct alias));
2114 ap->name = savestr(name);
2115 ap->val = savestr(val);
2124 unalias(const char *name)
2128 app = __lookupalias(name);
2132 *app = freealias(*app);
2143 struct alias *ap, **app;
2147 for (i = 0; i < ATABSIZE; i++) {
2149 for (ap = *app; ap; ap = *app) {
2150 *app = freealias(*app);
2159 static struct alias *
2160 lookupalias(const char *name, int check)
2162 struct alias *ap = *__lookupalias(name);
2164 if (check && ap && (ap->flag & ALIASINUSE))
2170 * TODO - sort output
2173 aliascmd(int argc, char **argv)
2182 for (i = 0; i < ATABSIZE; i++)
2183 for (ap = atab[i]; ap; ap = ap->next) {
2188 while ((n = *++argv) != NULL) {
2189 if ((v = strchr(n+1, '=')) == NULL) { /* n+1: funny ksh stuff */
2190 if ((ap = *__lookupalias(n)) == NULL) {
2191 fprintf(stderr, "%s: %s not found\n", "alias", n);
2205 unaliascmd(int argc, char **argv)
2209 while ((i = nextopt("a")) != '\0') {
2215 for (i = 0; *argptr; argptr++) {
2216 if (unalias(*argptr)) {
2217 fprintf(stderr, "%s: %s not found\n", "unalias", *argptr);
2225 static struct alias *
2226 freealias(struct alias *ap) {
2229 if (ap->flag & ALIASINUSE) {
2230 ap->flag |= ALIASDEAD;
2242 printalias(const struct alias *ap) {
2243 out1fmt("%s=%s\n", ap->name, single_quote(ap->val));
2246 static struct alias **
2247 __lookupalias(const char *name) {
2248 unsigned int hashval;
2255 ch = (unsigned char)*p;
2259 ch = (unsigned char)*++p;
2261 app = &atab[hashval % ATABSIZE];
2263 for (; *app; app = &(*app)->next) {
2264 if (equal(name, (*app)->name)) {
2271 #endif /* CONFIG_ASH_ALIAS */
2277 * The cd and pwd commands.
2280 #define CD_PHYSICAL 1
2283 static int docd(const char *, int);
2284 static int cdopt(void);
2286 static char *curdir = nullstr; /* current working directory */
2287 static char *physdir = nullstr; /* physical working directory */
2296 while ((i = nextopt("LP"))) {
2298 flags ^= CD_PHYSICAL;
2307 cdcmd(int argc, char **argv)
2319 dest = bltinlookup(homestr);
2320 else if (dest[0] == '-' && dest[1] == '\0') {
2321 dest = bltinlookup("OLDPWD");
2343 if (!(path = bltinlookup("CDPATH"))) {
2351 p = padvance(&path, dest);
2352 if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
2356 if (!docd(p, flags))
2361 sh_error("can't cd to %s", dest);
2364 if (flags & CD_PRINT)
2365 out1fmt(snlfmt, curdir);
2371 * Update curdir (the name of the current directory) in response to a
2375 static const char * updatepwd(const char *dir)
2382 cdcomppath = sstrdup(dir);
2385 if (curdir == nullstr)
2387 new = stputs(curdir, new);
2389 new = makestrspace(strlen(dir) + 2, new);
2390 lim = stackblock() + 1;
2394 if (new > lim && *lim == '/')
2399 if (dir[1] == '/' && dir[2] != '/') {
2405 p = strtok(cdcomppath, "/");
2409 if (p[1] == '.' && p[2] == '\0') {
2416 } else if (p[1] == '\0')
2420 new = stputs(p, new);
2428 return stackblock();
2432 * Actually do the chdir. We also call hashcd to let the routines in exec.c
2433 * know that the current directory has changed.
2437 docd(const char *dest, int flags)
2439 const char *dir = 0;
2442 TRACE(("docd(\"%s\", %d) called\n", dest, flags));
2445 if (!(flags & CD_PHYSICAL)) {
2446 dir = updatepwd(dest);
2461 * Find out what the current directory is. If we already know the current
2462 * directory, this routine returns immediately.
2464 static char * getpwd(void)
2466 char *dir = getcwd(0, 0);
2467 return dir ? dir : nullstr;
2471 pwdcmd(int argc, char **argv)
2474 const char *dir = curdir;
2478 if (physdir == nullstr)
2482 out1fmt(snlfmt, dir);
2487 setpwd(const char *val, int setold)
2491 oldcur = dir = curdir;
2494 setvar("OLDPWD", oldcur, VEXPORT);
2497 if (physdir != nullstr) {
2498 if (physdir != oldcur)
2502 if (oldcur == val || !val) {
2509 if (oldcur != dir && oldcur != nullstr) {
2514 setvar("PWD", dir, VEXPORT);
2520 * Errors and exceptions.
2524 * Code to handle exceptions in C.
2529 static void exverror(int, const char *, va_list)
2533 * Called to raise an exception. Since C doesn't include exceptions, we
2534 * just do a longjmp to the exception handler. The type of exception is
2535 * stored in the global variable "exception".
2542 if (handler == NULL)
2548 longjmp(handler->loc, 1);
2553 * Called from trap.c when a SIGINT is received. (If the user specifies
2554 * that SIGINT is to be trapped or ignored using the trap builtin, then
2555 * this routine is not called.) Suppressint is nonzero when interrupts
2556 * are held using the INTOFF macro. (The test for iflag is just
2557 * defensive programming.)
2566 if (gotsig[SIGINT - 1] && !trap[SIGINT]) {
2567 if (!(rootshell && iflag)) {
2568 signal(SIGINT, SIG_DFL);
2578 exvwarning(const char *msg, va_list ap)
2583 fprintf(errs, "%s: ", arg0);
2585 const char *fmt = (!iflag || parsefile->fd) ?
2586 "%s: %d: " : "%s: ";
2587 fprintf(errs, fmt, commandname, startlinno);
2589 vfprintf(errs, msg, ap);
2590 outcslow('\n', errs);
2594 * Exverror is called to raise the error exception. If the second argument
2595 * is not NULL then error prints an error message using printf style
2596 * formatting. It then raises the error exception.
2599 exverror(int cond, const char *msg, va_list ap)
2603 TRACE(("exverror(%d, \"", cond));
2605 TRACE(("\") pid=%d\n", getpid()));
2607 TRACE(("exverror(%d, NULL) pid=%d\n", cond, getpid()));
2610 exvwarning(msg, ap);
2619 sh_error(const char *msg, ...)
2624 exverror(EXERROR, msg, ap);
2631 exerror(int cond, const char *msg, ...)
2636 exverror(cond, msg, ap);
2642 * error/warning routines for external builtins
2646 sh_warnx(const char *fmt, ...)
2651 exvwarning(fmt, ap);
2657 * Return a string describing an error. The returned string may be a
2658 * pointer to a static buffer that will be overwritten on the next call.
2659 * Action describes the operation that got the error.
2663 errmsg(int e, const char *em)
2665 if(e == ENOENT || e == ENOTDIR) {
2676 * Evaluate a command.
2679 /* flags in argument to evaltree */
2680 #define EV_EXIT 01 /* exit after evaluating tree */
2681 #define EV_TESTED 02 /* exit status is checked; ignore -e flag */
2682 #define EV_BACKCMD 04 /* command executing within back quotes */
2685 static void evalloop(union node *, int);
2686 static void evalfor(union node *, int);
2687 static void evalcase(union node *, int);
2688 static void evalsubshell(union node *, int);
2689 static void expredir(union node *);
2690 static void evalpipe(union node *, int);
2691 static void evalcommand(union node *, int);
2692 static int evalbltin(const struct builtincmd *, int, char **);
2693 static int evalfun(struct funcnode *, int, char **, int);
2694 static void prehash(union node *);
2695 static int bltincmd(int, char **);
2698 static const struct builtincmd bltin = {
2704 * Called to reset things after an exception.
2712 evalcmd(int argc, char **argv)
2721 STARTSTACKSTR(concat);
2724 concat = stputs(p, concat);
2725 if ((p = *ap++) == NULL)
2727 STPUTC(' ', concat);
2729 STPUTC('\0', concat);
2730 p = grabstackstr(concat);
2732 evalstring(p, ~SKIPEVAL);
2740 * Execute a command or commands contained in a string.
2744 evalstring(char *s, int mask)
2747 struct stackmark smark;
2751 setstackmark(&smark);
2754 while ((n = parsecmd(0)) != NEOF) {
2756 popstackmark(&smark);
2771 * Evaluate a parse tree. The value is left in the global variable
2776 evaltree(union node *n, int flags)
2779 void (*evalfn)(union node *, int);
2783 TRACE(("evaltree(NULL) called\n"));
2786 TRACE(("pid %d, evaltree(%p: %d, %d) called\n",
2787 getpid(), n, n->type, flags));
2791 out1fmt("Node type = %d\n", n->type);
2796 evaltree(n->nnot.com, EV_TESTED);
2797 status = !exitstatus;
2800 expredir(n->nredir.redirect);
2801 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
2803 evaltree(n->nredir.n, flags & EV_TESTED);
2804 status = exitstatus;
2809 evalfn = evalcommand;
2811 if (eflag && !(flags & EV_TESTED))
2823 evalfn = evalsubshell;
2835 #error NAND + 1 != NOR
2837 #if NOR + 1 != NSEMI
2838 #error NOR + 1 != NSEMI
2840 isor = n->type - NAND;
2843 (flags | ((isor >> 1) - 1)) & EV_TESTED
2845 if (!exitstatus == isor)
2857 evaltree(n->nif.test, EV_TESTED);
2860 if (exitstatus == 0) {
2863 } else if (n->nif.elsepart) {
2864 n = n->nif.elsepart;
2869 defun(n->narg.text, n->narg.next);
2873 exitstatus = status;
2877 if ((checkexit & exitstatus))
2878 evalskip |= SKIPEVAL;
2879 else if (pendingsigs && dotrap())
2882 if (flags & EV_EXIT) {
2889 #if !defined(__alpha__) || (defined(__GNUC__) && __GNUC__ >= 3)
2892 void evaltreenr(union node *, int) __attribute__ ((alias("evaltree"),__noreturn__));
2896 evalloop(union node *n, int flags)
2906 evaltree(n->nbinary.ch1, EV_TESTED);
2908 skipping: if (evalskip == SKIPCONT && --skipcount <= 0) {
2912 if (evalskip == SKIPBREAK && --skipcount <= 0)
2917 if (n->type != NWHILE)
2921 evaltree(n->nbinary.ch2, flags);
2922 status = exitstatus;
2927 exitstatus = status;
2933 evalfor(union node *n, int flags)
2935 struct arglist arglist;
2938 struct stackmark smark;
2940 setstackmark(&smark);
2941 arglist.lastp = &arglist.list;
2942 for (argp = n->nfor.args ; argp ; argp = argp->narg.next) {
2943 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE | EXP_RECORD);
2948 *arglist.lastp = NULL;
2953 for (sp = arglist.list ; sp ; sp = sp->next) {
2954 setvar(n->nfor.var, sp->text, 0);
2955 evaltree(n->nfor.body, flags);
2957 if (evalskip == SKIPCONT && --skipcount <= 0) {
2961 if (evalskip == SKIPBREAK && --skipcount <= 0)
2968 popstackmark(&smark);
2974 evalcase(union node *n, int flags)
2978 struct arglist arglist;
2979 struct stackmark smark;
2981 setstackmark(&smark);
2982 arglist.lastp = &arglist.list;
2983 expandarg(n->ncase.expr, &arglist, EXP_TILDE);
2985 for (cp = n->ncase.cases ; cp && evalskip == 0 ; cp = cp->nclist.next) {
2986 for (patp = cp->nclist.pattern ; patp ; patp = patp->narg.next) {
2987 if (casematch(patp, arglist.list->text)) {
2988 if (evalskip == 0) {
2989 evaltree(cp->nclist.body, flags);
2996 popstackmark(&smark);
3002 * Kick off a subshell to evaluate a tree.
3006 evalsubshell(union node *n, int flags)
3009 int backgnd = (n->type == NBACKGND);
3012 expredir(n->nredir.redirect);
3013 if (!backgnd && flags & EV_EXIT && !trap[0])
3017 if (forkshell(jp, n, backgnd) == 0) {
3021 flags &=~ EV_TESTED;
3023 redirect(n->nredir.redirect, 0);
3024 evaltreenr(n->nredir.n, flags);
3029 status = waitforjob(jp);
3030 exitstatus = status;
3037 * Compute the names of the files in a redirection list.
3041 expredir(union node *n)
3045 for (redir = n ; redir ; redir = redir->nfile.next) {
3047 fn.lastp = &fn.list;
3048 switch (redir->type) {
3054 expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
3055 redir->nfile.expfname = fn.list->text;
3059 if (redir->ndup.vname) {
3060 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
3061 fixredir(redir, fn.list->text, 1);
3071 * Evaluate a pipeline. All the processes in the pipeline are children
3072 * of the process creating the pipeline. (This differs from some versions
3073 * of the shell, which make the last process in a pipeline the parent
3078 evalpipe(union node *n, int flags)
3081 struct nodelist *lp;
3086 TRACE(("evalpipe(0x%lx) called\n", (long)n));
3088 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next)
3092 jp = makejob(n, pipelen);
3094 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
3098 if (pipe(pip) < 0) {
3100 sh_error("Pipe call failed");
3103 if (forkshell(jp, lp->n, n->npipe.backgnd) == 0) {
3116 evaltreenr(lp->n, flags);
3124 if (n->npipe.backgnd == 0) {
3125 exitstatus = waitforjob(jp);
3126 TRACE(("evalpipe: job done exit status %d\n", exitstatus));
3134 * Execute a command inside back quotes. If it's a builtin command, we
3135 * want to save its output in a block obtained from malloc. Otherwise
3136 * we fork off a subprocess and get the output of the command via a pipe.
3137 * Should be called with interrupts off.
3141 evalbackcmd(union node *n, struct backcmd *result)
3153 saveherefd = herefd;
3161 sh_error("Pipe call failed");
3163 if (forkshell(jp, n, FORK_NOJOB) == 0) {
3172 evaltreenr(n, EV_EXIT);
3176 result->fd = pip[0];
3179 herefd = saveherefd;
3181 TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
3182 result->fd, result->buf, result->nleft, result->jp));
3185 #ifdef CONFIG_ASH_CMDCMD
3186 static char ** parse_command_args(char **argv, const char **path)
3198 if (c == '-' && !*cp) {
3208 /* run 'typecmd' for other options */
3211 } while ((c = *cp++));
3217 static int isassignment(const char *p)
3219 const char *q = endofname(p);
3225 #ifdef CONFIG_ASH_EXPAND_PRMT
3226 static const char *expandstr(const char *ps);
3228 #define expandstr(s) s
3232 * Execute a simple command.
3236 evalcommand(union node *cmd, int flags)
3238 struct stackmark smark;
3240 struct arglist arglist;
3241 struct arglist varlist;
3244 const struct strlist *sp;
3245 struct cmdentry cmdentry;
3253 struct builtincmd *bcmd;
3254 int pseudovarflag = 0;
3256 /* First expand the arguments. */
3257 TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
3258 setstackmark(&smark);
3259 back_exitstatus = 0;
3261 cmdentry.cmdtype = CMDBUILTIN;
3262 cmdentry.u.cmd = &bltin;
3263 varlist.lastp = &varlist.list;
3264 *varlist.lastp = NULL;
3265 arglist.lastp = &arglist.list;
3266 *arglist.lastp = NULL;
3271 bcmd = find_builtin(cmd->ncmd.args->narg.text);
3272 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
3275 for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
3276 struct strlist **spp;
3278 spp = arglist.lastp;
3279 if (pseudovarflag && isassignment(argp->narg.text))
3280 expandarg(argp, &arglist, EXP_VARTILDE);
3282 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
3284 for (sp = *spp; sp; sp = sp->next)
3288 argv = nargv = stalloc(sizeof (char *) * (argc + 1));
3289 for (sp = arglist.list ; sp ; sp = sp->next) {
3290 TRACE(("evalcommand arg: %s\n", sp->text));
3291 *nargv++ = sp->text;
3296 if (iflag && funcnest == 0 && argc > 0)
3297 lastarg = nargv[-1];
3300 expredir(cmd->ncmd.redirect);
3301 status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH|REDIR_SAVEFD2);
3304 for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
3305 struct strlist **spp;
3308 spp = varlist.lastp;
3309 expandarg(argp, &varlist, EXP_VARTILDE);
3312 * Modify the command lookup path, if a PATH= assignment
3316 if (varequal(p, path))
3320 /* Print the command if xflag is set. */
3323 const char *p = " %s";
3326 dprintf(preverrout_fd, p, expandstr(ps4val()));
3329 for(n = 0; n < 2; n++) {
3331 dprintf(preverrout_fd, p, sp->text);
3339 full_write(preverrout_fd, "\n", 1);
3345 /* Now locate the command. */
3347 const char *oldpath;
3348 int cmd_flag = DO_ERR;
3353 find_command(argv[0], &cmdentry, cmd_flag, path);
3354 if (cmdentry.cmdtype == CMDUNKNOWN) {
3360 /* implement bltin and command here */
3361 if (cmdentry.cmdtype != CMDBUILTIN)
3364 spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
3365 if (cmdentry.u.cmd == EXECCMD)
3367 #ifdef CONFIG_ASH_CMDCMD
3368 if (cmdentry.u.cmd == COMMANDCMD) {
3371 nargv = parse_command_args(argv, &path);
3374 argc -= nargv - argv;
3376 cmd_flag |= DO_NOFUNC;
3384 /* We have a redirection error. */
3388 exitstatus = status;
3392 /* Execute the command. */
3393 switch (cmdentry.cmdtype) {
3395 /* Fork off a child process if necessary. */
3396 if (!(flags & EV_EXIT) || trap[0]) {
3398 jp = makejob(cmd, 1);
3399 if (forkshell(jp, cmd, FORK_FG) != 0) {
3400 exitstatus = waitforjob(jp);
3406 listsetvar(varlist.list, VEXPORT|VSTACK);
3407 shellexec(argv, path, cmdentry.u.index);
3411 cmdenviron = varlist.list;
3413 struct strlist *list = cmdenviron;
3415 if (spclbltin > 0 || argc == 0) {
3417 if (cmd_is_exec && argc > 1)
3420 listsetvar(list, i);
3422 if (evalbltin(cmdentry.u.cmd, argc, argv)) {
3437 exit_status = j + 128;
3438 exitstatus = exit_status;
3440 if (i == EXINT || spclbltin > 0) {
3442 longjmp(handler->loc, 1);
3449 listsetvar(varlist.list, 0);
3450 if (evalfun(cmdentry.u.func, argc, argv, flags))
3456 popredir(cmd_is_exec);
3458 /* dsl: I think this is intended to be used to support
3459 * '_' in 'vi' command mode during line editing...
3460 * However I implemented that within libedit itself.
3462 setvar("_", lastarg, 0);
3463 popstackmark(&smark);
3467 evalbltin(const struct builtincmd *cmd, int argc, char **argv) {
3468 char *volatile savecmdname;
3469 struct jmploc *volatile savehandler;
3470 struct jmploc jmploc;
3473 savecmdname = commandname;
3474 if ((i = setjmp(jmploc.loc)))
3476 savehandler = handler;
3478 commandname = argv[0];
3480 optptr = NULL; /* initialize nextopt */
3481 exitstatus = (*cmd->builtin)(argc, argv);
3484 exitstatus |= ferror(stdout);
3486 commandname = savecmdname;
3488 handler = savehandler;
3494 evalfun(struct funcnode *func, int argc, char **argv, int flags)
3496 volatile struct shparam saveparam;
3497 struct localvar *volatile savelocalvars;
3498 struct jmploc *volatile savehandler;
3499 struct jmploc jmploc;
3502 saveparam = shellparam;
3503 savelocalvars = localvars;
3504 if ((e = setjmp(jmploc.loc))) {
3508 savehandler = handler;
3511 shellparam.malloc = 0;
3515 shellparam.nparam = argc - 1;
3516 shellparam.p = argv + 1;
3517 #ifdef CONFIG_ASH_GETOPTS
3518 shellparam.optind = 1;
3519 shellparam.optoff = -1;
3521 evaltree(&func->n, flags & EV_TESTED);
3527 localvars = savelocalvars;
3528 freeparam(&shellparam);
3529 shellparam = saveparam;
3530 handler = savehandler;
3532 evalskip &= ~SKIPFUNC;
3537 static int goodname(const char *p)
3539 return !*endofname(p);
3543 * Search for a command. This is called before we fork so that the
3544 * location of the command will be available in the parent as well as
3545 * the child. The check for "goodname" is an overly conservative
3546 * check that the name will not be subject to expansion.
3550 prehash(union node *n)
3552 struct cmdentry entry;
3554 if (n->type == NCMD && n->ncmd.args)
3555 if (goodname(n->ncmd.args->narg.text))
3556 find_command(n->ncmd.args->narg.text, &entry, 0,
3563 * Builtin commands. Builtin commands whose functions are closely
3564 * tied to evaluation are implemented here.
3572 bltincmd(int argc, char **argv)
3575 * Preserve exitstatus of a previous possible redirection
3578 return back_exitstatus;
3583 * Handle break and continue commands. Break, continue, and return are
3584 * all handled by setting the evalskip flag. The evaluation routines
3585 * above all check this flag, and if it is set they start skipping
3586 * commands rather than executing them. The variable skipcount is
3587 * the number of loops to break/continue, or the number of function
3588 * levels to return. (The latter is always 1.) It should probably
3589 * be an error to break out of more loops than exist, but it isn't
3590 * in the standard shell so we don't make it one here.
3594 breakcmd(int argc, char **argv)
3596 int n = argc > 1 ? number(argv[1]) : 1;
3599 sh_error(illnum, argv[1]);
3603 evalskip = (**argv == 'c')? SKIPCONT : SKIPBREAK;
3611 * The return command.
3615 returncmd(int argc, char **argv)
3618 * If called outside a function, do what ksh does;
3619 * skip the rest of the file.
3621 evalskip = funcnest ? SKIPFUNC : SKIPFILE;
3622 return argv[1] ? number(argv[1]) : exitstatus;
3627 falsecmd(int argc, char **argv)
3634 truecmd(int argc, char **argv)
3641 execcmd(int argc, char **argv)
3644 iflag = 0; /* exit on error */
3647 shellexec(argv + 1, pathval(), 0);
3656 * When commands are first encountered, they are entered in a hash table.
3657 * This ensures that a full path search will not have to be done for them
3658 * on each invocation.
3660 * We should investigate converting to a linear search, even though that
3661 * would make the command name "hash" a misnomer.
3664 #define CMDTABLESIZE 31 /* should be prime */
3665 #define ARB 1 /* actual size determined at run time */
3670 struct tblentry *next; /* next entry in hash chain */
3671 union param param; /* definition of builtin function */
3672 short cmdtype; /* index identifying command */
3673 char rehash; /* if set, cd done since entry created */
3674 char cmdname[ARB]; /* name of command */
3678 static struct tblentry *cmdtable[CMDTABLESIZE];
3679 static int builtinloc = -1; /* index in path of %builtin, or -1 */
3682 static void tryexec(char *, char **, char **);
3683 static void clearcmdentry(int);
3684 static struct tblentry *cmdlookup(const char *, int);
3685 static void delete_cmd_entry(void);
3689 * Exec a program. Never returns. If you change this routine, you may
3690 * have to change the find_command routine as well.
3694 shellexec(char **argv, const char *path, int idx)
3702 envp = environment();
3703 if (strchr(argv[0], '/') != NULL
3704 || is_safe_applet(argv[0])
3705 #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
3706 || find_applet_by_name(argv[0])
3709 tryexec(argv[0], argv, envp);
3713 while ((cmdname = padvance(&path, argv[0])) != NULL) {
3714 if (--idx < 0 && pathopt == NULL) {
3715 tryexec(cmdname, argv, envp);
3716 if (errno != ENOENT && errno != ENOTDIR)
3723 /* Map to POSIX errors */
3735 exitstatus = exerrno;
3736 TRACE(("shellexec failed for %s, errno %d, suppressint %d\n",
3737 argv[0], e, suppressint ));
3738 exerror(EXEXEC, "%s: %s", argv[0], errmsg(e, E_EXEC));
3744 tryexec(char *cmd, char **argv, char **envp)
3747 struct BB_applet *a;
3751 if(strchr(cmd, '/') == NULL && is_safe_applet(cmd) && (a = find_applet_by_name(cmd)) != NULL) {
3753 while (*c != NULL) {
3756 bb_applet_name = cmd;
3757 exit(a->main(argc, argv));
3759 #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
3760 if(find_applet_by_name(cmd) != NULL) {
3761 /* re-exec ourselves with the new arguments */
3762 execve(CONFIG_BUSYBOX_EXEC_PATH,argv,envp);
3763 /* If they called chroot or otherwise made the binary no longer
3764 * executable, fall through */
3771 execve(cmd, argv, envp);
3772 } while (errno == EINTR);
3774 execve(cmd, argv, envp);
3778 } else if (errno == ENOEXEC) {
3782 for (ap = argv; *ap; ap++)
3784 ap = new = ckmalloc((ap - argv + 2) * sizeof(char *));
3786 *ap = cmd = (char *)DEFAULT_SHELL;
3789 while ((*ap++ = *argv++))
3799 * Do a path search. The variable path (passed by reference) should be
3800 * set to the start of the path before the first call; padvance will update
3801 * this value as it proceeds. Successive calls to padvance will return
3802 * the possible path expansions in sequence. If an option (indicated by
3803 * a percent sign) appears in the path entry then the global variable
3804 * pathopt will be set to point to it; otherwise pathopt will be set to
3809 padvance(const char **path, const char *name)
3819 for (p = start ; *p && *p != ':' && *p != '%' ; p++);
3820 len = p - start + strlen(name) + 2; /* "2" is for '/' and '\0' */
3821 while (stackblocksize() < len)
3825 memcpy(q, start, p - start);
3833 while (*p && *p != ':') p++;
3839 return stalloc(len);
3843 /*** Command hashing code ***/
3846 printentry(struct tblentry *cmdp)
3852 idx = cmdp->param.index;
3855 name = padvance(&path, cmdp->cmdname);
3857 } while (--idx >= 0);
3858 out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
3863 hashcmd(int argc, char **argv)
3865 struct tblentry **pp;
3866 struct tblentry *cmdp;
3868 struct cmdentry entry;
3871 while ((c = nextopt("r")) != '\0') {
3875 if (*argptr == NULL) {
3876 for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
3877 for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
3878 if (cmdp->cmdtype == CMDNORMAL)
3885 while ((name = *argptr) != NULL) {
3886 if ((cmdp = cmdlookup(name, 0)) != NULL
3887 && (cmdp->cmdtype == CMDNORMAL
3888 || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0)))
3890 find_command(name, &entry, DO_ERR, pathval());
3891 if (entry.cmdtype == CMDUNKNOWN)
3900 * Resolve a command name. If you change this routine, you may have to
3901 * change the shellexec routine as well.
3905 find_command(char *name, struct cmdentry *entry, int act, const char *path)
3907 struct tblentry *cmdp;
3914 struct builtincmd *bcmd;
3916 /* If name contains a slash, don't use PATH or hash table */
3917 if (strchr(name, '/') != NULL) {
3918 entry->u.index = -1;
3920 while (stat(name, &statb) < 0) {
3925 entry->cmdtype = CMDUNKNOWN;
3929 entry->cmdtype = CMDNORMAL;
3933 #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
3934 if (find_applet_by_name(name)) {
3935 entry->cmdtype = CMDNORMAL;
3936 entry->u.index = -1;
3941 if (is_safe_applet(name)) {
3942 entry->cmdtype = CMDNORMAL;
3943 entry->u.index = -1;
3947 updatetbl = (path == pathval());
3950 if (strstr(path, "%builtin") != NULL)
3954 /* If name is in the table, check answer will be ok */
3955 if ((cmdp = cmdlookup(name, 0)) != NULL) {
3958 switch (cmdp->cmdtype) {
3976 } else if (cmdp->rehash == 0)
3977 /* if not invalidated by cd, we're done */
3981 /* If %builtin not in path, check for builtin next */
3982 bcmd = find_builtin(name);
3983 if (bcmd && (IS_BUILTIN_REGULAR(bcmd) || (
3984 act & DO_ALTPATH ? !(act & DO_ALTBLTIN) : builtinloc <= 0
3986 goto builtin_success;
3988 /* We have to search path. */
3989 prev = -1; /* where to start */
3990 if (cmdp && cmdp->rehash) { /* doing a rehash */
3991 if (cmdp->cmdtype == CMDBUILTIN)
3994 prev = cmdp->param.index;
4000 while ((fullname = padvance(&path, name)) != NULL) {
4001 stunalloc(fullname);
4004 if (prefix(pathopt, "builtin")) {
4006 goto builtin_success;
4008 } else if (!(act & DO_NOFUNC) &&
4009 prefix(pathopt, "func")) {
4012 /* ignore unimplemented options */
4016 /* if rehash, don't redo absolute path names */
4017 if (fullname[0] == '/' && idx <= prev) {
4020 TRACE(("searchexec \"%s\": no change\n", name));
4023 while (stat(fullname, &statb) < 0) {
4028 if (errno != ENOENT && errno != ENOTDIR)
4032 e = EACCES; /* if we fail, this will be the error */
4033 if (!S_ISREG(statb.st_mode))
4035 if (pathopt) { /* this is a %func directory */
4036 stalloc(strlen(fullname) + 1);
4037 readcmdfile(fullname);
4038 if ((cmdp = cmdlookup(name, 0)) == NULL ||
4039 cmdp->cmdtype != CMDFUNCTION)
4040 sh_error("%s not defined in %s", name, fullname);
4041 stunalloc(fullname);
4044 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
4046 entry->cmdtype = CMDNORMAL;
4047 entry->u.index = idx;
4051 cmdp = cmdlookup(name, 1);
4052 cmdp->cmdtype = CMDNORMAL;
4053 cmdp->param.index = idx;
4058 /* We failed. If there was an entry for this command, delete it */
4059 if (cmdp && updatetbl)
4062 sh_warnx("%s: %s", name, errmsg(e, E_EXEC));
4063 entry->cmdtype = CMDUNKNOWN;
4068 entry->cmdtype = CMDBUILTIN;
4069 entry->u.cmd = bcmd;
4073 cmdp = cmdlookup(name, 1);
4074 cmdp->cmdtype = CMDBUILTIN;
4075 cmdp->param.cmd = bcmd;
4079 entry->cmdtype = cmdp->cmdtype;
4080 entry->u = cmdp->param;
4085 * Wrapper around strcmp for qsort/bsearch/...
4087 static int pstrcmp(const void *a, const void *b)
4089 return strcmp((const char *) a, (*(const char *const *) b) + 1);
4093 * Search the table of builtin commands.
4096 static struct builtincmd *
4097 find_builtin(const char *name)
4099 struct builtincmd *bp;
4102 name, builtincmd, NUMBUILTINS, sizeof(struct builtincmd),
4111 * Called when a cd is done. Marks all commands so the next time they
4112 * are executed they will be rehashed.
4118 struct tblentry **pp;
4119 struct tblentry *cmdp;
4121 for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
4122 for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
4123 if (cmdp->cmdtype == CMDNORMAL || (
4124 cmdp->cmdtype == CMDBUILTIN &&
4125 !(IS_BUILTIN_REGULAR(cmdp->param.cmd)) &&
4136 * Fix command hash table when PATH changed.
4137 * Called before PATH is changed. The argument is the new value of PATH;
4138 * pathval() still returns the old value at this point.
4139 * Called with interrupts off.
4143 changepath(const char *newval)
4145 const char *old, *new;
4152 firstchange = 9999; /* assume no change */
4158 if ((*old == '\0' && *new == ':')
4159 || (*old == ':' && *new == '\0'))
4161 old = new; /* ignore subsequent differences */
4165 if (*new == '%' && idx_bltin < 0 && prefix(new + 1, "builtin"))
4172 if (builtinloc < 0 && idx_bltin >= 0)
4173 builtinloc = idx_bltin; /* zap builtins */
4174 if (builtinloc >= 0 && idx_bltin < 0)
4176 clearcmdentry(firstchange);
4177 builtinloc = idx_bltin;
4182 * Clear out command entries. The argument specifies the first entry in
4183 * PATH which has changed.
4187 clearcmdentry(int firstchange)
4189 struct tblentry **tblp;
4190 struct tblentry **pp;
4191 struct tblentry *cmdp;
4194 for (tblp = cmdtable ; tblp < &cmdtable[CMDTABLESIZE] ; tblp++) {
4196 while ((cmdp = *pp) != NULL) {
4197 if ((cmdp->cmdtype == CMDNORMAL &&
4198 cmdp->param.index >= firstchange)
4199 || (cmdp->cmdtype == CMDBUILTIN &&
4200 builtinloc >= firstchange)) {
4214 * Locate a command in the command hash table. If "add" is nonzero,
4215 * add the command to the table if it is not already present. The
4216 * variable "lastcmdentry" is set to point to the address of the link
4217 * pointing to the entry, so that delete_cmd_entry can delete the
4220 * Interrupts must be off if called with add != 0.
4223 static struct tblentry **lastcmdentry;
4226 static struct tblentry *
4227 cmdlookup(const char *name, int add)
4229 unsigned int hashval;
4231 struct tblentry *cmdp;
4232 struct tblentry **pp;
4235 hashval = (unsigned char)*p << 4;
4237 hashval += (unsigned char)*p++;
4239 pp = &cmdtable[hashval % CMDTABLESIZE];
4240 for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
4241 if (equal(cmdp->cmdname, name))
4245 if (add && cmdp == NULL) {
4246 cmdp = *pp = ckmalloc(sizeof (struct tblentry) - ARB
4247 + strlen(name) + 1);
4249 cmdp->cmdtype = CMDUNKNOWN;
4250 strcpy(cmdp->cmdname, name);
4257 * Delete the command entry returned on the last lookup.
4261 delete_cmd_entry(void)
4263 struct tblentry *cmdp;
4266 cmdp = *lastcmdentry;
4267 *lastcmdentry = cmdp->next;
4268 if (cmdp->cmdtype == CMDFUNCTION)
4269 freefunc(cmdp->param.func);
4276 * Add a new command entry, replacing any existing command entry for
4277 * the same name - except special builtins.
4280 static void addcmdentry(char *name, struct cmdentry *entry)
4282 struct tblentry *cmdp;
4284 cmdp = cmdlookup(name, 1);
4285 if (cmdp->cmdtype == CMDFUNCTION) {
4286 freefunc(cmdp->param.func);
4288 cmdp->cmdtype = entry->cmdtype;
4289 cmdp->param = entry->u;
4294 * Make a copy of a parse tree.
4297 static struct funcnode * copyfunc(union node *n)
4302 funcblocksize = offsetof(struct funcnode, n);
4305 blocksize = funcblocksize;
4306 f = ckmalloc(blocksize + funcstringsize);
4307 funcblock = (char *) f + offsetof(struct funcnode, n);
4308 funcstring = (char *) f + blocksize;
4315 * Define a shell function.
4319 defun(char *name, union node *func)
4321 struct cmdentry entry;
4324 entry.cmdtype = CMDFUNCTION;
4325 entry.u.func = copyfunc(func);
4326 addcmdentry(name, &entry);
4332 * Delete a function if it exists.
4336 unsetfunc(const char *name)
4338 struct tblentry *cmdp;
4340 if ((cmdp = cmdlookup(name, 0)) != NULL &&
4341 cmdp->cmdtype == CMDFUNCTION)
4346 * Locate and print what a word is...
4350 #ifdef CONFIG_ASH_CMDCMD
4352 describe_command(char *command, int describe_command_verbose)
4354 #define describe_command_verbose 1
4356 describe_command(char *command)
4359 struct cmdentry entry;
4360 struct tblentry *cmdp;
4361 #ifdef CONFIG_ASH_ALIAS
4362 const struct alias *ap;
4364 const char *path = pathval();
4366 if (describe_command_verbose) {
4370 /* First look at the keywords */
4371 if (findkwd(command)) {
4372 out1str(describe_command_verbose ? " is a shell keyword" : command);
4376 #ifdef CONFIG_ASH_ALIAS
4377 /* Then look at the aliases */
4378 if ((ap = lookupalias(command, 0)) != NULL) {
4379 if (describe_command_verbose) {
4380 out1fmt(" is an alias for %s", ap->val);
4389 /* Then check if it is a tracked alias */
4390 if ((cmdp = cmdlookup(command, 0)) != NULL) {
4391 entry.cmdtype = cmdp->cmdtype;
4392 entry.u = cmdp->param;
4394 /* Finally use brute force */
4395 find_command(command, &entry, DO_ABS, path);
4398 switch (entry.cmdtype) {
4400 int j = entry.u.index;
4406 p = padvance(&path, command);
4410 if (describe_command_verbose) {
4412 (cmdp ? " a tracked alias for" : nullstr), p
4421 if (describe_command_verbose) {
4422 out1str(" is a shell function");
4429 if (describe_command_verbose) {
4430 out1fmt(" is a %sshell builtin",
4431 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
4432 "special " : nullstr
4440 if (describe_command_verbose) {
4441 out1str(": not found\n");
4447 outstr("\n", stdout);
4452 typecmd(int argc, char **argv)
4457 for (i = 1; i < argc; i++) {
4458 #ifdef CONFIG_ASH_CMDCMD
4459 err |= describe_command(argv[i], 1);
4461 err |= describe_command(argv[i]);
4467 #ifdef CONFIG_ASH_CMDCMD
4469 commandcmd(int argc, char **argv)
4477 while ((c = nextopt("pvV")) != '\0')
4479 verify |= VERIFY_VERBOSE;
4481 verify |= VERIFY_BRIEF;
4487 return describe_command(*argptr, verify - VERIFY_BRIEF);
4496 * Routines to expand arguments to commands. We have to deal with
4497 * backquotes, shell variables, and file metacharacters.
4503 #define RMESCAPE_ALLOC 0x1 /* Allocate a new string */
4504 #define RMESCAPE_GLOB 0x2 /* Add backslashes for glob */
4505 #define RMESCAPE_QUOTED 0x4 /* Remove CTLESC unless in quotes */
4506 #define RMESCAPE_GROW 0x8 /* Grow strings instead of stalloc */
4507 #define RMESCAPE_HEAP 0x10 /* Malloc strings instead of stalloc */
4510 * Structure specifying which parts of the string should be searched
4511 * for IFS characters.
4515 struct ifsregion *next; /* next region in list */
4516 int begoff; /* offset of start of region */
4517 int endoff; /* offset of end of region */
4518 int nulonly; /* search for nul bytes only */
4521 /* output of current string */
4522 static char *expdest;
4523 /* list of back quote expressions */
4524 static struct nodelist *argbackq;
4525 /* first struct in list of ifs regions */
4526 static struct ifsregion ifsfirst;
4527 /* last struct in list */
4528 static struct ifsregion *ifslastp;
4529 /* holds expanded arg list */
4530 static struct arglist exparg;
4532 static void argstr(char *, int);
4533 static char *exptilde(char *, char *, int);
4534 static void expbackq(union node *, int, int);
4535 static const char *subevalvar(char *, char *, int, int, int, int, int);
4536 static char *evalvar(char *, int);
4537 static void strtodest(const char *, int, int);
4538 static void memtodest(const char *p, size_t len, int syntax, int quotes);
4539 static ssize_t varvalue(char *, int, int);
4540 static void recordregion(int, int, int);
4541 static void removerecordregions(int);
4542 static void ifsbreakup(char *, struct arglist *);
4543 static void ifsfree(void);
4544 static void expandmeta(struct strlist *, int);
4545 static int patmatch(char *, const char *);
4547 static int cvtnum(arith_t);
4548 static size_t esclen(const char *, const char *);
4549 static char *scanleft(char *, char *, char *, char *, int, int);
4550 static char *scanright(char *, char *, char *, char *, int, int);
4551 static void varunset(const char *, const char *, const char *, int)
4555 #define pmatch(a, b) !fnmatch((a), (b), 0)
4557 * Prepare a pattern for a expmeta (internal glob(3)) call.
4559 * Returns an stalloced string.
4562 static char * preglob(const char *pattern, int quoted, int flag) {
4563 flag |= RMESCAPE_GLOB;
4565 flag |= RMESCAPE_QUOTED;
4567 return _rmescapes((char *)pattern, flag);
4572 esclen(const char *start, const char *p) {
4575 while (p > start && *--p == CTLESC) {
4583 * Expand shell variables and backquotes inside a here document.
4586 static void expandhere(union node *arg, int fd)
4589 expandarg(arg, (struct arglist *)NULL, 0);
4590 full_write(fd, stackblock(), expdest - (char *)stackblock());
4595 * Perform variable substitution and command substitution on an argument,
4596 * placing the resulting list of arguments in arglist. If EXP_FULL is true,
4597 * perform splitting and file name expansion. When arglist is NULL, perform
4598 * here document expansion.
4602 expandarg(union node *arg, struct arglist *arglist, int flag)
4607 argbackq = arg->narg.backquote;
4608 STARTSTACKSTR(expdest);
4609 ifsfirst.next = NULL;
4611 argstr(arg->narg.text, flag);
4612 p = _STPUTC('\0', expdest);
4614 if (arglist == NULL) {
4615 return; /* here document expanded */
4617 p = grabstackstr(p);
4618 exparg.lastp = &exparg.list;
4622 if (flag & EXP_FULL) {
4623 ifsbreakup(p, &exparg);
4624 *exparg.lastp = NULL;
4625 exparg.lastp = &exparg.list;
4626 expandmeta(exparg.list, flag);
4628 if (flag & EXP_REDIR) /*XXX - for now, just remove escapes */
4630 sp = (struct strlist *)stalloc(sizeof (struct strlist));
4633 exparg.lastp = &sp->next;
4637 *exparg.lastp = NULL;
4639 *arglist->lastp = exparg.list;
4640 arglist->lastp = exparg.lastp;
4646 * Perform variable and command substitution. If EXP_FULL is set, output CTLESC
4647 * characters to allow for further processing. Otherwise treat
4648 * $@ like $* since no splitting will be performed.
4652 argstr(char *p, int flag)
4654 static const char spclchars[] = {
4662 CTLBACKQ | CTLQUOTE,
4663 #ifdef CONFIG_ASH_MATH_SUPPORT
4668 const char *reject = spclchars;
4670 int quotes = flag & (EXP_FULL | EXP_CASE); /* do CTLESC */
4671 int breakall = flag & EXP_WORD;
4676 if (!(flag & EXP_VARTILDE)) {
4678 } else if (flag & EXP_VARTILDE2) {
4683 if (flag & EXP_TILDE) {
4689 if (*q == CTLESC && (flag & EXP_QWORD))
4692 p = exptilde(p, q, flag);
4695 startloc = expdest - (char *)stackblock();
4697 length += strcspn(p + length, reject);
4699 if (c && (!(c & 0x80)
4700 #ifdef CONFIG_ASH_MATH_SUPPORT
4704 /* c == '=' || c == ':' || c == CTLENDARI */
4709 expdest = stnputs(p, length, expdest);
4710 newloc = expdest - (char *)stackblock();
4711 if (breakall && !inquotes && newloc > startloc) {
4712 recordregion(startloc, newloc, 0);
4723 if (flag & EXP_VARTILDE2) {
4727 flag |= EXP_VARTILDE2;
4732 * sort of a hack - expand tildes in variable
4733 * assignments (after the first '=' and after ':'s).
4742 case CTLENDVAR: /* ??? */
4745 /* "$@" syntax adherence hack */
4748 !memcmp(p, dolatstr, DOLATSTRLEN) &&
4749 (p[4] == CTLQUOTEMARK || (
4750 p[4] == CTLENDVAR &&
4751 p[5] == CTLQUOTEMARK
4754 p = evalvar(p + 1, flag) + 1;
4757 inquotes = !inquotes;
4770 p = evalvar(p, flag);
4774 case CTLBACKQ|CTLQUOTE:
4775 expbackq(argbackq->n, c, quotes);
4776 argbackq = argbackq->next;
4778 #ifdef CONFIG_ASH_MATH_SUPPORT
4791 exptilde(char *startp, char *p, int flag)
4797 int quotes = flag & (EXP_FULL | EXP_CASE);
4802 while ((c = *++p) != '\0') {
4809 if (flag & EXP_VARTILDE)
4819 if (*name == '\0') {
4820 home = lookupvar(homestr);
4822 if ((pw = getpwnam(name)) == NULL)
4826 if (!home || !*home)
4829 startloc = expdest - (char *)stackblock();
4830 strtodest(home, SQSYNTAX, quotes);
4831 recordregion(startloc, expdest - (char *)stackblock(), 0);
4840 removerecordregions(int endoff)
4842 if (ifslastp == NULL)
4845 if (ifsfirst.endoff > endoff) {
4846 while (ifsfirst.next != NULL) {
4847 struct ifsregion *ifsp;
4849 ifsp = ifsfirst.next->next;
4850 ckfree(ifsfirst.next);
4851 ifsfirst.next = ifsp;
4854 if (ifsfirst.begoff > endoff)
4857 ifslastp = &ifsfirst;
4858 ifsfirst.endoff = endoff;
4863 ifslastp = &ifsfirst;
4864 while (ifslastp->next && ifslastp->next->begoff < endoff)
4865 ifslastp=ifslastp->next;
4866 while (ifslastp->next != NULL) {
4867 struct ifsregion *ifsp;
4869 ifsp = ifslastp->next->next;
4870 ckfree(ifslastp->next);
4871 ifslastp->next = ifsp;
4874 if (ifslastp->endoff > endoff)
4875 ifslastp->endoff = endoff;
4879 #ifdef CONFIG_ASH_MATH_SUPPORT
4881 * Expand arithmetic expression. Backup to start of expression,
4882 * evaluate, place result in (backed up) result, adjust string position.
4895 * This routine is slightly over-complicated for
4896 * efficiency. Next we scan backwards looking for the
4897 * start of arithmetic.
4899 start = stackblock();
4906 while (*p != CTLARI) {
4910 sh_error("missing CTLARI (shouldn't happen)");
4915 esc = esclen(start, p);
4925 removerecordregions(begoff);
4934 len = cvtnum(dash_arith(p + 2));
4937 recordregion(begoff, begoff + len, 0);
4942 * Expand stuff in backwards quotes.
4946 expbackq(union node *cmd, int quoted, int quotes)
4954 int syntax = quoted? DQSYNTAX : BASESYNTAX;
4955 struct stackmark smark;
4958 setstackmark(&smark);
4960 startloc = dest - (char *)stackblock();
4962 evalbackcmd(cmd, (struct backcmd *) &in);
4963 popstackmark(&smark);
4970 memtodest(p, i, syntax, quotes);
4974 i = safe_read(in.fd, buf, sizeof buf);
4975 TRACE(("expbackq: read returns %d\n", i));
4985 back_exitstatus = waitforjob(in.jp);
4989 /* Eat all trailing newlines */
4991 for (; dest > (char *)stackblock() && dest[-1] == '\n';)
4996 recordregion(startloc, dest - (char *)stackblock(), 0);
4997 TRACE(("evalbackq: size=%d: \"%.*s\"\n",
4998 (dest - (char *)stackblock()) - startloc,
4999 (dest - (char *)stackblock()) - startloc,
5000 stackblock() + startloc));
5005 scanleft(char *startp, char *rmesc, char *rmescend, char *str, int quotes,
5016 const char *s = loc2;
5022 match = pmatch(str, s);
5026 if (quotes && *loc == CTLESC)
5036 scanright(char *startp, char *rmesc, char *rmescend, char *str, int quotes,
5043 for (loc = str - 1, loc2 = rmescend; loc >= startp; loc2--) {
5046 const char *s = loc2;
5051 match = pmatch(str, s);
5058 esc = esclen(startp, loc);
5070 subevalvar(char *p, char *str, int strloc, int subtype, int startloc, int varflags, int quotes)
5074 int saveherefd = herefd;
5075 struct nodelist *saveargbackq = argbackq;
5077 char *rmesc, *rmescend;
5079 char *(*scan)(char *, char *, char *, char *, int , int);
5082 argstr(p, subtype != VSASSIGN && subtype != VSQUESTION ? EXP_CASE : 0);
5083 STPUTC('\0', expdest);
5084 herefd = saveherefd;
5085 argbackq = saveargbackq;
5086 startp = stackblock() + startloc;
5090 setvar(str, startp, 0);
5091 amount = startp - expdest;
5092 STADJUST(amount, expdest);
5096 varunset(p, str, startp, varflags);
5100 subtype -= VSTRIMRIGHT;
5102 if (subtype < 0 || subtype > 3)
5107 rmescend = stackblock() + strloc;
5109 rmesc = _rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW);
5110 if (rmesc != startp) {
5112 startp = stackblock() + startloc;
5116 str = stackblock() + strloc;
5117 preglob(str, varflags & VSQUOTE, 0);
5119 /* zero = subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX */
5120 zero = subtype >> 1;
5121 /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
5122 scan = (subtype & 1) ^ zero ? scanleft : scanright;
5124 loc = scan(startp, rmesc, rmescend, str, quotes, zero);
5127 memmove(startp, loc, str - loc);
5128 loc = startp + (str - loc) - 1;
5131 amount = loc - expdest;
5132 STADJUST(amount, expdest);
5139 * Expand a variable, and return a pointer to the next character in the
5143 evalvar(char *p, int flag)
5156 quotes = flag & (EXP_FULL | EXP_CASE);
5158 subtype = varflags & VSTYPE;
5159 quoted = varflags & VSQUOTE;
5161 easy = (!quoted || (*var == '@' && shellparam.nparam));
5162 startloc = expdest - (char *)stackblock();
5163 p = strchr(p, '=') + 1;
5166 varlen = varvalue(var, varflags, flag);
5167 if (varflags & VSNUL)
5170 if (subtype == VSPLUS) {
5171 varlen = -1 - varlen;
5175 if (subtype == VSMINUS) {
5179 p, flag | EXP_TILDE |
5180 (quoted ? EXP_QWORD : EXP_WORD)
5189 if (subtype == VSASSIGN || subtype == VSQUESTION) {
5191 if (subevalvar(p, var, 0, subtype, startloc,
5195 * Remove any recorded regions beyond
5198 removerecordregions(startloc);
5208 if (varlen < 0 && uflag)
5209 varunset(p, var, 0, 0);
5211 if (subtype == VSLENGTH) {
5212 cvtnum(varlen > 0 ? varlen : 0);
5216 if (subtype == VSNORMAL) {
5220 recordregion(startloc, expdest - (char *)stackblock(), quoted);
5229 case VSTRIMRIGHTMAX:
5238 * Terminate the string and start recording the pattern
5241 STPUTC('\0', expdest);
5242 patloc = expdest - (char *)stackblock();
5243 if (subevalvar(p, NULL, patloc, subtype,
5244 startloc, varflags, quotes) == 0) {
5245 int amount = expdest - (
5246 (char *)stackblock() + patloc - 1
5248 STADJUST(-amount, expdest);
5250 /* Remove any recorded regions beyond start of variable */
5251 removerecordregions(startloc);
5256 if (subtype != VSNORMAL) { /* skip to end of alternative */
5259 if ((c = *p++) == CTLESC)
5261 else if (c == CTLBACKQ || c == (CTLBACKQ|CTLQUOTE)) {
5263 argbackq = argbackq->next;
5264 } else if (c == CTLVAR) {
5265 if ((*p++ & VSTYPE) != VSNORMAL)
5267 } else if (c == CTLENDVAR) {
5278 * Put a string on the stack.
5282 memtodest(const char *p, size_t len, int syntax, int quotes) {
5285 q = makestrspace(len * 2, q);
5288 int c = SC2INT(*p++);
5291 if (quotes && (SIT(c, syntax) == CCTL || SIT(c, syntax) == CBACK))
5301 strtodest(const char *p, int syntax, int quotes)
5303 memtodest(p, strlen(p), syntax, quotes);
5308 * Add the value of a specialized variable to the stack string.
5312 varvalue(char *name, int varflags, int flags)
5322 int quoted = varflags & VSQUOTE;
5323 int subtype = varflags & VSTYPE;
5324 int quotes = flags & (EXP_FULL | EXP_CASE);
5326 if (quoted && (flags & EXP_FULL))
5327 sep = 1 << CHAR_BIT;
5329 syntax = quoted ? DQSYNTAX : BASESYNTAX;
5338 num = shellparam.nparam;
5348 p = makestrspace(NOPTS, expdest);
5349 for (i = NOPTS - 1; i >= 0; i--) {
5351 USTPUTC(optletters(i), p);
5362 sep = ifsset() ? SC2INT(ifsval()[0]) : ' ';
5363 if (quotes && (SIT(sep, syntax) == CCTL || SIT(sep, syntax) == CBACK))
5366 if (!(ap = shellparam.p))
5368 while ((p = *ap++)) {
5371 partlen = strlen(p);
5374 if (!(subtype == VSPLUS || subtype == VSLENGTH))
5375 memtodest(p, partlen, syntax, quotes);
5381 if (subtype == VSPLUS || subtype == VSLENGTH) {
5403 if (num < 0 || num > shellparam.nparam)
5405 p = num ? shellparam.p[num - 1] : arg0;
5408 p = lookupvar(name);
5414 if (!(subtype == VSPLUS || subtype == VSLENGTH))
5415 memtodest(p, len, syntax, quotes);
5419 if (subtype == VSPLUS || subtype == VSLENGTH)
5420 STADJUST(-len, expdest);
5426 * Record the fact that we have to scan this region of the
5427 * string for IFS characters.
5431 recordregion(int start, int end, int nulonly)
5433 struct ifsregion *ifsp;
5435 if (ifslastp == NULL) {
5439 ifsp = (struct ifsregion *)ckmalloc(sizeof (struct ifsregion));
5441 ifslastp->next = ifsp;
5445 ifslastp->begoff = start;
5446 ifslastp->endoff = end;
5447 ifslastp->nulonly = nulonly;
5452 * Break the argument string into pieces based upon IFS and add the
5453 * strings to the argument list. The regions of the string to be
5454 * searched for IFS characters have been stored by recordregion.
5457 ifsbreakup(char *string, struct arglist *arglist)
5459 struct ifsregion *ifsp;
5464 const char *ifs, *realifs;
5470 if (ifslastp != NULL) {
5473 realifs = ifsset() ? ifsval() : defifs;
5476 p = string + ifsp->begoff;
5477 nulonly = ifsp->nulonly;
5478 ifs = nulonly ? nullstr : realifs;
5480 while (p < string + ifsp->endoff) {
5484 if (strchr(ifs, *p)) {
5486 ifsspc = (strchr(defifs, *p) != NULL);
5487 /* Ignore IFS whitespace at start */
5488 if (q == start && ifsspc) {
5494 sp = (struct strlist *)stalloc(sizeof *sp);
5496 *arglist->lastp = sp;
5497 arglist->lastp = &sp->next;
5501 if (p >= string + ifsp->endoff) {
5507 if (strchr(ifs, *p) == NULL ) {
5510 } else if (strchr(defifs, *p) == NULL) {
5526 } while ((ifsp = ifsp->next) != NULL);
5535 sp = (struct strlist *)stalloc(sizeof *sp);
5537 *arglist->lastp = sp;
5538 arglist->lastp = &sp->next;
5544 struct ifsregion *p;
5549 struct ifsregion *ifsp;
5555 ifsfirst.next = NULL;
5559 static void expmeta(char *, char *);
5560 static struct strlist *expsort(struct strlist *);
5561 static struct strlist *msort(struct strlist *, int);
5563 static char *expdir;
5567 expandmeta(struct strlist *str, int flag)
5569 static const char metachars[] = {
5572 /* TODO - EXP_REDIR */
5575 struct strlist **savelastp;
5581 if (!strpbrk(str->text, metachars))
5583 savelastp = exparg.lastp;
5586 p = preglob(str->text, 0, RMESCAPE_ALLOC | RMESCAPE_HEAP);
5588 int i = strlen(str->text);
5589 expdir = ckmalloc(i < 2048 ? 2048 : i); /* XXX */
5597 if (exparg.lastp == savelastp) {
5602 *exparg.lastp = str;
5603 rmescapes(str->text);
5604 exparg.lastp = &str->next;
5606 *exparg.lastp = NULL;
5607 *savelastp = sp = expsort(*savelastp);
5608 while (sp->next != NULL)
5610 exparg.lastp = &sp->next;
5617 * Add a file name to the list.
5621 addfname(const char *name)
5625 sp = (struct strlist *)stalloc(sizeof *sp);
5626 sp->text = sstrdup(name);
5628 exparg.lastp = &sp->next;
5633 * Do metacharacter (i.e. *, ?, [...]) expansion.
5637 expmeta(char *enddir, char *name)
5652 for (p = name; *p; p++) {
5653 if (*p == '*' || *p == '?')
5655 else if (*p == '[') {
5662 if (*q == '/' || *q == '\0')
5669 } else if (*p == '\\')
5671 else if (*p == '/') {
5678 if (metaflag == 0) { /* we've reached the end of the file name */
5679 if (enddir != expdir)
5687 if (metaflag == 0 || lstat(expdir, &statb) >= 0)
5698 } while (p < start);
5700 if (enddir == expdir) {
5702 } else if (enddir == expdir + 1 && *expdir == '/') {
5708 if ((dirp = opendir(cp)) == NULL)
5710 if (enddir != expdir)
5712 if (*endname == 0) {
5724 while (! intpending && (dp = readdir(dirp)) != NULL) {
5725 if (dp->d_name[0] == '.' && ! matchdot)
5727 if (pmatch(start, dp->d_name)) {
5729 scopy(dp->d_name, enddir);
5732 for (p = enddir, cp = dp->d_name;
5733 (*p++ = *cp++) != '\0';)
5736 expmeta(p, endname);
5746 * Sort the results of file name expansion. It calculates the number of
5747 * strings to sort and then calls msort (short for merge sort) to do the
5751 static struct strlist *
5752 expsort(struct strlist *str)
5758 for (sp = str ; sp ; sp = sp->next)
5760 return msort(str, len);
5764 static struct strlist *
5765 msort(struct strlist *list, int len)
5767 struct strlist *p, *q = NULL;
5768 struct strlist **lpp;
5776 for (n = half ; --n >= 0 ; ) {
5780 q->next = NULL; /* terminate first half of list */
5781 q = msort(list, half); /* sort first half of list */
5782 p = msort(p, len - half); /* sort second half */
5785 #ifdef CONFIG_LOCALE_SUPPORT
5786 if (strcoll(p->text, q->text) < 0)
5788 if (strcmp(p->text, q->text) < 0)
5793 if ((p = *lpp) == NULL) {
5800 if ((q = *lpp) == NULL) {
5811 * Returns true if the pattern matches the string.
5814 static int patmatch(char *pattern, const char *string)
5816 return pmatch(preglob(pattern, 0, 0), string);
5821 * Remove any CTLESC characters from a string.
5825 _rmescapes(char *str, int flag)
5828 static const char qchars[] = { CTLESC, CTLQUOTEMARK, 0 };
5833 p = strpbrk(str, qchars);
5839 if (flag & RMESCAPE_ALLOC) {
5840 size_t len = p - str;
5841 size_t fulllen = len + strlen(p) + 1;
5843 if (flag & RMESCAPE_GROW) {
5844 r = makestrspace(fulllen, expdest);
5845 } else if (flag & RMESCAPE_HEAP) {
5846 r = ckmalloc(fulllen);
5848 r = stalloc(fulllen);
5852 q = mempcpy(q, str, len);
5855 inquotes = (flag & RMESCAPE_QUOTED) ^ RMESCAPE_QUOTED;
5856 globbing = flag & RMESCAPE_GLOB;
5857 notescaped = globbing;
5859 if (*p == CTLQUOTEMARK) {
5860 inquotes = ~inquotes;
5862 notescaped = globbing;
5866 /* naked back slash */
5872 if (notescaped && inquotes && *p != '/') {
5876 notescaped = globbing;
5881 if (flag & RMESCAPE_GROW) {
5883 STADJUST(q - r + 1, expdest);
5890 * See if a pattern matches in a case statement.
5894 casematch(union node *pattern, char *val)
5896 struct stackmark smark;
5899 setstackmark(&smark);
5900 argbackq = pattern->narg.backquote;
5901 STARTSTACKSTR(expdest);
5903 argstr(pattern->narg.text, EXP_TILDE | EXP_CASE);
5904 STACKSTRNUL(expdest);
5905 result = patmatch(stackblock(), val);
5906 popstackmark(&smark);
5919 expdest = makestrspace(32, expdest);
5920 #ifdef CONFIG_ASH_MATH_SUPPORT_64
5921 len = fmtstr(expdest, 32, "%lld", (long long) num);
5923 len = fmtstr(expdest, 32, "%ld", num);
5925 STADJUST(len, expdest);
5930 varunset(const char *end, const char *var, const char *umsg, int varflags)
5936 msg = "parameter not set";
5938 if (*end == CTLENDVAR) {
5939 if (varflags & VSNUL)
5944 sh_error("%.*s: %s%s", end - var - 1, var, msg, tail);
5951 * This implements the input routines used by the parser.
5954 #define EOF_NLEFT -99 /* value of parsenleft when EOF pushed back */
5956 static void pushfile(void);
5959 * Read a character from the script, returning PEOF on end of file.
5960 * Nul characters in the input are silently discarded.
5964 #define pgetc_as_macro() (--parsenleft >= 0? SC2INT(*parsenextc++) : preadbuffer())
5966 #ifdef CONFIG_ASH_OPTIMIZE_FOR_SIZE
5967 #define pgetc_macro() pgetc()
5971 return pgetc_as_macro();
5974 #define pgetc_macro() pgetc_as_macro()
5978 return pgetc_macro();
5984 * Same as pgetc(), but ignores PEOA.
5986 #ifdef CONFIG_ASH_ALIAS
5987 static int pgetc2(void)
5993 } while (c == PEOA);
5997 static int pgetc2(void)
5999 return pgetc_macro();
6004 * Read a line from the script.
6007 static char * pfgets(char *line, int len)
6013 while (--nleft > 0) {
6030 #ifdef CONFIG_FEATURE_COMMAND_EDITING
6031 #ifdef CONFIG_ASH_EXPAND_PRMT
6032 static char *cmdedit_prompt;
6034 static const char *cmdedit_prompt;
6036 static void putprompt(const char *s)
6038 #ifdef CONFIG_ASH_EXPAND_PRMT
6039 free(cmdedit_prompt);
6040 cmdedit_prompt = xstrdup(s);
6046 static void putprompt(const char *s)
6052 static int preadfd(void)
6055 char *buf = parsefile->buf;
6059 #ifdef CONFIG_FEATURE_COMMAND_EDITING
6060 if (!iflag || parsefile->fd)
6061 nr = safe_read(parsefile->fd, buf, BUFSIZ - 1);
6063 #ifdef CONFIG_FEATURE_COMMAND_TAB_COMPLETION
6064 cmdedit_path_lookup = pathval();
6066 nr = cmdedit_read_input((char *) cmdedit_prompt, buf);
6068 /* Ctrl+C presend */
6077 if(nr < 0 && errno == 0) {
6078 /* Ctrl+D presend */
6083 nr = safe_read(parsefile->fd, buf, BUFSIZ - 1);
6087 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
6088 int flags = fcntl(0, F_GETFL, 0);
6089 if (flags >= 0 && flags & O_NONBLOCK) {
6090 flags &=~ O_NONBLOCK;
6091 if (fcntl(0, F_SETFL, flags) >= 0) {
6092 out2str("sh: turning off NDELAY mode\n");
6102 * Refill the input buffer and return the next input character:
6104 * 1) If a string was pushed back on the input, pop it;
6105 * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading
6106 * from a string so we can't refill the buffer, return EOF.
6107 * 3) If the is more stuff in this buffer, use it else call read to fill it.
6108 * 4) Process input up to the next newline, deleting nul characters.
6118 while (parsefile->strpush) {
6119 #ifdef CONFIG_ASH_ALIAS
6120 if (parsenleft == -1 && parsefile->strpush->ap &&
6121 parsenextc[-1] != ' ' && parsenextc[-1] != '\t') {
6126 if (--parsenleft >= 0)
6127 return SC2INT(*parsenextc++);
6129 if (parsenleft == EOF_NLEFT || parsefile->buf == NULL)
6136 if ((more = preadfd()) <= 0) {
6137 parselleft = parsenleft = EOF_NLEFT;
6144 /* delete nul characters */
6152 memmove(q, q + 1, more);
6156 parsenleft = q - parsenextc - 1;
6162 parsenleft = q - parsenextc - 1;
6174 out2str(parsenextc);
6179 return SC2INT(*parsenextc++);
6183 * Undo the last call to pgetc. Only one character may be pushed back.
6184 * PEOF may be pushed back.
6195 * Push a string back onto the input at this current parsefile level.
6196 * We handle aliases this way.
6199 pushstring(char *s, void *ap)
6206 /*dprintf("*** calling pushstring: %s, %d\n", s, len);*/
6207 if (parsefile->strpush) {
6208 sp = ckmalloc(sizeof (struct strpush));
6209 sp->prev = parsefile->strpush;
6210 parsefile->strpush = sp;
6212 sp = parsefile->strpush = &(parsefile->basestrpush);
6213 sp->prevstring = parsenextc;
6214 sp->prevnleft = parsenleft;
6215 #ifdef CONFIG_ASH_ALIAS
6216 sp->ap = (struct alias *)ap;
6218 ((struct alias *)ap)->flag |= ALIASINUSE;
6230 struct strpush *sp = parsefile->strpush;
6233 #ifdef CONFIG_ASH_ALIAS
6235 if (parsenextc[-1] == ' ' || parsenextc[-1] == '\t') {
6236 checkkwd |= CHKALIAS;
6238 if (sp->string != sp->ap->val) {
6241 sp->ap->flag &= ~ALIASINUSE;
6242 if (sp->ap->flag & ALIASDEAD) {
6243 unalias(sp->ap->name);
6247 parsenextc = sp->prevstring;
6248 parsenleft = sp->prevnleft;
6249 /*dprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/
6250 parsefile->strpush = sp->prev;
6251 if (sp != &(parsefile->basestrpush))
6257 * Set the input to take input from a file. If push is set, push the
6258 * old input onto the stack first.
6262 setinputfile(const char *fname, int flags)
6268 if ((fd = open(fname, O_RDONLY)) < 0) {
6269 if (flags & INPUT_NOFILE_OK)
6271 sh_error("Can't open %s", fname);
6274 fd2 = copyfd(fd, 10);
6277 sh_error("Out of file descriptors");
6280 setinputfd(fd, flags & INPUT_PUSH_FILE);
6288 * Like setinputfile, but takes an open file descriptor. Call this with
6293 setinputfd(int fd, int push)
6295 (void) fcntl(fd, F_SETFD, FD_CLOEXEC);
6301 if (parsefile->buf == NULL)
6302 parsefile->buf = ckmalloc(IBUFSIZ);
6303 parselleft = parsenleft = 0;
6309 * Like setinputfile, but takes input from a string.
6313 setinputstring(char *string)
6317 parsenextc = string;
6318 parsenleft = strlen(string);
6319 parsefile->buf = NULL;
6326 * To handle the "." command, a stack of input files is used. Pushfile
6327 * adds a new entry to the stack and popfile restores the previous level.
6333 struct parsefile *pf;
6335 parsefile->nleft = parsenleft;
6336 parsefile->lleft = parselleft;
6337 parsefile->nextc = parsenextc;
6338 parsefile->linno = plinno;
6339 pf = (struct parsefile *)ckmalloc(sizeof (struct parsefile));
6340 pf->prev = parsefile;
6343 pf->basestrpush.prev = NULL;
6351 struct parsefile *pf = parsefile;
6360 parsefile = pf->prev;
6362 parsenleft = parsefile->nleft;
6363 parselleft = parsefile->lleft;
6364 parsenextc = parsefile->nextc;
6365 plinno = parsefile->linno;
6371 * Return to top level.
6377 while (parsefile != &basepf)
6383 * Close the file(s) that the shell is reading commands from. Called
6384 * after a fork is done.
6391 if (parsefile->fd > 0) {
6392 close(parsefile->fd);
6399 /* mode flags for set_curjob */
6400 #define CUR_DELETE 2
6401 #define CUR_RUNNING 1
6402 #define CUR_STOPPED 0
6404 /* mode flags for dowait */
6405 #define DOWAIT_NORMAL 0
6406 #define DOWAIT_BLOCK 1
6409 static struct job *jobtab;
6411 static unsigned njobs;
6413 /* pgrp of shell on invocation */
6414 static int initialpgrp;
6415 static int ttyfd = -1;
6418 static struct job *curjob;
6419 /* number of presumed living untracked jobs */
6422 static void set_curjob(struct job *, unsigned);
6424 static int restartjob(struct job *, int);
6425 static void xtcsetpgrp(int, pid_t);
6426 static char *commandtext(union node *);
6427 static void cmdlist(union node *, int);
6428 static void cmdtxt(union node *);
6429 static void cmdputs(const char *);
6430 static void showpipe(struct job *, FILE *);
6432 static int sprint_status(char *, int, int);
6433 static void freejob(struct job *);
6434 static struct job *getjob(const char *, int);
6435 static struct job *growjobtab(void);
6436 static void forkchild(struct job *, union node *, int);
6437 static void forkparent(struct job *, union node *, int, pid_t);
6438 static int dowait(int, struct job *);
6439 static int getstatus(struct job *);
6442 set_curjob(struct job *jp, unsigned mode)
6445 struct job **jpp, **curp;
6447 /* first remove from list */
6448 jpp = curp = &curjob;
6453 jpp = &jp1->prev_job;
6455 *jpp = jp1->prev_job;
6457 /* Then re-insert in correct position */
6465 /* job being deleted */
6468 /* newly created job or backgrounded job,
6469 put after all stopped jobs. */
6473 if (!jp1 || jp1->state != JOBSTOPPED)
6476 jpp = &jp1->prev_job;
6482 /* newly stopped job - becomes curjob */
6483 jp->prev_job = *jpp;
6491 * Turn job control on and off.
6493 * Note: This code assumes that the third arg to ioctl is a character
6494 * pointer, which is true on Berkeley systems but not System V. Since
6495 * System V doesn't have job control yet, this isn't a problem now.
6497 * Called with interrupts off.
6506 if (on == jobctl || rootshell == 0)
6510 ofd = fd = open(_PATH_TTY, O_RDWR);
6513 while (!isatty(fd) && --fd >= 0)
6516 fd = fcntl(fd, F_DUPFD, 10);
6520 fcntl(fd, F_SETFD, FD_CLOEXEC);
6521 do { /* while we are in the background */
6522 if ((pgrp = tcgetpgrp(fd)) < 0) {
6524 sh_warnx("can't access tty; job control turned off");
6528 if (pgrp == getpgrp())
6539 xtcsetpgrp(fd, pgrp);
6541 /* turning job control off */
6544 xtcsetpgrp(fd, pgrp);
6558 killcmd(int argc, char **argv)
6569 "Usage: kill [-s sigspec | -signum | -sigspec] [pid | job]... or\n"
6570 "kill -l [exitstatus]"
6574 if (**++argv == '-') {
6575 signo = get_signum(*argv + 1);
6579 while ((c = nextopt("ls:")) != '\0')
6589 signo = get_signum(optionarg);
6592 "invalid signal number or name: %s",
6603 if (!list && signo < 0)
6606 if ((signo < 0 || !*argv) ^ list) {
6614 for (i = 1; i < NSIG; i++) {
6615 name = get_signame(i);
6617 out1fmt(snlfmt, name);
6621 name = get_signame(signo);
6623 out1fmt(snlfmt, name);
6625 sh_error("invalid signal number or exit status: %s", *argptr);
6631 if (**argv == '%') {
6632 jp = getjob(*argv, 0);
6633 pid = -jp->ps[0].pid;
6635 pid = **argv == '-' ?
6636 -number(*argv + 1) : number(*argv);
6638 if (kill(pid, signo) != 0) {
6639 sh_warnx("(%d) - %m", pid);
6648 #if defined(JOBS) || defined(DEBUG)
6650 jobno(const struct job *jp)
6652 return jp - jobtab + 1;
6658 fgcmd(int argc, char **argv)
6665 mode = (**argv == 'f') ? FORK_FG : FORK_BG;
6670 jp = getjob(*argv, 1);
6671 if (mode == FORK_BG) {
6672 set_curjob(jp, CUR_RUNNING);
6673 fprintf(out, "[%d] ", jobno(jp));
6675 outstr(jp->ps->cmd, out);
6677 retval = restartjob(jp, mode);
6678 } while (*argv && *++argv);
6682 static int bgcmd(int, char **) __attribute__((__alias__("fgcmd")));
6686 restartjob(struct job *jp, int mode)
6688 struct procstat *ps;
6694 if (jp->state == JOBDONE)
6696 jp->state = JOBRUNNING;
6698 if (mode == FORK_FG)
6699 xtcsetpgrp(ttyfd, pgid);
6700 killpg(pgid, SIGCONT);
6704 if (WIFSTOPPED(ps->status)) {
6707 } while (ps++, --i);
6709 status = (mode == FORK_FG) ? waitforjob(jp) : 0;
6716 sprint_status(char *s, int status, int sigonly)
6722 if (!WIFEXITED(status)) {
6724 if (WIFSTOPPED(status))
6725 st = WSTOPSIG(status);
6728 st = WTERMSIG(status);
6730 if (st == SIGINT || st == SIGPIPE)
6733 if (WIFSTOPPED(status))
6738 col = fmtstr(s, 32, strsignal(st));
6739 if (WCOREDUMP(status)) {
6740 col += fmtstr(s + col, 16, " (core dumped)");
6742 } else if (!sigonly) {
6743 st = WEXITSTATUS(status);
6745 col = fmtstr(s, 16, "Done(%d)", st);
6747 col = fmtstr(s, 16, "Done");
6756 showjob(FILE *out, struct job *jp, int mode)
6758 struct procstat *ps;
6759 struct procstat *psend;
6766 if (mode & SHOW_PGID) {
6767 /* just output process (group) id of pipeline */
6768 fprintf(out, "%d\n", ps->pid);
6772 col = fmtstr(s, 16, "[%d] ", jobno(jp));
6777 else if (curjob && jp == curjob->prev_job)
6780 if (mode & SHOW_PID)
6781 col += fmtstr(s + col, 16, "%d ", ps->pid);
6783 psend = ps + jp->nprocs;
6785 if (jp->state == JOBRUNNING) {
6786 scopy("Running", s + col);
6787 col += strlen("Running");
6789 int status = psend[-1].status;
6791 if (jp->state == JOBSTOPPED)
6792 status = jp->stopstatus;
6794 col += sprint_status(s + col, status, 0);
6800 /* for each process */
6801 col = fmtstr(s, 48, " |\n%*c%d ", indent, ' ', ps->pid) - 3;
6804 fprintf(out, "%s%*c%s",
6805 s, 33 - col >= 0 ? 33 - col : 0, ' ', ps->cmd
6807 if (!(mode & SHOW_PID)) {
6811 if (++ps == psend) {
6812 outcslow('\n', out);
6819 if (jp->state == JOBDONE) {
6820 TRACE(("showjob: freeing job %d\n", jobno(jp)));
6827 jobscmd(int argc, char **argv)
6833 while ((m = nextopt("lp")))
6843 showjob(out, getjob(*argv,0), mode);
6846 showjobs(out, mode);
6853 * Print a list of jobs. If "change" is nonzero, only print jobs whose
6854 * statuses have changed since the last call to showjobs.
6858 showjobs(FILE *out, int mode)
6862 TRACE(("showjobs(%x) called\n", mode));
6864 /* If not even one one job changed, there is nothing to do */
6865 while (dowait(DOWAIT_NORMAL, NULL) > 0)
6868 for (jp = curjob; jp; jp = jp->prev_job) {
6869 if (!(mode & SHOW_CHANGED) || jp->changed)
6870 showjob(out, jp, mode);
6876 * Mark a job structure as unused.
6880 freejob(struct job *jp)
6882 struct procstat *ps;
6886 for (i = jp->nprocs, ps = jp->ps ; --i >= 0 ; ps++) {
6887 if (ps->cmd != nullstr)
6890 if (jp->ps != &jp->ps0)
6893 set_curjob(jp, CUR_DELETE);
6899 waitcmd(int argc, char **argv)
6912 /* wait for all jobs */
6917 /* no running procs */
6920 if (jp->state == JOBRUNNING)
6925 dowait(DOWAIT_BLOCK, 0);
6931 if (**argv != '%') {
6932 pid_t pid = number(*argv);
6936 if (job->ps[job->nprocs - 1].pid == pid)
6938 job = job->prev_job;
6944 job = getjob(*argv, 0);
6945 /* loop until process terminated or stopped */
6946 while (job->state == JOBRUNNING)
6947 dowait(DOWAIT_BLOCK, 0);
6949 retval = getstatus(job);
6960 * Convert a job name to a job structure.
6964 getjob(const char *name, int getctl)
6968 const char *err_msg = "No such job: %s";
6972 char *(*match)(const char *, const char *);
6987 if (c == '+' || c == '%') {
6989 err_msg = "No current job";
6991 } else if (c == '-') {
6994 err_msg = "No previous job";
7005 jp = jobtab + num - 1;
7022 if (match(jp->ps[0].cmd, p)) {
7026 err_msg = "%s: ambiguous";
7033 err_msg = "job %s not created under job control";
7034 if (getctl && jp->jobctl == 0)
7039 sh_error(err_msg, name);
7044 * Return a new job structure.
7045 * Called with interrupts off.
7049 makejob(union node *node, int nprocs)
7054 for (i = njobs, jp = jobtab ; ; jp++) {
7061 if (jp->state != JOBDONE || !jp->waited)
7070 memset(jp, 0, sizeof(*jp));
7075 jp->prev_job = curjob;
7080 jp->ps = ckmalloc(nprocs * sizeof (struct procstat));
7082 TRACE(("makejob(0x%lx, %d) returns %%%d\n", (long)node, nprocs,
7092 struct job *jp, *jq;
7094 len = njobs * sizeof(*jp);
7096 jp = ckrealloc(jq, len + 4 * sizeof(*jp));
7098 offset = (char *)jp - (char *)jq;
7100 /* Relocate pointers */
7103 jq = (struct job *)((char *)jq + l);
7107 #define joff(p) ((struct job *)((char *)(p) + l))
7108 #define jmove(p) (p) = (void *)((char *)(p) + offset)
7109 if (xlikely(joff(jp)->ps == &jq->ps0))
7110 jmove(joff(jp)->ps);
7111 if (joff(jp)->prev_job)
7112 jmove(joff(jp)->prev_job);
7122 jp = (struct job *)((char *)jp + len);
7126 } while (--jq >= jp);
7132 * Fork off a subshell. If we are doing job control, give the subshell its
7133 * own process group. Jp is a job structure that the job is to be added to.
7134 * N is the command that will be evaluated by the child. Both jp and n may
7135 * be NULL. The mode parameter can be one of the following:
7136 * FORK_FG - Fork off a foreground process.
7137 * FORK_BG - Fork off a background process.
7138 * FORK_NOJOB - Like FORK_FG, but don't give the process its own
7139 * process group even if job control is on.
7141 * When job control is turned off, background processes have their standard
7142 * input redirected to /dev/null (except for the second and later processes
7145 * Called with interrupts off.
7148 static void forkchild(struct job *jp, union node *n, int mode)
7152 TRACE(("Child shell %d\n", getpid()));
7159 /* do job control only in root shell */
7161 if (mode != FORK_NOJOB && jp->jobctl && !oldlvl) {
7164 if (jp->nprocs == 0)
7167 pgrp = jp->ps[0].pid;
7168 /* This can fail because we are doing it in the parent also */
7169 (void)setpgid(0, pgrp);
7170 if (mode == FORK_FG)
7171 xtcsetpgrp(ttyfd, pgrp);
7176 if (mode == FORK_BG) {
7179 if (jp->nprocs == 0) {
7181 if (open(bb_dev_null, O_RDONLY) != 0)
7182 sh_error("Can't open %s", bb_dev_null);
7185 if (!oldlvl && iflag) {
7190 for (jp = curjob; jp; jp = jp->prev_job)
7195 static void forkparent(struct job *jp, union node *n, int mode, pid_t pid)
7197 TRACE(("In parent shell: child = %d\n", pid));
7199 while (jobless && dowait(DOWAIT_NORMAL, 0) > 0);
7204 if (mode != FORK_NOJOB && jp->jobctl) {
7207 if (jp->nprocs == 0)
7210 pgrp = jp->ps[0].pid;
7211 /* This can fail because we are doing it in the child also */
7212 (void)setpgid(pid, pgrp);
7215 if (mode == FORK_BG) {
7216 backgndpid = pid; /* set $! */
7217 set_curjob(jp, CUR_RUNNING);
7220 struct procstat *ps = &jp->ps[jp->nprocs++];
7226 ps->cmd = commandtext(n);
7232 forkshell(struct job *jp, union node *n, int mode)
7236 TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode));
7239 TRACE(("Fork failed, errno=%d", errno));
7242 sh_error("Cannot fork");
7245 forkchild(jp, n, mode);
7247 forkparent(jp, n, mode, pid);
7252 * Wait for job to finish.
7254 * Under job control we have the problem that while a child process is
7255 * running interrupts generated by the user are sent to the child but not
7256 * to the shell. This means that an infinite loop started by an inter-
7257 * active user may be hard to kill. With job control turned off, an
7258 * interactive user may place an interactive program inside a loop. If
7259 * the interactive program catches interrupts, the user doesn't want
7260 * these interrupts to also abort the loop. The approach we take here
7261 * is to have the shell ignore interrupt signals while waiting for a
7262 * foreground process to terminate, and then send itself an interrupt
7263 * signal if the child process was terminated by an interrupt signal.
7264 * Unfortunately, some programs want to do a bit of cleanup and then
7265 * exit on interrupt; unless these processes terminate themselves by
7266 * sending a signal to themselves (instead of calling exit) they will
7267 * confuse this approach.
7269 * Called with interrupts off.
7273 waitforjob(struct job *jp)
7277 TRACE(("waitforjob(%%%d) called\n", jobno(jp)));
7278 while (jp->state == JOBRUNNING) {
7279 dowait(DOWAIT_BLOCK, jp);
7284 xtcsetpgrp(ttyfd, rootpid);
7286 * This is truly gross.
7287 * If we're doing job control, then we did a TIOCSPGRP which
7288 * caused us (the shell) to no longer be in the controlling
7289 * session -- so we wouldn't have seen any ^C/SIGINT. So, we
7290 * intuit from the subprocess exit status whether a SIGINT
7291 * occurred, and if so interrupt ourselves. Yuck. - mycroft
7296 if (jp->state == JOBDONE)
7304 * Do a wait system call. If job control is compiled in, we accept
7305 * stopped processes. If block is zero, we return a value of zero
7306 * rather than blocking.
7308 * System V doesn't have a non-blocking wait system call. It does
7309 * have a SIGCLD signal that is sent to a process when one of it's
7310 * children dies. The obvious way to use SIGCLD would be to install
7311 * a handler for SIGCLD which simply bumped a counter when a SIGCLD
7312 * was received, and have waitproc bump another counter when it got
7313 * the status of a process. Waitproc would then know that a wait
7314 * system call would not block if the two counters were different.
7315 * This approach doesn't work because if a process has children that
7316 * have not been waited for, System V will send it a SIGCLD when it
7317 * installs a signal handler for SIGCLD. What this means is that when
7318 * a child exits, the shell will be sent SIGCLD signals continuously
7319 * until is runs out of stack space, unless it does a wait call before
7320 * restoring the signal handler. The code below takes advantage of
7321 * this (mis)feature by installing a signal handler for SIGCLD and
7322 * then checking to see whether it was called. If there are any
7323 * children to be waited for, it will be.
7325 * If neither SYSV nor BSD is defined, we don't implement nonblocking
7326 * waits at all. In this case, the user will not be informed when
7327 * a background process until the next time she runs a real program
7328 * (as opposed to running a builtin command or just typing return),
7329 * and the jobs command may give out of date information.
7332 static int waitproc(int block, int *status)
7342 return wait3(status, flags, (struct rusage *)NULL);
7346 * Wait for a process to terminate.
7350 dowait(int block, struct job *job)
7355 struct job *thisjob;
7358 TRACE(("dowait(%d) called\n", block));
7359 pid = waitproc(block, &status);
7360 TRACE(("wait returns pid %d, status=%d\n", pid, status));
7365 for (jp = curjob; jp; jp = jp->prev_job) {
7366 struct procstat *sp;
7367 struct procstat *spend;
7368 if (jp->state == JOBDONE)
7371 spend = jp->ps + jp->nprocs;
7374 if (sp->pid == pid) {
7375 TRACE(("Job %d: changing status of proc %d from 0x%x to 0x%x\n", jobno(jp), pid, sp->status, status));
7376 sp->status = status;
7379 if (sp->status == -1)
7382 if (state == JOBRUNNING)
7384 if (WIFSTOPPED(sp->status)) {
7385 jp->stopstatus = sp->status;
7389 } while (++sp < spend);
7394 if (!WIFSTOPPED(status))
7401 if (state != JOBRUNNING) {
7402 thisjob->changed = 1;
7404 if (thisjob->state != state) {
7405 TRACE(("Job %d: changing state from %d to %d\n", jobno(thisjob), thisjob->state, state));
7406 thisjob->state = state;
7408 if (state == JOBSTOPPED) {
7409 set_curjob(thisjob, CUR_STOPPED);
7418 if (thisjob && thisjob == job) {
7422 len = sprint_status(s, status, 1);
7434 * return 1 if there are stopped jobs, otherwise 0
7447 if (jp && jp->state == JOBSTOPPED) {
7448 out2str("You have stopped jobs.\n");
7458 * Return a string identifying a command (to be printed by the
7463 static char *cmdnextc;
7466 commandtext(union node *n)
7470 STARTSTACKSTR(cmdnextc);
7472 name = stackblock();
7473 TRACE(("commandtext: name %p, end %p\n\t\"%s\"\n",
7474 name, cmdnextc, cmdnextc));
7475 return savestr(name);
7479 cmdtxt(union node *n)
7482 struct nodelist *lp;
7494 lp = n->npipe.cmdlist;
7512 cmdtxt(n->nbinary.ch1);
7528 cmdtxt(n->nif.test);
7531 if (n->nif.elsepart) {
7534 n = n->nif.elsepart;
7550 cmdtxt(n->nbinary.ch1);
7560 cmdputs(n->nfor.var);
7562 cmdlist(n->nfor.args, 1);
7567 cmdputs(n->narg.text);
7571 cmdlist(n->ncmd.args, 1);
7572 cmdlist(n->ncmd.redirect, 0);
7585 cmdputs(n->ncase.expr->narg.text);
7587 for (np = n->ncase.cases; np; np = np->nclist.next) {
7588 cmdtxt(np->nclist.pattern);
7590 cmdtxt(np->nclist.body);
7616 s[0] = n->nfile.fd + '0';
7620 if (n->type == NTOFD || n->type == NFROMFD) {
7621 s[0] = n->ndup.dupfd + '0';
7632 cmdlist(union node *np, int sep)
7634 for (; np; np = np->narg.next) {
7638 if (sep && np->narg.next)
7644 cmdputs(const char *s)
7646 const char *p, *str;
7647 char c, cc[2] = " ";
7651 static const char vstype[VSTYPE + 1][4] = {
7652 "", "}", "-", "+", "?", "=",
7653 "%", "%%", "#", "##"
7655 nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc);
7657 while ((c = *p++) != 0) {
7665 if ((subtype & VSTYPE) == VSLENGTH)
7669 if (!(subtype & VSQUOTE) != !(quoted & 1)) {
7676 str = "\"}" + !(quoted & 1);
7683 case CTLBACKQ+CTLQUOTE:
7686 #ifdef CONFIG_ASH_MATH_SUPPORT
7701 if ((subtype & VSTYPE) != VSNORMAL)
7703 str = vstype[subtype & VSTYPE];
7704 if (subtype & VSNUL)
7713 /* These can only happen inside quotes */
7726 while ((c = *str++)) {
7731 USTPUTC('"', nextc);
7739 showpipe(struct job *jp, FILE *out)
7741 struct procstat *sp;
7742 struct procstat *spend;
7744 spend = jp->ps + jp->nprocs;
7745 for (sp = jp->ps + 1; sp < spend; sp++)
7746 fprintf(out, " | %s", sp->cmd);
7747 outcslow('\n', out);
7752 xtcsetpgrp(int fd, pid_t pgrp)
7754 if (tcsetpgrp(fd, pgrp))
7755 sh_error("Cannot set tty process group (%m)");
7760 getstatus(struct job *job) {
7764 status = job->ps[job->nprocs - 1].status;
7765 retval = WEXITSTATUS(status);
7766 if (!WIFEXITED(status)) {
7768 retval = WSTOPSIG(status);
7769 if (!WIFSTOPPED(status))
7772 /* XXX: limits number of signals */
7773 retval = WTERMSIG(status);
7775 if (retval == SIGINT)
7781 TRACE(("getstatus: job %d, nproc %d, status %x, retval %x\n",
7782 jobno(job), job->nprocs, status, retval));
7786 #ifdef CONFIG_ASH_MAIL
7790 * Routines to check for mail. (Perhaps make part of main.c?)
7793 #define MAXMBOXES 10
7795 /* times of mailboxes */
7796 static time_t mailtime[MAXMBOXES];
7797 /* Set if MAIL or MAILPATH is changed. */
7798 static int mail_var_path_changed;
7803 * Print appropriate message(s) if mail has arrived.
7804 * If mail_var_path_changed is set,
7805 * then the value of MAIL has mail_var_path_changed,
7806 * so we just update the values.
7816 struct stackmark smark;
7819 setstackmark(&smark);
7820 mpath = mpathset() ? mpathval() : mailval();
7821 for (mtp = mailtime; mtp < mailtime + MAXMBOXES; mtp++) {
7822 p = padvance(&mpath, nullstr);
7827 for (q = p ; *q ; q++);
7832 q[-1] = '\0'; /* delete trailing '/' */
7833 if (stat(p, &statb) < 0) {
7837 if (!mail_var_path_changed && statb.st_mtime != *mtp) {
7840 pathopt ? pathopt : "you have mail"
7843 *mtp = statb.st_mtime;
7845 mail_var_path_changed = 0;
7846 popstackmark(&smark);
7851 changemail(const char *val)
7853 mail_var_path_changed++;
7856 #endif /* CONFIG_ASH_MAIL */
7862 static short profile_buf[16384];
7866 static int isloginsh;
7868 static void read_profile(const char *);
7871 * Main routine. We initialize things, parse the arguments, execute
7872 * profiles if we're a login shell, and then call cmdloop to execute
7873 * commands. The setjmp call sets up the location to jump to when an
7874 * exception occurs. When an exception occurs the variable "state"
7875 * is used to figure out how far we had gotten.
7879 ash_main(int argc, char **argv)
7883 struct jmploc jmploc;
7884 struct stackmark smark;
7887 dash_errno = __errno_location();
7891 monitor(4, etext, profile_buf, sizeof profile_buf, 50);
7894 if (setjmp(jmploc.loc)) {
7904 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl)
7908 outcslow('\n', stderr);
7910 popstackmark(&smark);
7911 FORCEINTON; /* enable interrupts */
7924 trputs("Shell args: "); trargs(argv);
7928 #ifdef CONFIG_ASH_RANDOM_SUPPORT
7929 rseed = rootpid + ((time_t)time((time_t *)0));
7932 setstackmark(&smark);
7933 procargs(argc, argv);
7934 #ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
7936 const char *hp = lookupvar("HISTFILE");
7939 hp = lookupvar("HOME");
7941 char *defhp = concat_path_file(hp, ".ash_history");
7942 setvar("HISTFILE", defhp, 0);
7948 if (argv[0] && argv[0][0] == '-')
7952 read_profile("/etc/profile");
7955 read_profile(".profile");
7961 getuid() == geteuid() && getgid() == getegid() &&
7965 if ((shinit = lookupvar("ENV")) != NULL && *shinit != '\0') {
7966 read_profile(shinit);
7972 evalstring(minusc, 0);
7974 if (sflag || minusc == NULL) {
7975 #ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
7977 const char *hp = lookupvar("HISTFILE");
7980 load_history ( hp );
7983 state4: /* XXX ??? - why isn't this before the "if" statement */
7991 extern void _mcleanup(void);
8001 * Read and execute commands. "Top" is nonzero for the top level command
8002 * loop; it turns on prompting if the shell is interactive.
8009 struct stackmark smark;
8013 TRACE(("cmdloop(%d) called\n", top));
8017 setstackmark(&smark);
8020 showjobs(stderr, SHOW_CHANGED);
8025 #ifdef CONFIG_ASH_MAIL
8029 n = parsecmd(inter);
8030 /* showtree(n); DEBUG */
8032 if (!top || numeof >= 50)
8034 if (!stoppedjobs()) {
8037 out2str("\nUse \"exit\" to leave shell.\n");
8040 } else if (nflag == 0) {
8041 job_warning = (job_warning == 2) ? 1 : 0;
8045 popstackmark(&smark);
8050 return skip & SKIPEVAL;
8059 * Read /etc/profile or .profile. Return on error.
8063 read_profile(const char *name)
8067 if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
8079 * Read a file containing shell functions.
8083 readcmdfile(char *name)
8085 setinputfile(name, INPUT_PUSH_FILE);
8092 * Take commands from a file. To be compatible we should do a path
8093 * search for the file, which is necessary to find sub-commands.
8096 static char * find_dot_file(char *name)
8099 const char *path = pathval();
8102 /* don't try this for absolute or relative paths */
8103 if (strchr(name, '/'))
8106 while ((fullname = padvance(&path, name)) != NULL) {
8107 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
8109 * Don't bother freeing here, since it will
8110 * be freed by the caller.
8114 stunalloc(fullname);
8117 /* not found in the PATH */
8118 sh_error(not_found_msg, name);
8122 static int dotcmd(int argc, char **argv)
8125 volatile struct shparam saveparam;
8128 for (sp = cmdenviron; sp; sp = sp->next)
8129 setvareq(xstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
8131 if (argc >= 2) { /* That's what SVR2 does */
8134 fullname = find_dot_file(argv[1]);
8137 saveparam = shellparam;
8138 shellparam.malloc = 0;
8139 shellparam.nparam = argc - 2;
8140 shellparam.p = argv + 2;
8143 setinputfile(fullname, INPUT_PUSH_FILE);
8144 commandname = fullname;
8149 freeparam(&shellparam);
8150 shellparam = saveparam;
8152 status = exitstatus;
8159 exitcmd(int argc, char **argv)
8164 exitstatus = number(argv[1]);
8169 #ifdef CONFIG_ASH_BUILTIN_ECHO
8171 echocmd(int argc, char **argv)
8173 return bb_echo(argc, argv);
8177 #ifdef CONFIG_ASH_BUILTIN_TEST
8179 testcmd(int argc, char **argv)
8181 return bb_test(argc, argv);
8188 * Same for malloc, realloc, but returns an error when out of space.
8192 ckrealloc(pointer p, size_t nbytes)
8194 p = realloc(p, nbytes);
8196 sh_error(bb_msg_memory_exhausted);
8201 ckmalloc(size_t nbytes)
8203 return ckrealloc(NULL, nbytes);
8207 * Make a copy of a string in safe storage.
8211 savestr(const char *s)
8213 char *p = strdup(s);
8215 sh_error(bb_msg_memory_exhausted);
8221 * Parse trees for commands are allocated in lifo order, so we use a stack
8222 * to make this more efficient, and also to avoid all sorts of exception
8223 * handling code to handle interrupts in the middle of a parse.
8225 * The size 504 was chosen because the Ultrix malloc handles that size
8231 stalloc(size_t nbytes)
8236 aligned = SHELL_ALIGN(nbytes);
8237 if (aligned > stacknleft) {
8240 struct stack_block *sp;
8242 blocksize = aligned;
8243 if (blocksize < MINSIZE)
8244 blocksize = MINSIZE;
8245 len = sizeof(struct stack_block) - MINSIZE + blocksize;
8246 if (len < blocksize)
8247 sh_error(bb_msg_memory_exhausted);
8251 stacknxt = sp->space;
8252 stacknleft = blocksize;
8253 sstrend = stacknxt + blocksize;
8258 stacknxt += aligned;
8259 stacknleft -= aligned;
8265 stunalloc(pointer p)
8268 if (!p || (stacknxt < (char *)p) || ((char *)p < stackp->space)) {
8269 write(2, "stunalloc\n", 10);
8273 stacknleft += stacknxt - (char *)p;
8279 setstackmark(struct stackmark *mark)
8281 mark->stackp = stackp;
8282 mark->stacknxt = stacknxt;
8283 mark->stacknleft = stacknleft;
8284 mark->marknext = markp;
8290 popstackmark(struct stackmark *mark)
8292 struct stack_block *sp;
8295 markp = mark->marknext;
8296 while (stackp != mark->stackp) {
8301 stacknxt = mark->stacknxt;
8302 stacknleft = mark->stacknleft;
8303 sstrend = mark->stacknxt + mark->stacknleft;
8309 * When the parser reads in a string, it wants to stick the string on the
8310 * stack and only adjust the stack pointer when it knows how big the
8311 * string is. Stackblock (defined in stack.h) returns a pointer to a block
8312 * of space on top of the stack and stackblocklen returns the length of
8313 * this block. Growstackblock will grow this space by at least one byte,
8314 * possibly moving it (like realloc). Grabstackblock actually allocates the
8315 * part of the block that has been used.
8319 growstackblock(void)
8323 newlen = stacknleft * 2;
8324 if (newlen < stacknleft)
8325 sh_error(bb_msg_memory_exhausted);
8329 if (stacknxt == stackp->space && stackp != &stackbase) {
8330 struct stack_block *oldstackp;
8331 struct stackmark *xmark;
8332 struct stack_block *sp;
8333 struct stack_block *prevstackp;
8339 prevstackp = sp->prev;
8340 grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
8341 sp = ckrealloc((pointer)sp, grosslen);
8342 sp->prev = prevstackp;
8344 stacknxt = sp->space;
8345 stacknleft = newlen;
8346 sstrend = sp->space + newlen;
8349 * Stack marks pointing to the start of the old block
8350 * must be relocated to point to the new block
8353 while (xmark != NULL && xmark->stackp == oldstackp) {
8354 xmark->stackp = stackp;
8355 xmark->stacknxt = stacknxt;
8356 xmark->stacknleft = stacknleft;
8357 xmark = xmark->marknext;
8361 char *oldspace = stacknxt;
8362 int oldlen = stacknleft;
8363 char *p = stalloc(newlen);
8365 /* free the space we just allocated */
8366 stacknxt = memcpy(p, oldspace, oldlen);
8367 stacknleft += newlen;
8371 static void grabstackblock(size_t len)
8373 len = SHELL_ALIGN(len);
8379 * The following routines are somewhat easier to use than the above.
8380 * The user declares a variable of type STACKSTR, which may be declared
8381 * to be a register. The macro STARTSTACKSTR initializes things. Then
8382 * the user uses the macro STPUTC to add characters to the string. In
8383 * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
8384 * grown as necessary. When the user is done, she can just leave the
8385 * string there and refer to it using stackblock(). Or she can allocate
8386 * the space for it using grabstackstr(). If it is necessary to allow
8387 * someone else to use the stack temporarily and then continue to grow
8388 * the string, the user should use grabstack to allocate the space, and
8389 * then call ungrabstr(p) to return to the previous mode of operation.
8391 * USTPUTC is like STPUTC except that it doesn't check for overflow.
8392 * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
8393 * is space for at least one character.
8399 size_t len = stackblocksize();
8400 if (herefd >= 0 && len >= 1024) {
8401 full_write(herefd, stackblock(), len);
8402 return stackblock();
8405 return stackblock() + len;
8409 * Called from CHECKSTRSPACE.
8413 makestrspace(size_t newlen, char *p)
8415 size_t len = p - stacknxt;
8416 size_t size = stackblocksize();
8421 size = stackblocksize();
8423 if (nleft >= newlen)
8427 return stackblock() + len;
8431 stnputs(const char *s, size_t n, char *p)
8433 p = makestrspace(n, p);
8434 p = mempcpy(p, s, n);
8439 stputs(const char *s, char *p)
8441 return stnputs(s, strlen(s), p);
8449 * number(s) Convert a string of digits to an integer.
8450 * is_number(s) Return true if s is a string of digits.
8454 * prefix -- see if pfx is a prefix of string.
8458 prefix(const char *string, const char *pfx)
8461 if (*pfx++ != *string++)
8464 return (char *) string;
8469 * Convert a string of digits to an integer, printing an error message on
8474 number(const char *s)
8478 sh_error(illnum, s);
8484 * Check for a valid number. This should be elsewhere.
8488 is_number(const char *p)
8493 } while (*++p != '\0');
8499 * Produce a possibly single quoted string suitable as input to the shell.
8500 * The return string is allocated on the stack.
8504 single_quote(const char *s) {
8513 len = strchrnul(s, '\'') - s;
8515 q = p = makestrspace(len + 3, p);
8518 q = mempcpy(q, s, len);
8524 len = strspn(s, "'");
8528 q = p = makestrspace(len + 3, p);
8531 q = mempcpy(q, s, len);
8540 return stackblock();
8544 * Like strdup but works with the ash stack.
8548 sstrdup(const char *p)
8550 size_t len = strlen(p) + 1;
8551 return memcpy(stalloc(len), p, len);
8556 calcsize(union node *n)
8560 funcblocksize += nodesize[n->type];
8563 calcsize(n->ncmd.redirect);
8564 calcsize(n->ncmd.args);
8565 calcsize(n->ncmd.assign);
8568 sizenodelist(n->npipe.cmdlist);
8573 calcsize(n->nredir.redirect);
8574 calcsize(n->nredir.n);
8581 calcsize(n->nbinary.ch2);
8582 calcsize(n->nbinary.ch1);
8585 calcsize(n->nif.elsepart);
8586 calcsize(n->nif.ifpart);
8587 calcsize(n->nif.test);
8590 funcstringsize += strlen(n->nfor.var) + 1;
8591 calcsize(n->nfor.body);
8592 calcsize(n->nfor.args);
8595 calcsize(n->ncase.cases);
8596 calcsize(n->ncase.expr);
8599 calcsize(n->nclist.body);
8600 calcsize(n->nclist.pattern);
8601 calcsize(n->nclist.next);
8605 sizenodelist(n->narg.backquote);
8606 funcstringsize += strlen(n->narg.text) + 1;
8607 calcsize(n->narg.next);
8614 calcsize(n->nfile.fname);
8615 calcsize(n->nfile.next);
8619 calcsize(n->ndup.vname);
8620 calcsize(n->ndup.next);
8624 calcsize(n->nhere.doc);
8625 calcsize(n->nhere.next);
8628 calcsize(n->nnot.com);
8635 sizenodelist(struct nodelist *lp)
8638 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
8646 copynode(union node *n)
8653 funcblock = (char *) funcblock + nodesize[n->type];
8656 new->ncmd.redirect = copynode(n->ncmd.redirect);
8657 new->ncmd.args = copynode(n->ncmd.args);
8658 new->ncmd.assign = copynode(n->ncmd.assign);
8661 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
8662 new->npipe.backgnd = n->npipe.backgnd;
8667 new->nredir.redirect = copynode(n->nredir.redirect);
8668 new->nredir.n = copynode(n->nredir.n);
8675 new->nbinary.ch2 = copynode(n->nbinary.ch2);
8676 new->nbinary.ch1 = copynode(n->nbinary.ch1);
8679 new->nif.elsepart = copynode(n->nif.elsepart);
8680 new->nif.ifpart = copynode(n->nif.ifpart);
8681 new->nif.test = copynode(n->nif.test);
8684 new->nfor.var = nodesavestr(n->nfor.var);
8685 new->nfor.body = copynode(n->nfor.body);
8686 new->nfor.args = copynode(n->nfor.args);
8689 new->ncase.cases = copynode(n->ncase.cases);
8690 new->ncase.expr = copynode(n->ncase.expr);
8693 new->nclist.body = copynode(n->nclist.body);
8694 new->nclist.pattern = copynode(n->nclist.pattern);
8695 new->nclist.next = copynode(n->nclist.next);
8699 new->narg.backquote = copynodelist(n->narg.backquote);
8700 new->narg.text = nodesavestr(n->narg.text);
8701 new->narg.next = copynode(n->narg.next);
8708 new->nfile.fname = copynode(n->nfile.fname);
8709 new->nfile.fd = n->nfile.fd;
8710 new->nfile.next = copynode(n->nfile.next);
8714 new->ndup.vname = copynode(n->ndup.vname);
8715 new->ndup.dupfd = n->ndup.dupfd;
8716 new->ndup.fd = n->ndup.fd;
8717 new->ndup.next = copynode(n->ndup.next);
8721 new->nhere.doc = copynode(n->nhere.doc);
8722 new->nhere.fd = n->nhere.fd;
8723 new->nhere.next = copynode(n->nhere.next);
8726 new->nnot.com = copynode(n->nnot.com);
8729 new->type = n->type;
8734 static struct nodelist *
8735 copynodelist(struct nodelist *lp)
8737 struct nodelist *start;
8738 struct nodelist **lpp;
8743 funcblock = (char *) funcblock +
8744 SHELL_ALIGN(sizeof(struct nodelist));
8745 (*lpp)->n = copynode(lp->n);
8747 lpp = &(*lpp)->next;
8755 nodesavestr(char *s)
8757 char *rtn = funcstring;
8759 funcstring = stpcpy(funcstring, s) + 1;
8765 * Free a parse tree.
8769 freefunc(struct funcnode *f)
8771 if (f && --f->count < 0)
8776 static void options(int);
8777 static void setoption(int, int);
8781 * Process the shell command line arguments.
8785 procargs(int argc, char **argv)
8788 const char *xminusc;
8795 for (i = 0; i < NOPTS; i++)
8801 if (*xargv == NULL) {
8803 sh_error(bb_msg_requires_arg, "-c");
8806 if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
8810 for (i = 0; i < NOPTS; i++)
8811 if (optlist[i] == 2)
8816 /* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
8821 } else if (!sflag) {
8822 setinputfile(*xargv, 0);
8828 shellparam.p = xargv;
8829 #ifdef CONFIG_ASH_GETOPTS
8830 shellparam.optind = 1;
8831 shellparam.optoff = -1;
8833 /* assert(shellparam.malloc == 0 && shellparam.nparam == 0); */
8835 shellparam.nparam++;
8848 setinteractive(iflag);
8853 static void minus_o(char *name, int val)
8858 out1str("Current option settings\n");
8859 for (i = 0; i < NOPTS; i++)
8860 out1fmt("%-16s%s\n", optnames(i),
8861 optlist[i] ? "on" : "off");
8863 for (i = 0; i < NOPTS; i++)
8864 if (equal(name, optnames(i))) {
8868 sh_error("Illegal option -o %s", name);
8873 * Process shell options. The global variable argptr contains a pointer
8874 * to the argument list; we advance it past the options.
8878 options(int cmdline)
8886 while ((p = *argptr) != NULL) {
8888 if ((c = *p++) == '-') {
8890 if (p[0] == '\0' || (p[0] == '-' && p[1] == '\0')) {
8892 /* "-" means turn off -x and -v */
8895 /* "--" means reset params */
8896 else if (*argptr == NULL)
8899 break; /* "-" or "--" terminates options */
8901 } else if (c == '+') {
8907 while ((c = *p++) != '\0') {
8908 if (c == 'c' && cmdline) {
8909 minusc = p; /* command is after shell args*/
8910 } else if (c == 'o') {
8911 minus_o(*argptr, val);
8914 } else if (cmdline && (c == '-')) { // long options
8915 if (strcmp(p, "login") == 0)
8927 setoption(int flag, int val)
8931 for (i = 0; i < NOPTS; i++)
8932 if (optletters(i) == flag) {
8936 sh_error("Illegal option -%c", flag);
8943 * Set the shell parameters.
8947 setparam(char **argv)
8953 for (nparam = 0 ; argv[nparam] ; nparam++);
8954 ap = newparam = ckmalloc((nparam + 1) * sizeof *ap);
8956 *ap++ = savestr(*argv++);
8959 freeparam(&shellparam);
8960 shellparam.malloc = 1;
8961 shellparam.nparam = nparam;
8962 shellparam.p = newparam;
8963 #ifdef CONFIG_ASH_GETOPTS
8964 shellparam.optind = 1;
8965 shellparam.optoff = -1;
8971 * Free the list of positional parameters.
8975 freeparam(volatile struct shparam *param)
8979 if (param->malloc) {
8980 for (ap = param->p ; *ap ; ap++)
8989 * The shift builtin command.
8993 shiftcmd(int argc, char **argv)
9000 n = number(argv[1]);
9001 if (n > shellparam.nparam)
9002 sh_error("can't shift that many");
9004 shellparam.nparam -= n;
9005 for (ap1 = shellparam.p ; --n >= 0 ; ap1++) {
9006 if (shellparam.malloc)
9010 while ((*ap2++ = *ap1++) != NULL);
9011 #ifdef CONFIG_ASH_GETOPTS
9012 shellparam.optind = 1;
9013 shellparam.optoff = -1;
9022 * The set command builtin.
9026 setcmd(int argc, char **argv)
9029 return showvars(nullstr, 0, VUNSET);
9033 if (*argptr != NULL) {
9041 #ifdef CONFIG_ASH_GETOPTS
9043 getoptsreset(const char *value)
9045 shellparam.optind = number(value);
9046 shellparam.optoff = -1;
9050 #ifdef CONFIG_LOCALE_SUPPORT
9051 static void change_lc_all(const char *value)
9053 if (value != 0 && *value != 0)
9054 setlocale(LC_ALL, value);
9057 static void change_lc_ctype(const char *value)
9059 if (value != 0 && *value != 0)
9060 setlocale(LC_CTYPE, value);
9065 #ifdef CONFIG_ASH_RANDOM_SUPPORT
9066 /* Roughly copied from bash.. */
9067 static void change_random(const char *value)
9070 /* "get", generate */
9073 rseed = rseed * 1103515245 + 12345;
9074 sprintf(buf, "%d", (unsigned int)((rseed & 32767)));
9075 /* set without recursion */
9076 setvar(vrandom.text, buf, VNOFUNC);
9077 vrandom.flags &= ~VNOFUNC;
9080 rseed = strtoul(value, (char **)NULL, 10);
9086 #ifdef CONFIG_ASH_GETOPTS
9088 getopts(char *optstr, char *optvar, char **optfirst, int *param_optind, int *optoff)
9097 if(*param_optind < 1)
9099 optnext = optfirst + *param_optind - 1;
9101 if (*param_optind <= 1 || *optoff < 0 || strlen(optnext[-1]) < *optoff)
9104 p = optnext[-1] + *optoff;
9105 if (p == NULL || *p == '\0') {
9106 /* Current word is done, advance */
9108 if (p == NULL || *p != '-' || *++p == '\0') {
9115 if (p[0] == '-' && p[1] == '\0') /* check for "--" */
9120 for (q = optstr; *q != c; ) {
9122 if (optstr[0] == ':') {
9125 err |= setvarsafe("OPTARG", s, 0);
9127 fprintf(stderr, "Illegal option -%c\n", c);
9128 (void) unsetvar("OPTARG");
9138 if (*p == '\0' && (p = *optnext) == NULL) {
9139 if (optstr[0] == ':') {
9142 err |= setvarsafe("OPTARG", s, 0);
9145 fprintf(stderr, "No arg for -%c option\n", c);
9146 (void) unsetvar("OPTARG");
9154 err |= setvarsafe("OPTARG", p, 0);
9157 err |= setvarsafe("OPTARG", nullstr, 0);
9160 *optoff = p ? p - *(optnext - 1) : -1;
9161 *param_optind = optnext - optfirst + 1;
9162 fmtstr(s, sizeof(s), "%d", *param_optind);
9163 err |= setvarsafe("OPTIND", s, VNOFUNC);
9166 err |= setvarsafe(optvar, s, 0);
9177 * The getopts builtin. Shellparam.optnext points to the next argument
9178 * to be processed. Shellparam.optptr points to the next character to
9179 * be processed in the current argument. If shellparam.optnext is NULL,
9180 * then it's the first time getopts has been called.
9184 getoptscmd(int argc, char **argv)
9189 sh_error("Usage: getopts optstring var [arg]");
9190 else if (argc == 3) {
9191 optbase = shellparam.p;
9192 if (shellparam.optind > shellparam.nparam + 1) {
9193 shellparam.optind = 1;
9194 shellparam.optoff = -1;
9199 if (shellparam.optind > argc - 2) {
9200 shellparam.optind = 1;
9201 shellparam.optoff = -1;
9205 return getopts(argv[1], argv[2], optbase, &shellparam.optind,
9206 &shellparam.optoff);
9208 #endif /* CONFIG_ASH_GETOPTS */
9211 * XXX - should get rid of. have all builtins use getopt(3). the
9212 * library getopt must have the BSD extension static variable "optreset"
9213 * otherwise it can't be used within the shell safely.
9215 * Standard option processing (a la getopt) for builtin routines. The
9216 * only argument that is passed to nextopt is the option string; the
9217 * other arguments are unnecessary. It return the character, or '\0' on
9222 nextopt(const char *optstring)
9228 if ((p = optptr) == NULL || *p == '\0') {
9230 if (p == NULL || *p != '-' || *++p == '\0')
9233 if (p[0] == '-' && p[1] == '\0') /* check for "--" */
9237 for (q = optstring ; *q != c ; ) {
9239 sh_error("Illegal option -%c", c);
9244 if (*p == '\0' && (p = *argptr++) == NULL)
9245 sh_error("No arg for -%c option", c);
9257 outstr(const char *p, FILE *file)
9282 outcslow(int c, FILE *dest)
9292 out1fmt(const char *fmt, ...)
9299 r = vprintf(fmt, ap);
9307 fmtstr(char *outbuf, size_t length, const char *fmt, ...)
9314 ret = vsnprintf(outbuf, length, fmt, ap);
9326 * Shell command parser.
9329 #define EOFMARKLEN 79
9333 struct heredoc *next; /* next here document in list */
9334 union node *here; /* redirection node */
9335 char *eofmark; /* string indicating end of input */
9336 int striptabs; /* if set, strip leading tabs */
9341 static struct heredoc *heredoclist; /* list of here documents to read */
9344 static union node *list(int);
9345 static union node *andor(void);
9346 static union node *pipeline(void);
9347 static union node *command(void);
9348 static union node *simplecmd(void);
9349 static union node *makename(void);
9350 static void parsefname(void);
9351 static void parseheredoc(void);
9352 static char peektoken(void);
9353 static int readtoken(void);
9354 static int xxreadtoken(void);
9355 static int readtoken1(int firstc, int syntax, char *eofmark, int striptabs);
9356 static int noexpand(char *);
9357 static void synexpect(int) ATTRIBUTE_NORETURN;
9358 static void synerror(const char *) ATTRIBUTE_NORETURN;
9359 static void setprompt(int);
9365 * Read and parse a command. Returns NEOF on end of file. (NULL is a
9366 * valid parse tree indicating a blank line.)
9370 parsecmd(int interact)
9375 doprompt = interact;
9377 setprompt(doprompt);
9392 union node *n1, *n2, *n3;
9395 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9396 if (nlflag == 2 && peektoken())
9402 if (tok == TBACKGND) {
9403 if (n2->type == NPIPE) {
9404 n2->npipe.backgnd = 1;
9406 if (n2->type != NREDIR) {
9407 n3 = stalloc(sizeof(struct nredir));
9409 n3->nredir.redirect = NULL;
9412 n2->type = NBACKGND;
9419 n3 = (union node *)stalloc(sizeof (struct nbinary));
9421 n3->nbinary.ch1 = n1;
9422 n3->nbinary.ch2 = n2;
9438 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9446 pungetc(); /* push back EOF on input */
9462 union node *n1, *n2, *n3;
9467 if ((t = readtoken()) == TAND) {
9469 } else if (t == TOR) {
9475 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9477 n3 = (union node *)stalloc(sizeof (struct nbinary));
9479 n3->nbinary.ch1 = n1;
9480 n3->nbinary.ch2 = n2;
9490 union node *n1, *n2, *pipenode;
9491 struct nodelist *lp, *prev;
9495 TRACE(("pipeline: entered\n"));
9496 if (readtoken() == TNOT) {
9498 checkkwd = CHKKWD | CHKALIAS;
9502 if (readtoken() == TPIPE) {
9503 pipenode = (union node *)stalloc(sizeof (struct npipe));
9504 pipenode->type = NPIPE;
9505 pipenode->npipe.backgnd = 0;
9506 lp = (struct nodelist *)stalloc(sizeof (struct nodelist));
9507 pipenode->npipe.cmdlist = lp;
9511 lp = (struct nodelist *)stalloc(sizeof (struct nodelist));
9512 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9515 } while (readtoken() == TPIPE);
9521 n2 = (union node *)stalloc(sizeof (struct nnot));
9534 union node *n1, *n2;
9535 union node *ap, **app;
9536 union node *cp, **cpp;
9537 union node *redir, **rpp;
9544 switch (readtoken()) {
9549 n1 = (union node *)stalloc(sizeof (struct nif));
9551 n1->nif.test = list(0);
9552 if (readtoken() != TTHEN)
9554 n1->nif.ifpart = list(0);
9556 while (readtoken() == TELIF) {
9557 n2->nif.elsepart = (union node *)stalloc(sizeof (struct nif));
9558 n2 = n2->nif.elsepart;
9560 n2->nif.test = list(0);
9561 if (readtoken() != TTHEN)
9563 n2->nif.ifpart = list(0);
9565 if (lasttoken == TELSE)
9566 n2->nif.elsepart = list(0);
9568 n2->nif.elsepart = NULL;
9576 n1 = (union node *)stalloc(sizeof (struct nbinary));
9577 n1->type = (lasttoken == TWHILE)? NWHILE : NUNTIL;
9578 n1->nbinary.ch1 = list(0);
9579 if ((got=readtoken()) != TDO) {
9580 TRACE(("expecting DO got %s %s\n", tokname(got), got == TWORD ? wordtext : ""));
9583 n1->nbinary.ch2 = list(0);
9588 if (readtoken() != TWORD || quoteflag || ! goodname(wordtext))
9589 synerror("Bad for loop variable");
9590 n1 = (union node *)stalloc(sizeof (struct nfor));
9592 n1->nfor.var = wordtext;
9593 checkkwd = CHKKWD | CHKALIAS;
9594 if (readtoken() == TIN) {
9596 while (readtoken() == TWORD) {
9597 n2 = (union node *)stalloc(sizeof (struct narg));
9599 n2->narg.text = wordtext;
9600 n2->narg.backquote = backquotelist;
9602 app = &n2->narg.next;
9606 if (lasttoken != TNL && lasttoken != TSEMI)
9609 n2 = (union node *)stalloc(sizeof (struct narg));
9611 n2->narg.text = (char *)dolatstr;
9612 n2->narg.backquote = NULL;
9613 n2->narg.next = NULL;
9616 * Newline or semicolon here is optional (but note
9617 * that the original Bourne shell only allowed NL).
9619 if (lasttoken != TNL && lasttoken != TSEMI)
9622 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9623 if (readtoken() != TDO)
9625 n1->nfor.body = list(0);
9629 n1 = (union node *)stalloc(sizeof (struct ncase));
9631 if (readtoken() != TWORD)
9633 n1->ncase.expr = n2 = (union node *)stalloc(sizeof (struct narg));
9635 n2->narg.text = wordtext;
9636 n2->narg.backquote = backquotelist;
9637 n2->narg.next = NULL;
9639 checkkwd = CHKKWD | CHKALIAS;
9640 } while (readtoken() == TNL);
9641 if (lasttoken != TIN)
9643 cpp = &n1->ncase.cases;
9645 checkkwd = CHKNL | CHKKWD;
9648 if (lasttoken == TLP)
9650 *cpp = cp = (union node *)stalloc(sizeof (struct nclist));
9652 app = &cp->nclist.pattern;
9654 *app = ap = (union node *)stalloc(sizeof (struct narg));
9656 ap->narg.text = wordtext;
9657 ap->narg.backquote = backquotelist;
9658 if (readtoken() != TPIPE)
9660 app = &ap->narg.next;
9663 ap->narg.next = NULL;
9664 if (lasttoken != TRP)
9666 cp->nclist.body = list(2);
9668 cpp = &cp->nclist.next;
9670 checkkwd = CHKNL | CHKKWD;
9671 if ((t = readtoken()) != TESAC) {
9673 synexpect(TENDCASE);
9681 n1 = (union node *)stalloc(sizeof (struct nredir));
9682 n1->type = NSUBSHELL;
9683 n1->nredir.n = list(0);
9684 n1->nredir.redirect = NULL;
9697 if (readtoken() != t)
9701 /* Now check for redirection which may follow command */
9702 checkkwd = CHKKWD | CHKALIAS;
9704 while (readtoken() == TREDIR) {
9705 *rpp = n2 = redirnode;
9706 rpp = &n2->nfile.next;
9712 if (n1->type != NSUBSHELL) {
9713 n2 = (union node *)stalloc(sizeof (struct nredir));
9718 n1->nredir.redirect = redir;
9727 union node *args, **app;
9728 union node *n = NULL;
9729 union node *vars, **vpp;
9730 union node **rpp, *redir;
9740 savecheckkwd = CHKALIAS;
9742 checkkwd = savecheckkwd;
9743 switch (readtoken()) {
9745 n = (union node *)stalloc(sizeof (struct narg));
9747 n->narg.text = wordtext;
9748 n->narg.backquote = backquotelist;
9749 if (savecheckkwd && isassignment(wordtext)) {
9751 vpp = &n->narg.next;
9754 app = &n->narg.next;
9759 *rpp = n = redirnode;
9760 rpp = &n->nfile.next;
9761 parsefname(); /* read name of redirection file */
9765 args && app == &args->narg.next &&
9768 struct builtincmd *bcmd;
9771 /* We have a function */
9772 if (readtoken() != TRP)
9774 name = n->narg.text;
9776 !goodname(name) || (
9777 (bcmd = find_builtin(name)) &&
9778 IS_BUILTIN_SPECIAL(bcmd)
9781 synerror("Bad function name");
9783 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9784 n->narg.next = command();
9797 n = (union node *)stalloc(sizeof (struct ncmd));
9799 n->ncmd.args = args;
9800 n->ncmd.assign = vars;
9801 n->ncmd.redirect = redir;
9810 n = (union node *)stalloc(sizeof (struct narg));
9812 n->narg.next = NULL;
9813 n->narg.text = wordtext;
9814 n->narg.backquote = backquotelist;
9818 void fixredir(union node *n, const char *text, int err)
9820 TRACE(("Fix redir %s %d\n", text, err));
9822 n->ndup.vname = NULL;
9824 if (is_digit(text[0]) && text[1] == '\0')
9825 n->ndup.dupfd = digit_val(text[0]);
9826 else if (text[0] == '-' && text[1] == '\0')
9831 synerror("Bad fd number");
9833 n->ndup.vname = makename();
9841 union node *n = redirnode;
9843 if (readtoken() != TWORD)
9845 if (n->type == NHERE) {
9846 struct heredoc *here = heredoc;
9852 TRACE(("Here document %d\n", n->type));
9853 if (! noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)
9854 synerror("Illegal eof marker for << redirection");
9855 rmescapes(wordtext);
9856 here->eofmark = wordtext;
9858 if (heredoclist == NULL)
9861 for (p = heredoclist ; p->next ; p = p->next);
9864 } else if (n->type == NTOFD || n->type == NFROMFD) {
9865 fixredir(n, wordtext, 0);
9867 n->nfile.fname = makename();
9873 * Input any here documents.
9879 struct heredoc *here;
9889 readtoken1(pgetc(), here->here->type == NHERE? SQSYNTAX : DQSYNTAX,
9890 here->eofmark, here->striptabs);
9891 n = (union node *)stalloc(sizeof (struct narg));
9892 n->narg.type = NARG;
9893 n->narg.next = NULL;
9894 n->narg.text = wordtext;
9895 n->narg.backquote = backquotelist;
9896 here->here->nhere.doc = n;
9901 static char peektoken(void)
9907 return tokname_array[t][0];
9915 int alreadyseen = tokpushback;
9918 #ifdef CONFIG_ASH_ALIAS
9927 if (checkkwd & CHKNL) {
9934 if (t != TWORD || quoteflag) {
9939 * check for keywords
9941 if (checkkwd & CHKKWD) {
9942 const char *const *pp;
9944 if ((pp = findkwd(wordtext))) {
9945 lasttoken = t = pp - tokname_array;
9946 TRACE(("keyword %s recognized\n", tokname(t)));
9951 if (checkkwd & CHKALIAS) {
9952 #ifdef CONFIG_ASH_ALIAS
9954 if ((ap = lookupalias(wordtext, 1)) != NULL) {
9956 pushstring(ap->val, ap);
9966 TRACE(("token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
9968 TRACE(("reread token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
9975 * Read the next input token.
9976 * If the token is a word, we set backquotelist to the list of cmds in
9977 * backquotes. We set quoteflag to true if any part of the word was
9979 * If the token is TREDIR, then we set redirnode to a structure containing
9981 * In all cases, the variable startlinno is set to the number of the line
9982 * on which the token starts.
9984 * [Change comment: here documents and internal procedures]
9985 * [Readtoken shouldn't have any arguments. Perhaps we should make the
9986 * word parsing code into a separate routine. In this case, readtoken
9987 * doesn't need to have any internal procedures, but parseword does.
9988 * We could also make parseoperator in essence the main routine, and
9989 * have parseword (readtoken1?) handle both words and redirection.]
9992 #define NEW_xxreadtoken
9993 #ifdef NEW_xxreadtoken
9995 /* singles must be first! */
9996 static const char xxreadtoken_chars[7] = { '\n', '(', ')', '&', '|', ';', 0 };
9998 static const char xxreadtoken_tokens[] = {
9999 TNL, TLP, TRP, /* only single occurrence allowed */
10000 TBACKGND, TPIPE, TSEMI, /* if single occurrence */
10001 TEOF, /* corresponds to trailing nul */
10002 TAND, TOR, TENDCASE, /* if double occurrence */
10005 #define xxreadtoken_doubles \
10006 (sizeof(xxreadtoken_tokens) - sizeof(xxreadtoken_chars))
10007 #define xxreadtoken_singles \
10008 (sizeof(xxreadtoken_chars) - xxreadtoken_doubles - 1)
10010 static int xxreadtoken(void)
10021 startlinno = plinno;
10022 for (;;) { /* until token or start of word found */
10025 if ((c != ' ') && (c != '\t')
10026 #ifdef CONFIG_ASH_ALIAS
10031 while ((c = pgetc()) != '\n' && c != PEOF);
10033 } else if (c == '\\') {
10034 if (pgetc() != '\n') {
10038 startlinno = ++plinno;
10043 = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
10048 needprompt = doprompt;
10051 p = strchr(xxreadtoken_chars, c);
10054 return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
10057 if (p - xxreadtoken_chars >= xxreadtoken_singles) {
10058 if (pgetc() == *p) { /* double occurrence? */
10059 p += xxreadtoken_doubles + 1;
10066 return lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
10074 #define RETURN(token) return lasttoken = token
10088 startlinno = plinno;
10089 for (;;) { /* until token or start of word found */
10092 case ' ': case '\t':
10093 #ifdef CONFIG_ASH_ALIAS
10098 while ((c = pgetc()) != '\n' && c != PEOF);
10102 if (pgetc() == '\n') {
10103 startlinno = ++plinno;
10112 needprompt = doprompt;
10117 if (pgetc() == '&')
10122 if (pgetc() == '|')
10127 if (pgetc() == ';')
10140 return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
10143 #endif /* NEW_xxreadtoken */
10147 * If eofmark is NULL, read a word or a redirection symbol. If eofmark
10148 * is not NULL, read a here document. In the latter case, eofmark is the
10149 * word which marks the end of the document and striptabs is true if
10150 * leading tabs should be stripped from the document. The argument firstc
10151 * is the first character of the input token or document.
10153 * Because C does not have internal subroutines, I have simulated them
10154 * using goto's to implement the subroutine linkage. The following macros
10155 * will run code that appears at the end of readtoken1.
10158 #define CHECKEND() {goto checkend; checkend_return:;}
10159 #define PARSEREDIR() {goto parseredir; parseredir_return:;}
10160 #define PARSESUB() {goto parsesub; parsesub_return:;}
10161 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
10162 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
10163 #define PARSEARITH() {goto parsearith; parsearith_return:;}
10166 readtoken1(int firstc, int syntax, char *eofmark, int striptabs)
10171 char line[EOFMARKLEN + 1];
10172 struct nodelist *bqlist = 0;
10175 int varnest = 0; /* levels of variables expansion */
10176 int arinest = 0; /* levels of arithmetic expansion */
10177 int parenlevel = 0; /* levels of parens in arithmetic */
10178 int dqvarnest = 0; /* levels of variables expansion within double quotes */
10180 int prevsyntax = 0; /* syntax before arithmetic */
10182 /* Avoid longjmp clobbering */
10188 (void) &parenlevel;
10191 (void) &prevsyntax;
10195 startlinno = plinno;
10197 if (syntax == DQSYNTAX)
10206 STARTSTACKSTR(out);
10207 loop: { /* for each line, until end of word */
10208 CHECKEND(); /* set c to PEOF if at end of here document */
10209 for (;;) { /* until end of line or end of word */
10210 CHECKSTRSPACE(4, out); /* permit 4 calls to USTPUTC */
10211 switch(SIT(c, syntax)) {
10212 case CNL: /* '\n' */
10213 if (syntax == BASESYNTAX)
10214 goto endword; /* exit outer loop */
10220 goto loop; /* continue outer loop */
10225 if (eofmark == NULL || dblquote)
10226 USTPUTC(CTLESC, out);
10229 case CBACK: /* backslash */
10232 USTPUTC(CTLESC, out);
10233 USTPUTC('\\', out);
10235 } else if (c == '\n') {
10240 c != '\\' && c != '`' &&
10245 USTPUTC(CTLESC, out);
10246 USTPUTC('\\', out);
10248 if (SIT(c, SQSYNTAX) == CCTL)
10249 USTPUTC(CTLESC, out);
10257 if (eofmark == NULL) {
10258 USTPUTC(CTLQUOTEMARK, out);
10266 if (eofmark != NULL && arinest == 0 &&
10270 if (dqvarnest == 0) {
10271 syntax = BASESYNTAX;
10278 case CVAR: /* '$' */
10279 PARSESUB(); /* parse substitution */
10281 case CENDVAR: /* '}' */
10284 if (dqvarnest > 0) {
10287 USTPUTC(CTLENDVAR, out);
10292 #ifdef CONFIG_ASH_MATH_SUPPORT
10293 case CLP: /* '(' in arithmetic */
10297 case CRP: /* ')' in arithmetic */
10298 if (parenlevel > 0) {
10302 if (pgetc() == ')') {
10303 if (--arinest == 0) {
10304 USTPUTC(CTLENDARI, out);
10305 syntax = prevsyntax;
10306 if (syntax == DQSYNTAX)
10314 * unbalanced parens
10315 * (don't 2nd guess - no error)
10323 case CBQUOTE: /* '`' */
10327 goto endword; /* exit outer loop */
10332 goto endword; /* exit outer loop */
10333 #ifdef CONFIG_ASH_ALIAS
10343 #ifdef CONFIG_ASH_MATH_SUPPORT
10344 if (syntax == ARISYNTAX)
10345 synerror("Missing '))'");
10347 if (syntax != BASESYNTAX && ! parsebackquote && eofmark == NULL)
10348 synerror("Unterminated quoted string");
10349 if (varnest != 0) {
10350 startlinno = plinno;
10352 synerror("Missing '}'");
10354 USTPUTC('\0', out);
10355 len = out - (char *)stackblock();
10356 out = stackblock();
10357 if (eofmark == NULL) {
10358 if ((c == '>' || c == '<')
10361 && (*out == '\0' || is_digit(*out))) {
10363 return lasttoken = TREDIR;
10368 quoteflag = quotef;
10369 backquotelist = bqlist;
10370 grabstackblock(len);
10372 return lasttoken = TWORD;
10373 /* end of readtoken routine */
10378 * Check to see whether we are at the end of the here document. When this
10379 * is called, c is set to the first character of the next input line. If
10380 * we are at the end of the here document, this routine sets the c to PEOF.
10385 #ifdef CONFIG_ASH_ALIAS
10391 while (c == '\t') {
10395 if (c == *eofmark) {
10396 if (pfgets(line, sizeof line) != NULL) {
10400 for (q = eofmark + 1 ; *q && *p == *q ; p++, q++);
10401 if (*p == '\n' && *q == '\0') {
10404 needprompt = doprompt;
10406 pushstring(line, NULL);
10411 goto checkend_return;
10416 * Parse a redirection operator. The variable "out" points to a string
10417 * specifying the fd to be redirected. The variable "c" contains the
10418 * first character of the redirection operator.
10425 np = (union node *)stalloc(sizeof (struct nfile));
10430 np->type = NAPPEND;
10432 np->type = NCLOBBER;
10439 } else { /* c == '<' */
10441 switch (c = pgetc()) {
10443 if (sizeof (struct nfile) != sizeof (struct nhere)) {
10444 np = (union node *)stalloc(sizeof (struct nhere));
10448 heredoc = (struct heredoc *)stalloc(sizeof (struct heredoc));
10449 heredoc->here = np;
10450 if ((c = pgetc()) == '-') {
10451 heredoc->striptabs = 1;
10453 heredoc->striptabs = 0;
10459 np->type = NFROMFD;
10463 np->type = NFROMTO;
10473 np->nfile.fd = digit_val(fd);
10475 goto parseredir_return;
10480 * Parse a substitution. At this point, we have read the dollar sign
10481 * and nothing else.
10489 static const char types[] = "}-+?=";
10493 c <= PEOA_OR_PEOF ||
10494 (c != '(' && c != '{' && !is_name(c) && !is_special(c))
10498 } else if (c == '(') { /* $(command) or $((arith)) */
10499 if (pgetc() == '(') {
10500 #ifdef CONFIG_ASH_MATH_SUPPORT
10503 synerror("We unsupport $((arith))");
10510 USTPUTC(CTLVAR, out);
10511 typeloc = out - (char *)stackblock();
10512 USTPUTC(VSNORMAL, out);
10513 subtype = VSNORMAL;
10517 if ((c = pgetc()) == '}')
10520 subtype = VSLENGTH;
10525 if (c > PEOA_OR_PEOF && is_name(c)) {
10529 } while (c > PEOA_OR_PEOF && is_in_name(c));
10530 } else if (is_digit(c)) {
10534 } while (is_digit(c));
10536 else if (is_special(c)) {
10541 badsub: synerror("Bad substitution");
10545 if (subtype == 0) {
10552 p = strchr(types, c);
10555 subtype = p - types + VSNORMAL;
10561 subtype = c == '#' ? VSTRIMLEFT :
10574 if (dblquote || arinest)
10576 *((char *)stackblock() + typeloc) = subtype | flags;
10577 if (subtype != VSNORMAL) {
10579 if (dblquote || arinest) {
10584 goto parsesub_return;
10589 * Called to parse command substitutions. Newstyle is set if the command
10590 * is enclosed inside $(...); nlpp is a pointer to the head of the linked
10591 * list of commands (passed by reference), and savelen is the number of
10592 * characters on the top of the stack which must be preserved.
10596 struct nodelist **nlpp;
10599 char *volatile str;
10600 struct jmploc jmploc;
10601 struct jmploc *volatile savehandler;
10603 int saveprompt = 0;
10605 (void) &saveprompt;
10608 savepbq = parsebackquote;
10609 if (setjmp(jmploc.loc)) {
10612 parsebackquote = 0;
10613 handler = savehandler;
10614 longjmp(handler->loc, 1);
10618 savelen = out - (char *)stackblock();
10620 str = ckmalloc(savelen);
10621 memcpy(str, stackblock(), savelen);
10623 savehandler = handler;
10627 /* We must read until the closing backquote, giving special
10628 treatment to some slashes, and then push the string and
10629 reread it as input, interpreting it normally. */
10636 STARTSTACKSTR(pout);
10641 switch (pc = pgetc()) {
10646 if ((pc = pgetc()) == '\n') {
10651 * If eating a newline, avoid putting
10652 * the newline into the new character
10653 * stream (via the STPUTC after the
10658 if (pc != '\\' && pc != '`' && pc != '$'
10659 && (!dblquote || pc != '"'))
10660 STPUTC('\\', pout);
10661 if (pc > PEOA_OR_PEOF) {
10667 #ifdef CONFIG_ASH_ALIAS
10670 startlinno = plinno;
10671 synerror("EOF in backquote substitution");
10675 needprompt = doprompt;
10684 STPUTC('\0', pout);
10685 psavelen = pout - (char *)stackblock();
10686 if (psavelen > 0) {
10687 pstr = grabstackstr(pout);
10688 setinputstring(pstr);
10693 nlpp = &(*nlpp)->next;
10694 *nlpp = (struct nodelist *)stalloc(sizeof (struct nodelist));
10695 (*nlpp)->next = NULL;
10696 parsebackquote = oldstyle;
10699 saveprompt = doprompt;
10706 doprompt = saveprompt;
10708 if (readtoken() != TRP)
10715 * Start reading from old file again, ignoring any pushed back
10716 * tokens left from the backquote parsing
10721 while (stackblocksize() <= savelen)
10723 STARTSTACKSTR(out);
10725 memcpy(out, str, savelen);
10726 STADJUST(savelen, out);
10732 parsebackquote = savepbq;
10733 handler = savehandler;
10734 if (arinest || dblquote)
10735 USTPUTC(CTLBACKQ | CTLQUOTE, out);
10737 USTPUTC(CTLBACKQ, out);
10739 goto parsebackq_oldreturn;
10741 goto parsebackq_newreturn;
10744 #ifdef CONFIG_ASH_MATH_SUPPORT
10746 * Parse an arithmetic expansion (indicate start of one and set state)
10750 if (++arinest == 1) {
10751 prevsyntax = syntax;
10752 syntax = ARISYNTAX;
10753 USTPUTC(CTLARI, out);
10760 * we collapse embedded arithmetic expansion to
10761 * parenthesis, which should be equivalent
10765 goto parsearith_return;
10769 } /* end of readtoken */
10774 * Returns true if the text contains nothing to expand (no dollar signs
10779 noexpand(char *text)
10785 while ((c = *p++) != '\0') {
10786 if (c == CTLQUOTEMARK)
10790 else if (SIT(c, BASESYNTAX) == CCTL)
10798 * Return of a legal variable name (a letter or underscore followed by zero or
10799 * more letters, underscores, and digits).
10803 endofname(const char *name)
10811 if (! is_in_name(*p))
10819 * Called when an unexpected token is read during the parse. The argument
10820 * is the token that is expected, or -1 if more than one type of token can
10821 * occur at this point.
10824 static void synexpect(int token)
10829 l = sprintf(msg, "%s unexpected", tokname(lasttoken));
10831 sprintf(msg + l, " (expecting %s)", tokname(token));
10837 synerror(const char *msg)
10839 sh_error("Syntax error: %s", msg);
10845 * called by editline -- any expansions to the prompt
10846 * should be added here.
10849 #ifdef CONFIG_ASH_EXPAND_PRMT
10850 static const char *
10851 expandstr(const char *ps)
10855 /* XXX Fix (char *) cast. */
10856 setinputstring((char *)ps);
10857 readtoken1(pgetc(), DQSYNTAX, nullstr, 0);
10860 n.narg.type = NARG;
10861 n.narg.next = NULL;
10862 n.narg.text = wordtext;
10863 n.narg.backquote = backquotelist;
10865 expandarg(&n, NULL, 0);
10866 return stackblock();
10870 static void setprompt(int whichprompt)
10872 const char *prompt;
10873 #ifdef CONFIG_ASH_EXPAND_PRMT
10874 struct stackmark smark;
10879 switch (whichprompt) {
10889 #ifdef CONFIG_ASH_EXPAND_PRMT
10890 setstackmark(&smark);
10891 stalloc(stackblocksize());
10893 putprompt(expandstr(prompt));
10894 #ifdef CONFIG_ASH_EXPAND_PRMT
10895 popstackmark(&smark);
10900 static const char *const *findkwd(const char *s)
10902 return bsearch(s, tokname_array + KWDOFFSET,
10903 (sizeof(tokname_array) / sizeof(const char *)) - KWDOFFSET,
10904 sizeof(const char *), pstrcmp);
10910 * Code for dealing with input/output redirection.
10913 #define EMPTY -2 /* marks an unused slot in redirtab */
10915 # define PIPESIZE 4096 /* amount of buffering in a pipe */
10917 # define PIPESIZE PIPE_BUF
10921 * Open a file in noclobber mode.
10922 * The code was copied from bash.
10924 static int noclobberopen(const char *fname)
10927 struct stat finfo, finfo2;
10930 * If the file exists and is a regular file, return an error
10933 r = stat(fname, &finfo);
10934 if (r == 0 && S_ISREG(finfo.st_mode)) {
10940 * If the file was not present (r != 0), make sure we open it
10941 * exclusively so that if it is created before we open it, our open
10942 * will fail. Make sure that we do not truncate an existing file.
10943 * Note that we don't turn on O_EXCL unless the stat failed -- if the
10944 * file was not a regular file, we leave O_EXCL off.
10947 return open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
10948 fd = open(fname, O_WRONLY|O_CREAT, 0666);
10950 /* If the open failed, return the file descriptor right away. */
10955 * OK, the open succeeded, but the file may have been changed from a
10956 * non-regular file to a regular file between the stat and the open.
10957 * We are assuming that the O_EXCL open handles the case where FILENAME
10958 * did not exist and is symlinked to an existing file between the stat
10963 * If we can open it and fstat the file descriptor, and neither check
10964 * revealed that it was a regular file, and the file has not been
10965 * replaced, return the file descriptor.
10967 if (fstat(fd, &finfo2) == 0 && !S_ISREG(finfo2.st_mode) &&
10968 finfo.st_dev == finfo2.st_dev && finfo.st_ino == finfo2.st_ino)
10971 /* The file has been replaced. badness. */
10978 * Handle here documents. Normally we fork off a process to write the
10979 * data to a pipe. If the document is short, we can stuff the data in
10980 * the pipe without forking.
10983 static int openhere(union node *redir)
10989 sh_error("Pipe call failed");
10990 if (redir->type == NHERE) {
10991 len = strlen(redir->nhere.doc->narg.text);
10992 if (len <= PIPESIZE) {
10993 full_write(pip[1], redir->nhere.doc->narg.text, len);
10997 if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
10999 signal(SIGINT, SIG_IGN);
11000 signal(SIGQUIT, SIG_IGN);
11001 signal(SIGHUP, SIG_IGN);
11003 signal(SIGTSTP, SIG_IGN);
11005 signal(SIGPIPE, SIG_DFL);
11006 if (redir->type == NHERE)
11007 full_write(pip[1], redir->nhere.doc->narg.text, len);
11009 expandhere(redir->nhere.doc, pip[1]);
11018 openredirect(union node *redir)
11023 switch (redir->nfile.type) {
11025 fname = redir->nfile.expfname;
11026 if ((f = open(fname, O_RDONLY)) < 0)
11030 fname = redir->nfile.expfname;
11031 if ((f = open(fname, O_RDWR|O_CREAT|O_TRUNC, 0666)) < 0)
11035 /* Take care of noclobber mode. */
11037 fname = redir->nfile.expfname;
11038 if ((f = noclobberopen(fname)) < 0)
11044 fname = redir->nfile.expfname;
11045 if ((f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0)
11049 fname = redir->nfile.expfname;
11050 if ((f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666)) < 0)
11057 /* Fall through to eliminate warning. */
11064 f = openhere(redir);
11070 sh_error("cannot create %s: %s", fname, errmsg(errno, E_CREAT));
11072 sh_error("cannot open %s: %s", fname, errmsg(errno, E_OPEN));
11075 static void dupredirect(union node *redir, int f)
11077 int fd = redir->nfile.fd;
11079 if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
11080 if (redir->ndup.dupfd >= 0) { /* if not ">&-" */
11081 copyfd(redir->ndup.dupfd, fd);
11094 * Process a list of redirection commands. If the REDIR_PUSH flag is set,
11095 * old file descriptors are stashed away so that the redirection can be
11096 * undone by calling popredir. If the REDIR_BACKQ flag is set, then the
11097 * standard output, and the standard error if it becomes a duplicate of
11098 * stdout, is saved in memory.
11102 redirect(union node *redir, int flags)
11105 struct redirtab *sv;
11116 if (flags & REDIR_PUSH) {
11117 struct redirtab *q;
11118 q = ckmalloc(sizeof (struct redirtab));
11119 q->next = redirlist;
11121 q->nullredirs = nullredirs - 1;
11122 for (i = 0 ; i < 10 ; i++)
11123 q->renamed[i] = EMPTY;
11130 if ((n->nfile.type == NTOFD || n->nfile.type == NFROMFD) &&
11131 n->ndup.dupfd == fd)
11132 continue; /* redirect from/to same file descriptor */
11134 newfd = openredirect(n);
11137 if (sv && *(p = &sv->renamed[fd]) == EMPTY) {
11138 i = fcntl(fd, F_DUPFD, 10);
11145 sh_error("%d: %m", fd);
11155 dupredirect(n, newfd);
11156 } while ((n = n->nfile.next));
11158 if (flags & REDIR_SAVEFD2 && sv && sv->renamed[2] >= 0)
11159 preverrout_fd = sv->renamed[2];
11164 * Undo the effects of the last redirection.
11170 struct redirtab *rp;
11173 if (--nullredirs >= 0)
11177 for (i = 0 ; i < 10 ; i++) {
11178 if (rp->renamed[i] != EMPTY) {
11181 copyfd(rp->renamed[i], i);
11183 close(rp->renamed[i]);
11186 redirlist = rp->next;
11187 nullredirs = rp->nullredirs;
11193 * Undo all redirections. Called on error or interrupt.
11197 * Discard all saved file descriptors.
11201 clearredir(int drop)
11213 * Copy a file descriptor to be >= to. Returns -1
11214 * if the source file descriptor is closed, EMPTY if there are no unused
11215 * file descriptors left.
11219 copyfd(int from, int to)
11223 newfd = fcntl(from, F_DUPFD, to);
11225 if (errno == EMFILE)
11228 sh_error("%d: %m", from);
11235 redirectsafe(union node *redir, int flags)
11238 volatile int saveint;
11239 struct jmploc *volatile savehandler = handler;
11240 struct jmploc jmploc;
11243 if (!(err = setjmp(jmploc.loc) * 2)) {
11245 redirect(redir, flags);
11247 handler = savehandler;
11248 if (err && exception != EXERROR)
11249 longjmp(handler->loc, 1);
11250 RESTOREINT(saveint);
11257 static void shtree(union node *, int, char *, FILE*);
11258 static void shcmd(union node *, FILE *);
11259 static void sharg(union node *, FILE *);
11260 static void indent(int, char *, FILE *);
11261 static void trstring(char *);
11265 showtree(union node *n)
11267 trputs("showtree called\n");
11268 shtree(n, 1, NULL, stdout);
11273 shtree(union node *n, int ind, char *pfx, FILE *fp)
11275 struct nodelist *lp;
11281 indent(ind, pfx, fp);
11292 shtree(n->nbinary.ch1, ind, NULL, fp);
11295 shtree(n->nbinary.ch2, ind, NULL, fp);
11303 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
11308 if (n->npipe.backgnd)
11314 fprintf(fp, "<node type %d>", n->type);
11323 shcmd(union node *cmd, FILE *fp)
11331 for (np = cmd->ncmd.args ; np ; np = np->narg.next) {
11337 for (np = cmd->ncmd.redirect ; np ; np = np->nfile.next) {
11340 switch (np->nfile.type) {
11341 case NTO: s = ">"; dftfd = 1; break;
11342 case NCLOBBER: s = ">|"; dftfd = 1; break;
11343 case NAPPEND: s = ">>"; dftfd = 1; break;
11344 case NTOFD: s = ">&"; dftfd = 1; break;
11345 case NFROM: s = "<"; dftfd = 0; break;
11346 case NFROMFD: s = "<&"; dftfd = 0; break;
11347 case NFROMTO: s = "<>"; dftfd = 0; break;
11348 default: s = "*error*"; dftfd = 0; break;
11350 if (np->nfile.fd != dftfd)
11351 fprintf(fp, "%d", np->nfile.fd);
11353 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
11354 fprintf(fp, "%d", np->ndup.dupfd);
11356 sharg(np->nfile.fname, fp);
11365 sharg(union node *arg, FILE *fp)
11368 struct nodelist *bqlist;
11371 if (arg->type != NARG) {
11372 out1fmt("<node type %d>\n", arg->type);
11375 bqlist = arg->narg.backquote;
11376 for (p = arg->narg.text ; *p ; p++) {
11385 if (subtype == VSLENGTH)
11391 if (subtype & VSNUL)
11394 switch (subtype & VSTYPE) {
11413 case VSTRIMLEFTMAX:
11420 case VSTRIMRIGHTMAX:
11427 out1fmt("<subtype %d>", subtype);
11434 case CTLBACKQ|CTLQUOTE:
11437 shtree(bqlist->n, -1, NULL, fp);
11449 indent(int amount, char *pfx, FILE *fp)
11453 for (i = 0 ; i < amount ; i++) {
11454 if (pfx && i == amount - 1)
11475 putc(c, tracefile);
11479 trace(const char *fmt, ...)
11486 (void) vfprintf(tracefile, fmt, va);
11491 tracev(const char *fmt, va_list va)
11495 (void) vfprintf(tracefile, fmt, va);
11500 trputs(const char *s)
11504 fputs(s, tracefile);
11516 putc('"', tracefile);
11517 for (p = s ; *p ; p++) {
11519 case '\n': c = 'n'; goto backslash;
11520 case '\t': c = 't'; goto backslash;
11521 case '\r': c = 'r'; goto backslash;
11522 case '"': c = '"'; goto backslash;
11523 case '\\': c = '\\'; goto backslash;
11524 case CTLESC: c = 'e'; goto backslash;
11525 case CTLVAR: c = 'v'; goto backslash;
11526 case CTLVAR+CTLQUOTE: c = 'V'; goto backslash;
11527 case CTLBACKQ: c = 'q'; goto backslash;
11528 case CTLBACKQ+CTLQUOTE: c = 'Q'; goto backslash;
11529 backslash: putc('\\', tracefile);
11530 putc(c, tracefile);
11533 if (*p >= ' ' && *p <= '~')
11534 putc(*p, tracefile);
11536 putc('\\', tracefile);
11537 putc(*p >> 6 & 03, tracefile);
11538 putc(*p >> 3 & 07, tracefile);
11539 putc(*p & 07, tracefile);
11544 putc('"', tracefile);
11556 putc(' ', tracefile);
11558 putc('\n', tracefile);
11574 /* leave open because libedit might be using it */
11577 scopy("./trace", s);
11579 if (!freopen(s, "a", tracefile)) {
11580 fprintf(stderr, "Can't re-open %s\n", s);
11585 if ((tracefile = fopen(s, "a")) == NULL) {
11586 fprintf(stderr, "Can't open %s\n", s);
11592 if ((flags = fcntl(fileno(tracefile), F_GETFL, 0)) >= 0)
11593 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
11595 setlinebuf(tracefile);
11596 fputs("\nTracing started.\n", tracefile);
11604 * Sigmode records the current value of the signal handlers for the various
11605 * modes. A value of zero means that the current handler is not known.
11606 * S_HARD_IGN indicates that the signal was ignored on entry to the shell,
11609 #define S_DFL 1 /* default signal handling (SIG_DFL) */
11610 #define S_CATCH 2 /* signal is caught */
11611 #define S_IGN 3 /* signal is ignored (SIG_IGN) */
11612 #define S_HARD_IGN 4 /* signal is ignored permenantly */
11613 #define S_RESET 5 /* temporary - to reset a hard ignored sig */
11618 * The trap builtin.
11622 trapcmd(int argc, char **argv)
11631 for (signo = 0 ; signo < NSIG ; signo++) {
11632 if (trap[signo] != NULL) {
11635 sn = get_signame(signo);
11636 out1fmt("trap -- %s %s\n",
11637 single_quote(trap[signo]), sn);
11647 if ((signo = get_signum(*ap)) < 0)
11648 sh_error("%s: bad trap", *ap);
11651 if (action[0] == '-' && action[1] == '\0')
11654 action = savestr(action);
11657 ckfree(trap[signo]);
11658 trap[signo] = action;
11669 * Clear traps on a fork.
11677 for (tp = trap ; tp < &trap[NSIG] ; tp++) {
11678 if (*tp && **tp) { /* trap not NULL or SIG_IGN */
11682 if (tp != &trap[0])
11683 setsignal(tp - trap);
11691 * Set the signal handler for the specified signal. The routine figures
11692 * out what it should be set to.
11696 setsignal(int signo)
11700 struct sigaction act;
11702 if ((t = trap[signo]) == NULL)
11704 else if (*t != '\0')
11708 if (rootshell && action == S_DFL) {
11711 if (iflag || minusc || sflag == 0)
11734 t = &sigmode[signo - 1];
11738 * current setting unknown
11740 if (sigaction(signo, 0, &act) == -1) {
11742 * Pretend it worked; maybe we should give a warning
11743 * here, but other shells don't. We don't alter
11744 * sigmode, so that we retry every time.
11748 if (act.sa_handler == SIG_IGN) {
11749 if (mflag && (signo == SIGTSTP ||
11750 signo == SIGTTIN || signo == SIGTTOU)) {
11751 tsig = S_IGN; /* don't hard ignore these */
11755 tsig = S_RESET; /* force to be set */
11758 if (tsig == S_HARD_IGN || tsig == action)
11762 act.sa_handler = onsig;
11765 act.sa_handler = SIG_IGN;
11768 act.sa_handler = SIG_DFL;
11772 sigfillset(&act.sa_mask);
11773 sigaction(signo, &act, 0);
11781 ignoresig(int signo)
11783 if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
11784 signal(signo, SIG_IGN);
11786 sigmode[signo - 1] = S_HARD_IGN;
11797 gotsig[signo - 1] = 1;
11798 pendingsigs = signo;
11800 if (exsig || (signo == SIGINT && !trap[SIGINT])) {
11809 * Called to execute a trap. Perhaps we should avoid entering new trap
11810 * handlers while we are executing a trap handler.
11822 savestatus = exitstatus;
11826 for (i = 0, q = gotsig; i < NSIG - 1; i++, q++) {
11834 skip = evalstring(p, SKIPEVAL);
11835 exitstatus = savestatus;
11845 * Controls whether the shell is interactive or not.
11849 setinteractive(int on)
11851 static int is_interactive;
11853 if (++on == is_interactive)
11855 is_interactive = on;
11857 setsignal(SIGQUIT);
11858 setsignal(SIGTERM);
11859 #ifndef CONFIG_FEATURE_SH_EXTRA_QUIET
11860 if(is_interactive > 1) {
11861 /* Looks like they want an interactive shell */
11862 static int do_banner;
11866 "\n\n%s Built-in shell (ash)\n"
11867 "Enter 'help' for a list of built-in commands.\n\n",
11876 #ifndef CONFIG_FEATURE_SH_EXTRA_QUIET
11877 /*** List the available builtins ***/
11879 static int helpcmd(int argc, char **argv)
11883 out1fmt("\nBuilt-in commands:\n-------------------\n");
11884 for (col = 0, i = 0; i < NUMBUILTINS; i++) {
11885 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
11886 builtincmd[i].name + 1);
11892 #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
11894 extern const struct BB_applet applets[];
11895 extern const size_t NUM_APPLETS;
11897 for (i = 0; i < NUM_APPLETS; i++) {
11899 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), applets[i].name);
11908 return EXIT_SUCCESS;
11910 #endif /* CONFIG_FEATURE_SH_EXTRA_QUIET */
11913 * Called to exit the shell.
11923 status = exitstatus;
11924 TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
11925 if (setjmp(loc.loc)) {
11926 if (exception == EXEXIT)
11931 if ((p = trap[0])) {
11937 #ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
11938 if (iflag && rootshell) {
11939 const char *hp = lookupvar("HISTFILE");
11942 save_history ( hp );
11952 static struct var *vartab[VTABSIZE];
11954 static int vpcmp(const void *, const void *);
11955 static struct var **findvar(struct var **, const char *);
11958 * Initialize the variable symbol tables and import the environment
11962 #ifdef CONFIG_ASH_GETOPTS
11964 * Safe version of setvar, returns 1 on success 0 on failure.
11968 setvarsafe(const char *name, const char *val, int flags)
11971 volatile int saveint;
11972 struct jmploc *volatile savehandler = handler;
11973 struct jmploc jmploc;
11976 if (setjmp(jmploc.loc))
11980 setvar(name, val, flags);
11983 handler = savehandler;
11984 RESTOREINT(saveint);
11990 * Set the value of a variable. The flags argument is ored with the
11991 * flags of the variable. If val is NULL, the variable is unset.
11995 setvar(const char *name, const char *val, int flags)
12002 q = endofname(name);
12003 p = strchrnul(q, '=');
12004 namelen = p - name;
12005 if (!namelen || p != q)
12006 sh_error("%.*s: bad variable name", namelen, name);
12011 vallen = strlen(val);
12014 p = mempcpy(nameeq = ckmalloc(namelen + vallen + 2), name, namelen);
12017 p = mempcpy(p, val, vallen);
12020 setvareq(nameeq, flags | VNOSAVE);
12026 * Same as setvar except that the variable and value are passed in
12027 * the first argument as name=value. Since the first argument will
12028 * be actually stored in the table, it should not be a string that
12030 * Called with interrupts off.
12034 setvareq(char *s, int flags)
12036 struct var *vp, **vpp;
12039 flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
12040 vp = *findvar(vpp, s);
12042 if ((vp->flags & (VREADONLY|VDYNAMIC)) == VREADONLY) {
12045 if (flags & VNOSAVE)
12048 sh_error("%.*s: is read only", strchrnul(n, '=') - n, n);
12051 if (flags & VNOSET)
12054 if (vp->func && (flags & VNOFUNC) == 0)
12055 (*vp->func)(strchrnul(s, '=') + 1);
12057 if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
12060 flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET);
12062 if (flags & VNOSET)
12065 vp = ckmalloc(sizeof (*vp));
12070 if (!(flags & (VTEXTFIXED|VSTACK|VNOSAVE)))
12078 * Process a linked list of variable assignments.
12082 listsetvar(struct strlist *list_set_var, int flags)
12084 struct strlist *lp = list_set_var;
12090 setvareq(lp->text, flags);
12091 } while ((lp = lp->next));
12097 * Find the value of a variable. Returns NULL if not set.
12101 lookupvar(const char *name)
12105 if ((v = *findvar(hashvar(name), name))) {
12108 * Dynamic variables are implemented roughly the same way they are
12109 * in bash. Namely, they're "special" so long as they aren't unset.
12110 * As soon as they're unset, they're no longer dynamic, and dynamic
12111 * lookup will no longer happen at that point. -- PFM.
12113 if((v->flags & VDYNAMIC))
12116 if(!(v->flags & VUNSET))
12117 return strchrnul(v->text, '=') + 1;
12125 * Search the environment of a builtin command.
12129 bltinlookup(const char *name)
12131 struct strlist *sp;
12133 for (sp = cmdenviron ; sp ; sp = sp->next) {
12134 if (varequal(sp->text, name))
12135 return strchrnul(sp->text, '=') + 1;
12137 return lookupvar(name);
12142 * Generate a list of variables satisfying the given conditions.
12146 listvars(int on, int off, char ***end)
12157 for (vp = *vpp ; vp ; vp = vp->next)
12158 if ((vp->flags & mask) == on) {
12159 if (ep == stackstrend())
12160 ep = growstackstr();
12161 *ep++ = (char *) vp->text;
12163 } while (++vpp < vartab + VTABSIZE);
12164 if (ep == stackstrend())
12165 ep = growstackstr();
12169 return grabstackstr(ep);
12174 * POSIX requires that 'set' (but not export or readonly) output the
12175 * variables in lexicographic order - by the locale's collating order (sigh).
12176 * Maybe we could keep them in an ordered balanced binary tree
12177 * instead of hashed lists.
12178 * For now just roll 'em through qsort for printing...
12182 showvars(const char *sep_prefix, int on, int off)
12185 char **ep, **epend;
12187 ep = listvars(on, off, &epend);
12188 qsort(ep, epend - ep, sizeof(char *), vpcmp);
12190 sep = *sep_prefix ? spcstr : sep_prefix;
12192 for (; ep < epend; ep++) {
12196 p = strchrnul(*ep, '=');
12199 q = single_quote(++p);
12201 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
12210 * The export and readonly commands.
12214 exportcmd(int argc, char **argv)
12220 int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT;
12223 notp = nextopt("p") - 'p';
12224 if (notp && ((name = *(aptr = argptr)))) {
12226 if ((p = strchr(name, '=')) != NULL) {
12229 if ((vp = *findvar(hashvar(name), name))) {
12234 setvar(name, p, flag);
12235 } while ((name = *++aptr) != NULL);
12237 showvars(argv[0], flag, 0);
12244 * Make a variable a local variable. When a variable is made local, it's
12245 * value and flags are saved in a localvar structure. The saved values
12246 * will be restored when the shell function returns. We handle the name
12247 * "-" as a special case.
12250 static void mklocal(char *name)
12252 struct localvar *lvp;
12257 lvp = ckmalloc(sizeof (struct localvar));
12258 if (name[0] == '-' && name[1] == '\0') {
12260 p = ckmalloc(sizeof(optlist));
12261 lvp->text = memcpy(p, optlist, sizeof(optlist));
12266 vpp = hashvar(name);
12267 vp = *findvar(vpp, name);
12268 eq = strchr(name, '=');
12271 setvareq(name, VSTRFIXED);
12273 setvar(name, NULL, VSTRFIXED);
12274 vp = *vpp; /* the new variable */
12275 lvp->flags = VUNSET;
12277 lvp->text = vp->text;
12278 lvp->flags = vp->flags;
12279 vp->flags |= VSTRFIXED|VTEXTFIXED;
12285 lvp->next = localvars;
12291 * The "local" command.
12295 localcmd(int argc, char **argv)
12300 while ((name = *argv++) != NULL) {
12308 * Called after a function returns.
12309 * Interrupts must be off.
12315 struct localvar *lvp;
12318 while ((lvp = localvars) != NULL) {
12319 localvars = lvp->next;
12321 TRACE(("poplocalvar %s", vp ? vp->text : "-"));
12322 if (vp == NULL) { /* $- saved */
12323 memcpy(optlist, lvp->text, sizeof(optlist));
12326 } else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
12327 unsetvar(vp->text);
12330 (*vp->func)(strchrnul(lvp->text, '=') + 1);
12331 if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
12333 vp->flags = lvp->flags;
12334 vp->text = lvp->text;
12342 * The unset builtin command. We unset the function before we unset the
12343 * variable to allow a function to be unset when there is a readonly variable
12344 * with the same name.
12348 unsetcmd(int argc, char **argv)
12355 while ((i = nextopt("vf")) != '\0') {
12359 for (ap = argptr; *ap ; ap++) {
12374 * Unset the specified variable.
12378 unsetvar(const char *s)
12384 vpp = findvar(hashvar(s), s);
12388 int flags = vp->flags;
12391 if (flags & VREADONLY)
12394 vp->flags &= ~VDYNAMIC;
12396 if (flags & VUNSET)
12398 if ((flags & VSTRFIXED) == 0) {
12400 if ((flags & (VTEXTFIXED|VSTACK)) == 0)
12407 vp->flags &= ~VEXPORT;
12420 * Find the appropriate entry in the hash table from the name.
12423 static struct var **
12424 hashvar(const char *p)
12426 unsigned int hashval;
12428 hashval = ((unsigned char) *p) << 4;
12429 while (*p && *p != '=')
12430 hashval += (unsigned char) *p++;
12431 return &vartab[hashval % VTABSIZE];
12437 * Compares two strings up to the first = or '\0'. The first
12438 * string must be terminated by '='; the second may be terminated by
12439 * either '=' or '\0'.
12443 varcmp(const char *p, const char *q)
12447 while ((c = *p) == (d = *q)) {
12448 if (!c || c == '=')
12462 vpcmp(const void *a, const void *b)
12464 return varcmp(*(const char **)a, *(const char **)b);
12467 static struct var **
12468 findvar(struct var **vpp, const char *name)
12470 for (; *vpp; vpp = &(*vpp)->next) {
12471 if (varequal((*vpp)->text, name)) {
12479 #include <sys/times.h>
12481 static const unsigned char timescmd_str[] = {
12482 ' ', offsetof(struct tms, tms_utime),
12483 '\n', offsetof(struct tms, tms_stime),
12484 ' ', offsetof(struct tms, tms_cutime),
12485 '\n', offsetof(struct tms, tms_cstime),
12489 static int timescmd(int ac, char **av)
12491 long int clk_tck, s, t;
12492 const unsigned char *p;
12495 clk_tck = sysconf(_SC_CLK_TCK);
12500 t = *(clock_t *)(((char *) &buf) + p[1]);
12502 out1fmt("%ldm%ld.%.3lds%c",
12504 ((t - s * clk_tck) * 1000) / clk_tck,
12506 } while (*(p += 2));
12511 #ifdef CONFIG_ASH_MATH_SUPPORT
12513 dash_arith(const char *s)
12519 result = arith(s, &errcode);
12522 sh_error("exponent less than 0");
12523 else if (errcode == -2)
12524 sh_error("divide by zero");
12525 else if (errcode == -5)
12526 sh_error("expression recursion loop detected");
12537 * The let builtin. partial stolen from GNU Bash, the Bourne Again SHell.
12538 * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
12540 * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
12544 letcmd(int argc, char **argv)
12551 sh_error("expression expected");
12552 for (ap = argv + 1; *ap; ap++) {
12553 i = dash_arith(*ap);
12558 #endif /* CONFIG_ASH_MATH_SUPPORT */
12563 * Miscellaneous builtins.
12569 #if __GLIBC__ == 2 && __GLIBC_MINOR__ < 1
12570 typedef enum __rlimit_resource rlim_t;
12576 * The read builtin. The -e option causes backslashes to escape the
12577 * following character.
12579 * This uses unbuffered input, which may be avoidable in some cases.
12583 readcmd(int argc, char **argv)
12595 #if defined(CONFIG_ASH_READ_NCHARS)
12599 struct termios tty, old_tty;
12601 #if defined(CONFIG_ASH_READ_TIMEOUT)
12605 ts.tv_sec = ts.tv_usec = 0;
12610 #if defined(CONFIG_ASH_READ_NCHARS) && defined(CONFIG_ASH_READ_TIMEOUT)
12611 while ((i = nextopt("p:rt:n:s")) != '\0')
12612 #elif defined(CONFIG_ASH_READ_NCHARS)
12613 while ((i = nextopt("p:rn:s")) != '\0')
12614 #elif defined(CONFIG_ASH_READ_TIMEOUT)
12615 while ((i = nextopt("p:rt:")) != '\0')
12617 while ((i = nextopt("p:r")) != '\0')
12622 prompt = optionarg;
12624 #if defined(CONFIG_ASH_READ_NCHARS)
12626 nchars = strtol(optionarg, &p, 10);
12628 sh_error("invalid count");
12629 nch_flag = (nchars > 0);
12635 #if defined(CONFIG_ASH_READ_TIMEOUT)
12637 ts.tv_sec = strtol(optionarg, &p, 10);
12643 ts.tv_usec = strtol(p, &p2, 10);
12645 sh_error("invalid timeout");
12647 /* normalize to usec */
12649 sh_error("invalid timeout");
12650 while (scale++ < 6)
12654 sh_error("invalid timeout");
12656 if ( ! ts.tv_sec && ! ts.tv_usec)
12657 sh_error("invalid timeout");
12667 if (prompt && isatty(0)) {
12670 if (*(ap = argptr) == NULL)
12671 sh_error("arg count");
12672 if ((ifs = bltinlookup("IFS")) == NULL)
12674 #if defined(CONFIG_ASH_READ_NCHARS)
12675 if (nch_flag || silent) {
12676 tcgetattr(0, &tty);
12679 tty.c_lflag &= ~ICANON;
12680 tty.c_cc[VMIN] = nchars;
12683 tty.c_lflag &= ~(ECHO|ECHOK|ECHONL);
12686 tcsetattr(0, TCSANOW, &tty);
12689 #if defined(CONFIG_ASH_READ_TIMEOUT)
12690 if (ts.tv_sec || ts.tv_usec) {
12694 i = select (FD_SETSIZE, &set, NULL, NULL, &ts);
12696 #if defined(CONFIG_ASH_READ_NCHARS)
12698 tcsetattr(0, TCSANOW, &old_tty);
12708 #if defined(CONFIG_ASH_READ_NCHARS)
12709 while (!nch_flag || nchars--)
12714 if (read(0, &c, 1) != 1) {
12726 if (!rflag && c == '\\') {
12732 if (startword && *ifs == ' ' && strchr(ifs, c)) {
12736 if (ap[1] != NULL && strchr(ifs, c) != NULL) {
12738 setvar(*ap, stackblock(), 0);
12747 #if defined(CONFIG_ASH_READ_NCHARS)
12748 if (nch_flag || silent)
12749 tcsetattr(0, TCSANOW, &old_tty);
12753 /* Remove trailing blanks */
12754 while ((char *)stackblock() <= --p && strchr(ifs, *p) != NULL)
12756 setvar(*ap, stackblock(), 0);
12757 while (*++ap != NULL)
12758 setvar(*ap, nullstr, 0);
12763 static int umaskcmd(int argc, char **argv)
12765 static const char permuser[3] = "ugo";
12766 static const char permmode[3] = "rwx";
12767 static const short int permmask[] = {
12768 S_IRUSR, S_IWUSR, S_IXUSR,
12769 S_IRGRP, S_IWGRP, S_IXGRP,
12770 S_IROTH, S_IWOTH, S_IXOTH
12776 int symbolic_mode = 0;
12778 while (nextopt("S") != '\0') {
12787 if ((ap = *argptr) == NULL) {
12788 if (symbolic_mode) {
12792 for (i = 0; i < 3; i++) {
12795 *p++ = permuser[i];
12797 for (j = 0; j < 3; j++) {
12798 if ((mask & permmask[3 * i + j]) == 0) {
12799 *p++ = permmode[j];
12807 out1fmt("%.4o\n", mask);
12810 if (is_digit((unsigned char) *ap)) {
12813 if (*ap >= '8' || *ap < '0')
12814 sh_error(illnum, argv[1]);
12815 mask = (mask << 3) + (*ap - '0');
12816 } while (*++ap != '\0');
12819 mask = ~mask & 0777;
12820 if (!bb_parse_mode(ap, &mask)) {
12821 sh_error("Illegal mode: %s", ap);
12823 umask(~mask & 0777);
12832 * This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and
12833 * Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with
12834 * ash by J.T. Conklin.
12842 int factor; /* multiply by to get rlim_{cur,max} values */
12846 static const struct limits limits[] = {
12848 { "time(seconds)", RLIMIT_CPU, 1, 't' },
12850 #ifdef RLIMIT_FSIZE
12851 { "file(blocks)", RLIMIT_FSIZE, 512, 'f' },
12854 { "data(kbytes)", RLIMIT_DATA, 1024, 'd' },
12856 #ifdef RLIMIT_STACK
12857 { "stack(kbytes)", RLIMIT_STACK, 1024, 's' },
12860 { "coredump(blocks)", RLIMIT_CORE, 512, 'c' },
12863 { "memory(kbytes)", RLIMIT_RSS, 1024, 'm' },
12865 #ifdef RLIMIT_MEMLOCK
12866 { "locked memory(kbytes)", RLIMIT_MEMLOCK, 1024, 'l' },
12868 #ifdef RLIMIT_NPROC
12869 { "process", RLIMIT_NPROC, 1, 'p' },
12871 #ifdef RLIMIT_NOFILE
12872 { "nofiles", RLIMIT_NOFILE, 1, 'n' },
12875 { "vmemory(kbytes)", RLIMIT_AS, 1024, 'v' },
12877 #ifdef RLIMIT_LOCKS
12878 { "locks", RLIMIT_LOCKS, 1, 'w' },
12880 { (char *) 0, 0, 0, '\0' }
12883 enum limtype { SOFT = 0x1, HARD = 0x2 };
12885 static void printlim(enum limtype how, const struct rlimit *limit,
12886 const struct limits *l)
12890 val = limit->rlim_max;
12892 val = limit->rlim_cur;
12894 if (val == RLIM_INFINITY)
12895 out1fmt("unlimited\n");
12898 out1fmt("%lld\n", (long long) val);
12903 ulimitcmd(int argc, char **argv)
12907 enum limtype how = SOFT | HARD;
12908 const struct limits *l;
12911 struct rlimit limit;
12914 while ((optc = nextopt("HSa"
12918 #ifdef RLIMIT_FSIZE
12924 #ifdef RLIMIT_STACK
12933 #ifdef RLIMIT_MEMLOCK
12936 #ifdef RLIMIT_NPROC
12939 #ifdef RLIMIT_NOFILE
12945 #ifdef RLIMIT_LOCKS
12963 for (l = limits; l->option != what; l++)
12966 set = *argptr ? 1 : 0;
12970 if (all || argptr[1])
12971 sh_error("too many arguments");
12972 if (strncmp(p, "unlimited\n", 9) == 0)
12973 val = RLIM_INFINITY;
12977 while ((c = *p++) >= '0' && c <= '9')
12979 val = (val * 10) + (long)(c - '0');
12980 if (val < (rlim_t) 0)
12984 sh_error("bad number");
12989 for (l = limits; l->name; l++) {
12990 getrlimit(l->cmd, &limit);
12991 out1fmt("%-20s ", l->name);
12992 printlim(how, &limit, l);
12997 getrlimit(l->cmd, &limit);
13000 limit.rlim_max = val;
13002 limit.rlim_cur = val;
13003 if (setrlimit(l->cmd, &limit) < 0)
13004 sh_error("error setting limit (%m)");
13006 printlim(how, &limit, l);
13012 #ifdef CONFIG_ASH_MATH_SUPPORT
13014 /* Copyright (c) 2001 Aaron Lehmann <aaronl@vitelus.com>
13016 Permission is hereby granted, free of charge, to any person obtaining
13017 a copy of this software and associated documentation files (the
13018 "Software"), to deal in the Software without restriction, including
13019 without limitation the rights to use, copy, modify, merge, publish,
13020 distribute, sublicense, and/or sell copies of the Software, and to
13021 permit persons to whom the Software is furnished to do so, subject to
13022 the following conditions:
13024 The above copyright notice and this permission notice shall be
13025 included in all copies or substantial portions of the Software.
13027 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13028 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
13029 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
13030 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
13031 CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
13032 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
13033 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
13036 /* This is my infix parser/evaluator. It is optimized for size, intended
13037 * as a replacement for yacc-based parsers. However, it may well be faster
13038 * than a comparable parser written in yacc. The supported operators are
13039 * listed in #defines below. Parens, order of operations, and error handling
13040 * are supported. This code is thread safe. The exact expression format should
13041 * be that which POSIX specifies for shells. */
13043 /* The code uses a simple two-stack algorithm. See
13044 * http://www.onthenet.com.au/~grahamis/int2008/week02/lect02.html
13045 * for a detailed explanation of the infix-to-postfix algorithm on which
13046 * this is based (this code differs in that it applies operators immediately
13047 * to the stack instead of adding them to a queue to end up with an
13050 /* To use the routine, call it with an expression string and error return
13054 * Aug 24, 2001 Manuel Novoa III
13056 * Reduced the generated code size by about 30% (i386) and fixed several bugs.
13058 * 1) In arith_apply():
13059 * a) Cached values of *numptr and &(numptr[-1]).
13060 * b) Removed redundant test for zero denominator.
13063 * a) Eliminated redundant code for processing operator tokens by moving
13064 * to a table-based implementation. Also folded handling of parens
13066 * b) Combined all 3 loops which called arith_apply to reduce generated
13067 * code size at the cost of speed.
13069 * 3) The following expressions were treated as valid by the original code:
13070 * 1() , 0! , 1 ( *3 ) .
13071 * These bugs have been fixed by internally enclosing the expression in
13072 * parens and then checking that all binary ops and right parens are
13073 * preceded by a valid expression (NUM_TOKEN).
13075 * Note: It may be desirable to replace Aaron's test for whitespace with
13076 * ctype's isspace() if it is used by another busybox applet or if additional
13077 * whitespace chars should be considered. Look below the "#include"s for a
13078 * precompiler test.
13082 * Aug 26, 2001 Manuel Novoa III
13084 * Return 0 for null expressions. Pointed out by Vladimir Oleynik.
13086 * Merge in Aaron's comments previously posted to the busybox list,
13087 * modified slightly to take account of my changes to the code.
13092 * (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
13094 * - allow access to variable,
13095 * used recursive find value indirection (c=2*2; a="c"; $((a+=2)) produce 6)
13096 * - realize assign syntax (VAR=expr, +=, *= etc)
13097 * - realize exponentiation (** operator)
13098 * - realize comma separated - expr, expr
13099 * - realise ++expr --expr expr++ expr--
13100 * - realise expr ? expr : expr (but, second expr calculate always)
13101 * - allow hexadecimal and octal numbers
13102 * - was restored loses XOR operator
13103 * - remove one goto label, added three ;-)
13104 * - protect $((num num)) as true zero expr (Manuel`s error)
13105 * - always use special isspace(), see comment from bash ;-)
13109 #define arith_isspace(arithval) \
13110 (arithval == ' ' || arithval == '\n' || arithval == '\t')
13113 typedef unsigned char operator;
13115 /* An operator's token id is a bit of a bitfield. The lower 5 bits are the
13116 * precedence, and 3 high bits are an ID unique across operators of that
13117 * precedence. The ID portion is so that multiple operators can have the
13118 * same precedence, ensuring that the leftmost one is evaluated first.
13119 * Consider * and /. */
13121 #define tok_decl(prec,id) (((id)<<5)|(prec))
13122 #define PREC(op) ((op) & 0x1F)
13124 #define TOK_LPAREN tok_decl(0,0)
13126 #define TOK_COMMA tok_decl(1,0)
13128 #define TOK_ASSIGN tok_decl(2,0)
13129 #define TOK_AND_ASSIGN tok_decl(2,1)
13130 #define TOK_OR_ASSIGN tok_decl(2,2)
13131 #define TOK_XOR_ASSIGN tok_decl(2,3)
13132 #define TOK_PLUS_ASSIGN tok_decl(2,4)
13133 #define TOK_MINUS_ASSIGN tok_decl(2,5)
13134 #define TOK_LSHIFT_ASSIGN tok_decl(2,6)
13135 #define TOK_RSHIFT_ASSIGN tok_decl(2,7)
13137 #define TOK_MUL_ASSIGN tok_decl(3,0)
13138 #define TOK_DIV_ASSIGN tok_decl(3,1)
13139 #define TOK_REM_ASSIGN tok_decl(3,2)
13141 /* all assign is right associativity and precedence eq, but (7+3)<<5 > 256 */
13142 #define convert_prec_is_assing(prec) do { if(prec == 3) prec = 2; } while(0)
13144 /* conditional is right associativity too */
13145 #define TOK_CONDITIONAL tok_decl(4,0)
13146 #define TOK_CONDITIONAL_SEP tok_decl(4,1)
13148 #define TOK_OR tok_decl(5,0)
13150 #define TOK_AND tok_decl(6,0)
13152 #define TOK_BOR tok_decl(7,0)
13154 #define TOK_BXOR tok_decl(8,0)
13156 #define TOK_BAND tok_decl(9,0)
13158 #define TOK_EQ tok_decl(10,0)
13159 #define TOK_NE tok_decl(10,1)
13161 #define TOK_LT tok_decl(11,0)
13162 #define TOK_GT tok_decl(11,1)
13163 #define TOK_GE tok_decl(11,2)
13164 #define TOK_LE tok_decl(11,3)
13166 #define TOK_LSHIFT tok_decl(12,0)
13167 #define TOK_RSHIFT tok_decl(12,1)
13169 #define TOK_ADD tok_decl(13,0)
13170 #define TOK_SUB tok_decl(13,1)
13172 #define TOK_MUL tok_decl(14,0)
13173 #define TOK_DIV tok_decl(14,1)
13174 #define TOK_REM tok_decl(14,2)
13176 /* exponent is right associativity */
13177 #define TOK_EXPONENT tok_decl(15,1)
13179 /* For now unary operators. */
13180 #define UNARYPREC 16
13181 #define TOK_BNOT tok_decl(UNARYPREC,0)
13182 #define TOK_NOT tok_decl(UNARYPREC,1)
13184 #define TOK_UMINUS tok_decl(UNARYPREC+1,0)
13185 #define TOK_UPLUS tok_decl(UNARYPREC+1,1)
13187 #define PREC_PRE (UNARYPREC+2)
13189 #define TOK_PRE_INC tok_decl(PREC_PRE, 0)
13190 #define TOK_PRE_DEC tok_decl(PREC_PRE, 1)
13192 #define PREC_POST (UNARYPREC+3)
13194 #define TOK_POST_INC tok_decl(PREC_POST, 0)
13195 #define TOK_POST_DEC tok_decl(PREC_POST, 1)
13197 #define SPEC_PREC (UNARYPREC+4)
13199 #define TOK_NUM tok_decl(SPEC_PREC, 0)
13200 #define TOK_RPAREN tok_decl(SPEC_PREC, 1)
13202 #define NUMPTR (*numstackptr)
13204 static int tok_have_assign(operator op)
13206 operator prec = PREC(op);
13208 convert_prec_is_assing(prec);
13209 return (prec == PREC(TOK_ASSIGN) ||
13210 prec == PREC_PRE || prec == PREC_POST);
13213 static int is_right_associativity(operator prec)
13215 return (prec == PREC(TOK_ASSIGN) || prec == PREC(TOK_EXPONENT) ||
13216 prec == PREC(TOK_CONDITIONAL));
13220 typedef struct ARITCH_VAR_NUM {
13222 arith_t contidional_second_val;
13223 char contidional_second_val_initialized;
13224 char *var; /* if NULL then is regular number,
13225 else is variable name */
13229 typedef struct CHK_VAR_RECURSIVE_LOOPED {
13231 struct CHK_VAR_RECURSIVE_LOOPED *next;
13232 } chk_var_recursive_looped_t;
13234 static chk_var_recursive_looped_t *prev_chk_var_recursive;
13237 static int arith_lookup_val(v_n_t *t)
13240 const char * p = lookupvar(t->var);
13245 /* recursive try as expression */
13246 chk_var_recursive_looped_t *cur;
13247 chk_var_recursive_looped_t cur_save;
13249 for(cur = prev_chk_var_recursive; cur; cur = cur->next) {
13250 if(strcmp(cur->var, t->var) == 0) {
13251 /* expression recursion loop detected */
13255 /* save current lookuped var name */
13256 cur = prev_chk_var_recursive;
13257 cur_save.var = t->var;
13258 cur_save.next = cur;
13259 prev_chk_var_recursive = &cur_save;
13261 t->val = arith (p, &errcode);
13262 /* restore previous ptr after recursiving */
13263 prev_chk_var_recursive = cur;
13266 /* allow undefined var as 0 */
13273 /* "applying" a token means performing it on the top elements on the integer
13274 * stack. For a unary operator it will only change the top element, but a
13275 * binary operator will pop two arguments and push a result */
13276 static int arith_apply(operator op, v_n_t *numstack, v_n_t **numstackptr)
13279 arith_t numptr_val, rez;
13280 int ret_arith_lookup_val;
13282 if (NUMPTR == numstack) goto err; /* There is no operator that can work
13283 without arguments */
13284 numptr_m1 = NUMPTR - 1;
13286 /* check operand is var with noninteger value */
13287 ret_arith_lookup_val = arith_lookup_val(numptr_m1);
13288 if(ret_arith_lookup_val)
13289 return ret_arith_lookup_val;
13291 rez = numptr_m1->val;
13292 if (op == TOK_UMINUS)
13294 else if (op == TOK_NOT)
13296 else if (op == TOK_BNOT)
13298 else if (op == TOK_POST_INC || op == TOK_PRE_INC)
13300 else if (op == TOK_POST_DEC || op == TOK_PRE_DEC)
13302 else if (op != TOK_UPLUS) {
13303 /* Binary operators */
13305 /* check and binary operators need two arguments */
13306 if (numptr_m1 == numstack) goto err;
13308 /* ... and they pop one */
13311 if (op == TOK_CONDITIONAL) {
13312 if(! numptr_m1->contidional_second_val_initialized) {
13313 /* protect $((expr1 ? expr2)) without ": expr" */
13316 rez = numptr_m1->contidional_second_val;
13317 } else if(numptr_m1->contidional_second_val_initialized) {
13318 /* protect $((expr1 : expr2)) without "expr ? " */
13321 numptr_m1 = NUMPTR - 1;
13322 if(op != TOK_ASSIGN) {
13323 /* check operand is var with noninteger value for not '=' */
13324 ret_arith_lookup_val = arith_lookup_val(numptr_m1);
13325 if(ret_arith_lookup_val)
13326 return ret_arith_lookup_val;
13328 if (op == TOK_CONDITIONAL) {
13329 numptr_m1->contidional_second_val = rez;
13331 rez = numptr_m1->val;
13332 if (op == TOK_BOR || op == TOK_OR_ASSIGN)
13334 else if (op == TOK_OR)
13335 rez = numptr_val || rez;
13336 else if (op == TOK_BAND || op == TOK_AND_ASSIGN)
13338 else if (op == TOK_BXOR || op == TOK_XOR_ASSIGN)
13340 else if (op == TOK_AND)
13341 rez = rez && numptr_val;
13342 else if (op == TOK_EQ)
13343 rez = (rez == numptr_val);
13344 else if (op == TOK_NE)
13345 rez = (rez != numptr_val);
13346 else if (op == TOK_GE)
13347 rez = (rez >= numptr_val);
13348 else if (op == TOK_RSHIFT || op == TOK_RSHIFT_ASSIGN)
13349 rez >>= numptr_val;
13350 else if (op == TOK_LSHIFT || op == TOK_LSHIFT_ASSIGN)
13351 rez <<= numptr_val;
13352 else if (op == TOK_GT)
13353 rez = (rez > numptr_val);
13354 else if (op == TOK_LT)
13355 rez = (rez < numptr_val);
13356 else if (op == TOK_LE)
13357 rez = (rez <= numptr_val);
13358 else if (op == TOK_MUL || op == TOK_MUL_ASSIGN)
13360 else if (op == TOK_ADD || op == TOK_PLUS_ASSIGN)
13362 else if (op == TOK_SUB || op == TOK_MINUS_ASSIGN)
13364 else if (op == TOK_ASSIGN || op == TOK_COMMA)
13366 else if (op == TOK_CONDITIONAL_SEP) {
13367 if (numptr_m1 == numstack) {
13368 /* protect $((expr : expr)) without "expr ? " */
13371 numptr_m1->contidional_second_val_initialized = op;
13372 numptr_m1->contidional_second_val = numptr_val;
13374 else if (op == TOK_CONDITIONAL) {
13376 numptr_val : numptr_m1->contidional_second_val;
13378 else if(op == TOK_EXPONENT) {
13380 return -3; /* exponent less than 0 */
13385 while(numptr_val--)
13390 else if(numptr_val==0) /* zero divisor check */
13392 else if (op == TOK_DIV || op == TOK_DIV_ASSIGN)
13394 else if (op == TOK_REM || op == TOK_REM_ASSIGN)
13397 if(tok_have_assign(op)) {
13400 if(numptr_m1->var == NULL) {
13404 /* save to shell variable */
13405 #ifdef CONFIG_ASH_MATH_SUPPORT_64
13406 snprintf(buf, sizeof(buf), "%lld", arith_t_type rez);
13408 snprintf(buf, sizeof(buf), "%ld", arith_t_type rez);
13410 setvar(numptr_m1->var, buf, 0);
13411 /* after saving, make previous value for v++ or v-- */
13412 if(op == TOK_POST_INC)
13414 else if(op == TOK_POST_DEC)
13417 numptr_m1->val = rez;
13418 /* protect geting var value, is number now */
13419 numptr_m1->var = NULL;
13424 /* longest must first */
13425 static const char op_tokens[] = {
13426 '<','<','=',0, TOK_LSHIFT_ASSIGN,
13427 '>','>','=',0, TOK_RSHIFT_ASSIGN,
13428 '<','<', 0, TOK_LSHIFT,
13429 '>','>', 0, TOK_RSHIFT,
13430 '|','|', 0, TOK_OR,
13431 '&','&', 0, TOK_AND,
13432 '!','=', 0, TOK_NE,
13433 '<','=', 0, TOK_LE,
13434 '>','=', 0, TOK_GE,
13435 '=','=', 0, TOK_EQ,
13436 '|','=', 0, TOK_OR_ASSIGN,
13437 '&','=', 0, TOK_AND_ASSIGN,
13438 '*','=', 0, TOK_MUL_ASSIGN,
13439 '/','=', 0, TOK_DIV_ASSIGN,
13440 '%','=', 0, TOK_REM_ASSIGN,
13441 '+','=', 0, TOK_PLUS_ASSIGN,
13442 '-','=', 0, TOK_MINUS_ASSIGN,
13443 '-','-', 0, TOK_POST_DEC,
13444 '^','=', 0, TOK_XOR_ASSIGN,
13445 '+','+', 0, TOK_POST_INC,
13446 '*','*', 0, TOK_EXPONENT,
13450 '=', 0, TOK_ASSIGN,
13462 '?', 0, TOK_CONDITIONAL,
13463 ':', 0, TOK_CONDITIONAL_SEP,
13464 ')', 0, TOK_RPAREN,
13465 '(', 0, TOK_LPAREN,
13469 #define endexpression &op_tokens[sizeof(op_tokens)-7]
13472 static arith_t arith (const char *expr, int *perrcode)
13474 char arithval; /* Current character under analysis */
13475 operator lasttok, op;
13478 const char *p = endexpression;
13481 size_t datasizes = strlen(expr) + 2;
13483 /* Stack of integers */
13484 /* The proof that there can be no more than strlen(startbuf)/2+1 integers
13485 * in any given correct or incorrect expression is left as an exercise to
13487 v_n_t *numstack = alloca(((datasizes)/2)*sizeof(v_n_t)),
13488 *numstackptr = numstack;
13489 /* Stack of operator tokens */
13490 operator *stack = alloca((datasizes) * sizeof(operator)),
13493 *stackptr++ = lasttok = TOK_LPAREN; /* start off with a left paren */
13494 *perrcode = errcode = 0;
13497 if ((arithval = *expr) == 0) {
13498 if (p == endexpression) {
13499 /* Null expression. */
13503 /* This is only reached after all tokens have been extracted from the
13504 * input stream. If there are still tokens on the operator stack, they
13505 * are to be applied in order. At the end, there should be a final
13506 * result on the integer stack */
13508 if (expr != endexpression + 1) {
13509 /* If we haven't done so already, */
13510 /* append a closing right paren */
13511 expr = endexpression;
13512 /* and let the loop process it. */
13515 /* At this point, we're done with the expression. */
13516 if (numstackptr != numstack+1) {
13517 /* ... but if there isn't, it's bad */
13519 return (*perrcode = -1);
13521 if(numstack->var) {
13522 /* expression is $((var)) only, lookup now */
13523 errcode = arith_lookup_val(numstack);
13526 *perrcode = errcode;
13527 return numstack->val;
13529 /* Continue processing the expression. */
13530 if (arith_isspace(arithval)) {
13531 /* Skip whitespace */
13534 if((p = endofname(expr)) != expr) {
13535 size_t var_name_size = (p-expr) + 1; /* trailing zero */
13537 numstackptr->var = alloca(var_name_size);
13538 safe_strncpy(numstackptr->var, expr, var_name_size);
13541 numstackptr->contidional_second_val_initialized = 0;
13545 } else if (is_digit(arithval)) {
13546 numstackptr->var = NULL;
13547 #ifdef CONFIG_ASH_MATH_SUPPORT_64
13548 numstackptr->val = strtoll(expr, (char **) &expr, 0);
13550 numstackptr->val = strtol(expr, (char **) &expr, 0);
13554 for(p = op_tokens; ; p++) {
13558 /* strange operator not found */
13561 for(o = expr; *p && *o == *p; p++)
13568 /* skip tail uncompared token */
13571 /* skip zero delim */
13576 /* post grammar: a++ reduce to num */
13577 if(lasttok == TOK_POST_INC || lasttok == TOK_POST_DEC)
13580 /* Plus and minus are binary (not unary) _only_ if the last
13581 * token was as number, or a right paren (which pretends to be
13582 * a number, since it evaluates to one). Think about it.
13583 * It makes sense. */
13584 if (lasttok != TOK_NUM) {
13600 /* We don't want a unary operator to cause recursive descent on the
13601 * stack, because there can be many in a row and it could cause an
13602 * operator to be evaluated before its argument is pushed onto the
13603 * integer stack. */
13604 /* But for binary operators, "apply" everything on the operator
13605 * stack until we find an operator with a lesser priority than the
13606 * one we have just extracted. */
13607 /* Left paren is given the lowest priority so it will never be
13608 * "applied" in this way.
13609 * if associativity is right and priority eq, applied also skip
13612 if ((prec > 0 && prec < UNARYPREC) || prec == SPEC_PREC) {
13613 /* not left paren or unary */
13614 if (lasttok != TOK_NUM) {
13615 /* binary op must be preceded by a num */
13618 while (stackptr != stack) {
13619 if (op == TOK_RPAREN) {
13620 /* The algorithm employed here is simple: while we don't
13621 * hit an open paren nor the bottom of the stack, pop
13622 * tokens and apply them */
13623 if (stackptr[-1] == TOK_LPAREN) {
13625 /* Any operator directly after a */
13627 /* close paren should consider itself binary */
13631 operator prev_prec = PREC(stackptr[-1]);
13633 convert_prec_is_assing(prec);
13634 convert_prec_is_assing(prev_prec);
13635 if (prev_prec < prec)
13637 /* check right assoc */
13638 if(prev_prec == prec && is_right_associativity(prec))
13641 errcode = arith_apply(*--stackptr, numstack, &numstackptr);
13642 if(errcode) goto ret;
13644 if (op == TOK_RPAREN) {
13649 /* Push this operator to the stack and remember it. */
13650 *stackptr++ = lasttok = op;
13657 #endif /* CONFIG_ASH_MATH_SUPPORT */
13661 const char *bb_applet_name = "debug stuff usage";
13662 int main(int argc, char **argv)
13664 return ash_main(argc, argv);
13669 * Copyright (c) 1989, 1991, 1993, 1994
13670 * The Regents of the University of California. All rights reserved.
13672 * This code is derived from software contributed to Berkeley by
13673 * Kenneth Almquist.
13675 * Redistribution and use in source and binary forms, with or without
13676 * modification, are permitted provided that the following conditions
13678 * 1. Redistributions of source code must retain the above copyright
13679 * notice, this list of conditions and the following disclaimer.
13680 * 2. Redistributions in binary form must reproduce the above copyright
13681 * notice, this list of conditions and the following disclaimer in the
13682 * documentation and/or other materials provided with the distribution.
13683 * 3. Neither the name of the University nor the names of its contributors
13684 * may be used to endorse or promote products derived from this software
13685 * without specific prior written permission.
13687 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
13688 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
13689 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
13690 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
13691 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
13692 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
13693 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13694 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
13695 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
13696 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF