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.
58 #include <sys/types.h>
59 #include <sys/ioctl.h>
60 #include <sys/param.h>
61 #include <sys/resource.h>
81 /*#include <stdint.h>*/
85 #ifdef CONFIG_ASH_JOB_CONTROL
91 #if JOBS || defined(CONFIG_ASH_READ_NCHARS)
98 static int *dash_errno;
100 #define errno (*dash_errno)
103 #if defined(__uClinux__)
104 #error "Do not even bother, ash will not run on uClinux"
108 #define _DIAGASSERT(assert_expr) assert(assert_expr)
110 #define _DIAGASSERT(assert_expr)
114 #ifdef CONFIG_ASH_ALIAS
127 static struct alias *lookupalias(const char *, int);
128 static int aliascmd(int, char **);
129 static int unaliascmd(int, char **);
130 static void rmaliases(void);
131 static int unalias(const char *);
132 static void printalias(const struct alias *);
138 static void setpwd(const char *, int);
144 * Types of operations (passed to the errmsg routine).
148 static const char not_found_msg[] = "%s: not found";
151 #define E_OPEN "No such file" /* opening a file */
152 #define E_CREAT "Directory nonexistent" /* creating a file */
153 #define E_EXEC not_found_msg+4 /* executing a program */
156 * We enclose jmp_buf in a structure so that we can declare pointers to
157 * jump locations. The global variable handler contains the location to
158 * jump to when an exception occurs, and the global variable exception
159 * contains a code identifying the exception. To implement nested
160 * exception handlers, the user should save the value of handler on entry
161 * to an inner scope, set handler to point to a jmploc structure for the
162 * inner scope, and restore handler on exit from the scope.
169 static struct jmploc *handler;
170 static int exception;
171 static volatile int suppressint;
172 static volatile sig_atomic_t intpending;
175 #define EXINT 0 /* SIGINT received */
176 #define EXERROR 1 /* a generic error */
177 #define EXSHELLPROC 2 /* execute a shell procedure */
178 #define EXEXEC 3 /* command execution failed */
179 #define EXEXIT 4 /* exit the shell */
180 #define EXSIG 5 /* trapped signal in wait(1) */
183 /* do we generate EXSIG events */
185 /* last pending signal */
186 static volatile sig_atomic_t pendingsigs;
189 * These macros allow the user to suspend the handling of interrupt signals
190 * over a period of time. This is similar to SIGHOLD to or sigblock, but
191 * much more efficient and portable. (But hacking the kernel is so much
192 * more fun than worrying about efficiency and portability. :-))
195 #define xbarrier() ({ __asm__ __volatile__ ("": : :"memory"); })
202 #define SAVEINT(v) ((v) = suppressint)
203 #define RESTOREINT(v) \
206 if ((suppressint = (v)) == 0 && intpending) onint(); \
217 /* EXSIG is turned off by evalbltin(). */
220 static void exraise(int) ATTRIBUTE_NORETURN;
221 static void onint(void) ATTRIBUTE_NORETURN;
223 static void sh_error(const char *, ...) ATTRIBUTE_NORETURN;
224 static void exerror(int, const char *, ...) ATTRIBUTE_NORETURN;
226 static void sh_warnx(const char *, ...);
228 #ifdef CONFIG_ASH_OPTIMIZE_FOR_SIZE
231 if (--suppressint == 0 && intpending) {
235 #define INTON inton()
236 static void forceinton(void)
242 #define FORCEINTON forceinton()
247 if (--suppressint == 0 && intpending) onint(); \
254 if (intpending) onint(); \
257 #endif /* CONFIG_ASH_OPTIMIZE_FOR_SIZE */
262 struct strlist *next;
268 struct strlist *list;
269 struct strlist **lastp;
275 #define EXP_FULL 0x1 /* perform word splitting & file globbing */
276 #define EXP_TILDE 0x2 /* do normal tilde expansion */
277 #define EXP_VARTILDE 0x4 /* expand tildes in an assignment */
278 #define EXP_REDIR 0x8 /* file glob for a redirection (1 match only) */
279 #define EXP_CASE 0x10 /* keeps quotes around for CASE pattern */
280 #define EXP_RECORD 0x20 /* need to record arguments for ifs breakup */
281 #define EXP_VARTILDE2 0x40 /* expand tildes after colons only */
282 #define EXP_WORD 0x80 /* expand word in parameter expansion */
283 #define EXP_QWORD 0x100 /* expand word in quoted parameter expansion */
287 static void expandarg(union node *, struct arglist *, int);
288 #define rmescapes(p) _rmescapes((p), 0)
289 static char *_rmescapes(char *, int);
290 static int casematch(union node *, char *);
292 #ifdef CONFIG_ASH_MATH_SUPPORT
293 static void expari(int);
298 static char *commandname; /* currently executing command */
299 static struct strlist *cmdenviron; /* environment for builtin command */
300 static int exitstatus; /* exit status of last command */
301 static int back_exitstatus; /* exit status of backquoted command */
304 struct backcmd { /* result of evalbackcmd */
305 int fd; /* file descriptor to read from */
306 char *buf; /* buffer */
307 int nleft; /* number of chars in buffer */
308 struct job *jp; /* job structure for command */
312 * This file was generated by the mknodes program.
348 union node *redirect;
355 struct nodelist *cmdlist;
362 union node *redirect;
377 union node *elsepart;
408 struct nodelist *backquote;
448 struct nredir nredir;
449 struct nbinary nbinary;
453 struct nclist nclist;
463 struct nodelist *next;
474 static void freefunc(struct funcnode *);
477 /* control characters in argument strings */
478 #define CTL_FIRST '\201' /* first 'special' character */
479 #define CTLESC '\201' /* escape next character */
480 #define CTLVAR '\202' /* variable defn */
481 #define CTLENDVAR '\203'
482 #define CTLBACKQ '\204'
483 #define CTLQUOTE 01 /* ored with CTLBACKQ code if in quotes */
484 /* CTLBACKQ | CTLQUOTE == '\205' */
485 #define CTLARI '\206' /* arithmetic expression */
486 #define CTLENDARI '\207'
487 #define CTLQUOTEMARK '\210'
488 #define CTL_LAST '\210' /* last 'special' character */
490 /* variable substitution byte (follows CTLVAR) */
491 #define VSTYPE 0x0f /* type of variable substitution */
492 #define VSNUL 0x10 /* colon--treat the empty string as unset */
493 #define VSQUOTE 0x80 /* inside double quotes--suppress splitting */
495 /* values of VSTYPE field */
496 #define VSNORMAL 0x1 /* normal variable: $var or ${var} */
497 #define VSMINUS 0x2 /* ${var-text} */
498 #define VSPLUS 0x3 /* ${var+text} */
499 #define VSQUESTION 0x4 /* ${var?message} */
500 #define VSASSIGN 0x5 /* ${var=text} */
501 #define VSTRIMRIGHT 0x6 /* ${var%pattern} */
502 #define VSTRIMRIGHTMAX 0x7 /* ${var%%pattern} */
503 #define VSTRIMLEFT 0x8 /* ${var#pattern} */
504 #define VSTRIMLEFTMAX 0x9 /* ${var##pattern} */
505 #define VSLENGTH 0xa /* ${#var} */
507 /* values of checkkwd variable */
512 #define IBUFSIZ (BUFSIZ + 1)
515 * NEOF is returned by parsecmd when it encounters an end of file. It
516 * must be distinct from NULL, so we use the address of a variable that
517 * happens to be handy.
519 static int plinno = 1; /* input line number */
521 /* number of characters left in input buffer */
522 static int parsenleft; /* copy of parsefile->nleft */
523 static int parselleft; /* copy of parsefile->lleft */
525 /* next character in input buffer */
526 static char *parsenextc; /* copy of parsefile->nextc */
529 struct strpush *prev; /* preceding string on stack */
532 #ifdef CONFIG_ASH_ALIAS
533 struct alias *ap; /* if push was associated with an alias */
535 char *string; /* remember the string since it may change */
539 struct parsefile *prev; /* preceding file on stack */
540 int linno; /* current line */
541 int fd; /* file descriptor (or -1 if string) */
542 int nleft; /* number of chars left in this line */
543 int lleft; /* number of chars left in this buffer */
544 char *nextc; /* next char in buffer */
545 char *buf; /* input buffer */
546 struct strpush *strpush; /* for pushing strings at this level */
547 struct strpush basestrpush; /* so pushing one is fast */
550 static struct parsefile basepf; /* top level input file */
551 #define basebuf bb_common_bufsiz1 /* buffer for top level input file */
552 static struct parsefile *parsefile = &basepf; /* current input file */
555 static int tokpushback; /* last token pushed back */
556 #define NEOF ((union node *)&tokpushback)
557 static int parsebackquote; /* nonzero if we are inside backquotes */
558 static int doprompt; /* if set, prompt the user */
559 static int needprompt; /* true if interactive and at start of line */
560 static int lasttoken; /* last token read */
561 static char *wordtext; /* text of last word returned by readtoken */
563 static struct nodelist *backquotelist;
564 static union node *redirnode;
565 static struct heredoc *heredoc;
566 static int quoteflag; /* set if (part of) last token was quoted */
567 static int startlinno; /* line # where last token started */
569 static union node *parsecmd(int);
570 static void fixredir(union node *, const char *, int);
571 static const char *const *findkwd(const char *);
572 static char *endofname(const char *);
576 typedef void *pointer;
578 static char nullstr[1]; /* zero length string */
579 static const char spcstr[] = " ";
580 static const char snlfmt[] = "%s\n";
581 static const char dolatstr[] = { CTLVAR, VSNORMAL|VSQUOTE, '@', '=', '\0' };
582 static const char illnum[] = "Illegal number: %s";
583 static const char homestr[] = "HOME";
586 #define TRACE(param) trace param
587 #define TRACEV(param) tracev param
590 #define TRACEV(param)
593 #if !defined(__GNUC__) || (__GNUC__ == 2 && __GNUC_MINOR__ < 96)
594 #define __builtin_expect(x, expected_value) (x)
597 #define xlikely(x) __builtin_expect((x),1)
612 #define TENDBQUOTE 12
630 /* first char is indicating which tokens mark the end of a list */
631 static const char *const tokname_array[] = {
646 /* the following are keywords */
665 static const char *tokname(int tok)
671 sprintf(buf + (tok >= TSEMI), "%s%c",
672 tokname_array[tok] + 1, (tok >= TSEMI ? '"' : 0));
679 * Most machines require the value returned from malloc to be aligned
680 * in some way. The following macro will get this right on many machines.
683 #define SHELL_SIZE (sizeof(union {int i; char *cp; double d; }) - 1)
685 * It appears that grabstackstr() will barf with such alignments
686 * because stalloc() will return a string allocated in a new stackblock.
688 #define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE)
691 * This file was generated by the mksyntax program.
696 #define CWORD 0 /* character is nothing special */
697 #define CNL 1 /* newline character */
698 #define CBACK 2 /* a backslash character */
699 #define CSQUOTE 3 /* single quote */
700 #define CDQUOTE 4 /* double quote */
701 #define CENDQUOTE 5 /* a terminating quote */
702 #define CBQUOTE 6 /* backwards single quote */
703 #define CVAR 7 /* a dollar sign */
704 #define CENDVAR 8 /* a '}' character */
705 #define CLP 9 /* a left paren in arithmetic */
706 #define CRP 10 /* a right paren in arithmetic */
707 #define CENDFILE 11 /* end of file */
708 #define CCTL 12 /* like CWORD, except it must be escaped */
709 #define CSPCL 13 /* these terminate a word */
710 #define CIGN 14 /* character should be ignored */
712 #ifdef CONFIG_ASH_ALIAS
716 #define PEOA_OR_PEOF PEOA
720 #define PEOA_OR_PEOF PEOF
723 #define is_digit(c) ((unsigned)((c) - '0') <= 9)
724 #define is_name(c) ((c) == '_' || isalpha((unsigned char)(c)))
725 #define is_in_name(c) ((c) == '_' || isalnum((unsigned char)(c)))
727 /* C99 say: "char" declaration may be signed or unsigned default */
728 #define SC2INT(chr2may_be_negative_int) (int)((signed char)chr2may_be_negative_int)
731 * is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
732 * (assuming ascii char codes, as the original implementation did)
734 #define is_special(c) \
735 ( (((unsigned int)c) - 33 < 32) \
736 && ((0xc1ff920dUL >> (((unsigned int)c) - 33)) & 1))
738 #define digit_val(c) ((c) - '0')
741 * This file was generated by the mksyntax program.
744 #ifdef CONFIG_ASH_OPTIMIZE_FOR_SIZE
745 #define USE_SIT_FUNCTION
748 /* number syntax index */
749 #define BASESYNTAX 0 /* not in quotes */
750 #define DQSYNTAX 1 /* in double quotes */
751 #define SQSYNTAX 2 /* in single quotes */
752 #define ARISYNTAX 3 /* in arithmetic */
754 #ifdef CONFIG_ASH_MATH_SUPPORT
755 static const char S_I_T[][4] = {
756 #ifdef CONFIG_ASH_ALIAS
757 {CSPCL, CIGN, CIGN, CIGN}, /* 0, PEOA */
759 {CSPCL, CWORD, CWORD, CWORD}, /* 1, ' ' */
760 {CNL, CNL, CNL, CNL}, /* 2, \n */
761 {CWORD, CCTL, CCTL, CWORD}, /* 3, !*-/:=?[]~ */
762 {CDQUOTE, CENDQUOTE, CWORD, CWORD}, /* 4, '"' */
763 {CVAR, CVAR, CWORD, CVAR}, /* 5, $ */
764 {CSQUOTE, CWORD, CENDQUOTE, CWORD}, /* 6, "'" */
765 {CSPCL, CWORD, CWORD, CLP}, /* 7, ( */
766 {CSPCL, CWORD, CWORD, CRP}, /* 8, ) */
767 {CBACK, CBACK, CCTL, CBACK}, /* 9, \ */
768 {CBQUOTE, CBQUOTE, CWORD, CBQUOTE}, /* 10, ` */
769 {CENDVAR, CENDVAR, CWORD, CENDVAR}, /* 11, } */
770 #ifndef USE_SIT_FUNCTION
771 {CENDFILE, CENDFILE, CENDFILE, CENDFILE}, /* 12, PEOF */
772 {CWORD, CWORD, CWORD, CWORD}, /* 13, 0-9A-Za-z */
773 {CCTL, CCTL, CCTL, CCTL} /* 14, CTLESC ... */
777 static const char S_I_T[][3] = {
778 #ifdef CONFIG_ASH_ALIAS
779 {CSPCL, CIGN, CIGN}, /* 0, PEOA */
781 {CSPCL, CWORD, CWORD}, /* 1, ' ' */
782 {CNL, CNL, CNL}, /* 2, \n */
783 {CWORD, CCTL, CCTL}, /* 3, !*-/:=?[]~ */
784 {CDQUOTE, CENDQUOTE, CWORD}, /* 4, '"' */
785 {CVAR, CVAR, CWORD}, /* 5, $ */
786 {CSQUOTE, CWORD, CENDQUOTE}, /* 6, "'" */
787 {CSPCL, CWORD, CWORD}, /* 7, ( */
788 {CSPCL, CWORD, CWORD}, /* 8, ) */
789 {CBACK, CBACK, CCTL}, /* 9, \ */
790 {CBQUOTE, CBQUOTE, CWORD}, /* 10, ` */
791 {CENDVAR, CENDVAR, CWORD}, /* 11, } */
792 #ifndef USE_SIT_FUNCTION
793 {CENDFILE, CENDFILE, CENDFILE}, /* 12, PEOF */
794 {CWORD, CWORD, CWORD}, /* 13, 0-9A-Za-z */
795 {CCTL, CCTL, CCTL} /* 14, CTLESC ... */
798 #endif /* CONFIG_ASH_MATH_SUPPORT */
800 #ifdef USE_SIT_FUNCTION
802 #define U_C(c) ((unsigned char)(c))
804 static int SIT(int c, int syntax)
806 static const char spec_symbls[] = "\t\n !\"$&'()*-/:;<=>?[\\]`|}~";
807 #ifdef CONFIG_ASH_ALIAS
808 static const char syntax_index_table[] = {
809 1, 2, 1, 3, 4, 5, 1, 6, /* "\t\n !\"$&'" */
810 7, 8, 3, 3, 3, 3, 1, 1, /* "()*-/:;<" */
811 3, 1, 3, 3, 9, 3, 10, 1, /* "=>?[\\]`|" */
815 static const char syntax_index_table[] = {
816 0, 1, 0, 2, 3, 4, 0, 5, /* "\t\n !\"$&'" */
817 6, 7, 2, 2, 2, 2, 0, 0, /* "()*-/:;<" */
818 2, 0, 2, 2, 8, 2, 9, 0, /* "=>?[\\]`|" */
825 if (c == PEOF) /* 2^8+2 */
827 #ifdef CONFIG_ASH_ALIAS
828 if (c == PEOA) /* 2^8+1 */
832 if (U_C(c) >= U_C(CTLESC) && U_C(c) <= U_C(CTLQUOTEMARK))
835 s = strchr(spec_symbls, c);
836 if (s == 0 || *s == 0)
838 indx = syntax_index_table[(s - spec_symbls)];
840 return S_I_T[indx][syntax];
843 #else /* USE_SIT_FUNCTION */
845 #define SIT(c, syntax) S_I_T[(int)syntax_index_table[((int)c)+SYNBASE]][syntax]
847 #ifdef CONFIG_ASH_ALIAS
848 #define CSPCL_CIGN_CIGN_CIGN 0
849 #define CSPCL_CWORD_CWORD_CWORD 1
850 #define CNL_CNL_CNL_CNL 2
851 #define CWORD_CCTL_CCTL_CWORD 3
852 #define CDQUOTE_CENDQUOTE_CWORD_CWORD 4
853 #define CVAR_CVAR_CWORD_CVAR 5
854 #define CSQUOTE_CWORD_CENDQUOTE_CWORD 6
855 #define CSPCL_CWORD_CWORD_CLP 7
856 #define CSPCL_CWORD_CWORD_CRP 8
857 #define CBACK_CBACK_CCTL_CBACK 9
858 #define CBQUOTE_CBQUOTE_CWORD_CBQUOTE 10
859 #define CENDVAR_CENDVAR_CWORD_CENDVAR 11
860 #define CENDFILE_CENDFILE_CENDFILE_CENDFILE 12
861 #define CWORD_CWORD_CWORD_CWORD 13
862 #define CCTL_CCTL_CCTL_CCTL 14
864 #define CSPCL_CWORD_CWORD_CWORD 0
865 #define CNL_CNL_CNL_CNL 1
866 #define CWORD_CCTL_CCTL_CWORD 2
867 #define CDQUOTE_CENDQUOTE_CWORD_CWORD 3
868 #define CVAR_CVAR_CWORD_CVAR 4
869 #define CSQUOTE_CWORD_CENDQUOTE_CWORD 5
870 #define CSPCL_CWORD_CWORD_CLP 6
871 #define CSPCL_CWORD_CWORD_CRP 7
872 #define CBACK_CBACK_CCTL_CBACK 8
873 #define CBQUOTE_CBQUOTE_CWORD_CBQUOTE 9
874 #define CENDVAR_CENDVAR_CWORD_CENDVAR 10
875 #define CENDFILE_CENDFILE_CENDFILE_CENDFILE 11
876 #define CWORD_CWORD_CWORD_CWORD 12
877 #define CCTL_CCTL_CCTL_CCTL 13
880 static const char syntax_index_table[258] = {
881 /* BASESYNTAX_DQSYNTAX_SQSYNTAX_ARISYNTAX */
882 /* 0 PEOF */ CENDFILE_CENDFILE_CENDFILE_CENDFILE,
883 #ifdef CONFIG_ASH_ALIAS
884 /* 1 PEOA */ CSPCL_CIGN_CIGN_CIGN,
886 /* 2 -128 0x80 */ CWORD_CWORD_CWORD_CWORD,
887 /* 3 -127 CTLESC */ CCTL_CCTL_CCTL_CCTL,
888 /* 4 -126 CTLVAR */ CCTL_CCTL_CCTL_CCTL,
889 /* 5 -125 CTLENDVAR */ CCTL_CCTL_CCTL_CCTL,
890 /* 6 -124 CTLBACKQ */ CCTL_CCTL_CCTL_CCTL,
891 /* 7 -123 CTLQUOTE */ CCTL_CCTL_CCTL_CCTL,
892 /* 8 -122 CTLARI */ CCTL_CCTL_CCTL_CCTL,
893 /* 9 -121 CTLENDARI */ CCTL_CCTL_CCTL_CCTL,
894 /* 10 -120 CTLQUOTEMARK */ CCTL_CCTL_CCTL_CCTL,
895 /* 11 -119 */ CWORD_CWORD_CWORD_CWORD,
896 /* 12 -118 */ CWORD_CWORD_CWORD_CWORD,
897 /* 13 -117 */ CWORD_CWORD_CWORD_CWORD,
898 /* 14 -116 */ CWORD_CWORD_CWORD_CWORD,
899 /* 15 -115 */ CWORD_CWORD_CWORD_CWORD,
900 /* 16 -114 */ CWORD_CWORD_CWORD_CWORD,
901 /* 17 -113 */ CWORD_CWORD_CWORD_CWORD,
902 /* 18 -112 */ CWORD_CWORD_CWORD_CWORD,
903 /* 19 -111 */ CWORD_CWORD_CWORD_CWORD,
904 /* 20 -110 */ CWORD_CWORD_CWORD_CWORD,
905 /* 21 -109 */ CWORD_CWORD_CWORD_CWORD,
906 /* 22 -108 */ CWORD_CWORD_CWORD_CWORD,
907 /* 23 -107 */ CWORD_CWORD_CWORD_CWORD,
908 /* 24 -106 */ CWORD_CWORD_CWORD_CWORD,
909 /* 25 -105 */ CWORD_CWORD_CWORD_CWORD,
910 /* 26 -104 */ CWORD_CWORD_CWORD_CWORD,
911 /* 27 -103 */ CWORD_CWORD_CWORD_CWORD,
912 /* 28 -102 */ CWORD_CWORD_CWORD_CWORD,
913 /* 29 -101 */ CWORD_CWORD_CWORD_CWORD,
914 /* 30 -100 */ CWORD_CWORD_CWORD_CWORD,
915 /* 31 -99 */ CWORD_CWORD_CWORD_CWORD,
916 /* 32 -98 */ CWORD_CWORD_CWORD_CWORD,
917 /* 33 -97 */ CWORD_CWORD_CWORD_CWORD,
918 /* 34 -96 */ CWORD_CWORD_CWORD_CWORD,
919 /* 35 -95 */ CWORD_CWORD_CWORD_CWORD,
920 /* 36 -94 */ CWORD_CWORD_CWORD_CWORD,
921 /* 37 -93 */ CWORD_CWORD_CWORD_CWORD,
922 /* 38 -92 */ CWORD_CWORD_CWORD_CWORD,
923 /* 39 -91 */ CWORD_CWORD_CWORD_CWORD,
924 /* 40 -90 */ CWORD_CWORD_CWORD_CWORD,
925 /* 41 -89 */ CWORD_CWORD_CWORD_CWORD,
926 /* 42 -88 */ CWORD_CWORD_CWORD_CWORD,
927 /* 43 -87 */ CWORD_CWORD_CWORD_CWORD,
928 /* 44 -86 */ CWORD_CWORD_CWORD_CWORD,
929 /* 45 -85 */ CWORD_CWORD_CWORD_CWORD,
930 /* 46 -84 */ CWORD_CWORD_CWORD_CWORD,
931 /* 47 -83 */ CWORD_CWORD_CWORD_CWORD,
932 /* 48 -82 */ CWORD_CWORD_CWORD_CWORD,
933 /* 49 -81 */ CWORD_CWORD_CWORD_CWORD,
934 /* 50 -80 */ CWORD_CWORD_CWORD_CWORD,
935 /* 51 -79 */ CWORD_CWORD_CWORD_CWORD,
936 /* 52 -78 */ CWORD_CWORD_CWORD_CWORD,
937 /* 53 -77 */ CWORD_CWORD_CWORD_CWORD,
938 /* 54 -76 */ CWORD_CWORD_CWORD_CWORD,
939 /* 55 -75 */ CWORD_CWORD_CWORD_CWORD,
940 /* 56 -74 */ CWORD_CWORD_CWORD_CWORD,
941 /* 57 -73 */ CWORD_CWORD_CWORD_CWORD,
942 /* 58 -72 */ CWORD_CWORD_CWORD_CWORD,
943 /* 59 -71 */ CWORD_CWORD_CWORD_CWORD,
944 /* 60 -70 */ CWORD_CWORD_CWORD_CWORD,
945 /* 61 -69 */ CWORD_CWORD_CWORD_CWORD,
946 /* 62 -68 */ CWORD_CWORD_CWORD_CWORD,
947 /* 63 -67 */ CWORD_CWORD_CWORD_CWORD,
948 /* 64 -66 */ CWORD_CWORD_CWORD_CWORD,
949 /* 65 -65 */ CWORD_CWORD_CWORD_CWORD,
950 /* 66 -64 */ CWORD_CWORD_CWORD_CWORD,
951 /* 67 -63 */ CWORD_CWORD_CWORD_CWORD,
952 /* 68 -62 */ CWORD_CWORD_CWORD_CWORD,
953 /* 69 -61 */ CWORD_CWORD_CWORD_CWORD,
954 /* 70 -60 */ CWORD_CWORD_CWORD_CWORD,
955 /* 71 -59 */ CWORD_CWORD_CWORD_CWORD,
956 /* 72 -58 */ CWORD_CWORD_CWORD_CWORD,
957 /* 73 -57 */ CWORD_CWORD_CWORD_CWORD,
958 /* 74 -56 */ CWORD_CWORD_CWORD_CWORD,
959 /* 75 -55 */ CWORD_CWORD_CWORD_CWORD,
960 /* 76 -54 */ CWORD_CWORD_CWORD_CWORD,
961 /* 77 -53 */ CWORD_CWORD_CWORD_CWORD,
962 /* 78 -52 */ CWORD_CWORD_CWORD_CWORD,
963 /* 79 -51 */ CWORD_CWORD_CWORD_CWORD,
964 /* 80 -50 */ CWORD_CWORD_CWORD_CWORD,
965 /* 81 -49 */ CWORD_CWORD_CWORD_CWORD,
966 /* 82 -48 */ CWORD_CWORD_CWORD_CWORD,
967 /* 83 -47 */ CWORD_CWORD_CWORD_CWORD,
968 /* 84 -46 */ CWORD_CWORD_CWORD_CWORD,
969 /* 85 -45 */ CWORD_CWORD_CWORD_CWORD,
970 /* 86 -44 */ CWORD_CWORD_CWORD_CWORD,
971 /* 87 -43 */ CWORD_CWORD_CWORD_CWORD,
972 /* 88 -42 */ CWORD_CWORD_CWORD_CWORD,
973 /* 89 -41 */ CWORD_CWORD_CWORD_CWORD,
974 /* 90 -40 */ CWORD_CWORD_CWORD_CWORD,
975 /* 91 -39 */ CWORD_CWORD_CWORD_CWORD,
976 /* 92 -38 */ CWORD_CWORD_CWORD_CWORD,
977 /* 93 -37 */ CWORD_CWORD_CWORD_CWORD,
978 /* 94 -36 */ CWORD_CWORD_CWORD_CWORD,
979 /* 95 -35 */ CWORD_CWORD_CWORD_CWORD,
980 /* 96 -34 */ CWORD_CWORD_CWORD_CWORD,
981 /* 97 -33 */ CWORD_CWORD_CWORD_CWORD,
982 /* 98 -32 */ CWORD_CWORD_CWORD_CWORD,
983 /* 99 -31 */ CWORD_CWORD_CWORD_CWORD,
984 /* 100 -30 */ CWORD_CWORD_CWORD_CWORD,
985 /* 101 -29 */ CWORD_CWORD_CWORD_CWORD,
986 /* 102 -28 */ CWORD_CWORD_CWORD_CWORD,
987 /* 103 -27 */ CWORD_CWORD_CWORD_CWORD,
988 /* 104 -26 */ CWORD_CWORD_CWORD_CWORD,
989 /* 105 -25 */ CWORD_CWORD_CWORD_CWORD,
990 /* 106 -24 */ CWORD_CWORD_CWORD_CWORD,
991 /* 107 -23 */ CWORD_CWORD_CWORD_CWORD,
992 /* 108 -22 */ CWORD_CWORD_CWORD_CWORD,
993 /* 109 -21 */ CWORD_CWORD_CWORD_CWORD,
994 /* 110 -20 */ CWORD_CWORD_CWORD_CWORD,
995 /* 111 -19 */ CWORD_CWORD_CWORD_CWORD,
996 /* 112 -18 */ CWORD_CWORD_CWORD_CWORD,
997 /* 113 -17 */ CWORD_CWORD_CWORD_CWORD,
998 /* 114 -16 */ CWORD_CWORD_CWORD_CWORD,
999 /* 115 -15 */ CWORD_CWORD_CWORD_CWORD,
1000 /* 116 -14 */ CWORD_CWORD_CWORD_CWORD,
1001 /* 117 -13 */ CWORD_CWORD_CWORD_CWORD,
1002 /* 118 -12 */ CWORD_CWORD_CWORD_CWORD,
1003 /* 119 -11 */ CWORD_CWORD_CWORD_CWORD,
1004 /* 120 -10 */ CWORD_CWORD_CWORD_CWORD,
1005 /* 121 -9 */ CWORD_CWORD_CWORD_CWORD,
1006 /* 122 -8 */ CWORD_CWORD_CWORD_CWORD,
1007 /* 123 -7 */ CWORD_CWORD_CWORD_CWORD,
1008 /* 124 -6 */ CWORD_CWORD_CWORD_CWORD,
1009 /* 125 -5 */ CWORD_CWORD_CWORD_CWORD,
1010 /* 126 -4 */ CWORD_CWORD_CWORD_CWORD,
1011 /* 127 -3 */ CWORD_CWORD_CWORD_CWORD,
1012 /* 128 -2 */ CWORD_CWORD_CWORD_CWORD,
1013 /* 129 -1 */ CWORD_CWORD_CWORD_CWORD,
1014 /* 130 0 */ CWORD_CWORD_CWORD_CWORD,
1015 /* 131 1 */ CWORD_CWORD_CWORD_CWORD,
1016 /* 132 2 */ CWORD_CWORD_CWORD_CWORD,
1017 /* 133 3 */ CWORD_CWORD_CWORD_CWORD,
1018 /* 134 4 */ CWORD_CWORD_CWORD_CWORD,
1019 /* 135 5 */ CWORD_CWORD_CWORD_CWORD,
1020 /* 136 6 */ CWORD_CWORD_CWORD_CWORD,
1021 /* 137 7 */ CWORD_CWORD_CWORD_CWORD,
1022 /* 138 8 */ CWORD_CWORD_CWORD_CWORD,
1023 /* 139 9 "\t" */ CSPCL_CWORD_CWORD_CWORD,
1024 /* 140 10 "\n" */ CNL_CNL_CNL_CNL,
1025 /* 141 11 */ CWORD_CWORD_CWORD_CWORD,
1026 /* 142 12 */ CWORD_CWORD_CWORD_CWORD,
1027 /* 143 13 */ CWORD_CWORD_CWORD_CWORD,
1028 /* 144 14 */ CWORD_CWORD_CWORD_CWORD,
1029 /* 145 15 */ CWORD_CWORD_CWORD_CWORD,
1030 /* 146 16 */ CWORD_CWORD_CWORD_CWORD,
1031 /* 147 17 */ CWORD_CWORD_CWORD_CWORD,
1032 /* 148 18 */ CWORD_CWORD_CWORD_CWORD,
1033 /* 149 19 */ CWORD_CWORD_CWORD_CWORD,
1034 /* 150 20 */ CWORD_CWORD_CWORD_CWORD,
1035 /* 151 21 */ CWORD_CWORD_CWORD_CWORD,
1036 /* 152 22 */ CWORD_CWORD_CWORD_CWORD,
1037 /* 153 23 */ CWORD_CWORD_CWORD_CWORD,
1038 /* 154 24 */ CWORD_CWORD_CWORD_CWORD,
1039 /* 155 25 */ CWORD_CWORD_CWORD_CWORD,
1040 /* 156 26 */ CWORD_CWORD_CWORD_CWORD,
1041 /* 157 27 */ CWORD_CWORD_CWORD_CWORD,
1042 /* 158 28 */ CWORD_CWORD_CWORD_CWORD,
1043 /* 159 29 */ CWORD_CWORD_CWORD_CWORD,
1044 /* 160 30 */ CWORD_CWORD_CWORD_CWORD,
1045 /* 161 31 */ CWORD_CWORD_CWORD_CWORD,
1046 /* 162 32 " " */ CSPCL_CWORD_CWORD_CWORD,
1047 /* 163 33 "!" */ CWORD_CCTL_CCTL_CWORD,
1048 /* 164 34 """ */ CDQUOTE_CENDQUOTE_CWORD_CWORD,
1049 /* 165 35 "#" */ CWORD_CWORD_CWORD_CWORD,
1050 /* 166 36 "$" */ CVAR_CVAR_CWORD_CVAR,
1051 /* 167 37 "%" */ CWORD_CWORD_CWORD_CWORD,
1052 /* 168 38 "&" */ CSPCL_CWORD_CWORD_CWORD,
1053 /* 169 39 "'" */ CSQUOTE_CWORD_CENDQUOTE_CWORD,
1054 /* 170 40 "(" */ CSPCL_CWORD_CWORD_CLP,
1055 /* 171 41 ")" */ CSPCL_CWORD_CWORD_CRP,
1056 /* 172 42 "*" */ CWORD_CCTL_CCTL_CWORD,
1057 /* 173 43 "+" */ CWORD_CWORD_CWORD_CWORD,
1058 /* 174 44 "," */ CWORD_CWORD_CWORD_CWORD,
1059 /* 175 45 "-" */ CWORD_CCTL_CCTL_CWORD,
1060 /* 176 46 "." */ CWORD_CWORD_CWORD_CWORD,
1061 /* 177 47 "/" */ CWORD_CCTL_CCTL_CWORD,
1062 /* 178 48 "0" */ CWORD_CWORD_CWORD_CWORD,
1063 /* 179 49 "1" */ CWORD_CWORD_CWORD_CWORD,
1064 /* 180 50 "2" */ CWORD_CWORD_CWORD_CWORD,
1065 /* 181 51 "3" */ CWORD_CWORD_CWORD_CWORD,
1066 /* 182 52 "4" */ CWORD_CWORD_CWORD_CWORD,
1067 /* 183 53 "5" */ CWORD_CWORD_CWORD_CWORD,
1068 /* 184 54 "6" */ CWORD_CWORD_CWORD_CWORD,
1069 /* 185 55 "7" */ CWORD_CWORD_CWORD_CWORD,
1070 /* 186 56 "8" */ CWORD_CWORD_CWORD_CWORD,
1071 /* 187 57 "9" */ CWORD_CWORD_CWORD_CWORD,
1072 /* 188 58 ":" */ CWORD_CCTL_CCTL_CWORD,
1073 /* 189 59 ";" */ CSPCL_CWORD_CWORD_CWORD,
1074 /* 190 60 "<" */ CSPCL_CWORD_CWORD_CWORD,
1075 /* 191 61 "=" */ CWORD_CCTL_CCTL_CWORD,
1076 /* 192 62 ">" */ CSPCL_CWORD_CWORD_CWORD,
1077 /* 193 63 "?" */ CWORD_CCTL_CCTL_CWORD,
1078 /* 194 64 "@" */ CWORD_CWORD_CWORD_CWORD,
1079 /* 195 65 "A" */ CWORD_CWORD_CWORD_CWORD,
1080 /* 196 66 "B" */ CWORD_CWORD_CWORD_CWORD,
1081 /* 197 67 "C" */ CWORD_CWORD_CWORD_CWORD,
1082 /* 198 68 "D" */ CWORD_CWORD_CWORD_CWORD,
1083 /* 199 69 "E" */ CWORD_CWORD_CWORD_CWORD,
1084 /* 200 70 "F" */ CWORD_CWORD_CWORD_CWORD,
1085 /* 201 71 "G" */ CWORD_CWORD_CWORD_CWORD,
1086 /* 202 72 "H" */ CWORD_CWORD_CWORD_CWORD,
1087 /* 203 73 "I" */ CWORD_CWORD_CWORD_CWORD,
1088 /* 204 74 "J" */ CWORD_CWORD_CWORD_CWORD,
1089 /* 205 75 "K" */ CWORD_CWORD_CWORD_CWORD,
1090 /* 206 76 "L" */ CWORD_CWORD_CWORD_CWORD,
1091 /* 207 77 "M" */ CWORD_CWORD_CWORD_CWORD,
1092 /* 208 78 "N" */ CWORD_CWORD_CWORD_CWORD,
1093 /* 209 79 "O" */ CWORD_CWORD_CWORD_CWORD,
1094 /* 210 80 "P" */ CWORD_CWORD_CWORD_CWORD,
1095 /* 211 81 "Q" */ CWORD_CWORD_CWORD_CWORD,
1096 /* 212 82 "R" */ CWORD_CWORD_CWORD_CWORD,
1097 /* 213 83 "S" */ CWORD_CWORD_CWORD_CWORD,
1098 /* 214 84 "T" */ CWORD_CWORD_CWORD_CWORD,
1099 /* 215 85 "U" */ CWORD_CWORD_CWORD_CWORD,
1100 /* 216 86 "V" */ CWORD_CWORD_CWORD_CWORD,
1101 /* 217 87 "W" */ CWORD_CWORD_CWORD_CWORD,
1102 /* 218 88 "X" */ CWORD_CWORD_CWORD_CWORD,
1103 /* 219 89 "Y" */ CWORD_CWORD_CWORD_CWORD,
1104 /* 220 90 "Z" */ CWORD_CWORD_CWORD_CWORD,
1105 /* 221 91 "[" */ CWORD_CCTL_CCTL_CWORD,
1106 /* 222 92 "\" */ CBACK_CBACK_CCTL_CBACK,
1107 /* 223 93 "]" */ CWORD_CCTL_CCTL_CWORD,
1108 /* 224 94 "^" */ CWORD_CWORD_CWORD_CWORD,
1109 /* 225 95 "_" */ CWORD_CWORD_CWORD_CWORD,
1110 /* 226 96 "`" */ CBQUOTE_CBQUOTE_CWORD_CBQUOTE,
1111 /* 227 97 "a" */ CWORD_CWORD_CWORD_CWORD,
1112 /* 228 98 "b" */ CWORD_CWORD_CWORD_CWORD,
1113 /* 229 99 "c" */ CWORD_CWORD_CWORD_CWORD,
1114 /* 230 100 "d" */ CWORD_CWORD_CWORD_CWORD,
1115 /* 231 101 "e" */ CWORD_CWORD_CWORD_CWORD,
1116 /* 232 102 "f" */ CWORD_CWORD_CWORD_CWORD,
1117 /* 233 103 "g" */ CWORD_CWORD_CWORD_CWORD,
1118 /* 234 104 "h" */ CWORD_CWORD_CWORD_CWORD,
1119 /* 235 105 "i" */ CWORD_CWORD_CWORD_CWORD,
1120 /* 236 106 "j" */ CWORD_CWORD_CWORD_CWORD,
1121 /* 237 107 "k" */ CWORD_CWORD_CWORD_CWORD,
1122 /* 238 108 "l" */ CWORD_CWORD_CWORD_CWORD,
1123 /* 239 109 "m" */ CWORD_CWORD_CWORD_CWORD,
1124 /* 240 110 "n" */ CWORD_CWORD_CWORD_CWORD,
1125 /* 241 111 "o" */ CWORD_CWORD_CWORD_CWORD,
1126 /* 242 112 "p" */ CWORD_CWORD_CWORD_CWORD,
1127 /* 243 113 "q" */ CWORD_CWORD_CWORD_CWORD,
1128 /* 244 114 "r" */ CWORD_CWORD_CWORD_CWORD,
1129 /* 245 115 "s" */ CWORD_CWORD_CWORD_CWORD,
1130 /* 246 116 "t" */ CWORD_CWORD_CWORD_CWORD,
1131 /* 247 117 "u" */ CWORD_CWORD_CWORD_CWORD,
1132 /* 248 118 "v" */ CWORD_CWORD_CWORD_CWORD,
1133 /* 249 119 "w" */ CWORD_CWORD_CWORD_CWORD,
1134 /* 250 120 "x" */ CWORD_CWORD_CWORD_CWORD,
1135 /* 251 121 "y" */ CWORD_CWORD_CWORD_CWORD,
1136 /* 252 122 "z" */ CWORD_CWORD_CWORD_CWORD,
1137 /* 253 123 "{" */ CWORD_CWORD_CWORD_CWORD,
1138 /* 254 124 "|" */ CSPCL_CWORD_CWORD_CWORD,
1139 /* 255 125 "}" */ CENDVAR_CENDVAR_CWORD_CENDVAR,
1140 /* 256 126 "~" */ CWORD_CCTL_CCTL_CWORD,
1141 /* 257 127 */ CWORD_CWORD_CWORD_CWORD,
1144 #endif /* USE_SIT_FUNCTION */
1151 static int funcblocksize; /* size of structures in function */
1152 static int funcstringsize; /* size of strings in node */
1153 static pointer funcblock; /* block to allocate function from */
1154 static char *funcstring; /* block to allocate strings from */
1156 static const short nodesize[26] = {
1157 SHELL_ALIGN(sizeof (struct ncmd)),
1158 SHELL_ALIGN(sizeof (struct npipe)),
1159 SHELL_ALIGN(sizeof (struct nredir)),
1160 SHELL_ALIGN(sizeof (struct nredir)),
1161 SHELL_ALIGN(sizeof (struct nredir)),
1162 SHELL_ALIGN(sizeof (struct nbinary)),
1163 SHELL_ALIGN(sizeof (struct nbinary)),
1164 SHELL_ALIGN(sizeof (struct nbinary)),
1165 SHELL_ALIGN(sizeof (struct nif)),
1166 SHELL_ALIGN(sizeof (struct nbinary)),
1167 SHELL_ALIGN(sizeof (struct nbinary)),
1168 SHELL_ALIGN(sizeof (struct nfor)),
1169 SHELL_ALIGN(sizeof (struct ncase)),
1170 SHELL_ALIGN(sizeof (struct nclist)),
1171 SHELL_ALIGN(sizeof (struct narg)),
1172 SHELL_ALIGN(sizeof (struct narg)),
1173 SHELL_ALIGN(sizeof (struct nfile)),
1174 SHELL_ALIGN(sizeof (struct nfile)),
1175 SHELL_ALIGN(sizeof (struct nfile)),
1176 SHELL_ALIGN(sizeof (struct nfile)),
1177 SHELL_ALIGN(sizeof (struct nfile)),
1178 SHELL_ALIGN(sizeof (struct ndup)),
1179 SHELL_ALIGN(sizeof (struct ndup)),
1180 SHELL_ALIGN(sizeof (struct nhere)),
1181 SHELL_ALIGN(sizeof (struct nhere)),
1182 SHELL_ALIGN(sizeof (struct nnot)),
1186 static void calcsize(union node *);
1187 static void sizenodelist(struct nodelist *);
1188 static union node *copynode(union node *);
1189 static struct nodelist *copynodelist(struct nodelist *);
1190 static char *nodesavestr(char *);
1193 static int evalstring(char *, int mask);
1194 union node; /* BLETCH for ansi C */
1195 static void evaltree(union node *, int);
1196 static void evalbackcmd(union node *, struct backcmd *);
1198 static int evalskip; /* set if we are skipping commands */
1199 static int skipcount; /* number of levels to skip */
1200 static int funcnest; /* depth of function calls */
1202 /* reasons for skipping commands (see comment on breakcmd routine) */
1203 #define SKIPBREAK (1 << 0)
1204 #define SKIPCONT (1 << 1)
1205 #define SKIPFUNC (1 << 2)
1206 #define SKIPFILE (1 << 3)
1207 #define SKIPEVAL (1 << 4)
1210 * This file was generated by the mkbuiltins program.
1214 static int bgcmd(int, char **);
1216 static int breakcmd(int, char **);
1217 static int cdcmd(int, char **);
1218 #ifdef CONFIG_ASH_CMDCMD
1219 static int commandcmd(int, char **);
1221 static int dotcmd(int, char **);
1222 static int evalcmd(int, char **);
1223 #ifdef CONFIG_ASH_BUILTIN_ECHO
1224 static int echocmd(int, char **);
1226 #ifdef CONFIG_ASH_BUILTIN_TEST
1227 static int testcmd(int, char **);
1229 static int execcmd(int, char **);
1230 static int exitcmd(int, char **);
1231 static int exportcmd(int, char **);
1232 static int falsecmd(int, char **);
1234 static int fgcmd(int, char **);
1236 #ifdef CONFIG_ASH_GETOPTS
1237 static int getoptscmd(int, char **);
1239 static int hashcmd(int, char **);
1240 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
1241 static int helpcmd(int argc, char **argv);
1244 static int jobscmd(int, char **);
1246 #ifdef CONFIG_ASH_MATH_SUPPORT
1247 static int letcmd(int, char **);
1249 static int localcmd(int, char **);
1250 static int pwdcmd(int, char **);
1251 static int readcmd(int, char **);
1252 static int returncmd(int, char **);
1253 static int setcmd(int, char **);
1254 static int shiftcmd(int, char **);
1255 static int timescmd(int, char **);
1256 static int trapcmd(int, char **);
1257 static int truecmd(int, char **);
1258 static int typecmd(int, char **);
1259 static int umaskcmd(int, char **);
1260 static int unsetcmd(int, char **);
1261 static int waitcmd(int, char **);
1262 static int ulimitcmd(int, char **);
1264 static int killcmd(int, char **);
1269 #ifdef CONFIG_ASH_MAIL
1270 static void chkmail(void);
1271 static void changemail(const char *);
1276 /* values of cmdtype */
1277 #define CMDUNKNOWN -1 /* no entry in table for command */
1278 #define CMDNORMAL 0 /* command is an executable program */
1279 #define CMDFUNCTION 1 /* command is a shell function */
1280 #define CMDBUILTIN 2 /* command is a shell builtin */
1284 int (*builtin)(int, char **);
1285 /* unsigned flags; */
1289 #define COMMANDCMD (builtincmd + 5 + \
1290 2 * ENABLE_ASH_BUILTIN_TEST + \
1291 ENABLE_ASH_ALIAS + \
1292 ENABLE_ASH_JOB_CONTROL)
1293 #define EXECCMD (builtincmd + 7 + \
1294 2 * ENABLE_ASH_BUILTIN_TEST + \
1295 ENABLE_ASH_ALIAS + \
1296 ENABLE_ASH_JOB_CONTROL + \
1297 ENABLE_ASH_CMDCMD + \
1298 ENABLE_ASH_BUILTIN_ECHO)
1300 #define BUILTIN_NOSPEC "0"
1301 #define BUILTIN_SPECIAL "1"
1302 #define BUILTIN_REGULAR "2"
1303 #define BUILTIN_SPEC_REG "3"
1304 #define BUILTIN_ASSIGN "4"
1305 #define BUILTIN_SPEC_ASSG "5"
1306 #define BUILTIN_REG_ASSG "6"
1307 #define BUILTIN_SPEC_REG_ASSG "7"
1309 #define IS_BUILTIN_SPECIAL(builtincmd) ((builtincmd)->name[0] & 1)
1310 #define IS_BUILTIN_REGULAR(builtincmd) ((builtincmd)->name[0] & 2)
1311 #define IS_BUILTIN_ASSIGN(builtincmd) ((builtincmd)->name[0] & 4)
1313 /* make sure to keep these in proper order since it is searched via bsearch() */
1314 static const struct builtincmd builtincmd[] = {
1315 { BUILTIN_SPEC_REG ".", dotcmd },
1316 { BUILTIN_SPEC_REG ":", truecmd },
1317 #ifdef CONFIG_ASH_BUILTIN_TEST
1318 { BUILTIN_REGULAR "[", testcmd },
1319 { BUILTIN_REGULAR "[[", testcmd },
1321 #ifdef CONFIG_ASH_ALIAS
1322 { BUILTIN_REG_ASSG "alias", aliascmd },
1325 { BUILTIN_REGULAR "bg", bgcmd },
1327 { BUILTIN_SPEC_REG "break", breakcmd },
1328 { BUILTIN_REGULAR "cd", cdcmd },
1329 { BUILTIN_NOSPEC "chdir", cdcmd },
1330 #ifdef CONFIG_ASH_CMDCMD
1331 { BUILTIN_REGULAR "command", commandcmd },
1333 { BUILTIN_SPEC_REG "continue", breakcmd },
1334 #ifdef CONFIG_ASH_BUILTIN_ECHO
1335 { BUILTIN_REGULAR "echo", echocmd },
1337 { BUILTIN_SPEC_REG "eval", evalcmd },
1338 { BUILTIN_SPEC_REG "exec", execcmd },
1339 { BUILTIN_SPEC_REG "exit", exitcmd },
1340 { BUILTIN_SPEC_REG_ASSG "export", exportcmd },
1341 { BUILTIN_REGULAR "false", falsecmd },
1343 { BUILTIN_REGULAR "fg", fgcmd },
1345 #ifdef CONFIG_ASH_GETOPTS
1346 { BUILTIN_REGULAR "getopts", getoptscmd },
1348 { BUILTIN_NOSPEC "hash", hashcmd },
1349 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
1350 { BUILTIN_NOSPEC "help", helpcmd },
1353 { BUILTIN_REGULAR "jobs", jobscmd },
1354 { BUILTIN_REGULAR "kill", killcmd },
1356 #ifdef CONFIG_ASH_MATH_SUPPORT
1357 { BUILTIN_NOSPEC "let", letcmd },
1359 { BUILTIN_ASSIGN "local", localcmd },
1360 { BUILTIN_NOSPEC "pwd", pwdcmd },
1361 { BUILTIN_REGULAR "read", readcmd },
1362 { BUILTIN_SPEC_REG_ASSG "readonly", exportcmd },
1363 { BUILTIN_SPEC_REG "return", returncmd },
1364 { BUILTIN_SPEC_REG "set", setcmd },
1365 { BUILTIN_SPEC_REG "shift", shiftcmd },
1366 { BUILTIN_SPEC_REG "source", dotcmd },
1367 #ifdef CONFIG_ASH_BUILTIN_TEST
1368 { BUILTIN_REGULAR "test", testcmd },
1370 { BUILTIN_SPEC_REG "times", timescmd },
1371 { BUILTIN_SPEC_REG "trap", trapcmd },
1372 { BUILTIN_REGULAR "true", truecmd },
1373 { BUILTIN_NOSPEC "type", typecmd },
1374 { BUILTIN_NOSPEC "ulimit", ulimitcmd },
1375 { BUILTIN_REGULAR "umask", umaskcmd },
1376 #ifdef CONFIG_ASH_ALIAS
1377 { BUILTIN_REGULAR "unalias", unaliascmd },
1379 { BUILTIN_SPEC_REG "unset", unsetcmd },
1380 { BUILTIN_REGULAR "wait", waitcmd },
1383 #define NUMBUILTINS (sizeof(builtincmd) / sizeof(builtincmd[0]))
1390 const struct builtincmd *cmd;
1391 struct funcnode *func;
1396 /* action to find_command() */
1397 #define DO_ERR 0x01 /* prints errors */
1398 #define DO_ABS 0x02 /* checks absolute paths */
1399 #define DO_NOFUNC 0x04 /* don't return shell functions, for command */
1400 #define DO_ALTPATH 0x08 /* using alternate path */
1401 #define DO_ALTBLTIN 0x20 /* %builtin in alt. path */
1403 static const char *pathopt; /* set by padvance */
1405 static void shellexec(char **, const char *, int)
1407 static char *padvance(const char **, const char *);
1408 static void find_command(char *, struct cmdentry *, int, const char *);
1409 static struct builtincmd *find_builtin(const char *);
1410 static void hashcd(void);
1411 static void changepath(const char *);
1412 static void defun(char *, union node *);
1413 static void unsetfunc(const char *);
1415 #ifdef CONFIG_ASH_MATH_SUPPORT_64
1416 typedef int64_t arith_t;
1417 #define arith_t_type (long long)
1419 typedef long arith_t;
1420 #define arith_t_type (long)
1423 #ifdef CONFIG_ASH_MATH_SUPPORT
1424 static arith_t dash_arith(const char *);
1425 static arith_t arith(const char *expr, int *perrcode);
1428 #ifdef CONFIG_ASH_RANDOM_SUPPORT
1429 static unsigned long rseed;
1430 static void change_random(const char *);
1431 # ifndef DYNAMIC_VAR
1432 # define DYNAMIC_VAR
1438 static void reset(void);
1447 #define VEXPORT 0x01 /* variable is exported */
1448 #define VREADONLY 0x02 /* variable cannot be modified */
1449 #define VSTRFIXED 0x04 /* variable struct is statically allocated */
1450 #define VTEXTFIXED 0x08 /* text is statically allocated */
1451 #define VSTACK 0x10 /* text is allocated on the stack */
1452 #define VUNSET 0x20 /* the variable is not set */
1453 #define VNOFUNC 0x40 /* don't call the callback function */
1454 #define VNOSET 0x80 /* do not set variable - just readonly test */
1455 #define VNOSAVE 0x100 /* when text is on the heap before setvareq */
1457 # define VDYNAMIC 0x200 /* dynamic variable */
1463 struct var *next; /* next entry in hash list */
1464 int flags; /* flags are defined above */
1465 const char *text; /* name=value */
1466 void (*func)(const char *); /* function to be called when */
1467 /* the variable gets set/unset */
1471 struct localvar *next; /* next local variable in list */
1472 struct var *vp; /* the variable that was made local */
1473 int flags; /* saved flags */
1474 const char *text; /* saved text */
1478 static struct localvar *localvars;
1484 #ifdef CONFIG_ASH_GETOPTS
1485 static void getoptsreset(const char *);
1488 #ifdef CONFIG_LOCALE_SUPPORT
1489 static void change_lc_all(const char *value);
1490 static void change_lc_ctype(const char *value);
1496 static const char defpathvar[] = "PATH=/usr/local/bin:/usr/bin:/sbin:/bin";
1498 static const char defifsvar[] = "IFS= \t\n";
1499 #define defifs (defifsvar + 4)
1501 static const char defifs[] = " \t\n";
1505 static struct var varinit[] = {
1507 { 0, VSTRFIXED|VTEXTFIXED, defifsvar, 0 },
1509 { 0, VSTRFIXED|VTEXTFIXED|VUNSET, "IFS\0", 0 },
1512 #ifdef CONFIG_ASH_MAIL
1513 { 0, VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL\0", changemail },
1514 { 0, VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH\0", changemail },
1517 { 0, VSTRFIXED|VTEXTFIXED, defpathvar, changepath },
1518 { 0, VSTRFIXED|VTEXTFIXED, "PS1=$ ", 0 },
1519 { 0, VSTRFIXED|VTEXTFIXED, "PS2=> ", 0 },
1520 { 0, VSTRFIXED|VTEXTFIXED, "PS4=+ ", 0 },
1521 #ifdef CONFIG_ASH_GETOPTS
1522 { 0, VSTRFIXED|VTEXTFIXED, "OPTIND=1", getoptsreset },
1524 #ifdef CONFIG_ASH_RANDOM_SUPPORT
1525 {0, VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM\0", change_random },
1527 #ifdef CONFIG_LOCALE_SUPPORT
1528 {0, VSTRFIXED | VTEXTFIXED | VUNSET, "LC_ALL\0", change_lc_all },
1529 {0, VSTRFIXED | VTEXTFIXED | VUNSET, "LC_CTYPE\0", change_lc_ctype },
1531 #if ENABLE_FEATURE_COMMAND_SAVEHISTORY
1532 {0, VSTRFIXED | VTEXTFIXED | VUNSET, "HISTFILE\0", NULL },
1536 #define vifs varinit[0]
1537 #ifdef CONFIG_ASH_MAIL
1538 #define vmail (&vifs)[1]
1539 #define vmpath (&vmail)[1]
1543 #define vpath (&vmpath)[1]
1544 #define vps1 (&vpath)[1]
1545 #define vps2 (&vps1)[1]
1546 #define vps4 (&vps2)[1]
1547 #define voptind (&vps4)[1]
1548 #ifdef CONFIG_ASH_GETOPTS
1549 #define vrandom (&voptind)[1]
1551 #define vrandom (&vps4)[1]
1553 #define defpath (defpathvar + 5)
1556 * The following macros access the values of the above variables.
1557 * They have to skip over the name. They return the null string
1558 * for unset variables.
1561 #define ifsval() (vifs.text + 4)
1562 #define ifsset() ((vifs.flags & VUNSET) == 0)
1563 #define mailval() (vmail.text + 5)
1564 #define mpathval() (vmpath.text + 9)
1565 #define pathval() (vpath.text + 5)
1566 #define ps1val() (vps1.text + 4)
1567 #define ps2val() (vps2.text + 4)
1568 #define ps4val() (vps4.text + 4)
1569 #define optindval() (voptind.text + 7)
1571 #define mpathset() ((vmpath.flags & VUNSET) == 0)
1573 static void setvar(const char *, const char *, int);
1574 static void setvareq(char *, int);
1575 static void listsetvar(struct strlist *, int);
1576 static char *lookupvar(const char *);
1577 static char *bltinlookup(const char *);
1578 static char **listvars(int, int, char ***);
1579 #define environment() listvars(VEXPORT, VUNSET, 0)
1580 static int showvars(const char *, int, int);
1581 static void poplocalvars(void);
1582 static int unsetvar(const char *);
1583 #ifdef CONFIG_ASH_GETOPTS
1584 static int setvarsafe(const char *, const char *, int);
1586 static int varcmp(const char *, const char *);
1587 static struct var **hashvar(const char *);
1590 static int varequal(const char *a, const char *b) {
1591 return !varcmp(a, b);
1595 static int loopnest; /* current loop nesting level */
1598 * The parsefile structure pointed to by the global variable parsefile
1599 * contains information about the current file being read.
1604 struct redirtab *next;
1609 static struct redirtab *redirlist;
1610 static int nullredirs;
1612 extern char **environ;
1617 static void outstr(const char *, FILE *);
1618 static void outcslow(int, FILE *);
1619 static void flushall(void);
1620 static void flusherr(void);
1621 static int out1fmt(const char *, ...)
1622 __attribute__((__format__(__printf__,1,2)));
1623 static int fmtstr(char *, size_t, const char *, ...)
1624 __attribute__((__format__(__printf__,3,4)));
1626 static int preverrout_fd; /* save fd2 before print debug if xflag is set. */
1629 static void out1str(const char *p)
1634 static void out2str(const char *p)
1641 * Initialization code.
1645 * This routine initializes the builtin variables.
1648 static void initvar(void)
1655 * PS1 depends on uid
1657 #if defined(CONFIG_FEATURE_COMMAND_EDITING) && defined(CONFIG_FEATURE_SH_FANCY_PROMPT)
1658 vps1.text = "PS1=\\w \\$ ";
1661 vps1.text = "PS1=# ";
1664 end = vp + sizeof(varinit) / sizeof(varinit[0]);
1666 vpp = hashvar(vp->text);
1669 } while (++vp < end);
1672 static void init(void)
1677 basepf.nextc = basepf.buf = basebuf;
1682 signal(SIGCHLD, SIG_DFL);
1690 struct stat st1, st2;
1693 for (envp = environ ; envp && *envp ; envp++) {
1694 if (strchr(*envp, '=')) {
1695 setvareq(*envp, VEXPORT|VTEXTFIXED);
1699 snprintf(ppid, sizeof(ppid), "%d", (int) getppid());
1700 setvar("PPID", ppid, 0);
1702 p = lookupvar("PWD");
1704 if (*p != '/' || stat(p, &st1) || stat(".", &st2) ||
1705 st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino)
1711 /* PEOF (the end of file marker) */
1714 INPUT_PUSH_FILE = 1,
1715 INPUT_NOFILE_OK = 2,
1719 * The input line number. Input.c just defines this variable, and saves
1720 * and restores it when files are pushed and popped. The user of this
1721 * package must set its value.
1724 static int pgetc(void);
1725 static int pgetc2(void);
1726 static int preadbuffer(void);
1727 static void pungetc(void);
1728 static void pushstring(char *, void *);
1729 static void popstring(void);
1730 static void setinputfd(int, int);
1731 static void setinputstring(char *);
1732 static void popfile(void);
1733 static void popallfiles(void);
1734 static void closescript(void);
1740 /* Mode argument to forkshell. Don't change FORK_FG or FORK_BG. */
1743 #define FORK_NOJOB 2
1745 /* mode flags for showjob(s) */
1746 #define SHOW_PGID 0x01 /* only show pgid - for jobs -p */
1747 #define SHOW_PID 0x04 /* include process pid */
1748 #define SHOW_CHANGED 0x08 /* only jobs whose state has changed */
1752 * A job structure contains information about a job. A job is either a
1753 * single process or a set of processes contained in a pipeline. In the
1754 * latter case, pidlist will be non-NULL, and will point to a -1 terminated
1759 pid_t pid; /* process id */
1760 int status; /* last process status from wait() */
1761 char *cmd; /* text of command being run */
1765 struct procstat ps0; /* status of process */
1766 struct procstat *ps; /* status or processes when more than one */
1768 int stopstatus; /* status of a stopped job */
1771 nprocs: 16, /* number of processes */
1773 #define JOBRUNNING 0 /* at least one proc running */
1774 #define JOBSTOPPED 1 /* all procs are stopped */
1775 #define JOBDONE 2 /* all procs are completed */
1777 sigint: 1, /* job was killed by SIGINT */
1778 jobctl: 1, /* job running under job control */
1780 waited: 1, /* true if this entry has been waited for */
1781 used: 1, /* true if this entry is in used */
1782 changed: 1; /* true if status has changed */
1783 struct job *prev_job; /* previous job */
1786 static pid_t backgndpid; /* pid of last background process */
1787 static int job_warning; /* user was warned about stopped jobs */
1789 static int jobctl; /* true if doing job control */
1792 static struct job *makejob(union node *, int);
1793 static int forkshell(struct job *, union node *, int);
1794 static int waitforjob(struct job *);
1795 static int stoppedjobs(void);
1798 #define setjobctl(on) /* do nothing */
1800 static void setjobctl(int);
1801 static void showjobs(FILE *, int);
1807 /* pid of main shell */
1809 /* shell level: 0 for the main shell, 1 for its children, and so on */
1811 #define rootshell (!shlvl)
1813 static void readcmdfile(char *);
1814 static int cmdloop(int);
1820 struct stack_block *stackp;
1823 struct stackmark *marknext;
1826 /* minimum size of a block */
1827 #define MINSIZE SHELL_ALIGN(504)
1829 struct stack_block {
1830 struct stack_block *prev;
1831 char space[MINSIZE];
1834 static struct stack_block stackbase;
1835 static struct stack_block *stackp = &stackbase;
1836 static struct stackmark *markp;
1837 static char *stacknxt = stackbase.space;
1838 static size_t stacknleft = MINSIZE;
1839 static char *sstrend = stackbase.space + MINSIZE;
1840 static int herefd = -1;
1843 static pointer ckmalloc(size_t);
1844 static pointer ckrealloc(pointer, size_t);
1845 static char *savestr(const char *);
1846 static pointer stalloc(size_t);
1847 static void stunalloc(pointer);
1848 static void setstackmark(struct stackmark *);
1849 static void popstackmark(struct stackmark *);
1850 static void growstackblock(void);
1851 static void *growstackstr(void);
1852 static char *makestrspace(size_t, char *);
1853 static char *stnputs(const char *, size_t, char *);
1854 static char *stputs(const char *, char *);
1857 static char *_STPUTC(int c, char *p) {
1864 #define stackblock() ((void *)stacknxt)
1865 #define stackblocksize() stacknleft
1866 #define STARTSTACKSTR(p) ((p) = stackblock())
1867 #define STPUTC(c, p) ((p) = _STPUTC((c), (p)))
1868 #define CHECKSTRSPACE(n, p) \
1872 size_t m = sstrend - q; \
1874 (p) = makestrspace(l, q); \
1877 #define USTPUTC(c, p) (*p++ = (c))
1878 #define STACKSTRNUL(p) ((p) == sstrend? (p = growstackstr(), *p = '\0') : (*p = '\0'))
1879 #define STUNPUTC(p) (--p)
1880 #define STTOPC(p) p[-1]
1881 #define STADJUST(amount, p) (p += (amount))
1883 #define grabstackstr(p) stalloc((char *)(p) - (char *)stackblock())
1884 #define ungrabstackstr(s, p) stunalloc((s))
1885 #define stackstrend() ((void *)sstrend)
1887 #define ckfree(p) free((pointer)(p))
1892 #define DOLATSTRLEN 4
1894 static char *prefix(const char *, const char *);
1895 static int number(const char *);
1896 static int is_number(const char *);
1897 static char *single_quote(const char *);
1898 static char *sstrdup(const char *);
1900 #define equal(s1, s2) (strcmp(s1, s2) == 0)
1901 #define scopy(s1, s2) ((void)strcpy(s2, s1))
1906 int nparam; /* # of positional parameters (without $0) */
1907 unsigned char malloc; /* if parameter list dynamically allocated */
1908 char **p; /* parameter list */
1909 #ifdef CONFIG_ASH_GETOPTS
1910 int optind; /* next parameter to be processed by getopts */
1911 int optoff; /* used by getopts */
1916 #define eflag optlist[0]
1917 #define fflag optlist[1]
1918 #define Iflag optlist[2]
1919 #define iflag optlist[3]
1920 #define mflag optlist[4]
1921 #define nflag optlist[5]
1922 #define sflag optlist[6]
1923 #define xflag optlist[7]
1924 #define vflag optlist[8]
1925 #define Cflag optlist[9]
1926 #define aflag optlist[10]
1927 #define bflag optlist[11]
1928 #define uflag optlist[12]
1929 #define viflag optlist[13]
1932 #define nolog optlist[14]
1933 #define debug optlist[15]
1939 static const char *const optletters_optnames[] = {
1960 #define optletters(n) optletters_optnames[(n)][0]
1961 #define optnames(n) (&optletters_optnames[(n)][1])
1963 #define NOPTS (sizeof(optletters_optnames)/sizeof(optletters_optnames[0]))
1965 static char optlist[NOPTS];
1968 static char *arg0; /* value of $0 */
1969 static struct shparam shellparam; /* $@ current positional parameters */
1970 static char **argptr; /* argument list for builtin commands */
1971 static char *optionarg; /* set by nextopt (like getopt) */
1972 static char *optptr; /* used by nextopt */
1974 static char *minusc; /* argument to -c option */
1977 static void procargs(int, char **);
1978 static void optschanged(void);
1979 static void setparam(char **);
1980 static void freeparam(volatile struct shparam *);
1981 static int shiftcmd(int, char **);
1982 static int setcmd(int, char **);
1983 static int nextopt(const char *);
1987 /* flags passed to redirect */
1988 #define REDIR_PUSH 01 /* save previous values of file descriptors */
1989 #define REDIR_SAVEFD2 03 /* set preverrout */
1992 static void redirect(union node *, int);
1993 static void popredir(int);
1994 static void clearredir(int);
1995 static int copyfd(int, int);
1996 static int redirectsafe(union node *, int);
2002 static void showtree(union node *);
2003 static void trace(const char *, ...);
2004 static void tracev(const char *, va_list);
2005 static void trargs(char **);
2006 static void trputc(int);
2007 static void trputs(const char *);
2008 static void opentrace(void);
2014 /* trap handler commands */
2015 static char *trap[NSIG];
2016 /* current value of signal */
2017 static char sigmode[NSIG - 1];
2018 /* indicates specified signal received */
2019 static char gotsig[NSIG - 1];
2021 static void clear_traps(void);
2022 static void setsignal(int);
2023 static void ignoresig(int);
2024 static void onsig(int);
2025 static int dotrap(void);
2026 static void setinteractive(int);
2027 static void exitshell(void) ATTRIBUTE_NORETURN;
2030 static int is_safe_applet(char *name)
2032 /* It isn't a bug to have non-existent applet here... */
2033 /* ...just a waste of space... */
2034 static const char safe_applets[][8] = {
2038 USE_CHMOD (, "chmod" )
2039 USE_CHOWN (, "chown" )
2043 USE_ECHO (, "echo" )
2044 USE_FIND (, "find" )
2045 USE_HEXDUMP(, "hexdump")
2048 USE_MKDIR (, "mkdir" )
2050 USE_SORT (, "sort" )
2051 USE_TEST (, "test" )
2052 USE_TOUCH (, "touch" )
2053 USE_XARGS (, "xargs" )
2055 int n = sizeof(safe_applets) / sizeof(safe_applets[0]);
2057 for (i = 0; i < n; i++)
2058 if (strcmp(safe_applets[i], name) == 0)
2066 * This routine is called when an error or an interrupt occurs in an
2067 * interactive shell and control is returned to the main command loop.
2081 parselleft = parsenleft = 0; /* clear input buffer */
2085 /* from parser.c: */
2098 #ifdef CONFIG_ASH_ALIAS
2099 static struct alias *atab[ATABSIZE];
2101 static void setalias(const char *, const char *);
2102 static struct alias *freealias(struct alias *);
2103 static struct alias **__lookupalias(const char *);
2106 setalias(const char *name, const char *val)
2108 struct alias *ap, **app;
2110 app = __lookupalias(name);
2114 if (!(ap->flag & ALIASINUSE)) {
2117 ap->val = savestr(val);
2118 ap->flag &= ~ALIASDEAD;
2121 ap = ckmalloc(sizeof (struct alias));
2122 ap->name = savestr(name);
2123 ap->val = savestr(val);
2132 unalias(const char *name)
2136 app = __lookupalias(name);
2140 *app = freealias(*app);
2151 struct alias *ap, **app;
2155 for (i = 0; i < ATABSIZE; i++) {
2157 for (ap = *app; ap; ap = *app) {
2158 *app = freealias(*app);
2167 static struct alias *
2168 lookupalias(const char *name, int check)
2170 struct alias *ap = *__lookupalias(name);
2172 if (check && ap && (ap->flag & ALIASINUSE))
2178 * TODO - sort output
2181 aliascmd(int argc, char **argv)
2190 for (i = 0; i < ATABSIZE; i++)
2191 for (ap = atab[i]; ap; ap = ap->next) {
2196 while ((n = *++argv) != NULL) {
2197 if ((v = strchr(n+1, '=')) == NULL) { /* n+1: funny ksh stuff */
2198 if ((ap = *__lookupalias(n)) == NULL) {
2199 fprintf(stderr, "%s: %s not found\n", "alias", n);
2213 unaliascmd(int argc, char **argv)
2217 while ((i = nextopt("a")) != '\0') {
2223 for (i = 0; *argptr; argptr++) {
2224 if (unalias(*argptr)) {
2225 fprintf(stderr, "%s: %s not found\n", "unalias", *argptr);
2233 static struct alias *
2234 freealias(struct alias *ap) {
2237 if (ap->flag & ALIASINUSE) {
2238 ap->flag |= ALIASDEAD;
2250 printalias(const struct alias *ap) {
2251 out1fmt("%s=%s\n", ap->name, single_quote(ap->val));
2254 static struct alias **
2255 __lookupalias(const char *name) {
2256 unsigned int hashval;
2263 ch = (unsigned char)*p;
2267 ch = (unsigned char)*++p;
2269 app = &atab[hashval % ATABSIZE];
2271 for (; *app; app = &(*app)->next) {
2272 if (equal(name, (*app)->name)) {
2279 #endif /* CONFIG_ASH_ALIAS */
2285 * The cd and pwd commands.
2288 #define CD_PHYSICAL 1
2291 static int docd(const char *, int);
2292 static int cdopt(void);
2294 static char *curdir = nullstr; /* current working directory */
2295 static char *physdir = nullstr; /* physical working directory */
2304 while ((i = nextopt("LP"))) {
2306 flags ^= CD_PHYSICAL;
2315 cdcmd(int argc, char **argv)
2327 dest = bltinlookup(homestr);
2328 else if (LONE_DASH(dest)) {
2329 dest = bltinlookup("OLDPWD");
2351 if (!(path = bltinlookup("CDPATH"))) {
2359 p = padvance(&path, dest);
2360 if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
2364 if (!docd(p, flags))
2369 sh_error("can't cd to %s", dest);
2372 if (flags & CD_PRINT)
2373 out1fmt(snlfmt, curdir);
2379 * Update curdir (the name of the current directory) in response to a
2383 static const char * updatepwd(const char *dir)
2390 cdcomppath = sstrdup(dir);
2393 if (curdir == nullstr)
2395 new = stputs(curdir, new);
2397 new = makestrspace(strlen(dir) + 2, new);
2398 lim = stackblock() + 1;
2402 if (new > lim && *lim == '/')
2407 if (dir[1] == '/' && dir[2] != '/') {
2413 p = strtok(cdcomppath, "/");
2417 if (p[1] == '.' && p[2] == '\0') {
2424 } else if (p[1] == '\0')
2428 new = stputs(p, new);
2436 return stackblock();
2440 * Actually do the chdir. We also call hashcd to let the routines in exec.c
2441 * know that the current directory has changed.
2445 docd(const char *dest, int flags)
2447 const char *dir = 0;
2450 TRACE(("docd(\"%s\", %d) called\n", dest, flags));
2453 if (!(flags & CD_PHYSICAL)) {
2454 dir = updatepwd(dest);
2469 * Find out what the current directory is. If we already know the current
2470 * directory, this routine returns immediately.
2472 static char * getpwd(void)
2474 char *dir = getcwd(0, 0);
2475 return dir ? dir : nullstr;
2479 pwdcmd(int argc, char **argv)
2482 const char *dir = curdir;
2486 if (physdir == nullstr)
2490 out1fmt(snlfmt, dir);
2495 setpwd(const char *val, int setold)
2499 oldcur = dir = curdir;
2502 setvar("OLDPWD", oldcur, VEXPORT);
2505 if (physdir != nullstr) {
2506 if (physdir != oldcur)
2510 if (oldcur == val || !val) {
2517 if (oldcur != dir && oldcur != nullstr) {
2522 setvar("PWD", dir, VEXPORT);
2528 * Errors and exceptions.
2532 * Code to handle exceptions in C.
2537 static void exverror(int, const char *, va_list)
2541 * Called to raise an exception. Since C doesn't include exceptions, we
2542 * just do a longjmp to the exception handler. The type of exception is
2543 * stored in the global variable "exception".
2550 if (handler == NULL)
2556 longjmp(handler->loc, 1);
2561 * Called from trap.c when a SIGINT is received. (If the user specifies
2562 * that SIGINT is to be trapped or ignored using the trap builtin, then
2563 * this routine is not called.) Suppressint is nonzero when interrupts
2564 * are held using the INTOFF macro. (The test for iflag is just
2565 * defensive programming.)
2574 if (gotsig[SIGINT - 1] && !trap[SIGINT]) {
2575 if (!(rootshell && iflag)) {
2576 signal(SIGINT, SIG_DFL);
2586 exvwarning(const char *msg, va_list ap)
2591 fprintf(errs, "%s: ", arg0);
2593 const char *fmt = (!iflag || parsefile->fd) ?
2594 "%s: %d: " : "%s: ";
2595 fprintf(errs, fmt, commandname, startlinno);
2597 vfprintf(errs, msg, ap);
2598 outcslow('\n', errs);
2602 * Exverror is called to raise the error exception. If the second argument
2603 * is not NULL then error prints an error message using printf style
2604 * formatting. It then raises the error exception.
2607 exverror(int cond, const char *msg, va_list ap)
2611 TRACE(("exverror(%d, \"", cond));
2613 TRACE(("\") pid=%d\n", getpid()));
2615 TRACE(("exverror(%d, NULL) pid=%d\n", cond, getpid()));
2618 exvwarning(msg, ap);
2627 sh_error(const char *msg, ...)
2632 exverror(EXERROR, msg, ap);
2639 exerror(int cond, const char *msg, ...)
2644 exverror(cond, msg, ap);
2650 * error/warning routines for external builtins
2654 sh_warnx(const char *fmt, ...)
2659 exvwarning(fmt, ap);
2665 * Return a string describing an error. The returned string may be a
2666 * pointer to a static buffer that will be overwritten on the next call.
2667 * Action describes the operation that got the error.
2671 errmsg(int e, const char *em)
2673 if(e == ENOENT || e == ENOTDIR) {
2684 * Evaluate a command.
2687 /* flags in argument to evaltree */
2688 #define EV_EXIT 01 /* exit after evaluating tree */
2689 #define EV_TESTED 02 /* exit status is checked; ignore -e flag */
2690 #define EV_BACKCMD 04 /* command executing within back quotes */
2693 static void evalloop(union node *, int);
2694 static void evalfor(union node *, int);
2695 static void evalcase(union node *, int);
2696 static void evalsubshell(union node *, int);
2697 static void expredir(union node *);
2698 static void evalpipe(union node *, int);
2699 static void evalcommand(union node *, int);
2700 static int evalbltin(const struct builtincmd *, int, char **);
2701 static int evalfun(struct funcnode *, int, char **, int);
2702 static void prehash(union node *);
2703 static int bltincmd(int, char **);
2706 static const struct builtincmd bltin = {
2712 * Called to reset things after an exception.
2720 evalcmd(int argc, char **argv)
2729 STARTSTACKSTR(concat);
2732 concat = stputs(p, concat);
2733 if ((p = *ap++) == NULL)
2735 STPUTC(' ', concat);
2737 STPUTC('\0', concat);
2738 p = grabstackstr(concat);
2740 evalstring(p, ~SKIPEVAL);
2748 * Execute a command or commands contained in a string.
2752 evalstring(char *s, int mask)
2755 struct stackmark smark;
2759 setstackmark(&smark);
2762 while ((n = parsecmd(0)) != NEOF) {
2764 popstackmark(&smark);
2779 * Evaluate a parse tree. The value is left in the global variable
2784 evaltree(union node *n, int flags)
2787 void (*evalfn)(union node *, int);
2791 TRACE(("evaltree(NULL) called\n"));
2794 TRACE(("pid %d, evaltree(%p: %d, %d) called\n",
2795 getpid(), n, n->type, flags));
2799 out1fmt("Node type = %d\n", n->type);
2804 evaltree(n->nnot.com, EV_TESTED);
2805 status = !exitstatus;
2808 expredir(n->nredir.redirect);
2809 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
2811 evaltree(n->nredir.n, flags & EV_TESTED);
2812 status = exitstatus;
2817 evalfn = evalcommand;
2819 if (eflag && !(flags & EV_TESTED))
2831 evalfn = evalsubshell;
2843 #error NAND + 1 != NOR
2845 #if NOR + 1 != NSEMI
2846 #error NOR + 1 != NSEMI
2848 isor = n->type - NAND;
2851 (flags | ((isor >> 1) - 1)) & EV_TESTED
2853 if (!exitstatus == isor)
2865 evaltree(n->nif.test, EV_TESTED);
2868 if (exitstatus == 0) {
2871 } else if (n->nif.elsepart) {
2872 n = n->nif.elsepart;
2877 defun(n->narg.text, n->narg.next);
2881 exitstatus = status;
2885 if ((checkexit & exitstatus))
2886 evalskip |= SKIPEVAL;
2887 else if (pendingsigs && dotrap())
2890 if (flags & EV_EXIT) {
2897 #if !defined(__alpha__) || (defined(__GNUC__) && __GNUC__ >= 3)
2900 void evaltreenr(union node *, int) __attribute__ ((alias("evaltree"),__noreturn__));
2904 evalloop(union node *n, int flags)
2914 evaltree(n->nbinary.ch1, EV_TESTED);
2916 skipping: if (evalskip == SKIPCONT && --skipcount <= 0) {
2920 if (evalskip == SKIPBREAK && --skipcount <= 0)
2925 if (n->type != NWHILE)
2929 evaltree(n->nbinary.ch2, flags);
2930 status = exitstatus;
2935 exitstatus = status;
2941 evalfor(union node *n, int flags)
2943 struct arglist arglist;
2946 struct stackmark smark;
2948 setstackmark(&smark);
2949 arglist.lastp = &arglist.list;
2950 for (argp = n->nfor.args ; argp ; argp = argp->narg.next) {
2951 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE | EXP_RECORD);
2956 *arglist.lastp = NULL;
2961 for (sp = arglist.list ; sp ; sp = sp->next) {
2962 setvar(n->nfor.var, sp->text, 0);
2963 evaltree(n->nfor.body, flags);
2965 if (evalskip == SKIPCONT && --skipcount <= 0) {
2969 if (evalskip == SKIPBREAK && --skipcount <= 0)
2976 popstackmark(&smark);
2982 evalcase(union node *n, int flags)
2986 struct arglist arglist;
2987 struct stackmark smark;
2989 setstackmark(&smark);
2990 arglist.lastp = &arglist.list;
2991 expandarg(n->ncase.expr, &arglist, EXP_TILDE);
2993 for (cp = n->ncase.cases ; cp && evalskip == 0 ; cp = cp->nclist.next) {
2994 for (patp = cp->nclist.pattern ; patp ; patp = patp->narg.next) {
2995 if (casematch(patp, arglist.list->text)) {
2996 if (evalskip == 0) {
2997 evaltree(cp->nclist.body, flags);
3004 popstackmark(&smark);
3010 * Kick off a subshell to evaluate a tree.
3014 evalsubshell(union node *n, int flags)
3017 int backgnd = (n->type == NBACKGND);
3020 expredir(n->nredir.redirect);
3021 if (!backgnd && flags & EV_EXIT && !trap[0])
3025 if (forkshell(jp, n, backgnd) == 0) {
3029 flags &=~ EV_TESTED;
3031 redirect(n->nredir.redirect, 0);
3032 evaltreenr(n->nredir.n, flags);
3037 status = waitforjob(jp);
3038 exitstatus = status;
3045 * Compute the names of the files in a redirection list.
3049 expredir(union node *n)
3053 for (redir = n ; redir ; redir = redir->nfile.next) {
3055 memset(&fn, 0, sizeof(struct arglist));
3056 fn.lastp = &fn.list;
3057 switch (redir->type) {
3063 expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
3064 redir->nfile.expfname = fn.list->text;
3068 if (redir->ndup.vname) {
3069 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
3070 if (fn.list != NULL)
3071 fixredir(redir, fn.list->text, 1);
3073 sh_error("redir error");
3083 * Evaluate a pipeline. All the processes in the pipeline are children
3084 * of the process creating the pipeline. (This differs from some versions
3085 * of the shell, which make the last process in a pipeline the parent
3090 evalpipe(union node *n, int flags)
3093 struct nodelist *lp;
3098 TRACE(("evalpipe(0x%lx) called\n", (long)n));
3100 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next)
3104 jp = makejob(n, pipelen);
3106 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
3110 if (pipe(pip) < 0) {
3112 sh_error("Pipe call failed");
3115 if (forkshell(jp, lp->n, n->npipe.backgnd) == 0) {
3128 evaltreenr(lp->n, flags);
3136 if (n->npipe.backgnd == 0) {
3137 exitstatus = waitforjob(jp);
3138 TRACE(("evalpipe: job done exit status %d\n", exitstatus));
3146 * Execute a command inside back quotes. If it's a builtin command, we
3147 * want to save its output in a block obtained from malloc. Otherwise
3148 * we fork off a subprocess and get the output of the command via a pipe.
3149 * Should be called with interrupts off.
3153 evalbackcmd(union node *n, struct backcmd *result)
3165 saveherefd = herefd;
3173 sh_error("Pipe call failed");
3175 if (forkshell(jp, n, FORK_NOJOB) == 0) {
3184 evaltreenr(n, EV_EXIT);
3188 result->fd = pip[0];
3191 herefd = saveherefd;
3193 TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
3194 result->fd, result->buf, result->nleft, result->jp));
3197 #ifdef CONFIG_ASH_CMDCMD
3198 static char ** parse_command_args(char **argv, const char **path)
3210 if (c == '-' && !*cp) {
3220 /* run 'typecmd' for other options */
3223 } while ((c = *cp++));
3229 static int isassignment(const char *p)
3231 const char *q = endofname(p);
3237 #ifdef CONFIG_ASH_EXPAND_PRMT
3238 static const char *expandstr(const char *ps);
3240 #define expandstr(s) s
3244 * Execute a simple command.
3248 evalcommand(union node *cmd, int flags)
3250 struct stackmark smark;
3252 struct arglist arglist;
3253 struct arglist varlist;
3256 const struct strlist *sp;
3257 struct cmdentry cmdentry;
3265 struct builtincmd *bcmd;
3266 int pseudovarflag = 0;
3268 /* First expand the arguments. */
3269 TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
3270 setstackmark(&smark);
3271 back_exitstatus = 0;
3273 cmdentry.cmdtype = CMDBUILTIN;
3274 cmdentry.u.cmd = &bltin;
3275 varlist.lastp = &varlist.list;
3276 *varlist.lastp = NULL;
3277 arglist.lastp = &arglist.list;
3278 *arglist.lastp = NULL;
3283 bcmd = find_builtin(cmd->ncmd.args->narg.text);
3284 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
3287 for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
3288 struct strlist **spp;
3290 spp = arglist.lastp;
3291 if (pseudovarflag && isassignment(argp->narg.text))
3292 expandarg(argp, &arglist, EXP_VARTILDE);
3294 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
3296 for (sp = *spp; sp; sp = sp->next)
3300 argv = nargv = stalloc(sizeof (char *) * (argc + 1));
3301 for (sp = arglist.list ; sp ; sp = sp->next) {
3302 TRACE(("evalcommand arg: %s\n", sp->text));
3303 *nargv++ = sp->text;
3308 if (iflag && funcnest == 0 && argc > 0)
3309 lastarg = nargv[-1];
3312 expredir(cmd->ncmd.redirect);
3313 status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH|REDIR_SAVEFD2);
3316 for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
3317 struct strlist **spp;
3320 spp = varlist.lastp;
3321 expandarg(argp, &varlist, EXP_VARTILDE);
3324 * Modify the command lookup path, if a PATH= assignment
3328 if (varequal(p, path))
3332 /* Print the command if xflag is set. */
3335 const char *p = " %s";
3338 dprintf(preverrout_fd, p, expandstr(ps4val()));
3341 for(n = 0; n < 2; n++) {
3343 dprintf(preverrout_fd, p, sp->text);
3351 full_write(preverrout_fd, "\n", 1);
3357 /* Now locate the command. */
3359 const char *oldpath;
3360 int cmd_flag = DO_ERR;
3365 find_command(argv[0], &cmdentry, cmd_flag, path);
3366 if (cmdentry.cmdtype == CMDUNKNOWN) {
3372 /* implement bltin and command here */
3373 if (cmdentry.cmdtype != CMDBUILTIN)
3376 spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
3377 if (cmdentry.u.cmd == EXECCMD)
3379 #ifdef CONFIG_ASH_CMDCMD
3380 if (cmdentry.u.cmd == COMMANDCMD) {
3383 nargv = parse_command_args(argv, &path);
3386 argc -= nargv - argv;
3388 cmd_flag |= DO_NOFUNC;
3396 /* We have a redirection error. */
3400 exitstatus = status;
3404 /* Execute the command. */
3405 switch (cmdentry.cmdtype) {
3407 /* Fork off a child process if necessary. */
3408 if (!(flags & EV_EXIT) || trap[0]) {
3410 jp = makejob(cmd, 1);
3411 if (forkshell(jp, cmd, FORK_FG) != 0) {
3412 exitstatus = waitforjob(jp);
3418 listsetvar(varlist.list, VEXPORT|VSTACK);
3419 shellexec(argv, path, cmdentry.u.index);
3423 cmdenviron = varlist.list;
3425 struct strlist *list = cmdenviron;
3427 if (spclbltin > 0 || argc == 0) {
3429 if (cmd_is_exec && argc > 1)
3432 listsetvar(list, i);
3434 if (evalbltin(cmdentry.u.cmd, argc, argv)) {
3449 exit_status = j + 128;
3450 exitstatus = exit_status;
3452 if (i == EXINT || spclbltin > 0) {
3454 longjmp(handler->loc, 1);
3461 listsetvar(varlist.list, 0);
3462 if (evalfun(cmdentry.u.func, argc, argv, flags))
3468 popredir(cmd_is_exec);
3470 /* dsl: I think this is intended to be used to support
3471 * '_' in 'vi' command mode during line editing...
3472 * However I implemented that within libedit itself.
3474 setvar("_", lastarg, 0);
3475 popstackmark(&smark);
3479 evalbltin(const struct builtincmd *cmd, int argc, char **argv) {
3480 char *volatile savecmdname;
3481 struct jmploc *volatile savehandler;
3482 struct jmploc jmploc;
3485 savecmdname = commandname;
3486 if ((i = setjmp(jmploc.loc)))
3488 savehandler = handler;
3490 commandname = argv[0];
3492 optptr = NULL; /* initialize nextopt */
3493 exitstatus = (*cmd->builtin)(argc, argv);
3496 exitstatus |= ferror(stdout);
3498 commandname = savecmdname;
3500 handler = savehandler;
3506 evalfun(struct funcnode *func, int argc, char **argv, int flags)
3508 volatile struct shparam saveparam;
3509 struct localvar *volatile savelocalvars;
3510 struct jmploc *volatile savehandler;
3511 struct jmploc jmploc;
3514 saveparam = shellparam;
3515 savelocalvars = localvars;
3516 if ((e = setjmp(jmploc.loc))) {
3520 savehandler = handler;
3523 shellparam.malloc = 0;
3527 shellparam.nparam = argc - 1;
3528 shellparam.p = argv + 1;
3529 #ifdef CONFIG_ASH_GETOPTS
3530 shellparam.optind = 1;
3531 shellparam.optoff = -1;
3533 evaltree(&func->n, flags & EV_TESTED);
3539 localvars = savelocalvars;
3540 freeparam(&shellparam);
3541 shellparam = saveparam;
3542 handler = savehandler;
3544 evalskip &= ~SKIPFUNC;
3549 static int goodname(const char *p)
3551 return !*endofname(p);
3555 * Search for a command. This is called before we fork so that the
3556 * location of the command will be available in the parent as well as
3557 * the child. The check for "goodname" is an overly conservative
3558 * check that the name will not be subject to expansion.
3562 prehash(union node *n)
3564 struct cmdentry entry;
3566 if (n->type == NCMD && n->ncmd.args)
3567 if (goodname(n->ncmd.args->narg.text))
3568 find_command(n->ncmd.args->narg.text, &entry, 0,
3575 * Builtin commands. Builtin commands whose functions are closely
3576 * tied to evaluation are implemented here.
3584 bltincmd(int argc, char **argv)
3587 * Preserve exitstatus of a previous possible redirection
3590 return back_exitstatus;
3595 * Handle break and continue commands. Break, continue, and return are
3596 * all handled by setting the evalskip flag. The evaluation routines
3597 * above all check this flag, and if it is set they start skipping
3598 * commands rather than executing them. The variable skipcount is
3599 * the number of loops to break/continue, or the number of function
3600 * levels to return. (The latter is always 1.) It should probably
3601 * be an error to break out of more loops than exist, but it isn't
3602 * in the standard shell so we don't make it one here.
3606 breakcmd(int argc, char **argv)
3608 int n = argc > 1 ? number(argv[1]) : 1;
3611 sh_error(illnum, argv[1]);
3615 evalskip = (**argv == 'c')? SKIPCONT : SKIPBREAK;
3623 * The return command.
3627 returncmd(int argc, char **argv)
3630 * If called outside a function, do what ksh does;
3631 * skip the rest of the file.
3633 evalskip = funcnest ? SKIPFUNC : SKIPFILE;
3634 return argv[1] ? number(argv[1]) : exitstatus;
3639 falsecmd(int argc, char **argv)
3646 truecmd(int argc, char **argv)
3653 execcmd(int argc, char **argv)
3656 iflag = 0; /* exit on error */
3659 shellexec(argv + 1, pathval(), 0);
3668 * When commands are first encountered, they are entered in a hash table.
3669 * This ensures that a full path search will not have to be done for them
3670 * on each invocation.
3672 * We should investigate converting to a linear search, even though that
3673 * would make the command name "hash" a misnomer.
3676 #define CMDTABLESIZE 31 /* should be prime */
3677 #define ARB 1 /* actual size determined at run time */
3682 struct tblentry *next; /* next entry in hash chain */
3683 union param param; /* definition of builtin function */
3684 short cmdtype; /* index identifying command */
3685 char rehash; /* if set, cd done since entry created */
3686 char cmdname[ARB]; /* name of command */
3690 static struct tblentry *cmdtable[CMDTABLESIZE];
3691 static int builtinloc = -1; /* index in path of %builtin, or -1 */
3694 static void tryexec(char *, char **, char **);
3695 static void clearcmdentry(int);
3696 static struct tblentry *cmdlookup(const char *, int);
3697 static void delete_cmd_entry(void);
3701 * Exec a program. Never returns. If you change this routine, you may
3702 * have to change the find_command routine as well.
3706 shellexec(char **argv, const char *path, int idx)
3714 envp = environment();
3715 if (strchr(argv[0], '/') || is_safe_applet(argv[0])
3716 #if ENABLE_FEATURE_SH_STANDALONE_SHELL
3717 || find_applet_by_name(argv[0])
3720 tryexec(argv[0], argv, envp);
3724 while ((cmdname = padvance(&path, argv[0])) != NULL) {
3725 if (--idx < 0 && pathopt == NULL) {
3726 tryexec(cmdname, argv, envp);
3727 if (errno != ENOENT && errno != ENOTDIR)
3734 /* Map to POSIX errors */
3746 exitstatus = exerrno;
3747 TRACE(("shellexec failed for %s, errno %d, suppressint %d\n",
3748 argv[0], e, suppressint ));
3749 exerror(EXEXEC, "%s: %s", argv[0], errmsg(e, E_EXEC));
3755 tryexec(char *cmd, char **argv, char **envp)
3758 struct BB_applet *a;
3762 if (strchr(cmd, '/') == NULL
3763 && (a = find_applet_by_name(cmd)) != NULL
3764 && is_safe_applet(cmd)
3767 while (*c != NULL) {
3771 exit(a->main(argc, argv));
3773 #if ENABLE_FEATURE_SH_STANDALONE_SHELL
3774 if (find_applet_by_name(cmd) != NULL) {
3775 /* re-exec ourselves with the new arguments */
3776 execve(CONFIG_BUSYBOX_EXEC_PATH,argv,envp);
3777 /* If they called chroot or otherwise made the binary no longer
3778 * executable, fall through */
3785 execve(cmd, argv, envp);
3786 } while (errno == EINTR);
3788 execve(cmd, argv, envp);
3792 } else if (errno == ENOEXEC) {
3796 for (ap = argv; *ap; ap++)
3798 ap = new = ckmalloc((ap - argv + 2) * sizeof(char *));
3800 *ap = cmd = (char *)DEFAULT_SHELL;
3803 while ((*ap++ = *argv++))
3813 * Do a path search. The variable path (passed by reference) should be
3814 * set to the start of the path before the first call; padvance will update
3815 * this value as it proceeds. Successive calls to padvance will return
3816 * the possible path expansions in sequence. If an option (indicated by
3817 * a percent sign) appears in the path entry then the global variable
3818 * pathopt will be set to point to it; otherwise pathopt will be set to
3823 padvance(const char **path, const char *name)
3833 for (p = start ; *p && *p != ':' && *p != '%' ; p++);
3834 len = p - start + strlen(name) + 2; /* "2" is for '/' and '\0' */
3835 while (stackblocksize() < len)
3839 memcpy(q, start, p - start);
3847 while (*p && *p != ':') p++;
3853 return stalloc(len);
3857 /*** Command hashing code ***/
3860 printentry(struct tblentry *cmdp)
3866 idx = cmdp->param.index;
3869 name = padvance(&path, cmdp->cmdname);
3871 } while (--idx >= 0);
3872 out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
3877 hashcmd(int argc, char **argv)
3879 struct tblentry **pp;
3880 struct tblentry *cmdp;
3882 struct cmdentry entry;
3885 while ((c = nextopt("r")) != '\0') {
3889 if (*argptr == NULL) {
3890 for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
3891 for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
3892 if (cmdp->cmdtype == CMDNORMAL)
3899 while ((name = *argptr) != NULL) {
3900 if ((cmdp = cmdlookup(name, 0)) != NULL
3901 && (cmdp->cmdtype == CMDNORMAL
3902 || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0)))
3904 find_command(name, &entry, DO_ERR, pathval());
3905 if (entry.cmdtype == CMDUNKNOWN)
3914 * Resolve a command name. If you change this routine, you may have to
3915 * change the shellexec routine as well.
3919 find_command(char *name, struct cmdentry *entry, int act, const char *path)
3921 struct tblentry *cmdp;
3928 struct builtincmd *bcmd;
3930 /* If name contains a slash, don't use PATH or hash table */
3931 if (strchr(name, '/') != NULL) {
3932 entry->u.index = -1;
3934 while (stat(name, &statb) < 0) {
3939 entry->cmdtype = CMDUNKNOWN;
3943 entry->cmdtype = CMDNORMAL;
3947 #if ENABLE_FEATURE_SH_STANDALONE_SHELL
3948 if (find_applet_by_name(name)) {
3949 entry->cmdtype = CMDNORMAL;
3950 entry->u.index = -1;
3955 if (is_safe_applet(name)) {
3956 entry->cmdtype = CMDNORMAL;
3957 entry->u.index = -1;
3961 updatetbl = (path == pathval());
3964 if (strstr(path, "%builtin") != NULL)
3968 /* If name is in the table, check answer will be ok */
3969 if ((cmdp = cmdlookup(name, 0)) != NULL) {
3972 switch (cmdp->cmdtype) {
3990 } else if (cmdp->rehash == 0)
3991 /* if not invalidated by cd, we're done */
3995 /* If %builtin not in path, check for builtin next */
3996 bcmd = find_builtin(name);
3997 if (bcmd && (IS_BUILTIN_REGULAR(bcmd) || (
3998 act & DO_ALTPATH ? !(act & DO_ALTBLTIN) : builtinloc <= 0
4000 goto builtin_success;
4002 /* We have to search path. */
4003 prev = -1; /* where to start */
4004 if (cmdp && cmdp->rehash) { /* doing a rehash */
4005 if (cmdp->cmdtype == CMDBUILTIN)
4008 prev = cmdp->param.index;
4014 while ((fullname = padvance(&path, name)) != NULL) {
4015 stunalloc(fullname);
4018 if (prefix(pathopt, "builtin")) {
4020 goto builtin_success;
4022 } else if (!(act & DO_NOFUNC) &&
4023 prefix(pathopt, "func")) {
4026 /* ignore unimplemented options */
4030 /* if rehash, don't redo absolute path names */
4031 if (fullname[0] == '/' && idx <= prev) {
4034 TRACE(("searchexec \"%s\": no change\n", name));
4037 while (stat(fullname, &statb) < 0) {
4042 if (errno != ENOENT && errno != ENOTDIR)
4046 e = EACCES; /* if we fail, this will be the error */
4047 if (!S_ISREG(statb.st_mode))
4049 if (pathopt) { /* this is a %func directory */
4050 stalloc(strlen(fullname) + 1);
4051 readcmdfile(fullname);
4052 if ((cmdp = cmdlookup(name, 0)) == NULL ||
4053 cmdp->cmdtype != CMDFUNCTION)
4054 sh_error("%s not defined in %s", name, fullname);
4055 stunalloc(fullname);
4058 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
4060 entry->cmdtype = CMDNORMAL;
4061 entry->u.index = idx;
4065 cmdp = cmdlookup(name, 1);
4066 cmdp->cmdtype = CMDNORMAL;
4067 cmdp->param.index = idx;
4072 /* We failed. If there was an entry for this command, delete it */
4073 if (cmdp && updatetbl)
4076 sh_warnx("%s: %s", name, errmsg(e, E_EXEC));
4077 entry->cmdtype = CMDUNKNOWN;
4082 entry->cmdtype = CMDBUILTIN;
4083 entry->u.cmd = bcmd;
4087 cmdp = cmdlookup(name, 1);
4088 cmdp->cmdtype = CMDBUILTIN;
4089 cmdp->param.cmd = bcmd;
4093 entry->cmdtype = cmdp->cmdtype;
4094 entry->u = cmdp->param;
4099 * Wrapper around strcmp for qsort/bsearch/...
4101 static int pstrcmp(const void *a, const void *b)
4103 return strcmp((const char *) a, (*(const char *const *) b) + 1);
4107 * Search the table of builtin commands.
4110 static struct builtincmd *
4111 find_builtin(const char *name)
4113 struct builtincmd *bp;
4116 name, builtincmd, NUMBUILTINS, sizeof(struct builtincmd),
4125 * Called when a cd is done. Marks all commands so the next time they
4126 * are executed they will be rehashed.
4132 struct tblentry **pp;
4133 struct tblentry *cmdp;
4135 for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
4136 for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
4137 if (cmdp->cmdtype == CMDNORMAL || (
4138 cmdp->cmdtype == CMDBUILTIN &&
4139 !(IS_BUILTIN_REGULAR(cmdp->param.cmd)) &&
4150 * Fix command hash table when PATH changed.
4151 * Called before PATH is changed. The argument is the new value of PATH;
4152 * pathval() still returns the old value at this point.
4153 * Called with interrupts off.
4157 changepath(const char *newval)
4159 const char *old, *new;
4166 firstchange = 9999; /* assume no change */
4172 if ((*old == '\0' && *new == ':')
4173 || (*old == ':' && *new == '\0'))
4175 old = new; /* ignore subsequent differences */
4179 if (*new == '%' && idx_bltin < 0 && prefix(new + 1, "builtin"))
4186 if (builtinloc < 0 && idx_bltin >= 0)
4187 builtinloc = idx_bltin; /* zap builtins */
4188 if (builtinloc >= 0 && idx_bltin < 0)
4190 clearcmdentry(firstchange);
4191 builtinloc = idx_bltin;
4196 * Clear out command entries. The argument specifies the first entry in
4197 * PATH which has changed.
4201 clearcmdentry(int firstchange)
4203 struct tblentry **tblp;
4204 struct tblentry **pp;
4205 struct tblentry *cmdp;
4208 for (tblp = cmdtable ; tblp < &cmdtable[CMDTABLESIZE] ; tblp++) {
4210 while ((cmdp = *pp) != NULL) {
4211 if ((cmdp->cmdtype == CMDNORMAL &&
4212 cmdp->param.index >= firstchange)
4213 || (cmdp->cmdtype == CMDBUILTIN &&
4214 builtinloc >= firstchange)) {
4228 * Locate a command in the command hash table. If "add" is nonzero,
4229 * add the command to the table if it is not already present. The
4230 * variable "lastcmdentry" is set to point to the address of the link
4231 * pointing to the entry, so that delete_cmd_entry can delete the
4234 * Interrupts must be off if called with add != 0.
4237 static struct tblentry **lastcmdentry;
4240 static struct tblentry *
4241 cmdlookup(const char *name, int add)
4243 unsigned int hashval;
4245 struct tblentry *cmdp;
4246 struct tblentry **pp;
4249 hashval = (unsigned char)*p << 4;
4251 hashval += (unsigned char)*p++;
4253 pp = &cmdtable[hashval % CMDTABLESIZE];
4254 for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
4255 if (equal(cmdp->cmdname, name))
4259 if (add && cmdp == NULL) {
4260 cmdp = *pp = ckmalloc(sizeof (struct tblentry) - ARB
4261 + strlen(name) + 1);
4263 cmdp->cmdtype = CMDUNKNOWN;
4264 strcpy(cmdp->cmdname, name);
4271 * Delete the command entry returned on the last lookup.
4275 delete_cmd_entry(void)
4277 struct tblentry *cmdp;
4280 cmdp = *lastcmdentry;
4281 *lastcmdentry = cmdp->next;
4282 if (cmdp->cmdtype == CMDFUNCTION)
4283 freefunc(cmdp->param.func);
4290 * Add a new command entry, replacing any existing command entry for
4291 * the same name - except special builtins.
4294 static void addcmdentry(char *name, struct cmdentry *entry)
4296 struct tblentry *cmdp;
4298 cmdp = cmdlookup(name, 1);
4299 if (cmdp->cmdtype == CMDFUNCTION) {
4300 freefunc(cmdp->param.func);
4302 cmdp->cmdtype = entry->cmdtype;
4303 cmdp->param = entry->u;
4308 * Make a copy of a parse tree.
4311 static struct funcnode * copyfunc(union node *n)
4316 funcblocksize = offsetof(struct funcnode, n);
4319 blocksize = funcblocksize;
4320 f = ckmalloc(blocksize + funcstringsize);
4321 funcblock = (char *) f + offsetof(struct funcnode, n);
4322 funcstring = (char *) f + blocksize;
4329 * Define a shell function.
4333 defun(char *name, union node *func)
4335 struct cmdentry entry;
4338 entry.cmdtype = CMDFUNCTION;
4339 entry.u.func = copyfunc(func);
4340 addcmdentry(name, &entry);
4346 * Delete a function if it exists.
4350 unsetfunc(const char *name)
4352 struct tblentry *cmdp;
4354 if ((cmdp = cmdlookup(name, 0)) != NULL &&
4355 cmdp->cmdtype == CMDFUNCTION)
4360 * Locate and print what a word is...
4364 #ifdef CONFIG_ASH_CMDCMD
4366 describe_command(char *command, int describe_command_verbose)
4368 #define describe_command_verbose 1
4370 describe_command(char *command)
4373 struct cmdentry entry;
4374 struct tblentry *cmdp;
4375 #ifdef CONFIG_ASH_ALIAS
4376 const struct alias *ap;
4378 const char *path = pathval();
4380 if (describe_command_verbose) {
4384 /* First look at the keywords */
4385 if (findkwd(command)) {
4386 out1str(describe_command_verbose ? " is a shell keyword" : command);
4390 #ifdef CONFIG_ASH_ALIAS
4391 /* Then look at the aliases */
4392 if ((ap = lookupalias(command, 0)) != NULL) {
4393 if (describe_command_verbose) {
4394 out1fmt(" is an alias for %s", ap->val);
4403 /* Then check if it is a tracked alias */
4404 if ((cmdp = cmdlookup(command, 0)) != NULL) {
4405 entry.cmdtype = cmdp->cmdtype;
4406 entry.u = cmdp->param;
4408 /* Finally use brute force */
4409 find_command(command, &entry, DO_ABS, path);
4412 switch (entry.cmdtype) {
4414 int j = entry.u.index;
4420 p = padvance(&path, command);
4424 if (describe_command_verbose) {
4426 (cmdp ? " a tracked alias for" : nullstr), p
4435 if (describe_command_verbose) {
4436 out1str(" is a shell function");
4443 if (describe_command_verbose) {
4444 out1fmt(" is a %sshell builtin",
4445 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
4446 "special " : nullstr
4454 if (describe_command_verbose) {
4455 out1str(": not found\n");
4461 outstr("\n", stdout);
4466 typecmd(int argc, char **argv)
4471 for (i = 1; i < argc; i++) {
4472 #ifdef CONFIG_ASH_CMDCMD
4473 err |= describe_command(argv[i], 1);
4475 err |= describe_command(argv[i]);
4481 #ifdef CONFIG_ASH_CMDCMD
4483 commandcmd(int argc, char **argv)
4491 while ((c = nextopt("pvV")) != '\0')
4493 verify |= VERIFY_VERBOSE;
4495 verify |= VERIFY_BRIEF;
4501 return describe_command(*argptr, verify - VERIFY_BRIEF);
4510 * Routines to expand arguments to commands. We have to deal with
4511 * backquotes, shell variables, and file metacharacters.
4517 #define RMESCAPE_ALLOC 0x1 /* Allocate a new string */
4518 #define RMESCAPE_GLOB 0x2 /* Add backslashes for glob */
4519 #define RMESCAPE_QUOTED 0x4 /* Remove CTLESC unless in quotes */
4520 #define RMESCAPE_GROW 0x8 /* Grow strings instead of stalloc */
4521 #define RMESCAPE_HEAP 0x10 /* Malloc strings instead of stalloc */
4524 * Structure specifying which parts of the string should be searched
4525 * for IFS characters.
4529 struct ifsregion *next; /* next region in list */
4530 int begoff; /* offset of start of region */
4531 int endoff; /* offset of end of region */
4532 int nulonly; /* search for nul bytes only */
4535 /* output of current string */
4536 static char *expdest;
4537 /* list of back quote expressions */
4538 static struct nodelist *argbackq;
4539 /* first struct in list of ifs regions */
4540 static struct ifsregion ifsfirst;
4541 /* last struct in list */
4542 static struct ifsregion *ifslastp;
4543 /* holds expanded arg list */
4544 static struct arglist exparg;
4546 static void argstr(char *, int);
4547 static char *exptilde(char *, char *, int);
4548 static void expbackq(union node *, int, int);
4549 static const char *subevalvar(char *, char *, int, int, int, int, int);
4550 static char *evalvar(char *, int);
4551 static void strtodest(const char *, int, int);
4552 static void memtodest(const char *p, size_t len, int syntax, int quotes);
4553 static ssize_t varvalue(char *, int, int);
4554 static void recordregion(int, int, int);
4555 static void removerecordregions(int);
4556 static void ifsbreakup(char *, struct arglist *);
4557 static void ifsfree(void);
4558 static void expandmeta(struct strlist *, int);
4559 static int patmatch(char *, const char *);
4561 static int cvtnum(arith_t);
4562 static size_t esclen(const char *, const char *);
4563 static char *scanleft(char *, char *, char *, char *, int, int);
4564 static char *scanright(char *, char *, char *, char *, int, int);
4565 static void varunset(const char *, const char *, const char *, int)
4569 #define pmatch(a, b) !fnmatch((a), (b), 0)
4571 * Prepare a pattern for a expmeta (internal glob(3)) call.
4573 * Returns an stalloced string.
4576 static char * preglob(const char *pattern, int quoted, int flag) {
4577 flag |= RMESCAPE_GLOB;
4579 flag |= RMESCAPE_QUOTED;
4581 return _rmescapes((char *)pattern, flag);
4586 esclen(const char *start, const char *p) {
4589 while (p > start && *--p == CTLESC) {
4597 * Expand shell variables and backquotes inside a here document.
4600 static void expandhere(union node *arg, int fd)
4603 expandarg(arg, (struct arglist *)NULL, 0);
4604 full_write(fd, stackblock(), expdest - (char *)stackblock());
4609 * Perform variable substitution and command substitution on an argument,
4610 * placing the resulting list of arguments in arglist. If EXP_FULL is true,
4611 * perform splitting and file name expansion. When arglist is NULL, perform
4612 * here document expansion.
4616 expandarg(union node *arg, struct arglist *arglist, int flag)
4621 argbackq = arg->narg.backquote;
4622 STARTSTACKSTR(expdest);
4623 ifsfirst.next = NULL;
4625 argstr(arg->narg.text, flag);
4626 p = _STPUTC('\0', expdest);
4628 if (arglist == NULL) {
4629 return; /* here document expanded */
4631 p = grabstackstr(p);
4632 exparg.lastp = &exparg.list;
4636 if (flag & EXP_FULL) {
4637 ifsbreakup(p, &exparg);
4638 *exparg.lastp = NULL;
4639 exparg.lastp = &exparg.list;
4640 expandmeta(exparg.list, flag);
4642 if (flag & EXP_REDIR) /*XXX - for now, just remove escapes */
4644 sp = (struct strlist *)stalloc(sizeof (struct strlist));
4647 exparg.lastp = &sp->next;
4651 *exparg.lastp = NULL;
4653 *arglist->lastp = exparg.list;
4654 arglist->lastp = exparg.lastp;
4660 * Perform variable and command substitution. If EXP_FULL is set, output CTLESC
4661 * characters to allow for further processing. Otherwise treat
4662 * $@ like $* since no splitting will be performed.
4666 argstr(char *p, int flag)
4668 static const char spclchars[] = {
4676 CTLBACKQ | CTLQUOTE,
4677 #ifdef CONFIG_ASH_MATH_SUPPORT
4682 const char *reject = spclchars;
4684 int quotes = flag & (EXP_FULL | EXP_CASE); /* do CTLESC */
4685 int breakall = flag & EXP_WORD;
4690 if (!(flag & EXP_VARTILDE)) {
4692 } else if (flag & EXP_VARTILDE2) {
4697 if (flag & EXP_TILDE) {
4703 if (*q == CTLESC && (flag & EXP_QWORD))
4706 p = exptilde(p, q, flag);
4709 startloc = expdest - (char *)stackblock();
4711 length += strcspn(p + length, reject);
4713 if (c && (!(c & 0x80)
4714 #ifdef CONFIG_ASH_MATH_SUPPORT
4718 /* c == '=' || c == ':' || c == CTLENDARI */
4723 expdest = stnputs(p, length, expdest);
4724 newloc = expdest - (char *)stackblock();
4725 if (breakall && !inquotes && newloc > startloc) {
4726 recordregion(startloc, newloc, 0);
4737 if (flag & EXP_VARTILDE2) {
4741 flag |= EXP_VARTILDE2;
4746 * sort of a hack - expand tildes in variable
4747 * assignments (after the first '=' and after ':'s).
4756 case CTLENDVAR: /* ??? */
4759 /* "$@" syntax adherence hack */
4762 !memcmp(p, dolatstr, DOLATSTRLEN) &&
4763 (p[4] == CTLQUOTEMARK || (
4764 p[4] == CTLENDVAR &&
4765 p[5] == CTLQUOTEMARK
4768 p = evalvar(p + 1, flag) + 1;
4771 inquotes = !inquotes;
4784 p = evalvar(p, flag);
4788 case CTLBACKQ|CTLQUOTE:
4789 expbackq(argbackq->n, c, quotes);
4790 argbackq = argbackq->next;
4792 #ifdef CONFIG_ASH_MATH_SUPPORT
4805 exptilde(char *startp, char *p, int flag)
4811 int quotes = flag & (EXP_FULL | EXP_CASE);
4816 while ((c = *++p) != '\0') {
4823 if (flag & EXP_VARTILDE)
4833 if (*name == '\0') {
4834 home = lookupvar(homestr);
4836 if ((pw = getpwnam(name)) == NULL)
4840 if (!home || !*home)
4843 startloc = expdest - (char *)stackblock();
4844 strtodest(home, SQSYNTAX, quotes);
4845 recordregion(startloc, expdest - (char *)stackblock(), 0);
4854 removerecordregions(int endoff)
4856 if (ifslastp == NULL)
4859 if (ifsfirst.endoff > endoff) {
4860 while (ifsfirst.next != NULL) {
4861 struct ifsregion *ifsp;
4863 ifsp = ifsfirst.next->next;
4864 ckfree(ifsfirst.next);
4865 ifsfirst.next = ifsp;
4868 if (ifsfirst.begoff > endoff)
4871 ifslastp = &ifsfirst;
4872 ifsfirst.endoff = endoff;
4877 ifslastp = &ifsfirst;
4878 while (ifslastp->next && ifslastp->next->begoff < endoff)
4879 ifslastp=ifslastp->next;
4880 while (ifslastp->next != NULL) {
4881 struct ifsregion *ifsp;
4883 ifsp = ifslastp->next->next;
4884 ckfree(ifslastp->next);
4885 ifslastp->next = ifsp;
4888 if (ifslastp->endoff > endoff)
4889 ifslastp->endoff = endoff;
4893 #ifdef CONFIG_ASH_MATH_SUPPORT
4895 * Expand arithmetic expression. Backup to start of expression,
4896 * evaluate, place result in (backed up) result, adjust string position.
4909 * This routine is slightly over-complicated for
4910 * efficiency. Next we scan backwards looking for the
4911 * start of arithmetic.
4913 start = stackblock();
4920 while (*p != CTLARI) {
4924 sh_error("missing CTLARI (shouldn't happen)");
4929 esc = esclen(start, p);
4939 removerecordregions(begoff);
4948 len = cvtnum(dash_arith(p + 2));
4951 recordregion(begoff, begoff + len, 0);
4956 * Expand stuff in backwards quotes.
4960 expbackq(union node *cmd, int quoted, int quotes)
4968 int syntax = quoted? DQSYNTAX : BASESYNTAX;
4969 struct stackmark smark;
4972 setstackmark(&smark);
4974 startloc = dest - (char *)stackblock();
4976 evalbackcmd(cmd, (struct backcmd *) &in);
4977 popstackmark(&smark);
4984 memtodest(p, i, syntax, quotes);
4988 i = safe_read(in.fd, buf, sizeof buf);
4989 TRACE(("expbackq: read returns %d\n", i));
4999 back_exitstatus = waitforjob(in.jp);
5003 /* Eat all trailing newlines */
5005 for (; dest > (char *)stackblock() && dest[-1] == '\n';)
5010 recordregion(startloc, dest - (char *)stackblock(), 0);
5011 TRACE(("evalbackq: size=%d: \"%.*s\"\n",
5012 (dest - (char *)stackblock()) - startloc,
5013 (dest - (char *)stackblock()) - startloc,
5014 stackblock() + startloc));
5019 scanleft(char *startp, char *rmesc, char *rmescend, char *str, int quotes,
5030 const char *s = loc2;
5036 match = pmatch(str, s);
5040 if (quotes && *loc == CTLESC)
5050 scanright(char *startp, char *rmesc, char *rmescend, char *str, int quotes,
5057 for (loc = str - 1, loc2 = rmescend; loc >= startp; loc2--) {
5060 const char *s = loc2;
5065 match = pmatch(str, s);
5072 esc = esclen(startp, loc);
5084 subevalvar(char *p, char *str, int strloc, int subtype, int startloc, int varflags, int quotes)
5088 int saveherefd = herefd;
5089 struct nodelist *saveargbackq = argbackq;
5091 char *rmesc, *rmescend;
5093 char *(*scan)(char *, char *, char *, char *, int , int);
5096 argstr(p, subtype != VSASSIGN && subtype != VSQUESTION ? EXP_CASE : 0);
5097 STPUTC('\0', expdest);
5098 herefd = saveherefd;
5099 argbackq = saveargbackq;
5100 startp = stackblock() + startloc;
5104 setvar(str, startp, 0);
5105 amount = startp - expdest;
5106 STADJUST(amount, expdest);
5110 varunset(p, str, startp, varflags);
5114 subtype -= VSTRIMRIGHT;
5116 if (subtype < 0 || subtype > 3)
5121 rmescend = stackblock() + strloc;
5123 rmesc = _rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW);
5124 if (rmesc != startp) {
5126 startp = stackblock() + startloc;
5130 str = stackblock() + strloc;
5131 preglob(str, varflags & VSQUOTE, 0);
5133 /* zero = subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX */
5134 zero = subtype >> 1;
5135 /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
5136 scan = (subtype & 1) ^ zero ? scanleft : scanright;
5138 loc = scan(startp, rmesc, rmescend, str, quotes, zero);
5141 memmove(startp, loc, str - loc);
5142 loc = startp + (str - loc) - 1;
5145 amount = loc - expdest;
5146 STADJUST(amount, expdest);
5153 * Expand a variable, and return a pointer to the next character in the
5157 evalvar(char *p, int flag)
5170 quotes = flag & (EXP_FULL | EXP_CASE);
5172 subtype = varflags & VSTYPE;
5173 quoted = varflags & VSQUOTE;
5175 easy = (!quoted || (*var == '@' && shellparam.nparam));
5176 startloc = expdest - (char *)stackblock();
5177 p = strchr(p, '=') + 1;
5180 varlen = varvalue(var, varflags, flag);
5181 if (varflags & VSNUL)
5184 if (subtype == VSPLUS) {
5185 varlen = -1 - varlen;
5189 if (subtype == VSMINUS) {
5193 p, flag | EXP_TILDE |
5194 (quoted ? EXP_QWORD : EXP_WORD)
5203 if (subtype == VSASSIGN || subtype == VSQUESTION) {
5205 if (subevalvar(p, var, 0, subtype, startloc,
5209 * Remove any recorded regions beyond
5212 removerecordregions(startloc);
5222 if (varlen < 0 && uflag)
5223 varunset(p, var, 0, 0);
5225 if (subtype == VSLENGTH) {
5226 cvtnum(varlen > 0 ? varlen : 0);
5230 if (subtype == VSNORMAL) {
5234 recordregion(startloc, expdest - (char *)stackblock(), quoted);
5243 case VSTRIMRIGHTMAX:
5252 * Terminate the string and start recording the pattern
5255 STPUTC('\0', expdest);
5256 patloc = expdest - (char *)stackblock();
5257 if (subevalvar(p, NULL, patloc, subtype,
5258 startloc, varflags, quotes) == 0) {
5259 int amount = expdest - (
5260 (char *)stackblock() + patloc - 1
5262 STADJUST(-amount, expdest);
5264 /* Remove any recorded regions beyond start of variable */
5265 removerecordregions(startloc);
5270 if (subtype != VSNORMAL) { /* skip to end of alternative */
5273 if ((c = *p++) == CTLESC)
5275 else if (c == CTLBACKQ || c == (CTLBACKQ|CTLQUOTE)) {
5277 argbackq = argbackq->next;
5278 } else if (c == CTLVAR) {
5279 if ((*p++ & VSTYPE) != VSNORMAL)
5281 } else if (c == CTLENDVAR) {
5292 * Put a string on the stack.
5296 memtodest(const char *p, size_t len, int syntax, int quotes) {
5299 q = makestrspace(len * 2, q);
5302 int c = SC2INT(*p++);
5305 if (quotes && (SIT(c, syntax) == CCTL || SIT(c, syntax) == CBACK))
5315 strtodest(const char *p, int syntax, int quotes)
5317 memtodest(p, strlen(p), syntax, quotes);
5322 * Add the value of a specialized variable to the stack string.
5326 varvalue(char *name, int varflags, int flags)
5336 int quoted = varflags & VSQUOTE;
5337 int subtype = varflags & VSTYPE;
5338 int quotes = flags & (EXP_FULL | EXP_CASE);
5340 if (quoted && (flags & EXP_FULL))
5341 sep = 1 << CHAR_BIT;
5343 syntax = quoted ? DQSYNTAX : BASESYNTAX;
5352 num = shellparam.nparam;
5362 p = makestrspace(NOPTS, expdest);
5363 for (i = NOPTS - 1; i >= 0; i--) {
5365 USTPUTC(optletters(i), p);
5376 sep = ifsset() ? SC2INT(ifsval()[0]) : ' ';
5377 if (quotes && (SIT(sep, syntax) == CCTL || SIT(sep, syntax) == CBACK))
5380 if (!(ap = shellparam.p))
5382 while ((p = *ap++)) {
5385 partlen = strlen(p);
5388 if (!(subtype == VSPLUS || subtype == VSLENGTH))
5389 memtodest(p, partlen, syntax, quotes);
5395 if (subtype == VSPLUS || subtype == VSLENGTH) {
5417 if (num < 0 || num > shellparam.nparam)
5419 p = num ? shellparam.p[num - 1] : arg0;
5422 p = lookupvar(name);
5428 if (!(subtype == VSPLUS || subtype == VSLENGTH))
5429 memtodest(p, len, syntax, quotes);
5433 if (subtype == VSPLUS || subtype == VSLENGTH)
5434 STADJUST(-len, expdest);
5440 * Record the fact that we have to scan this region of the
5441 * string for IFS characters.
5445 recordregion(int start, int end, int nulonly)
5447 struct ifsregion *ifsp;
5449 if (ifslastp == NULL) {
5453 ifsp = (struct ifsregion *)ckmalloc(sizeof (struct ifsregion));
5455 ifslastp->next = ifsp;
5459 ifslastp->begoff = start;
5460 ifslastp->endoff = end;
5461 ifslastp->nulonly = nulonly;
5466 * Break the argument string into pieces based upon IFS and add the
5467 * strings to the argument list. The regions of the string to be
5468 * searched for IFS characters have been stored by recordregion.
5471 ifsbreakup(char *string, struct arglist *arglist)
5473 struct ifsregion *ifsp;
5478 const char *ifs, *realifs;
5484 if (ifslastp != NULL) {
5487 realifs = ifsset() ? ifsval() : defifs;
5490 p = string + ifsp->begoff;
5491 nulonly = ifsp->nulonly;
5492 ifs = nulonly ? nullstr : realifs;
5494 while (p < string + ifsp->endoff) {
5498 if (strchr(ifs, *p)) {
5500 ifsspc = (strchr(defifs, *p) != NULL);
5501 /* Ignore IFS whitespace at start */
5502 if (q == start && ifsspc) {
5508 sp = (struct strlist *)stalloc(sizeof *sp);
5510 *arglist->lastp = sp;
5511 arglist->lastp = &sp->next;
5515 if (p >= string + ifsp->endoff) {
5521 if (strchr(ifs, *p) == NULL ) {
5524 } else if (strchr(defifs, *p) == NULL) {
5540 } while ((ifsp = ifsp->next) != NULL);
5549 sp = (struct strlist *)stalloc(sizeof *sp);
5551 *arglist->lastp = sp;
5552 arglist->lastp = &sp->next;
5558 struct ifsregion *p;
5563 struct ifsregion *ifsp;
5569 ifsfirst.next = NULL;
5573 static void expmeta(char *, char *);
5574 static struct strlist *expsort(struct strlist *);
5575 static struct strlist *msort(struct strlist *, int);
5577 static char *expdir;
5581 expandmeta(struct strlist *str, int flag)
5583 static const char metachars[] = {
5586 /* TODO - EXP_REDIR */
5589 struct strlist **savelastp;
5595 if (!strpbrk(str->text, metachars))
5597 savelastp = exparg.lastp;
5600 p = preglob(str->text, 0, RMESCAPE_ALLOC | RMESCAPE_HEAP);
5602 int i = strlen(str->text);
5603 expdir = ckmalloc(i < 2048 ? 2048 : i); /* XXX */
5611 if (exparg.lastp == savelastp) {
5616 *exparg.lastp = str;
5617 rmescapes(str->text);
5618 exparg.lastp = &str->next;
5620 *exparg.lastp = NULL;
5621 *savelastp = sp = expsort(*savelastp);
5622 while (sp->next != NULL)
5624 exparg.lastp = &sp->next;
5631 * Add a file name to the list.
5635 addfname(const char *name)
5639 sp = (struct strlist *)stalloc(sizeof *sp);
5640 sp->text = sstrdup(name);
5642 exparg.lastp = &sp->next;
5647 * Do metacharacter (i.e. *, ?, [...]) expansion.
5651 expmeta(char *enddir, char *name)
5666 for (p = name; *p; p++) {
5667 if (*p == '*' || *p == '?')
5669 else if (*p == '[') {
5676 if (*q == '/' || *q == '\0')
5683 } else if (*p == '\\')
5685 else if (*p == '/') {
5692 if (metaflag == 0) { /* we've reached the end of the file name */
5693 if (enddir != expdir)
5701 if (metaflag == 0 || lstat(expdir, &statb) >= 0)
5712 } while (p < start);
5714 if (enddir == expdir) {
5716 } else if (enddir == expdir + 1 && *expdir == '/') {
5722 if ((dirp = opendir(cp)) == NULL)
5724 if (enddir != expdir)
5726 if (*endname == 0) {
5738 while (! intpending && (dp = readdir(dirp)) != NULL) {
5739 if (dp->d_name[0] == '.' && ! matchdot)
5741 if (pmatch(start, dp->d_name)) {
5743 scopy(dp->d_name, enddir);
5746 for (p = enddir, cp = dp->d_name;
5747 (*p++ = *cp++) != '\0';)
5750 expmeta(p, endname);
5760 * Sort the results of file name expansion. It calculates the number of
5761 * strings to sort and then calls msort (short for merge sort) to do the
5765 static struct strlist *
5766 expsort(struct strlist *str)
5772 for (sp = str ; sp ; sp = sp->next)
5774 return msort(str, len);
5778 static struct strlist *
5779 msort(struct strlist *list, int len)
5781 struct strlist *p, *q = NULL;
5782 struct strlist **lpp;
5790 for (n = half ; --n >= 0 ; ) {
5794 q->next = NULL; /* terminate first half of list */
5795 q = msort(list, half); /* sort first half of list */
5796 p = msort(p, len - half); /* sort second half */
5799 #ifdef CONFIG_LOCALE_SUPPORT
5800 if (strcoll(p->text, q->text) < 0)
5802 if (strcmp(p->text, q->text) < 0)
5807 if ((p = *lpp) == NULL) {
5814 if ((q = *lpp) == NULL) {
5825 * Returns true if the pattern matches the string.
5828 static int patmatch(char *pattern, const char *string)
5830 return pmatch(preglob(pattern, 0, 0), string);
5835 * Remove any CTLESC characters from a string.
5839 _rmescapes(char *str, int flag)
5842 static const char qchars[] = { CTLESC, CTLQUOTEMARK, 0 };
5847 p = strpbrk(str, qchars);
5853 if (flag & RMESCAPE_ALLOC) {
5854 size_t len = p - str;
5855 size_t fulllen = len + strlen(p) + 1;
5857 if (flag & RMESCAPE_GROW) {
5858 r = makestrspace(fulllen, expdest);
5859 } else if (flag & RMESCAPE_HEAP) {
5860 r = ckmalloc(fulllen);
5862 r = stalloc(fulllen);
5866 q = memcpy(q, str, len) + len;
5869 inquotes = (flag & RMESCAPE_QUOTED) ^ RMESCAPE_QUOTED;
5870 globbing = flag & RMESCAPE_GLOB;
5871 notescaped = globbing;
5873 if (*p == CTLQUOTEMARK) {
5874 inquotes = ~inquotes;
5876 notescaped = globbing;
5880 /* naked back slash */
5886 if (notescaped && inquotes && *p != '/') {
5890 notescaped = globbing;
5895 if (flag & RMESCAPE_GROW) {
5897 STADJUST(q - r + 1, expdest);
5904 * See if a pattern matches in a case statement.
5908 casematch(union node *pattern, char *val)
5910 struct stackmark smark;
5913 setstackmark(&smark);
5914 argbackq = pattern->narg.backquote;
5915 STARTSTACKSTR(expdest);
5917 argstr(pattern->narg.text, EXP_TILDE | EXP_CASE);
5918 STACKSTRNUL(expdest);
5919 result = patmatch(stackblock(), val);
5920 popstackmark(&smark);
5933 expdest = makestrspace(32, expdest);
5934 #ifdef CONFIG_ASH_MATH_SUPPORT_64
5935 len = fmtstr(expdest, 32, "%lld", (long long) num);
5937 len = fmtstr(expdest, 32, "%ld", num);
5939 STADJUST(len, expdest);
5944 varunset(const char *end, const char *var, const char *umsg, int varflags)
5950 msg = "parameter not set";
5952 if (*end == CTLENDVAR) {
5953 if (varflags & VSNUL)
5958 sh_error("%.*s: %s%s", end - var - 1, var, msg, tail);
5965 * This implements the input routines used by the parser.
5968 #define EOF_NLEFT -99 /* value of parsenleft when EOF pushed back */
5970 static void pushfile(void);
5973 * Read a character from the script, returning PEOF on end of file.
5974 * Nul characters in the input are silently discarded.
5978 #define pgetc_as_macro() (--parsenleft >= 0? SC2INT(*parsenextc++) : preadbuffer())
5980 #ifdef CONFIG_ASH_OPTIMIZE_FOR_SIZE
5981 #define pgetc_macro() pgetc()
5985 return pgetc_as_macro();
5988 #define pgetc_macro() pgetc_as_macro()
5992 return pgetc_macro();
5998 * Same as pgetc(), but ignores PEOA.
6000 #ifdef CONFIG_ASH_ALIAS
6001 static int pgetc2(void)
6007 } while (c == PEOA);
6011 static int pgetc2(void)
6013 return pgetc_macro();
6018 * Read a line from the script.
6021 static char * pfgets(char *line, int len)
6027 while (--nleft > 0) {
6043 #if ENABLE_FEATURE_COMMAND_EDITING
6044 static line_input_t *line_input_state;
6045 //static SKIP_ASH_EXPAND_PRMT(const) char *cmdedit_prompt;
6046 static const char *cmdedit_prompt;
6047 static void putprompt(const char *s)
6049 if (ENABLE_ASH_EXPAND_PRMT) {
6050 free((char*)cmdedit_prompt);
6051 cmdedit_prompt = xstrdup(s);
6057 static void putprompt(const char *s)
6063 #if ENABLE_FEATURE_COMMAND_EDITING_VI
6064 #define setvimode(on) do { \
6065 if (on) line_input_state->flags |= VI_MODE; \
6066 else line_input_state->flags &= ~VI_MODE; \
6069 #define setvimode(on) viflag = 0 /* forcibly keep the option off */
6073 static int preadfd(void)
6076 char *buf = parsefile->buf;
6080 #if ENABLE_FEATURE_COMMAND_EDITING
6081 if (!iflag || parsefile->fd)
6082 nr = safe_read(parsefile->fd, buf, BUFSIZ - 1);
6084 #if ENABLE_FEATURE_COMMAND_TAB_COMPLETION
6085 line_input_state->path_lookup = pathval();
6087 nr = read_line_input(cmdedit_prompt, buf, BUFSIZ, line_input_state);
6089 /* Ctrl+C pressed */
6098 if (nr < 0 && errno == 0) {
6099 /* Ctrl+D presend */
6104 nr = safe_read(parsefile->fd, buf, BUFSIZ - 1);
6108 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
6109 int flags = fcntl(0, F_GETFL, 0);
6110 if (flags >= 0 && flags & O_NONBLOCK) {
6111 flags &=~ O_NONBLOCK;
6112 if (fcntl(0, F_SETFL, flags) >= 0) {
6113 out2str("sh: turning off NDELAY mode\n");
6123 * Refill the input buffer and return the next input character:
6125 * 1) If a string was pushed back on the input, pop it;
6126 * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading
6127 * from a string so we can't refill the buffer, return EOF.
6128 * 3) If the is more stuff in this buffer, use it else call read to fill it.
6129 * 4) Process input up to the next newline, deleting nul characters.
6139 while (parsefile->strpush) {
6140 #ifdef CONFIG_ASH_ALIAS
6141 if (parsenleft == -1 && parsefile->strpush->ap &&
6142 parsenextc[-1] != ' ' && parsenextc[-1] != '\t') {
6147 if (--parsenleft >= 0)
6148 return SC2INT(*parsenextc++);
6150 if (parsenleft == EOF_NLEFT || parsefile->buf == NULL)
6157 if ((more = preadfd()) <= 0) {
6158 parselleft = parsenleft = EOF_NLEFT;
6165 /* delete nul characters */
6173 memmove(q, q + 1, more);
6177 parsenleft = q - parsenextc - 1;
6183 parsenleft = q - parsenextc - 1;
6195 out2str(parsenextc);
6200 return SC2INT(*parsenextc++);
6204 * Undo the last call to pgetc. Only one character may be pushed back.
6205 * PEOF may be pushed back.
6216 * Push a string back onto the input at this current parsefile level.
6217 * We handle aliases this way.
6220 pushstring(char *s, void *ap)
6227 /*dprintf("*** calling pushstring: %s, %d\n", s, len);*/
6228 if (parsefile->strpush) {
6229 sp = ckmalloc(sizeof (struct strpush));
6230 sp->prev = parsefile->strpush;
6231 parsefile->strpush = sp;
6233 sp = parsefile->strpush = &(parsefile->basestrpush);
6234 sp->prevstring = parsenextc;
6235 sp->prevnleft = parsenleft;
6236 #ifdef CONFIG_ASH_ALIAS
6237 sp->ap = (struct alias *)ap;
6239 ((struct alias *)ap)->flag |= ALIASINUSE;
6251 struct strpush *sp = parsefile->strpush;
6254 #ifdef CONFIG_ASH_ALIAS
6256 if (parsenextc[-1] == ' ' || parsenextc[-1] == '\t') {
6257 checkkwd |= CHKALIAS;
6259 if (sp->string != sp->ap->val) {
6262 sp->ap->flag &= ~ALIASINUSE;
6263 if (sp->ap->flag & ALIASDEAD) {
6264 unalias(sp->ap->name);
6268 parsenextc = sp->prevstring;
6269 parsenleft = sp->prevnleft;
6270 /*dprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/
6271 parsefile->strpush = sp->prev;
6272 if (sp != &(parsefile->basestrpush))
6278 * Set the input to take input from a file. If push is set, push the
6279 * old input onto the stack first.
6283 setinputfile(const char *fname, int flags)
6289 if ((fd = open(fname, O_RDONLY)) < 0) {
6290 if (flags & INPUT_NOFILE_OK)
6292 sh_error("Can't open %s", fname);
6295 fd2 = copyfd(fd, 10);
6298 sh_error("Out of file descriptors");
6301 setinputfd(fd, flags & INPUT_PUSH_FILE);
6309 * Like setinputfile, but takes an open file descriptor. Call this with
6314 setinputfd(int fd, int push)
6316 (void) fcntl(fd, F_SETFD, FD_CLOEXEC);
6322 if (parsefile->buf == NULL)
6323 parsefile->buf = ckmalloc(IBUFSIZ);
6324 parselleft = parsenleft = 0;
6330 * Like setinputfile, but takes input from a string.
6334 setinputstring(char *string)
6338 parsenextc = string;
6339 parsenleft = strlen(string);
6340 parsefile->buf = NULL;
6347 * To handle the "." command, a stack of input files is used. Pushfile
6348 * adds a new entry to the stack and popfile restores the previous level.
6354 struct parsefile *pf;
6356 parsefile->nleft = parsenleft;
6357 parsefile->lleft = parselleft;
6358 parsefile->nextc = parsenextc;
6359 parsefile->linno = plinno;
6360 pf = (struct parsefile *)ckmalloc(sizeof (struct parsefile));
6361 pf->prev = parsefile;
6364 pf->basestrpush.prev = NULL;
6372 struct parsefile *pf = parsefile;
6381 parsefile = pf->prev;
6383 parsenleft = parsefile->nleft;
6384 parselleft = parsefile->lleft;
6385 parsenextc = parsefile->nextc;
6386 plinno = parsefile->linno;
6392 * Return to top level.
6398 while (parsefile != &basepf)
6404 * Close the file(s) that the shell is reading commands from. Called
6405 * after a fork is done.
6412 if (parsefile->fd > 0) {
6413 close(parsefile->fd);
6420 /* mode flags for set_curjob */
6421 #define CUR_DELETE 2
6422 #define CUR_RUNNING 1
6423 #define CUR_STOPPED 0
6425 /* mode flags for dowait */
6426 #define DOWAIT_NORMAL 0
6427 #define DOWAIT_BLOCK 1
6430 static struct job *jobtab;
6432 static unsigned njobs;
6434 /* pgrp of shell on invocation */
6435 static int initialpgrp;
6436 static int ttyfd = -1;
6439 static struct job *curjob;
6440 /* number of presumed living untracked jobs */
6443 static void set_curjob(struct job *, unsigned);
6445 static int restartjob(struct job *, int);
6446 static void xtcsetpgrp(int, pid_t);
6447 static char *commandtext(union node *);
6448 static void cmdlist(union node *, int);
6449 static void cmdtxt(union node *);
6450 static void cmdputs(const char *);
6451 static void showpipe(struct job *, FILE *);
6453 static int sprint_status(char *, int, int);
6454 static void freejob(struct job *);
6455 static struct job *getjob(const char *, int);
6456 static struct job *growjobtab(void);
6457 static void forkchild(struct job *, union node *, int);
6458 static void forkparent(struct job *, union node *, int, pid_t);
6459 static int dowait(int, struct job *);
6460 static int getstatus(struct job *);
6463 set_curjob(struct job *jp, unsigned mode)
6466 struct job **jpp, **curp;
6468 /* first remove from list */
6469 jpp = curp = &curjob;
6474 jpp = &jp1->prev_job;
6476 *jpp = jp1->prev_job;
6478 /* Then re-insert in correct position */
6486 /* job being deleted */
6489 /* newly created job or backgrounded job,
6490 put after all stopped jobs. */
6494 if (!jp1 || jp1->state != JOBSTOPPED)
6497 jpp = &jp1->prev_job;
6503 /* newly stopped job - becomes curjob */
6504 jp->prev_job = *jpp;
6512 * Turn job control on and off.
6514 * Note: This code assumes that the third arg to ioctl is a character
6515 * pointer, which is true on Berkeley systems but not System V. Since
6516 * System V doesn't have job control yet, this isn't a problem now.
6518 * Called with interrupts off.
6527 if (on == jobctl || rootshell == 0)
6531 ofd = fd = open(_PATH_TTY, O_RDWR);
6533 /* BTW, bash will try to open(ttyname(0)) if open("/dev/tty") fails.
6534 * That sometimes helps to acquire controlling tty.
6535 * Obviously, a workaround for bugs when someone
6536 * failed to provide a controlling tty to bash! :) */
6538 while (!isatty(fd) && --fd >= 0)
6541 fd = fcntl(fd, F_DUPFD, 10);
6545 fcntl(fd, F_SETFD, FD_CLOEXEC);
6546 do { /* while we are in the background */
6547 if ((pgrp = tcgetpgrp(fd)) < 0) {
6549 sh_warnx("can't access tty; job control turned off");
6553 if (pgrp == getpgrp())
6564 xtcsetpgrp(fd, pgrp);
6566 /* turning job control off */
6569 xtcsetpgrp(fd, pgrp);
6583 killcmd(int argc, char **argv)
6594 "Usage: kill [-s sigspec | -signum | -sigspec] [pid | job]... or\n"
6595 "kill -l [exitstatus]"
6599 if (**++argv == '-') {
6600 signo = get_signum(*argv + 1);
6604 while ((c = nextopt("ls:")) != '\0')
6614 signo = get_signum(optionarg);
6617 "invalid signal number or name: %s",
6628 if (!list && signo < 0)
6631 if ((signo < 0 || !*argv) ^ list) {
6639 for (i = 1; i < NSIG; i++) {
6640 name = get_signame(i);
6642 out1fmt(snlfmt, name);
6646 name = get_signame(signo);
6648 out1fmt(snlfmt, name);
6650 sh_error("invalid signal number or exit status: %s", *argptr);
6656 if (**argv == '%') {
6657 jp = getjob(*argv, 0);
6658 pid = -jp->ps[0].pid;
6660 pid = **argv == '-' ?
6661 -number(*argv + 1) : number(*argv);
6663 if (kill(pid, signo) != 0) {
6664 sh_warnx("(%d) - %m", pid);
6675 jobno(const struct job *jp)
6677 return jp - jobtab + 1;
6683 fgcmd(int argc, char **argv)
6690 mode = (**argv == 'f') ? FORK_FG : FORK_BG;
6695 jp = getjob(*argv, 1);
6696 if (mode == FORK_BG) {
6697 set_curjob(jp, CUR_RUNNING);
6698 fprintf(out, "[%d] ", jobno(jp));
6700 outstr(jp->ps->cmd, out);
6702 retval = restartjob(jp, mode);
6703 } while (*argv && *++argv);
6707 static int bgcmd(int, char **) __attribute__((__alias__("fgcmd")));
6711 restartjob(struct job *jp, int mode)
6713 struct procstat *ps;
6719 if (jp->state == JOBDONE)
6721 jp->state = JOBRUNNING;
6723 if (mode == FORK_FG)
6724 xtcsetpgrp(ttyfd, pgid);
6725 killpg(pgid, SIGCONT);
6729 if (WIFSTOPPED(ps->status)) {
6732 } while (ps++, --i);
6734 status = (mode == FORK_FG) ? waitforjob(jp) : 0;
6741 sprint_status(char *s, int status, int sigonly)
6747 if (!WIFEXITED(status)) {
6749 if (WIFSTOPPED(status))
6750 st = WSTOPSIG(status);
6753 st = WTERMSIG(status);
6755 if (st == SIGINT || st == SIGPIPE)
6758 if (WIFSTOPPED(status))
6763 col = fmtstr(s, 32, strsignal(st));
6764 if (WCOREDUMP(status)) {
6765 col += fmtstr(s + col, 16, " (core dumped)");
6767 } else if (!sigonly) {
6768 st = WEXITSTATUS(status);
6770 col = fmtstr(s, 16, "Done(%d)", st);
6772 col = fmtstr(s, 16, "Done");
6781 showjob(FILE *out, struct job *jp, int mode)
6783 struct procstat *ps;
6784 struct procstat *psend;
6791 if (mode & SHOW_PGID) {
6792 /* just output process (group) id of pipeline */
6793 fprintf(out, "%d\n", ps->pid);
6797 col = fmtstr(s, 16, "[%d] ", jobno(jp));
6802 else if (curjob && jp == curjob->prev_job)
6805 if (mode & SHOW_PID)
6806 col += fmtstr(s + col, 16, "%d ", ps->pid);
6808 psend = ps + jp->nprocs;
6810 if (jp->state == JOBRUNNING) {
6811 scopy("Running", s + col);
6812 col += strlen("Running");
6814 int status = psend[-1].status;
6816 if (jp->state == JOBSTOPPED)
6817 status = jp->stopstatus;
6819 col += sprint_status(s + col, status, 0);
6825 /* for each process */
6826 col = fmtstr(s, 48, " |\n%*c%d ", indent, ' ', ps->pid) - 3;
6829 fprintf(out, "%s%*c%s",
6830 s, 33 - col >= 0 ? 33 - col : 0, ' ', ps->cmd
6832 if (!(mode & SHOW_PID)) {
6836 if (++ps == psend) {
6837 outcslow('\n', out);
6844 if (jp->state == JOBDONE) {
6845 TRACE(("showjob: freeing job %d\n", jobno(jp)));
6852 jobscmd(int argc, char **argv)
6858 while ((m = nextopt("lp")))
6868 showjob(out, getjob(*argv,0), mode);
6871 showjobs(out, mode);
6878 * Print a list of jobs. If "change" is nonzero, only print jobs whose
6879 * statuses have changed since the last call to showjobs.
6883 showjobs(FILE *out, int mode)
6887 TRACE(("showjobs(%x) called\n", mode));
6889 /* If not even one one job changed, there is nothing to do */
6890 while (dowait(DOWAIT_NORMAL, NULL) > 0)
6893 for (jp = curjob; jp; jp = jp->prev_job) {
6894 if (!(mode & SHOW_CHANGED) || jp->changed)
6895 showjob(out, jp, mode);
6901 * Mark a job structure as unused.
6905 freejob(struct job *jp)
6907 struct procstat *ps;
6911 for (i = jp->nprocs, ps = jp->ps ; --i >= 0 ; ps++) {
6912 if (ps->cmd != nullstr)
6915 if (jp->ps != &jp->ps0)
6918 set_curjob(jp, CUR_DELETE);
6924 waitcmd(int argc, char **argv)
6937 /* wait for all jobs */
6942 /* no running procs */
6945 if (jp->state == JOBRUNNING)
6950 dowait(DOWAIT_BLOCK, 0);
6956 if (**argv != '%') {
6957 pid_t pid = number(*argv);
6961 if (job->ps[job->nprocs - 1].pid == pid)
6963 job = job->prev_job;
6969 job = getjob(*argv, 0);
6970 /* loop until process terminated or stopped */
6971 while (job->state == JOBRUNNING)
6972 dowait(DOWAIT_BLOCK, 0);
6974 retval = getstatus(job);
6985 * Convert a job name to a job structure.
6989 getjob(const char *name, int getctl)
6993 const char *err_msg = "No such job: %s";
6997 char *(*match)(const char *, const char *);
7012 if (c == '+' || c == '%') {
7014 err_msg = "No current job";
7016 } else if (c == '-') {
7019 err_msg = "No previous job";
7030 jp = jobtab + num - 1;
7047 if (match(jp->ps[0].cmd, p)) {
7051 err_msg = "%s: ambiguous";
7058 err_msg = "job %s not created under job control";
7059 if (getctl && jp->jobctl == 0)
7064 sh_error(err_msg, name);
7069 * Return a new job structure.
7070 * Called with interrupts off.
7074 makejob(union node *node, int nprocs)
7079 for (i = njobs, jp = jobtab ; ; jp++) {
7086 if (jp->state != JOBDONE || !jp->waited)
7095 memset(jp, 0, sizeof(*jp));
7100 jp->prev_job = curjob;
7105 jp->ps = ckmalloc(nprocs * sizeof (struct procstat));
7107 TRACE(("makejob(0x%lx, %d) returns %%%d\n", (long)node, nprocs,
7117 struct job *jp, *jq;
7119 len = njobs * sizeof(*jp);
7121 jp = ckrealloc(jq, len + 4 * sizeof(*jp));
7123 offset = (char *)jp - (char *)jq;
7125 /* Relocate pointers */
7128 jq = (struct job *)((char *)jq + l);
7132 #define joff(p) ((struct job *)((char *)(p) + l))
7133 #define jmove(p) (p) = (void *)((char *)(p) + offset)
7134 if (xlikely(joff(jp)->ps == &jq->ps0))
7135 jmove(joff(jp)->ps);
7136 if (joff(jp)->prev_job)
7137 jmove(joff(jp)->prev_job);
7147 jp = (struct job *)((char *)jp + len);
7151 } while (--jq >= jp);
7157 * Fork off a subshell. If we are doing job control, give the subshell its
7158 * own process group. Jp is a job structure that the job is to be added to.
7159 * N is the command that will be evaluated by the child. Both jp and n may
7160 * be NULL. The mode parameter can be one of the following:
7161 * FORK_FG - Fork off a foreground process.
7162 * FORK_BG - Fork off a background process.
7163 * FORK_NOJOB - Like FORK_FG, but don't give the process its own
7164 * process group even if job control is on.
7166 * When job control is turned off, background processes have their standard
7167 * input redirected to /dev/null (except for the second and later processes
7170 * Called with interrupts off.
7173 static void forkchild(struct job *jp, union node *n, int mode)
7177 TRACE(("Child shell %d\n", getpid()));
7184 /* do job control only in root shell */
7186 if (mode != FORK_NOJOB && jp->jobctl && !oldlvl) {
7189 if (jp->nprocs == 0)
7192 pgrp = jp->ps[0].pid;
7193 /* This can fail because we are doing it in the parent also */
7194 (void)setpgid(0, pgrp);
7195 if (mode == FORK_FG)
7196 xtcsetpgrp(ttyfd, pgrp);
7201 if (mode == FORK_BG) {
7204 if (jp->nprocs == 0) {
7206 if (open(bb_dev_null, O_RDONLY) != 0)
7207 sh_error("Can't open %s", bb_dev_null);
7210 if (!oldlvl && iflag) {
7215 for (jp = curjob; jp; jp = jp->prev_job)
7220 static void forkparent(struct job *jp, union node *n, int mode, pid_t pid)
7222 TRACE(("In parent shell: child = %d\n", pid));
7224 while (jobless && dowait(DOWAIT_NORMAL, 0) > 0);
7229 if (mode != FORK_NOJOB && jp->jobctl) {
7232 if (jp->nprocs == 0)
7235 pgrp = jp->ps[0].pid;
7236 /* This can fail because we are doing it in the child also */
7237 (void)setpgid(pid, pgrp);
7240 if (mode == FORK_BG) {
7241 backgndpid = pid; /* set $! */
7242 set_curjob(jp, CUR_RUNNING);
7245 struct procstat *ps = &jp->ps[jp->nprocs++];
7251 ps->cmd = commandtext(n);
7257 forkshell(struct job *jp, union node *n, int mode)
7261 TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode));
7264 TRACE(("Fork failed, errno=%d", errno));
7267 sh_error("Cannot fork");
7270 forkchild(jp, n, mode);
7272 forkparent(jp, n, mode, pid);
7277 * Wait for job to finish.
7279 * Under job control we have the problem that while a child process is
7280 * running interrupts generated by the user are sent to the child but not
7281 * to the shell. This means that an infinite loop started by an inter-
7282 * active user may be hard to kill. With job control turned off, an
7283 * interactive user may place an interactive program inside a loop. If
7284 * the interactive program catches interrupts, the user doesn't want
7285 * these interrupts to also abort the loop. The approach we take here
7286 * is to have the shell ignore interrupt signals while waiting for a
7287 * foreground process to terminate, and then send itself an interrupt
7288 * signal if the child process was terminated by an interrupt signal.
7289 * Unfortunately, some programs want to do a bit of cleanup and then
7290 * exit on interrupt; unless these processes terminate themselves by
7291 * sending a signal to themselves (instead of calling exit) they will
7292 * confuse this approach.
7294 * Called with interrupts off.
7298 waitforjob(struct job *jp)
7302 TRACE(("waitforjob(%%%d) called\n", jobno(jp)));
7303 while (jp->state == JOBRUNNING) {
7304 dowait(DOWAIT_BLOCK, jp);
7309 xtcsetpgrp(ttyfd, rootpid);
7311 * This is truly gross.
7312 * If we're doing job control, then we did a TIOCSPGRP which
7313 * caused us (the shell) to no longer be in the controlling
7314 * session -- so we wouldn't have seen any ^C/SIGINT. So, we
7315 * intuit from the subprocess exit status whether a SIGINT
7316 * occurred, and if so interrupt ourselves. Yuck. - mycroft
7321 if (jp->state == JOBDONE)
7329 * Do a wait system call. If job control is compiled in, we accept
7330 * stopped processes. If block is zero, we return a value of zero
7331 * rather than blocking.
7333 * System V doesn't have a non-blocking wait system call. It does
7334 * have a SIGCLD signal that is sent to a process when one of it's
7335 * children dies. The obvious way to use SIGCLD would be to install
7336 * a handler for SIGCLD which simply bumped a counter when a SIGCLD
7337 * was received, and have waitproc bump another counter when it got
7338 * the status of a process. Waitproc would then know that a wait
7339 * system call would not block if the two counters were different.
7340 * This approach doesn't work because if a process has children that
7341 * have not been waited for, System V will send it a SIGCLD when it
7342 * installs a signal handler for SIGCLD. What this means is that when
7343 * a child exits, the shell will be sent SIGCLD signals continuously
7344 * until is runs out of stack space, unless it does a wait call before
7345 * restoring the signal handler. The code below takes advantage of
7346 * this (mis)feature by installing a signal handler for SIGCLD and
7347 * then checking to see whether it was called. If there are any
7348 * children to be waited for, it will be.
7350 * If neither SYSV nor BSD is defined, we don't implement nonblocking
7351 * waits at all. In this case, the user will not be informed when
7352 * a background process until the next time she runs a real program
7353 * (as opposed to running a builtin command or just typing return),
7354 * and the jobs command may give out of date information.
7357 static int waitproc(int block, int *status)
7367 return wait3(status, flags, (struct rusage *)NULL);
7371 * Wait for a process to terminate.
7375 dowait(int block, struct job *job)
7380 struct job *thisjob;
7383 TRACE(("dowait(%d) called\n", block));
7384 pid = waitproc(block, &status);
7385 TRACE(("wait returns pid %d, status=%d\n", pid, status));
7390 for (jp = curjob; jp; jp = jp->prev_job) {
7391 struct procstat *sp;
7392 struct procstat *spend;
7393 if (jp->state == JOBDONE)
7396 spend = jp->ps + jp->nprocs;
7399 if (sp->pid == pid) {
7400 TRACE(("Job %d: changing status of proc %d from 0x%x to 0x%x\n", jobno(jp), pid, sp->status, status));
7401 sp->status = status;
7404 if (sp->status == -1)
7407 if (state == JOBRUNNING)
7409 if (WIFSTOPPED(sp->status)) {
7410 jp->stopstatus = sp->status;
7414 } while (++sp < spend);
7419 if (!WIFSTOPPED(status))
7426 if (state != JOBRUNNING) {
7427 thisjob->changed = 1;
7429 if (thisjob->state != state) {
7430 TRACE(("Job %d: changing state from %d to %d\n", jobno(thisjob), thisjob->state, state));
7431 thisjob->state = state;
7433 if (state == JOBSTOPPED) {
7434 set_curjob(thisjob, CUR_STOPPED);
7443 if (thisjob && thisjob == job) {
7447 len = sprint_status(s, status, 1);
7459 * return 1 if there are stopped jobs, otherwise 0
7472 if (jp && jp->state == JOBSTOPPED) {
7473 out2str("You have stopped jobs.\n");
7483 * Return a string identifying a command (to be printed by the
7488 static char *cmdnextc;
7491 commandtext(union node *n)
7495 STARTSTACKSTR(cmdnextc);
7497 name = stackblock();
7498 TRACE(("commandtext: name %p, end %p\n\t\"%s\"\n",
7499 name, cmdnextc, cmdnextc));
7500 return savestr(name);
7504 cmdtxt(union node *n)
7507 struct nodelist *lp;
7519 lp = n->npipe.cmdlist;
7537 cmdtxt(n->nbinary.ch1);
7553 cmdtxt(n->nif.test);
7556 if (n->nif.elsepart) {
7559 n = n->nif.elsepart;
7575 cmdtxt(n->nbinary.ch1);
7585 cmdputs(n->nfor.var);
7587 cmdlist(n->nfor.args, 1);
7592 cmdputs(n->narg.text);
7596 cmdlist(n->ncmd.args, 1);
7597 cmdlist(n->ncmd.redirect, 0);
7610 cmdputs(n->ncase.expr->narg.text);
7612 for (np = n->ncase.cases; np; np = np->nclist.next) {
7613 cmdtxt(np->nclist.pattern);
7615 cmdtxt(np->nclist.body);
7641 s[0] = n->nfile.fd + '0';
7645 if (n->type == NTOFD || n->type == NFROMFD) {
7646 s[0] = n->ndup.dupfd + '0';
7657 cmdlist(union node *np, int sep)
7659 for (; np; np = np->narg.next) {
7663 if (sep && np->narg.next)
7669 cmdputs(const char *s)
7671 const char *p, *str;
7672 char c, cc[2] = " ";
7676 static const char vstype[VSTYPE + 1][4] = {
7677 "", "}", "-", "+", "?", "=",
7678 "%", "%%", "#", "##"
7680 nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc);
7682 while ((c = *p++) != 0) {
7690 if ((subtype & VSTYPE) == VSLENGTH)
7694 if (!(subtype & VSQUOTE) != !(quoted & 1)) {
7701 str = "\"}" + !(quoted & 1);
7708 case CTLBACKQ+CTLQUOTE:
7711 #ifdef CONFIG_ASH_MATH_SUPPORT
7726 if ((subtype & VSTYPE) != VSNORMAL)
7728 str = vstype[subtype & VSTYPE];
7729 if (subtype & VSNUL)
7738 /* These can only happen inside quotes */
7751 while ((c = *str++)) {
7756 USTPUTC('"', nextc);
7764 showpipe(struct job *jp, FILE *out)
7766 struct procstat *sp;
7767 struct procstat *spend;
7769 spend = jp->ps + jp->nprocs;
7770 for (sp = jp->ps + 1; sp < spend; sp++)
7771 fprintf(out, " | %s", sp->cmd);
7772 outcslow('\n', out);
7777 xtcsetpgrp(int fd, pid_t pgrp)
7779 if (tcsetpgrp(fd, pgrp))
7780 sh_error("Cannot set tty process group (%m)");
7785 getstatus(struct job *job) {
7789 status = job->ps[job->nprocs - 1].status;
7790 retval = WEXITSTATUS(status);
7791 if (!WIFEXITED(status)) {
7793 retval = WSTOPSIG(status);
7794 if (!WIFSTOPPED(status))
7797 /* XXX: limits number of signals */
7798 retval = WTERMSIG(status);
7800 if (retval == SIGINT)
7806 TRACE(("getstatus: job %d, nproc %d, status %x, retval %x\n",
7807 jobno(job), job->nprocs, status, retval));
7811 #ifdef CONFIG_ASH_MAIL
7815 * Routines to check for mail. (Perhaps make part of main.c?)
7818 #define MAXMBOXES 10
7820 /* times of mailboxes */
7821 static time_t mailtime[MAXMBOXES];
7822 /* Set if MAIL or MAILPATH is changed. */
7823 static int mail_var_path_changed;
7828 * Print appropriate message(s) if mail has arrived.
7829 * If mail_var_path_changed is set,
7830 * then the value of MAIL has mail_var_path_changed,
7831 * so we just update the values.
7841 struct stackmark smark;
7844 setstackmark(&smark);
7845 mpath = mpathset() ? mpathval() : mailval();
7846 for (mtp = mailtime; mtp < mailtime + MAXMBOXES; mtp++) {
7847 p = padvance(&mpath, nullstr);
7852 for (q = p ; *q ; q++);
7857 q[-1] = '\0'; /* delete trailing '/' */
7858 if (stat(p, &statb) < 0) {
7862 if (!mail_var_path_changed && statb.st_mtime != *mtp) {
7865 pathopt ? pathopt : "you have mail"
7868 *mtp = statb.st_mtime;
7870 mail_var_path_changed = 0;
7871 popstackmark(&smark);
7876 changemail(const char *val)
7878 mail_var_path_changed++;
7881 #endif /* CONFIG_ASH_MAIL */
7887 static short profile_buf[16384];
7891 static int isloginsh;
7893 static void read_profile(const char *);
7896 * Main routine. We initialize things, parse the arguments, execute
7897 * profiles if we're a login shell, and then call cmdloop to execute
7898 * commands. The setjmp call sets up the location to jump to when an
7899 * exception occurs. When an exception occurs the variable "state"
7900 * is used to figure out how far we had gotten.
7904 ash_main(int argc, char **argv)
7908 struct jmploc jmploc;
7909 struct stackmark smark;
7912 dash_errno = __errno_location();
7916 monitor(4, etext, profile_buf, sizeof profile_buf, 50);
7919 #if ENABLE_FEATURE_COMMAND_EDITING
7920 line_input_state = new_line_input_t(FOR_SHELL | WITH_PATH_LOOKUP);
7923 if (setjmp(jmploc.loc)) {
7933 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl)
7937 outcslow('\n', stderr);
7939 popstackmark(&smark);
7940 FORCEINTON; /* enable interrupts */
7953 trputs("Shell args: "); trargs(argv);
7957 #ifdef CONFIG_ASH_RANDOM_SUPPORT
7958 rseed = rootpid + ((time_t)time((time_t *)0));
7961 setstackmark(&smark);
7962 procargs(argc, argv);
7963 #if ENABLE_FEATURE_COMMAND_SAVEHISTORY
7965 const char *hp = lookupvar("HISTFILE");
7968 hp = lookupvar("HOME");
7970 char *defhp = concat_path_file(hp, ".ash_history");
7971 setvar("HISTFILE", defhp, 0);
7977 if (argv[0] && argv[0][0] == '-')
7981 read_profile("/etc/profile");
7984 read_profile(".profile");
7990 getuid() == geteuid() && getgid() == getegid() &&
7994 if ((shinit = lookupvar("ENV")) != NULL && *shinit != '\0') {
7995 read_profile(shinit);
8001 evalstring(minusc, 0);
8003 if (sflag || minusc == NULL) {
8004 #if ENABLE_FEATURE_COMMAND_SAVEHISTORY
8006 const char *hp = lookupvar("HISTFILE");
8009 line_input_state->hist_file = hp;
8012 state4: /* XXX ??? - why isn't this before the "if" statement */
8020 extern void _mcleanup(void);
8030 * Read and execute commands. "Top" is nonzero for the top level command
8031 * loop; it turns on prompting if the shell is interactive.
8038 struct stackmark smark;
8042 TRACE(("cmdloop(%d) called\n", top));
8046 setstackmark(&smark);
8049 showjobs(stderr, SHOW_CHANGED);
8054 #ifdef CONFIG_ASH_MAIL
8058 n = parsecmd(inter);
8059 /* showtree(n); DEBUG */
8061 if (!top || numeof >= 50)
8063 if (!stoppedjobs()) {
8066 out2str("\nUse \"exit\" to leave shell.\n");
8069 } else if (nflag == 0) {
8070 job_warning = (job_warning == 2) ? 1 : 0;
8074 popstackmark(&smark);
8079 return skip & SKIPEVAL;
8088 * Read /etc/profile or .profile. Return on error.
8092 read_profile(const char *name)
8096 if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
8108 * Read a file containing shell functions.
8112 readcmdfile(char *name)
8114 setinputfile(name, INPUT_PUSH_FILE);
8121 * Take commands from a file. To be compatible we should do a path
8122 * search for the file, which is necessary to find sub-commands.
8125 static char * find_dot_file(char *name)
8128 const char *path = pathval();
8131 /* don't try this for absolute or relative paths */
8132 if (strchr(name, '/'))
8135 while ((fullname = padvance(&path, name)) != NULL) {
8136 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
8138 * Don't bother freeing here, since it will
8139 * be freed by the caller.
8143 stunalloc(fullname);
8146 /* not found in the PATH */
8147 sh_error(not_found_msg, name);
8151 static int dotcmd(int argc, char **argv)
8154 volatile struct shparam saveparam;
8157 for (sp = cmdenviron; sp; sp = sp->next)
8158 setvareq(xstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
8160 if (argc >= 2) { /* That's what SVR2 does */
8163 fullname = find_dot_file(argv[1]);
8166 saveparam = shellparam;
8167 shellparam.malloc = 0;
8168 shellparam.nparam = argc - 2;
8169 shellparam.p = argv + 2;
8172 setinputfile(fullname, INPUT_PUSH_FILE);
8173 commandname = fullname;
8178 freeparam(&shellparam);
8179 shellparam = saveparam;
8181 status = exitstatus;
8188 exitcmd(int argc, char **argv)
8193 exitstatus = number(argv[1]);
8198 #ifdef CONFIG_ASH_BUILTIN_ECHO
8200 echocmd(int argc, char **argv)
8202 return bb_echo(argv);
8206 #ifdef CONFIG_ASH_BUILTIN_TEST
8208 testcmd(int argc, char **argv)
8210 return bb_test(argc, argv);
8217 * Same for malloc, realloc, but returns an error when out of space.
8221 ckrealloc(pointer p, size_t nbytes)
8223 p = realloc(p, nbytes);
8225 sh_error(bb_msg_memory_exhausted);
8230 ckmalloc(size_t nbytes)
8232 return ckrealloc(NULL, nbytes);
8236 * Make a copy of a string in safe storage.
8240 savestr(const char *s)
8242 char *p = strdup(s);
8244 sh_error(bb_msg_memory_exhausted);
8250 * Parse trees for commands are allocated in lifo order, so we use a stack
8251 * to make this more efficient, and also to avoid all sorts of exception
8252 * handling code to handle interrupts in the middle of a parse.
8254 * The size 504 was chosen because the Ultrix malloc handles that size
8260 stalloc(size_t nbytes)
8265 aligned = SHELL_ALIGN(nbytes);
8266 if (aligned > stacknleft) {
8269 struct stack_block *sp;
8271 blocksize = aligned;
8272 if (blocksize < MINSIZE)
8273 blocksize = MINSIZE;
8274 len = sizeof(struct stack_block) - MINSIZE + blocksize;
8275 if (len < blocksize)
8276 sh_error(bb_msg_memory_exhausted);
8280 stacknxt = sp->space;
8281 stacknleft = blocksize;
8282 sstrend = stacknxt + blocksize;
8287 stacknxt += aligned;
8288 stacknleft -= aligned;
8294 stunalloc(pointer p)
8297 if (!p || (stacknxt < (char *)p) || ((char *)p < stackp->space)) {
8298 write(2, "stunalloc\n", 10);
8302 stacknleft += stacknxt - (char *)p;
8308 setstackmark(struct stackmark *mark)
8310 mark->stackp = stackp;
8311 mark->stacknxt = stacknxt;
8312 mark->stacknleft = stacknleft;
8313 mark->marknext = markp;
8319 popstackmark(struct stackmark *mark)
8321 struct stack_block *sp;
8324 markp = mark->marknext;
8325 while (stackp != mark->stackp) {
8330 stacknxt = mark->stacknxt;
8331 stacknleft = mark->stacknleft;
8332 sstrend = mark->stacknxt + mark->stacknleft;
8338 * When the parser reads in a string, it wants to stick the string on the
8339 * stack and only adjust the stack pointer when it knows how big the
8340 * string is. Stackblock (defined in stack.h) returns a pointer to a block
8341 * of space on top of the stack and stackblocklen returns the length of
8342 * this block. Growstackblock will grow this space by at least one byte,
8343 * possibly moving it (like realloc). Grabstackblock actually allocates the
8344 * part of the block that has been used.
8348 growstackblock(void)
8352 newlen = stacknleft * 2;
8353 if (newlen < stacknleft)
8354 sh_error(bb_msg_memory_exhausted);
8358 if (stacknxt == stackp->space && stackp != &stackbase) {
8359 struct stack_block *oldstackp;
8360 struct stackmark *xmark;
8361 struct stack_block *sp;
8362 struct stack_block *prevstackp;
8368 prevstackp = sp->prev;
8369 grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
8370 sp = ckrealloc((pointer)sp, grosslen);
8371 sp->prev = prevstackp;
8373 stacknxt = sp->space;
8374 stacknleft = newlen;
8375 sstrend = sp->space + newlen;
8378 * Stack marks pointing to the start of the old block
8379 * must be relocated to point to the new block
8382 while (xmark != NULL && xmark->stackp == oldstackp) {
8383 xmark->stackp = stackp;
8384 xmark->stacknxt = stacknxt;
8385 xmark->stacknleft = stacknleft;
8386 xmark = xmark->marknext;
8390 char *oldspace = stacknxt;
8391 int oldlen = stacknleft;
8392 char *p = stalloc(newlen);
8394 /* free the space we just allocated */
8395 stacknxt = memcpy(p, oldspace, oldlen);
8396 stacknleft += newlen;
8400 static void grabstackblock(size_t len)
8402 len = SHELL_ALIGN(len);
8408 * The following routines are somewhat easier to use than the above.
8409 * The user declares a variable of type STACKSTR, which may be declared
8410 * to be a register. The macro STARTSTACKSTR initializes things. Then
8411 * the user uses the macro STPUTC to add characters to the string. In
8412 * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
8413 * grown as necessary. When the user is done, she can just leave the
8414 * string there and refer to it using stackblock(). Or she can allocate
8415 * the space for it using grabstackstr(). If it is necessary to allow
8416 * someone else to use the stack temporarily and then continue to grow
8417 * the string, the user should use grabstack to allocate the space, and
8418 * then call ungrabstr(p) to return to the previous mode of operation.
8420 * USTPUTC is like STPUTC except that it doesn't check for overflow.
8421 * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
8422 * is space for at least one character.
8428 size_t len = stackblocksize();
8429 if (herefd >= 0 && len >= 1024) {
8430 full_write(herefd, stackblock(), len);
8431 return stackblock();
8434 return stackblock() + len;
8438 * Called from CHECKSTRSPACE.
8442 makestrspace(size_t newlen, char *p)
8444 size_t len = p - stacknxt;
8445 size_t size = stackblocksize();
8450 size = stackblocksize();
8452 if (nleft >= newlen)
8456 return stackblock() + len;
8460 stnputs(const char *s, size_t n, char *p)
8462 p = makestrspace(n, p);
8463 p = memcpy(p, s, n) + n;
8468 stputs(const char *s, char *p)
8470 return stnputs(s, strlen(s), p);
8478 * number(s) Convert a string of digits to an integer.
8479 * is_number(s) Return true if s is a string of digits.
8483 * prefix -- see if pfx is a prefix of string.
8487 prefix(const char *string, const char *pfx)
8490 if (*pfx++ != *string++)
8493 return (char *) string;
8498 * Convert a string of digits to an integer, printing an error message on
8503 number(const char *s)
8507 sh_error(illnum, s);
8513 * Check for a valid number. This should be elsewhere.
8517 is_number(const char *p)
8522 } while (*++p != '\0');
8528 * Produce a possibly single quoted string suitable as input to the shell.
8529 * The return string is allocated on the stack.
8533 single_quote(const char *s) {
8542 len = strchrnul(s, '\'') - s;
8544 q = p = makestrspace(len + 3, p);
8547 q = memcpy(q, s, len) + len;
8553 len = strspn(s, "'");
8557 q = p = makestrspace(len + 3, p);
8560 q = memcpy(q, s, len) + len;
8569 return stackblock();
8573 * Like strdup but works with the ash stack.
8577 sstrdup(const char *p)
8579 size_t len = strlen(p) + 1;
8580 return memcpy(stalloc(len), p, len);
8585 calcsize(union node *n)
8589 funcblocksize += nodesize[n->type];
8592 calcsize(n->ncmd.redirect);
8593 calcsize(n->ncmd.args);
8594 calcsize(n->ncmd.assign);
8597 sizenodelist(n->npipe.cmdlist);
8602 calcsize(n->nredir.redirect);
8603 calcsize(n->nredir.n);
8610 calcsize(n->nbinary.ch2);
8611 calcsize(n->nbinary.ch1);
8614 calcsize(n->nif.elsepart);
8615 calcsize(n->nif.ifpart);
8616 calcsize(n->nif.test);
8619 funcstringsize += strlen(n->nfor.var) + 1;
8620 calcsize(n->nfor.body);
8621 calcsize(n->nfor.args);
8624 calcsize(n->ncase.cases);
8625 calcsize(n->ncase.expr);
8628 calcsize(n->nclist.body);
8629 calcsize(n->nclist.pattern);
8630 calcsize(n->nclist.next);
8634 sizenodelist(n->narg.backquote);
8635 funcstringsize += strlen(n->narg.text) + 1;
8636 calcsize(n->narg.next);
8643 calcsize(n->nfile.fname);
8644 calcsize(n->nfile.next);
8648 calcsize(n->ndup.vname);
8649 calcsize(n->ndup.next);
8653 calcsize(n->nhere.doc);
8654 calcsize(n->nhere.next);
8657 calcsize(n->nnot.com);
8664 sizenodelist(struct nodelist *lp)
8667 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
8675 copynode(union node *n)
8682 funcblock = (char *) funcblock + nodesize[n->type];
8685 new->ncmd.redirect = copynode(n->ncmd.redirect);
8686 new->ncmd.args = copynode(n->ncmd.args);
8687 new->ncmd.assign = copynode(n->ncmd.assign);
8690 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
8691 new->npipe.backgnd = n->npipe.backgnd;
8696 new->nredir.redirect = copynode(n->nredir.redirect);
8697 new->nredir.n = copynode(n->nredir.n);
8704 new->nbinary.ch2 = copynode(n->nbinary.ch2);
8705 new->nbinary.ch1 = copynode(n->nbinary.ch1);
8708 new->nif.elsepart = copynode(n->nif.elsepart);
8709 new->nif.ifpart = copynode(n->nif.ifpart);
8710 new->nif.test = copynode(n->nif.test);
8713 new->nfor.var = nodesavestr(n->nfor.var);
8714 new->nfor.body = copynode(n->nfor.body);
8715 new->nfor.args = copynode(n->nfor.args);
8718 new->ncase.cases = copynode(n->ncase.cases);
8719 new->ncase.expr = copynode(n->ncase.expr);
8722 new->nclist.body = copynode(n->nclist.body);
8723 new->nclist.pattern = copynode(n->nclist.pattern);
8724 new->nclist.next = copynode(n->nclist.next);
8728 new->narg.backquote = copynodelist(n->narg.backquote);
8729 new->narg.text = nodesavestr(n->narg.text);
8730 new->narg.next = copynode(n->narg.next);
8737 new->nfile.fname = copynode(n->nfile.fname);
8738 new->nfile.fd = n->nfile.fd;
8739 new->nfile.next = copynode(n->nfile.next);
8743 new->ndup.vname = copynode(n->ndup.vname);
8744 new->ndup.dupfd = n->ndup.dupfd;
8745 new->ndup.fd = n->ndup.fd;
8746 new->ndup.next = copynode(n->ndup.next);
8750 new->nhere.doc = copynode(n->nhere.doc);
8751 new->nhere.fd = n->nhere.fd;
8752 new->nhere.next = copynode(n->nhere.next);
8755 new->nnot.com = copynode(n->nnot.com);
8758 new->type = n->type;
8763 static struct nodelist *
8764 copynodelist(struct nodelist *lp)
8766 struct nodelist *start;
8767 struct nodelist **lpp;
8772 funcblock = (char *) funcblock +
8773 SHELL_ALIGN(sizeof(struct nodelist));
8774 (*lpp)->n = copynode(lp->n);
8776 lpp = &(*lpp)->next;
8784 nodesavestr(char *s)
8786 char *rtn = funcstring;
8788 strcpy(funcstring, s);
8789 funcstring += strlen(s) + 1;
8795 * Free a parse tree.
8799 freefunc(struct funcnode *f)
8801 if (f && --f->count < 0)
8806 static void options(int);
8807 static void setoption(int, int);
8811 * Process the shell command line arguments.
8815 procargs(int argc, char **argv)
8818 const char *xminusc;
8825 for (i = 0; i < NOPTS; i++)
8831 if (*xargv == NULL) {
8833 sh_error(bb_msg_requires_arg, "-c");
8836 if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
8840 for (i = 0; i < NOPTS; i++)
8841 if (optlist[i] == 2)
8846 /* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
8851 } else if (!sflag) {
8852 setinputfile(*xargv, 0);
8858 shellparam.p = xargv;
8859 #ifdef CONFIG_ASH_GETOPTS
8860 shellparam.optind = 1;
8861 shellparam.optoff = -1;
8863 /* assert(shellparam.malloc == 0 && shellparam.nparam == 0); */
8865 shellparam.nparam++;
8878 setinteractive(iflag);
8883 static void minus_o(char *name, int val)
8888 out1str("Current option settings\n");
8889 for (i = 0; i < NOPTS; i++)
8890 out1fmt("%-16s%s\n", optnames(i),
8891 optlist[i] ? "on" : "off");
8893 for (i = 0; i < NOPTS; i++)
8894 if (equal(name, optnames(i))) {
8898 sh_error("Illegal option -o %s", name);
8903 * Process shell options. The global variable argptr contains a pointer
8904 * to the argument list; we advance it past the options.
8908 options(int cmdline)
8916 while ((p = *argptr) != NULL) {
8918 if ((c = *p++) == '-') {
8920 if (p[0] == '\0' || LONE_DASH(p)) {
8922 /* "-" means turn off -x and -v */
8925 /* "--" means reset params */
8926 else if (*argptr == NULL)
8929 break; /* "-" or "--" terminates options */
8931 } else if (c == '+') {
8937 while ((c = *p++) != '\0') {
8938 if (c == 'c' && cmdline) {
8939 minusc = p; /* command is after shell args*/
8940 } else if (c == 'o') {
8941 minus_o(*argptr, val);
8944 } else if (cmdline && (c == '-')) { // long options
8945 if (strcmp(p, "login") == 0)
8957 setoption(int flag, int val)
8961 for (i = 0; i < NOPTS; i++)
8962 if (optletters(i) == flag) {
8966 sh_error("Illegal option -%c", flag);
8973 * Set the shell parameters.
8977 setparam(char **argv)
8983 for (nparam = 0 ; argv[nparam] ; nparam++);
8984 ap = newparam = ckmalloc((nparam + 1) * sizeof *ap);
8986 *ap++ = savestr(*argv++);
8989 freeparam(&shellparam);
8990 shellparam.malloc = 1;
8991 shellparam.nparam = nparam;
8992 shellparam.p = newparam;
8993 #ifdef CONFIG_ASH_GETOPTS
8994 shellparam.optind = 1;
8995 shellparam.optoff = -1;
9001 * Free the list of positional parameters.
9005 freeparam(volatile struct shparam *param)
9009 if (param->malloc) {
9010 for (ap = param->p ; *ap ; ap++)
9019 * The shift builtin command.
9023 shiftcmd(int argc, char **argv)
9030 n = number(argv[1]);
9031 if (n > shellparam.nparam)
9032 sh_error("can't shift that many");
9034 shellparam.nparam -= n;
9035 for (ap1 = shellparam.p ; --n >= 0 ; ap1++) {
9036 if (shellparam.malloc)
9040 while ((*ap2++ = *ap1++) != NULL);
9041 #ifdef CONFIG_ASH_GETOPTS
9042 shellparam.optind = 1;
9043 shellparam.optoff = -1;
9052 * The set command builtin.
9056 setcmd(int argc, char **argv)
9059 return showvars(nullstr, 0, VUNSET);
9063 if (*argptr != NULL) {
9071 #ifdef CONFIG_ASH_GETOPTS
9073 getoptsreset(const char *value)
9075 shellparam.optind = number(value);
9076 shellparam.optoff = -1;
9080 #ifdef CONFIG_LOCALE_SUPPORT
9081 static void change_lc_all(const char *value)
9083 if (value != 0 && *value != 0)
9084 setlocale(LC_ALL, value);
9087 static void change_lc_ctype(const char *value)
9089 if (value != 0 && *value != 0)
9090 setlocale(LC_CTYPE, value);
9095 #ifdef CONFIG_ASH_RANDOM_SUPPORT
9096 /* Roughly copied from bash.. */
9097 static void change_random(const char *value)
9100 /* "get", generate */
9103 rseed = rseed * 1103515245 + 12345;
9104 sprintf(buf, "%d", (unsigned int)((rseed & 32767)));
9105 /* set without recursion */
9106 setvar(vrandom.text, buf, VNOFUNC);
9107 vrandom.flags &= ~VNOFUNC;
9110 rseed = strtoul(value, (char **)NULL, 10);
9116 #ifdef CONFIG_ASH_GETOPTS
9118 getopts(char *optstr, char *optvar, char **optfirst, int *param_optind, int *optoff)
9127 if(*param_optind < 1)
9129 optnext = optfirst + *param_optind - 1;
9131 if (*param_optind <= 1 || *optoff < 0 || strlen(optnext[-1]) < *optoff)
9134 p = optnext[-1] + *optoff;
9135 if (p == NULL || *p == '\0') {
9136 /* Current word is done, advance */
9138 if (p == NULL || *p != '-' || *++p == '\0') {
9145 if (LONE_DASH(p)) /* check for "--" */
9150 for (q = optstr; *q != c; ) {
9152 if (optstr[0] == ':') {
9155 err |= setvarsafe("OPTARG", s, 0);
9157 fprintf(stderr, "Illegal option -%c\n", c);
9158 (void) unsetvar("OPTARG");
9168 if (*p == '\0' && (p = *optnext) == NULL) {
9169 if (optstr[0] == ':') {
9172 err |= setvarsafe("OPTARG", s, 0);
9175 fprintf(stderr, "No arg for -%c option\n", c);
9176 (void) unsetvar("OPTARG");
9184 err |= setvarsafe("OPTARG", p, 0);
9187 err |= setvarsafe("OPTARG", nullstr, 0);
9190 *optoff = p ? p - *(optnext - 1) : -1;
9191 *param_optind = optnext - optfirst + 1;
9192 fmtstr(s, sizeof(s), "%d", *param_optind);
9193 err |= setvarsafe("OPTIND", s, VNOFUNC);
9196 err |= setvarsafe(optvar, s, 0);
9207 * The getopts builtin. Shellparam.optnext points to the next argument
9208 * to be processed. Shellparam.optptr points to the next character to
9209 * be processed in the current argument. If shellparam.optnext is NULL,
9210 * then it's the first time getopts has been called.
9214 getoptscmd(int argc, char **argv)
9219 sh_error("Usage: getopts optstring var [arg]");
9220 else if (argc == 3) {
9221 optbase = shellparam.p;
9222 if (shellparam.optind > shellparam.nparam + 1) {
9223 shellparam.optind = 1;
9224 shellparam.optoff = -1;
9229 if (shellparam.optind > argc - 2) {
9230 shellparam.optind = 1;
9231 shellparam.optoff = -1;
9235 return getopts(argv[1], argv[2], optbase, &shellparam.optind,
9236 &shellparam.optoff);
9238 #endif /* CONFIG_ASH_GETOPTS */
9241 * XXX - should get rid of. have all builtins use getopt(3). the
9242 * library getopt must have the BSD extension static variable "optreset"
9243 * otherwise it can't be used within the shell safely.
9245 * Standard option processing (a la getopt) for builtin routines. The
9246 * only argument that is passed to nextopt is the option string; the
9247 * other arguments are unnecessary. It return the character, or '\0' on
9252 nextopt(const char *optstring)
9258 if ((p = optptr) == NULL || *p == '\0') {
9260 if (p == NULL || *p != '-' || *++p == '\0')
9263 if (LONE_DASH(p)) /* check for "--" */
9267 for (q = optstring ; *q != c ; ) {
9269 sh_error("Illegal option -%c", c);
9274 if (*p == '\0' && (p = *argptr++) == NULL)
9275 sh_error("No arg for -%c option", c);
9287 outstr(const char *p, FILE *file)
9312 outcslow(int c, FILE *dest)
9322 out1fmt(const char *fmt, ...)
9329 r = vprintf(fmt, ap);
9337 fmtstr(char *outbuf, size_t length, const char *fmt, ...)
9344 ret = vsnprintf(outbuf, length, fmt, ap);
9356 * Shell command parser.
9359 #define EOFMARKLEN 79
9363 struct heredoc *next; /* next here document in list */
9364 union node *here; /* redirection node */
9365 char *eofmark; /* string indicating end of input */
9366 int striptabs; /* if set, strip leading tabs */
9371 static struct heredoc *heredoclist; /* list of here documents to read */
9374 static union node *list(int);
9375 static union node *andor(void);
9376 static union node *pipeline(void);
9377 static union node *command(void);
9378 static union node *simplecmd(void);
9379 static union node *makename(void);
9380 static void parsefname(void);
9381 static void parseheredoc(void);
9382 static char peektoken(void);
9383 static int readtoken(void);
9384 static int xxreadtoken(void);
9385 static int readtoken1(int firstc, int syntax, char *eofmark, int striptabs);
9386 static int noexpand(char *);
9387 static void synexpect(int) ATTRIBUTE_NORETURN;
9388 static void synerror(const char *) ATTRIBUTE_NORETURN;
9389 static void setprompt(int);
9395 * Read and parse a command. Returns NEOF on end of file. (NULL is a
9396 * valid parse tree indicating a blank line.)
9400 parsecmd(int interact)
9405 doprompt = interact;
9407 setprompt(doprompt);
9422 union node *n1, *n2, *n3;
9425 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9426 if (nlflag == 2 && peektoken())
9432 if (tok == TBACKGND) {
9433 if (n2->type == NPIPE) {
9434 n2->npipe.backgnd = 1;
9436 if (n2->type != NREDIR) {
9437 n3 = stalloc(sizeof(struct nredir));
9439 n3->nredir.redirect = NULL;
9442 n2->type = NBACKGND;
9449 n3 = (union node *)stalloc(sizeof (struct nbinary));
9451 n3->nbinary.ch1 = n1;
9452 n3->nbinary.ch2 = n2;
9468 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9476 pungetc(); /* push back EOF on input */
9492 union node *n1, *n2, *n3;
9497 if ((t = readtoken()) == TAND) {
9499 } else if (t == TOR) {
9505 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9507 n3 = (union node *)stalloc(sizeof (struct nbinary));
9509 n3->nbinary.ch1 = n1;
9510 n3->nbinary.ch2 = n2;
9520 union node *n1, *n2, *pipenode;
9521 struct nodelist *lp, *prev;
9525 TRACE(("pipeline: entered\n"));
9526 if (readtoken() == TNOT) {
9528 checkkwd = CHKKWD | CHKALIAS;
9532 if (readtoken() == TPIPE) {
9533 pipenode = (union node *)stalloc(sizeof (struct npipe));
9534 pipenode->type = NPIPE;
9535 pipenode->npipe.backgnd = 0;
9536 lp = (struct nodelist *)stalloc(sizeof (struct nodelist));
9537 pipenode->npipe.cmdlist = lp;
9541 lp = (struct nodelist *)stalloc(sizeof (struct nodelist));
9542 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9545 } while (readtoken() == TPIPE);
9551 n2 = (union node *)stalloc(sizeof (struct nnot));
9564 union node *n1, *n2;
9565 union node *ap, **app;
9566 union node *cp, **cpp;
9567 union node *redir, **rpp;
9574 switch (readtoken()) {
9579 n1 = (union node *)stalloc(sizeof (struct nif));
9581 n1->nif.test = list(0);
9582 if (readtoken() != TTHEN)
9584 n1->nif.ifpart = list(0);
9586 while (readtoken() == TELIF) {
9587 n2->nif.elsepart = (union node *)stalloc(sizeof (struct nif));
9588 n2 = n2->nif.elsepart;
9590 n2->nif.test = list(0);
9591 if (readtoken() != TTHEN)
9593 n2->nif.ifpart = list(0);
9595 if (lasttoken == TELSE)
9596 n2->nif.elsepart = list(0);
9598 n2->nif.elsepart = NULL;
9606 n1 = (union node *)stalloc(sizeof (struct nbinary));
9607 n1->type = (lasttoken == TWHILE)? NWHILE : NUNTIL;
9608 n1->nbinary.ch1 = list(0);
9609 if ((got=readtoken()) != TDO) {
9610 TRACE(("expecting DO got %s %s\n", tokname(got), got == TWORD ? wordtext : ""));
9613 n1->nbinary.ch2 = list(0);
9618 if (readtoken() != TWORD || quoteflag || ! goodname(wordtext))
9619 synerror("Bad for loop variable");
9620 n1 = (union node *)stalloc(sizeof (struct nfor));
9622 n1->nfor.var = wordtext;
9623 checkkwd = CHKKWD | CHKALIAS;
9624 if (readtoken() == TIN) {
9626 while (readtoken() == TWORD) {
9627 n2 = (union node *)stalloc(sizeof (struct narg));
9629 n2->narg.text = wordtext;
9630 n2->narg.backquote = backquotelist;
9632 app = &n2->narg.next;
9636 if (lasttoken != TNL && lasttoken != TSEMI)
9639 n2 = (union node *)stalloc(sizeof (struct narg));
9641 n2->narg.text = (char *)dolatstr;
9642 n2->narg.backquote = NULL;
9643 n2->narg.next = NULL;
9646 * Newline or semicolon here is optional (but note
9647 * that the original Bourne shell only allowed NL).
9649 if (lasttoken != TNL && lasttoken != TSEMI)
9652 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9653 if (readtoken() != TDO)
9655 n1->nfor.body = list(0);
9659 n1 = (union node *)stalloc(sizeof (struct ncase));
9661 if (readtoken() != TWORD)
9663 n1->ncase.expr = n2 = (union node *)stalloc(sizeof (struct narg));
9665 n2->narg.text = wordtext;
9666 n2->narg.backquote = backquotelist;
9667 n2->narg.next = NULL;
9669 checkkwd = CHKKWD | CHKALIAS;
9670 } while (readtoken() == TNL);
9671 if (lasttoken != TIN)
9673 cpp = &n1->ncase.cases;
9675 checkkwd = CHKNL | CHKKWD;
9678 if (lasttoken == TLP)
9680 *cpp = cp = (union node *)stalloc(sizeof (struct nclist));
9682 app = &cp->nclist.pattern;
9684 *app = ap = (union node *)stalloc(sizeof (struct narg));
9686 ap->narg.text = wordtext;
9687 ap->narg.backquote = backquotelist;
9688 if (readtoken() != TPIPE)
9690 app = &ap->narg.next;
9693 ap->narg.next = NULL;
9694 if (lasttoken != TRP)
9696 cp->nclist.body = list(2);
9698 cpp = &cp->nclist.next;
9700 checkkwd = CHKNL | CHKKWD;
9701 if ((t = readtoken()) != TESAC) {
9703 synexpect(TENDCASE);
9711 n1 = (union node *)stalloc(sizeof (struct nredir));
9712 n1->type = NSUBSHELL;
9713 n1->nredir.n = list(0);
9714 n1->nredir.redirect = NULL;
9727 if (readtoken() != t)
9731 /* Now check for redirection which may follow command */
9732 checkkwd = CHKKWD | CHKALIAS;
9734 while (readtoken() == TREDIR) {
9735 *rpp = n2 = redirnode;
9736 rpp = &n2->nfile.next;
9742 if (n1->type != NSUBSHELL) {
9743 n2 = (union node *)stalloc(sizeof (struct nredir));
9748 n1->nredir.redirect = redir;
9757 union node *args, **app;
9758 union node *n = NULL;
9759 union node *vars, **vpp;
9760 union node **rpp, *redir;
9770 savecheckkwd = CHKALIAS;
9772 checkkwd = savecheckkwd;
9773 switch (readtoken()) {
9775 n = (union node *)stalloc(sizeof (struct narg));
9777 n->narg.text = wordtext;
9778 n->narg.backquote = backquotelist;
9779 if (savecheckkwd && isassignment(wordtext)) {
9781 vpp = &n->narg.next;
9784 app = &n->narg.next;
9789 *rpp = n = redirnode;
9790 rpp = &n->nfile.next;
9791 parsefname(); /* read name of redirection file */
9795 args && app == &args->narg.next &&
9798 struct builtincmd *bcmd;
9801 /* We have a function */
9802 if (readtoken() != TRP)
9804 name = n->narg.text;
9806 !goodname(name) || (
9807 (bcmd = find_builtin(name)) &&
9808 IS_BUILTIN_SPECIAL(bcmd)
9811 synerror("Bad function name");
9813 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9814 n->narg.next = command();
9827 n = (union node *)stalloc(sizeof (struct ncmd));
9829 n->ncmd.args = args;
9830 n->ncmd.assign = vars;
9831 n->ncmd.redirect = redir;
9840 n = (union node *)stalloc(sizeof (struct narg));
9842 n->narg.next = NULL;
9843 n->narg.text = wordtext;
9844 n->narg.backquote = backquotelist;
9848 void fixredir(union node *n, const char *text, int err)
9850 TRACE(("Fix redir %s %d\n", text, err));
9852 n->ndup.vname = NULL;
9854 if (is_digit(text[0]) && text[1] == '\0')
9855 n->ndup.dupfd = digit_val(text[0]);
9856 else if (LONE_DASH(text))
9861 synerror("Bad fd number");
9863 n->ndup.vname = makename();
9871 union node *n = redirnode;
9873 if (readtoken() != TWORD)
9875 if (n->type == NHERE) {
9876 struct heredoc *here = heredoc;
9882 TRACE(("Here document %d\n", n->type));
9883 if (! noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)
9884 synerror("Illegal eof marker for << redirection");
9885 rmescapes(wordtext);
9886 here->eofmark = wordtext;
9888 if (heredoclist == NULL)
9891 for (p = heredoclist ; p->next ; p = p->next);
9894 } else if (n->type == NTOFD || n->type == NFROMFD) {
9895 fixredir(n, wordtext, 0);
9897 n->nfile.fname = makename();
9903 * Input any here documents.
9909 struct heredoc *here;
9919 readtoken1(pgetc(), here->here->type == NHERE? SQSYNTAX : DQSYNTAX,
9920 here->eofmark, here->striptabs);
9921 n = (union node *)stalloc(sizeof (struct narg));
9922 n->narg.type = NARG;
9923 n->narg.next = NULL;
9924 n->narg.text = wordtext;
9925 n->narg.backquote = backquotelist;
9926 here->here->nhere.doc = n;
9931 static char peektoken(void)
9937 return tokname_array[t][0];
9945 int alreadyseen = tokpushback;
9948 #ifdef CONFIG_ASH_ALIAS
9957 if (checkkwd & CHKNL) {
9964 if (t != TWORD || quoteflag) {
9969 * check for keywords
9971 if (checkkwd & CHKKWD) {
9972 const char *const *pp;
9974 if ((pp = findkwd(wordtext))) {
9975 lasttoken = t = pp - tokname_array;
9976 TRACE(("keyword %s recognized\n", tokname(t)));
9981 if (checkkwd & CHKALIAS) {
9982 #ifdef CONFIG_ASH_ALIAS
9984 if ((ap = lookupalias(wordtext, 1)) != NULL) {
9986 pushstring(ap->val, ap);
9996 TRACE(("token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
9998 TRACE(("reread token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
10005 * Read the next input token.
10006 * If the token is a word, we set backquotelist to the list of cmds in
10007 * backquotes. We set quoteflag to true if any part of the word was
10009 * If the token is TREDIR, then we set redirnode to a structure containing
10011 * In all cases, the variable startlinno is set to the number of the line
10012 * on which the token starts.
10014 * [Change comment: here documents and internal procedures]
10015 * [Readtoken shouldn't have any arguments. Perhaps we should make the
10016 * word parsing code into a separate routine. In this case, readtoken
10017 * doesn't need to have any internal procedures, but parseword does.
10018 * We could also make parseoperator in essence the main routine, and
10019 * have parseword (readtoken1?) handle both words and redirection.]
10022 #define NEW_xxreadtoken
10023 #ifdef NEW_xxreadtoken
10025 /* singles must be first! */
10026 static const char xxreadtoken_chars[7] = { '\n', '(', ')', '&', '|', ';', 0 };
10028 static const char xxreadtoken_tokens[] = {
10029 TNL, TLP, TRP, /* only single occurrence allowed */
10030 TBACKGND, TPIPE, TSEMI, /* if single occurrence */
10031 TEOF, /* corresponds to trailing nul */
10032 TAND, TOR, TENDCASE, /* if double occurrence */
10035 #define xxreadtoken_doubles \
10036 (sizeof(xxreadtoken_tokens) - sizeof(xxreadtoken_chars))
10037 #define xxreadtoken_singles \
10038 (sizeof(xxreadtoken_chars) - xxreadtoken_doubles - 1)
10040 static int xxreadtoken(void)
10051 startlinno = plinno;
10052 for (;;) { /* until token or start of word found */
10055 if ((c != ' ') && (c != '\t')
10056 #ifdef CONFIG_ASH_ALIAS
10061 while ((c = pgetc()) != '\n' && c != PEOF);
10063 } else if (c == '\\') {
10064 if (pgetc() != '\n') {
10068 startlinno = ++plinno;
10073 = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
10078 needprompt = doprompt;
10081 p = strchr(xxreadtoken_chars, c);
10084 return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
10087 if (p - xxreadtoken_chars >= xxreadtoken_singles) {
10088 if (pgetc() == *p) { /* double occurrence? */
10089 p += xxreadtoken_doubles + 1;
10096 return lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
10104 #define RETURN(token) return lasttoken = token
10118 startlinno = plinno;
10119 for (;;) { /* until token or start of word found */
10122 case ' ': case '\t':
10123 #ifdef CONFIG_ASH_ALIAS
10128 while ((c = pgetc()) != '\n' && c != PEOF);
10132 if (pgetc() == '\n') {
10133 startlinno = ++plinno;
10142 needprompt = doprompt;
10147 if (pgetc() == '&')
10152 if (pgetc() == '|')
10157 if (pgetc() == ';')
10170 return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
10173 #endif /* NEW_xxreadtoken */
10177 * If eofmark is NULL, read a word or a redirection symbol. If eofmark
10178 * is not NULL, read a here document. In the latter case, eofmark is the
10179 * word which marks the end of the document and striptabs is true if
10180 * leading tabs should be stripped from the document. The argument firstc
10181 * is the first character of the input token or document.
10183 * Because C does not have internal subroutines, I have simulated them
10184 * using goto's to implement the subroutine linkage. The following macros
10185 * will run code that appears at the end of readtoken1.
10188 #define CHECKEND() {goto checkend; checkend_return:;}
10189 #define PARSEREDIR() {goto parseredir; parseredir_return:;}
10190 #define PARSESUB() {goto parsesub; parsesub_return:;}
10191 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
10192 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
10193 #define PARSEARITH() {goto parsearith; parsearith_return:;}
10196 readtoken1(int firstc, int syntax, char *eofmark, int striptabs)
10201 char line[EOFMARKLEN + 1];
10202 struct nodelist *bqlist = 0;
10205 int varnest = 0; /* levels of variables expansion */
10206 int arinest = 0; /* levels of arithmetic expansion */
10207 int parenlevel = 0; /* levels of parens in arithmetic */
10208 int dqvarnest = 0; /* levels of variables expansion within double quotes */
10210 int prevsyntax = 0; /* syntax before arithmetic */
10212 /* Avoid longjmp clobbering */
10218 (void) &parenlevel;
10221 (void) &prevsyntax;
10225 startlinno = plinno;
10227 if (syntax == DQSYNTAX)
10236 STARTSTACKSTR(out);
10237 loop: { /* for each line, until end of word */
10238 CHECKEND(); /* set c to PEOF if at end of here document */
10239 for (;;) { /* until end of line or end of word */
10240 CHECKSTRSPACE(4, out); /* permit 4 calls to USTPUTC */
10241 switch (SIT(c, syntax)) {
10242 case CNL: /* '\n' */
10243 if (syntax == BASESYNTAX)
10244 goto endword; /* exit outer loop */
10250 goto loop; /* continue outer loop */
10255 if (eofmark == NULL || dblquote)
10256 USTPUTC(CTLESC, out);
10259 case CBACK: /* backslash */
10262 USTPUTC(CTLESC, out);
10263 USTPUTC('\\', out);
10265 } else if (c == '\n') {
10270 c != '\\' && c != '`' &&
10275 USTPUTC(CTLESC, out);
10276 USTPUTC('\\', out);
10278 if (SIT(c, SQSYNTAX) == CCTL)
10279 USTPUTC(CTLESC, out);
10287 if (eofmark == NULL) {
10288 USTPUTC(CTLQUOTEMARK, out);
10296 if (eofmark != NULL && arinest == 0 &&
10300 if (dqvarnest == 0) {
10301 syntax = BASESYNTAX;
10308 case CVAR: /* '$' */
10309 PARSESUB(); /* parse substitution */
10311 case CENDVAR: /* '}' */
10314 if (dqvarnest > 0) {
10317 USTPUTC(CTLENDVAR, out);
10322 #ifdef CONFIG_ASH_MATH_SUPPORT
10323 case CLP: /* '(' in arithmetic */
10327 case CRP: /* ')' in arithmetic */
10328 if (parenlevel > 0) {
10332 if (pgetc() == ')') {
10333 if (--arinest == 0) {
10334 USTPUTC(CTLENDARI, out);
10335 syntax = prevsyntax;
10336 if (syntax == DQSYNTAX)
10344 * unbalanced parens
10345 * (don't 2nd guess - no error)
10353 case CBQUOTE: /* '`' */
10357 goto endword; /* exit outer loop */
10362 goto endword; /* exit outer loop */
10363 #ifdef CONFIG_ASH_ALIAS
10373 #ifdef CONFIG_ASH_MATH_SUPPORT
10374 if (syntax == ARISYNTAX)
10375 synerror("Missing '))'");
10377 if (syntax != BASESYNTAX && ! parsebackquote && eofmark == NULL)
10378 synerror("Unterminated quoted string");
10379 if (varnest != 0) {
10380 startlinno = plinno;
10382 synerror("Missing '}'");
10384 USTPUTC('\0', out);
10385 len = out - (char *)stackblock();
10386 out = stackblock();
10387 if (eofmark == NULL) {
10388 if ((c == '>' || c == '<')
10391 && (*out == '\0' || is_digit(*out))) {
10393 return lasttoken = TREDIR;
10398 quoteflag = quotef;
10399 backquotelist = bqlist;
10400 grabstackblock(len);
10402 return lasttoken = TWORD;
10403 /* end of readtoken routine */
10408 * Check to see whether we are at the end of the here document. When this
10409 * is called, c is set to the first character of the next input line. If
10410 * we are at the end of the here document, this routine sets the c to PEOF.
10415 #ifdef CONFIG_ASH_ALIAS
10421 while (c == '\t') {
10425 if (c == *eofmark) {
10426 if (pfgets(line, sizeof line) != NULL) {
10430 for (q = eofmark + 1 ; *q && *p == *q ; p++, q++);
10431 if (*p == '\n' && *q == '\0') {
10434 needprompt = doprompt;
10436 pushstring(line, NULL);
10441 goto checkend_return;
10446 * Parse a redirection operator. The variable "out" points to a string
10447 * specifying the fd to be redirected. The variable "c" contains the
10448 * first character of the redirection operator.
10455 np = (union node *)stalloc(sizeof (struct nfile));
10460 np->type = NAPPEND;
10462 np->type = NCLOBBER;
10469 } else { /* c == '<' */
10471 switch (c = pgetc()) {
10473 if (sizeof (struct nfile) != sizeof (struct nhere)) {
10474 np = (union node *)stalloc(sizeof (struct nhere));
10478 heredoc = (struct heredoc *)stalloc(sizeof (struct heredoc));
10479 heredoc->here = np;
10480 if ((c = pgetc()) == '-') {
10481 heredoc->striptabs = 1;
10483 heredoc->striptabs = 0;
10489 np->type = NFROMFD;
10493 np->type = NFROMTO;
10503 np->nfile.fd = digit_val(fd);
10505 goto parseredir_return;
10510 * Parse a substitution. At this point, we have read the dollar sign
10511 * and nothing else.
10519 static const char types[] = "}-+?=";
10523 c <= PEOA_OR_PEOF ||
10524 (c != '(' && c != '{' && !is_name(c) && !is_special(c))
10528 } else if (c == '(') { /* $(command) or $((arith)) */
10529 if (pgetc() == '(') {
10530 #ifdef CONFIG_ASH_MATH_SUPPORT
10533 synerror("We unsupport $((arith))");
10540 USTPUTC(CTLVAR, out);
10541 typeloc = out - (char *)stackblock();
10542 USTPUTC(VSNORMAL, out);
10543 subtype = VSNORMAL;
10547 if ((c = pgetc()) == '}')
10550 subtype = VSLENGTH;
10555 if (c > PEOA_OR_PEOF && is_name(c)) {
10559 } while (c > PEOA_OR_PEOF && is_in_name(c));
10560 } else if (is_digit(c)) {
10564 } while (is_digit(c));
10566 else if (is_special(c)) {
10571 badsub: synerror("Bad substitution");
10575 if (subtype == 0) {
10582 p = strchr(types, c);
10585 subtype = p - types + VSNORMAL;
10591 subtype = c == '#' ? VSTRIMLEFT :
10604 if (dblquote || arinest)
10606 *((char *)stackblock() + typeloc) = subtype | flags;
10607 if (subtype != VSNORMAL) {
10609 if (dblquote || arinest) {
10614 goto parsesub_return;
10619 * Called to parse command substitutions. Newstyle is set if the command
10620 * is enclosed inside $(...); nlpp is a pointer to the head of the linked
10621 * list of commands (passed by reference), and savelen is the number of
10622 * characters on the top of the stack which must be preserved.
10626 struct nodelist **nlpp;
10629 char *volatile str;
10630 struct jmploc jmploc;
10631 struct jmploc *volatile savehandler;
10633 int saveprompt = 0;
10635 (void) &saveprompt;
10638 savepbq = parsebackquote;
10639 if (setjmp(jmploc.loc)) {
10642 parsebackquote = 0;
10643 handler = savehandler;
10644 longjmp(handler->loc, 1);
10648 savelen = out - (char *)stackblock();
10650 str = ckmalloc(savelen);
10651 memcpy(str, stackblock(), savelen);
10653 savehandler = handler;
10657 /* We must read until the closing backquote, giving special
10658 treatment to some slashes, and then push the string and
10659 reread it as input, interpreting it normally. */
10666 STARTSTACKSTR(pout);
10671 switch (pc = pgetc()) {
10676 if ((pc = pgetc()) == '\n') {
10681 * If eating a newline, avoid putting
10682 * the newline into the new character
10683 * stream (via the STPUTC after the
10688 if (pc != '\\' && pc != '`' && pc != '$'
10689 && (!dblquote || pc != '"'))
10690 STPUTC('\\', pout);
10691 if (pc > PEOA_OR_PEOF) {
10697 #ifdef CONFIG_ASH_ALIAS
10700 startlinno = plinno;
10701 synerror("EOF in backquote substitution");
10705 needprompt = doprompt;
10714 STPUTC('\0', pout);
10715 psavelen = pout - (char *)stackblock();
10716 if (psavelen > 0) {
10717 pstr = grabstackstr(pout);
10718 setinputstring(pstr);
10723 nlpp = &(*nlpp)->next;
10724 *nlpp = (struct nodelist *)stalloc(sizeof (struct nodelist));
10725 (*nlpp)->next = NULL;
10726 parsebackquote = oldstyle;
10729 saveprompt = doprompt;
10736 doprompt = saveprompt;
10738 if (readtoken() != TRP)
10745 * Start reading from old file again, ignoring any pushed back
10746 * tokens left from the backquote parsing
10751 while (stackblocksize() <= savelen)
10753 STARTSTACKSTR(out);
10755 memcpy(out, str, savelen);
10756 STADJUST(savelen, out);
10762 parsebackquote = savepbq;
10763 handler = savehandler;
10764 if (arinest || dblquote)
10765 USTPUTC(CTLBACKQ | CTLQUOTE, out);
10767 USTPUTC(CTLBACKQ, out);
10769 goto parsebackq_oldreturn;
10771 goto parsebackq_newreturn;
10774 #ifdef CONFIG_ASH_MATH_SUPPORT
10776 * Parse an arithmetic expansion (indicate start of one and set state)
10780 if (++arinest == 1) {
10781 prevsyntax = syntax;
10782 syntax = ARISYNTAX;
10783 USTPUTC(CTLARI, out);
10790 * we collapse embedded arithmetic expansion to
10791 * parenthesis, which should be equivalent
10795 goto parsearith_return;
10799 } /* end of readtoken */
10804 * Returns true if the text contains nothing to expand (no dollar signs
10809 noexpand(char *text)
10815 while ((c = *p++) != '\0') {
10816 if (c == CTLQUOTEMARK)
10820 else if (SIT(c, BASESYNTAX) == CCTL)
10828 * Return of a legal variable name (a letter or underscore followed by zero or
10829 * more letters, underscores, and digits).
10833 endofname(const char *name)
10841 if (! is_in_name(*p))
10849 * Called when an unexpected token is read during the parse. The argument
10850 * is the token that is expected, or -1 if more than one type of token can
10851 * occur at this point.
10854 static void synexpect(int token)
10859 l = sprintf(msg, "%s unexpected", tokname(lasttoken));
10861 sprintf(msg + l, " (expecting %s)", tokname(token));
10867 synerror(const char *msg)
10869 sh_error("Syntax error: %s", msg);
10875 * called by editline -- any expansions to the prompt
10876 * should be added here.
10879 #ifdef CONFIG_ASH_EXPAND_PRMT
10880 static const char *
10881 expandstr(const char *ps)
10885 /* XXX Fix (char *) cast. */
10886 setinputstring((char *)ps);
10887 readtoken1(pgetc(), DQSYNTAX, nullstr, 0);
10890 n.narg.type = NARG;
10891 n.narg.next = NULL;
10892 n.narg.text = wordtext;
10893 n.narg.backquote = backquotelist;
10895 expandarg(&n, NULL, 0);
10896 return stackblock();
10900 static void setprompt(int whichprompt)
10902 const char *prompt;
10903 #ifdef CONFIG_ASH_EXPAND_PRMT
10904 struct stackmark smark;
10909 switch (whichprompt) {
10919 #ifdef CONFIG_ASH_EXPAND_PRMT
10920 setstackmark(&smark);
10921 stalloc(stackblocksize());
10923 putprompt(expandstr(prompt));
10924 #ifdef CONFIG_ASH_EXPAND_PRMT
10925 popstackmark(&smark);
10930 static const char *const *findkwd(const char *s)
10932 return bsearch(s, tokname_array + KWDOFFSET,
10933 (sizeof(tokname_array) / sizeof(const char *)) - KWDOFFSET,
10934 sizeof(const char *), pstrcmp);
10940 * Code for dealing with input/output redirection.
10943 #define EMPTY -2 /* marks an unused slot in redirtab */
10945 # define PIPESIZE 4096 /* amount of buffering in a pipe */
10947 # define PIPESIZE PIPE_BUF
10951 * Open a file in noclobber mode.
10952 * The code was copied from bash.
10954 static int noclobberopen(const char *fname)
10957 struct stat finfo, finfo2;
10960 * If the file exists and is a regular file, return an error
10963 r = stat(fname, &finfo);
10964 if (r == 0 && S_ISREG(finfo.st_mode)) {
10970 * If the file was not present (r != 0), make sure we open it
10971 * exclusively so that if it is created before we open it, our open
10972 * will fail. Make sure that we do not truncate an existing file.
10973 * Note that we don't turn on O_EXCL unless the stat failed -- if the
10974 * file was not a regular file, we leave O_EXCL off.
10977 return open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
10978 fd = open(fname, O_WRONLY|O_CREAT, 0666);
10980 /* If the open failed, return the file descriptor right away. */
10985 * OK, the open succeeded, but the file may have been changed from a
10986 * non-regular file to a regular file between the stat and the open.
10987 * We are assuming that the O_EXCL open handles the case where FILENAME
10988 * did not exist and is symlinked to an existing file between the stat
10993 * If we can open it and fstat the file descriptor, and neither check
10994 * revealed that it was a regular file, and the file has not been
10995 * replaced, return the file descriptor.
10997 if (fstat(fd, &finfo2) == 0 && !S_ISREG(finfo2.st_mode) &&
10998 finfo.st_dev == finfo2.st_dev && finfo.st_ino == finfo2.st_ino)
11001 /* The file has been replaced. badness. */
11008 * Handle here documents. Normally we fork off a process to write the
11009 * data to a pipe. If the document is short, we can stuff the data in
11010 * the pipe without forking.
11013 static int openhere(union node *redir)
11019 sh_error("Pipe call failed");
11020 if (redir->type == NHERE) {
11021 len = strlen(redir->nhere.doc->narg.text);
11022 if (len <= PIPESIZE) {
11023 full_write(pip[1], redir->nhere.doc->narg.text, len);
11027 if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
11029 signal(SIGINT, SIG_IGN);
11030 signal(SIGQUIT, SIG_IGN);
11031 signal(SIGHUP, SIG_IGN);
11033 signal(SIGTSTP, SIG_IGN);
11035 signal(SIGPIPE, SIG_DFL);
11036 if (redir->type == NHERE)
11037 full_write(pip[1], redir->nhere.doc->narg.text, len);
11039 expandhere(redir->nhere.doc, pip[1]);
11048 openredirect(union node *redir)
11053 switch (redir->nfile.type) {
11055 fname = redir->nfile.expfname;
11056 if ((f = open(fname, O_RDONLY)) < 0)
11060 fname = redir->nfile.expfname;
11061 if ((f = open(fname, O_RDWR|O_CREAT|O_TRUNC, 0666)) < 0)
11065 /* Take care of noclobber mode. */
11067 fname = redir->nfile.expfname;
11068 if ((f = noclobberopen(fname)) < 0)
11074 fname = redir->nfile.expfname;
11075 if ((f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0)
11079 fname = redir->nfile.expfname;
11080 if ((f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666)) < 0)
11087 /* Fall through to eliminate warning. */
11094 f = openhere(redir);
11100 sh_error("cannot create %s: %s", fname, errmsg(errno, E_CREAT));
11102 sh_error("cannot open %s: %s", fname, errmsg(errno, E_OPEN));
11105 static void dupredirect(union node *redir, int f)
11107 int fd = redir->nfile.fd;
11109 if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
11110 if (redir->ndup.dupfd >= 0) { /* if not ">&-" */
11111 copyfd(redir->ndup.dupfd, fd);
11124 * Process a list of redirection commands. If the REDIR_PUSH flag is set,
11125 * old file descriptors are stashed away so that the redirection can be
11126 * undone by calling popredir. If the REDIR_BACKQ flag is set, then the
11127 * standard output, and the standard error if it becomes a duplicate of
11128 * stdout, is saved in memory.
11132 redirect(union node *redir, int flags)
11135 struct redirtab *sv;
11146 if (flags & REDIR_PUSH) {
11147 struct redirtab *q;
11148 q = ckmalloc(sizeof (struct redirtab));
11149 q->next = redirlist;
11151 q->nullredirs = nullredirs - 1;
11152 for (i = 0 ; i < 10 ; i++)
11153 q->renamed[i] = EMPTY;
11160 if ((n->nfile.type == NTOFD || n->nfile.type == NFROMFD) &&
11161 n->ndup.dupfd == fd)
11162 continue; /* redirect from/to same file descriptor */
11164 newfd = openredirect(n);
11167 if (sv && *(p = &sv->renamed[fd]) == EMPTY) {
11168 i = fcntl(fd, F_DUPFD, 10);
11175 sh_error("%d: %m", fd);
11185 dupredirect(n, newfd);
11186 } while ((n = n->nfile.next));
11188 if (flags & REDIR_SAVEFD2 && sv && sv->renamed[2] >= 0)
11189 preverrout_fd = sv->renamed[2];
11194 * Undo the effects of the last redirection.
11200 struct redirtab *rp;
11203 if (--nullredirs >= 0)
11207 for (i = 0 ; i < 10 ; i++) {
11208 if (rp->renamed[i] != EMPTY) {
11211 copyfd(rp->renamed[i], i);
11213 close(rp->renamed[i]);
11216 redirlist = rp->next;
11217 nullredirs = rp->nullredirs;
11223 * Undo all redirections. Called on error or interrupt.
11227 * Discard all saved file descriptors.
11231 clearredir(int drop)
11243 * Copy a file descriptor to be >= to. Returns -1
11244 * if the source file descriptor is closed, EMPTY if there are no unused
11245 * file descriptors left.
11249 copyfd(int from, int to)
11253 newfd = fcntl(from, F_DUPFD, to);
11255 if (errno == EMFILE)
11258 sh_error("%d: %m", from);
11265 redirectsafe(union node *redir, int flags)
11268 volatile int saveint;
11269 struct jmploc *volatile savehandler = handler;
11270 struct jmploc jmploc;
11273 if (!(err = setjmp(jmploc.loc) * 2)) {
11275 redirect(redir, flags);
11277 handler = savehandler;
11278 if (err && exception != EXERROR)
11279 longjmp(handler->loc, 1);
11280 RESTOREINT(saveint);
11287 static void shtree(union node *, int, char *, FILE*);
11288 static void shcmd(union node *, FILE *);
11289 static void sharg(union node *, FILE *);
11290 static void indent(int, char *, FILE *);
11291 static void trstring(char *);
11295 showtree(union node *n)
11297 trputs("showtree called\n");
11298 shtree(n, 1, NULL, stdout);
11303 shtree(union node *n, int ind, char *pfx, FILE *fp)
11305 struct nodelist *lp;
11311 indent(ind, pfx, fp);
11322 shtree(n->nbinary.ch1, ind, NULL, fp);
11325 shtree(n->nbinary.ch2, ind, NULL, fp);
11333 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
11338 if (n->npipe.backgnd)
11344 fprintf(fp, "<node type %d>", n->type);
11353 shcmd(union node *cmd, FILE *fp)
11361 for (np = cmd->ncmd.args ; np ; np = np->narg.next) {
11367 for (np = cmd->ncmd.redirect ; np ; np = np->nfile.next) {
11370 switch (np->nfile.type) {
11371 case NTO: s = ">"; dftfd = 1; break;
11372 case NCLOBBER: s = ">|"; dftfd = 1; break;
11373 case NAPPEND: s = ">>"; dftfd = 1; break;
11374 case NTOFD: s = ">&"; dftfd = 1; break;
11375 case NFROM: s = "<"; dftfd = 0; break;
11376 case NFROMFD: s = "<&"; dftfd = 0; break;
11377 case NFROMTO: s = "<>"; dftfd = 0; break;
11378 default: s = "*error*"; dftfd = 0; break;
11380 if (np->nfile.fd != dftfd)
11381 fprintf(fp, "%d", np->nfile.fd);
11383 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
11384 fprintf(fp, "%d", np->ndup.dupfd);
11386 sharg(np->nfile.fname, fp);
11395 sharg(union node *arg, FILE *fp)
11398 struct nodelist *bqlist;
11401 if (arg->type != NARG) {
11402 out1fmt("<node type %d>\n", arg->type);
11405 bqlist = arg->narg.backquote;
11406 for (p = arg->narg.text ; *p ; p++) {
11415 if (subtype == VSLENGTH)
11421 if (subtype & VSNUL)
11424 switch (subtype & VSTYPE) {
11443 case VSTRIMLEFTMAX:
11450 case VSTRIMRIGHTMAX:
11457 out1fmt("<subtype %d>", subtype);
11464 case CTLBACKQ|CTLQUOTE:
11467 shtree(bqlist->n, -1, NULL, fp);
11479 indent(int amount, char *pfx, FILE *fp)
11483 for (i = 0 ; i < amount ; i++) {
11484 if (pfx && i == amount - 1)
11505 putc(c, tracefile);
11509 trace(const char *fmt, ...)
11516 (void) vfprintf(tracefile, fmt, va);
11521 tracev(const char *fmt, va_list va)
11525 (void) vfprintf(tracefile, fmt, va);
11530 trputs(const char *s)
11534 fputs(s, tracefile);
11546 putc('"', tracefile);
11547 for (p = s ; *p ; p++) {
11549 case '\n': c = 'n'; goto backslash;
11550 case '\t': c = 't'; goto backslash;
11551 case '\r': c = 'r'; goto backslash;
11552 case '"': c = '"'; goto backslash;
11553 case '\\': c = '\\'; goto backslash;
11554 case CTLESC: c = 'e'; goto backslash;
11555 case CTLVAR: c = 'v'; goto backslash;
11556 case CTLVAR+CTLQUOTE: c = 'V'; goto backslash;
11557 case CTLBACKQ: c = 'q'; goto backslash;
11558 case CTLBACKQ+CTLQUOTE: c = 'Q'; goto backslash;
11559 backslash: putc('\\', tracefile);
11560 putc(c, tracefile);
11563 if (*p >= ' ' && *p <= '~')
11564 putc(*p, tracefile);
11566 putc('\\', tracefile);
11567 putc(*p >> 6 & 03, tracefile);
11568 putc(*p >> 3 & 07, tracefile);
11569 putc(*p & 07, tracefile);
11574 putc('"', tracefile);
11586 putc(' ', tracefile);
11588 putc('\n', tracefile);
11604 /* leave open because libedit might be using it */
11607 scopy("./trace", s);
11609 if (!freopen(s, "a", tracefile)) {
11610 fprintf(stderr, "Can't re-open %s\n", s);
11615 if ((tracefile = fopen(s, "a")) == NULL) {
11616 fprintf(stderr, "Can't open %s\n", s);
11622 if ((flags = fcntl(fileno(tracefile), F_GETFL, 0)) >= 0)
11623 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
11625 setlinebuf(tracefile);
11626 fputs("\nTracing started.\n", tracefile);
11634 * Sigmode records the current value of the signal handlers for the various
11635 * modes. A value of zero means that the current handler is not known.
11636 * S_HARD_IGN indicates that the signal was ignored on entry to the shell,
11639 #define S_DFL 1 /* default signal handling (SIG_DFL) */
11640 #define S_CATCH 2 /* signal is caught */
11641 #define S_IGN 3 /* signal is ignored (SIG_IGN) */
11642 #define S_HARD_IGN 4 /* signal is ignored permenantly */
11643 #define S_RESET 5 /* temporary - to reset a hard ignored sig */
11648 * The trap builtin.
11652 trapcmd(int argc, char **argv)
11661 for (signo = 0 ; signo < NSIG ; signo++) {
11662 if (trap[signo] != NULL) {
11665 sn = get_signame(signo);
11666 out1fmt("trap -- %s %s\n",
11667 single_quote(trap[signo]), sn);
11677 if ((signo = get_signum(*ap)) < 0)
11678 sh_error("%s: bad trap", *ap);
11681 if (LONE_DASH(action))
11684 action = savestr(action);
11687 ckfree(trap[signo]);
11688 trap[signo] = action;
11699 * Clear traps on a fork.
11707 for (tp = trap ; tp < &trap[NSIG] ; tp++) {
11708 if (*tp && **tp) { /* trap not NULL or SIG_IGN */
11712 if (tp != &trap[0])
11713 setsignal(tp - trap);
11721 * Set the signal handler for the specified signal. The routine figures
11722 * out what it should be set to.
11726 setsignal(int signo)
11730 struct sigaction act;
11732 if ((t = trap[signo]) == NULL)
11734 else if (*t != '\0')
11738 if (rootshell && action == S_DFL) {
11741 if (iflag || minusc || sflag == 0)
11764 t = &sigmode[signo - 1];
11768 * current setting unknown
11770 if (sigaction(signo, 0, &act) == -1) {
11772 * Pretend it worked; maybe we should give a warning
11773 * here, but other shells don't. We don't alter
11774 * sigmode, so that we retry every time.
11778 if (act.sa_handler == SIG_IGN) {
11779 if (mflag && (signo == SIGTSTP ||
11780 signo == SIGTTIN || signo == SIGTTOU)) {
11781 tsig = S_IGN; /* don't hard ignore these */
11785 tsig = S_RESET; /* force to be set */
11788 if (tsig == S_HARD_IGN || tsig == action)
11792 act.sa_handler = onsig;
11795 act.sa_handler = SIG_IGN;
11798 act.sa_handler = SIG_DFL;
11802 sigfillset(&act.sa_mask);
11803 sigaction(signo, &act, 0);
11811 ignoresig(int signo)
11813 if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
11814 signal(signo, SIG_IGN);
11816 sigmode[signo - 1] = S_HARD_IGN;
11827 gotsig[signo - 1] = 1;
11828 pendingsigs = signo;
11830 if (exsig || (signo == SIGINT && !trap[SIGINT])) {
11839 * Called to execute a trap. Perhaps we should avoid entering new trap
11840 * handlers while we are executing a trap handler.
11852 savestatus = exitstatus;
11856 for (i = 0, q = gotsig; i < NSIG - 1; i++, q++) {
11864 skip = evalstring(p, SKIPEVAL);
11865 exitstatus = savestatus;
11875 * Controls whether the shell is interactive or not.
11879 setinteractive(int on)
11881 static int is_interactive;
11883 if (++on == is_interactive)
11885 is_interactive = on;
11887 setsignal(SIGQUIT);
11888 setsignal(SIGTERM);
11889 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
11890 if(is_interactive > 1) {
11891 /* Looks like they want an interactive shell */
11892 static int do_banner;
11896 "\n\n%s Built-in shell (ash)\n"
11897 "Enter 'help' for a list of built-in commands.\n\n",
11906 #if !ENABLE_FEATURE_SH_EXTRA_QUIET
11907 /*** List the available builtins ***/
11909 static int helpcmd(int argc, char **argv)
11913 out1fmt("\nBuilt-in commands:\n-------------------\n");
11914 for (col = 0, i = 0; i < NUMBUILTINS; i++) {
11915 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
11916 builtincmd[i].name + 1);
11922 #if ENABLE_FEATURE_SH_STANDALONE_SHELL
11923 for (i = 0; i < NUM_APPLETS; i++) {
11924 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), applets[i].name);
11932 return EXIT_SUCCESS;
11934 #endif /* CONFIG_FEATURE_SH_EXTRA_QUIET */
11937 * Called to exit the shell.
11947 status = exitstatus;
11948 TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
11949 if (setjmp(loc.loc)) {
11950 if (exception == EXEXIT)
11951 /* dash bug: it just does _exit(exitstatus) here
11952 * but we have to do setjobctl(0) first!
11953 * (bug is still not fixed in dash-0.5.3 - if you run dash
11954 * under Midnight Commander, on exit from dash MC is backgrounded) */
11955 status = exitstatus;
11959 if ((p = trap[0])) {
11972 static struct var *vartab[VTABSIZE];
11974 static int vpcmp(const void *, const void *);
11975 static struct var **findvar(struct var **, const char *);
11978 * Initialize the variable symbol tables and import the environment
11982 #ifdef CONFIG_ASH_GETOPTS
11984 * Safe version of setvar, returns 1 on success 0 on failure.
11988 setvarsafe(const char *name, const char *val, int flags)
11991 volatile int saveint;
11992 struct jmploc *volatile savehandler = handler;
11993 struct jmploc jmploc;
11996 if (setjmp(jmploc.loc))
12000 setvar(name, val, flags);
12003 handler = savehandler;
12004 RESTOREINT(saveint);
12010 * Set the value of a variable. The flags argument is ored with the
12011 * flags of the variable. If val is NULL, the variable is unset.
12015 setvar(const char *name, const char *val, int flags)
12022 q = endofname(name);
12023 p = strchrnul(q, '=');
12024 namelen = p - name;
12025 if (!namelen || p != q)
12026 sh_error("%.*s: bad variable name", namelen, name);
12031 vallen = strlen(val);
12034 nameeq = ckmalloc(namelen + vallen + 2);
12035 p = memcpy(nameeq, name, namelen) + namelen;
12038 p = memcpy(p, val, vallen) + vallen;
12041 setvareq(nameeq, flags | VNOSAVE);
12047 * Same as setvar except that the variable and value are passed in
12048 * the first argument as name=value. Since the first argument will
12049 * be actually stored in the table, it should not be a string that
12051 * Called with interrupts off.
12055 setvareq(char *s, int flags)
12057 struct var *vp, **vpp;
12060 flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
12061 vp = *findvar(vpp, s);
12063 if ((vp->flags & (VREADONLY|VDYNAMIC)) == VREADONLY) {
12066 if (flags & VNOSAVE)
12069 sh_error("%.*s: is read only", strchrnul(n, '=') - n, n);
12072 if (flags & VNOSET)
12075 if (vp->func && (flags & VNOFUNC) == 0)
12076 (*vp->func)(strchrnul(s, '=') + 1);
12078 if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
12081 flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET);
12083 if (flags & VNOSET)
12086 vp = ckmalloc(sizeof (*vp));
12091 if (!(flags & (VTEXTFIXED|VSTACK|VNOSAVE)))
12099 * Process a linked list of variable assignments.
12103 listsetvar(struct strlist *list_set_var, int flags)
12105 struct strlist *lp = list_set_var;
12111 setvareq(lp->text, flags);
12112 } while ((lp = lp->next));
12118 * Find the value of a variable. Returns NULL if not set.
12122 lookupvar(const char *name)
12126 if ((v = *findvar(hashvar(name), name))) {
12129 * Dynamic variables are implemented roughly the same way they are
12130 * in bash. Namely, they're "special" so long as they aren't unset.
12131 * As soon as they're unset, they're no longer dynamic, and dynamic
12132 * lookup will no longer happen at that point. -- PFM.
12134 if((v->flags & VDYNAMIC))
12137 if(!(v->flags & VUNSET))
12138 return strchrnul(v->text, '=') + 1;
12146 * Search the environment of a builtin command.
12150 bltinlookup(const char *name)
12152 struct strlist *sp;
12154 for (sp = cmdenviron ; sp ; sp = sp->next) {
12155 if (varequal(sp->text, name))
12156 return strchrnul(sp->text, '=') + 1;
12158 return lookupvar(name);
12163 * Generate a list of variables satisfying the given conditions.
12167 listvars(int on, int off, char ***end)
12178 for (vp = *vpp ; vp ; vp = vp->next)
12179 if ((vp->flags & mask) == on) {
12180 if (ep == stackstrend())
12181 ep = growstackstr();
12182 *ep++ = (char *) vp->text;
12184 } while (++vpp < vartab + VTABSIZE);
12185 if (ep == stackstrend())
12186 ep = growstackstr();
12190 return grabstackstr(ep);
12195 * POSIX requires that 'set' (but not export or readonly) output the
12196 * variables in lexicographic order - by the locale's collating order (sigh).
12197 * Maybe we could keep them in an ordered balanced binary tree
12198 * instead of hashed lists.
12199 * For now just roll 'em through qsort for printing...
12203 showvars(const char *sep_prefix, int on, int off)
12206 char **ep, **epend;
12208 ep = listvars(on, off, &epend);
12209 qsort(ep, epend - ep, sizeof(char *), vpcmp);
12211 sep = *sep_prefix ? spcstr : sep_prefix;
12213 for (; ep < epend; ep++) {
12217 p = strchrnul(*ep, '=');
12220 q = single_quote(++p);
12222 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
12231 * The export and readonly commands.
12235 exportcmd(int argc, char **argv)
12241 int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT;
12244 notp = nextopt("p") - 'p';
12245 if (notp && ((name = *(aptr = argptr)))) {
12247 if ((p = strchr(name, '=')) != NULL) {
12250 if ((vp = *findvar(hashvar(name), name))) {
12255 setvar(name, p, flag);
12256 } while ((name = *++aptr) != NULL);
12258 showvars(argv[0], flag, 0);
12265 * Make a variable a local variable. When a variable is made local, it's
12266 * value and flags are saved in a localvar structure. The saved values
12267 * will be restored when the shell function returns. We handle the name
12268 * "-" as a special case.
12271 static void mklocal(char *name)
12273 struct localvar *lvp;
12278 lvp = ckmalloc(sizeof (struct localvar));
12279 if (LONE_DASH(name)) {
12281 p = ckmalloc(sizeof(optlist));
12282 lvp->text = memcpy(p, optlist, sizeof(optlist));
12287 vpp = hashvar(name);
12288 vp = *findvar(vpp, name);
12289 eq = strchr(name, '=');
12292 setvareq(name, VSTRFIXED);
12294 setvar(name, NULL, VSTRFIXED);
12295 vp = *vpp; /* the new variable */
12296 lvp->flags = VUNSET;
12298 lvp->text = vp->text;
12299 lvp->flags = vp->flags;
12300 vp->flags |= VSTRFIXED|VTEXTFIXED;
12306 lvp->next = localvars;
12312 * The "local" command.
12316 localcmd(int argc, char **argv)
12321 while ((name = *argv++) != NULL) {
12329 * Called after a function returns.
12330 * Interrupts must be off.
12336 struct localvar *lvp;
12339 while ((lvp = localvars) != NULL) {
12340 localvars = lvp->next;
12342 TRACE(("poplocalvar %s", vp ? vp->text : "-"));
12343 if (vp == NULL) { /* $- saved */
12344 memcpy(optlist, lvp->text, sizeof(optlist));
12347 } else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
12348 unsetvar(vp->text);
12351 (*vp->func)(strchrnul(lvp->text, '=') + 1);
12352 if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
12354 vp->flags = lvp->flags;
12355 vp->text = lvp->text;
12363 * The unset builtin command. We unset the function before we unset the
12364 * variable to allow a function to be unset when there is a readonly variable
12365 * with the same name.
12369 unsetcmd(int argc, char **argv)
12376 while ((i = nextopt("vf")) != '\0') {
12380 for (ap = argptr; *ap ; ap++) {
12395 * Unset the specified variable.
12399 unsetvar(const char *s)
12405 vpp = findvar(hashvar(s), s);
12409 int flags = vp->flags;
12412 if (flags & VREADONLY)
12415 vp->flags &= ~VDYNAMIC;
12417 if (flags & VUNSET)
12419 if ((flags & VSTRFIXED) == 0) {
12421 if ((flags & (VTEXTFIXED|VSTACK)) == 0)
12428 vp->flags &= ~VEXPORT;
12441 * Find the appropriate entry in the hash table from the name.
12444 static struct var **
12445 hashvar(const char *p)
12447 unsigned int hashval;
12449 hashval = ((unsigned char) *p) << 4;
12450 while (*p && *p != '=')
12451 hashval += (unsigned char) *p++;
12452 return &vartab[hashval % VTABSIZE];
12458 * Compares two strings up to the first = or '\0'. The first
12459 * string must be terminated by '='; the second may be terminated by
12460 * either '=' or '\0'.
12464 varcmp(const char *p, const char *q)
12468 while ((c = *p) == (d = *q)) {
12469 if (!c || c == '=')
12483 vpcmp(const void *a, const void *b)
12485 return varcmp(*(const char **)a, *(const char **)b);
12488 static struct var **
12489 findvar(struct var **vpp, const char *name)
12491 for (; *vpp; vpp = &(*vpp)->next) {
12492 if (varequal((*vpp)->text, name)) {
12500 #include <sys/times.h>
12502 static const unsigned char timescmd_str[] = {
12503 ' ', offsetof(struct tms, tms_utime),
12504 '\n', offsetof(struct tms, tms_stime),
12505 ' ', offsetof(struct tms, tms_cutime),
12506 '\n', offsetof(struct tms, tms_cstime),
12510 static int timescmd(int ac, char **av)
12512 long int clk_tck, s, t;
12513 const unsigned char *p;
12516 clk_tck = sysconf(_SC_CLK_TCK);
12521 t = *(clock_t *)(((char *) &buf) + p[1]);
12523 out1fmt("%ldm%ld.%.3lds%c",
12525 ((t - s * clk_tck) * 1000) / clk_tck,
12527 } while (*(p += 2));
12532 #ifdef CONFIG_ASH_MATH_SUPPORT
12534 dash_arith(const char *s)
12540 result = arith(s, &errcode);
12543 sh_error("exponent less than 0");
12544 else if (errcode == -2)
12545 sh_error("divide by zero");
12546 else if (errcode == -5)
12547 sh_error("expression recursion loop detected");
12558 * The let builtin. partial stolen from GNU Bash, the Bourne Again SHell.
12559 * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
12561 * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
12565 letcmd(int argc, char **argv)
12572 sh_error("expression expected");
12573 for (ap = argv + 1; *ap; ap++) {
12574 i = dash_arith(*ap);
12579 #endif /* CONFIG_ASH_MATH_SUPPORT */
12584 * Miscellaneous builtins.
12589 #if defined(__GLIBC__) && __GLIBC__ == 2 && __GLIBC_MINOR__ < 1
12590 typedef enum __rlimit_resource rlim_t;
12595 * The read builtin. The -e option causes backslashes to escape the
12596 * following character.
12598 * This uses unbuffered input, which may be avoidable in some cases.
12602 readcmd(int argc, char **argv)
12614 #if defined(CONFIG_ASH_READ_NCHARS)
12618 struct termios tty, old_tty;
12620 #if defined(CONFIG_ASH_READ_TIMEOUT)
12624 ts.tv_sec = ts.tv_usec = 0;
12629 #if defined(CONFIG_ASH_READ_NCHARS) && defined(CONFIG_ASH_READ_TIMEOUT)
12630 while ((i = nextopt("p:rt:n:s")) != '\0')
12631 #elif defined(CONFIG_ASH_READ_NCHARS)
12632 while ((i = nextopt("p:rn:s")) != '\0')
12633 #elif defined(CONFIG_ASH_READ_TIMEOUT)
12634 while ((i = nextopt("p:rt:")) != '\0')
12636 while ((i = nextopt("p:r")) != '\0')
12641 prompt = optionarg;
12643 #if defined(CONFIG_ASH_READ_NCHARS)
12645 nchars = strtol(optionarg, &p, 10);
12647 sh_error("invalid count");
12648 nch_flag = (nchars > 0);
12654 #if defined(CONFIG_ASH_READ_TIMEOUT)
12656 ts.tv_sec = strtol(optionarg, &p, 10);
12662 ts.tv_usec = strtol(p, &p2, 10);
12664 sh_error("invalid timeout");
12666 /* normalize to usec */
12668 sh_error("invalid timeout");
12669 while (scale++ < 6)
12673 sh_error("invalid timeout");
12675 if ( ! ts.tv_sec && ! ts.tv_usec)
12676 sh_error("invalid timeout");
12686 if (prompt && isatty(0)) {
12689 if (*(ap = argptr) == NULL)
12690 sh_error("arg count");
12691 if ((ifs = bltinlookup("IFS")) == NULL)
12693 #if defined(CONFIG_ASH_READ_NCHARS)
12694 if (nch_flag || silent) {
12695 tcgetattr(0, &tty);
12698 tty.c_lflag &= ~ICANON;
12699 tty.c_cc[VMIN] = nchars;
12702 tty.c_lflag &= ~(ECHO|ECHOK|ECHONL);
12705 tcsetattr(0, TCSANOW, &tty);
12708 #if defined(CONFIG_ASH_READ_TIMEOUT)
12709 if (ts.tv_sec || ts.tv_usec) {
12713 i = select(FD_SETSIZE, &set, NULL, NULL, &ts);
12715 #if defined(CONFIG_ASH_READ_NCHARS)
12717 tcsetattr(0, TCSANOW, &old_tty);
12727 #if defined(CONFIG_ASH_READ_NCHARS)
12728 while (!nch_flag || nchars--)
12733 if (read(0, &c, 1) != 1) {
12745 if (!rflag && c == '\\') {
12751 if (startword && *ifs == ' ' && strchr(ifs, c)) {
12755 if (ap[1] != NULL && strchr(ifs, c) != NULL) {
12757 setvar(*ap, stackblock(), 0);
12766 #if defined(CONFIG_ASH_READ_NCHARS)
12767 if (nch_flag || silent)
12768 tcsetattr(0, TCSANOW, &old_tty);
12772 /* Remove trailing blanks */
12773 while ((char *)stackblock() <= --p && strchr(ifs, *p) != NULL)
12775 setvar(*ap, stackblock(), 0);
12776 while (*++ap != NULL)
12777 setvar(*ap, nullstr, 0);
12782 static int umaskcmd(int argc, char **argv)
12784 static const char permuser[3] = "ugo";
12785 static const char permmode[3] = "rwx";
12786 static const short int permmask[] = {
12787 S_IRUSR, S_IWUSR, S_IXUSR,
12788 S_IRGRP, S_IWGRP, S_IXGRP,
12789 S_IROTH, S_IWOTH, S_IXOTH
12795 int symbolic_mode = 0;
12797 while (nextopt("S") != '\0') {
12806 if ((ap = *argptr) == NULL) {
12807 if (symbolic_mode) {
12811 for (i = 0; i < 3; i++) {
12814 *p++ = permuser[i];
12816 for (j = 0; j < 3; j++) {
12817 if ((mask & permmask[3 * i + j]) == 0) {
12818 *p++ = permmode[j];
12826 out1fmt("%.4o\n", mask);
12829 if (is_digit((unsigned char) *ap)) {
12832 if (*ap >= '8' || *ap < '0')
12833 sh_error(illnum, argv[1]);
12834 mask = (mask << 3) + (*ap - '0');
12835 } while (*++ap != '\0');
12838 mask = ~mask & 0777;
12839 if (!bb_parse_mode(ap, &mask)) {
12840 sh_error("Illegal mode: %s", ap);
12842 umask(~mask & 0777);
12851 * This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and
12852 * Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with
12853 * ash by J.T. Conklin.
12861 int factor; /* multiply by to get rlim_{cur,max} values */
12865 static const struct limits limits[] = {
12867 { "time(seconds)", RLIMIT_CPU, 1, 't' },
12869 #ifdef RLIMIT_FSIZE
12870 { "file(blocks)", RLIMIT_FSIZE, 512, 'f' },
12873 { "data(kbytes)", RLIMIT_DATA, 1024, 'd' },
12875 #ifdef RLIMIT_STACK
12876 { "stack(kbytes)", RLIMIT_STACK, 1024, 's' },
12879 { "coredump(blocks)", RLIMIT_CORE, 512, 'c' },
12882 { "memory(kbytes)", RLIMIT_RSS, 1024, 'm' },
12884 #ifdef RLIMIT_MEMLOCK
12885 { "locked memory(kbytes)", RLIMIT_MEMLOCK, 1024, 'l' },
12887 #ifdef RLIMIT_NPROC
12888 { "process", RLIMIT_NPROC, 1, 'p' },
12890 #ifdef RLIMIT_NOFILE
12891 { "nofiles", RLIMIT_NOFILE, 1, 'n' },
12894 { "vmemory(kbytes)", RLIMIT_AS, 1024, 'v' },
12896 #ifdef RLIMIT_LOCKS
12897 { "locks", RLIMIT_LOCKS, 1, 'w' },
12899 { (char *) 0, 0, 0, '\0' }
12902 enum limtype { SOFT = 0x1, HARD = 0x2 };
12904 static void printlim(enum limtype how, const struct rlimit *limit,
12905 const struct limits *l)
12909 val = limit->rlim_max;
12911 val = limit->rlim_cur;
12913 if (val == RLIM_INFINITY)
12914 out1fmt("unlimited\n");
12917 out1fmt("%lld\n", (long long) val);
12922 ulimitcmd(int argc, char **argv)
12926 enum limtype how = SOFT | HARD;
12927 const struct limits *l;
12930 struct rlimit limit;
12933 while ((optc = nextopt("HSa"
12937 #ifdef RLIMIT_FSIZE
12943 #ifdef RLIMIT_STACK
12952 #ifdef RLIMIT_MEMLOCK
12955 #ifdef RLIMIT_NPROC
12958 #ifdef RLIMIT_NOFILE
12964 #ifdef RLIMIT_LOCKS
12982 for (l = limits; l->option != what; l++)
12985 set = *argptr ? 1 : 0;
12989 if (all || argptr[1])
12990 sh_error("too many arguments");
12991 if (strncmp(p, "unlimited\n", 9) == 0)
12992 val = RLIM_INFINITY;
12996 while ((c = *p++) >= '0' && c <= '9')
12998 val = (val * 10) + (long)(c - '0');
12999 if (val < (rlim_t) 0)
13003 sh_error("bad number");
13008 for (l = limits; l->name; l++) {
13009 getrlimit(l->cmd, &limit);
13010 out1fmt("%-20s ", l->name);
13011 printlim(how, &limit, l);
13016 getrlimit(l->cmd, &limit);
13019 limit.rlim_max = val;
13021 limit.rlim_cur = val;
13022 if (setrlimit(l->cmd, &limit) < 0)
13023 sh_error("error setting limit (%m)");
13025 printlim(how, &limit, l);
13031 #ifdef CONFIG_ASH_MATH_SUPPORT
13033 /* Copyright (c) 2001 Aaron Lehmann <aaronl@vitelus.com>
13035 Permission is hereby granted, free of charge, to any person obtaining
13036 a copy of this software and associated documentation files (the
13037 "Software"), to deal in the Software without restriction, including
13038 without limitation the rights to use, copy, modify, merge, publish,
13039 distribute, sublicense, and/or sell copies of the Software, and to
13040 permit persons to whom the Software is furnished to do so, subject to
13041 the following conditions:
13043 The above copyright notice and this permission notice shall be
13044 included in all copies or substantial portions of the Software.
13046 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13047 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
13048 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
13049 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
13050 CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
13051 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
13052 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
13055 /* This is my infix parser/evaluator. It is optimized for size, intended
13056 * as a replacement for yacc-based parsers. However, it may well be faster
13057 * than a comparable parser written in yacc. The supported operators are
13058 * listed in #defines below. Parens, order of operations, and error handling
13059 * are supported. This code is thread safe. The exact expression format should
13060 * be that which POSIX specifies for shells. */
13062 /* The code uses a simple two-stack algorithm. See
13063 * http://www.onthenet.com.au/~grahamis/int2008/week02/lect02.html
13064 * for a detailed explanation of the infix-to-postfix algorithm on which
13065 * this is based (this code differs in that it applies operators immediately
13066 * to the stack instead of adding them to a queue to end up with an
13069 /* To use the routine, call it with an expression string and error return
13073 * Aug 24, 2001 Manuel Novoa III
13075 * Reduced the generated code size by about 30% (i386) and fixed several bugs.
13077 * 1) In arith_apply():
13078 * a) Cached values of *numptr and &(numptr[-1]).
13079 * b) Removed redundant test for zero denominator.
13082 * a) Eliminated redundant code for processing operator tokens by moving
13083 * to a table-based implementation. Also folded handling of parens
13085 * b) Combined all 3 loops which called arith_apply to reduce generated
13086 * code size at the cost of speed.
13088 * 3) The following expressions were treated as valid by the original code:
13089 * 1() , 0! , 1 ( *3 ) .
13090 * These bugs have been fixed by internally enclosing the expression in
13091 * parens and then checking that all binary ops and right parens are
13092 * preceded by a valid expression (NUM_TOKEN).
13094 * Note: It may be desirable to replace Aaron's test for whitespace with
13095 * ctype's isspace() if it is used by another busybox applet or if additional
13096 * whitespace chars should be considered. Look below the "#include"s for a
13097 * precompiler test.
13101 * Aug 26, 2001 Manuel Novoa III
13103 * Return 0 for null expressions. Pointed out by Vladimir Oleynik.
13105 * Merge in Aaron's comments previously posted to the busybox list,
13106 * modified slightly to take account of my changes to the code.
13111 * (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
13113 * - allow access to variable,
13114 * used recursive find value indirection (c=2*2; a="c"; $((a+=2)) produce 6)
13115 * - realize assign syntax (VAR=expr, +=, *= etc)
13116 * - realize exponentiation (** operator)
13117 * - realize comma separated - expr, expr
13118 * - realise ++expr --expr expr++ expr--
13119 * - realise expr ? expr : expr (but, second expr calculate always)
13120 * - allow hexadecimal and octal numbers
13121 * - was restored loses XOR operator
13122 * - remove one goto label, added three ;-)
13123 * - protect $((num num)) as true zero expr (Manuel`s error)
13124 * - always use special isspace(), see comment from bash ;-)
13128 #define arith_isspace(arithval) \
13129 (arithval == ' ' || arithval == '\n' || arithval == '\t')
13132 typedef unsigned char operator;
13134 /* An operator's token id is a bit of a bitfield. The lower 5 bits are the
13135 * precedence, and 3 high bits are an ID unique across operators of that
13136 * precedence. The ID portion is so that multiple operators can have the
13137 * same precedence, ensuring that the leftmost one is evaluated first.
13138 * Consider * and /. */
13140 #define tok_decl(prec,id) (((id)<<5)|(prec))
13141 #define PREC(op) ((op) & 0x1F)
13143 #define TOK_LPAREN tok_decl(0,0)
13145 #define TOK_COMMA tok_decl(1,0)
13147 #define TOK_ASSIGN tok_decl(2,0)
13148 #define TOK_AND_ASSIGN tok_decl(2,1)
13149 #define TOK_OR_ASSIGN tok_decl(2,2)
13150 #define TOK_XOR_ASSIGN tok_decl(2,3)
13151 #define TOK_PLUS_ASSIGN tok_decl(2,4)
13152 #define TOK_MINUS_ASSIGN tok_decl(2,5)
13153 #define TOK_LSHIFT_ASSIGN tok_decl(2,6)
13154 #define TOK_RSHIFT_ASSIGN tok_decl(2,7)
13156 #define TOK_MUL_ASSIGN tok_decl(3,0)
13157 #define TOK_DIV_ASSIGN tok_decl(3,1)
13158 #define TOK_REM_ASSIGN tok_decl(3,2)
13160 /* all assign is right associativity and precedence eq, but (7+3)<<5 > 256 */
13161 #define convert_prec_is_assing(prec) do { if(prec == 3) prec = 2; } while(0)
13163 /* conditional is right associativity too */
13164 #define TOK_CONDITIONAL tok_decl(4,0)
13165 #define TOK_CONDITIONAL_SEP tok_decl(4,1)
13167 #define TOK_OR tok_decl(5,0)
13169 #define TOK_AND tok_decl(6,0)
13171 #define TOK_BOR tok_decl(7,0)
13173 #define TOK_BXOR tok_decl(8,0)
13175 #define TOK_BAND tok_decl(9,0)
13177 #define TOK_EQ tok_decl(10,0)
13178 #define TOK_NE tok_decl(10,1)
13180 #define TOK_LT tok_decl(11,0)
13181 #define TOK_GT tok_decl(11,1)
13182 #define TOK_GE tok_decl(11,2)
13183 #define TOK_LE tok_decl(11,3)
13185 #define TOK_LSHIFT tok_decl(12,0)
13186 #define TOK_RSHIFT tok_decl(12,1)
13188 #define TOK_ADD tok_decl(13,0)
13189 #define TOK_SUB tok_decl(13,1)
13191 #define TOK_MUL tok_decl(14,0)
13192 #define TOK_DIV tok_decl(14,1)
13193 #define TOK_REM tok_decl(14,2)
13195 /* exponent is right associativity */
13196 #define TOK_EXPONENT tok_decl(15,1)
13198 /* For now unary operators. */
13199 #define UNARYPREC 16
13200 #define TOK_BNOT tok_decl(UNARYPREC,0)
13201 #define TOK_NOT tok_decl(UNARYPREC,1)
13203 #define TOK_UMINUS tok_decl(UNARYPREC+1,0)
13204 #define TOK_UPLUS tok_decl(UNARYPREC+1,1)
13206 #define PREC_PRE (UNARYPREC+2)
13208 #define TOK_PRE_INC tok_decl(PREC_PRE, 0)
13209 #define TOK_PRE_DEC tok_decl(PREC_PRE, 1)
13211 #define PREC_POST (UNARYPREC+3)
13213 #define TOK_POST_INC tok_decl(PREC_POST, 0)
13214 #define TOK_POST_DEC tok_decl(PREC_POST, 1)
13216 #define SPEC_PREC (UNARYPREC+4)
13218 #define TOK_NUM tok_decl(SPEC_PREC, 0)
13219 #define TOK_RPAREN tok_decl(SPEC_PREC, 1)
13221 #define NUMPTR (*numstackptr)
13223 static int tok_have_assign(operator op)
13225 operator prec = PREC(op);
13227 convert_prec_is_assing(prec);
13228 return (prec == PREC(TOK_ASSIGN) ||
13229 prec == PREC_PRE || prec == PREC_POST);
13232 static int is_right_associativity(operator prec)
13234 return (prec == PREC(TOK_ASSIGN) || prec == PREC(TOK_EXPONENT) ||
13235 prec == PREC(TOK_CONDITIONAL));
13239 typedef struct ARITCH_VAR_NUM {
13241 arith_t contidional_second_val;
13242 char contidional_second_val_initialized;
13243 char *var; /* if NULL then is regular number,
13244 else is variable name */
13248 typedef struct CHK_VAR_RECURSIVE_LOOPED {
13250 struct CHK_VAR_RECURSIVE_LOOPED *next;
13251 } chk_var_recursive_looped_t;
13253 static chk_var_recursive_looped_t *prev_chk_var_recursive;
13256 static int arith_lookup_val(v_n_t *t)
13259 const char * p = lookupvar(t->var);
13264 /* recursive try as expression */
13265 chk_var_recursive_looped_t *cur;
13266 chk_var_recursive_looped_t cur_save;
13268 for(cur = prev_chk_var_recursive; cur; cur = cur->next) {
13269 if(strcmp(cur->var, t->var) == 0) {
13270 /* expression recursion loop detected */
13274 /* save current lookuped var name */
13275 cur = prev_chk_var_recursive;
13276 cur_save.var = t->var;
13277 cur_save.next = cur;
13278 prev_chk_var_recursive = &cur_save;
13280 t->val = arith (p, &errcode);
13281 /* restore previous ptr after recursiving */
13282 prev_chk_var_recursive = cur;
13285 /* allow undefined var as 0 */
13292 /* "applying" a token means performing it on the top elements on the integer
13293 * stack. For a unary operator it will only change the top element, but a
13294 * binary operator will pop two arguments and push a result */
13295 static int arith_apply(operator op, v_n_t *numstack, v_n_t **numstackptr)
13298 arith_t numptr_val, rez;
13299 int ret_arith_lookup_val;
13301 if (NUMPTR == numstack) goto err; /* There is no operator that can work
13302 without arguments */
13303 numptr_m1 = NUMPTR - 1;
13305 /* check operand is var with noninteger value */
13306 ret_arith_lookup_val = arith_lookup_val(numptr_m1);
13307 if(ret_arith_lookup_val)
13308 return ret_arith_lookup_val;
13310 rez = numptr_m1->val;
13311 if (op == TOK_UMINUS)
13313 else if (op == TOK_NOT)
13315 else if (op == TOK_BNOT)
13317 else if (op == TOK_POST_INC || op == TOK_PRE_INC)
13319 else if (op == TOK_POST_DEC || op == TOK_PRE_DEC)
13321 else if (op != TOK_UPLUS) {
13322 /* Binary operators */
13324 /* check and binary operators need two arguments */
13325 if (numptr_m1 == numstack) goto err;
13327 /* ... and they pop one */
13330 if (op == TOK_CONDITIONAL) {
13331 if(! numptr_m1->contidional_second_val_initialized) {
13332 /* protect $((expr1 ? expr2)) without ": expr" */
13335 rez = numptr_m1->contidional_second_val;
13336 } else if(numptr_m1->contidional_second_val_initialized) {
13337 /* protect $((expr1 : expr2)) without "expr ? " */
13340 numptr_m1 = NUMPTR - 1;
13341 if(op != TOK_ASSIGN) {
13342 /* check operand is var with noninteger value for not '=' */
13343 ret_arith_lookup_val = arith_lookup_val(numptr_m1);
13344 if(ret_arith_lookup_val)
13345 return ret_arith_lookup_val;
13347 if (op == TOK_CONDITIONAL) {
13348 numptr_m1->contidional_second_val = rez;
13350 rez = numptr_m1->val;
13351 if (op == TOK_BOR || op == TOK_OR_ASSIGN)
13353 else if (op == TOK_OR)
13354 rez = numptr_val || rez;
13355 else if (op == TOK_BAND || op == TOK_AND_ASSIGN)
13357 else if (op == TOK_BXOR || op == TOK_XOR_ASSIGN)
13359 else if (op == TOK_AND)
13360 rez = rez && numptr_val;
13361 else if (op == TOK_EQ)
13362 rez = (rez == numptr_val);
13363 else if (op == TOK_NE)
13364 rez = (rez != numptr_val);
13365 else if (op == TOK_GE)
13366 rez = (rez >= numptr_val);
13367 else if (op == TOK_RSHIFT || op == TOK_RSHIFT_ASSIGN)
13368 rez >>= numptr_val;
13369 else if (op == TOK_LSHIFT || op == TOK_LSHIFT_ASSIGN)
13370 rez <<= numptr_val;
13371 else if (op == TOK_GT)
13372 rez = (rez > numptr_val);
13373 else if (op == TOK_LT)
13374 rez = (rez < numptr_val);
13375 else if (op == TOK_LE)
13376 rez = (rez <= numptr_val);
13377 else if (op == TOK_MUL || op == TOK_MUL_ASSIGN)
13379 else if (op == TOK_ADD || op == TOK_PLUS_ASSIGN)
13381 else if (op == TOK_SUB || op == TOK_MINUS_ASSIGN)
13383 else if (op == TOK_ASSIGN || op == TOK_COMMA)
13385 else if (op == TOK_CONDITIONAL_SEP) {
13386 if (numptr_m1 == numstack) {
13387 /* protect $((expr : expr)) without "expr ? " */
13390 numptr_m1->contidional_second_val_initialized = op;
13391 numptr_m1->contidional_second_val = numptr_val;
13393 else if (op == TOK_CONDITIONAL) {
13395 numptr_val : numptr_m1->contidional_second_val;
13397 else if(op == TOK_EXPONENT) {
13399 return -3; /* exponent less than 0 */
13404 while(numptr_val--)
13409 else if(numptr_val==0) /* zero divisor check */
13411 else if (op == TOK_DIV || op == TOK_DIV_ASSIGN)
13413 else if (op == TOK_REM || op == TOK_REM_ASSIGN)
13416 if(tok_have_assign(op)) {
13419 if(numptr_m1->var == NULL) {
13423 /* save to shell variable */
13424 #ifdef CONFIG_ASH_MATH_SUPPORT_64
13425 snprintf(buf, sizeof(buf), "%lld", arith_t_type rez);
13427 snprintf(buf, sizeof(buf), "%ld", arith_t_type rez);
13429 setvar(numptr_m1->var, buf, 0);
13430 /* after saving, make previous value for v++ or v-- */
13431 if(op == TOK_POST_INC)
13433 else if(op == TOK_POST_DEC)
13436 numptr_m1->val = rez;
13437 /* protect geting var value, is number now */
13438 numptr_m1->var = NULL;
13444 /* longest must first */
13445 static const char op_tokens[] = {
13446 '<','<','=',0, TOK_LSHIFT_ASSIGN,
13447 '>','>','=',0, TOK_RSHIFT_ASSIGN,
13448 '<','<', 0, TOK_LSHIFT,
13449 '>','>', 0, TOK_RSHIFT,
13450 '|','|', 0, TOK_OR,
13451 '&','&', 0, TOK_AND,
13452 '!','=', 0, TOK_NE,
13453 '<','=', 0, TOK_LE,
13454 '>','=', 0, TOK_GE,
13455 '=','=', 0, TOK_EQ,
13456 '|','=', 0, TOK_OR_ASSIGN,
13457 '&','=', 0, TOK_AND_ASSIGN,
13458 '*','=', 0, TOK_MUL_ASSIGN,
13459 '/','=', 0, TOK_DIV_ASSIGN,
13460 '%','=', 0, TOK_REM_ASSIGN,
13461 '+','=', 0, TOK_PLUS_ASSIGN,
13462 '-','=', 0, TOK_MINUS_ASSIGN,
13463 '-','-', 0, TOK_POST_DEC,
13464 '^','=', 0, TOK_XOR_ASSIGN,
13465 '+','+', 0, TOK_POST_INC,
13466 '*','*', 0, TOK_EXPONENT,
13470 '=', 0, TOK_ASSIGN,
13482 '?', 0, TOK_CONDITIONAL,
13483 ':', 0, TOK_CONDITIONAL_SEP,
13484 ')', 0, TOK_RPAREN,
13485 '(', 0, TOK_LPAREN,
13489 #define endexpression &op_tokens[sizeof(op_tokens)-7]
13492 static arith_t arith(const char *expr, int *perrcode)
13494 char arithval; /* Current character under analysis */
13495 operator lasttok, op;
13498 const char *p = endexpression;
13501 size_t datasizes = strlen(expr) + 2;
13503 /* Stack of integers */
13504 /* The proof that there can be no more than strlen(startbuf)/2+1 integers
13505 * in any given correct or incorrect expression is left as an exercise to
13507 v_n_t *numstack = alloca(((datasizes)/2)*sizeof(v_n_t)),
13508 *numstackptr = numstack;
13509 /* Stack of operator tokens */
13510 operator *stack = alloca((datasizes) * sizeof(operator)),
13513 *stackptr++ = lasttok = TOK_LPAREN; /* start off with a left paren */
13514 *perrcode = errcode = 0;
13517 if ((arithval = *expr) == 0) {
13518 if (p == endexpression) {
13519 /* Null expression. */
13523 /* This is only reached after all tokens have been extracted from the
13524 * input stream. If there are still tokens on the operator stack, they
13525 * are to be applied in order. At the end, there should be a final
13526 * result on the integer stack */
13528 if (expr != endexpression + 1) {
13529 /* If we haven't done so already, */
13530 /* append a closing right paren */
13531 expr = endexpression;
13532 /* and let the loop process it. */
13535 /* At this point, we're done with the expression. */
13536 if (numstackptr != numstack+1) {
13537 /* ... but if there isn't, it's bad */
13539 return (*perrcode = -1);
13541 if(numstack->var) {
13542 /* expression is $((var)) only, lookup now */
13543 errcode = arith_lookup_val(numstack);
13546 *perrcode = errcode;
13547 return numstack->val;
13549 /* Continue processing the expression. */
13550 if (arith_isspace(arithval)) {
13551 /* Skip whitespace */
13554 if((p = endofname(expr)) != expr) {
13555 size_t var_name_size = (p-expr) + 1; /* trailing zero */
13557 numstackptr->var = alloca(var_name_size);
13558 safe_strncpy(numstackptr->var, expr, var_name_size);
13561 numstackptr->contidional_second_val_initialized = 0;
13565 } else if (is_digit(arithval)) {
13566 numstackptr->var = NULL;
13567 #ifdef CONFIG_ASH_MATH_SUPPORT_64
13568 numstackptr->val = strtoll(expr, (char **) &expr, 0);
13570 numstackptr->val = strtol(expr, (char **) &expr, 0);
13574 for(p = op_tokens; ; p++) {
13578 /* strange operator not found */
13581 for(o = expr; *p && *o == *p; p++)
13588 /* skip tail uncompared token */
13591 /* skip zero delim */
13596 /* post grammar: a++ reduce to num */
13597 if(lasttok == TOK_POST_INC || lasttok == TOK_POST_DEC)
13600 /* Plus and minus are binary (not unary) _only_ if the last
13601 * token was as number, or a right paren (which pretends to be
13602 * a number, since it evaluates to one). Think about it.
13603 * It makes sense. */
13604 if (lasttok != TOK_NUM) {
13620 /* We don't want a unary operator to cause recursive descent on the
13621 * stack, because there can be many in a row and it could cause an
13622 * operator to be evaluated before its argument is pushed onto the
13623 * integer stack. */
13624 /* But for binary operators, "apply" everything on the operator
13625 * stack until we find an operator with a lesser priority than the
13626 * one we have just extracted. */
13627 /* Left paren is given the lowest priority so it will never be
13628 * "applied" in this way.
13629 * if associativity is right and priority eq, applied also skip
13632 if ((prec > 0 && prec < UNARYPREC) || prec == SPEC_PREC) {
13633 /* not left paren or unary */
13634 if (lasttok != TOK_NUM) {
13635 /* binary op must be preceded by a num */
13638 while (stackptr != stack) {
13639 if (op == TOK_RPAREN) {
13640 /* The algorithm employed here is simple: while we don't
13641 * hit an open paren nor the bottom of the stack, pop
13642 * tokens and apply them */
13643 if (stackptr[-1] == TOK_LPAREN) {
13645 /* Any operator directly after a */
13647 /* close paren should consider itself binary */
13651 operator prev_prec = PREC(stackptr[-1]);
13653 convert_prec_is_assing(prec);
13654 convert_prec_is_assing(prev_prec);
13655 if (prev_prec < prec)
13657 /* check right assoc */
13658 if(prev_prec == prec && is_right_associativity(prec))
13661 errcode = arith_apply(*--stackptr, numstack, &numstackptr);
13662 if(errcode) goto ret;
13664 if (op == TOK_RPAREN) {
13669 /* Push this operator to the stack and remember it. */
13670 *stackptr++ = lasttok = op;
13677 #endif /* CONFIG_ASH_MATH_SUPPORT */
13681 const char *applet_name = "debug stuff usage";
13682 int main(int argc, char **argv)
13684 return ash_main(argc, argv);
13689 * Copyright (c) 1989, 1991, 1993, 1994
13690 * The Regents of the University of California. All rights reserved.
13692 * This code is derived from software contributed to Berkeley by
13693 * Kenneth Almquist.
13695 * Redistribution and use in source and binary forms, with or without
13696 * modification, are permitted provided that the following conditions
13698 * 1. Redistributions of source code must retain the above copyright
13699 * notice, this list of conditions and the following disclaimer.
13700 * 2. Redistributions in binary form must reproduce the above copyright
13701 * notice, this list of conditions and the following disclaimer in the
13702 * documentation and/or other materials provided with the distribution.
13703 * 3. Neither the name of the University nor the names of its contributors
13704 * may be used to endorse or promote products derived from this software
13705 * without specific prior written permission.
13707 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
13708 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
13709 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
13710 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
13711 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
13712 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
13713 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13714 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
13715 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
13716 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF