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 * This program is free software; you can redistribute it and/or modify
16 * it under the terms of the GNU General Public License as published by
17 * the Free Software Foundation; either version 2 of the License, or
18 * (at your option) any later version.
20 * This program is distributed in the hope that it will be useful,
21 * but WITHOUT ANY WARRANTY; without even the implied warranty of
22 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
23 * General Public License for more details.
25 * You should have received a copy of the GNU General Public License
26 * along with this program; if not, write to the Free Software
27 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
29 * Original BSD copyright notice is retained at the end of this file.
33 * rewrite arith.y to micro stack based cryptic algorithm by
34 * Copyright (c) 2001 Aaron Lehmann <aaronl@vitelus.com>
36 * Modified by Paul Mundt <lethal@linux-sh.org> (c) 2004 to support
39 * Modified by Vladimir Oleynik <dzo@simtreas.ru> (c) 2001-2005 to be
40 * used in busybox and size optimizations,
41 * rewrote arith (see notes to this), added locale support,
42 * rewrote dynamic variables.
48 * The follow should be set to reflect the type of system you have:
49 * JOBS -> 1 if you have Berkeley job control, 0 otherwise.
50 * define SYSV if you are running under System V.
51 * define DEBUG=1 to compile in debugging ('set -o debug' to turn on)
52 * define DEBUG=2 to compile in and turn on debugging.
54 * When debugging is on, debugging info will be written to ./trace and
55 * a quit signal will generate a core dump.
68 #include <sys/types.h>
69 #include <sys/ioctl.h>
70 #include <sys/param.h>
71 #include <sys/resource.h>
100 #ifdef CONFIG_ASH_JOB_CONTROL
106 #if JOBS || defined(CONFIG_ASH_READ_NCHARS)
114 static int *dash_errno;
116 #define errno (*dash_errno)
119 #if defined(__uClinux__)
120 #error "Do not even bother, ash will not run on uClinux"
124 #define _DIAGASSERT(assert_expr) assert(assert_expr)
126 #define _DIAGASSERT(assert_expr)
130 #ifdef CONFIG_ASH_ALIAS
143 static struct alias *lookupalias(const char *, int);
144 static int aliascmd(int, char **);
145 static int unaliascmd(int, char **);
146 static void rmaliases(void);
147 static int unalias(const char *);
148 static void printalias(const struct alias *);
154 static void setpwd(const char *, int);
160 * Types of operations (passed to the errmsg routine).
164 static const char not_found_msg[] = "%s: not found";
167 #define E_OPEN "No such file" /* opening a file */
168 #define E_CREAT "Directory nonexistent" /* creating a file */
169 #define E_EXEC not_found_msg+4 /* executing a program */
172 * We enclose jmp_buf in a structure so that we can declare pointers to
173 * jump locations. The global variable handler contains the location to
174 * jump to when an exception occurs, and the global variable exception
175 * contains a code identifying the exception. To implement nested
176 * exception handlers, the user should save the value of handler on entry
177 * to an inner scope, set handler to point to a jmploc structure for the
178 * inner scope, and restore handler on exit from the scope.
185 static struct jmploc *handler;
186 static int exception;
187 static volatile int suppressint;
188 static volatile sig_atomic_t intpending;
191 #define EXINT 0 /* SIGINT received */
192 #define EXERROR 1 /* a generic error */
193 #define EXSHELLPROC 2 /* execute a shell procedure */
194 #define EXEXEC 3 /* command execution failed */
195 #define EXEXIT 4 /* exit the shell */
196 #define EXSIG 5 /* trapped signal in wait(1) */
199 /* do we generate EXSIG events */
201 /* last pending signal */
202 static volatile sig_atomic_t pendingsigs;
205 * These macros allow the user to suspend the handling of interrupt signals
206 * over a period of time. This is similar to SIGHOLD to or sigblock, but
207 * much more efficient and portable. (But hacking the kernel is so much
208 * more fun than worrying about efficiency and portability. :-))
211 #define xbarrier() ({ __asm__ __volatile__ ("": : :"memory"); })
218 #define SAVEINT(v) ((v) = suppressint)
219 #define RESTOREINT(v) \
222 if ((suppressint = (v)) == 0 && intpending) onint(); \
233 /* EXSIG is turned off by evalbltin(). */
236 static void exraise(int) __attribute__((__noreturn__));
237 static void onint(void) __attribute__((__noreturn__));
239 static void sh_error(const char *, ...) __attribute__((__noreturn__));
240 static void exerror(int, const char *, ...) __attribute__((__noreturn__));
242 static void sh_warnx(const char *, ...);
244 #ifdef CONFIG_ASH_OPTIMIZE_FOR_SIZE
247 if (--suppressint == 0 && intpending) {
251 #define INTON inton()
252 static void forceinton(void)
258 #define FORCEINTON forceinton()
263 if (--suppressint == 0 && intpending) onint(); \
270 if (intpending) onint(); \
273 #endif /* CONFIG_ASH_OPTIMIZE_FOR_SIZE */
278 struct strlist *next;
284 struct strlist *list;
285 struct strlist **lastp;
291 #define EXP_FULL 0x1 /* perform word splitting & file globbing */
292 #define EXP_TILDE 0x2 /* do normal tilde expansion */
293 #define EXP_VARTILDE 0x4 /* expand tildes in an assignment */
294 #define EXP_REDIR 0x8 /* file glob for a redirection (1 match only) */
295 #define EXP_CASE 0x10 /* keeps quotes around for CASE pattern */
296 #define EXP_RECORD 0x20 /* need to record arguments for ifs breakup */
297 #define EXP_VARTILDE2 0x40 /* expand tildes after colons only */
298 #define EXP_WORD 0x80 /* expand word in parameter expansion */
299 #define EXP_QWORD 0x100 /* expand word in quoted parameter expansion */
303 static void expandarg(union node *, struct arglist *, int);
304 #define rmescapes(p) _rmescapes((p), 0)
305 static char *_rmescapes(char *, int);
306 static int casematch(union node *, char *);
308 #ifdef CONFIG_ASH_MATH_SUPPORT
309 static void expari(int);
314 static char *commandname; /* currently executing command */
315 static struct strlist *cmdenviron; /* environment for builtin command */
316 static int exitstatus; /* exit status of last command */
317 static int back_exitstatus; /* exit status of backquoted command */
320 struct backcmd { /* result of evalbackcmd */
321 int fd; /* file descriptor to read from */
322 char *buf; /* buffer */
323 int nleft; /* number of chars in buffer */
324 struct job *jp; /* job structure for command */
328 * This file was generated by the mknodes program.
364 union node *redirect;
371 struct nodelist *cmdlist;
378 union node *redirect;
393 union node *elsepart;
424 struct nodelist *backquote;
464 struct nredir nredir;
465 struct nbinary nbinary;
469 struct nclist nclist;
479 struct nodelist *next;
490 static void freefunc(struct funcnode *);
493 /* control characters in argument strings */
494 #define CTL_FIRST '\201' /* first 'special' character */
495 #define CTLESC '\201' /* escape next character */
496 #define CTLVAR '\202' /* variable defn */
497 #define CTLENDVAR '\203'
498 #define CTLBACKQ '\204'
499 #define CTLQUOTE 01 /* ored with CTLBACKQ code if in quotes */
500 /* CTLBACKQ | CTLQUOTE == '\205' */
501 #define CTLARI '\206' /* arithmetic expression */
502 #define CTLENDARI '\207'
503 #define CTLQUOTEMARK '\210'
504 #define CTL_LAST '\210' /* last 'special' character */
506 /* variable substitution byte (follows CTLVAR) */
507 #define VSTYPE 0x0f /* type of variable substitution */
508 #define VSNUL 0x10 /* colon--treat the empty string as unset */
509 #define VSQUOTE 0x80 /* inside double quotes--suppress splitting */
511 /* values of VSTYPE field */
512 #define VSNORMAL 0x1 /* normal variable: $var or ${var} */
513 #define VSMINUS 0x2 /* ${var-text} */
514 #define VSPLUS 0x3 /* ${var+text} */
515 #define VSQUESTION 0x4 /* ${var?message} */
516 #define VSASSIGN 0x5 /* ${var=text} */
517 #define VSTRIMRIGHT 0x6 /* ${var%pattern} */
518 #define VSTRIMRIGHTMAX 0x7 /* ${var%%pattern} */
519 #define VSTRIMLEFT 0x8 /* ${var#pattern} */
520 #define VSTRIMLEFTMAX 0x9 /* ${var##pattern} */
521 #define VSLENGTH 0xa /* ${#var} */
523 /* values of checkkwd variable */
528 #define IBUFSIZ (BUFSIZ + 1)
531 * NEOF is returned by parsecmd when it encounters an end of file. It
532 * must be distinct from NULL, so we use the address of a variable that
533 * happens to be handy.
535 static int plinno = 1; /* input line number */
537 /* number of characters left in input buffer */
538 static int parsenleft; /* copy of parsefile->nleft */
539 static int parselleft; /* copy of parsefile->lleft */
541 /* next character in input buffer */
542 static char *parsenextc; /* copy of parsefile->nextc */
545 struct strpush *prev; /* preceding string on stack */
548 #ifdef CONFIG_ASH_ALIAS
549 struct alias *ap; /* if push was associated with an alias */
551 char *string; /* remember the string since it may change */
555 struct parsefile *prev; /* preceding file on stack */
556 int linno; /* current line */
557 int fd; /* file descriptor (or -1 if string) */
558 int nleft; /* number of chars left in this line */
559 int lleft; /* number of chars left in this buffer */
560 char *nextc; /* next char in buffer */
561 char *buf; /* input buffer */
562 struct strpush *strpush; /* for pushing strings at this level */
563 struct strpush basestrpush; /* so pushing one is fast */
566 static struct parsefile basepf; /* top level input file */
567 #define basebuf bb_common_bufsiz1 /* buffer for top level input file */
568 static struct parsefile *parsefile = &basepf; /* current input file */
571 static int tokpushback; /* last token pushed back */
572 #define NEOF ((union node *)&tokpushback)
573 static int parsebackquote; /* nonzero if we are inside backquotes */
574 static int doprompt; /* if set, prompt the user */
575 static int needprompt; /* true if interactive and at start of line */
576 static int lasttoken; /* last token read */
577 static char *wordtext; /* text of last word returned by readtoken */
579 static struct nodelist *backquotelist;
580 static union node *redirnode;
581 static struct heredoc *heredoc;
582 static int quoteflag; /* set if (part of) last token was quoted */
583 static int startlinno; /* line # where last token started */
585 static union node *parsecmd(int);
586 static void fixredir(union node *, const char *, int);
587 static const char *const *findkwd(const char *);
588 static char *endofname(const char *);
592 typedef void *pointer;
594 static char nullstr[1]; /* zero length string */
595 static const char spcstr[] = " ";
596 static const char snlfmt[] = "%s\n";
597 static const char dolatstr[] = { CTLVAR, VSNORMAL|VSQUOTE, '@', '=', '\0' };
598 static const char illnum[] = "Illegal number: %s";
599 static const char homestr[] = "HOME";
602 #define TRACE(param) trace param
603 #define TRACEV(param) tracev param
606 #define TRACEV(param)
609 #if !defined(__GNUC__) || (__GNUC__ == 2 && __GNUC_MINOR__ < 96)
610 #define __builtin_expect(x, expected_value) (x)
613 #define xlikely(x) __builtin_expect((x),1)
628 #define TENDBQUOTE 12
646 /* first char is indicating which tokens mark the end of a list */
647 static const char *const tokname_array[] = {
662 /* the following are keywords */
681 static const char *tokname(int tok)
687 sprintf(buf + (tok >= TSEMI), "%s%c",
688 tokname_array[tok] + 1, (tok >= TSEMI ? '"' : 0));
695 * Most machines require the value returned from malloc to be aligned
696 * in some way. The following macro will get this right on many machines.
699 #define SHELL_SIZE (sizeof(union {int i; char *cp; double d; }) - 1)
701 * It appears that grabstackstr() will barf with such alignments
702 * because stalloc() will return a string allocated in a new stackblock.
704 #define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE)
707 * This file was generated by the mksyntax program.
712 #define CWORD 0 /* character is nothing special */
713 #define CNL 1 /* newline character */
714 #define CBACK 2 /* a backslash character */
715 #define CSQUOTE 3 /* single quote */
716 #define CDQUOTE 4 /* double quote */
717 #define CENDQUOTE 5 /* a terminating quote */
718 #define CBQUOTE 6 /* backwards single quote */
719 #define CVAR 7 /* a dollar sign */
720 #define CENDVAR 8 /* a '}' character */
721 #define CLP 9 /* a left paren in arithmetic */
722 #define CRP 10 /* a right paren in arithmetic */
723 #define CENDFILE 11 /* end of file */
724 #define CCTL 12 /* like CWORD, except it must be escaped */
725 #define CSPCL 13 /* these terminate a word */
726 #define CIGN 14 /* character should be ignored */
728 #ifdef CONFIG_ASH_ALIAS
732 #define PEOA_OR_PEOF PEOA
736 #define PEOA_OR_PEOF PEOF
739 #define is_digit(c) ((unsigned)((c) - '0') <= 9)
740 #define is_name(c) ((c) == '_' || isalpha((unsigned char)(c)))
741 #define is_in_name(c) ((c) == '_' || isalnum((unsigned char)(c)))
744 * is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
745 * (assuming ascii char codes, as the original implementation did)
747 #define is_special(c) \
748 ( (((unsigned int)c) - 33 < 32) \
749 && ((0xc1ff920dUL >> (((unsigned int)c) - 33)) & 1))
751 #define digit_val(c) ((c) - '0')
754 * This file was generated by the mksyntax program.
757 #ifdef CONFIG_ASH_OPTIMIZE_FOR_SIZE
758 #define USE_SIT_FUNCTION
761 /* number syntax index */
762 #define BASESYNTAX 0 /* not in quotes */
763 #define DQSYNTAX 1 /* in double quotes */
764 #define SQSYNTAX 2 /* in single quotes */
765 #define ARISYNTAX 3 /* in arithmetic */
767 #ifdef CONFIG_ASH_MATH_SUPPORT
768 static const char S_I_T[][4] = {
769 #ifdef CONFIG_ASH_ALIAS
770 {CSPCL, CIGN, CIGN, CIGN}, /* 0, PEOA */
772 {CSPCL, CWORD, CWORD, CWORD}, /* 1, ' ' */
773 {CNL, CNL, CNL, CNL}, /* 2, \n */
774 {CWORD, CCTL, CCTL, CWORD}, /* 3, !*-/:=?[]~ */
775 {CDQUOTE, CENDQUOTE, CWORD, CWORD}, /* 4, '"' */
776 {CVAR, CVAR, CWORD, CVAR}, /* 5, $ */
777 {CSQUOTE, CWORD, CENDQUOTE, CWORD}, /* 6, "'" */
778 {CSPCL, CWORD, CWORD, CLP}, /* 7, ( */
779 {CSPCL, CWORD, CWORD, CRP}, /* 8, ) */
780 {CBACK, CBACK, CCTL, CBACK}, /* 9, \ */
781 {CBQUOTE, CBQUOTE, CWORD, CBQUOTE}, /* 10, ` */
782 {CENDVAR, CENDVAR, CWORD, CENDVAR}, /* 11, } */
783 #ifndef USE_SIT_FUNCTION
784 {CENDFILE, CENDFILE, CENDFILE, CENDFILE}, /* 12, PEOF */
785 {CWORD, CWORD, CWORD, CWORD}, /* 13, 0-9A-Za-z */
786 {CCTL, CCTL, CCTL, CCTL} /* 14, CTLESC ... */
790 static const char S_I_T[][3] = {
791 #ifdef CONFIG_ASH_ALIAS
792 {CSPCL, CIGN, CIGN}, /* 0, PEOA */
794 {CSPCL, CWORD, CWORD}, /* 1, ' ' */
795 {CNL, CNL, CNL}, /* 2, \n */
796 {CWORD, CCTL, CCTL}, /* 3, !*-/:=?[]~ */
797 {CDQUOTE, CENDQUOTE, CWORD}, /* 4, '"' */
798 {CVAR, CVAR, CWORD}, /* 5, $ */
799 {CSQUOTE, CWORD, CENDQUOTE}, /* 6, "'" */
800 {CSPCL, CWORD, CWORD}, /* 7, ( */
801 {CSPCL, CWORD, CWORD}, /* 8, ) */
802 {CBACK, CBACK, CCTL}, /* 9, \ */
803 {CBQUOTE, CBQUOTE, CWORD}, /* 10, ` */
804 {CENDVAR, CENDVAR, CWORD}, /* 11, } */
805 #ifndef USE_SIT_FUNCTION
806 {CENDFILE, CENDFILE, CENDFILE}, /* 12, PEOF */
807 {CWORD, CWORD, CWORD}, /* 13, 0-9A-Za-z */
808 {CCTL, CCTL, CCTL} /* 14, CTLESC ... */
811 #endif /* CONFIG_ASH_MATH_SUPPORT */
813 #ifdef USE_SIT_FUNCTION
815 #define U_C(c) ((unsigned char)(c))
817 static int SIT(int c, int syntax)
819 static const char spec_symbls[] = "\t\n !\"$&'()*-/:;<=>?[\\]`|}~";
820 #ifdef CONFIG_ASH_ALIAS
821 static const char syntax_index_table[] = {
822 1, 2, 1, 3, 4, 5, 1, 6, /* "\t\n !\"$&'" */
823 7, 8, 3, 3, 3, 3, 1, 1, /* "()*-/:;<" */
824 3, 1, 3, 3, 9, 3, 10, 1, /* "=>?[\\]`|" */
828 static const char syntax_index_table[] = {
829 0, 1, 0, 2, 3, 4, 0, 5, /* "\t\n !\"$&'" */
830 6, 7, 2, 2, 2, 2, 0, 0, /* "()*-/:;<" */
831 2, 0, 2, 2, 8, 2, 9, 0, /* "=>?[\\]`|" */
838 if (c == PEOF) /* 2^8+2 */
840 #ifdef CONFIG_ASH_ALIAS
841 if (c == PEOA) /* 2^8+1 */
845 if (U_C(c) >= U_C(CTLESC) && U_C(c) <= U_C(CTLQUOTEMARK))
848 s = strchr(spec_symbls, c);
849 if (s == 0 || *s == 0)
851 indx = syntax_index_table[(s - spec_symbls)];
853 return S_I_T[indx][syntax];
856 #else /* USE_SIT_FUNCTION */
858 #define SIT(c, syntax) S_I_T[(int)syntax_index_table[((int)c)+SYNBASE]][syntax]
860 #ifdef CONFIG_ASH_ALIAS
861 #define CSPCL_CIGN_CIGN_CIGN 0
862 #define CSPCL_CWORD_CWORD_CWORD 1
863 #define CNL_CNL_CNL_CNL 2
864 #define CWORD_CCTL_CCTL_CWORD 3
865 #define CDQUOTE_CENDQUOTE_CWORD_CWORD 4
866 #define CVAR_CVAR_CWORD_CVAR 5
867 #define CSQUOTE_CWORD_CENDQUOTE_CWORD 6
868 #define CSPCL_CWORD_CWORD_CLP 7
869 #define CSPCL_CWORD_CWORD_CRP 8
870 #define CBACK_CBACK_CCTL_CBACK 9
871 #define CBQUOTE_CBQUOTE_CWORD_CBQUOTE 10
872 #define CENDVAR_CENDVAR_CWORD_CENDVAR 11
873 #define CENDFILE_CENDFILE_CENDFILE_CENDFILE 12
874 #define CWORD_CWORD_CWORD_CWORD 13
875 #define CCTL_CCTL_CCTL_CCTL 14
877 #define CSPCL_CWORD_CWORD_CWORD 0
878 #define CNL_CNL_CNL_CNL 1
879 #define CWORD_CCTL_CCTL_CWORD 2
880 #define CDQUOTE_CENDQUOTE_CWORD_CWORD 3
881 #define CVAR_CVAR_CWORD_CVAR 4
882 #define CSQUOTE_CWORD_CENDQUOTE_CWORD 5
883 #define CSPCL_CWORD_CWORD_CLP 6
884 #define CSPCL_CWORD_CWORD_CRP 7
885 #define CBACK_CBACK_CCTL_CBACK 8
886 #define CBQUOTE_CBQUOTE_CWORD_CBQUOTE 9
887 #define CENDVAR_CENDVAR_CWORD_CENDVAR 10
888 #define CENDFILE_CENDFILE_CENDFILE_CENDFILE 11
889 #define CWORD_CWORD_CWORD_CWORD 12
890 #define CCTL_CCTL_CCTL_CCTL 13
893 static const char syntax_index_table[258] = {
894 /* BASESYNTAX_DQSYNTAX_SQSYNTAX_ARISYNTAX */
895 /* 0 PEOF */ CENDFILE_CENDFILE_CENDFILE_CENDFILE,
896 #ifdef CONFIG_ASH_ALIAS
897 /* 1 PEOA */ CSPCL_CIGN_CIGN_CIGN,
899 /* 2 -128 0x80 */ CWORD_CWORD_CWORD_CWORD,
900 /* 3 -127 CTLESC */ CCTL_CCTL_CCTL_CCTL,
901 /* 4 -126 CTLVAR */ CCTL_CCTL_CCTL_CCTL,
902 /* 5 -125 CTLENDVAR */ CCTL_CCTL_CCTL_CCTL,
903 /* 6 -124 CTLBACKQ */ CCTL_CCTL_CCTL_CCTL,
904 /* 7 -123 CTLQUOTE */ CCTL_CCTL_CCTL_CCTL,
905 /* 8 -122 CTLARI */ CCTL_CCTL_CCTL_CCTL,
906 /* 9 -121 CTLENDARI */ CCTL_CCTL_CCTL_CCTL,
907 /* 10 -120 CTLQUOTEMARK */ CCTL_CCTL_CCTL_CCTL,
908 /* 11 -119 */ CWORD_CWORD_CWORD_CWORD,
909 /* 12 -118 */ CWORD_CWORD_CWORD_CWORD,
910 /* 13 -117 */ CWORD_CWORD_CWORD_CWORD,
911 /* 14 -116 */ CWORD_CWORD_CWORD_CWORD,
912 /* 15 -115 */ CWORD_CWORD_CWORD_CWORD,
913 /* 16 -114 */ CWORD_CWORD_CWORD_CWORD,
914 /* 17 -113 */ CWORD_CWORD_CWORD_CWORD,
915 /* 18 -112 */ CWORD_CWORD_CWORD_CWORD,
916 /* 19 -111 */ CWORD_CWORD_CWORD_CWORD,
917 /* 20 -110 */ CWORD_CWORD_CWORD_CWORD,
918 /* 21 -109 */ CWORD_CWORD_CWORD_CWORD,
919 /* 22 -108 */ CWORD_CWORD_CWORD_CWORD,
920 /* 23 -107 */ CWORD_CWORD_CWORD_CWORD,
921 /* 24 -106 */ CWORD_CWORD_CWORD_CWORD,
922 /* 25 -105 */ CWORD_CWORD_CWORD_CWORD,
923 /* 26 -104 */ CWORD_CWORD_CWORD_CWORD,
924 /* 27 -103 */ CWORD_CWORD_CWORD_CWORD,
925 /* 28 -102 */ CWORD_CWORD_CWORD_CWORD,
926 /* 29 -101 */ CWORD_CWORD_CWORD_CWORD,
927 /* 30 -100 */ CWORD_CWORD_CWORD_CWORD,
928 /* 31 -99 */ CWORD_CWORD_CWORD_CWORD,
929 /* 32 -98 */ CWORD_CWORD_CWORD_CWORD,
930 /* 33 -97 */ CWORD_CWORD_CWORD_CWORD,
931 /* 34 -96 */ CWORD_CWORD_CWORD_CWORD,
932 /* 35 -95 */ CWORD_CWORD_CWORD_CWORD,
933 /* 36 -94 */ CWORD_CWORD_CWORD_CWORD,
934 /* 37 -93 */ CWORD_CWORD_CWORD_CWORD,
935 /* 38 -92 */ CWORD_CWORD_CWORD_CWORD,
936 /* 39 -91 */ CWORD_CWORD_CWORD_CWORD,
937 /* 40 -90 */ CWORD_CWORD_CWORD_CWORD,
938 /* 41 -89 */ CWORD_CWORD_CWORD_CWORD,
939 /* 42 -88 */ CWORD_CWORD_CWORD_CWORD,
940 /* 43 -87 */ CWORD_CWORD_CWORD_CWORD,
941 /* 44 -86 */ CWORD_CWORD_CWORD_CWORD,
942 /* 45 -85 */ CWORD_CWORD_CWORD_CWORD,
943 /* 46 -84 */ CWORD_CWORD_CWORD_CWORD,
944 /* 47 -83 */ CWORD_CWORD_CWORD_CWORD,
945 /* 48 -82 */ CWORD_CWORD_CWORD_CWORD,
946 /* 49 -81 */ CWORD_CWORD_CWORD_CWORD,
947 /* 50 -80 */ CWORD_CWORD_CWORD_CWORD,
948 /* 51 -79 */ CWORD_CWORD_CWORD_CWORD,
949 /* 52 -78 */ CWORD_CWORD_CWORD_CWORD,
950 /* 53 -77 */ CWORD_CWORD_CWORD_CWORD,
951 /* 54 -76 */ CWORD_CWORD_CWORD_CWORD,
952 /* 55 -75 */ CWORD_CWORD_CWORD_CWORD,
953 /* 56 -74 */ CWORD_CWORD_CWORD_CWORD,
954 /* 57 -73 */ CWORD_CWORD_CWORD_CWORD,
955 /* 58 -72 */ CWORD_CWORD_CWORD_CWORD,
956 /* 59 -71 */ CWORD_CWORD_CWORD_CWORD,
957 /* 60 -70 */ CWORD_CWORD_CWORD_CWORD,
958 /* 61 -69 */ CWORD_CWORD_CWORD_CWORD,
959 /* 62 -68 */ CWORD_CWORD_CWORD_CWORD,
960 /* 63 -67 */ CWORD_CWORD_CWORD_CWORD,
961 /* 64 -66 */ CWORD_CWORD_CWORD_CWORD,
962 /* 65 -65 */ CWORD_CWORD_CWORD_CWORD,
963 /* 66 -64 */ CWORD_CWORD_CWORD_CWORD,
964 /* 67 -63 */ CWORD_CWORD_CWORD_CWORD,
965 /* 68 -62 */ CWORD_CWORD_CWORD_CWORD,
966 /* 69 -61 */ CWORD_CWORD_CWORD_CWORD,
967 /* 70 -60 */ CWORD_CWORD_CWORD_CWORD,
968 /* 71 -59 */ CWORD_CWORD_CWORD_CWORD,
969 /* 72 -58 */ CWORD_CWORD_CWORD_CWORD,
970 /* 73 -57 */ CWORD_CWORD_CWORD_CWORD,
971 /* 74 -56 */ CWORD_CWORD_CWORD_CWORD,
972 /* 75 -55 */ CWORD_CWORD_CWORD_CWORD,
973 /* 76 -54 */ CWORD_CWORD_CWORD_CWORD,
974 /* 77 -53 */ CWORD_CWORD_CWORD_CWORD,
975 /* 78 -52 */ CWORD_CWORD_CWORD_CWORD,
976 /* 79 -51 */ CWORD_CWORD_CWORD_CWORD,
977 /* 80 -50 */ CWORD_CWORD_CWORD_CWORD,
978 /* 81 -49 */ CWORD_CWORD_CWORD_CWORD,
979 /* 82 -48 */ CWORD_CWORD_CWORD_CWORD,
980 /* 83 -47 */ CWORD_CWORD_CWORD_CWORD,
981 /* 84 -46 */ CWORD_CWORD_CWORD_CWORD,
982 /* 85 -45 */ CWORD_CWORD_CWORD_CWORD,
983 /* 86 -44 */ CWORD_CWORD_CWORD_CWORD,
984 /* 87 -43 */ CWORD_CWORD_CWORD_CWORD,
985 /* 88 -42 */ CWORD_CWORD_CWORD_CWORD,
986 /* 89 -41 */ CWORD_CWORD_CWORD_CWORD,
987 /* 90 -40 */ CWORD_CWORD_CWORD_CWORD,
988 /* 91 -39 */ CWORD_CWORD_CWORD_CWORD,
989 /* 92 -38 */ CWORD_CWORD_CWORD_CWORD,
990 /* 93 -37 */ CWORD_CWORD_CWORD_CWORD,
991 /* 94 -36 */ CWORD_CWORD_CWORD_CWORD,
992 /* 95 -35 */ CWORD_CWORD_CWORD_CWORD,
993 /* 96 -34 */ CWORD_CWORD_CWORD_CWORD,
994 /* 97 -33 */ CWORD_CWORD_CWORD_CWORD,
995 /* 98 -32 */ CWORD_CWORD_CWORD_CWORD,
996 /* 99 -31 */ CWORD_CWORD_CWORD_CWORD,
997 /* 100 -30 */ CWORD_CWORD_CWORD_CWORD,
998 /* 101 -29 */ CWORD_CWORD_CWORD_CWORD,
999 /* 102 -28 */ CWORD_CWORD_CWORD_CWORD,
1000 /* 103 -27 */ CWORD_CWORD_CWORD_CWORD,
1001 /* 104 -26 */ CWORD_CWORD_CWORD_CWORD,
1002 /* 105 -25 */ CWORD_CWORD_CWORD_CWORD,
1003 /* 106 -24 */ CWORD_CWORD_CWORD_CWORD,
1004 /* 107 -23 */ CWORD_CWORD_CWORD_CWORD,
1005 /* 108 -22 */ CWORD_CWORD_CWORD_CWORD,
1006 /* 109 -21 */ CWORD_CWORD_CWORD_CWORD,
1007 /* 110 -20 */ CWORD_CWORD_CWORD_CWORD,
1008 /* 111 -19 */ CWORD_CWORD_CWORD_CWORD,
1009 /* 112 -18 */ CWORD_CWORD_CWORD_CWORD,
1010 /* 113 -17 */ CWORD_CWORD_CWORD_CWORD,
1011 /* 114 -16 */ CWORD_CWORD_CWORD_CWORD,
1012 /* 115 -15 */ CWORD_CWORD_CWORD_CWORD,
1013 /* 116 -14 */ CWORD_CWORD_CWORD_CWORD,
1014 /* 117 -13 */ CWORD_CWORD_CWORD_CWORD,
1015 /* 118 -12 */ CWORD_CWORD_CWORD_CWORD,
1016 /* 119 -11 */ CWORD_CWORD_CWORD_CWORD,
1017 /* 120 -10 */ CWORD_CWORD_CWORD_CWORD,
1018 /* 121 -9 */ CWORD_CWORD_CWORD_CWORD,
1019 /* 122 -8 */ CWORD_CWORD_CWORD_CWORD,
1020 /* 123 -7 */ CWORD_CWORD_CWORD_CWORD,
1021 /* 124 -6 */ CWORD_CWORD_CWORD_CWORD,
1022 /* 125 -5 */ CWORD_CWORD_CWORD_CWORD,
1023 /* 126 -4 */ CWORD_CWORD_CWORD_CWORD,
1024 /* 127 -3 */ CWORD_CWORD_CWORD_CWORD,
1025 /* 128 -2 */ CWORD_CWORD_CWORD_CWORD,
1026 /* 129 -1 */ CWORD_CWORD_CWORD_CWORD,
1027 /* 130 0 */ CWORD_CWORD_CWORD_CWORD,
1028 /* 131 1 */ CWORD_CWORD_CWORD_CWORD,
1029 /* 132 2 */ CWORD_CWORD_CWORD_CWORD,
1030 /* 133 3 */ CWORD_CWORD_CWORD_CWORD,
1031 /* 134 4 */ CWORD_CWORD_CWORD_CWORD,
1032 /* 135 5 */ CWORD_CWORD_CWORD_CWORD,
1033 /* 136 6 */ CWORD_CWORD_CWORD_CWORD,
1034 /* 137 7 */ CWORD_CWORD_CWORD_CWORD,
1035 /* 138 8 */ CWORD_CWORD_CWORD_CWORD,
1036 /* 139 9 "\t" */ CSPCL_CWORD_CWORD_CWORD,
1037 /* 140 10 "\n" */ CNL_CNL_CNL_CNL,
1038 /* 141 11 */ CWORD_CWORD_CWORD_CWORD,
1039 /* 142 12 */ CWORD_CWORD_CWORD_CWORD,
1040 /* 143 13 */ CWORD_CWORD_CWORD_CWORD,
1041 /* 144 14 */ CWORD_CWORD_CWORD_CWORD,
1042 /* 145 15 */ CWORD_CWORD_CWORD_CWORD,
1043 /* 146 16 */ CWORD_CWORD_CWORD_CWORD,
1044 /* 147 17 */ CWORD_CWORD_CWORD_CWORD,
1045 /* 148 18 */ CWORD_CWORD_CWORD_CWORD,
1046 /* 149 19 */ CWORD_CWORD_CWORD_CWORD,
1047 /* 150 20 */ CWORD_CWORD_CWORD_CWORD,
1048 /* 151 21 */ CWORD_CWORD_CWORD_CWORD,
1049 /* 152 22 */ CWORD_CWORD_CWORD_CWORD,
1050 /* 153 23 */ CWORD_CWORD_CWORD_CWORD,
1051 /* 154 24 */ CWORD_CWORD_CWORD_CWORD,
1052 /* 155 25 */ CWORD_CWORD_CWORD_CWORD,
1053 /* 156 26 */ CWORD_CWORD_CWORD_CWORD,
1054 /* 157 27 */ CWORD_CWORD_CWORD_CWORD,
1055 /* 158 28 */ CWORD_CWORD_CWORD_CWORD,
1056 /* 159 29 */ CWORD_CWORD_CWORD_CWORD,
1057 /* 160 30 */ CWORD_CWORD_CWORD_CWORD,
1058 /* 161 31 */ CWORD_CWORD_CWORD_CWORD,
1059 /* 162 32 " " */ CSPCL_CWORD_CWORD_CWORD,
1060 /* 163 33 "!" */ CWORD_CCTL_CCTL_CWORD,
1061 /* 164 34 """ */ CDQUOTE_CENDQUOTE_CWORD_CWORD,
1062 /* 165 35 "#" */ CWORD_CWORD_CWORD_CWORD,
1063 /* 166 36 "$" */ CVAR_CVAR_CWORD_CVAR,
1064 /* 167 37 "%" */ CWORD_CWORD_CWORD_CWORD,
1065 /* 168 38 "&" */ CSPCL_CWORD_CWORD_CWORD,
1066 /* 169 39 "'" */ CSQUOTE_CWORD_CENDQUOTE_CWORD,
1067 /* 170 40 "(" */ CSPCL_CWORD_CWORD_CLP,
1068 /* 171 41 ")" */ CSPCL_CWORD_CWORD_CRP,
1069 /* 172 42 "*" */ CWORD_CCTL_CCTL_CWORD,
1070 /* 173 43 "+" */ CWORD_CWORD_CWORD_CWORD,
1071 /* 174 44 "," */ CWORD_CWORD_CWORD_CWORD,
1072 /* 175 45 "-" */ CWORD_CCTL_CCTL_CWORD,
1073 /* 176 46 "." */ CWORD_CWORD_CWORD_CWORD,
1074 /* 177 47 "/" */ CWORD_CCTL_CCTL_CWORD,
1075 /* 178 48 "0" */ CWORD_CWORD_CWORD_CWORD,
1076 /* 179 49 "1" */ CWORD_CWORD_CWORD_CWORD,
1077 /* 180 50 "2" */ CWORD_CWORD_CWORD_CWORD,
1078 /* 181 51 "3" */ CWORD_CWORD_CWORD_CWORD,
1079 /* 182 52 "4" */ CWORD_CWORD_CWORD_CWORD,
1080 /* 183 53 "5" */ CWORD_CWORD_CWORD_CWORD,
1081 /* 184 54 "6" */ CWORD_CWORD_CWORD_CWORD,
1082 /* 185 55 "7" */ CWORD_CWORD_CWORD_CWORD,
1083 /* 186 56 "8" */ CWORD_CWORD_CWORD_CWORD,
1084 /* 187 57 "9" */ CWORD_CWORD_CWORD_CWORD,
1085 /* 188 58 ":" */ CWORD_CCTL_CCTL_CWORD,
1086 /* 189 59 ";" */ CSPCL_CWORD_CWORD_CWORD,
1087 /* 190 60 "<" */ CSPCL_CWORD_CWORD_CWORD,
1088 /* 191 61 "=" */ CWORD_CCTL_CCTL_CWORD,
1089 /* 192 62 ">" */ CSPCL_CWORD_CWORD_CWORD,
1090 /* 193 63 "?" */ CWORD_CCTL_CCTL_CWORD,
1091 /* 194 64 "@" */ CWORD_CWORD_CWORD_CWORD,
1092 /* 195 65 "A" */ CWORD_CWORD_CWORD_CWORD,
1093 /* 196 66 "B" */ CWORD_CWORD_CWORD_CWORD,
1094 /* 197 67 "C" */ CWORD_CWORD_CWORD_CWORD,
1095 /* 198 68 "D" */ CWORD_CWORD_CWORD_CWORD,
1096 /* 199 69 "E" */ CWORD_CWORD_CWORD_CWORD,
1097 /* 200 70 "F" */ CWORD_CWORD_CWORD_CWORD,
1098 /* 201 71 "G" */ CWORD_CWORD_CWORD_CWORD,
1099 /* 202 72 "H" */ CWORD_CWORD_CWORD_CWORD,
1100 /* 203 73 "I" */ CWORD_CWORD_CWORD_CWORD,
1101 /* 204 74 "J" */ CWORD_CWORD_CWORD_CWORD,
1102 /* 205 75 "K" */ CWORD_CWORD_CWORD_CWORD,
1103 /* 206 76 "L" */ CWORD_CWORD_CWORD_CWORD,
1104 /* 207 77 "M" */ CWORD_CWORD_CWORD_CWORD,
1105 /* 208 78 "N" */ CWORD_CWORD_CWORD_CWORD,
1106 /* 209 79 "O" */ CWORD_CWORD_CWORD_CWORD,
1107 /* 210 80 "P" */ CWORD_CWORD_CWORD_CWORD,
1108 /* 211 81 "Q" */ CWORD_CWORD_CWORD_CWORD,
1109 /* 212 82 "R" */ CWORD_CWORD_CWORD_CWORD,
1110 /* 213 83 "S" */ CWORD_CWORD_CWORD_CWORD,
1111 /* 214 84 "T" */ CWORD_CWORD_CWORD_CWORD,
1112 /* 215 85 "U" */ CWORD_CWORD_CWORD_CWORD,
1113 /* 216 86 "V" */ CWORD_CWORD_CWORD_CWORD,
1114 /* 217 87 "W" */ CWORD_CWORD_CWORD_CWORD,
1115 /* 218 88 "X" */ CWORD_CWORD_CWORD_CWORD,
1116 /* 219 89 "Y" */ CWORD_CWORD_CWORD_CWORD,
1117 /* 220 90 "Z" */ CWORD_CWORD_CWORD_CWORD,
1118 /* 221 91 "[" */ CWORD_CCTL_CCTL_CWORD,
1119 /* 222 92 "\" */ CBACK_CBACK_CCTL_CBACK,
1120 /* 223 93 "]" */ CWORD_CCTL_CCTL_CWORD,
1121 /* 224 94 "^" */ CWORD_CWORD_CWORD_CWORD,
1122 /* 225 95 "_" */ CWORD_CWORD_CWORD_CWORD,
1123 /* 226 96 "`" */ CBQUOTE_CBQUOTE_CWORD_CBQUOTE,
1124 /* 227 97 "a" */ CWORD_CWORD_CWORD_CWORD,
1125 /* 228 98 "b" */ CWORD_CWORD_CWORD_CWORD,
1126 /* 229 99 "c" */ CWORD_CWORD_CWORD_CWORD,
1127 /* 230 100 "d" */ CWORD_CWORD_CWORD_CWORD,
1128 /* 231 101 "e" */ CWORD_CWORD_CWORD_CWORD,
1129 /* 232 102 "f" */ CWORD_CWORD_CWORD_CWORD,
1130 /* 233 103 "g" */ CWORD_CWORD_CWORD_CWORD,
1131 /* 234 104 "h" */ CWORD_CWORD_CWORD_CWORD,
1132 /* 235 105 "i" */ CWORD_CWORD_CWORD_CWORD,
1133 /* 236 106 "j" */ CWORD_CWORD_CWORD_CWORD,
1134 /* 237 107 "k" */ CWORD_CWORD_CWORD_CWORD,
1135 /* 238 108 "l" */ CWORD_CWORD_CWORD_CWORD,
1136 /* 239 109 "m" */ CWORD_CWORD_CWORD_CWORD,
1137 /* 240 110 "n" */ CWORD_CWORD_CWORD_CWORD,
1138 /* 241 111 "o" */ CWORD_CWORD_CWORD_CWORD,
1139 /* 242 112 "p" */ CWORD_CWORD_CWORD_CWORD,
1140 /* 243 113 "q" */ CWORD_CWORD_CWORD_CWORD,
1141 /* 244 114 "r" */ CWORD_CWORD_CWORD_CWORD,
1142 /* 245 115 "s" */ CWORD_CWORD_CWORD_CWORD,
1143 /* 246 116 "t" */ CWORD_CWORD_CWORD_CWORD,
1144 /* 247 117 "u" */ CWORD_CWORD_CWORD_CWORD,
1145 /* 248 118 "v" */ CWORD_CWORD_CWORD_CWORD,
1146 /* 249 119 "w" */ CWORD_CWORD_CWORD_CWORD,
1147 /* 250 120 "x" */ CWORD_CWORD_CWORD_CWORD,
1148 /* 251 121 "y" */ CWORD_CWORD_CWORD_CWORD,
1149 /* 252 122 "z" */ CWORD_CWORD_CWORD_CWORD,
1150 /* 253 123 "{" */ CWORD_CWORD_CWORD_CWORD,
1151 /* 254 124 "|" */ CSPCL_CWORD_CWORD_CWORD,
1152 /* 255 125 "}" */ CENDVAR_CENDVAR_CWORD_CENDVAR,
1153 /* 256 126 "~" */ CWORD_CCTL_CCTL_CWORD,
1154 /* 257 127 */ CWORD_CWORD_CWORD_CWORD,
1157 #endif /* USE_SIT_FUNCTION */
1164 static int funcblocksize; /* size of structures in function */
1165 static int funcstringsize; /* size of strings in node */
1166 static pointer funcblock; /* block to allocate function from */
1167 static char *funcstring; /* block to allocate strings from */
1169 static const short nodesize[26] = {
1170 SHELL_ALIGN(sizeof (struct ncmd)),
1171 SHELL_ALIGN(sizeof (struct npipe)),
1172 SHELL_ALIGN(sizeof (struct nredir)),
1173 SHELL_ALIGN(sizeof (struct nredir)),
1174 SHELL_ALIGN(sizeof (struct nredir)),
1175 SHELL_ALIGN(sizeof (struct nbinary)),
1176 SHELL_ALIGN(sizeof (struct nbinary)),
1177 SHELL_ALIGN(sizeof (struct nbinary)),
1178 SHELL_ALIGN(sizeof (struct nif)),
1179 SHELL_ALIGN(sizeof (struct nbinary)),
1180 SHELL_ALIGN(sizeof (struct nbinary)),
1181 SHELL_ALIGN(sizeof (struct nfor)),
1182 SHELL_ALIGN(sizeof (struct ncase)),
1183 SHELL_ALIGN(sizeof (struct nclist)),
1184 SHELL_ALIGN(sizeof (struct narg)),
1185 SHELL_ALIGN(sizeof (struct narg)),
1186 SHELL_ALIGN(sizeof (struct nfile)),
1187 SHELL_ALIGN(sizeof (struct nfile)),
1188 SHELL_ALIGN(sizeof (struct nfile)),
1189 SHELL_ALIGN(sizeof (struct nfile)),
1190 SHELL_ALIGN(sizeof (struct nfile)),
1191 SHELL_ALIGN(sizeof (struct ndup)),
1192 SHELL_ALIGN(sizeof (struct ndup)),
1193 SHELL_ALIGN(sizeof (struct nhere)),
1194 SHELL_ALIGN(sizeof (struct nhere)),
1195 SHELL_ALIGN(sizeof (struct nnot)),
1199 static void calcsize(union node *);
1200 static void sizenodelist(struct nodelist *);
1201 static union node *copynode(union node *);
1202 static struct nodelist *copynodelist(struct nodelist *);
1203 static char *nodesavestr(char *);
1206 static int evalstring(char *, int mask);
1207 union node; /* BLETCH for ansi C */
1208 static void evaltree(union node *, int);
1209 static void evalbackcmd(union node *, struct backcmd *);
1211 static int evalskip; /* set if we are skipping commands */
1212 static int skipcount; /* number of levels to skip */
1213 static int funcnest; /* depth of function calls */
1215 /* reasons for skipping commands (see comment on breakcmd routine) */
1216 #define SKIPBREAK (1 << 0)
1217 #define SKIPCONT (1 << 1)
1218 #define SKIPFUNC (1 << 2)
1219 #define SKIPFILE (1 << 3)
1220 #define SKIPEVAL (1 << 4)
1223 * This file was generated by the mkbuiltins program.
1227 static int bgcmd(int, char **);
1229 static int breakcmd(int, char **);
1230 static int cdcmd(int, char **);
1231 #ifdef CONFIG_ASH_CMDCMD
1232 static int commandcmd(int, char **);
1234 static int dotcmd(int, char **);
1235 static int evalcmd(int, char **);
1236 #ifdef CONFIG_ASH_BUILTIN_ECHO
1237 static int echocmd(int, char **);
1239 static int execcmd(int, char **);
1240 static int exitcmd(int, char **);
1241 static int exportcmd(int, char **);
1242 static int falsecmd(int, char **);
1244 static int fgcmd(int, char **);
1246 #ifdef CONFIG_ASH_GETOPTS
1247 static int getoptscmd(int, char **);
1249 static int hashcmd(int, char **);
1250 #ifndef CONFIG_FEATURE_SH_EXTRA_QUIET
1251 static int helpcmd(int argc, char **argv);
1254 static int jobscmd(int, char **);
1256 #ifdef CONFIG_ASH_MATH_SUPPORT
1257 static int letcmd(int, char **);
1259 static int localcmd(int, char **);
1260 static int pwdcmd(int, char **);
1261 static int readcmd(int, char **);
1262 static int returncmd(int, char **);
1263 static int setcmd(int, char **);
1264 static int shiftcmd(int, char **);
1265 static int timescmd(int, char **);
1266 static int trapcmd(int, char **);
1267 static int truecmd(int, char **);
1268 static int typecmd(int, char **);
1269 static int umaskcmd(int, char **);
1270 static int unsetcmd(int, char **);
1271 static int waitcmd(int, char **);
1272 static int ulimitcmd(int, char **);
1274 static int killcmd(int, char **);
1279 #ifdef CONFIG_ASH_MAIL
1280 static void chkmail(void);
1281 static void changemail(const char *);
1286 /* values of cmdtype */
1287 #define CMDUNKNOWN -1 /* no entry in table for command */
1288 #define CMDNORMAL 0 /* command is an executable program */
1289 #define CMDFUNCTION 1 /* command is a shell function */
1290 #define CMDBUILTIN 2 /* command is a shell builtin */
1294 int (*builtin)(int, char **);
1295 /* unsigned flags; */
1299 #define COMMANDCMD (builtincmd + 5 + \
1300 ENABLE_ASH_ALIAS + ENABLE_ASH_JOB_CONTROL)
1301 #define EXECCMD (builtincmd + 7 + \
1302 ENABLE_ASH_CMDCMD + ENABLE_ASH_ALIAS + \
1303 ENABLE_ASH_BUILTIN_ECHO + ENABLE_ASH_JOB_CONTROL)
1305 #define BUILTIN_NOSPEC "0"
1306 #define BUILTIN_SPECIAL "1"
1307 #define BUILTIN_REGULAR "2"
1308 #define BUILTIN_SPEC_REG "3"
1309 #define BUILTIN_ASSIGN "4"
1310 #define BUILTIN_SPEC_ASSG "5"
1311 #define BUILTIN_REG_ASSG "6"
1312 #define BUILTIN_SPEC_REG_ASSG "7"
1314 #define IS_BUILTIN_SPECIAL(builtincmd) ((builtincmd)->name[0] & 1)
1315 #define IS_BUILTIN_REGULAR(builtincmd) ((builtincmd)->name[0] & 2)
1316 #define IS_BUILTIN_ASSIGN(builtincmd) ((builtincmd)->name[0] & 4)
1318 static const struct builtincmd builtincmd[] = {
1319 { BUILTIN_SPEC_REG ".", dotcmd },
1320 { BUILTIN_SPEC_REG ":", truecmd },
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 #ifndef CONFIG_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 "times", timescmd },
1367 { BUILTIN_SPEC_REG "trap", trapcmd },
1368 { BUILTIN_REGULAR "true", truecmd },
1369 { BUILTIN_NOSPEC "type", typecmd },
1370 { BUILTIN_NOSPEC "ulimit", ulimitcmd },
1371 { BUILTIN_REGULAR "umask", umaskcmd },
1372 #ifdef CONFIG_ASH_ALIAS
1373 { BUILTIN_REGULAR "unalias", unaliascmd },
1375 { BUILTIN_SPEC_REG "unset", unsetcmd },
1376 { BUILTIN_REGULAR "wait", waitcmd },
1379 #define NUMBUILTINS (sizeof (builtincmd) / sizeof (struct builtincmd) )
1387 const struct builtincmd *cmd;
1388 struct funcnode *func;
1393 /* action to find_command() */
1394 #define DO_ERR 0x01 /* prints errors */
1395 #define DO_ABS 0x02 /* checks absolute paths */
1396 #define DO_NOFUNC 0x04 /* don't return shell functions, for command */
1397 #define DO_ALTPATH 0x08 /* using alternate path */
1398 #define DO_ALTBLTIN 0x20 /* %builtin in alt. path */
1400 static const char *pathopt; /* set by padvance */
1402 static void shellexec(char **, const char *, int)
1403 __attribute__((__noreturn__));
1404 static char *padvance(const char **, const char *);
1405 static void find_command(char *, struct cmdentry *, int, const char *);
1406 static struct builtincmd *find_builtin(const char *);
1407 static void hashcd(void);
1408 static void changepath(const char *);
1409 static void defun(char *, union node *);
1410 static void unsetfunc(const char *);
1412 #ifdef CONFIG_ASH_MATH_SUPPORT_64
1413 typedef int64_t arith_t;
1415 typedef long arith_t;
1418 #ifdef CONFIG_ASH_MATH_SUPPORT
1419 static arith_t dash_arith(const char *);
1420 static arith_t arith(const char *expr, int *perrcode);
1423 #ifdef CONFIG_ASH_RANDOM_SUPPORT
1424 static unsigned long rseed;
1425 static void change_random(const char *);
1426 # ifndef DYNAMIC_VAR
1427 # define DYNAMIC_VAR
1433 static void reset(void);
1442 #define VEXPORT 0x01 /* variable is exported */
1443 #define VREADONLY 0x02 /* variable cannot be modified */
1444 #define VSTRFIXED 0x04 /* variable struct is statically allocated */
1445 #define VTEXTFIXED 0x08 /* text is statically allocated */
1446 #define VSTACK 0x10 /* text is allocated on the stack */
1447 #define VUNSET 0x20 /* the variable is not set */
1448 #define VNOFUNC 0x40 /* don't call the callback function */
1449 #define VNOSET 0x80 /* do not set variable - just readonly test */
1450 #define VNOSAVE 0x100 /* when text is on the heap before setvareq */
1452 # define VDYNAMIC 0x200 /* dynamic variable */
1458 struct var *next; /* next entry in hash list */
1459 int flags; /* flags are defined above */
1460 const char *text; /* name=value */
1461 void (*func)(const char *); /* function to be called when */
1462 /* the variable gets set/unset */
1466 struct localvar *next; /* next local variable in list */
1467 struct var *vp; /* the variable that was made local */
1468 int flags; /* saved flags */
1469 const char *text; /* saved text */
1473 static struct localvar *localvars;
1479 #ifdef CONFIG_ASH_GETOPTS
1480 static void getoptsreset(const char *);
1483 #ifdef CONFIG_LOCALE_SUPPORT
1485 static void change_lc_all(const char *value);
1486 static void change_lc_ctype(const char *value);
1492 static const char defpathvar[] = "PATH=/usr/local/bin:/usr/bin:/sbin:/bin";
1494 static const char defifsvar[] = "IFS= \t\n";
1495 #define defifs (defifsvar + 4)
1497 static const char defifs[] = " \t\n";
1501 static struct var varinit[] = {
1503 { 0, VSTRFIXED|VTEXTFIXED, defifsvar, 0 },
1505 { 0, VSTRFIXED|VTEXTFIXED|VUNSET, "IFS\0", 0 },
1508 #ifdef CONFIG_ASH_MAIL
1509 { 0, VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL\0", changemail },
1510 { 0, VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH\0", changemail },
1513 { 0, VSTRFIXED|VTEXTFIXED, defpathvar, changepath },
1514 { 0, VSTRFIXED|VTEXTFIXED, "PS1=$ ", 0 },
1515 { 0, VSTRFIXED|VTEXTFIXED, "PS2=> ", 0 },
1516 { 0, VSTRFIXED|VTEXTFIXED, "PS4=+ ", 0 },
1517 #ifdef CONFIG_ASH_GETOPTS
1518 { 0, VSTRFIXED|VTEXTFIXED, "OPTIND=1", getoptsreset },
1520 #ifdef CONFIG_ASH_RANDOM_SUPPORT
1521 {0, VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM\0", change_random },
1523 #ifdef CONFIG_LOCALE_SUPPORT
1524 {0, VSTRFIXED | VTEXTFIXED | VUNSET, "LC_ALL\0", change_lc_all },
1525 {0, VSTRFIXED | VTEXTFIXED | VUNSET, "LC_CTYPE\0", change_lc_ctype },
1527 #ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
1528 {0, VSTRFIXED | VTEXTFIXED | VUNSET, "HISTFILE\0", NULL },
1532 #define vifs varinit[0]
1533 #ifdef CONFIG_ASH_MAIL
1534 #define vmail (&vifs)[1]
1535 #define vmpath (&vmail)[1]
1539 #define vpath (&vmpath)[1]
1540 #define vps1 (&vpath)[1]
1541 #define vps2 (&vps1)[1]
1542 #define vps4 (&vps2)[1]
1543 #define voptind (&vps4)[1]
1544 #ifdef CONFIG_ASH_GETOPTS
1545 #define vrandom (&voptind)[1]
1547 #define vrandom (&vps4)[1]
1549 #define defpath (defpathvar + 5)
1552 * The following macros access the values of the above variables.
1553 * They have to skip over the name. They return the null string
1554 * for unset variables.
1557 #define ifsval() (vifs.text + 4)
1558 #define ifsset() ((vifs.flags & VUNSET) == 0)
1559 #define mailval() (vmail.text + 5)
1560 #define mpathval() (vmpath.text + 9)
1561 #define pathval() (vpath.text + 5)
1562 #define ps1val() (vps1.text + 4)
1563 #define ps2val() (vps2.text + 4)
1564 #define ps4val() (vps4.text + 4)
1565 #define optindval() (voptind.text + 7)
1567 #define mpathset() ((vmpath.flags & VUNSET) == 0)
1569 static void setvar(const char *, const char *, int);
1570 static void setvareq(char *, int);
1571 static void listsetvar(struct strlist *, int);
1572 static char *lookupvar(const char *);
1573 static char *bltinlookup(const char *);
1574 static char **listvars(int, int, char ***);
1575 #define environment() listvars(VEXPORT, VUNSET, 0)
1576 static int showvars(const char *, int, int);
1577 static void poplocalvars(void);
1578 static int unsetvar(const char *);
1579 #ifdef CONFIG_ASH_GETOPTS
1580 static int setvarsafe(const char *, const char *, int);
1582 static int varcmp(const char *, const char *);
1583 static struct var **hashvar(const char *);
1586 static inline int varequal(const char *a, const char *b) {
1587 return !varcmp(a, b);
1591 static int loopnest; /* current loop nesting level */
1594 * The parsefile structure pointed to by the global variable parsefile
1595 * contains information about the current file being read.
1600 struct redirtab *next;
1605 static struct redirtab *redirlist;
1606 static int nullredirs;
1608 extern char **environ;
1613 static void outstr(const char *, FILE *);
1614 static void outcslow(int, FILE *);
1615 static void flushall(void);
1616 static void flusherr(void);
1617 static int out1fmt(const char *, ...)
1618 __attribute__((__format__(__printf__,1,2)));
1619 static int fmtstr(char *, size_t, const char *, ...)
1620 __attribute__((__format__(__printf__,3,4)));
1622 static int preverrout_fd; /* save fd2 before print debug if xflag is set. */
1625 static void out1str(const char *p)
1630 static void out2str(const char *p)
1637 * Initialization code.
1641 * This routine initializes the builtin variables.
1652 * PS1 depends on uid
1654 #if defined(CONFIG_FEATURE_COMMAND_EDITING) && defined(CONFIG_FEATURE_SH_FANCY_PROMPT)
1655 vps1.text = "PS1=\\w \\$ ";
1658 vps1.text = "PS1=# ";
1661 end = vp + sizeof(varinit) / sizeof(varinit[0]);
1663 vpp = hashvar(vp->text);
1666 } while (++vp < end);
1675 basepf.nextc = basepf.buf = basebuf;
1680 signal(SIGCHLD, SIG_DFL);
1688 struct stat st1, st2;
1691 for (envp = environ ; envp && *envp ; envp++) {
1692 if (strchr(*envp, '=')) {
1693 setvareq(*envp, VEXPORT|VTEXTFIXED);
1697 snprintf(ppid, sizeof(ppid), "%d", (int) getppid());
1698 setvar("PPID", ppid, 0);
1700 p = lookupvar("PWD");
1702 if (*p != '/' || stat(p, &st1) || stat(".", &st2) ||
1703 st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino)
1709 /* PEOF (the end of file marker) */
1712 INPUT_PUSH_FILE = 1,
1713 INPUT_NOFILE_OK = 2,
1717 * The input line number. Input.c just defines this variable, and saves
1718 * and restores it when files are pushed and popped. The user of this
1719 * package must set its value.
1722 static int pgetc(void);
1723 static int pgetc2(void);
1724 static int preadbuffer(void);
1725 static void pungetc(void);
1726 static void pushstring(char *, void *);
1727 static void popstring(void);
1728 static void setinputfd(int, int);
1729 static void setinputstring(char *);
1730 static void popfile(void);
1731 static void popallfiles(void);
1732 static void closescript(void);
1738 /* Mode argument to forkshell. Don't change FORK_FG or FORK_BG. */
1741 #define FORK_NOJOB 2
1743 /* mode flags for showjob(s) */
1744 #define SHOW_PGID 0x01 /* only show pgid - for jobs -p */
1745 #define SHOW_PID 0x04 /* include process pid */
1746 #define SHOW_CHANGED 0x08 /* only jobs whose state has changed */
1750 * A job structure contains information about a job. A job is either a
1751 * single process or a set of processes contained in a pipeline. In the
1752 * latter case, pidlist will be non-NULL, and will point to a -1 terminated
1757 pid_t pid; /* process id */
1758 int status; /* last process status from wait() */
1759 char *cmd; /* text of command being run */
1763 struct procstat ps0; /* status of process */
1764 struct procstat *ps; /* status or processes when more than one */
1766 int stopstatus; /* status of a stopped job */
1769 nprocs: 16, /* number of processes */
1771 #define JOBRUNNING 0 /* at least one proc running */
1772 #define JOBSTOPPED 1 /* all procs are stopped */
1773 #define JOBDONE 2 /* all procs are completed */
1775 sigint: 1, /* job was killed by SIGINT */
1776 jobctl: 1, /* job running under job control */
1778 waited: 1, /* true if this entry has been waited for */
1779 used: 1, /* true if this entry is in used */
1780 changed: 1; /* true if status has changed */
1781 struct job *prev_job; /* previous job */
1784 static pid_t backgndpid; /* pid of last background process */
1785 static int job_warning; /* user was warned about stopped jobs */
1787 static int jobctl; /* true if doing job control */
1790 static struct job *makejob(union node *, int);
1791 static int forkshell(struct job *, union node *, int);
1792 static int waitforjob(struct job *);
1793 static int stoppedjobs(void);
1796 #define setjobctl(on) /* do nothing */
1798 static void setjobctl(int);
1799 static void showjobs(FILE *, int);
1805 /* pid of main shell */
1807 /* shell level: 0 for the main shell, 1 for its children, and so on */
1809 #define rootshell (!shlvl)
1811 static void readcmdfile(char *);
1812 static int cmdloop(int);
1818 struct stack_block *stackp;
1821 struct stackmark *marknext;
1824 /* minimum size of a block */
1825 #define MINSIZE SHELL_ALIGN(504)
1827 struct stack_block {
1828 struct stack_block *prev;
1829 char space[MINSIZE];
1832 static struct stack_block stackbase;
1833 static struct stack_block *stackp = &stackbase;
1834 static struct stackmark *markp;
1835 static char *stacknxt = stackbase.space;
1836 static size_t stacknleft = MINSIZE;
1837 static char *sstrend = stackbase.space + MINSIZE;
1838 static int herefd = -1;
1841 static pointer ckmalloc(size_t);
1842 static pointer ckrealloc(pointer, size_t);
1843 static char *savestr(const char *);
1844 static pointer stalloc(size_t);
1845 static void stunalloc(pointer);
1846 static void setstackmark(struct stackmark *);
1847 static void popstackmark(struct stackmark *);
1848 static void growstackblock(void);
1849 static void *growstackstr(void);
1850 static char *makestrspace(size_t, char *);
1851 static char *stnputs(const char *, size_t, char *);
1852 static char *stputs(const char *, char *);
1855 static inline char *_STPUTC(int c, char *p) {
1862 #define stackblock() ((void *)stacknxt)
1863 #define stackblocksize() stacknleft
1864 #define STARTSTACKSTR(p) ((p) = stackblock())
1865 #define STPUTC(c, p) ((p) = _STPUTC((c), (p)))
1866 #define CHECKSTRSPACE(n, p) \
1870 size_t m = sstrend - q; \
1872 (p) = makestrspace(l, q); \
1875 #define USTPUTC(c, p) (*p++ = (c))
1876 #define STACKSTRNUL(p) ((p) == sstrend? (p = growstackstr(), *p = '\0') : (*p = '\0'))
1877 #define STUNPUTC(p) (--p)
1878 #define STTOPC(p) p[-1]
1879 #define STADJUST(amount, p) (p += (amount))
1881 #define grabstackstr(p) stalloc((char *)(p) - (char *)stackblock())
1882 #define ungrabstackstr(s, p) stunalloc((s))
1883 #define stackstrend() ((void *)sstrend)
1885 #define ckfree(p) free((pointer)(p))
1890 #define DOLATSTRLEN 4
1892 static char *prefix(const char *, const char *);
1893 static int number(const char *);
1894 static int is_number(const char *);
1895 static char *single_quote(const char *);
1896 static char *sstrdup(const char *);
1898 #define equal(s1, s2) (strcmp(s1, s2) == 0)
1899 #define scopy(s1, s2) ((void)strcpy(s2, s1))
1904 int nparam; /* # of positional parameters (without $0) */
1905 unsigned char malloc; /* if parameter list dynamically allocated */
1906 char **p; /* parameter list */
1907 #ifdef CONFIG_ASH_GETOPTS
1908 int optind; /* next parameter to be processed by getopts */
1909 int optoff; /* used by getopts */
1914 #define eflag optlist[0]
1915 #define fflag optlist[1]
1916 #define Iflag optlist[2]
1917 #define iflag optlist[3]
1918 #define mflag optlist[4]
1919 #define nflag optlist[5]
1920 #define sflag optlist[6]
1921 #define xflag optlist[7]
1922 #define vflag optlist[8]
1923 #define Cflag optlist[9]
1924 #define aflag optlist[10]
1925 #define bflag optlist[11]
1926 #define uflag optlist[12]
1927 #define viflag optlist[13]
1930 #define nolog optlist[14]
1931 #define debug optlist[15]
1934 #ifndef CONFIG_FEATURE_COMMAND_EDITING_VI
1935 #define setvimode(on) viflag = 0 /* forcibly keep the option off */
1941 static const char *const optletters_optnames[] = {
1962 #define optletters(n) optletters_optnames[(n)][0]
1963 #define optnames(n) (&optletters_optnames[(n)][1])
1965 #define NOPTS (sizeof(optletters_optnames)/sizeof(optletters_optnames[0]))
1967 static char optlist[NOPTS];
1970 static char *arg0; /* value of $0 */
1971 static struct shparam shellparam; /* $@ current positional parameters */
1972 static char **argptr; /* argument list for builtin commands */
1973 static char *optionarg; /* set by nextopt (like getopt) */
1974 static char *optptr; /* used by nextopt */
1976 static char *minusc; /* argument to -c option */
1979 static void procargs(int, char **);
1980 static void optschanged(void);
1981 static void setparam(char **);
1982 static void freeparam(volatile struct shparam *);
1983 static int shiftcmd(int, char **);
1984 static int setcmd(int, char **);
1985 static int nextopt(const char *);
1989 /* flags passed to redirect */
1990 #define REDIR_PUSH 01 /* save previous values of file descriptors */
1991 #define REDIR_SAVEFD2 03 /* set preverrout */
1994 static void redirect(union node *, int);
1995 static void popredir(int);
1996 static void clearredir(int);
1997 static int copyfd(int, int);
1998 static int redirectsafe(union node *, int);
2004 static void showtree(union node *);
2005 static void trace(const char *, ...);
2006 static void tracev(const char *, va_list);
2007 static void trargs(char **);
2008 static void trputc(int);
2009 static void trputs(const char *);
2010 static void opentrace(void);
2016 /* trap handler commands */
2017 static char *trap[NSIG];
2018 /* current value of signal */
2019 static char sigmode[NSIG - 1];
2020 /* indicates specified signal received */
2021 static char gotsig[NSIG - 1];
2023 static void clear_traps(void);
2024 static void setsignal(int);
2025 static void ignoresig(int);
2026 static void onsig(int);
2027 static int dotrap(void);
2028 static void setinteractive(int);
2029 static void exitshell(void) __attribute__((__noreturn__));
2030 static int decode_signal(const char *, int);
2033 * This routine is called when an error or an interrupt occurs in an
2034 * interactive shell and control is returned to the main command loop.
2048 parselleft = parsenleft = 0; /* clear input buffer */
2052 /* from parser.c: */
2065 #ifdef CONFIG_ASH_ALIAS
2066 static struct alias *atab[ATABSIZE];
2068 static void setalias(const char *, const char *);
2069 static struct alias *freealias(struct alias *);
2070 static struct alias **__lookupalias(const char *);
2073 setalias(const char *name, const char *val)
2075 struct alias *ap, **app;
2077 app = __lookupalias(name);
2081 if (!(ap->flag & ALIASINUSE)) {
2084 ap->val = savestr(val);
2085 ap->flag &= ~ALIASDEAD;
2088 ap = ckmalloc(sizeof (struct alias));
2089 ap->name = savestr(name);
2090 ap->val = savestr(val);
2099 unalias(const char *name)
2103 app = __lookupalias(name);
2107 *app = freealias(*app);
2118 struct alias *ap, **app;
2122 for (i = 0; i < ATABSIZE; i++) {
2124 for (ap = *app; ap; ap = *app) {
2125 *app = freealias(*app);
2134 static struct alias *
2135 lookupalias(const char *name, int check)
2137 struct alias *ap = *__lookupalias(name);
2139 if (check && ap && (ap->flag & ALIASINUSE))
2145 * TODO - sort output
2148 aliascmd(int argc, char **argv)
2157 for (i = 0; i < ATABSIZE; i++)
2158 for (ap = atab[i]; ap; ap = ap->next) {
2163 while ((n = *++argv) != NULL) {
2164 if ((v = strchr(n+1, '=')) == NULL) { /* n+1: funny ksh stuff */
2165 if ((ap = *__lookupalias(n)) == NULL) {
2166 fprintf(stderr, "%s: %s not found\n", "alias", n);
2180 unaliascmd(int argc, char **argv)
2184 while ((i = nextopt("a")) != '\0') {
2190 for (i = 0; *argptr; argptr++) {
2191 if (unalias(*argptr)) {
2192 fprintf(stderr, "%s: %s not found\n", "unalias", *argptr);
2200 static struct alias *
2201 freealias(struct alias *ap) {
2204 if (ap->flag & ALIASINUSE) {
2205 ap->flag |= ALIASDEAD;
2217 printalias(const struct alias *ap) {
2218 out1fmt("%s=%s\n", ap->name, single_quote(ap->val));
2221 static struct alias **
2222 __lookupalias(const char *name) {
2223 unsigned int hashval;
2230 ch = (unsigned char)*p;
2234 ch = (unsigned char)*++p;
2236 app = &atab[hashval % ATABSIZE];
2238 for (; *app; app = &(*app)->next) {
2239 if (equal(name, (*app)->name)) {
2246 #endif /* CONFIG_ASH_ALIAS */
2252 * The cd and pwd commands.
2255 #define CD_PHYSICAL 1
2258 static int docd(const char *, int);
2259 static int cdopt(void);
2261 static char *curdir = nullstr; /* current working directory */
2262 static char *physdir = nullstr; /* physical working directory */
2271 while ((i = nextopt("LP"))) {
2273 flags ^= CD_PHYSICAL;
2282 cdcmd(int argc, char **argv)
2294 dest = bltinlookup(homestr);
2295 else if (dest[0] == '-' && dest[1] == '\0') {
2296 dest = bltinlookup("OLDPWD");
2318 if (!(path = bltinlookup("CDPATH"))) {
2326 p = padvance(&path, dest);
2327 if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
2331 if (!docd(p, flags))
2336 sh_error("can't cd to %s", dest);
2339 if (flags & CD_PRINT)
2340 out1fmt(snlfmt, curdir);
2346 * Update curdir (the name of the current directory) in response to a
2350 static inline const char *
2351 updatepwd(const char *dir)
2358 cdcomppath = sstrdup(dir);
2361 if (curdir == nullstr)
2363 new = stputs(curdir, new);
2365 new = makestrspace(strlen(dir) + 2, new);
2366 lim = stackblock() + 1;
2370 if (new > lim && *lim == '/')
2375 if (dir[1] == '/' && dir[2] != '/') {
2381 p = strtok(cdcomppath, "/");
2385 if (p[1] == '.' && p[2] == '\0') {
2392 } else if (p[1] == '\0')
2396 new = stputs(p, new);
2404 return stackblock();
2408 * Actually do the chdir. We also call hashcd to let the routines in exec.c
2409 * know that the current directory has changed.
2413 docd(const char *dest, int flags)
2415 const char *dir = 0;
2418 TRACE(("docd(\"%s\", %d) called\n", dest, flags));
2421 if (!(flags & CD_PHYSICAL)) {
2422 dir = updatepwd(dest);
2437 * Find out what the current directory is. If we already know the current
2438 * directory, this routine returns immediately.
2440 static inline char *
2443 char *dir = getcwd(0, 0);
2444 return dir ? dir : nullstr;
2448 pwdcmd(int argc, char **argv)
2451 const char *dir = curdir;
2455 if (physdir == nullstr)
2459 out1fmt(snlfmt, dir);
2464 setpwd(const char *val, int setold)
2468 oldcur = dir = curdir;
2471 setvar("OLDPWD", oldcur, VEXPORT);
2474 if (physdir != nullstr) {
2475 if (physdir != oldcur)
2479 if (oldcur == val || !val) {
2486 if (oldcur != dir && oldcur != nullstr) {
2491 setvar("PWD", dir, VEXPORT);
2497 * Errors and exceptions.
2501 * Code to handle exceptions in C.
2506 static void exverror(int, const char *, va_list)
2507 __attribute__((__noreturn__));
2510 * Called to raise an exception. Since C doesn't include exceptions, we
2511 * just do a longjmp to the exception handler. The type of exception is
2512 * stored in the global variable "exception".
2519 if (handler == NULL)
2525 longjmp(handler->loc, 1);
2530 * Called from trap.c when a SIGINT is received. (If the user specifies
2531 * that SIGINT is to be trapped or ignored using the trap builtin, then
2532 * this routine is not called.) Suppressint is nonzero when interrupts
2533 * are held using the INTOFF macro. (The test for iflag is just
2534 * defensive programming.)
2543 /* comment by vodz: its strange for me, this programm don`t use other
2548 if (gotsig[SIGINT - 1] && !trap[SIGINT]) {
2549 if (!(rootshell && iflag)) {
2550 signal(SIGINT, SIG_DFL);
2560 exvwarning(const char *msg, va_list ap)
2565 fprintf(errs, "%s: ", arg0);
2567 const char *fmt = (!iflag || parsefile->fd) ?
2568 "%s: %d: " : "%s: ";
2569 fprintf(errs, fmt, commandname, startlinno);
2571 vfprintf(errs, msg, ap);
2572 outcslow('\n', errs);
2576 * Exverror is called to raise the error exception. If the second argument
2577 * is not NULL then error prints an error message using printf style
2578 * formatting. It then raises the error exception.
2581 exverror(int cond, const char *msg, va_list ap)
2585 TRACE(("exverror(%d, \"", cond));
2587 TRACE(("\") pid=%d\n", getpid()));
2589 TRACE(("exverror(%d, NULL) pid=%d\n", cond, getpid()));
2592 exvwarning(msg, ap);
2601 sh_error(const char *msg, ...)
2606 exverror(EXERROR, msg, ap);
2613 exerror(int cond, const char *msg, ...)
2618 exverror(cond, msg, ap);
2624 * error/warning routines for external builtins
2628 sh_warnx(const char *fmt, ...)
2633 exvwarning(fmt, ap);
2639 * Return a string describing an error. The returned string may be a
2640 * pointer to a static buffer that will be overwritten on the next call.
2641 * Action describes the operation that got the error.
2645 errmsg(int e, const char *em)
2647 if(e == ENOENT || e == ENOTDIR) {
2658 * Evaluate a command.
2661 /* flags in argument to evaltree */
2662 #define EV_EXIT 01 /* exit after evaluating tree */
2663 #define EV_TESTED 02 /* exit status is checked; ignore -e flag */
2664 #define EV_BACKCMD 04 /* command executing within back quotes */
2667 static void evalloop(union node *, int);
2668 static void evalfor(union node *, int);
2669 static void evalcase(union node *, int);
2670 static void evalsubshell(union node *, int);
2671 static void expredir(union node *);
2672 static void evalpipe(union node *, int);
2673 static void evalcommand(union node *, int);
2674 static int evalbltin(const struct builtincmd *, int, char **);
2675 static int evalfun(struct funcnode *, int, char **, int);
2676 static void prehash(union node *);
2677 static int bltincmd(int, char **);
2680 static const struct builtincmd bltin = {
2686 * Called to reset things after an exception.
2694 evalcmd(int argc, char **argv)
2703 STARTSTACKSTR(concat);
2706 concat = stputs(p, concat);
2707 if ((p = *ap++) == NULL)
2709 STPUTC(' ', concat);
2711 STPUTC('\0', concat);
2712 p = grabstackstr(concat);
2714 evalstring(p, ~SKIPEVAL);
2722 * Execute a command or commands contained in a string.
2726 evalstring(char *s, int mask)
2729 struct stackmark smark;
2733 setstackmark(&smark);
2736 while ((n = parsecmd(0)) != NEOF) {
2738 popstackmark(&smark);
2753 * Evaluate a parse tree. The value is left in the global variable
2758 evaltree(union node *n, int flags)
2761 void (*evalfn)(union node *, int);
2765 TRACE(("evaltree(NULL) called\n"));
2768 TRACE(("pid %d, evaltree(%p: %d, %d) called\n",
2769 getpid(), n, n->type, flags));
2773 out1fmt("Node type = %d\n", n->type);
2778 evaltree(n->nnot.com, EV_TESTED);
2779 status = !exitstatus;
2782 expredir(n->nredir.redirect);
2783 status = redirectsafe(n->nredir.redirect, REDIR_PUSH);
2785 evaltree(n->nredir.n, flags & EV_TESTED);
2786 status = exitstatus;
2791 evalfn = evalcommand;
2793 if (eflag && !(flags & EV_TESTED))
2805 evalfn = evalsubshell;
2817 #error NAND + 1 != NOR
2819 #if NOR + 1 != NSEMI
2820 #error NOR + 1 != NSEMI
2822 isor = n->type - NAND;
2825 (flags | ((isor >> 1) - 1)) & EV_TESTED
2827 if (!exitstatus == isor)
2839 evaltree(n->nif.test, EV_TESTED);
2842 if (exitstatus == 0) {
2845 } else if (n->nif.elsepart) {
2846 n = n->nif.elsepart;
2851 defun(n->narg.text, n->narg.next);
2855 exitstatus = status;
2859 if ((checkexit & exitstatus))
2860 evalskip |= SKIPEVAL;
2861 else if (pendingsigs && dotrap())
2864 if (flags & EV_EXIT) {
2871 #if !defined(__alpha__) || (defined(__GNUC__) && __GNUC__ >= 3)
2874 void evaltreenr(union node *, int) __attribute__ ((alias("evaltree"),__noreturn__));
2878 evalloop(union node *n, int flags)
2888 evaltree(n->nbinary.ch1, EV_TESTED);
2890 skipping: if (evalskip == SKIPCONT && --skipcount <= 0) {
2894 if (evalskip == SKIPBREAK && --skipcount <= 0)
2899 if (n->type != NWHILE)
2903 evaltree(n->nbinary.ch2, flags);
2904 status = exitstatus;
2909 exitstatus = status;
2915 evalfor(union node *n, int flags)
2917 struct arglist arglist;
2920 struct stackmark smark;
2922 setstackmark(&smark);
2923 arglist.lastp = &arglist.list;
2924 for (argp = n->nfor.args ; argp ; argp = argp->narg.next) {
2925 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE | EXP_RECORD);
2930 *arglist.lastp = NULL;
2935 for (sp = arglist.list ; sp ; sp = sp->next) {
2936 setvar(n->nfor.var, sp->text, 0);
2937 evaltree(n->nfor.body, flags);
2939 if (evalskip == SKIPCONT && --skipcount <= 0) {
2943 if (evalskip == SKIPBREAK && --skipcount <= 0)
2950 popstackmark(&smark);
2956 evalcase(union node *n, int flags)
2960 struct arglist arglist;
2961 struct stackmark smark;
2963 setstackmark(&smark);
2964 arglist.lastp = &arglist.list;
2965 expandarg(n->ncase.expr, &arglist, EXP_TILDE);
2967 for (cp = n->ncase.cases ; cp && evalskip == 0 ; cp = cp->nclist.next) {
2968 for (patp = cp->nclist.pattern ; patp ; patp = patp->narg.next) {
2969 if (casematch(patp, arglist.list->text)) {
2970 if (evalskip == 0) {
2971 evaltree(cp->nclist.body, flags);
2978 popstackmark(&smark);
2984 * Kick off a subshell to evaluate a tree.
2988 evalsubshell(union node *n, int flags)
2991 int backgnd = (n->type == NBACKGND);
2994 expredir(n->nredir.redirect);
2995 if (!backgnd && flags & EV_EXIT && !trap[0])
2999 if (forkshell(jp, n, backgnd) == 0) {
3003 flags &=~ EV_TESTED;
3005 redirect(n->nredir.redirect, 0);
3006 evaltreenr(n->nredir.n, flags);
3011 status = waitforjob(jp);
3012 exitstatus = status;
3019 * Compute the names of the files in a redirection list.
3023 expredir(union node *n)
3027 for (redir = n ; redir ; redir = redir->nfile.next) {
3029 fn.lastp = &fn.list;
3030 switch (redir->type) {
3036 expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
3037 redir->nfile.expfname = fn.list->text;
3041 if (redir->ndup.vname) {
3042 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
3043 fixredir(redir, fn.list->text, 1);
3053 * Evaluate a pipeline. All the processes in the pipeline are children
3054 * of the process creating the pipeline. (This differs from some versions
3055 * of the shell, which make the last process in a pipeline the parent
3060 evalpipe(union node *n, int flags)
3063 struct nodelist *lp;
3068 TRACE(("evalpipe(0x%lx) called\n", (long)n));
3070 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next)
3074 jp = makejob(n, pipelen);
3076 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
3080 if (pipe(pip) < 0) {
3082 sh_error("Pipe call failed");
3085 if (forkshell(jp, lp->n, n->npipe.backgnd) == 0) {
3098 evaltreenr(lp->n, flags);
3106 if (n->npipe.backgnd == 0) {
3107 exitstatus = waitforjob(jp);
3108 TRACE(("evalpipe: job done exit status %d\n", exitstatus));
3116 * Execute a command inside back quotes. If it's a builtin command, we
3117 * want to save its output in a block obtained from malloc. Otherwise
3118 * we fork off a subprocess and get the output of the command via a pipe.
3119 * Should be called with interrupts off.
3123 evalbackcmd(union node *n, struct backcmd *result)
3135 saveherefd = herefd;
3143 sh_error("Pipe call failed");
3145 if (forkshell(jp, n, FORK_NOJOB) == 0) {
3154 evaltreenr(n, EV_EXIT);
3158 result->fd = pip[0];
3161 herefd = saveherefd;
3163 TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
3164 result->fd, result->buf, result->nleft, result->jp));
3167 #ifdef CONFIG_ASH_CMDCMD
3168 static inline char **
3169 parse_command_args(char **argv, const char **path)
3181 if (c == '-' && !*cp) {
3191 /* run 'typecmd' for other options */
3194 } while ((c = *cp++));
3201 isassignment(const char *p)
3203 const char *q = endofname(p);
3209 #ifdef CONFIG_ASH_EXPAND_PRMT
3210 static const char *expandstr(const char *ps);
3212 #define expandstr(s) s
3216 * Execute a simple command.
3220 evalcommand(union node *cmd, int flags)
3222 struct stackmark smark;
3224 struct arglist arglist;
3225 struct arglist varlist;
3228 const struct strlist *sp;
3229 struct cmdentry cmdentry;
3237 struct builtincmd *bcmd;
3238 int pseudovarflag = 0;
3240 /* First expand the arguments. */
3241 TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
3242 setstackmark(&smark);
3243 back_exitstatus = 0;
3245 cmdentry.cmdtype = CMDBUILTIN;
3246 cmdentry.u.cmd = &bltin;
3247 varlist.lastp = &varlist.list;
3248 *varlist.lastp = NULL;
3249 arglist.lastp = &arglist.list;
3250 *arglist.lastp = NULL;
3255 bcmd = find_builtin(cmd->ncmd.args->narg.text);
3256 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
3259 for (argp = cmd->ncmd.args; argp; argp = argp->narg.next) {
3260 struct strlist **spp;
3262 spp = arglist.lastp;
3263 if (pseudovarflag && isassignment(argp->narg.text))
3264 expandarg(argp, &arglist, EXP_VARTILDE);
3266 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
3268 for (sp = *spp; sp; sp = sp->next)
3272 argv = nargv = stalloc(sizeof (char *) * (argc + 1));
3273 for (sp = arglist.list ; sp ; sp = sp->next) {
3274 TRACE(("evalcommand arg: %s\n", sp->text));
3275 *nargv++ = sp->text;
3280 if (iflag && funcnest == 0 && argc > 0)
3281 lastarg = nargv[-1];
3284 expredir(cmd->ncmd.redirect);
3285 status = redirectsafe(cmd->ncmd.redirect, REDIR_PUSH|REDIR_SAVEFD2);
3288 for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
3289 struct strlist **spp;
3292 spp = varlist.lastp;
3293 expandarg(argp, &varlist, EXP_VARTILDE);
3296 * Modify the command lookup path, if a PATH= assignment
3300 if (varequal(p, path))
3304 /* Print the command if xflag is set. */
3307 const char *p = " %s";
3310 dprintf(preverrout_fd, p, expandstr(ps4val()));
3313 for(n = 0; n < 2; n++) {
3315 dprintf(preverrout_fd, p, sp->text);
3323 bb_full_write(preverrout_fd, "\n", 1);
3329 /* Now locate the command. */
3331 const char *oldpath;
3332 int cmd_flag = DO_ERR;
3337 find_command(argv[0], &cmdentry, cmd_flag, path);
3338 if (cmdentry.cmdtype == CMDUNKNOWN) {
3344 /* implement bltin and command here */
3345 if (cmdentry.cmdtype != CMDBUILTIN)
3348 spclbltin = IS_BUILTIN_SPECIAL(cmdentry.u.cmd);
3349 if (cmdentry.u.cmd == EXECCMD)
3351 #ifdef CONFIG_ASH_CMDCMD
3352 if (cmdentry.u.cmd == COMMANDCMD) {
3355 nargv = parse_command_args(argv, &path);
3358 argc -= nargv - argv;
3360 cmd_flag |= DO_NOFUNC;
3368 /* We have a redirection error. */
3372 exitstatus = status;
3376 /* Execute the command. */
3377 switch (cmdentry.cmdtype) {
3379 /* Fork off a child process if necessary. */
3380 if (!(flags & EV_EXIT) || trap[0]) {
3382 jp = makejob(cmd, 1);
3383 if (forkshell(jp, cmd, FORK_FG) != 0) {
3384 exitstatus = waitforjob(jp);
3390 listsetvar(varlist.list, VEXPORT|VSTACK);
3391 shellexec(argv, path, cmdentry.u.index);
3395 cmdenviron = varlist.list;
3397 struct strlist *list = cmdenviron;
3399 if (spclbltin > 0 || argc == 0) {
3401 if (cmd_is_exec && argc > 1)
3404 listsetvar(list, i);
3406 if (evalbltin(cmdentry.u.cmd, argc, argv)) {
3421 exit_status = j + 128;
3422 exitstatus = exit_status;
3424 if (i == EXINT || spclbltin > 0) {
3426 longjmp(handler->loc, 1);
3433 listsetvar(varlist.list, 0);
3434 if (evalfun(cmdentry.u.func, argc, argv, flags))
3440 popredir(cmd_is_exec);
3442 /* dsl: I think this is intended to be used to support
3443 * '_' in 'vi' command mode during line editing...
3444 * However I implemented that within libedit itself.
3446 setvar("_", lastarg, 0);
3447 popstackmark(&smark);
3451 evalbltin(const struct builtincmd *cmd, int argc, char **argv) {
3452 char *volatile savecmdname;
3453 struct jmploc *volatile savehandler;
3454 struct jmploc jmploc;
3457 savecmdname = commandname;
3458 if ((i = setjmp(jmploc.loc)))
3460 savehandler = handler;
3462 commandname = argv[0];
3464 optptr = NULL; /* initialize nextopt */
3465 exitstatus = (*cmd->builtin)(argc, argv);
3468 exitstatus |= ferror(stdout);
3469 commandname = savecmdname;
3471 handler = savehandler;
3477 evalfun(struct funcnode *func, int argc, char **argv, int flags)
3479 volatile struct shparam saveparam;
3480 struct localvar *volatile savelocalvars;
3481 struct jmploc *volatile savehandler;
3482 struct jmploc jmploc;
3485 saveparam = shellparam;
3486 savelocalvars = localvars;
3487 if ((e = setjmp(jmploc.loc))) {
3491 savehandler = handler;
3494 shellparam.malloc = 0;
3498 shellparam.nparam = argc - 1;
3499 shellparam.p = argv + 1;
3500 #ifdef CONFIG_ASH_GETOPTS
3501 shellparam.optind = 1;
3502 shellparam.optoff = -1;
3504 evaltree(&func->n, flags & EV_TESTED);
3510 localvars = savelocalvars;
3511 freeparam(&shellparam);
3512 shellparam = saveparam;
3513 handler = savehandler;
3515 evalskip &= ~SKIPFUNC;
3521 goodname(const char *p)
3523 return !*endofname(p);
3527 * Search for a command. This is called before we fork so that the
3528 * location of the command will be available in the parent as well as
3529 * the child. The check for "goodname" is an overly conservative
3530 * check that the name will not be subject to expansion.
3534 prehash(union node *n)
3536 struct cmdentry entry;
3538 if (n->type == NCMD && n->ncmd.args)
3539 if (goodname(n->ncmd.args->narg.text))
3540 find_command(n->ncmd.args->narg.text, &entry, 0,
3547 * Builtin commands. Builtin commands whose functions are closely
3548 * tied to evaluation are implemented here.
3556 bltincmd(int argc, char **argv)
3559 * Preserve exitstatus of a previous possible redirection
3562 return back_exitstatus;
3567 * Handle break and continue commands. Break, continue, and return are
3568 * all handled by setting the evalskip flag. The evaluation routines
3569 * above all check this flag, and if it is set they start skipping
3570 * commands rather than executing them. The variable skipcount is
3571 * the number of loops to break/continue, or the number of function
3572 * levels to return. (The latter is always 1.) It should probably
3573 * be an error to break out of more loops than exist, but it isn't
3574 * in the standard shell so we don't make it one here.
3578 breakcmd(int argc, char **argv)
3580 int n = argc > 1 ? number(argv[1]) : 1;
3583 sh_error(illnum, argv[1]);
3587 evalskip = (**argv == 'c')? SKIPCONT : SKIPBREAK;
3595 * The return command.
3599 returncmd(int argc, char **argv)
3602 * If called outside a function, do what ksh does;
3603 * skip the rest of the file.
3605 evalskip = funcnest ? SKIPFUNC : SKIPFILE;
3606 return argv[1] ? number(argv[1]) : exitstatus;
3611 falsecmd(int argc, char **argv)
3618 truecmd(int argc, char **argv)
3625 execcmd(int argc, char **argv)
3628 iflag = 0; /* exit on error */
3631 shellexec(argv + 1, pathval(), 0);
3640 * When commands are first encountered, they are entered in a hash table.
3641 * This ensures that a full path search will not have to be done for them
3642 * on each invocation.
3644 * We should investigate converting to a linear search, even though that
3645 * would make the command name "hash" a misnomer.
3648 #define CMDTABLESIZE 31 /* should be prime */
3649 #define ARB 1 /* actual size determined at run time */
3654 struct tblentry *next; /* next entry in hash chain */
3655 union param param; /* definition of builtin function */
3656 short cmdtype; /* index identifying command */
3657 char rehash; /* if set, cd done since entry created */
3658 char cmdname[ARB]; /* name of command */
3662 static struct tblentry *cmdtable[CMDTABLESIZE];
3663 static int builtinloc = -1; /* index in path of %builtin, or -1 */
3666 static void tryexec(char *, char **, char **);
3667 static void clearcmdentry(int);
3668 static struct tblentry *cmdlookup(const char *, int);
3669 static void delete_cmd_entry(void);
3673 * Exec a program. Never returns. If you change this routine, you may
3674 * have to change the find_command routine as well.
3678 shellexec(char **argv, const char *path, int idx)
3686 envp = environment();
3687 if (strchr(argv[0], '/') != NULL
3688 #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
3689 || find_applet_by_name(argv[0])
3692 tryexec(argv[0], argv, envp);
3696 while ((cmdname = padvance(&path, argv[0])) != NULL) {
3697 if (--idx < 0 && pathopt == NULL) {
3698 tryexec(cmdname, argv, envp);
3699 if (errno != ENOENT && errno != ENOTDIR)
3706 /* Map to POSIX errors */
3718 exitstatus = exerrno;
3719 TRACE(("shellexec failed for %s, errno %d, suppressint %d\n",
3720 argv[0], e, suppressint ));
3721 exerror(EXEXEC, "%s: %s", argv[0], errmsg(e, E_EXEC));
3727 tryexec(char *cmd, char **argv, char **envp)
3730 #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
3731 if(find_applet_by_name(cmd) != NULL) {
3732 /* re-exec ourselves with the new arguments */
3733 execve("/proc/self/exe",argv,envp);
3734 /* If proc isn't mounted, try hardcoded path to busybox binary*/
3735 execve("/bin/busybox",argv,envp);
3736 /* If they called chroot or otherwise made the binary no longer
3737 * executable, fall through */
3744 execve(cmd, argv, envp);
3745 } while (errno == EINTR);
3747 execve(cmd, argv, envp);
3751 } else if (errno == ENOEXEC) {
3755 for (ap = argv; *ap; ap++)
3757 ap = new = ckmalloc((ap - argv + 2) * sizeof(char *));
3759 *ap = cmd = (char *)DEFAULT_SHELL;
3762 while ((*ap++ = *argv++))
3772 * Do a path search. The variable path (passed by reference) should be
3773 * set to the start of the path before the first call; padvance will update
3774 * this value as it proceeds. Successive calls to padvance will return
3775 * the possible path expansions in sequence. If an option (indicated by
3776 * a percent sign) appears in the path entry then the global variable
3777 * pathopt will be set to point to it; otherwise pathopt will be set to
3782 padvance(const char **path, const char *name)
3792 for (p = start ; *p && *p != ':' && *p != '%' ; p++);
3793 len = p - start + strlen(name) + 2; /* "2" is for '/' and '\0' */
3794 while (stackblocksize() < len)
3798 memcpy(q, start, p - start);
3806 while (*p && *p != ':') p++;
3812 return stalloc(len);
3816 /*** Command hashing code ***/
3819 printentry(struct tblentry *cmdp)
3825 idx = cmdp->param.index;
3828 name = padvance(&path, cmdp->cmdname);
3830 } while (--idx >= 0);
3831 out1fmt("%s%s\n", name, (cmdp->rehash ? "*" : nullstr));
3836 hashcmd(int argc, char **argv)
3838 struct tblentry **pp;
3839 struct tblentry *cmdp;
3841 struct cmdentry entry;
3844 while ((c = nextopt("r")) != '\0') {
3848 if (*argptr == NULL) {
3849 for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
3850 for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
3851 if (cmdp->cmdtype == CMDNORMAL)
3858 while ((name = *argptr) != NULL) {
3859 if ((cmdp = cmdlookup(name, 0)) != NULL
3860 && (cmdp->cmdtype == CMDNORMAL
3861 || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0)))
3863 find_command(name, &entry, DO_ERR, pathval());
3864 if (entry.cmdtype == CMDUNKNOWN)
3873 * Resolve a command name. If you change this routine, you may have to
3874 * change the shellexec routine as well.
3878 find_command(char *name, struct cmdentry *entry, int act, const char *path)
3880 struct tblentry *cmdp;
3887 struct builtincmd *bcmd;
3889 /* If name contains a slash, don't use PATH or hash table */
3890 if (strchr(name, '/') != NULL) {
3891 entry->u.index = -1;
3893 while (stat(name, &statb) < 0) {
3898 entry->cmdtype = CMDUNKNOWN;
3902 entry->cmdtype = CMDNORMAL;
3906 #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
3907 if (find_applet_by_name(name)) {
3908 entry->cmdtype = CMDNORMAL;
3909 entry->u.index = -1;
3914 updatetbl = (path == pathval());
3917 if (strstr(path, "%builtin") != NULL)
3921 /* If name is in the table, check answer will be ok */
3922 if ((cmdp = cmdlookup(name, 0)) != NULL) {
3925 switch (cmdp->cmdtype) {
3943 } else if (cmdp->rehash == 0)
3944 /* if not invalidated by cd, we're done */
3948 /* If %builtin not in path, check for builtin next */
3949 bcmd = find_builtin(name);
3950 if (bcmd && (IS_BUILTIN_REGULAR(bcmd) || (
3951 act & DO_ALTPATH ? !(act & DO_ALTBLTIN) : builtinloc <= 0
3953 goto builtin_success;
3955 /* We have to search path. */
3956 prev = -1; /* where to start */
3957 if (cmdp && cmdp->rehash) { /* doing a rehash */
3958 if (cmdp->cmdtype == CMDBUILTIN)
3961 prev = cmdp->param.index;
3967 while ((fullname = padvance(&path, name)) != NULL) {
3968 stunalloc(fullname);
3971 if (prefix(pathopt, "builtin")) {
3973 goto builtin_success;
3975 } else if (!(act & DO_NOFUNC) &&
3976 prefix(pathopt, "func")) {
3979 /* ignore unimplemented options */
3983 /* if rehash, don't redo absolute path names */
3984 if (fullname[0] == '/' && idx <= prev) {
3987 TRACE(("searchexec \"%s\": no change\n", name));
3990 while (stat(fullname, &statb) < 0) {
3995 if (errno != ENOENT && errno != ENOTDIR)
3999 e = EACCES; /* if we fail, this will be the error */
4000 if (!S_ISREG(statb.st_mode))
4002 if (pathopt) { /* this is a %func directory */
4003 stalloc(strlen(fullname) + 1);
4004 readcmdfile(fullname);
4005 if ((cmdp = cmdlookup(name, 0)) == NULL ||
4006 cmdp->cmdtype != CMDFUNCTION)
4007 sh_error("%s not defined in %s", name, fullname);
4008 stunalloc(fullname);
4011 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
4013 entry->cmdtype = CMDNORMAL;
4014 entry->u.index = idx;
4018 cmdp = cmdlookup(name, 1);
4019 cmdp->cmdtype = CMDNORMAL;
4020 cmdp->param.index = idx;
4025 /* We failed. If there was an entry for this command, delete it */
4026 if (cmdp && updatetbl)
4029 sh_warnx("%s: %s", name, errmsg(e, E_EXEC));
4030 entry->cmdtype = CMDUNKNOWN;
4035 entry->cmdtype = CMDBUILTIN;
4036 entry->u.cmd = bcmd;
4040 cmdp = cmdlookup(name, 1);
4041 cmdp->cmdtype = CMDBUILTIN;
4042 cmdp->param.cmd = bcmd;
4046 entry->cmdtype = cmdp->cmdtype;
4047 entry->u = cmdp->param;
4052 * Wrapper around strcmp for qsort/bsearch/...
4054 static int pstrcmp(const void *a, const void *b)
4056 return strcmp((const char *) a, (*(const char *const *) b) + 1);
4060 * Search the table of builtin commands.
4063 static struct builtincmd *
4064 find_builtin(const char *name)
4066 struct builtincmd *bp;
4069 name, builtincmd, NUMBUILTINS, sizeof(struct builtincmd),
4078 * Called when a cd is done. Marks all commands so the next time they
4079 * are executed they will be rehashed.
4085 struct tblentry **pp;
4086 struct tblentry *cmdp;
4088 for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
4089 for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
4090 if (cmdp->cmdtype == CMDNORMAL || (
4091 cmdp->cmdtype == CMDBUILTIN &&
4092 !(IS_BUILTIN_REGULAR(cmdp->param.cmd)) &&
4103 * Fix command hash table when PATH changed.
4104 * Called before PATH is changed. The argument is the new value of PATH;
4105 * pathval() still returns the old value at this point.
4106 * Called with interrupts off.
4110 changepath(const char *newval)
4112 const char *old, *new;
4119 firstchange = 9999; /* assume no change */
4125 if ((*old == '\0' && *new == ':')
4126 || (*old == ':' && *new == '\0'))
4128 old = new; /* ignore subsequent differences */
4132 if (*new == '%' && idx_bltin < 0 && prefix(new + 1, "builtin"))
4139 if (builtinloc < 0 && idx_bltin >= 0)
4140 builtinloc = idx_bltin; /* zap builtins */
4141 if (builtinloc >= 0 && idx_bltin < 0)
4143 clearcmdentry(firstchange);
4144 builtinloc = idx_bltin;
4149 * Clear out command entries. The argument specifies the first entry in
4150 * PATH which has changed.
4154 clearcmdentry(int firstchange)
4156 struct tblentry **tblp;
4157 struct tblentry **pp;
4158 struct tblentry *cmdp;
4161 for (tblp = cmdtable ; tblp < &cmdtable[CMDTABLESIZE] ; tblp++) {
4163 while ((cmdp = *pp) != NULL) {
4164 if ((cmdp->cmdtype == CMDNORMAL &&
4165 cmdp->param.index >= firstchange)
4166 || (cmdp->cmdtype == CMDBUILTIN &&
4167 builtinloc >= firstchange)) {
4181 * Locate a command in the command hash table. If "add" is nonzero,
4182 * add the command to the table if it is not already present. The
4183 * variable "lastcmdentry" is set to point to the address of the link
4184 * pointing to the entry, so that delete_cmd_entry can delete the
4187 * Interrupts must be off if called with add != 0.
4190 static struct tblentry **lastcmdentry;
4193 static struct tblentry *
4194 cmdlookup(const char *name, int add)
4196 unsigned int hashval;
4198 struct tblentry *cmdp;
4199 struct tblentry **pp;
4202 hashval = (unsigned char)*p << 4;
4204 hashval += (unsigned char)*p++;
4206 pp = &cmdtable[hashval % CMDTABLESIZE];
4207 for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
4208 if (equal(cmdp->cmdname, name))
4212 if (add && cmdp == NULL) {
4213 cmdp = *pp = ckmalloc(sizeof (struct tblentry) - ARB
4214 + strlen(name) + 1);
4216 cmdp->cmdtype = CMDUNKNOWN;
4217 strcpy(cmdp->cmdname, name);
4224 * Delete the command entry returned on the last lookup.
4228 delete_cmd_entry(void)
4230 struct tblentry *cmdp;
4233 cmdp = *lastcmdentry;
4234 *lastcmdentry = cmdp->next;
4235 if (cmdp->cmdtype == CMDFUNCTION)
4236 freefunc(cmdp->param.func);
4243 * Add a new command entry, replacing any existing command entry for
4244 * the same name - except special builtins.
4248 addcmdentry(char *name, struct cmdentry *entry)
4250 struct tblentry *cmdp;
4252 cmdp = cmdlookup(name, 1);
4253 if (cmdp->cmdtype == CMDFUNCTION) {
4254 freefunc(cmdp->param.func);
4256 cmdp->cmdtype = entry->cmdtype;
4257 cmdp->param = entry->u;
4262 * Make a copy of a parse tree.
4265 static inline struct funcnode *
4266 copyfunc(union node *n)
4271 funcblocksize = offsetof(struct funcnode, n);
4274 blocksize = funcblocksize;
4275 f = ckmalloc(blocksize + funcstringsize);
4276 funcblock = (char *) f + offsetof(struct funcnode, n);
4277 funcstring = (char *) f + blocksize;
4284 * Define a shell function.
4288 defun(char *name, union node *func)
4290 struct cmdentry entry;
4293 entry.cmdtype = CMDFUNCTION;
4294 entry.u.func = copyfunc(func);
4295 addcmdentry(name, &entry);
4301 * Delete a function if it exists.
4305 unsetfunc(const char *name)
4307 struct tblentry *cmdp;
4309 if ((cmdp = cmdlookup(name, 0)) != NULL &&
4310 cmdp->cmdtype == CMDFUNCTION)
4315 * Locate and print what a word is...
4319 #ifdef CONFIG_ASH_CMDCMD
4321 describe_command(char *command, int describe_command_verbose)
4323 #define describe_command_verbose 1
4325 describe_command(char *command)
4328 struct cmdentry entry;
4329 struct tblentry *cmdp;
4330 #ifdef CONFIG_ASH_ALIAS
4331 const struct alias *ap;
4333 const char *path = pathval();
4335 if (describe_command_verbose) {
4339 /* First look at the keywords */
4340 if (findkwd(command)) {
4341 out1str(describe_command_verbose ? " is a shell keyword" : command);
4345 #ifdef CONFIG_ASH_ALIAS
4346 /* Then look at the aliases */
4347 if ((ap = lookupalias(command, 0)) != NULL) {
4348 if (describe_command_verbose) {
4349 out1fmt(" is an alias for %s", ap->val);
4358 /* Then check if it is a tracked alias */
4359 if ((cmdp = cmdlookup(command, 0)) != NULL) {
4360 entry.cmdtype = cmdp->cmdtype;
4361 entry.u = cmdp->param;
4363 /* Finally use brute force */
4364 find_command(command, &entry, DO_ABS, path);
4367 switch (entry.cmdtype) {
4369 int j = entry.u.index;
4375 p = padvance(&path, command);
4379 if (describe_command_verbose) {
4381 (cmdp ? " a tracked alias for" : nullstr), p
4390 if (describe_command_verbose) {
4391 out1str(" is a shell function");
4398 if (describe_command_verbose) {
4399 out1fmt(" is a %sshell builtin",
4400 IS_BUILTIN_SPECIAL(entry.u.cmd) ?
4401 "special " : nullstr
4409 if (describe_command_verbose) {
4410 out1str(": not found\n");
4416 outstr("\n", stdout);
4421 typecmd(int argc, char **argv)
4426 for (i = 1; i < argc; i++) {
4427 #ifdef CONFIG_ASH_CMDCMD
4428 err |= describe_command(argv[i], 1);
4430 err |= describe_command(argv[i]);
4436 #ifdef CONFIG_ASH_CMDCMD
4438 commandcmd(int argc, char **argv)
4446 while ((c = nextopt("pvV")) != '\0')
4448 verify |= VERIFY_VERBOSE;
4450 verify |= VERIFY_BRIEF;
4456 return describe_command(*argptr, verify - VERIFY_BRIEF);
4465 * Routines to expand arguments to commands. We have to deal with
4466 * backquotes, shell variables, and file metacharacters.
4472 #define RMESCAPE_ALLOC 0x1 /* Allocate a new string */
4473 #define RMESCAPE_GLOB 0x2 /* Add backslashes for glob */
4474 #define RMESCAPE_QUOTED 0x4 /* Remove CTLESC unless in quotes */
4475 #define RMESCAPE_GROW 0x8 /* Grow strings instead of stalloc */
4476 #define RMESCAPE_HEAP 0x10 /* Malloc strings instead of stalloc */
4479 * Structure specifying which parts of the string should be searched
4480 * for IFS characters.
4484 struct ifsregion *next; /* next region in list */
4485 int begoff; /* offset of start of region */
4486 int endoff; /* offset of end of region */
4487 int nulonly; /* search for nul bytes only */
4490 /* output of current string */
4491 static char *expdest;
4492 /* list of back quote expressions */
4493 static struct nodelist *argbackq;
4494 /* first struct in list of ifs regions */
4495 static struct ifsregion ifsfirst;
4496 /* last struct in list */
4497 static struct ifsregion *ifslastp;
4498 /* holds expanded arg list */
4499 static struct arglist exparg;
4501 static void argstr(char *, int);
4502 static char *exptilde(char *, char *, int);
4503 static void expbackq(union node *, int, int);
4504 static const char *subevalvar(char *, char *, int, int, int, int, int);
4505 static char *evalvar(char *, int);
4506 static void strtodest(const char *, int, int);
4507 static void memtodest(const char *p, size_t len, int syntax, int quotes);
4508 static ssize_t varvalue(char *, int, int);
4509 static void recordregion(int, int, int);
4510 static void removerecordregions(int);
4511 static void ifsbreakup(char *, struct arglist *);
4512 static void ifsfree(void);
4513 static void expandmeta(struct strlist *, int);
4514 static int patmatch(char *, const char *);
4516 static int cvtnum(arith_t);
4517 static size_t esclen(const char *, const char *);
4518 static char *scanleft(char *, char *, char *, char *, int, int);
4519 static char *scanright(char *, char *, char *, char *, int, int);
4520 static void varunset(const char *, const char *, const char *, int)
4521 __attribute__((__noreturn__));
4524 #define pmatch(a, b) !fnmatch((a), (b), 0)
4526 * Prepare a pattern for a expmeta (internal glob(3)) call.
4528 * Returns an stalloced string.
4531 static inline char *
4532 preglob(const char *pattern, int quoted, int flag) {
4533 flag |= RMESCAPE_GLOB;
4535 flag |= RMESCAPE_QUOTED;
4537 return _rmescapes((char *)pattern, flag);
4542 esclen(const char *start, const char *p) {
4545 while (p > start && *--p == CTLESC) {
4553 * Expand shell variables and backquotes inside a here document.
4557 expandhere(union node *arg, int fd)
4560 expandarg(arg, (struct arglist *)NULL, 0);
4561 bb_full_write(fd, stackblock(), expdest - (char *)stackblock());
4566 * Perform variable substitution and command substitution on an argument,
4567 * placing the resulting list of arguments in arglist. If EXP_FULL is true,
4568 * perform splitting and file name expansion. When arglist is NULL, perform
4569 * here document expansion.
4573 expandarg(union node *arg, struct arglist *arglist, int flag)
4578 argbackq = arg->narg.backquote;
4579 STARTSTACKSTR(expdest);
4580 ifsfirst.next = NULL;
4582 argstr(arg->narg.text, flag);
4583 p = _STPUTC('\0', expdest);
4585 if (arglist == NULL) {
4586 return; /* here document expanded */
4588 p = grabstackstr(p);
4589 exparg.lastp = &exparg.list;
4593 if (flag & EXP_FULL) {
4594 ifsbreakup(p, &exparg);
4595 *exparg.lastp = NULL;
4596 exparg.lastp = &exparg.list;
4597 expandmeta(exparg.list, flag);
4599 if (flag & EXP_REDIR) /*XXX - for now, just remove escapes */
4601 sp = (struct strlist *)stalloc(sizeof (struct strlist));
4604 exparg.lastp = &sp->next;
4608 *exparg.lastp = NULL;
4610 *arglist->lastp = exparg.list;
4611 arglist->lastp = exparg.lastp;
4617 * Perform variable and command substitution. If EXP_FULL is set, output CTLESC
4618 * characters to allow for further processing. Otherwise treat
4619 * $@ like $* since no splitting will be performed.
4623 argstr(char *p, int flag)
4625 static const char spclchars[] = {
4633 CTLBACKQ | CTLQUOTE,
4634 #ifdef CONFIG_ASH_MATH_SUPPORT
4639 const char *reject = spclchars;
4641 int quotes = flag & (EXP_FULL | EXP_CASE); /* do CTLESC */
4642 int breakall = flag & EXP_WORD;
4647 if (!(flag & EXP_VARTILDE)) {
4649 } else if (flag & EXP_VARTILDE2) {
4654 if (flag & EXP_TILDE) {
4660 if (*q == CTLESC && (flag & EXP_QWORD))
4663 p = exptilde(p, q, flag);
4666 startloc = expdest - (char *)stackblock();
4668 length += strcspn(p + length, reject);
4670 if (c && (!(c & 0x80)
4671 #ifdef CONFIG_ASH_MATH_SUPPORT
4675 /* c == '=' || c == ':' || c == CTLENDARI */
4680 expdest = stnputs(p, length, expdest);
4681 newloc = expdest - (char *)stackblock();
4682 if (breakall && !inquotes && newloc > startloc) {
4683 recordregion(startloc, newloc, 0);
4694 if (flag & EXP_VARTILDE2) {
4698 flag |= EXP_VARTILDE2;
4703 * sort of a hack - expand tildes in variable
4704 * assignments (after the first '=' and after ':'s).
4713 case CTLENDVAR: /* ??? */
4716 /* "$@" syntax adherence hack */
4719 !memcmp(p, dolatstr, DOLATSTRLEN) &&
4720 (p[4] == CTLQUOTEMARK || (
4721 p[4] == CTLENDVAR &&
4722 p[5] == CTLQUOTEMARK
4725 p = evalvar(p + 1, flag) + 1;
4728 inquotes = !inquotes;
4741 p = evalvar(p, flag);
4745 case CTLBACKQ|CTLQUOTE:
4746 expbackq(argbackq->n, c, quotes);
4747 argbackq = argbackq->next;
4749 #ifdef CONFIG_ASH_MATH_SUPPORT
4762 exptilde(char *startp, char *p, int flag)
4768 int quotes = flag & (EXP_FULL | EXP_CASE);
4773 while ((c = *++p) != '\0') {
4780 if (flag & EXP_VARTILDE)
4790 if (*name == '\0') {
4791 home = lookupvar(homestr);
4793 if ((pw = getpwnam(name)) == NULL)
4797 if (!home || !*home)
4800 startloc = expdest - (char *)stackblock();
4801 strtodest(home, SQSYNTAX, quotes);
4802 recordregion(startloc, expdest - (char *)stackblock(), 0);
4811 removerecordregions(int endoff)
4813 if (ifslastp == NULL)
4816 if (ifsfirst.endoff > endoff) {
4817 while (ifsfirst.next != NULL) {
4818 struct ifsregion *ifsp;
4820 ifsp = ifsfirst.next->next;
4821 ckfree(ifsfirst.next);
4822 ifsfirst.next = ifsp;
4825 if (ifsfirst.begoff > endoff)
4828 ifslastp = &ifsfirst;
4829 ifsfirst.endoff = endoff;
4834 ifslastp = &ifsfirst;
4835 while (ifslastp->next && ifslastp->next->begoff < endoff)
4836 ifslastp=ifslastp->next;
4837 while (ifslastp->next != NULL) {
4838 struct ifsregion *ifsp;
4840 ifsp = ifslastp->next->next;
4841 ckfree(ifslastp->next);
4842 ifslastp->next = ifsp;
4845 if (ifslastp->endoff > endoff)
4846 ifslastp->endoff = endoff;
4850 #ifdef CONFIG_ASH_MATH_SUPPORT
4852 * Expand arithmetic expression. Backup to start of expression,
4853 * evaluate, place result in (backed up) result, adjust string position.
4866 * This routine is slightly over-complicated for
4867 * efficiency. Next we scan backwards looking for the
4868 * start of arithmetic.
4870 start = stackblock();
4877 while (*p != CTLARI) {
4881 sh_error("missing CTLARI (shouldn't happen)");
4886 esc = esclen(start, p);
4896 removerecordregions(begoff);
4905 len = cvtnum(dash_arith(p + 2));
4908 recordregion(begoff, begoff + len, 0);
4913 * Expand stuff in backwards quotes.
4917 expbackq(union node *cmd, int quoted, int quotes)
4925 int syntax = quoted? DQSYNTAX : BASESYNTAX;
4926 struct stackmark smark;
4929 setstackmark(&smark);
4931 startloc = dest - (char *)stackblock();
4933 evalbackcmd(cmd, (struct backcmd *) &in);
4934 popstackmark(&smark);
4941 memtodest(p, i, syntax, quotes);
4945 i = safe_read(in.fd, buf, sizeof buf);
4946 TRACE(("expbackq: read returns %d\n", i));
4956 back_exitstatus = waitforjob(in.jp);
4960 /* Eat all trailing newlines */
4962 for (; dest > (char *)stackblock() && dest[-1] == '\n';)
4967 recordregion(startloc, dest - (char *)stackblock(), 0);
4968 TRACE(("evalbackq: size=%d: \"%.*s\"\n",
4969 (dest - (char *)stackblock()) - startloc,
4970 (dest - (char *)stackblock()) - startloc,
4971 stackblock() + startloc));
4976 scanleft(char *startp, char *rmesc, char *rmescend, char *str, int quotes,
4987 const char *s = loc2;
4993 match = pmatch(str, s);
4997 if (quotes && *loc == CTLESC)
5007 scanright(char *startp, char *rmesc, char *rmescend, char *str, int quotes,
5014 for (loc = str - 1, loc2 = rmescend; loc >= startp; loc2--) {
5017 const char *s = loc2;
5022 match = pmatch(str, s);
5029 esc = esclen(startp, loc);
5041 subevalvar(char *p, char *str, int strloc, int subtype, int startloc, int varflags, int quotes)
5045 int saveherefd = herefd;
5046 struct nodelist *saveargbackq = argbackq;
5048 char *rmesc, *rmescend;
5050 char *(*scan)(char *, char *, char *, char *, int , int);
5053 argstr(p, subtype != VSASSIGN && subtype != VSQUESTION ? EXP_CASE : 0);
5054 STPUTC('\0', expdest);
5055 herefd = saveherefd;
5056 argbackq = saveargbackq;
5057 startp = stackblock() + startloc;
5061 setvar(str, startp, 0);
5062 amount = startp - expdest;
5063 STADJUST(amount, expdest);
5067 varunset(p, str, startp, varflags);
5071 subtype -= VSTRIMRIGHT;
5073 if (subtype < 0 || subtype > 3)
5078 rmescend = stackblock() + strloc;
5080 rmesc = _rmescapes(startp, RMESCAPE_ALLOC | RMESCAPE_GROW);
5081 if (rmesc != startp) {
5083 startp = stackblock() + startloc;
5087 str = stackblock() + strloc;
5088 preglob(str, varflags & VSQUOTE, 0);
5090 /* zero = subtype == VSTRIMLEFT || subtype == VSTRIMLEFTMAX */
5091 zero = subtype >> 1;
5092 /* VSTRIMLEFT/VSTRIMRIGHTMAX -> scanleft */
5093 scan = (subtype & 1) ^ zero ? scanleft : scanright;
5095 loc = scan(startp, rmesc, rmescend, str, quotes, zero);
5098 memmove(startp, loc, str - loc);
5099 loc = startp + (str - loc) - 1;
5102 amount = loc - expdest;
5103 STADJUST(amount, expdest);
5110 * Expand a variable, and return a pointer to the next character in the
5114 evalvar(char *p, int flag)
5127 quotes = flag & (EXP_FULL | EXP_CASE);
5129 subtype = varflags & VSTYPE;
5130 quoted = varflags & VSQUOTE;
5132 easy = (!quoted || (*var == '@' && shellparam.nparam));
5133 startloc = expdest - (char *)stackblock();
5134 p = strchr(p, '=') + 1;
5137 varlen = varvalue(var, varflags, flag);
5138 if (varflags & VSNUL)
5141 if (subtype == VSPLUS) {
5142 varlen = -1 - varlen;
5146 if (subtype == VSMINUS) {
5150 p, flag | EXP_TILDE |
5151 (quoted ? EXP_QWORD : EXP_WORD)
5160 if (subtype == VSASSIGN || subtype == VSQUESTION) {
5162 if (subevalvar(p, var, 0, subtype, startloc,
5166 * Remove any recorded regions beyond
5169 removerecordregions(startloc);
5179 if (varlen < 0 && uflag)
5180 varunset(p, var, 0, 0);
5182 if (subtype == VSLENGTH) {
5183 cvtnum(varlen > 0 ? varlen : 0);
5187 if (subtype == VSNORMAL) {
5191 recordregion(startloc, expdest - (char *)stackblock(), quoted);
5200 case VSTRIMRIGHTMAX:
5209 * Terminate the string and start recording the pattern
5212 STPUTC('\0', expdest);
5213 patloc = expdest - (char *)stackblock();
5214 if (subevalvar(p, NULL, patloc, subtype,
5215 startloc, varflags, quotes) == 0) {
5216 int amount = expdest - (
5217 (char *)stackblock() + patloc - 1
5219 STADJUST(-amount, expdest);
5221 /* Remove any recorded regions beyond start of variable */
5222 removerecordregions(startloc);
5227 if (subtype != VSNORMAL) { /* skip to end of alternative */
5230 if ((c = *p++) == CTLESC)
5232 else if (c == CTLBACKQ || c == (CTLBACKQ|CTLQUOTE)) {
5234 argbackq = argbackq->next;
5235 } else if (c == CTLVAR) {
5236 if ((*p++ & VSTYPE) != VSNORMAL)
5238 } else if (c == CTLENDVAR) {
5249 * Put a string on the stack.
5253 memtodest(const char *p, size_t len, int syntax, int quotes) {
5256 q = makestrspace(len * 2, q);
5262 if (quotes && (SIT(c, syntax) == CCTL || SIT(c, syntax) == CBACK))
5272 strtodest(const char *p, int syntax, int quotes)
5274 memtodest(p, strlen(p), syntax, quotes);
5279 * Add the value of a specialized variable to the stack string.
5283 varvalue(char *name, int varflags, int flags)
5293 int quoted = varflags & VSQUOTE;
5294 int subtype = varflags & VSTYPE;
5295 int quotes = flags & (EXP_FULL | EXP_CASE);
5297 if (quoted && (flags & EXP_FULL))
5298 sep = 1 << CHAR_BIT;
5300 syntax = quoted ? DQSYNTAX : BASESYNTAX;
5309 num = shellparam.nparam;
5319 p = makestrspace(NOPTS, expdest);
5320 for (i = NOPTS - 1; i >= 0; i--) {
5322 USTPUTC(optletters(i), p);
5333 sep = ifsset() ? ifsval()[0] : ' ';
5334 if (quotes && (SIT(sep, syntax) == CCTL || SIT(sep, syntax) == CBACK))
5337 if (!(ap = shellparam.p))
5339 while ((p = *ap++)) {
5342 partlen = strlen(p);
5345 if (!(subtype == VSPLUS || subtype == VSLENGTH))
5346 memtodest(p, partlen, syntax, quotes);
5352 if (subtype == VSPLUS || subtype == VSLENGTH) {
5374 if (num < 0 || num > shellparam.nparam)
5376 p = num ? shellparam.p[num - 1] : arg0;
5379 p = lookupvar(name);
5385 if (!(subtype == VSPLUS || subtype == VSLENGTH))
5386 memtodest(p, len, syntax, quotes);
5390 if (subtype == VSPLUS || subtype == VSLENGTH)
5391 STADJUST(-len, expdest);
5397 * Record the fact that we have to scan this region of the
5398 * string for IFS characters.
5402 recordregion(int start, int end, int nulonly)
5404 struct ifsregion *ifsp;
5406 if (ifslastp == NULL) {
5410 ifsp = (struct ifsregion *)ckmalloc(sizeof (struct ifsregion));
5412 ifslastp->next = ifsp;
5416 ifslastp->begoff = start;
5417 ifslastp->endoff = end;
5418 ifslastp->nulonly = nulonly;
5423 * Break the argument string into pieces based upon IFS and add the
5424 * strings to the argument list. The regions of the string to be
5425 * searched for IFS characters have been stored by recordregion.
5428 ifsbreakup(char *string, struct arglist *arglist)
5430 struct ifsregion *ifsp;
5435 const char *ifs, *realifs;
5441 if (ifslastp != NULL) {
5444 realifs = ifsset() ? ifsval() : defifs;
5447 p = string + ifsp->begoff;
5448 nulonly = ifsp->nulonly;
5449 ifs = nulonly ? nullstr : realifs;
5451 while (p < string + ifsp->endoff) {
5455 if (strchr(ifs, *p)) {
5457 ifsspc = (strchr(defifs, *p) != NULL);
5458 /* Ignore IFS whitespace at start */
5459 if (q == start && ifsspc) {
5465 sp = (struct strlist *)stalloc(sizeof *sp);
5467 *arglist->lastp = sp;
5468 arglist->lastp = &sp->next;
5472 if (p >= string + ifsp->endoff) {
5478 if (strchr(ifs, *p) == NULL ) {
5481 } else if (strchr(defifs, *p) == NULL) {
5497 } while ((ifsp = ifsp->next) != NULL);
5506 sp = (struct strlist *)stalloc(sizeof *sp);
5508 *arglist->lastp = sp;
5509 arglist->lastp = &sp->next;
5515 struct ifsregion *p;
5520 struct ifsregion *ifsp;
5526 ifsfirst.next = NULL;
5530 static void expmeta(char *, char *);
5531 static struct strlist *expsort(struct strlist *);
5532 static struct strlist *msort(struct strlist *, int);
5534 static char *expdir;
5538 expandmeta(struct strlist *str, int flag)
5540 static const char metachars[] = {
5543 /* TODO - EXP_REDIR */
5546 struct strlist **savelastp;
5552 if (!strpbrk(str->text, metachars))
5554 savelastp = exparg.lastp;
5557 p = preglob(str->text, 0, RMESCAPE_ALLOC | RMESCAPE_HEAP);
5559 int i = strlen(str->text);
5560 expdir = ckmalloc(i < 2048 ? 2048 : i); /* XXX */
5568 if (exparg.lastp == savelastp) {
5573 *exparg.lastp = str;
5574 rmescapes(str->text);
5575 exparg.lastp = &str->next;
5577 *exparg.lastp = NULL;
5578 *savelastp = sp = expsort(*savelastp);
5579 while (sp->next != NULL)
5581 exparg.lastp = &sp->next;
5588 * Add a file name to the list.
5592 addfname(const char *name)
5596 sp = (struct strlist *)stalloc(sizeof *sp);
5597 sp->text = sstrdup(name);
5599 exparg.lastp = &sp->next;
5604 * Do metacharacter (i.e. *, ?, [...]) expansion.
5608 expmeta(char *enddir, char *name)
5623 for (p = name; *p; p++) {
5624 if (*p == '*' || *p == '?')
5626 else if (*p == '[') {
5633 if (*q == '/' || *q == '\0')
5640 } else if (*p == '\\')
5642 else if (*p == '/') {
5649 if (metaflag == 0) { /* we've reached the end of the file name */
5650 if (enddir != expdir)
5658 if (metaflag == 0 || lstat(expdir, &statb) >= 0)
5669 } while (p < start);
5671 if (enddir == expdir) {
5673 } else if (enddir == expdir + 1 && *expdir == '/') {
5679 if ((dirp = opendir(cp)) == NULL)
5681 if (enddir != expdir)
5683 if (*endname == 0) {
5695 while (! intpending && (dp = readdir(dirp)) != NULL) {
5696 if (dp->d_name[0] == '.' && ! matchdot)
5698 if (pmatch(start, dp->d_name)) {
5700 scopy(dp->d_name, enddir);
5703 for (p = enddir, cp = dp->d_name;
5704 (*p++ = *cp++) != '\0';)
5707 expmeta(p, endname);
5717 * Sort the results of file name expansion. It calculates the number of
5718 * strings to sort and then calls msort (short for merge sort) to do the
5722 static struct strlist *
5723 expsort(struct strlist *str)
5729 for (sp = str ; sp ; sp = sp->next)
5731 return msort(str, len);
5735 static struct strlist *
5736 msort(struct strlist *list, int len)
5738 struct strlist *p, *q = NULL;
5739 struct strlist **lpp;
5747 for (n = half ; --n >= 0 ; ) {
5751 q->next = NULL; /* terminate first half of list */
5752 q = msort(list, half); /* sort first half of list */
5753 p = msort(p, len - half); /* sort second half */
5756 #ifdef CONFIG_LOCALE_SUPPORT
5757 if (strcoll(p->text, q->text) < 0)
5759 if (strcmp(p->text, q->text) < 0)
5764 if ((p = *lpp) == NULL) {
5771 if ((q = *lpp) == NULL) {
5782 * Returns true if the pattern matches the string.
5786 patmatch(char *pattern, const char *string)
5788 return pmatch(preglob(pattern, 0, 0), string);
5793 * Remove any CTLESC characters from a string.
5797 _rmescapes(char *str, int flag)
5800 static const char qchars[] = { CTLESC, CTLQUOTEMARK, 0 };
5805 p = strpbrk(str, qchars);
5811 if (flag & RMESCAPE_ALLOC) {
5812 size_t len = p - str;
5813 size_t fulllen = len + strlen(p) + 1;
5815 if (flag & RMESCAPE_GROW) {
5816 r = makestrspace(fulllen, expdest);
5817 } else if (flag & RMESCAPE_HEAP) {
5818 r = ckmalloc(fulllen);
5820 r = stalloc(fulllen);
5824 q = mempcpy(q, str, len);
5827 inquotes = (flag & RMESCAPE_QUOTED) ^ RMESCAPE_QUOTED;
5828 globbing = flag & RMESCAPE_GLOB;
5829 notescaped = globbing;
5831 if (*p == CTLQUOTEMARK) {
5832 inquotes = ~inquotes;
5834 notescaped = globbing;
5838 /* naked back slash */
5844 if (notescaped && inquotes && *p != '/') {
5848 notescaped = globbing;
5853 if (flag & RMESCAPE_GROW) {
5855 STADJUST(q - r + 1, expdest);
5862 * See if a pattern matches in a case statement.
5866 casematch(union node *pattern, char *val)
5868 struct stackmark smark;
5871 setstackmark(&smark);
5872 argbackq = pattern->narg.backquote;
5873 STARTSTACKSTR(expdest);
5875 argstr(pattern->narg.text, EXP_TILDE | EXP_CASE);
5876 STACKSTRNUL(expdest);
5877 result = patmatch(stackblock(), val);
5878 popstackmark(&smark);
5891 expdest = makestrspace(32, expdest);
5892 #ifdef CONFIG_ASH_MATH_SUPPORT_64
5893 len = fmtstr(expdest, 32, "%lld", (long long) num);
5895 len = fmtstr(expdest, 32, "%ld", num);
5897 STADJUST(len, expdest);
5902 varunset(const char *end, const char *var, const char *umsg, int varflags)
5908 msg = "parameter not set";
5910 if (*end == CTLENDVAR) {
5911 if (varflags & VSNUL)
5916 sh_error("%.*s: %s%s", end - var - 1, var, msg, tail);
5923 * This implements the input routines used by the parser.
5926 #define EOF_NLEFT -99 /* value of parsenleft when EOF pushed back */
5928 static void pushfile(void);
5931 * Read a character from the script, returning PEOF on end of file.
5932 * Nul characters in the input are silently discarded.
5935 #define pgetc_as_macro() (--parsenleft >= 0? *parsenextc++ : preadbuffer())
5937 #ifdef CONFIG_ASH_OPTIMIZE_FOR_SIZE
5938 #define pgetc_macro() pgetc()
5942 return pgetc_as_macro();
5945 #define pgetc_macro() pgetc_as_macro()
5949 return pgetc_macro();
5955 * Same as pgetc(), but ignores PEOA.
5957 #ifdef CONFIG_ASH_ALIAS
5958 static int pgetc2(void)
5964 } while (c == PEOA);
5968 static inline int pgetc2(void)
5970 return pgetc_macro();
5975 * Read a line from the script.
5978 static inline char *
5979 pfgets(char *line, int len)
5985 while (--nleft > 0) {
6002 #ifdef CONFIG_FEATURE_COMMAND_EDITING
6003 #ifdef CONFIG_ASH_EXPAND_PRMT
6004 static char *cmdedit_prompt;
6006 static const char *cmdedit_prompt;
6008 static inline void putprompt(const char *s)
6010 #ifdef CONFIG_ASH_EXPAND_PRMT
6011 free(cmdedit_prompt);
6012 cmdedit_prompt = bb_xstrdup(s);
6018 static inline void putprompt(const char *s)
6028 char *buf = parsefile->buf;
6032 #ifdef CONFIG_FEATURE_COMMAND_EDITING
6033 if (!iflag || parsefile->fd)
6034 nr = safe_read(parsefile->fd, buf, BUFSIZ - 1);
6036 #ifdef CONFIG_FEATURE_COMMAND_TAB_COMPLETION
6037 cmdedit_path_lookup = pathval();
6039 nr = cmdedit_read_input((char *) cmdedit_prompt, buf);
6041 /* Ctrl+C presend */
6050 if(nr < 0 && errno == 0) {
6051 /* Ctrl+D presend */
6056 nr = safe_read(parsefile->fd, buf, BUFSIZ - 1);
6060 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
6061 int flags = fcntl(0, F_GETFL, 0);
6062 if (flags >= 0 && flags & O_NONBLOCK) {
6063 flags &=~ O_NONBLOCK;
6064 if (fcntl(0, F_SETFL, flags) >= 0) {
6065 out2str("sh: turning off NDELAY mode\n");
6075 * Refill the input buffer and return the next input character:
6077 * 1) If a string was pushed back on the input, pop it;
6078 * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading
6079 * from a string so we can't refill the buffer, return EOF.
6080 * 3) If the is more stuff in this buffer, use it else call read to fill it.
6081 * 4) Process input up to the next newline, deleting nul characters.
6091 while (parsefile->strpush) {
6092 #ifdef CONFIG_ASH_ALIAS
6093 if (parsenleft == -1 && parsefile->strpush->ap &&
6094 parsenextc[-1] != ' ' && parsenextc[-1] != '\t') {
6099 if (--parsenleft >= 0)
6100 return (*parsenextc++);
6102 if (parsenleft == EOF_NLEFT || parsefile->buf == NULL)
6109 if ((more = preadfd()) <= 0) {
6110 parselleft = parsenleft = EOF_NLEFT;
6117 /* delete nul characters */
6125 memmove(q, q + 1, more);
6129 parsenleft = q - parsenextc - 1;
6135 parsenleft = q - parsenextc - 1;
6147 out2str(parsenextc);
6152 return *parsenextc++;
6156 * Undo the last call to pgetc. Only one character may be pushed back.
6157 * PEOF may be pushed back.
6168 * Push a string back onto the input at this current parsefile level.
6169 * We handle aliases this way.
6172 pushstring(char *s, void *ap)
6179 /*dprintf("*** calling pushstring: %s, %d\n", s, len);*/
6180 if (parsefile->strpush) {
6181 sp = ckmalloc(sizeof (struct strpush));
6182 sp->prev = parsefile->strpush;
6183 parsefile->strpush = sp;
6185 sp = parsefile->strpush = &(parsefile->basestrpush);
6186 sp->prevstring = parsenextc;
6187 sp->prevnleft = parsenleft;
6188 #ifdef CONFIG_ASH_ALIAS
6189 sp->ap = (struct alias *)ap;
6191 ((struct alias *)ap)->flag |= ALIASINUSE;
6203 struct strpush *sp = parsefile->strpush;
6206 #ifdef CONFIG_ASH_ALIAS
6208 if (parsenextc[-1] == ' ' || parsenextc[-1] == '\t') {
6209 checkkwd |= CHKALIAS;
6211 if (sp->string != sp->ap->val) {
6214 sp->ap->flag &= ~ALIASINUSE;
6215 if (sp->ap->flag & ALIASDEAD) {
6216 unalias(sp->ap->name);
6220 parsenextc = sp->prevstring;
6221 parsenleft = sp->prevnleft;
6222 /*dprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/
6223 parsefile->strpush = sp->prev;
6224 if (sp != &(parsefile->basestrpush))
6230 * Set the input to take input from a file. If push is set, push the
6231 * old input onto the stack first.
6235 setinputfile(const char *fname, int flags)
6241 if ((fd = open(fname, O_RDONLY)) < 0) {
6242 if (flags & INPUT_NOFILE_OK)
6244 sh_error("Can't open %s", fname);
6247 fd2 = copyfd(fd, 10);
6250 sh_error("Out of file descriptors");
6253 setinputfd(fd, flags & INPUT_PUSH_FILE);
6261 * Like setinputfile, but takes an open file descriptor. Call this with
6266 setinputfd(int fd, int push)
6268 (void) fcntl(fd, F_SETFD, FD_CLOEXEC);
6274 if (parsefile->buf == NULL)
6275 parsefile->buf = ckmalloc(IBUFSIZ);
6276 parselleft = parsenleft = 0;
6282 * Like setinputfile, but takes input from a string.
6286 setinputstring(char *string)
6290 parsenextc = string;
6291 parsenleft = strlen(string);
6292 parsefile->buf = NULL;
6299 * To handle the "." command, a stack of input files is used. Pushfile
6300 * adds a new entry to the stack and popfile restores the previous level.
6306 struct parsefile *pf;
6308 parsefile->nleft = parsenleft;
6309 parsefile->lleft = parselleft;
6310 parsefile->nextc = parsenextc;
6311 parsefile->linno = plinno;
6312 pf = (struct parsefile *)ckmalloc(sizeof (struct parsefile));
6313 pf->prev = parsefile;
6316 pf->basestrpush.prev = NULL;
6324 struct parsefile *pf = parsefile;
6333 parsefile = pf->prev;
6335 parsenleft = parsefile->nleft;
6336 parselleft = parsefile->lleft;
6337 parsenextc = parsefile->nextc;
6338 plinno = parsefile->linno;
6344 * Return to top level.
6350 while (parsefile != &basepf)
6356 * Close the file(s) that the shell is reading commands from. Called
6357 * after a fork is done.
6364 if (parsefile->fd > 0) {
6365 close(parsefile->fd);
6372 /* mode flags for set_curjob */
6373 #define CUR_DELETE 2
6374 #define CUR_RUNNING 1
6375 #define CUR_STOPPED 0
6377 /* mode flags for dowait */
6378 #define DOWAIT_NORMAL 0
6379 #define DOWAIT_BLOCK 1
6382 static struct job *jobtab;
6384 static unsigned njobs;
6386 /* pgrp of shell on invocation */
6387 static int initialpgrp;
6388 static int ttyfd = -1;
6391 static struct job *curjob;
6392 /* number of presumed living untracked jobs */
6395 static void set_curjob(struct job *, unsigned);
6397 static int restartjob(struct job *, int);
6398 static void xtcsetpgrp(int, pid_t);
6399 static char *commandtext(union node *);
6400 static void cmdlist(union node *, int);
6401 static void cmdtxt(union node *);
6402 static void cmdputs(const char *);
6403 static void showpipe(struct job *, FILE *);
6405 static int sprint_status(char *, int, int);
6406 static void freejob(struct job *);
6407 static struct job *getjob(const char *, int);
6408 static struct job *growjobtab(void);
6409 static void forkchild(struct job *, union node *, int);
6410 static void forkparent(struct job *, union node *, int, pid_t);
6411 static int dowait(int, struct job *);
6412 static int getstatus(struct job *);
6415 set_curjob(struct job *jp, unsigned mode)
6418 struct job **jpp, **curp;
6420 /* first remove from list */
6421 jpp = curp = &curjob;
6426 jpp = &jp1->prev_job;
6428 *jpp = jp1->prev_job;
6430 /* Then re-insert in correct position */
6438 /* job being deleted */
6441 /* newly created job or backgrounded job,
6442 put after all stopped jobs. */
6446 if (!jp1 || jp1->state != JOBSTOPPED)
6449 jpp = &jp1->prev_job;
6455 /* newly stopped job - becomes curjob */
6456 jp->prev_job = *jpp;
6464 * Turn job control on and off.
6466 * Note: This code assumes that the third arg to ioctl is a character
6467 * pointer, which is true on Berkeley systems but not System V. Since
6468 * System V doesn't have job control yet, this isn't a problem now.
6470 * Called with interrupts off.
6479 if (on == jobctl || rootshell == 0)
6483 ofd = fd = open(_PATH_TTY, O_RDWR);
6486 while (!isatty(fd) && --fd >= 0)
6489 fd = fcntl(fd, F_DUPFD, 10);
6493 fcntl(fd, F_SETFD, FD_CLOEXEC);
6494 do { /* while we are in the background */
6495 if ((pgrp = tcgetpgrp(fd)) < 0) {
6497 sh_warnx("can't access tty; job control turned off");
6501 if (pgrp == getpgrp())
6512 xtcsetpgrp(fd, pgrp);
6514 /* turning job control off */
6517 xtcsetpgrp(fd, pgrp);
6531 killcmd(int argc, char **argv)
6542 "Usage: kill [-s sigspec | -signum | -sigspec] [pid | job]... or\n"
6543 "kill -l [exitstatus]"
6547 if (**++argv == '-') {
6548 signo = decode_signal(*argv + 1, 1);
6552 while ((c = nextopt("ls:")) != '\0')
6562 signo = decode_signal(optionarg, 1);
6565 "invalid signal number or name: %s",
6576 if (!list && signo < 0)
6579 if ((signo < 0 || !*argv) ^ list) {
6587 for (i = 1; i < NSIG; i++) {
6588 name = u_signal_names(0, &i, 1);
6590 out1fmt(snlfmt, name);
6594 name = u_signal_names(*argptr, &signo, -1);
6596 out1fmt(snlfmt, name);
6598 sh_error("invalid signal number or exit status: %s", *argptr);
6604 if (**argv == '%') {
6605 jp = getjob(*argv, 0);
6606 pid = -jp->ps[0].pid;
6608 pid = **argv == '-' ?
6609 -number(*argv + 1) : number(*argv);
6611 if (kill(pid, signo) != 0) {
6612 sh_warnx("(%d) - %m", pid);
6621 #if defined(JOBS) || defined(DEBUG)
6623 jobno(const struct job *jp)
6625 return jp - jobtab + 1;
6631 fgcmd(int argc, char **argv)
6638 mode = (**argv == 'f') ? FORK_FG : FORK_BG;
6643 jp = getjob(*argv, 1);
6644 if (mode == FORK_BG) {
6645 set_curjob(jp, CUR_RUNNING);
6646 fprintf(out, "[%d] ", jobno(jp));
6648 outstr(jp->ps->cmd, out);
6650 retval = restartjob(jp, mode);
6651 } while (*argv && *++argv);
6655 static int bgcmd(int, char **) __attribute__((__alias__("fgcmd")));
6659 restartjob(struct job *jp, int mode)
6661 struct procstat *ps;
6667 if (jp->state == JOBDONE)
6669 jp->state = JOBRUNNING;
6671 if (mode == FORK_FG)
6672 xtcsetpgrp(ttyfd, pgid);
6673 killpg(pgid, SIGCONT);
6677 if (WIFSTOPPED(ps->status)) {
6680 } while (ps++, --i);
6682 status = (mode == FORK_FG) ? waitforjob(jp) : 0;
6689 sprint_status(char *s, int status, int sigonly)
6695 if (!WIFEXITED(status)) {
6697 if (WIFSTOPPED(status))
6698 st = WSTOPSIG(status);
6701 st = WTERMSIG(status);
6703 if (st == SIGINT || st == SIGPIPE)
6706 if (WIFSTOPPED(status))
6711 col = fmtstr(s, 32, strsignal(st));
6712 if (WCOREDUMP(status)) {
6713 col += fmtstr(s + col, 16, " (core dumped)");
6715 } else if (!sigonly) {
6716 st = WEXITSTATUS(status);
6718 col = fmtstr(s, 16, "Done(%d)", st);
6720 col = fmtstr(s, 16, "Done");
6729 showjob(FILE *out, struct job *jp, int mode)
6731 struct procstat *ps;
6732 struct procstat *psend;
6739 if (mode & SHOW_PGID) {
6740 /* just output process (group) id of pipeline */
6741 fprintf(out, "%d\n", ps->pid);
6745 col = fmtstr(s, 16, "[%d] ", jobno(jp));
6750 else if (curjob && jp == curjob->prev_job)
6753 if (mode & SHOW_PID)
6754 col += fmtstr(s + col, 16, "%d ", ps->pid);
6756 psend = ps + jp->nprocs;
6758 if (jp->state == JOBRUNNING) {
6759 scopy("Running", s + col);
6760 col += strlen("Running");
6762 int status = psend[-1].status;
6764 if (jp->state == JOBSTOPPED)
6765 status = jp->stopstatus;
6767 col += sprint_status(s + col, status, 0);
6773 /* for each process */
6774 col = fmtstr(s, 48, " |\n%*c%d ", indent, ' ', ps->pid) - 3;
6777 fprintf(out, "%s%*c%s",
6778 s, 33 - col >= 0 ? 33 - col : 0, ' ', ps->cmd
6780 if (!(mode & SHOW_PID)) {
6784 if (++ps == psend) {
6785 outcslow('\n', out);
6792 if (jp->state == JOBDONE) {
6793 TRACE(("showjob: freeing job %d\n", jobno(jp)));
6800 jobscmd(int argc, char **argv)
6806 while ((m = nextopt("lp")))
6816 showjob(out, getjob(*argv,0), mode);
6819 showjobs(out, mode);
6826 * Print a list of jobs. If "change" is nonzero, only print jobs whose
6827 * statuses have changed since the last call to showjobs.
6831 showjobs(FILE *out, int mode)
6835 TRACE(("showjobs(%x) called\n", mode));
6837 /* If not even one one job changed, there is nothing to do */
6838 while (dowait(DOWAIT_NORMAL, NULL) > 0)
6841 for (jp = curjob; jp; jp = jp->prev_job) {
6842 if (!(mode & SHOW_CHANGED) || jp->changed)
6843 showjob(out, jp, mode);
6849 * Mark a job structure as unused.
6853 freejob(struct job *jp)
6855 struct procstat *ps;
6859 for (i = jp->nprocs, ps = jp->ps ; --i >= 0 ; ps++) {
6860 if (ps->cmd != nullstr)
6863 if (jp->ps != &jp->ps0)
6866 set_curjob(jp, CUR_DELETE);
6872 waitcmd(int argc, char **argv)
6885 /* wait for all jobs */
6890 /* no running procs */
6893 if (jp->state == JOBRUNNING)
6898 dowait(DOWAIT_BLOCK, 0);
6904 if (**argv != '%') {
6905 pid_t pid = number(*argv);
6909 if (job->ps[job->nprocs - 1].pid == pid)
6911 job = job->prev_job;
6917 job = getjob(*argv, 0);
6918 /* loop until process terminated or stopped */
6919 while (job->state == JOBRUNNING)
6920 dowait(DOWAIT_BLOCK, 0);
6922 retval = getstatus(job);
6933 * Convert a job name to a job structure.
6937 getjob(const char *name, int getctl)
6941 const char *err_msg = "No such job: %s";
6945 char *(*match)(const char *, const char *);
6960 if (c == '+' || c == '%') {
6962 err_msg = "No current job";
6964 } else if (c == '-') {
6967 err_msg = "No previous job";
6978 jp = jobtab + num - 1;
6995 if (match(jp->ps[0].cmd, p)) {
6999 err_msg = "%s: ambiguous";
7006 err_msg = "job %s not created under job control";
7007 if (getctl && jp->jobctl == 0)
7012 sh_error(err_msg, name);
7017 * Return a new job structure.
7018 * Called with interrupts off.
7022 makejob(union node *node, int nprocs)
7027 for (i = njobs, jp = jobtab ; ; jp++) {
7034 if (jp->state != JOBDONE || !jp->waited)
7043 memset(jp, 0, sizeof(*jp));
7048 jp->prev_job = curjob;
7053 jp->ps = ckmalloc(nprocs * sizeof (struct procstat));
7055 TRACE(("makejob(0x%lx, %d) returns %%%d\n", (long)node, nprocs,
7065 struct job *jp, *jq;
7067 len = njobs * sizeof(*jp);
7069 jp = ckrealloc(jq, len + 4 * sizeof(*jp));
7071 offset = (char *)jp - (char *)jq;
7073 /* Relocate pointers */
7076 jq = (struct job *)((char *)jq + l);
7080 #define joff(p) ((struct job *)((char *)(p) + l))
7081 #define jmove(p) (p) = (void *)((char *)(p) + offset)
7082 if (xlikely(joff(jp)->ps == &jq->ps0))
7083 jmove(joff(jp)->ps);
7084 if (joff(jp)->prev_job)
7085 jmove(joff(jp)->prev_job);
7095 jp = (struct job *)((char *)jp + len);
7099 } while (--jq >= jp);
7105 * Fork off a subshell. If we are doing job control, give the subshell its
7106 * own process group. Jp is a job structure that the job is to be added to.
7107 * N is the command that will be evaluated by the child. Both jp and n may
7108 * be NULL. The mode parameter can be one of the following:
7109 * FORK_FG - Fork off a foreground process.
7110 * FORK_BG - Fork off a background process.
7111 * FORK_NOJOB - Like FORK_FG, but don't give the process its own
7112 * process group even if job control is on.
7114 * When job control is turned off, background processes have their standard
7115 * input redirected to /dev/null (except for the second and later processes
7118 * Called with interrupts off.
7122 forkchild(struct job *jp, union node *n, int mode)
7126 TRACE(("Child shell %d\n", getpid()));
7133 /* do job control only in root shell */
7135 if (mode != FORK_NOJOB && jp->jobctl && !oldlvl) {
7138 if (jp->nprocs == 0)
7141 pgrp = jp->ps[0].pid;
7142 /* This can fail because we are doing it in the parent also */
7143 (void)setpgid(0, pgrp);
7144 if (mode == FORK_FG)
7145 xtcsetpgrp(ttyfd, pgrp);
7150 if (mode == FORK_BG) {
7153 if (jp->nprocs == 0) {
7155 if (open(_PATH_DEVNULL, O_RDONLY) != 0)
7156 sh_error("Can't open %s", _PATH_DEVNULL);
7159 if (!oldlvl && iflag) {
7164 for (jp = curjob; jp; jp = jp->prev_job)
7170 forkparent(struct job *jp, union node *n, int mode, pid_t pid)
7172 TRACE(("In parent shell: child = %d\n", pid));
7174 while (jobless && dowait(DOWAIT_NORMAL, 0) > 0);
7179 if (mode != FORK_NOJOB && jp->jobctl) {
7182 if (jp->nprocs == 0)
7185 pgrp = jp->ps[0].pid;
7186 /* This can fail because we are doing it in the child also */
7187 (void)setpgid(pid, pgrp);
7190 if (mode == FORK_BG) {
7191 backgndpid = pid; /* set $! */
7192 set_curjob(jp, CUR_RUNNING);
7195 struct procstat *ps = &jp->ps[jp->nprocs++];
7201 ps->cmd = commandtext(n);
7207 forkshell(struct job *jp, union node *n, int mode)
7211 TRACE(("forkshell(%%%d, %p, %d) called\n", jobno(jp), n, mode));
7214 TRACE(("Fork failed, errno=%d", errno));
7217 sh_error("Cannot fork");
7220 forkchild(jp, n, mode);
7222 forkparent(jp, n, mode, pid);
7227 * Wait for job to finish.
7229 * Under job control we have the problem that while a child process is
7230 * running interrupts generated by the user are sent to the child but not
7231 * to the shell. This means that an infinite loop started by an inter-
7232 * active user may be hard to kill. With job control turned off, an
7233 * interactive user may place an interactive program inside a loop. If
7234 * the interactive program catches interrupts, the user doesn't want
7235 * these interrupts to also abort the loop. The approach we take here
7236 * is to have the shell ignore interrupt signals while waiting for a
7237 * foreground process to terminate, and then send itself an interrupt
7238 * signal if the child process was terminated by an interrupt signal.
7239 * Unfortunately, some programs want to do a bit of cleanup and then
7240 * exit on interrupt; unless these processes terminate themselves by
7241 * sending a signal to themselves (instead of calling exit) they will
7242 * confuse this approach.
7244 * Called with interrupts off.
7248 waitforjob(struct job *jp)
7252 TRACE(("waitforjob(%%%d) called\n", jobno(jp)));
7253 while (jp->state == JOBRUNNING) {
7254 dowait(DOWAIT_BLOCK, jp);
7259 xtcsetpgrp(ttyfd, rootpid);
7261 * This is truly gross.
7262 * If we're doing job control, then we did a TIOCSPGRP which
7263 * caused us (the shell) to no longer be in the controlling
7264 * session -- so we wouldn't have seen any ^C/SIGINT. So, we
7265 * intuit from the subprocess exit status whether a SIGINT
7266 * occurred, and if so interrupt ourselves. Yuck. - mycroft
7271 if (jp->state == JOBDONE)
7279 * Do a wait system call. If job control is compiled in, we accept
7280 * stopped processes. If block is zero, we return a value of zero
7281 * rather than blocking.
7283 * System V doesn't have a non-blocking wait system call. It does
7284 * have a SIGCLD signal that is sent to a process when one of it's
7285 * children dies. The obvious way to use SIGCLD would be to install
7286 * a handler for SIGCLD which simply bumped a counter when a SIGCLD
7287 * was received, and have waitproc bump another counter when it got
7288 * the status of a process. Waitproc would then know that a wait
7289 * system call would not block if the two counters were different.
7290 * This approach doesn't work because if a process has children that
7291 * have not been waited for, System V will send it a SIGCLD when it
7292 * installs a signal handler for SIGCLD. What this means is that when
7293 * a child exits, the shell will be sent SIGCLD signals continuously
7294 * until is runs out of stack space, unless it does a wait call before
7295 * restoring the signal handler. The code below takes advantage of
7296 * this (mis)feature by installing a signal handler for SIGCLD and
7297 * then checking to see whether it was called. If there are any
7298 * children to be waited for, it will be.
7300 * If neither SYSV nor BSD is defined, we don't implement nonblocking
7301 * waits at all. In this case, the user will not be informed when
7302 * a background process until the next time she runs a real program
7303 * (as opposed to running a builtin command or just typing return),
7304 * and the jobs command may give out of date information.
7308 waitproc(int block, int *status)
7318 return wait3(status, flags, (struct rusage *)NULL);
7322 * Wait for a process to terminate.
7326 dowait(int block, struct job *job)
7331 struct job *thisjob;
7334 TRACE(("dowait(%d) called\n", block));
7335 pid = waitproc(block, &status);
7336 TRACE(("wait returns pid %d, status=%d\n", pid, status));
7341 for (jp = curjob; jp; jp = jp->prev_job) {
7342 struct procstat *sp;
7343 struct procstat *spend;
7344 if (jp->state == JOBDONE)
7347 spend = jp->ps + jp->nprocs;
7350 if (sp->pid == pid) {
7351 TRACE(("Job %d: changing status of proc %d from 0x%x to 0x%x\n", jobno(jp), pid, sp->status, status));
7352 sp->status = status;
7355 if (sp->status == -1)
7358 if (state == JOBRUNNING)
7360 if (WIFSTOPPED(sp->status)) {
7361 jp->stopstatus = sp->status;
7365 } while (++sp < spend);
7370 if (!WIFSTOPPED(status))
7377 if (state != JOBRUNNING) {
7378 thisjob->changed = 1;
7380 if (thisjob->state != state) {
7381 TRACE(("Job %d: changing state from %d to %d\n", jobno(thisjob), thisjob->state, state));
7382 thisjob->state = state;
7384 if (state == JOBSTOPPED) {
7385 set_curjob(thisjob, CUR_STOPPED);
7394 if (thisjob && thisjob == job) {
7398 len = sprint_status(s, status, 1);
7410 * return 1 if there are stopped jobs, otherwise 0
7423 if (jp && jp->state == JOBSTOPPED) {
7424 out2str("You have stopped jobs.\n");
7434 * Return a string identifying a command (to be printed by the
7439 static char *cmdnextc;
7442 commandtext(union node *n)
7446 STARTSTACKSTR(cmdnextc);
7448 name = stackblock();
7449 TRACE(("commandtext: name %p, end %p\n\t\"%s\"\n",
7450 name, cmdnextc, cmdnextc));
7451 return savestr(name);
7455 cmdtxt(union node *n)
7458 struct nodelist *lp;
7470 lp = n->npipe.cmdlist;
7488 cmdtxt(n->nbinary.ch1);
7504 cmdtxt(n->nif.test);
7507 if (n->nif.elsepart) {
7510 n = n->nif.elsepart;
7526 cmdtxt(n->nbinary.ch1);
7536 cmdputs(n->nfor.var);
7538 cmdlist(n->nfor.args, 1);
7543 cmdputs(n->narg.text);
7547 cmdlist(n->ncmd.args, 1);
7548 cmdlist(n->ncmd.redirect, 0);
7561 cmdputs(n->ncase.expr->narg.text);
7563 for (np = n->ncase.cases; np; np = np->nclist.next) {
7564 cmdtxt(np->nclist.pattern);
7566 cmdtxt(np->nclist.body);
7592 s[0] = n->nfile.fd + '0';
7596 if (n->type == NTOFD || n->type == NFROMFD) {
7597 s[0] = n->ndup.dupfd + '0';
7608 cmdlist(union node *np, int sep)
7610 for (; np; np = np->narg.next) {
7614 if (sep && np->narg.next)
7620 cmdputs(const char *s)
7622 const char *p, *str;
7623 char c, cc[2] = " ";
7627 static const char vstype[VSTYPE + 1][4] = {
7628 "", "}", "-", "+", "?", "=",
7629 "%", "%%", "#", "##"
7631 nextc = makestrspace((strlen(s) + 1) * 8, cmdnextc);
7633 while ((c = *p++) != 0) {
7641 if ((subtype & VSTYPE) == VSLENGTH)
7645 if (!(subtype & VSQUOTE) != !(quoted & 1)) {
7652 str = "\"}" + !(quoted & 1);
7659 case CTLBACKQ+CTLQUOTE:
7662 #ifdef CONFIG_ASH_MATH_SUPPORT
7677 if ((subtype & VSTYPE) != VSNORMAL)
7679 str = vstype[subtype & VSTYPE];
7680 if (subtype & VSNUL)
7689 /* These can only happen inside quotes */
7702 while ((c = *str++)) {
7707 USTPUTC('"', nextc);
7715 showpipe(struct job *jp, FILE *out)
7717 struct procstat *sp;
7718 struct procstat *spend;
7720 spend = jp->ps + jp->nprocs;
7721 for (sp = jp->ps + 1; sp < spend; sp++)
7722 fprintf(out, " | %s", sp->cmd);
7723 outcslow('\n', out);
7728 xtcsetpgrp(int fd, pid_t pgrp)
7730 if (tcsetpgrp(fd, pgrp))
7731 sh_error("Cannot set tty process group (%m)");
7736 getstatus(struct job *job) {
7740 status = job->ps[job->nprocs - 1].status;
7741 retval = WEXITSTATUS(status);
7742 if (!WIFEXITED(status)) {
7744 retval = WSTOPSIG(status);
7745 if (!WIFSTOPPED(status))
7748 /* XXX: limits number of signals */
7749 retval = WTERMSIG(status);
7751 if (retval == SIGINT)
7757 TRACE(("getstatus: job %d, nproc %d, status %x, retval %x\n",
7758 jobno(job), job->nprocs, status, retval));
7762 #ifdef CONFIG_ASH_MAIL
7766 * Routines to check for mail. (Perhaps make part of main.c?)
7769 #define MAXMBOXES 10
7771 /* times of mailboxes */
7772 static time_t mailtime[MAXMBOXES];
7773 /* Set if MAIL or MAILPATH is changed. */
7774 static int mail_var_path_changed;
7779 * Print appropriate message(s) if mail has arrived.
7780 * If mail_var_path_changed is set,
7781 * then the value of MAIL has mail_var_path_changed,
7782 * so we just update the values.
7792 struct stackmark smark;
7795 setstackmark(&smark);
7796 mpath = mpathset() ? mpathval() : mailval();
7797 for (mtp = mailtime; mtp < mailtime + MAXMBOXES; mtp++) {
7798 p = padvance(&mpath, nullstr);
7803 for (q = p ; *q ; q++);
7808 q[-1] = '\0'; /* delete trailing '/' */
7809 if (stat(p, &statb) < 0) {
7813 if (!mail_var_path_changed && statb.st_mtime != *mtp) {
7816 pathopt ? pathopt : "you have mail"
7819 *mtp = statb.st_mtime;
7821 mail_var_path_changed = 0;
7822 popstackmark(&smark);
7827 changemail(const char *val)
7829 mail_var_path_changed++;
7832 #endif /* CONFIG_ASH_MAIL */
7838 static short profile_buf[16384];
7842 static int isloginsh;
7844 static void read_profile(const char *);
7847 * Main routine. We initialize things, parse the arguments, execute
7848 * profiles if we're a login shell, and then call cmdloop to execute
7849 * commands. The setjmp call sets up the location to jump to when an
7850 * exception occurs. When an exception occurs the variable "state"
7851 * is used to figure out how far we had gotten.
7855 ash_main(int argc, char **argv)
7859 struct jmploc jmploc;
7860 struct stackmark smark;
7863 dash_errno = __errno_location();
7867 monitor(4, etext, profile_buf, sizeof profile_buf, 50);
7870 if (setjmp(jmploc.loc)) {
7880 if (e == EXEXIT || s == 0 || iflag == 0 || shlvl)
7884 outcslow('\n', stderr);
7886 popstackmark(&smark);
7887 FORCEINTON; /* enable interrupts */
7900 trputs("Shell args: "); trargs(argv);
7904 #ifdef CONFIG_ASH_RANDOM_SUPPORT
7905 rseed = rootpid + ((time_t)time((time_t *)0));
7908 setstackmark(&smark);
7909 procargs(argc, argv);
7910 #ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
7912 const char *hp = lookupvar("HISTFILE");
7915 hp = lookupvar("HOME");
7917 char *defhp = concat_path_file(hp, ".ash_history");
7918 setvar("HISTFILE", defhp, 0);
7924 if (argv[0] && argv[0][0] == '-')
7928 read_profile("/etc/profile");
7931 read_profile(".profile");
7937 getuid() == geteuid() && getgid() == getegid() &&
7941 if ((shinit = lookupvar("ENV")) != NULL && *shinit != '\0') {
7942 read_profile(shinit);
7948 evalstring(minusc, 0);
7950 if (sflag || minusc == NULL) {
7951 #ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
7953 const char *hp = lookupvar("HISTFILE");
7956 load_history ( hp );
7959 state4: /* XXX ??? - why isn't this before the "if" statement */
7967 extern void _mcleanup(void);
7977 * Read and execute commands. "Top" is nonzero for the top level command
7978 * loop; it turns on prompting if the shell is interactive.
7985 struct stackmark smark;
7989 TRACE(("cmdloop(%d) called\n", top));
7993 setstackmark(&smark);
7996 showjobs(stderr, SHOW_CHANGED);
8001 #ifdef CONFIG_ASH_MAIL
8005 n = parsecmd(inter);
8006 /* showtree(n); DEBUG */
8008 if (!top || numeof >= 50)
8010 if (!stoppedjobs()) {
8013 out2str("\nUse \"exit\" to leave shell.\n");
8016 } else if (nflag == 0) {
8017 job_warning = (job_warning == 2) ? 1 : 0;
8021 popstackmark(&smark);
8026 return skip & SKIPEVAL;
8035 * Read /etc/profile or .profile. Return on error.
8039 read_profile(const char *name)
8043 if (setinputfile(name, INPUT_PUSH_FILE | INPUT_NOFILE_OK) < 0)
8055 * Read a file containing shell functions.
8059 readcmdfile(char *name)
8061 setinputfile(name, INPUT_PUSH_FILE);
8068 * Take commands from a file. To be compatible we should do a path
8069 * search for the file, which is necessary to find sub-commands.
8072 static inline char *
8073 find_dot_file(char *name)
8076 const char *path = pathval();
8079 /* don't try this for absolute or relative paths */
8080 if (strchr(name, '/'))
8083 while ((fullname = padvance(&path, name)) != NULL) {
8084 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
8086 * Don't bother freeing here, since it will
8087 * be freed by the caller.
8091 stunalloc(fullname);
8094 /* not found in the PATH */
8095 sh_error(not_found_msg, name);
8099 static int dotcmd(int argc, char **argv)
8102 volatile struct shparam saveparam;
8105 for (sp = cmdenviron; sp; sp = sp->next)
8106 setvareq(bb_xstrdup(sp->text), VSTRFIXED | VTEXTFIXED);
8108 if (argc >= 2) { /* That's what SVR2 does */
8111 fullname = find_dot_file(argv[1]);
8114 saveparam = shellparam;
8115 shellparam.malloc = 0;
8116 shellparam.nparam = argc - 2;
8117 shellparam.p = argv + 2;
8120 setinputfile(fullname, INPUT_PUSH_FILE);
8121 commandname = fullname;
8126 freeparam(&shellparam);
8127 shellparam = saveparam;
8129 status = exitstatus;
8136 exitcmd(int argc, char **argv)
8141 exitstatus = number(argv[1]);
8146 #ifdef CONFIG_ASH_BUILTIN_ECHO
8148 echocmd(int argc, char **argv)
8150 return bb_echo(argc, argv);
8156 * Same for malloc, realloc, but returns an error when out of space.
8160 ckrealloc(pointer p, size_t nbytes)
8162 p = realloc(p, nbytes);
8164 sh_error(bb_msg_memory_exhausted);
8169 ckmalloc(size_t nbytes)
8171 return ckrealloc(NULL, nbytes);
8175 * Make a copy of a string in safe storage.
8179 savestr(const char *s)
8181 char *p = strdup(s);
8183 sh_error(bb_msg_memory_exhausted);
8189 * Parse trees for commands are allocated in lifo order, so we use a stack
8190 * to make this more efficient, and also to avoid all sorts of exception
8191 * handling code to handle interrupts in the middle of a parse.
8193 * The size 504 was chosen because the Ultrix malloc handles that size
8199 stalloc(size_t nbytes)
8204 aligned = SHELL_ALIGN(nbytes);
8205 if (aligned > stacknleft) {
8208 struct stack_block *sp;
8210 blocksize = aligned;
8211 if (blocksize < MINSIZE)
8212 blocksize = MINSIZE;
8213 len = sizeof(struct stack_block) - MINSIZE + blocksize;
8214 if (len < blocksize)
8215 sh_error(bb_msg_memory_exhausted);
8219 stacknxt = sp->space;
8220 stacknleft = blocksize;
8221 sstrend = stacknxt + blocksize;
8226 stacknxt += aligned;
8227 stacknleft -= aligned;
8233 stunalloc(pointer p)
8236 if (!p || (stacknxt < (char *)p) || ((char *)p < stackp->space)) {
8237 write(2, "stunalloc\n", 10);
8241 stacknleft += stacknxt - (char *)p;
8247 setstackmark(struct stackmark *mark)
8249 mark->stackp = stackp;
8250 mark->stacknxt = stacknxt;
8251 mark->stacknleft = stacknleft;
8252 mark->marknext = markp;
8258 popstackmark(struct stackmark *mark)
8260 struct stack_block *sp;
8263 markp = mark->marknext;
8264 while (stackp != mark->stackp) {
8269 stacknxt = mark->stacknxt;
8270 stacknleft = mark->stacknleft;
8271 sstrend = mark->stacknxt + mark->stacknleft;
8277 * When the parser reads in a string, it wants to stick the string on the
8278 * stack and only adjust the stack pointer when it knows how big the
8279 * string is. Stackblock (defined in stack.h) returns a pointer to a block
8280 * of space on top of the stack and stackblocklen returns the length of
8281 * this block. Growstackblock will grow this space by at least one byte,
8282 * possibly moving it (like realloc). Grabstackblock actually allocates the
8283 * part of the block that has been used.
8287 growstackblock(void)
8291 newlen = stacknleft * 2;
8292 if (newlen < stacknleft)
8293 sh_error(bb_msg_memory_exhausted);
8297 if (stacknxt == stackp->space && stackp != &stackbase) {
8298 struct stack_block *oldstackp;
8299 struct stackmark *xmark;
8300 struct stack_block *sp;
8301 struct stack_block *prevstackp;
8307 prevstackp = sp->prev;
8308 grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
8309 sp = ckrealloc((pointer)sp, grosslen);
8310 sp->prev = prevstackp;
8312 stacknxt = sp->space;
8313 stacknleft = newlen;
8314 sstrend = sp->space + newlen;
8317 * Stack marks pointing to the start of the old block
8318 * must be relocated to point to the new block
8321 while (xmark != NULL && xmark->stackp == oldstackp) {
8322 xmark->stackp = stackp;
8323 xmark->stacknxt = stacknxt;
8324 xmark->stacknleft = stacknleft;
8325 xmark = xmark->marknext;
8329 char *oldspace = stacknxt;
8330 int oldlen = stacknleft;
8331 char *p = stalloc(newlen);
8333 /* free the space we just allocated */
8334 stacknxt = memcpy(p, oldspace, oldlen);
8335 stacknleft += newlen;
8340 grabstackblock(size_t len)
8342 len = SHELL_ALIGN(len);
8348 * The following routines are somewhat easier to use than the above.
8349 * The user declares a variable of type STACKSTR, which may be declared
8350 * to be a register. The macro STARTSTACKSTR initializes things. Then
8351 * the user uses the macro STPUTC to add characters to the string. In
8352 * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
8353 * grown as necessary. When the user is done, she can just leave the
8354 * string there and refer to it using stackblock(). Or she can allocate
8355 * the space for it using grabstackstr(). If it is necessary to allow
8356 * someone else to use the stack temporarily and then continue to grow
8357 * the string, the user should use grabstack to allocate the space, and
8358 * then call ungrabstr(p) to return to the previous mode of operation.
8360 * USTPUTC is like STPUTC except that it doesn't check for overflow.
8361 * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
8362 * is space for at least one character.
8368 size_t len = stackblocksize();
8369 if (herefd >= 0 && len >= 1024) {
8370 bb_full_write(herefd, stackblock(), len);
8371 return stackblock();
8374 return stackblock() + len;
8378 * Called from CHECKSTRSPACE.
8382 makestrspace(size_t newlen, char *p)
8384 size_t len = p - stacknxt;
8385 size_t size = stackblocksize();
8390 size = stackblocksize();
8392 if (nleft >= newlen)
8396 return stackblock() + len;
8400 stnputs(const char *s, size_t n, char *p)
8402 p = makestrspace(n, p);
8403 p = mempcpy(p, s, n);
8408 stputs(const char *s, char *p)
8410 return stnputs(s, strlen(s), p);
8418 * number(s) Convert a string of digits to an integer.
8419 * is_number(s) Return true if s is a string of digits.
8423 * prefix -- see if pfx is a prefix of string.
8427 prefix(const char *string, const char *pfx)
8430 if (*pfx++ != *string++)
8433 return (char *) string;
8438 * Convert a string of digits to an integer, printing an error message on
8443 number(const char *s)
8447 sh_error(illnum, s);
8453 * Check for a valid number. This should be elsewhere.
8457 is_number(const char *p)
8462 } while (*++p != '\0');
8468 * Produce a possibly single quoted string suitable as input to the shell.
8469 * The return string is allocated on the stack.
8473 single_quote(const char *s) {
8482 len = strchrnul(s, '\'') - s;
8484 q = p = makestrspace(len + 3, p);
8487 q = mempcpy(q, s, len);
8493 len = strspn(s, "'");
8497 q = p = makestrspace(len + 3, p);
8500 q = mempcpy(q, s, len);
8509 return stackblock();
8513 * Like strdup but works with the ash stack.
8517 sstrdup(const char *p)
8519 size_t len = strlen(p) + 1;
8520 return memcpy(stalloc(len), p, len);
8525 calcsize(union node *n)
8529 funcblocksize += nodesize[n->type];
8532 calcsize(n->ncmd.redirect);
8533 calcsize(n->ncmd.args);
8534 calcsize(n->ncmd.assign);
8537 sizenodelist(n->npipe.cmdlist);
8542 calcsize(n->nredir.redirect);
8543 calcsize(n->nredir.n);
8550 calcsize(n->nbinary.ch2);
8551 calcsize(n->nbinary.ch1);
8554 calcsize(n->nif.elsepart);
8555 calcsize(n->nif.ifpart);
8556 calcsize(n->nif.test);
8559 funcstringsize += strlen(n->nfor.var) + 1;
8560 calcsize(n->nfor.body);
8561 calcsize(n->nfor.args);
8564 calcsize(n->ncase.cases);
8565 calcsize(n->ncase.expr);
8568 calcsize(n->nclist.body);
8569 calcsize(n->nclist.pattern);
8570 calcsize(n->nclist.next);
8574 sizenodelist(n->narg.backquote);
8575 funcstringsize += strlen(n->narg.text) + 1;
8576 calcsize(n->narg.next);
8583 calcsize(n->nfile.fname);
8584 calcsize(n->nfile.next);
8588 calcsize(n->ndup.vname);
8589 calcsize(n->ndup.next);
8593 calcsize(n->nhere.doc);
8594 calcsize(n->nhere.next);
8597 calcsize(n->nnot.com);
8604 sizenodelist(struct nodelist *lp)
8607 funcblocksize += SHELL_ALIGN(sizeof(struct nodelist));
8615 copynode(union node *n)
8622 funcblock = (char *) funcblock + nodesize[n->type];
8625 new->ncmd.redirect = copynode(n->ncmd.redirect);
8626 new->ncmd.args = copynode(n->ncmd.args);
8627 new->ncmd.assign = copynode(n->ncmd.assign);
8630 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
8631 new->npipe.backgnd = n->npipe.backgnd;
8636 new->nredir.redirect = copynode(n->nredir.redirect);
8637 new->nredir.n = copynode(n->nredir.n);
8644 new->nbinary.ch2 = copynode(n->nbinary.ch2);
8645 new->nbinary.ch1 = copynode(n->nbinary.ch1);
8648 new->nif.elsepart = copynode(n->nif.elsepart);
8649 new->nif.ifpart = copynode(n->nif.ifpart);
8650 new->nif.test = copynode(n->nif.test);
8653 new->nfor.var = nodesavestr(n->nfor.var);
8654 new->nfor.body = copynode(n->nfor.body);
8655 new->nfor.args = copynode(n->nfor.args);
8658 new->ncase.cases = copynode(n->ncase.cases);
8659 new->ncase.expr = copynode(n->ncase.expr);
8662 new->nclist.body = copynode(n->nclist.body);
8663 new->nclist.pattern = copynode(n->nclist.pattern);
8664 new->nclist.next = copynode(n->nclist.next);
8668 new->narg.backquote = copynodelist(n->narg.backquote);
8669 new->narg.text = nodesavestr(n->narg.text);
8670 new->narg.next = copynode(n->narg.next);
8677 new->nfile.fname = copynode(n->nfile.fname);
8678 new->nfile.fd = n->nfile.fd;
8679 new->nfile.next = copynode(n->nfile.next);
8683 new->ndup.vname = copynode(n->ndup.vname);
8684 new->ndup.dupfd = n->ndup.dupfd;
8685 new->ndup.fd = n->ndup.fd;
8686 new->ndup.next = copynode(n->ndup.next);
8690 new->nhere.doc = copynode(n->nhere.doc);
8691 new->nhere.fd = n->nhere.fd;
8692 new->nhere.next = copynode(n->nhere.next);
8695 new->nnot.com = copynode(n->nnot.com);
8698 new->type = n->type;
8703 static struct nodelist *
8704 copynodelist(struct nodelist *lp)
8706 struct nodelist *start;
8707 struct nodelist **lpp;
8712 funcblock = (char *) funcblock +
8713 SHELL_ALIGN(sizeof(struct nodelist));
8714 (*lpp)->n = copynode(lp->n);
8716 lpp = &(*lpp)->next;
8724 nodesavestr(char *s)
8726 char *rtn = funcstring;
8728 funcstring = stpcpy(funcstring, s) + 1;
8734 * Free a parse tree.
8738 freefunc(struct funcnode *f)
8740 if (f && --f->count < 0)
8745 static void options(int);
8746 static void setoption(int, int);
8750 * Process the shell command line arguments.
8754 procargs(int argc, char **argv)
8757 const char *xminusc;
8764 for (i = 0; i < NOPTS; i++)
8770 if (*xargv == NULL) {
8772 sh_error("-c requires an argument");
8775 if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
8779 for (i = 0; i < NOPTS; i++)
8780 if (optlist[i] == 2)
8785 /* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
8790 } else if (!sflag) {
8791 setinputfile(*xargv, 0);
8797 shellparam.p = xargv;
8798 #ifdef CONFIG_ASH_GETOPTS
8799 shellparam.optind = 1;
8800 shellparam.optoff = -1;
8802 /* assert(shellparam.malloc == 0 && shellparam.nparam == 0); */
8804 shellparam.nparam++;
8817 setinteractive(iflag);
8823 minus_o(char *name, int val)
8828 out1str("Current option settings\n");
8829 for (i = 0; i < NOPTS; i++)
8830 out1fmt("%-16s%s\n", optnames(i),
8831 optlist[i] ? "on" : "off");
8833 for (i = 0; i < NOPTS; i++)
8834 if (equal(name, optnames(i))) {
8838 sh_error("Illegal option -o %s", name);
8843 * Process shell options. The global variable argptr contains a pointer
8844 * to the argument list; we advance it past the options.
8848 options(int cmdline)
8856 while ((p = *argptr) != NULL) {
8858 if ((c = *p++) == '-') {
8860 if (p[0] == '\0' || (p[0] == '-' && p[1] == '\0')) {
8862 /* "-" means turn off -x and -v */
8865 /* "--" means reset params */
8866 else if (*argptr == NULL)
8869 break; /* "-" or "--" terminates options */
8871 } else if (c == '+') {
8877 while ((c = *p++) != '\0') {
8878 if (c == 'c' && cmdline) {
8879 minusc = p; /* command is after shell args*/
8880 } else if (c == 'o') {
8881 minus_o(*argptr, val);
8884 } else if (cmdline && (c == '-')) { // long options
8885 if (strcmp(p, "login") == 0)
8897 setoption(int flag, int val)
8901 for (i = 0; i < NOPTS; i++)
8902 if (optletters(i) == flag) {
8906 sh_error("Illegal option -%c", flag);
8913 * Set the shell parameters.
8917 setparam(char **argv)
8923 for (nparam = 0 ; argv[nparam] ; nparam++);
8924 ap = newparam = ckmalloc((nparam + 1) * sizeof *ap);
8926 *ap++ = savestr(*argv++);
8929 freeparam(&shellparam);
8930 shellparam.malloc = 1;
8931 shellparam.nparam = nparam;
8932 shellparam.p = newparam;
8933 #ifdef CONFIG_ASH_GETOPTS
8934 shellparam.optind = 1;
8935 shellparam.optoff = -1;
8941 * Free the list of positional parameters.
8945 freeparam(volatile struct shparam *param)
8949 if (param->malloc) {
8950 for (ap = param->p ; *ap ; ap++)
8959 * The shift builtin command.
8963 shiftcmd(int argc, char **argv)
8970 n = number(argv[1]);
8971 if (n > shellparam.nparam)
8972 sh_error("can't shift that many");
8974 shellparam.nparam -= n;
8975 for (ap1 = shellparam.p ; --n >= 0 ; ap1++) {
8976 if (shellparam.malloc)
8980 while ((*ap2++ = *ap1++) != NULL);
8981 #ifdef CONFIG_ASH_GETOPTS
8982 shellparam.optind = 1;
8983 shellparam.optoff = -1;
8992 * The set command builtin.
8996 setcmd(int argc, char **argv)
8999 return showvars(nullstr, 0, VUNSET);
9003 if (*argptr != NULL) {
9011 #ifdef CONFIG_ASH_GETOPTS
9016 shellparam.optind = number(value);
9017 shellparam.optoff = -1;
9021 #ifdef CONFIG_LOCALE_SUPPORT
9022 static void change_lc_all(const char *value)
9024 if (value != 0 && *value != 0)
9025 setlocale(LC_ALL, value);
9028 static void change_lc_ctype(const char *value)
9030 if (value != 0 && *value != 0)
9031 setlocale(LC_CTYPE, value);
9036 #ifdef CONFIG_ASH_RANDOM_SUPPORT
9037 /* Roughly copied from bash.. */
9038 static void change_random(const char *value)
9041 /* "get", generate */
9044 rseed = rseed * 1103515245 + 12345;
9045 sprintf(buf, "%d", (unsigned int)((rseed & 32767)));
9046 /* set without recursion */
9047 setvar(vrandom.text, buf, VNOFUNC);
9048 vrandom.flags &= ~VNOFUNC;
9051 rseed = strtoul(value, (char **)NULL, 10);
9057 #ifdef CONFIG_ASH_GETOPTS
9059 getopts(char *optstr, char *optvar, char **optfirst, int *param_optind, int *optoff)
9068 if(*param_optind < 1)
9070 optnext = optfirst + *param_optind - 1;
9072 if (*param_optind <= 1 || *optoff < 0 || strlen(optnext[-1]) < *optoff)
9075 p = optnext[-1] + *optoff;
9076 if (p == NULL || *p == '\0') {
9077 /* Current word is done, advance */
9079 if (p == NULL || *p != '-' || *++p == '\0') {
9086 if (p[0] == '-' && p[1] == '\0') /* check for "--" */
9091 for (q = optstr; *q != c; ) {
9093 if (optstr[0] == ':') {
9096 err |= setvarsafe("OPTARG", s, 0);
9098 fprintf(stderr, "Illegal option -%c\n", c);
9099 (void) unsetvar("OPTARG");
9109 if (*p == '\0' && (p = *optnext) == NULL) {
9110 if (optstr[0] == ':') {
9113 err |= setvarsafe("OPTARG", s, 0);
9116 fprintf(stderr, "No arg for -%c option\n", c);
9117 (void) unsetvar("OPTARG");
9125 err |= setvarsafe("OPTARG", p, 0);
9128 err |= setvarsafe("OPTARG", nullstr, 0);
9131 *optoff = p ? p - *(optnext - 1) : -1;
9132 *param_optind = optnext - optfirst + 1;
9133 fmtstr(s, sizeof(s), "%d", *param_optind);
9134 err |= setvarsafe("OPTIND", s, VNOFUNC);
9137 err |= setvarsafe(optvar, s, 0);
9148 * The getopts builtin. Shellparam.optnext points to the next argument
9149 * to be processed. Shellparam.optptr points to the next character to
9150 * be processed in the current argument. If shellparam.optnext is NULL,
9151 * then it's the first time getopts has been called.
9155 getoptscmd(int argc, char **argv)
9160 sh_error("Usage: getopts optstring var [arg]");
9161 else if (argc == 3) {
9162 optbase = shellparam.p;
9163 if (shellparam.optind > shellparam.nparam + 1) {
9164 shellparam.optind = 1;
9165 shellparam.optoff = -1;
9170 if (shellparam.optind > argc - 2) {
9171 shellparam.optind = 1;
9172 shellparam.optoff = -1;
9176 return getopts(argv[1], argv[2], optbase, &shellparam.optind,
9177 &shellparam.optoff);
9179 #endif /* CONFIG_ASH_GETOPTS */
9182 * XXX - should get rid of. have all builtins use getopt(3). the
9183 * library getopt must have the BSD extension static variable "optreset"
9184 * otherwise it can't be used within the shell safely.
9186 * Standard option processing (a la getopt) for builtin routines. The
9187 * only argument that is passed to nextopt is the option string; the
9188 * other arguments are unnecessary. It return the character, or '\0' on
9193 nextopt(const char *optstring)
9199 if ((p = optptr) == NULL || *p == '\0') {
9201 if (p == NULL || *p != '-' || *++p == '\0')
9204 if (p[0] == '-' && p[1] == '\0') /* check for "--" */
9208 for (q = optstring ; *q != c ; ) {
9210 sh_error("Illegal option -%c", c);
9215 if (*p == '\0' && (p = *argptr++) == NULL)
9216 sh_error("No arg for -%c option", c);
9228 outstr(const char *p, FILE *file)
9253 outcslow(int c, FILE *dest)
9263 out1fmt(const char *fmt, ...)
9270 r = vprintf(fmt, ap);
9278 fmtstr(char *outbuf, size_t length, const char *fmt, ...)
9285 ret = vsnprintf(outbuf, length, fmt, ap);
9297 * Shell command parser.
9300 #define EOFMARKLEN 79
9304 struct heredoc *next; /* next here document in list */
9305 union node *here; /* redirection node */
9306 char *eofmark; /* string indicating end of input */
9307 int striptabs; /* if set, strip leading tabs */
9312 static struct heredoc *heredoclist; /* list of here documents to read */
9315 static union node *list(int);
9316 static union node *andor(void);
9317 static union node *pipeline(void);
9318 static union node *command(void);
9319 static union node *simplecmd(void);
9320 static union node *makename(void);
9321 static void parsefname(void);
9322 static void parseheredoc(void);
9323 static char peektoken(void);
9324 static int readtoken(void);
9325 static int xxreadtoken(void);
9326 static int readtoken1(int firstc, int syntax, char *eofmark, int striptabs);
9327 static int noexpand(char *);
9328 static void synexpect(int) __attribute__((__noreturn__));
9329 static void synerror(const char *) __attribute__((__noreturn__));
9330 static void setprompt(int);
9336 * Read and parse a command. Returns NEOF on end of file. (NULL is a
9337 * valid parse tree indicating a blank line.)
9341 parsecmd(int interact)
9346 doprompt = interact;
9348 setprompt(doprompt);
9363 union node *n1, *n2, *n3;
9366 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9367 if (nlflag == 2 && peektoken())
9373 if (tok == TBACKGND) {
9374 if (n2->type == NPIPE) {
9375 n2->npipe.backgnd = 1;
9377 if (n2->type != NREDIR) {
9378 n3 = stalloc(sizeof(struct nredir));
9380 n3->nredir.redirect = NULL;
9383 n2->type = NBACKGND;
9390 n3 = (union node *)stalloc(sizeof (struct nbinary));
9392 n3->nbinary.ch1 = n1;
9393 n3->nbinary.ch2 = n2;
9409 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9417 pungetc(); /* push back EOF on input */
9433 union node *n1, *n2, *n3;
9438 if ((t = readtoken()) == TAND) {
9440 } else if (t == TOR) {
9446 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9448 n3 = (union node *)stalloc(sizeof (struct nbinary));
9450 n3->nbinary.ch1 = n1;
9451 n3->nbinary.ch2 = n2;
9461 union node *n1, *n2, *pipenode;
9462 struct nodelist *lp, *prev;
9466 TRACE(("pipeline: entered\n"));
9467 if (readtoken() == TNOT) {
9469 checkkwd = CHKKWD | CHKALIAS;
9473 if (readtoken() == TPIPE) {
9474 pipenode = (union node *)stalloc(sizeof (struct npipe));
9475 pipenode->type = NPIPE;
9476 pipenode->npipe.backgnd = 0;
9477 lp = (struct nodelist *)stalloc(sizeof (struct nodelist));
9478 pipenode->npipe.cmdlist = lp;
9482 lp = (struct nodelist *)stalloc(sizeof (struct nodelist));
9483 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9486 } while (readtoken() == TPIPE);
9492 n2 = (union node *)stalloc(sizeof (struct nnot));
9505 union node *n1, *n2;
9506 union node *ap, **app;
9507 union node *cp, **cpp;
9508 union node *redir, **rpp;
9515 switch (readtoken()) {
9520 n1 = (union node *)stalloc(sizeof (struct nif));
9522 n1->nif.test = list(0);
9523 if (readtoken() != TTHEN)
9525 n1->nif.ifpart = list(0);
9527 while (readtoken() == TELIF) {
9528 n2->nif.elsepart = (union node *)stalloc(sizeof (struct nif));
9529 n2 = n2->nif.elsepart;
9531 n2->nif.test = list(0);
9532 if (readtoken() != TTHEN)
9534 n2->nif.ifpart = list(0);
9536 if (lasttoken == TELSE)
9537 n2->nif.elsepart = list(0);
9539 n2->nif.elsepart = NULL;
9547 n1 = (union node *)stalloc(sizeof (struct nbinary));
9548 n1->type = (lasttoken == TWHILE)? NWHILE : NUNTIL;
9549 n1->nbinary.ch1 = list(0);
9550 if ((got=readtoken()) != TDO) {
9551 TRACE(("expecting DO got %s %s\n", tokname(got), got == TWORD ? wordtext : ""));
9554 n1->nbinary.ch2 = list(0);
9559 if (readtoken() != TWORD || quoteflag || ! goodname(wordtext))
9560 synerror("Bad for loop variable");
9561 n1 = (union node *)stalloc(sizeof (struct nfor));
9563 n1->nfor.var = wordtext;
9564 checkkwd = CHKKWD | CHKALIAS;
9565 if (readtoken() == TIN) {
9567 while (readtoken() == TWORD) {
9568 n2 = (union node *)stalloc(sizeof (struct narg));
9570 n2->narg.text = wordtext;
9571 n2->narg.backquote = backquotelist;
9573 app = &n2->narg.next;
9577 if (lasttoken != TNL && lasttoken != TSEMI)
9580 n2 = (union node *)stalloc(sizeof (struct narg));
9582 n2->narg.text = (char *)dolatstr;
9583 n2->narg.backquote = NULL;
9584 n2->narg.next = NULL;
9587 * Newline or semicolon here is optional (but note
9588 * that the original Bourne shell only allowed NL).
9590 if (lasttoken != TNL && lasttoken != TSEMI)
9593 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9594 if (readtoken() != TDO)
9596 n1->nfor.body = list(0);
9600 n1 = (union node *)stalloc(sizeof (struct ncase));
9602 if (readtoken() != TWORD)
9604 n1->ncase.expr = n2 = (union node *)stalloc(sizeof (struct narg));
9606 n2->narg.text = wordtext;
9607 n2->narg.backquote = backquotelist;
9608 n2->narg.next = NULL;
9610 checkkwd = CHKKWD | CHKALIAS;
9611 } while (readtoken() == TNL);
9612 if (lasttoken != TIN)
9614 cpp = &n1->ncase.cases;
9616 checkkwd = CHKNL | CHKKWD;
9619 if (lasttoken == TLP)
9621 *cpp = cp = (union node *)stalloc(sizeof (struct nclist));
9623 app = &cp->nclist.pattern;
9625 *app = ap = (union node *)stalloc(sizeof (struct narg));
9627 ap->narg.text = wordtext;
9628 ap->narg.backquote = backquotelist;
9629 if (readtoken() != TPIPE)
9631 app = &ap->narg.next;
9634 ap->narg.next = NULL;
9635 if (lasttoken != TRP)
9637 cp->nclist.body = list(2);
9639 cpp = &cp->nclist.next;
9641 checkkwd = CHKNL | CHKKWD;
9642 if ((t = readtoken()) != TESAC) {
9644 synexpect(TENDCASE);
9652 n1 = (union node *)stalloc(sizeof (struct nredir));
9653 n1->type = NSUBSHELL;
9654 n1->nredir.n = list(0);
9655 n1->nredir.redirect = NULL;
9668 if (readtoken() != t)
9672 /* Now check for redirection which may follow command */
9673 checkkwd = CHKKWD | CHKALIAS;
9675 while (readtoken() == TREDIR) {
9676 *rpp = n2 = redirnode;
9677 rpp = &n2->nfile.next;
9683 if (n1->type != NSUBSHELL) {
9684 n2 = (union node *)stalloc(sizeof (struct nredir));
9689 n1->nredir.redirect = redir;
9698 union node *args, **app;
9699 union node *n = NULL;
9700 union node *vars, **vpp;
9701 union node **rpp, *redir;
9711 savecheckkwd = CHKALIAS;
9713 checkkwd = savecheckkwd;
9714 switch (readtoken()) {
9716 n = (union node *)stalloc(sizeof (struct narg));
9718 n->narg.text = wordtext;
9719 n->narg.backquote = backquotelist;
9720 if (savecheckkwd && isassignment(wordtext)) {
9722 vpp = &n->narg.next;
9725 app = &n->narg.next;
9730 *rpp = n = redirnode;
9731 rpp = &n->nfile.next;
9732 parsefname(); /* read name of redirection file */
9736 args && app == &args->narg.next &&
9739 struct builtincmd *bcmd;
9742 /* We have a function */
9743 if (readtoken() != TRP)
9745 name = n->narg.text;
9747 !goodname(name) || (
9748 (bcmd = find_builtin(name)) &&
9749 IS_BUILTIN_SPECIAL(bcmd)
9752 synerror("Bad function name");
9754 checkkwd = CHKNL | CHKKWD | CHKALIAS;
9755 n->narg.next = command();
9768 n = (union node *)stalloc(sizeof (struct ncmd));
9770 n->ncmd.args = args;
9771 n->ncmd.assign = vars;
9772 n->ncmd.redirect = redir;
9781 n = (union node *)stalloc(sizeof (struct narg));
9783 n->narg.next = NULL;
9784 n->narg.text = wordtext;
9785 n->narg.backquote = backquotelist;
9789 void fixredir(union node *n, const char *text, int err)
9791 TRACE(("Fix redir %s %d\n", text, err));
9793 n->ndup.vname = NULL;
9795 if (is_digit(text[0]) && text[1] == '\0')
9796 n->ndup.dupfd = digit_val(text[0]);
9797 else if (text[0] == '-' && text[1] == '\0')
9802 synerror("Bad fd number");
9804 n->ndup.vname = makename();
9812 union node *n = redirnode;
9814 if (readtoken() != TWORD)
9816 if (n->type == NHERE) {
9817 struct heredoc *here = heredoc;
9823 TRACE(("Here document %d\n", n->type));
9824 if (! noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)
9825 synerror("Illegal eof marker for << redirection");
9826 rmescapes(wordtext);
9827 here->eofmark = wordtext;
9829 if (heredoclist == NULL)
9832 for (p = heredoclist ; p->next ; p = p->next);
9835 } else if (n->type == NTOFD || n->type == NFROMFD) {
9836 fixredir(n, wordtext, 0);
9838 n->nfile.fname = makename();
9844 * Input any here documents.
9850 struct heredoc *here;
9860 readtoken1(pgetc(), here->here->type == NHERE? SQSYNTAX : DQSYNTAX,
9861 here->eofmark, here->striptabs);
9862 n = (union node *)stalloc(sizeof (struct narg));
9863 n->narg.type = NARG;
9864 n->narg.next = NULL;
9865 n->narg.text = wordtext;
9866 n->narg.backquote = backquotelist;
9867 here->here->nhere.doc = n;
9872 static char peektoken(void)
9878 return tokname_array[t][0];
9886 int alreadyseen = tokpushback;
9889 #ifdef CONFIG_ASH_ALIAS
9898 if (checkkwd & CHKNL) {
9905 if (t != TWORD || quoteflag) {
9910 * check for keywords
9912 if (checkkwd & CHKKWD) {
9913 const char *const *pp;
9915 if ((pp = findkwd(wordtext))) {
9916 lasttoken = t = pp - tokname_array;
9917 TRACE(("keyword %s recognized\n", tokname(t)));
9922 if (checkkwd & CHKALIAS) {
9923 #ifdef CONFIG_ASH_ALIAS
9925 if ((ap = lookupalias(wordtext, 1)) != NULL) {
9927 pushstring(ap->val, ap);
9937 TRACE(("token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
9939 TRACE(("reread token %s %s\n", tokname(t), t == TWORD ? wordtext : ""));
9946 * Read the next input token.
9947 * If the token is a word, we set backquotelist to the list of cmds in
9948 * backquotes. We set quoteflag to true if any part of the word was
9950 * If the token is TREDIR, then we set redirnode to a structure containing
9952 * In all cases, the variable startlinno is set to the number of the line
9953 * on which the token starts.
9955 * [Change comment: here documents and internal procedures]
9956 * [Readtoken shouldn't have any arguments. Perhaps we should make the
9957 * word parsing code into a separate routine. In this case, readtoken
9958 * doesn't need to have any internal procedures, but parseword does.
9959 * We could also make parseoperator in essence the main routine, and
9960 * have parseword (readtoken1?) handle both words and redirection.]
9963 #define NEW_xxreadtoken
9964 #ifdef NEW_xxreadtoken
9966 /* singles must be first! */
9967 static const char xxreadtoken_chars[7] = { '\n', '(', ')', '&', '|', ';', 0 };
9969 static const char xxreadtoken_tokens[] = {
9970 TNL, TLP, TRP, /* only single occurrence allowed */
9971 TBACKGND, TPIPE, TSEMI, /* if single occurrence */
9972 TEOF, /* corresponds to trailing nul */
9973 TAND, TOR, TENDCASE, /* if double occurrence */
9976 #define xxreadtoken_doubles \
9977 (sizeof(xxreadtoken_tokens) - sizeof(xxreadtoken_chars))
9978 #define xxreadtoken_singles \
9979 (sizeof(xxreadtoken_chars) - xxreadtoken_doubles - 1)
9981 static int xxreadtoken()
9992 startlinno = plinno;
9993 for (;;) { /* until token or start of word found */
9996 if ((c != ' ') && (c != '\t')
9997 #ifdef CONFIG_ASH_ALIAS
10002 while ((c = pgetc()) != '\n' && c != PEOF);
10004 } else if (c == '\\') {
10005 if (pgetc() != '\n') {
10009 startlinno = ++plinno;
10014 = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
10019 needprompt = doprompt;
10022 p = strchr(xxreadtoken_chars, c);
10025 return readtoken1(c, BASESYNTAX, (char *) NULL, 0);
10028 if (p - xxreadtoken_chars >= xxreadtoken_singles) {
10029 if (pgetc() == *p) { /* double occurrence? */
10030 p += xxreadtoken_doubles + 1;
10037 return lasttoken = xxreadtoken_tokens[p - xxreadtoken_chars];
10045 #define RETURN(token) return lasttoken = token
10059 startlinno = plinno;
10060 for (;;) { /* until token or start of word found */
10063 case ' ': case '\t':
10064 #ifdef CONFIG_ASH_ALIAS
10069 while ((c = pgetc()) != '\n' && c != PEOF);
10073 if (pgetc() == '\n') {
10074 startlinno = ++plinno;
10083 needprompt = doprompt;
10088 if (pgetc() == '&')
10093 if (pgetc() == '|')
10098 if (pgetc() == ';')
10111 return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
10114 #endif /* NEW_xxreadtoken */
10118 * If eofmark is NULL, read a word or a redirection symbol. If eofmark
10119 * is not NULL, read a here document. In the latter case, eofmark is the
10120 * word which marks the end of the document and striptabs is true if
10121 * leading tabs should be stripped from the document. The argument firstc
10122 * is the first character of the input token or document.
10124 * Because C does not have internal subroutines, I have simulated them
10125 * using goto's to implement the subroutine linkage. The following macros
10126 * will run code that appears at the end of readtoken1.
10129 #define CHECKEND() {goto checkend; checkend_return:;}
10130 #define PARSEREDIR() {goto parseredir; parseredir_return:;}
10131 #define PARSESUB() {goto parsesub; parsesub_return:;}
10132 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
10133 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
10134 #define PARSEARITH() {goto parsearith; parsearith_return:;}
10137 readtoken1(int firstc, int syntax, char *eofmark, int striptabs)
10142 char line[EOFMARKLEN + 1];
10143 struct nodelist *bqlist;
10146 int varnest; /* levels of variables expansion */
10147 int arinest; /* levels of arithmetic expansion */
10148 int parenlevel; /* levels of parens in arithmetic */
10149 int dqvarnest; /* levels of variables expansion within double quotes */
10151 int prevsyntax; /* syntax before arithmetic */
10153 /* Avoid longjmp clobbering */
10159 (void) &parenlevel;
10162 (void) &prevsyntax;
10166 startlinno = plinno;
10168 if (syntax == DQSYNTAX)
10177 STARTSTACKSTR(out);
10178 loop: { /* for each line, until end of word */
10179 CHECKEND(); /* set c to PEOF if at end of here document */
10180 for (;;) { /* until end of line or end of word */
10181 CHECKSTRSPACE(4, out); /* permit 4 calls to USTPUTC */
10182 switch(SIT(c, syntax)) {
10183 case CNL: /* '\n' */
10184 if (syntax == BASESYNTAX)
10185 goto endword; /* exit outer loop */
10191 goto loop; /* continue outer loop */
10196 if (eofmark == NULL || dblquote)
10197 USTPUTC(CTLESC, out);
10200 case CBACK: /* backslash */
10203 USTPUTC(CTLESC, out);
10204 USTPUTC('\\', out);
10206 } else if (c == '\n') {
10212 c != '\\' && c != '`' &&
10218 USTPUTC(CTLESC, out);
10219 USTPUTC('\\', out);
10221 if (SIT(c, SQSYNTAX) == CCTL)
10222 USTPUTC(CTLESC, out);
10230 if (eofmark == NULL) {
10231 USTPUTC(CTLQUOTEMARK, out);
10239 if (eofmark != NULL && arinest == 0 &&
10243 if (dqvarnest == 0) {
10244 syntax = BASESYNTAX;
10251 case CVAR: /* '$' */
10252 PARSESUB(); /* parse substitution */
10254 case CENDVAR: /* '}' */
10257 if (dqvarnest > 0) {
10260 USTPUTC(CTLENDVAR, out);
10265 #ifdef CONFIG_ASH_MATH_SUPPORT
10266 case CLP: /* '(' in arithmetic */
10270 case CRP: /* ')' in arithmetic */
10271 if (parenlevel > 0) {
10275 if (pgetc() == ')') {
10276 if (--arinest == 0) {
10277 USTPUTC(CTLENDARI, out);
10278 syntax = prevsyntax;
10279 if (syntax == DQSYNTAX)
10287 * unbalanced parens
10288 * (don't 2nd guess - no error)
10296 case CBQUOTE: /* '`' */
10300 goto endword; /* exit outer loop */
10305 goto endword; /* exit outer loop */
10306 #ifdef CONFIG_ASH_ALIAS
10316 #ifdef CONFIG_ASH_MATH_SUPPORT
10317 if (syntax == ARISYNTAX)
10318 synerror("Missing '))'");
10320 if (syntax != BASESYNTAX && ! parsebackquote && eofmark == NULL)
10321 synerror("Unterminated quoted string");
10322 if (varnest != 0) {
10323 startlinno = plinno;
10325 synerror("Missing '}'");
10327 USTPUTC('\0', out);
10328 len = out - (char *)stackblock();
10329 out = stackblock();
10330 if (eofmark == NULL) {
10331 if ((c == '>' || c == '<')
10334 && (*out == '\0' || is_digit(*out))) {
10336 return lasttoken = TREDIR;
10341 quoteflag = quotef;
10342 backquotelist = bqlist;
10343 grabstackblock(len);
10345 return lasttoken = TWORD;
10346 /* end of readtoken routine */
10351 * Check to see whether we are at the end of the here document. When this
10352 * is called, c is set to the first character of the next input line. If
10353 * we are at the end of the here document, this routine sets the c to PEOF.
10358 #ifdef CONFIG_ASH_ALIAS
10364 while (c == '\t') {
10368 if (c == *eofmark) {
10369 if (pfgets(line, sizeof line) != NULL) {
10373 for (q = eofmark + 1 ; *q && *p == *q ; p++, q++);
10374 if (*p == '\n' && *q == '\0') {
10377 needprompt = doprompt;
10379 pushstring(line, NULL);
10384 goto checkend_return;
10389 * Parse a redirection operator. The variable "out" points to a string
10390 * specifying the fd to be redirected. The variable "c" contains the
10391 * first character of the redirection operator.
10398 np = (union node *)stalloc(sizeof (struct nfile));
10403 np->type = NAPPEND;
10405 np->type = NCLOBBER;
10412 } else { /* c == '<' */
10414 switch (c = pgetc()) {
10416 if (sizeof (struct nfile) != sizeof (struct nhere)) {
10417 np = (union node *)stalloc(sizeof (struct nhere));
10421 heredoc = (struct heredoc *)stalloc(sizeof (struct heredoc));
10422 heredoc->here = np;
10423 if ((c = pgetc()) == '-') {
10424 heredoc->striptabs = 1;
10426 heredoc->striptabs = 0;
10432 np->type = NFROMFD;
10436 np->type = NFROMTO;
10446 np->nfile.fd = digit_val(fd);
10448 goto parseredir_return;
10453 * Parse a substitution. At this point, we have read the dollar sign
10454 * and nothing else.
10462 static const char types[] = "}-+?=";
10466 c <= PEOA_OR_PEOF ||
10467 (c != '(' && c != '{' && !is_name(c) && !is_special(c))
10471 } else if (c == '(') { /* $(command) or $((arith)) */
10472 if (pgetc() == '(') {
10473 #ifdef CONFIG_ASH_MATH_SUPPORT
10476 synerror("We unsupport $((arith))");
10483 USTPUTC(CTLVAR, out);
10484 typeloc = out - (char *)stackblock();
10485 USTPUTC(VSNORMAL, out);
10486 subtype = VSNORMAL;
10490 if ((c = pgetc()) == '}')
10493 subtype = VSLENGTH;
10498 if (c > PEOA_OR_PEOF && is_name(c)) {
10502 } while (c > PEOA_OR_PEOF && is_in_name(c));
10503 } else if (is_digit(c)) {
10507 } while (is_digit(c));
10509 else if (is_special(c)) {
10514 badsub: synerror("Bad substitution");
10518 if (subtype == 0) {
10525 p = strchr(types, c);
10528 subtype = p - types + VSNORMAL;
10534 subtype = c == '#' ? VSTRIMLEFT :
10547 if (dblquote || arinest)
10549 *((char *)stackblock() + typeloc) = subtype | flags;
10550 if (subtype != VSNORMAL) {
10552 if (dblquote || arinest) {
10557 goto parsesub_return;
10562 * Called to parse command substitutions. Newstyle is set if the command
10563 * is enclosed inside $(...); nlpp is a pointer to the head of the linked
10564 * list of commands (passed by reference), and savelen is the number of
10565 * characters on the top of the stack which must be preserved.
10569 struct nodelist **nlpp;
10572 char *volatile str;
10573 struct jmploc jmploc;
10574 struct jmploc *volatile savehandler;
10578 (void) &saveprompt;
10581 savepbq = parsebackquote;
10582 if (setjmp(jmploc.loc)) {
10585 parsebackquote = 0;
10586 handler = savehandler;
10587 longjmp(handler->loc, 1);
10591 savelen = out - (char *)stackblock();
10593 str = ckmalloc(savelen);
10594 memcpy(str, stackblock(), savelen);
10596 savehandler = handler;
10600 /* We must read until the closing backquote, giving special
10601 treatment to some slashes, and then push the string and
10602 reread it as input, interpreting it normally. */
10609 STARTSTACKSTR(pout);
10614 switch (pc = pgetc()) {
10619 if ((pc = pgetc()) == '\n') {
10624 * If eating a newline, avoid putting
10625 * the newline into the new character
10626 * stream (via the STPUTC after the
10631 if (pc != '\\' && pc != '`' && pc != '$'
10632 && (!dblquote || pc != '"'))
10633 STPUTC('\\', pout);
10634 if (pc > PEOA_OR_PEOF) {
10640 #ifdef CONFIG_ASH_ALIAS
10643 startlinno = plinno;
10644 synerror("EOF in backquote substitution");
10648 needprompt = doprompt;
10657 STPUTC('\0', pout);
10658 psavelen = pout - (char *)stackblock();
10659 if (psavelen > 0) {
10660 pstr = grabstackstr(pout);
10661 setinputstring(pstr);
10666 nlpp = &(*nlpp)->next;
10667 *nlpp = (struct nodelist *)stalloc(sizeof (struct nodelist));
10668 (*nlpp)->next = NULL;
10669 parsebackquote = oldstyle;
10672 saveprompt = doprompt;
10679 doprompt = saveprompt;
10681 if (readtoken() != TRP)
10688 * Start reading from old file again, ignoring any pushed back
10689 * tokens left from the backquote parsing
10694 while (stackblocksize() <= savelen)
10696 STARTSTACKSTR(out);
10698 memcpy(out, str, savelen);
10699 STADJUST(savelen, out);
10705 parsebackquote = savepbq;
10706 handler = savehandler;
10707 if (arinest || dblquote)
10708 USTPUTC(CTLBACKQ | CTLQUOTE, out);
10710 USTPUTC(CTLBACKQ, out);
10712 goto parsebackq_oldreturn;
10714 goto parsebackq_newreturn;
10717 #ifdef CONFIG_ASH_MATH_SUPPORT
10719 * Parse an arithmetic expansion (indicate start of one and set state)
10723 if (++arinest == 1) {
10724 prevsyntax = syntax;
10725 syntax = ARISYNTAX;
10726 USTPUTC(CTLARI, out);
10733 * we collapse embedded arithmetic expansion to
10734 * parenthesis, which should be equivalent
10738 goto parsearith_return;
10742 } /* end of readtoken */
10747 * Returns true if the text contains nothing to expand (no dollar signs
10752 noexpand(char *text)
10758 while ((c = *p++) != '\0') {
10759 if (c == CTLQUOTEMARK)
10763 else if (SIT(c, BASESYNTAX) == CCTL)
10771 * Return of a legal variable name (a letter or underscore followed by zero or
10772 * more letters, underscores, and digits).
10776 endofname(const char *name)
10784 if (! is_in_name(*p))
10792 * Called when an unexpected token is read during the parse. The argument
10793 * is the token that is expected, or -1 if more than one type of token can
10794 * occur at this point.
10797 static void synexpect(int token)
10802 l = sprintf(msg, "%s unexpected", tokname(lasttoken));
10804 sprintf(msg + l, " (expecting %s)", tokname(token));
10810 synerror(const char *msg)
10812 sh_error("Syntax error: %s", msg);
10818 * called by editline -- any expansions to the prompt
10819 * should be added here.
10822 #ifdef CONFIG_ASH_EXPAND_PRMT
10823 static const char *
10824 expandstr(const char *ps)
10828 /* XXX Fix (char *) cast. */
10829 setinputstring((char *)ps);
10830 readtoken1(pgetc(), DQSYNTAX, nullstr, 0);
10833 n.narg.type = NARG;
10834 n.narg.next = NULL;
10835 n.narg.text = wordtext;
10836 n.narg.backquote = backquotelist;
10838 expandarg(&n, NULL, 0);
10839 return stackblock();
10843 static void setprompt(int whichprompt)
10845 const char *prompt;
10846 #ifdef CONFIG_ASH_EXPAND_PRMT
10847 struct stackmark smark;
10852 switch (whichprompt) {
10862 #ifdef CONFIG_ASH_EXPAND_PRMT
10863 setstackmark(&smark);
10864 stalloc(stackblocksize());
10866 putprompt(expandstr(prompt));
10867 #ifdef CONFIG_ASH_EXPAND_PRMT
10868 popstackmark(&smark);
10873 static const char *const *findkwd(const char *s)
10875 return bsearch(s, tokname_array + KWDOFFSET,
10876 (sizeof(tokname_array) / sizeof(const char *)) - KWDOFFSET,
10877 sizeof(const char *), pstrcmp);
10883 * Code for dealing with input/output redirection.
10886 #define EMPTY -2 /* marks an unused slot in redirtab */
10888 # define PIPESIZE 4096 /* amount of buffering in a pipe */
10890 # define PIPESIZE PIPE_BUF
10894 * Open a file in noclobber mode.
10895 * The code was copied from bash.
10898 noclobberopen(const char *fname)
10901 struct stat finfo, finfo2;
10904 * If the file exists and is a regular file, return an error
10907 r = stat(fname, &finfo);
10908 if (r == 0 && S_ISREG(finfo.st_mode)) {
10914 * If the file was not present (r != 0), make sure we open it
10915 * exclusively so that if it is created before we open it, our open
10916 * will fail. Make sure that we do not truncate an existing file.
10917 * Note that we don't turn on O_EXCL unless the stat failed -- if the
10918 * file was not a regular file, we leave O_EXCL off.
10921 return open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
10922 fd = open(fname, O_WRONLY|O_CREAT, 0666);
10924 /* If the open failed, return the file descriptor right away. */
10929 * OK, the open succeeded, but the file may have been changed from a
10930 * non-regular file to a regular file between the stat and the open.
10931 * We are assuming that the O_EXCL open handles the case where FILENAME
10932 * did not exist and is symlinked to an existing file between the stat
10937 * If we can open it and fstat the file descriptor, and neither check
10938 * revealed that it was a regular file, and the file has not been
10939 * replaced, return the file descriptor.
10941 if (fstat(fd, &finfo2) == 0 && !S_ISREG(finfo2.st_mode) &&
10942 finfo.st_dev == finfo2.st_dev && finfo.st_ino == finfo2.st_ino)
10945 /* The file has been replaced. badness. */
10952 * Handle here documents. Normally we fork off a process to write the
10953 * data to a pipe. If the document is short, we can stuff the data in
10954 * the pipe without forking.
10958 openhere(union node *redir)
10964 sh_error("Pipe call failed");
10965 if (redir->type == NHERE) {
10966 len = strlen(redir->nhere.doc->narg.text);
10967 if (len <= PIPESIZE) {
10968 bb_full_write(pip[1], redir->nhere.doc->narg.text, len);
10972 if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
10974 signal(SIGINT, SIG_IGN);
10975 signal(SIGQUIT, SIG_IGN);
10976 signal(SIGHUP, SIG_IGN);
10978 signal(SIGTSTP, SIG_IGN);
10980 signal(SIGPIPE, SIG_DFL);
10981 if (redir->type == NHERE)
10982 bb_full_write(pip[1], redir->nhere.doc->narg.text, len);
10984 expandhere(redir->nhere.doc, pip[1]);
10993 openredirect(union node *redir)
10998 switch (redir->nfile.type) {
11000 fname = redir->nfile.expfname;
11001 if ((f = open(fname, O_RDONLY)) < 0)
11005 fname = redir->nfile.expfname;
11006 if ((f = open(fname, O_RDWR|O_CREAT|O_TRUNC, 0666)) < 0)
11010 /* Take care of noclobber mode. */
11012 fname = redir->nfile.expfname;
11013 if ((f = noclobberopen(fname)) < 0)
11019 fname = redir->nfile.expfname;
11020 if ((f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0)
11024 fname = redir->nfile.expfname;
11025 if ((f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666)) < 0)
11032 /* Fall through to eliminate warning. */
11039 f = openhere(redir);
11045 sh_error("cannot create %s: %s", fname, errmsg(errno, E_CREAT));
11047 sh_error("cannot open %s: %s", fname, errmsg(errno, E_OPEN));
11051 dupredirect(union node *redir, int f)
11053 int fd = redir->nfile.fd;
11055 if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
11056 if (redir->ndup.dupfd >= 0) { /* if not ">&-" */
11057 copyfd(redir->ndup.dupfd, fd);
11070 * Process a list of redirection commands. If the REDIR_PUSH flag is set,
11071 * old file descriptors are stashed away so that the redirection can be
11072 * undone by calling popredir. If the REDIR_BACKQ flag is set, then the
11073 * standard output, and the standard error if it becomes a duplicate of
11074 * stdout, is saved in memory.
11078 redirect(union node *redir, int flags)
11081 struct redirtab *sv;
11092 if (flags & REDIR_PUSH) {
11093 struct redirtab *q;
11094 q = ckmalloc(sizeof (struct redirtab));
11095 q->next = redirlist;
11097 q->nullredirs = nullredirs - 1;
11098 for (i = 0 ; i < 10 ; i++)
11099 q->renamed[i] = EMPTY;
11106 if ((n->nfile.type == NTOFD || n->nfile.type == NFROMFD) &&
11107 n->ndup.dupfd == fd)
11108 continue; /* redirect from/to same file descriptor */
11110 newfd = openredirect(n);
11113 if (sv && *(p = &sv->renamed[fd]) == EMPTY) {
11114 i = fcntl(fd, F_DUPFD, 10);
11121 sh_error("%d: %m", fd);
11131 dupredirect(n, newfd);
11132 } while ((n = n->nfile.next));
11134 if (flags & REDIR_SAVEFD2 && sv && sv->renamed[2] >= 0)
11135 preverrout_fd = sv->renamed[2];
11140 * Undo the effects of the last redirection.
11146 struct redirtab *rp;
11149 if (--nullredirs >= 0)
11153 for (i = 0 ; i < 10 ; i++) {
11154 if (rp->renamed[i] != EMPTY) {
11157 copyfd(rp->renamed[i], i);
11159 close(rp->renamed[i]);
11162 redirlist = rp->next;
11163 nullredirs = rp->nullredirs;
11169 * Undo all redirections. Called on error or interrupt.
11173 * Discard all saved file descriptors.
11177 clearredir(int drop)
11189 * Copy a file descriptor to be >= to. Returns -1
11190 * if the source file descriptor is closed, EMPTY if there are no unused
11191 * file descriptors left.
11195 copyfd(int from, int to)
11199 newfd = fcntl(from, F_DUPFD, to);
11201 if (errno == EMFILE)
11204 sh_error("%d: %m", from);
11211 redirectsafe(union node *redir, int flags)
11214 volatile int saveint;
11215 struct jmploc *volatile savehandler = handler;
11216 struct jmploc jmploc;
11219 if (!(err = setjmp(jmploc.loc) * 2)) {
11221 redirect(redir, flags);
11223 handler = savehandler;
11224 if (err && exception != EXERROR)
11225 longjmp(handler->loc, 1);
11226 RESTOREINT(saveint);
11233 static void shtree(union node *, int, char *, FILE*);
11234 static void shcmd(union node *, FILE *);
11235 static void sharg(union node *, FILE *);
11236 static void indent(int, char *, FILE *);
11237 static void trstring(char *);
11241 showtree(union node *n)
11243 trputs("showtree called\n");
11244 shtree(n, 1, NULL, stdout);
11249 shtree(union node *n, int ind, char *pfx, FILE *fp)
11251 struct nodelist *lp;
11257 indent(ind, pfx, fp);
11268 shtree(n->nbinary.ch1, ind, NULL, fp);
11271 shtree(n->nbinary.ch2, ind, NULL, fp);
11279 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
11284 if (n->npipe.backgnd)
11290 fprintf(fp, "<node type %d>", n->type);
11299 shcmd(union node *cmd, FILE *fp)
11307 for (np = cmd->ncmd.args ; np ; np = np->narg.next) {
11313 for (np = cmd->ncmd.redirect ; np ; np = np->nfile.next) {
11316 switch (np->nfile.type) {
11317 case NTO: s = ">"; dftfd = 1; break;
11318 case NCLOBBER: s = ">|"; dftfd = 1; break;
11319 case NAPPEND: s = ">>"; dftfd = 1; break;
11320 case NTOFD: s = ">&"; dftfd = 1; break;
11321 case NFROM: s = "<"; dftfd = 0; break;
11322 case NFROMFD: s = "<&"; dftfd = 0; break;
11323 case NFROMTO: s = "<>"; dftfd = 0; break;
11324 default: s = "*error*"; dftfd = 0; break;
11326 if (np->nfile.fd != dftfd)
11327 fprintf(fp, "%d", np->nfile.fd);
11329 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
11330 fprintf(fp, "%d", np->ndup.dupfd);
11332 sharg(np->nfile.fname, fp);
11341 sharg(union node *arg, FILE *fp)
11344 struct nodelist *bqlist;
11347 if (arg->type != NARG) {
11348 out1fmt("<node type %d>\n", arg->type);
11351 bqlist = arg->narg.backquote;
11352 for (p = arg->narg.text ; *p ; p++) {
11361 if (subtype == VSLENGTH)
11367 if (subtype & VSNUL)
11370 switch (subtype & VSTYPE) {
11389 case VSTRIMLEFTMAX:
11396 case VSTRIMRIGHTMAX:
11403 out1fmt("<subtype %d>", subtype);
11410 case CTLBACKQ|CTLQUOTE:
11413 shtree(bqlist->n, -1, NULL, fp);
11425 indent(int amount, char *pfx, FILE *fp)
11429 for (i = 0 ; i < amount ; i++) {
11430 if (pfx && i == amount - 1)
11451 putc(c, tracefile);
11455 trace(const char *fmt, ...)
11462 (void) vfprintf(tracefile, fmt, va);
11467 tracev(const char *fmt, va_list va)
11471 (void) vfprintf(tracefile, fmt, va);
11476 trputs(const char *s)
11480 fputs(s, tracefile);
11492 putc('"', tracefile);
11493 for (p = s ; *p ; p++) {
11495 case '\n': c = 'n'; goto backslash;
11496 case '\t': c = 't'; goto backslash;
11497 case '\r': c = 'r'; goto backslash;
11498 case '"': c = '"'; goto backslash;
11499 case '\\': c = '\\'; goto backslash;
11500 case CTLESC: c = 'e'; goto backslash;
11501 case CTLVAR: c = 'v'; goto backslash;
11502 case CTLVAR+CTLQUOTE: c = 'V'; goto backslash;
11503 case CTLBACKQ: c = 'q'; goto backslash;
11504 case CTLBACKQ+CTLQUOTE: c = 'Q'; goto backslash;
11505 backslash: putc('\\', tracefile);
11506 putc(c, tracefile);
11509 if (*p >= ' ' && *p <= '~')
11510 putc(*p, tracefile);
11512 putc('\\', tracefile);
11513 putc(*p >> 6 & 03, tracefile);
11514 putc(*p >> 3 & 07, tracefile);
11515 putc(*p & 07, tracefile);
11520 putc('"', tracefile);
11532 putc(' ', tracefile);
11534 putc('\n', tracefile);
11550 /* leave open because libedit might be using it */
11553 scopy("./trace", s);
11555 if (!freopen(s, "a", tracefile)) {
11556 fprintf(stderr, "Can't re-open %s\n", s);
11561 if ((tracefile = fopen(s, "a")) == NULL) {
11562 fprintf(stderr, "Can't open %s\n", s);
11568 if ((flags = fcntl(fileno(tracefile), F_GETFL, 0)) >= 0)
11569 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
11571 setlinebuf(tracefile);
11572 fputs("\nTracing started.\n", tracefile);
11580 * Sigmode records the current value of the signal handlers for the various
11581 * modes. A value of zero means that the current handler is not known.
11582 * S_HARD_IGN indicates that the signal was ignored on entry to the shell,
11585 #define S_DFL 1 /* default signal handling (SIG_DFL) */
11586 #define S_CATCH 2 /* signal is caught */
11587 #define S_IGN 3 /* signal is ignored (SIG_IGN) */
11588 #define S_HARD_IGN 4 /* signal is ignored permenantly */
11589 #define S_RESET 5 /* temporary - to reset a hard ignored sig */
11594 * The trap builtin.
11598 trapcmd(int argc, char **argv)
11607 for (signo = 0 ; signo < NSIG ; signo++) {
11608 if (trap[signo] != NULL) {
11611 sn = u_signal_names(0, &signo, 0);
11614 out1fmt("trap -- %s %s\n",
11615 single_quote(trap[signo]), sn);
11625 if ((signo = decode_signal(*ap, 0)) < 0)
11626 sh_error("%s: bad trap", *ap);
11629 if (action[0] == '-' && action[1] == '\0')
11632 action = savestr(action);
11635 ckfree(trap[signo]);
11636 trap[signo] = action;
11647 * Clear traps on a fork.
11655 for (tp = trap ; tp < &trap[NSIG] ; tp++) {
11656 if (*tp && **tp) { /* trap not NULL or SIG_IGN */
11660 if (tp != &trap[0])
11661 setsignal(tp - trap);
11669 * Set the signal handler for the specified signal. The routine figures
11670 * out what it should be set to.
11674 setsignal(int signo)
11678 struct sigaction act;
11680 if ((t = trap[signo]) == NULL)
11682 else if (*t != '\0')
11686 if (rootshell && action == S_DFL) {
11689 if (iflag || minusc || sflag == 0)
11712 t = &sigmode[signo - 1];
11716 * current setting unknown
11718 if (sigaction(signo, 0, &act) == -1) {
11720 * Pretend it worked; maybe we should give a warning
11721 * here, but other shells don't. We don't alter
11722 * sigmode, so that we retry every time.
11726 if (act.sa_handler == SIG_IGN) {
11727 if (mflag && (signo == SIGTSTP ||
11728 signo == SIGTTIN || signo == SIGTTOU)) {
11729 tsig = S_IGN; /* don't hard ignore these */
11733 tsig = S_RESET; /* force to be set */
11736 if (tsig == S_HARD_IGN || tsig == action)
11740 act.sa_handler = onsig;
11743 act.sa_handler = SIG_IGN;
11746 act.sa_handler = SIG_DFL;
11750 sigfillset(&act.sa_mask);
11751 sigaction(signo, &act, 0);
11759 ignoresig(int signo)
11761 if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
11762 signal(signo, SIG_IGN);
11764 sigmode[signo - 1] = S_HARD_IGN;
11775 gotsig[signo - 1] = 1;
11776 pendingsigs = signo;
11778 if (exsig || (signo == SIGINT && !trap[SIGINT])) {
11787 * Called to execute a trap. Perhaps we should avoid entering new trap
11788 * handlers while we are executing a trap handler.
11800 savestatus = exitstatus;
11804 for (i = 0, q = gotsig; i < NSIG - 1; i++, q++) {
11812 skip = evalstring(p, SKIPEVAL);
11813 exitstatus = savestatus;
11823 * Controls whether the shell is interactive or not.
11827 setinteractive(int on)
11829 static int is_interactive;
11831 if (++on == is_interactive)
11833 is_interactive = on;
11835 setsignal(SIGQUIT);
11836 setsignal(SIGTERM);
11837 #ifndef CONFIG_FEATURE_SH_EXTRA_QUIET
11838 if(is_interactive > 1) {
11839 /* Looks like they want an interactive shell */
11840 static int do_banner;
11844 "\n\n" BB_BANNER " Built-in shell (ash)\n"
11845 "Enter 'help' for a list of built-in commands.\n\n");
11853 #ifndef CONFIG_FEATURE_SH_EXTRA_QUIET
11854 /*** List the available builtins ***/
11856 static int helpcmd(int argc, char **argv)
11860 out1fmt("\nBuilt-in commands:\n-------------------\n");
11861 for (col = 0, i = 0; i < NUMBUILTINS; i++) {
11862 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '),
11863 builtincmd[i].name + 1);
11869 #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
11871 extern const struct BB_applet applets[];
11872 extern const size_t NUM_APPLETS;
11874 for (i = 0; i < NUM_APPLETS; i++) {
11876 col += out1fmt("%c%s", ((col == 0) ? '\t' : ' '), applets[i].name);
11885 return EXIT_SUCCESS;
11887 #endif /* CONFIG_FEATURE_SH_EXTRA_QUIET */
11890 * Called to exit the shell.
11900 status = exitstatus;
11901 TRACE(("pid %d, exitshell(%d)\n", getpid(), status));
11902 if (setjmp(loc.loc)) {
11903 if (exception == EXEXIT)
11908 if ((p = trap[0])) {
11914 #ifdef CONFIG_FEATURE_COMMAND_SAVEHISTORY
11915 if (iflag && rootshell) {
11916 const char *hp = lookupvar("HISTFILE");
11919 save_history ( hp );
11927 static int decode_signal(const char *string, int minsig)
11930 const char *name = u_signal_names(string, &signo, minsig);
11932 return name ? signo : -1;
11937 static struct var *vartab[VTABSIZE];
11939 static int vpcmp(const void *, const void *);
11940 static struct var **findvar(struct var **, const char *);
11943 * Initialize the variable symbol tables and import the environment
11947 #ifdef CONFIG_ASH_GETOPTS
11949 * Safe version of setvar, returns 1 on success 0 on failure.
11953 setvarsafe(const char *name, const char *val, int flags)
11956 volatile int saveint;
11957 struct jmploc *volatile savehandler = handler;
11958 struct jmploc jmploc;
11961 if (setjmp(jmploc.loc))
11965 setvar(name, val, flags);
11968 handler = savehandler;
11969 RESTOREINT(saveint);
11975 * Set the value of a variable. The flags argument is ored with the
11976 * flags of the variable. If val is NULL, the variable is unset.
11980 setvar(const char *name, const char *val, int flags)
11987 q = endofname(name);
11988 p = strchrnul(q, '=');
11989 namelen = p - name;
11990 if (!namelen || p != q)
11991 sh_error("%.*s: bad variable name", namelen, name);
11996 vallen = strlen(val);
11999 p = mempcpy(nameeq = ckmalloc(namelen + vallen + 2), name, namelen);
12002 p = mempcpy(p, val, vallen);
12005 setvareq(nameeq, flags | VNOSAVE);
12011 * Same as setvar except that the variable and value are passed in
12012 * the first argument as name=value. Since the first argument will
12013 * be actually stored in the table, it should not be a string that
12015 * Called with interrupts off.
12019 setvareq(char *s, int flags)
12021 struct var *vp, **vpp;
12024 flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
12025 vp = *findvar(vpp, s);
12027 if ((vp->flags & (VREADONLY|VDYNAMIC)) == VREADONLY) {
12030 if (flags & VNOSAVE)
12033 sh_error("%.*s: is read only", strchrnul(n, '=') - n, n);
12036 if (flags & VNOSET)
12039 if (vp->func && (flags & VNOFUNC) == 0)
12040 (*vp->func)(strchrnul(s, '=') + 1);
12042 if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
12045 flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET);
12047 if (flags & VNOSET)
12050 vp = ckmalloc(sizeof (*vp));
12055 if (!(flags & (VTEXTFIXED|VSTACK|VNOSAVE)))
12063 * Process a linked list of variable assignments.
12067 listsetvar(struct strlist *list_set_var, int flags)
12069 struct strlist *lp = list_set_var;
12075 setvareq(lp->text, flags);
12076 } while ((lp = lp->next));
12082 * Find the value of a variable. Returns NULL if not set.
12086 lookupvar(const char *name)
12090 if ((v = *findvar(hashvar(name), name))) {
12093 * Dynamic variables are implemented roughly the same way they are
12094 * in bash. Namely, they're "special" so long as they aren't unset.
12095 * As soon as they're unset, they're no longer dynamic, and dynamic
12096 * lookup will no longer happen at that point. -- PFM.
12098 if((v->flags & VDYNAMIC))
12101 if(!(v->flags & VUNSET))
12102 return strchrnul(v->text, '=') + 1;
12110 * Search the environment of a builtin command.
12114 bltinlookup(const char *name)
12116 struct strlist *sp;
12118 for (sp = cmdenviron ; sp ; sp = sp->next) {
12119 if (varequal(sp->text, name))
12120 return strchrnul(sp->text, '=') + 1;
12122 return lookupvar(name);
12127 * Generate a list of variables satisfying the given conditions.
12131 listvars(int on, int off, char ***end)
12142 for (vp = *vpp ; vp ; vp = vp->next)
12143 if ((vp->flags & mask) == on) {
12144 if (ep == stackstrend())
12145 ep = growstackstr();
12146 *ep++ = (char *) vp->text;
12148 } while (++vpp < vartab + VTABSIZE);
12149 if (ep == stackstrend())
12150 ep = growstackstr();
12154 return grabstackstr(ep);
12159 * POSIX requires that 'set' (but not export or readonly) output the
12160 * variables in lexicographic order - by the locale's collating order (sigh).
12161 * Maybe we could keep them in an ordered balanced binary tree
12162 * instead of hashed lists.
12163 * For now just roll 'em through qsort for printing...
12167 showvars(const char *sep_prefix, int on, int off)
12170 char **ep, **epend;
12172 ep = listvars(on, off, &epend);
12173 qsort(ep, epend - ep, sizeof(char *), vpcmp);
12175 sep = *sep_prefix ? spcstr : sep_prefix;
12177 for (; ep < epend; ep++) {
12181 p = strchrnul(*ep, '=');
12184 q = single_quote(++p);
12186 out1fmt("%s%s%.*s%s\n", sep_prefix, sep, (int)(p - *ep), *ep, q);
12195 * The export and readonly commands.
12199 exportcmd(int argc, char **argv)
12205 int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT;
12208 notp = nextopt("p") - 'p';
12209 if (notp && ((name = *(aptr = argptr)))) {
12211 if ((p = strchr(name, '=')) != NULL) {
12214 if ((vp = *findvar(hashvar(name), name))) {
12219 setvar(name, p, flag);
12220 } while ((name = *++aptr) != NULL);
12222 showvars(argv[0], flag, 0);
12229 * Make a variable a local variable. When a variable is made local, it's
12230 * value and flags are saved in a localvar structure. The saved values
12231 * will be restored when the shell function returns. We handle the name
12232 * "-" as a special case.
12236 mklocal(char *name)
12238 struct localvar *lvp;
12243 lvp = ckmalloc(sizeof (struct localvar));
12244 if (name[0] == '-' && name[1] == '\0') {
12246 p = ckmalloc(sizeof(optlist));
12247 lvp->text = memcpy(p, optlist, sizeof(optlist));
12252 vpp = hashvar(name);
12253 vp = *findvar(vpp, name);
12254 eq = strchr(name, '=');
12257 setvareq(name, VSTRFIXED);
12259 setvar(name, NULL, VSTRFIXED);
12260 vp = *vpp; /* the new variable */
12261 lvp->flags = VUNSET;
12263 lvp->text = vp->text;
12264 lvp->flags = vp->flags;
12265 vp->flags |= VSTRFIXED|VTEXTFIXED;
12271 lvp->next = localvars;
12277 * The "local" command.
12281 localcmd(int argc, char **argv)
12286 while ((name = *argv++) != NULL) {
12294 * Called after a function returns.
12295 * Interrupts must be off.
12301 struct localvar *lvp;
12304 while ((lvp = localvars) != NULL) {
12305 localvars = lvp->next;
12307 TRACE(("poplocalvar %s", vp ? vp->text : "-"));
12308 if (vp == NULL) { /* $- saved */
12309 memcpy(optlist, lvp->text, sizeof(optlist));
12312 } else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
12313 unsetvar(vp->text);
12316 (*vp->func)(strchrnul(lvp->text, '=') + 1);
12317 if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
12319 vp->flags = lvp->flags;
12320 vp->text = lvp->text;
12328 * The unset builtin command. We unset the function before we unset the
12329 * variable to allow a function to be unset when there is a readonly variable
12330 * with the same name.
12334 unsetcmd(int argc, char **argv)
12341 while ((i = nextopt("vf")) != '\0') {
12345 for (ap = argptr; *ap ; ap++) {
12360 * Unset the specified variable.
12364 unsetvar(const char *s)
12370 vpp = findvar(hashvar(s), s);
12374 int flags = vp->flags;
12377 if (flags & VREADONLY)
12380 vp->flags &= ~VDYNAMIC;
12382 if (flags & VUNSET)
12384 if ((flags & VSTRFIXED) == 0) {
12386 if ((flags & (VTEXTFIXED|VSTACK)) == 0)
12393 vp->flags &= ~VEXPORT;
12406 * Find the appropriate entry in the hash table from the name.
12409 static struct var **
12410 hashvar(const char *p)
12412 unsigned int hashval;
12414 hashval = ((unsigned char) *p) << 4;
12415 while (*p && *p != '=')
12416 hashval += (unsigned char) *p++;
12417 return &vartab[hashval % VTABSIZE];
12423 * Compares two strings up to the first = or '\0'. The first
12424 * string must be terminated by '='; the second may be terminated by
12425 * either '=' or '\0'.
12429 varcmp(const char *p, const char *q)
12433 while ((c = *p) == (d = *q)) {
12434 if (!c || c == '=')
12448 vpcmp(const void *a, const void *b)
12450 return varcmp(*(const char **)a, *(const char **)b);
12453 static struct var **
12454 findvar(struct var **vpp, const char *name)
12456 for (; *vpp; vpp = &(*vpp)->next) {
12457 if (varequal((*vpp)->text, name)) {
12465 #include <sys/times.h>
12467 static const unsigned char timescmd_str[] = {
12468 ' ', offsetof(struct tms, tms_utime),
12469 '\n', offsetof(struct tms, tms_stime),
12470 ' ', offsetof(struct tms, tms_cutime),
12471 '\n', offsetof(struct tms, tms_cstime),
12475 static int timescmd(int ac, char **av)
12477 long int clk_tck, s, t;
12478 const unsigned char *p;
12481 clk_tck = sysconf(_SC_CLK_TCK);
12486 t = *(clock_t *)(((char *) &buf) + p[1]);
12488 out1fmt("%ldm%ld.%.3lds%c",
12490 ((t - s * clk_tck) * 1000) / clk_tck,
12492 } while (*(p += 2));
12497 #ifdef CONFIG_ASH_MATH_SUPPORT
12499 dash_arith(const char *s)
12505 result = arith(s, &errcode);
12508 sh_error("exponent less than 0");
12509 else if (errcode == -2)
12510 sh_error("divide by zero");
12511 else if (errcode == -5)
12512 sh_error("expression recursion loop detected");
12523 * The let builtin. partial stolen from GNU Bash, the Bourne Again SHell.
12524 * Copyright (C) 1987, 1989, 1991 Free Software Foundation, Inc.
12526 * Copyright (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
12530 letcmd(int argc, char **argv)
12537 sh_error("expression expected");
12538 for (ap = argv + 1; *ap; ap++) {
12539 i = dash_arith(*ap);
12544 #endif /* CONFIG_ASH_MATH_SUPPORT */
12549 * Miscellaneous builtins.
12555 #if __GLIBC__ == 2 && __GLIBC_MINOR__ < 1
12556 typedef enum __rlimit_resource rlim_t;
12562 * The read builtin. The -e option causes backslashes to escape the
12563 * following character.
12565 * This uses unbuffered input, which may be avoidable in some cases.
12569 readcmd(int argc, char **argv)
12581 #if defined(CONFIG_ASH_READ_NCHARS)
12585 struct termios tty, old_tty;
12587 #if defined(CONFIG_ASH_READ_TIMEOUT)
12591 ts.tv_sec = ts.tv_usec = 0;
12596 #if defined(CONFIG_ASH_READ_NCHARS) && defined(CONFIG_ASH_READ_TIMEOUT)
12597 while ((i = nextopt("p:rt:n:s")) != '\0')
12598 #elif defined(CONFIG_ASH_READ_NCHARS)
12599 while ((i = nextopt("p:rn:s")) != '\0')
12600 #elif defined(CONFIG_ASH_READ_TIMEOUT)
12601 while ((i = nextopt("p:rt:")) != '\0')
12603 while ((i = nextopt("p:r")) != '\0')
12608 prompt = optionarg;
12610 #if defined(CONFIG_ASH_READ_NCHARS)
12612 nchars = strtol(optionarg, &p, 10);
12614 sh_error("invalid count");
12615 nch_flag = (nchars > 0);
12621 #if defined(CONFIG_ASH_READ_TIMEOUT)
12623 ts.tv_sec = strtol(optionarg, &p, 10);
12629 ts.tv_usec = strtol(p, &p2, 10);
12631 sh_error("invalid timeout");
12633 /* normalize to usec */
12635 sh_error("invalid timeout");
12636 while (scale++ < 6)
12640 sh_error("invalid timeout");
12642 if ( ! ts.tv_sec && ! ts.tv_usec)
12643 sh_error("invalid timeout");
12653 if (prompt && isatty(0)) {
12656 if (*(ap = argptr) == NULL)
12657 sh_error("arg count");
12658 if ((ifs = bltinlookup("IFS")) == NULL)
12660 #if defined(CONFIG_ASH_READ_NCHARS)
12661 if (nch_flag || silent) {
12662 tcgetattr(0, &tty);
12665 tty.c_lflag &= ~ICANON;
12666 tty.c_cc[VMIN] = nchars;
12669 tty.c_lflag &= ~(ECHO|ECHOK|ECHONL);
12672 tcsetattr(0, TCSANOW, &tty);
12675 #if defined(CONFIG_ASH_READ_TIMEOUT)
12676 if (ts.tv_sec || ts.tv_usec) {
12680 i = select (FD_SETSIZE, &set, NULL, NULL, &ts);
12682 #if defined(CONFIG_ASH_READ_NCHARS)
12684 tcsetattr(0, TCSANOW, &old_tty);
12694 #if defined(CONFIG_ASH_READ_NCHARS)
12695 while (!nch_flag || nchars--)
12700 if (read(0, &c, 1) != 1) {
12712 if (!rflag && c == '\\') {
12718 if (startword && *ifs == ' ' && strchr(ifs, c)) {
12722 if (ap[1] != NULL && strchr(ifs, c) != NULL) {
12724 setvar(*ap, stackblock(), 0);
12733 #if defined(CONFIG_ASH_READ_NCHARS)
12734 if (nch_flag || silent)
12735 tcsetattr(0, TCSANOW, &old_tty);
12739 /* Remove trailing blanks */
12740 while ((char *)stackblock() <= --p && strchr(ifs, *p) != NULL)
12742 setvar(*ap, stackblock(), 0);
12743 while (*++ap != NULL)
12744 setvar(*ap, nullstr, 0);
12749 static int umaskcmd(int argc, char **argv)
12751 static const char permuser[3] = "ugo";
12752 static const char permmode[3] = "rwx";
12753 static const short int permmask[] = {
12754 S_IRUSR, S_IWUSR, S_IXUSR,
12755 S_IRGRP, S_IWGRP, S_IXGRP,
12756 S_IROTH, S_IWOTH, S_IXOTH
12762 int symbolic_mode = 0;
12764 while (nextopt("S") != '\0') {
12773 if ((ap = *argptr) == NULL) {
12774 if (symbolic_mode) {
12778 for (i = 0; i < 3; i++) {
12781 *p++ = permuser[i];
12783 for (j = 0; j < 3; j++) {
12784 if ((mask & permmask[3 * i + j]) == 0) {
12785 *p++ = permmode[j];
12793 out1fmt("%.4o\n", mask);
12796 if (is_digit((unsigned char) *ap)) {
12799 if (*ap >= '8' || *ap < '0')
12800 sh_error(illnum, argv[1]);
12801 mask = (mask << 3) + (*ap - '0');
12802 } while (*++ap != '\0');
12805 mask = ~mask & 0777;
12806 if (!bb_parse_mode(ap, &mask)) {
12807 sh_error("Illegal mode: %s", ap);
12809 umask(~mask & 0777);
12818 * This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and
12819 * Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with
12820 * ash by J.T. Conklin.
12828 int factor; /* multiply by to get rlim_{cur,max} values */
12832 static const struct limits limits[] = {
12834 { "time(seconds)", RLIMIT_CPU, 1, 't' },
12836 #ifdef RLIMIT_FSIZE
12837 { "file(blocks)", RLIMIT_FSIZE, 512, 'f' },
12840 { "data(kbytes)", RLIMIT_DATA, 1024, 'd' },
12842 #ifdef RLIMIT_STACK
12843 { "stack(kbytes)", RLIMIT_STACK, 1024, 's' },
12846 { "coredump(blocks)", RLIMIT_CORE, 512, 'c' },
12849 { "memory(kbytes)", RLIMIT_RSS, 1024, 'm' },
12851 #ifdef RLIMIT_MEMLOCK
12852 { "locked memory(kbytes)", RLIMIT_MEMLOCK, 1024, 'l' },
12854 #ifdef RLIMIT_NPROC
12855 { "process", RLIMIT_NPROC, 1, 'p' },
12857 #ifdef RLIMIT_NOFILE
12858 { "nofiles", RLIMIT_NOFILE, 1, 'n' },
12861 { "vmemory(kbytes)", RLIMIT_AS, 1024, 'v' },
12863 #ifdef RLIMIT_LOCKS
12864 { "locks", RLIMIT_LOCKS, 1, 'w' },
12866 { (char *) 0, 0, 0, '\0' }
12869 enum limtype { SOFT = 0x1, HARD = 0x2 };
12871 static void printlim(enum limtype how, const struct rlimit *limit,
12872 const struct limits *l)
12876 val = limit->rlim_max;
12878 val = limit->rlim_cur;
12880 if (val == RLIM_INFINITY)
12881 out1fmt("unlimited\n");
12884 out1fmt("%lld\n", (long long) val);
12889 ulimitcmd(int argc, char **argv)
12893 enum limtype how = SOFT | HARD;
12894 const struct limits *l;
12897 struct rlimit limit;
12900 while ((optc = nextopt("HSa"
12904 #ifdef RLIMIT_FSIZE
12910 #ifdef RLIMIT_STACK
12919 #ifdef RLIMIT_MEMLOCK
12922 #ifdef RLIMIT_NPROC
12925 #ifdef RLIMIT_NOFILE
12931 #ifdef RLIMIT_LOCKS
12949 for (l = limits; l->option != what; l++)
12952 set = *argptr ? 1 : 0;
12956 if (all || argptr[1])
12957 sh_error("too many arguments");
12958 if (strncmp(p, "unlimited\n", 9) == 0)
12959 val = RLIM_INFINITY;
12963 while ((c = *p++) >= '0' && c <= '9')
12965 val = (val * 10) + (long)(c - '0');
12966 if (val < (rlim_t) 0)
12970 sh_error("bad number");
12975 for (l = limits; l->name; l++) {
12976 getrlimit(l->cmd, &limit);
12977 out1fmt("%-20s ", l->name);
12978 printlim(how, &limit, l);
12983 getrlimit(l->cmd, &limit);
12986 limit.rlim_max = val;
12988 limit.rlim_cur = val;
12989 if (setrlimit(l->cmd, &limit) < 0)
12990 sh_error("error setting limit (%m)");
12992 printlim(how, &limit, l);
12998 #ifdef CONFIG_ASH_MATH_SUPPORT
13000 /* Copyright (c) 2001 Aaron Lehmann <aaronl@vitelus.com>
13002 Permission is hereby granted, free of charge, to any person obtaining
13003 a copy of this software and associated documentation files (the
13004 "Software"), to deal in the Software without restriction, including
13005 without limitation the rights to use, copy, modify, merge, publish,
13006 distribute, sublicense, and/or sell copies of the Software, and to
13007 permit persons to whom the Software is furnished to do so, subject to
13008 the following conditions:
13010 The above copyright notice and this permission notice shall be
13011 included in all copies or substantial portions of the Software.
13013 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
13014 EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
13015 MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
13016 IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
13017 CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
13018 TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
13019 SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
13022 /* This is my infix parser/evaluator. It is optimized for size, intended
13023 * as a replacement for yacc-based parsers. However, it may well be faster
13024 * than a comparable parser written in yacc. The supported operators are
13025 * listed in #defines below. Parens, order of operations, and error handling
13026 * are supported. This code is thread safe. The exact expression format should
13027 * be that which POSIX specifies for shells. */
13029 /* The code uses a simple two-stack algorithm. See
13030 * http://www.onthenet.com.au/~grahamis/int2008/week02/lect02.html
13031 * for a detailed explanation of the infix-to-postfix algorithm on which
13032 * this is based (this code differs in that it applies operators immediately
13033 * to the stack instead of adding them to a queue to end up with an
13036 /* To use the routine, call it with an expression string and error return
13040 * Aug 24, 2001 Manuel Novoa III
13042 * Reduced the generated code size by about 30% (i386) and fixed several bugs.
13044 * 1) In arith_apply():
13045 * a) Cached values of *numptr and &(numptr[-1]).
13046 * b) Removed redundant test for zero denominator.
13049 * a) Eliminated redundant code for processing operator tokens by moving
13050 * to a table-based implementation. Also folded handling of parens
13052 * b) Combined all 3 loops which called arith_apply to reduce generated
13053 * code size at the cost of speed.
13055 * 3) The following expressions were treated as valid by the original code:
13056 * 1() , 0! , 1 ( *3 ) .
13057 * These bugs have been fixed by internally enclosing the expression in
13058 * parens and then checking that all binary ops and right parens are
13059 * preceded by a valid expression (NUM_TOKEN).
13061 * Note: It may be desirable to replace Aaron's test for whitespace with
13062 * ctype's isspace() if it is used by another busybox applet or if additional
13063 * whitespace chars should be considered. Look below the "#include"s for a
13064 * precompiler test.
13068 * Aug 26, 2001 Manuel Novoa III
13070 * Return 0 for null expressions. Pointed out by Vladimir Oleynik.
13072 * Merge in Aaron's comments previously posted to the busybox list,
13073 * modified slightly to take account of my changes to the code.
13078 * (C) 2003 Vladimir Oleynik <dzo@simtreas.ru>
13080 * - allow access to variable,
13081 * used recursive find value indirection (c=2*2; a="c"; $((a+=2)) produce 6)
13082 * - realize assign syntax (VAR=expr, +=, *= etc)
13083 * - realize exponentiation (** operator)
13084 * - realize comma separated - expr, expr
13085 * - realise ++expr --expr expr++ expr--
13086 * - realise expr ? expr : expr (but, second expr calculate always)
13087 * - allow hexadecimal and octal numbers
13088 * - was restored loses XOR operator
13089 * - remove one goto label, added three ;-)
13090 * - protect $((num num)) as true zero expr (Manuel`s error)
13091 * - always use special isspace(), see comment from bash ;-)
13095 #define arith_isspace(arithval) \
13096 (arithval == ' ' || arithval == '\n' || arithval == '\t')
13099 typedef unsigned char operator;
13101 /* An operator's token id is a bit of a bitfield. The lower 5 bits are the
13102 * precedence, and 3 high bits are an ID unique across operators of that
13103 * precedence. The ID portion is so that multiple operators can have the
13104 * same precedence, ensuring that the leftmost one is evaluated first.
13105 * Consider * and /. */
13107 #define tok_decl(prec,id) (((id)<<5)|(prec))
13108 #define PREC(op) ((op) & 0x1F)
13110 #define TOK_LPAREN tok_decl(0,0)
13112 #define TOK_COMMA tok_decl(1,0)
13114 #define TOK_ASSIGN tok_decl(2,0)
13115 #define TOK_AND_ASSIGN tok_decl(2,1)
13116 #define TOK_OR_ASSIGN tok_decl(2,2)
13117 #define TOK_XOR_ASSIGN tok_decl(2,3)
13118 #define TOK_PLUS_ASSIGN tok_decl(2,4)
13119 #define TOK_MINUS_ASSIGN tok_decl(2,5)
13120 #define TOK_LSHIFT_ASSIGN tok_decl(2,6)
13121 #define TOK_RSHIFT_ASSIGN tok_decl(2,7)
13123 #define TOK_MUL_ASSIGN tok_decl(3,0)
13124 #define TOK_DIV_ASSIGN tok_decl(3,1)
13125 #define TOK_REM_ASSIGN tok_decl(3,2)
13127 /* all assign is right associativity and precedence eq, but (7+3)<<5 > 256 */
13128 #define convert_prec_is_assing(prec) do { if(prec == 3) prec = 2; } while(0)
13130 /* conditional is right associativity too */
13131 #define TOK_CONDITIONAL tok_decl(4,0)
13132 #define TOK_CONDITIONAL_SEP tok_decl(4,1)
13134 #define TOK_OR tok_decl(5,0)
13136 #define TOK_AND tok_decl(6,0)
13138 #define TOK_BOR tok_decl(7,0)
13140 #define TOK_BXOR tok_decl(8,0)
13142 #define TOK_BAND tok_decl(9,0)
13144 #define TOK_EQ tok_decl(10,0)
13145 #define TOK_NE tok_decl(10,1)
13147 #define TOK_LT tok_decl(11,0)
13148 #define TOK_GT tok_decl(11,1)
13149 #define TOK_GE tok_decl(11,2)
13150 #define TOK_LE tok_decl(11,3)
13152 #define TOK_LSHIFT tok_decl(12,0)
13153 #define TOK_RSHIFT tok_decl(12,1)
13155 #define TOK_ADD tok_decl(13,0)
13156 #define TOK_SUB tok_decl(13,1)
13158 #define TOK_MUL tok_decl(14,0)
13159 #define TOK_DIV tok_decl(14,1)
13160 #define TOK_REM tok_decl(14,2)
13162 /* exponent is right associativity */
13163 #define TOK_EXPONENT tok_decl(15,1)
13165 /* For now unary operators. */
13166 #define UNARYPREC 16
13167 #define TOK_BNOT tok_decl(UNARYPREC,0)
13168 #define TOK_NOT tok_decl(UNARYPREC,1)
13170 #define TOK_UMINUS tok_decl(UNARYPREC+1,0)
13171 #define TOK_UPLUS tok_decl(UNARYPREC+1,1)
13173 #define PREC_PRE (UNARYPREC+2)
13175 #define TOK_PRE_INC tok_decl(PREC_PRE, 0)
13176 #define TOK_PRE_DEC tok_decl(PREC_PRE, 1)
13178 #define PREC_POST (UNARYPREC+3)
13180 #define TOK_POST_INC tok_decl(PREC_POST, 0)
13181 #define TOK_POST_DEC tok_decl(PREC_POST, 1)
13183 #define SPEC_PREC (UNARYPREC+4)
13185 #define TOK_NUM tok_decl(SPEC_PREC, 0)
13186 #define TOK_RPAREN tok_decl(SPEC_PREC, 1)
13188 #define NUMPTR (*numstackptr)
13190 static inline int tok_have_assign(operator op)
13192 operator prec = PREC(op);
13194 convert_prec_is_assing(prec);
13195 return (prec == PREC(TOK_ASSIGN) ||
13196 prec == PREC_PRE || prec == PREC_POST);
13199 static inline int is_right_associativity(operator prec)
13201 return (prec == PREC(TOK_ASSIGN) || prec == PREC(TOK_EXPONENT) ||
13202 prec == PREC(TOK_CONDITIONAL));
13206 typedef struct ARITCH_VAR_NUM {
13208 arith_t contidional_second_val;
13209 char contidional_second_val_initialized;
13210 char *var; /* if NULL then is regular number,
13211 else is variable name */
13215 typedef struct CHK_VAR_RECURSIVE_LOOPED {
13217 struct CHK_VAR_RECURSIVE_LOOPED *next;
13218 } chk_var_recursive_looped_t;
13220 static chk_var_recursive_looped_t *prev_chk_var_recursive;
13223 static int arith_lookup_val(v_n_t *t)
13226 const char * p = lookupvar(t->var);
13231 /* recursive try as expression */
13232 chk_var_recursive_looped_t *cur;
13233 chk_var_recursive_looped_t cur_save;
13235 for(cur = prev_chk_var_recursive; cur; cur = cur->next) {
13236 if(strcmp(cur->var, t->var) == 0) {
13237 /* expression recursion loop detected */
13241 /* save current lookuped var name */
13242 cur = prev_chk_var_recursive;
13243 cur_save.var = t->var;
13244 cur_save.next = cur;
13245 prev_chk_var_recursive = &cur_save;
13247 t->val = arith (p, &errcode);
13248 /* restore previous ptr after recursiving */
13249 prev_chk_var_recursive = cur;
13252 /* allow undefined var as 0 */
13259 /* "applying" a token means performing it on the top elements on the integer
13260 * stack. For a unary operator it will only change the top element, but a
13261 * binary operator will pop two arguments and push a result */
13263 arith_apply(operator op, v_n_t *numstack, v_n_t **numstackptr)
13266 arith_t numptr_val, rez;
13267 int ret_arith_lookup_val;
13269 if (NUMPTR == numstack) goto err; /* There is no operator that can work
13270 without arguments */
13271 numptr_m1 = NUMPTR - 1;
13273 /* check operand is var with noninteger value */
13274 ret_arith_lookup_val = arith_lookup_val(numptr_m1);
13275 if(ret_arith_lookup_val)
13276 return ret_arith_lookup_val;
13278 rez = numptr_m1->val;
13279 if (op == TOK_UMINUS)
13281 else if (op == TOK_NOT)
13283 else if (op == TOK_BNOT)
13285 else if (op == TOK_POST_INC || op == TOK_PRE_INC)
13287 else if (op == TOK_POST_DEC || op == TOK_PRE_DEC)
13289 else if (op != TOK_UPLUS) {
13290 /* Binary operators */
13292 /* check and binary operators need two arguments */
13293 if (numptr_m1 == numstack) goto err;
13295 /* ... and they pop one */
13298 if (op == TOK_CONDITIONAL) {
13299 if(! numptr_m1->contidional_second_val_initialized) {
13300 /* protect $((expr1 ? expr2)) without ": expr" */
13303 rez = numptr_m1->contidional_second_val;
13304 } else if(numptr_m1->contidional_second_val_initialized) {
13305 /* protect $((expr1 : expr2)) without "expr ? " */
13308 numptr_m1 = NUMPTR - 1;
13309 if(op != TOK_ASSIGN) {
13310 /* check operand is var with noninteger value for not '=' */
13311 ret_arith_lookup_val = arith_lookup_val(numptr_m1);
13312 if(ret_arith_lookup_val)
13313 return ret_arith_lookup_val;
13315 if (op == TOK_CONDITIONAL) {
13316 numptr_m1->contidional_second_val = rez;
13318 rez = numptr_m1->val;
13319 if (op == TOK_BOR || op == TOK_OR_ASSIGN)
13321 else if (op == TOK_OR)
13322 rez = numptr_val || rez;
13323 else if (op == TOK_BAND || op == TOK_AND_ASSIGN)
13325 else if (op == TOK_BXOR || op == TOK_XOR_ASSIGN)
13327 else if (op == TOK_AND)
13328 rez = rez && numptr_val;
13329 else if (op == TOK_EQ)
13330 rez = (rez == numptr_val);
13331 else if (op == TOK_NE)
13332 rez = (rez != numptr_val);
13333 else if (op == TOK_GE)
13334 rez = (rez >= numptr_val);
13335 else if (op == TOK_RSHIFT || op == TOK_RSHIFT_ASSIGN)
13336 rez >>= numptr_val;
13337 else if (op == TOK_LSHIFT || op == TOK_LSHIFT_ASSIGN)
13338 rez <<= numptr_val;
13339 else if (op == TOK_GT)
13340 rez = (rez > numptr_val);
13341 else if (op == TOK_LT)
13342 rez = (rez < numptr_val);
13343 else if (op == TOK_LE)
13344 rez = (rez <= numptr_val);
13345 else if (op == TOK_MUL || op == TOK_MUL_ASSIGN)
13347 else if (op == TOK_ADD || op == TOK_PLUS_ASSIGN)
13349 else if (op == TOK_SUB || op == TOK_MINUS_ASSIGN)
13351 else if (op == TOK_ASSIGN || op == TOK_COMMA)
13353 else if (op == TOK_CONDITIONAL_SEP) {
13354 if (numptr_m1 == numstack) {
13355 /* protect $((expr : expr)) without "expr ? " */
13358 numptr_m1->contidional_second_val_initialized = op;
13359 numptr_m1->contidional_second_val = numptr_val;
13361 else if (op == TOK_CONDITIONAL) {
13363 numptr_val : numptr_m1->contidional_second_val;
13365 else if(op == TOK_EXPONENT) {
13367 return -3; /* exponent less than 0 */
13372 while(numptr_val--)
13377 else if(numptr_val==0) /* zero divisor check */
13379 else if (op == TOK_DIV || op == TOK_DIV_ASSIGN)
13381 else if (op == TOK_REM || op == TOK_REM_ASSIGN)
13384 if(tok_have_assign(op)) {
13387 if(numptr_m1->var == NULL) {
13391 /* save to shell variable */
13392 #ifdef CONFIG_ASH_MATH_SUPPORT_64
13393 snprintf(buf, sizeof(buf), "%lld", rez);
13395 snprintf(buf, sizeof(buf), "%ld", rez);
13397 setvar(numptr_m1->var, buf, 0);
13398 /* after saving, make previous value for v++ or v-- */
13399 if(op == TOK_POST_INC)
13401 else if(op == TOK_POST_DEC)
13404 numptr_m1->val = rez;
13405 /* protect geting var value, is number now */
13406 numptr_m1->var = NULL;
13411 /* longest must first */
13412 static const char op_tokens[] = {
13413 '<','<','=',0, TOK_LSHIFT_ASSIGN,
13414 '>','>','=',0, TOK_RSHIFT_ASSIGN,
13415 '<','<', 0, TOK_LSHIFT,
13416 '>','>', 0, TOK_RSHIFT,
13417 '|','|', 0, TOK_OR,
13418 '&','&', 0, TOK_AND,
13419 '!','=', 0, TOK_NE,
13420 '<','=', 0, TOK_LE,
13421 '>','=', 0, TOK_GE,
13422 '=','=', 0, TOK_EQ,
13423 '|','=', 0, TOK_OR_ASSIGN,
13424 '&','=', 0, TOK_AND_ASSIGN,
13425 '*','=', 0, TOK_MUL_ASSIGN,
13426 '/','=', 0, TOK_DIV_ASSIGN,
13427 '%','=', 0, TOK_REM_ASSIGN,
13428 '+','=', 0, TOK_PLUS_ASSIGN,
13429 '-','=', 0, TOK_MINUS_ASSIGN,
13430 '-','-', 0, TOK_POST_DEC,
13431 '^','=', 0, TOK_XOR_ASSIGN,
13432 '+','+', 0, TOK_POST_INC,
13433 '*','*', 0, TOK_EXPONENT,
13437 '=', 0, TOK_ASSIGN,
13449 '?', 0, TOK_CONDITIONAL,
13450 ':', 0, TOK_CONDITIONAL_SEP,
13451 ')', 0, TOK_RPAREN,
13452 '(', 0, TOK_LPAREN,
13456 #define endexpression &op_tokens[sizeof(op_tokens)-7]
13459 static arith_t arith (const char *expr, int *perrcode)
13461 register char arithval; /* Current character under analysis */
13462 operator lasttok, op;
13465 const char *p = endexpression;
13468 size_t datasizes = strlen(expr) + 2;
13470 /* Stack of integers */
13471 /* The proof that there can be no more than strlen(startbuf)/2+1 integers
13472 * in any given correct or incorrect expression is left as an exercise to
13474 v_n_t *numstack = alloca(((datasizes)/2)*sizeof(v_n_t)),
13475 *numstackptr = numstack;
13476 /* Stack of operator tokens */
13477 operator *stack = alloca((datasizes) * sizeof(operator)),
13480 *stackptr++ = lasttok = TOK_LPAREN; /* start off with a left paren */
13481 *perrcode = errcode = 0;
13484 if ((arithval = *expr) == 0) {
13485 if (p == endexpression) {
13486 /* Null expression. */
13490 /* This is only reached after all tokens have been extracted from the
13491 * input stream. If there are still tokens on the operator stack, they
13492 * are to be applied in order. At the end, there should be a final
13493 * result on the integer stack */
13495 if (expr != endexpression + 1) {
13496 /* If we haven't done so already, */
13497 /* append a closing right paren */
13498 expr = endexpression;
13499 /* and let the loop process it. */
13502 /* At this point, we're done with the expression. */
13503 if (numstackptr != numstack+1) {
13504 /* ... but if there isn't, it's bad */
13506 return (*perrcode = -1);
13508 if(numstack->var) {
13509 /* expression is $((var)) only, lookup now */
13510 errcode = arith_lookup_val(numstack);
13513 *perrcode = errcode;
13514 return numstack->val;
13516 /* Continue processing the expression. */
13517 if (arith_isspace(arithval)) {
13518 /* Skip whitespace */
13521 if((p = endofname(expr)) != expr) {
13522 size_t var_name_size = (p-expr) + 1; /* trailing zero */
13524 numstackptr->var = alloca(var_name_size);
13525 safe_strncpy(numstackptr->var, expr, var_name_size);
13528 numstackptr->contidional_second_val_initialized = 0;
13532 } else if (is_digit(arithval)) {
13533 numstackptr->var = NULL;
13534 #ifdef CONFIG_ASH_MATH_SUPPORT_64
13535 numstackptr->val = strtoll(expr, (char **) &expr, 0);
13537 numstackptr->val = strtol(expr, (char **) &expr, 0);
13541 for(p = op_tokens; ; p++) {
13545 /* strange operator not found */
13548 for(o = expr; *p && *o == *p; p++)
13555 /* skip tail uncompared token */
13558 /* skip zero delim */
13563 /* post grammar: a++ reduce to num */
13564 if(lasttok == TOK_POST_INC || lasttok == TOK_POST_DEC)
13567 /* Plus and minus are binary (not unary) _only_ if the last
13568 * token was as number, or a right paren (which pretends to be
13569 * a number, since it evaluates to one). Think about it.
13570 * It makes sense. */
13571 if (lasttok != TOK_NUM) {
13587 /* We don't want a unary operator to cause recursive descent on the
13588 * stack, because there can be many in a row and it could cause an
13589 * operator to be evaluated before its argument is pushed onto the
13590 * integer stack. */
13591 /* But for binary operators, "apply" everything on the operator
13592 * stack until we find an operator with a lesser priority than the
13593 * one we have just extracted. */
13594 /* Left paren is given the lowest priority so it will never be
13595 * "applied" in this way.
13596 * if associativity is right and priority eq, applied also skip
13599 if ((prec > 0 && prec < UNARYPREC) || prec == SPEC_PREC) {
13600 /* not left paren or unary */
13601 if (lasttok != TOK_NUM) {
13602 /* binary op must be preceded by a num */
13605 while (stackptr != stack) {
13606 if (op == TOK_RPAREN) {
13607 /* The algorithm employed here is simple: while we don't
13608 * hit an open paren nor the bottom of the stack, pop
13609 * tokens and apply them */
13610 if (stackptr[-1] == TOK_LPAREN) {
13612 /* Any operator directly after a */
13614 /* close paren should consider itself binary */
13618 operator prev_prec = PREC(stackptr[-1]);
13620 convert_prec_is_assing(prec);
13621 convert_prec_is_assing(prev_prec);
13622 if (prev_prec < prec)
13624 /* check right assoc */
13625 if(prev_prec == prec && is_right_associativity(prec))
13628 errcode = arith_apply(*--stackptr, numstack, &numstackptr);
13629 if(errcode) goto ret;
13631 if (op == TOK_RPAREN) {
13636 /* Push this operator to the stack and remember it. */
13637 *stackptr++ = lasttok = op;
13644 #endif /* CONFIG_ASH_MATH_SUPPORT */
13648 const char *bb_applet_name = "debug stuff usage";
13649 int main(int argc, char **argv)
13651 return ash_main(argc, argv);
13656 * Copyright (c) 1989, 1991, 1993, 1994
13657 * The Regents of the University of California. All rights reserved.
13659 * This code is derived from software contributed to Berkeley by
13660 * Kenneth Almquist.
13662 * Redistribution and use in source and binary forms, with or without
13663 * modification, are permitted provided that the following conditions
13665 * 1. Redistributions of source code must retain the above copyright
13666 * notice, this list of conditions and the following disclaimer.
13667 * 2. Redistributions in binary form must reproduce the above copyright
13668 * notice, this list of conditions and the following disclaimer in the
13669 * documentation and/or other materials provided with the distribution.
13670 * 3. Neither the name of the University nor the names of its contributors
13671 * may be used to endorse or promote products derived from this software
13672 * without specific prior written permission.
13674 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
13675 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
13676 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
13677 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
13678 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
13679 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
13680 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
13681 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
13682 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
13683 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF