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 * This code is derived from software contributed to Berkeley by
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * General Public License for more details.
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 * This version of ash is adapted from the source in Debian's ash 0.3.8-5
28 * Modified by Erik Andersen <andersee@debian.org> and
29 * Vladimir Oleynik <dzo@simtreas.ru> to be used in busybox
32 * Original copyright notice is retained at the end of this file.
36 /* These defines allow you to adjust the feature set to be compiled
37 * into the ash shell. As a rule, enabling these options will make
38 * ash get bigger... With all of these options off, ash adds about
39 * 60k to busybox on an x86 system.*/
42 /* Enable job control. This allows you to run jobs in the background,
43 * which is great when ash is being used as an interactive shell, but
44 * it completely useless for is all you are doing is running scripts.
45 * This adds about 2.5k on an x86 system. */
48 /* This enables alias support in ash. If you want to support things
49 * like "alias ls='ls -l'" with ash, enable this. This is only useful
50 * when ash is used as an intractive shell. This adds about 1.5k */
53 /* If you need ash to act as a full Posix shell, with full math
54 * support, enable this. This adds a bit over 2k an x86 system. */
55 //#undef ASH_MATH_SUPPORT
56 #define ASH_MATH_SUPPORT
58 /* Getopts is used by shell procedures to parse positional parameters.
59 * You probably want to leave this disabled, and use the busybox getopt
60 * applet if you want to do this sort of thing. There are some scripts
61 * out there that use it, so it you need it, enable. Most people will
62 * leave this disabled. This adds 1k on an x86 system. */
65 /* This allows you to override shell builtins and use whatever is on
66 * the filesystem. This is most useful when ash is acting as a
67 * standalone shell. Adds about 272 bytes. */
71 /* Optimize size vs speed as size */
72 #define ASH_OPTIMIZE_FOR_SIZE
74 /* Enable this to compile in extra debugging noise. When debugging is
75 * on, debugging info will be written to $HOME/trace and a quit signal
76 * will generate a core dump. */
79 /* These are here to work with glibc -- Don't change these... */
101 #include <sys/stat.h>
102 #include <sys/cdefs.h>
103 #include <sys/ioctl.h>
104 #include <sys/param.h>
105 #include <sys/resource.h>
106 #include <sys/time.h>
107 #include <sys/times.h>
108 #include <sys/types.h>
109 #include <sys/wait.h>
112 #if !defined(FNMATCH_BROKEN)
115 #if !defined(GLOB_BROKEN)
127 * This file was generated by the mksyntax program.
131 #define CWORD 0 /* character is nothing special */
132 #define CNL 1 /* newline character */
133 #define CBACK 2 /* a backslash character */
134 #define CSQUOTE 3 /* single quote */
135 #define CDQUOTE 4 /* double quote */
136 #define CENDQUOTE 5 /* a terminating quote */
137 #define CBQUOTE 6 /* backwards single quote */
138 #define CVAR 7 /* a dollar sign */
139 #define CENDVAR 8 /* a '}' character */
140 #define CLP 9 /* a left paren in arithmetic */
141 #define CRP 10 /* a right paren in arithmetic */
142 #define CENDFILE 11 /* end of file */
143 #define CCTL 12 /* like CWORD, except it must be escaped */
144 #define CSPCL 13 /* these terminate a word */
145 #define CIGN 14 /* character should be ignored */
165 #define TENDBQUOTE 13
185 /* control characters in argument strings */
186 #define CTLESC '\201'
187 #define CTLVAR '\202'
188 #define CTLENDVAR '\203'
189 #define CTLBACKQ '\204'
190 #define CTLQUOTE 01 /* ored with CTLBACKQ code if in quotes */
191 /* CTLBACKQ | CTLQUOTE == '\205' */
192 #define CTLARI '\206'
193 #define CTLENDARI '\207'
194 #define CTLQUOTEMARK '\210'
197 #define is_digit(c) ((c)>='0' && (c)<='9')
198 #define is_name(c) (((c) < CTLESC || (c) > CTLENDARI) && ((c) == '_' || isalpha((unsigned char) (c))))
199 #define is_in_name(c) (((c) < CTLESC || (c) > CTLENDARI) && ((c) == '_' || isalnum((unsigned char) (c))))
202 * is_special(c) evaluates to 1 for c in "!#$*-0123456789?@"; 0 otherwise
203 * (assuming ascii char codes, as the original implementation did)
205 #define is_special(c) \
206 ( (((unsigned int)c) - 33 < 32) \
207 && ((0xc1ff920dUL >> (((unsigned int)c) - 33)) & 1))
209 #define digit_val(c) ((c) - '0')
212 #define _DIAGASSERT(x)
216 #define S_DFL 1 /* default signal handling (SIG_DFL) */
217 #define S_CATCH 2 /* signal is caught */
218 #define S_IGN 3 /* signal is ignored (SIG_IGN) */
219 #define S_HARD_IGN 4 /* signal is ignored permenantly */
220 #define S_RESET 5 /* temporary - to reset a hard ignored sig */
223 /* variable substitution byte (follows CTLVAR) */
224 #define VSTYPE 0x0f /* type of variable substitution */
225 #define VSNUL 0x10 /* colon--treat the empty string as unset */
226 #define VSQUOTE 0x80 /* inside double quotes--suppress splitting */
228 /* values of VSTYPE field */
229 #define VSNORMAL 0x1 /* normal variable: $var or ${var} */
230 #define VSMINUS 0x2 /* ${var-text} */
231 #define VSPLUS 0x3 /* ${var+text} */
232 #define VSQUESTION 0x4 /* ${var?message} */
233 #define VSASSIGN 0x5 /* ${var=text} */
234 #define VSTRIMLEFT 0x6 /* ${var#pattern} */
235 #define VSTRIMLEFTMAX 0x7 /* ${var##pattern} */
236 #define VSTRIMRIGHT 0x8 /* ${var%pattern} */
237 #define VSTRIMRIGHTMAX 0x9 /* ${var%%pattern} */
238 #define VSLENGTH 0xa /* ${#var} */
240 /* flags passed to redirect */
241 #define REDIR_PUSH 01 /* save previous values of file descriptors */
242 #define REDIR_BACKQ 02 /* save the command output to pipe */
245 * BSD setjmp saves the signal mask, which violates ANSI C and takes time,
246 * so we use _setjmp instead.
250 #define setjmp(jmploc) _setjmp(jmploc)
251 #define longjmp(jmploc, val) _longjmp(jmploc, val)
255 * Most machines require the value returned from malloc to be aligned
256 * in some way. The following macro will get this right on many machines.
265 #define ALIGN(nbytes) (((nbytes) + sizeof(union align) - 1) & ~(sizeof(union align) - 1))
268 #ifdef CONFIG_LOCALE_SUPPORT
270 static void change_lc_all(const char *value);
271 static void change_lc_ctype(const char *value);
275 * These macros allow the user to suspend the handling of interrupt signals
276 * over a period of time. This is similar to SIGHOLD to or sigblock, but
277 * much more efficient and portable. (But hacking the kernel is so much
278 * more fun than worrying about efficiency and portability. :-))
281 static void onint (void);
282 static volatile int suppressint;
283 static volatile int intpending;
285 #define INTOFF suppressint++
286 #ifndef ASH_OPTIMIZE_FOR_SIZE
287 #define INTON { if (--suppressint == 0 && intpending) onint(); }
288 #define FORCEINTON {suppressint = 0; if (intpending) onint();}
290 static void __inton (void);
291 static void forceinton (void);
292 #define INTON __inton()
293 #define FORCEINTON forceinton()
296 #define CLEAR_PENDING_INT intpending = 0
297 #define int_pending() intpending
300 typedef void *pointer;
302 #define NULL (void *)0
305 static inline pointer ckmalloc (int sz) { return xmalloc(sz); }
306 static inline pointer ckrealloc(void *p, int sz) { return xrealloc(p, sz); }
307 static inline char * savestr (const char *s) { return xstrdup(s); }
309 static pointer stalloc (int);
310 static void stunalloc (pointer);
311 static void ungrabstackstr (char *, char *);
312 static char * growstackstr(void);
313 static char * makestrspace(size_t newlen);
314 static char *sstrdup (const char *);
317 * Parse trees for commands are allocated in lifo order, so we use a stack
318 * to make this more efficient, and also to avoid all sorts of exception
319 * handling code to handle interrupts in the middle of a parse.
321 * The size 504 was chosen because the Ultrix malloc handles that size
325 #define MINSIZE 504 /* minimum size of a block */
329 struct stack_block *prev;
333 static struct stack_block stackbase;
334 static struct stack_block *stackp = &stackbase;
335 static struct stackmark *markp;
336 static char *stacknxt = stackbase.space;
337 static int stacknleft = MINSIZE;
340 #define equal(s1, s2) (strcmp(s1, s2) == 0)
342 #define stackblock() stacknxt
343 #define stackblocksize() stacknleft
344 #define STARTSTACKSTR(p) p = stackblock(), sstrnleft = stackblocksize()
346 #define STPUTC(c, p) (--sstrnleft >= 0? (*p++ = (c)) : (p = growstackstr(), *p++ = (c)))
347 #define CHECKSTRSPACE(n, p) { if (sstrnleft < n) p = makestrspace(n); }
348 #define STACKSTRNUL(p) (sstrnleft == 0? (p = growstackstr(), *p = '\0') : (*p = '\0'))
351 #define USTPUTC(c, p) (--sstrnleft, *p++ = (c))
352 #define STUNPUTC(p) (++sstrnleft, --p)
353 #define STTOPC(p) p[-1]
354 #define STADJUST(amount, p) (p += (amount), sstrnleft -= (amount))
355 #define grabstackstr(p) stalloc(stackblocksize() - sstrnleft)
357 #define ckfree(p) free((pointer)(p))
361 #define TRACE(param) trace param
362 static void trace (const char *, ...);
363 static void trargs (char **);
364 static void showtree (union node *);
365 static void trputc (int);
366 static void trputs (const char *);
367 static void opentrace (void);
402 #define EXP_FULL 0x1 /* perform word splitting & file globbing */
403 #define EXP_TILDE 0x2 /* do normal tilde expansion */
404 #define EXP_VARTILDE 0x4 /* expand tildes in an assignment */
405 #define EXP_REDIR 0x8 /* file glob for a redirection (1 match only) */
406 #define EXP_CASE 0x10 /* keeps quotes around for CASE pattern */
407 #define EXP_RECORD 0x20 /* need to record arguments for ifs breakup */
412 static char optet_vals[NOPTS];
414 static const char * const optlist[NOPTS] = {
433 #define optent_name(optent) (optent+1)
434 #define optent_letter(optent) optent[0]
435 #define optent_val(optent) optet_vals[optent]
437 #define eflag optent_val(0)
438 #define fflag optent_val(1)
439 #define Iflag optent_val(2)
440 #define iflag optent_val(3)
441 #define mflag optent_val(4)
442 #define nflag optent_val(5)
443 #define sflag optent_val(6)
444 #define xflag optent_val(7)
445 #define vflag optent_val(8)
446 #define Vflag optent_val(9)
447 #define Eflag optent_val(10)
448 #define Cflag optent_val(11)
449 #define aflag optent_val(12)
450 #define bflag optent_val(13)
451 #define uflag optent_val(14)
452 #define qflag optent_val(15)
455 /* Mode argument to forkshell. Don't change FORK_FG or FORK_BG. */
473 union node *redirect;
480 struct nodelist *cmdlist;
487 union node *redirect;
495 union node *elsepart;
526 struct nodelist *backquote;
564 struct nbinary nbinary;
567 struct nredir nredir;
571 struct nclist nclist;
581 struct nodelist *next;
585 struct backcmd { /* result of evalbackcmd */
586 int fd; /* file descriptor to read from */
587 char *buf; /* buffer */
588 int nleft; /* number of chars in buffer */
589 struct job *jp; /* job structure for command */
597 const struct builtincmd *cmd;
602 struct strlist *next;
608 struct strlist *list;
609 struct strlist **lastp;
613 struct strpush *prev; /* preceding string on stack */
617 struct alias *ap; /* if push was associated with an alias */
619 char *string; /* remember the string since it may change */
623 struct parsefile *prev; /* preceding file on stack */
624 int linno; /* current line */
625 int fd; /* file descriptor (or -1 if string) */
626 int nleft; /* number of chars left in this line */
627 int lleft; /* number of chars left in this buffer */
628 char *nextc; /* next char in buffer */
629 char *buf; /* input buffer */
630 struct strpush *strpush; /* for pushing strings at this level */
631 struct strpush basestrpush; /* so pushing one is fast */
635 struct stack_block *stackp;
638 struct stackmark *marknext;
642 int nparam; /* # of positional parameters (without $0) */
643 unsigned char malloc; /* if parameter list dynamically allocated */
644 char **p; /* parameter list */
645 int optind; /* next parameter to be processed by getopts */
646 int optoff; /* used by getopts */
650 * When commands are first encountered, they are entered in a hash table.
651 * This ensures that a full path search will not have to be done for them
652 * on each invocation.
654 * We should investigate converting to a linear search, even though that
655 * would make the command name "hash" a misnomer.
657 #define CMDTABLESIZE 31 /* should be prime */
658 #define ARB 1 /* actual size determined at run time */
663 struct tblentry *next; /* next entry in hash chain */
664 union param param; /* definition of builtin function */
665 short cmdtype; /* index identifying command */
666 char rehash; /* if set, cd done since entry created */
667 char cmdname[ARB]; /* name of command */
671 static struct tblentry *cmdtable[CMDTABLESIZE];
672 static int builtinloc = -1; /* index in path of %builtin, or -1 */
673 static int exerrno = 0; /* Last exec error */
676 static void tryexec (char *, char **, char **);
677 static void printentry (struct tblentry *, int);
678 static void clearcmdentry (int);
679 static struct tblentry *cmdlookup (const char *, int);
680 static void delete_cmd_entry (void);
681 static int path_change (const char *, int *);
684 static void flushall (void);
685 static void out2fmt (const char *, ...)
686 __attribute__((__format__(__printf__,1,2)));
687 static int xwrite (int, const char *, int);
689 static inline void outstr (const char *p, FILE *file) { fputs(p, file); }
690 static void out1str(const char *p) { outstr(p, stdout); }
691 static void out2str(const char *p) { outstr(p, stderr); }
693 #ifndef ASH_OPTIMIZE_FOR_SIZE
694 #define out2c(c) putc((c), stderr)
696 static void out2c(int c) { putc(c, stderr); }
700 #ifdef ASH_OPTIMIZE_FOR_SIZE
701 #define USE_SIT_FUNCTION
704 /* number syntax index */
705 #define BASESYNTAX 0 /* not in quotes */
706 #define DQSYNTAX 1 /* in double quotes */
707 #define SQSYNTAX 2 /* in single quotes */
708 #define ARISYNTAX 3 /* in arithmetic */
710 static const char S_I_T[][4] = {
711 /* 0 */ { CSPCL, CIGN, CIGN, CIGN }, /* PEOA */
712 /* 1 */ { CSPCL, CWORD, CWORD, CWORD }, /* ' ' */
713 /* 2 */ { CNL, CNL, CNL, CNL }, /* \n */
714 /* 3 */ { CWORD, CCTL, CCTL, CWORD }, /* !*-/:=?[]~ */
715 /* 4 */ { CDQUOTE, CENDQUOTE, CWORD, CDQUOTE }, /* '"' */
716 /* 5 */ { CVAR, CVAR, CWORD, CVAR }, /* $ */
717 /* 6 */ { CSQUOTE, CWORD, CENDQUOTE, CSQUOTE }, /* "'" */
718 /* 7 */ { CSPCL, CWORD, CWORD, CLP }, /* ( */
719 /* 8 */ { CSPCL, CWORD, CWORD, CRP }, /* ) */
720 /* 9 */ { CBACK, CBACK, CCTL, CBACK }, /* \ */
721 /* 10 */ { CBQUOTE, CBQUOTE, CWORD, CBQUOTE }, /* ` */
722 /* 11 */ { CENDVAR, CENDVAR, CWORD, CENDVAR }, /* } */
723 #ifndef USE_SIT_FUNCTION
724 /* 12 */ { CENDFILE, CENDFILE, CENDFILE, CENDFILE }, /* PEOF */
725 /* 13 */ { CWORD, CWORD, CWORD, CWORD }, /* 0-9A-Za-z */
726 /* 14 */ { CCTL, CCTL, CCTL, CCTL } /* CTLESC ... */
730 #ifdef USE_SIT_FUNCTION
732 #define U_C(c) ((unsigned char)(c))
734 static int SIT(int c, int syntax)
736 static const char spec_symbls[]="\t\n !\"$&'()*-/:;<=>?[\\]`|}~";
737 static const char syntax_index_table [] = {
738 1, 2, 1, 3, 4, 5, 1, 6, /* "\t\n !\"$&'" */
739 7, 8, 3, 3, 3, 3, 1, 1, /* "()*-/:;<" */
740 3, 1, 3, 3, 9, 3,10, 1, /* "=>?[\\]`|" */
745 if(c==PEOF) /* 2^8+2 */
747 if(c==PEOA) /* 2^8+1 */
749 else if(U_C(c)>=U_C(CTLESC) && U_C(c)<=U_C(CTLQUOTEMARK))
752 s = strchr(spec_symbls, c);
755 indx = syntax_index_table[(s-spec_symbls)];
757 return S_I_T[indx][syntax];
760 #else /* USE_SIT_FUNCTION */
762 #define SIT(c, syntax) S_I_T[(int)syntax_index_table[((int)c)+SYNBASE]][syntax]
764 #define CSPCL_CIGN_CIGN_CIGN 0
765 #define CSPCL_CWORD_CWORD_CWORD 1
766 #define CNL_CNL_CNL_CNL 2
767 #define CWORD_CCTL_CCTL_CWORD 3
768 #define CDQUOTE_CENDQUOTE_CWORD_CDQUOTE 4
769 #define CVAR_CVAR_CWORD_CVAR 5
770 #define CSQUOTE_CWORD_CENDQUOTE_CSQUOTE 6
771 #define CSPCL_CWORD_CWORD_CLP 7
772 #define CSPCL_CWORD_CWORD_CRP 8
773 #define CBACK_CBACK_CCTL_CBACK 9
774 #define CBQUOTE_CBQUOTE_CWORD_CBQUOTE 10
775 #define CENDVAR_CENDVAR_CWORD_CENDVAR 11
776 #define CENDFILE_CENDFILE_CENDFILE_CENDFILE 12
777 #define CWORD_CWORD_CWORD_CWORD 13
778 #define CCTL_CCTL_CCTL_CCTL 14
780 static const char syntax_index_table[258] = {
781 /* BASESYNTAX_DQSYNTAX_SQSYNTAX_ARISYNTAX */
782 /* 0 -130 PEOF */ CENDFILE_CENDFILE_CENDFILE_CENDFILE,
783 /* 1 -129 PEOA */ CSPCL_CIGN_CIGN_CIGN,
784 /* 2 -128 0xff */ CWORD_CWORD_CWORD_CWORD,
785 /* 3 -127 */ CCTL_CCTL_CCTL_CCTL, /* CTLQUOTEMARK */
786 /* 4 -126 */ CCTL_CCTL_CCTL_CCTL,
787 /* 5 -125 */ CCTL_CCTL_CCTL_CCTL,
788 /* 6 -124 */ CCTL_CCTL_CCTL_CCTL,
789 /* 7 -123 */ CCTL_CCTL_CCTL_CCTL,
790 /* 8 -122 */ CCTL_CCTL_CCTL_CCTL,
791 /* 9 -121 */ CCTL_CCTL_CCTL_CCTL,
792 /* 10 -120 */ CCTL_CCTL_CCTL_CCTL, /* CTLESC */
793 /* 11 -119 */ CWORD_CWORD_CWORD_CWORD,
794 /* 12 -118 */ CWORD_CWORD_CWORD_CWORD,
795 /* 13 -117 */ CWORD_CWORD_CWORD_CWORD,
796 /* 14 -116 */ CWORD_CWORD_CWORD_CWORD,
797 /* 15 -115 */ CWORD_CWORD_CWORD_CWORD,
798 /* 16 -114 */ CWORD_CWORD_CWORD_CWORD,
799 /* 17 -113 */ CWORD_CWORD_CWORD_CWORD,
800 /* 18 -112 */ CWORD_CWORD_CWORD_CWORD,
801 /* 19 -111 */ CWORD_CWORD_CWORD_CWORD,
802 /* 20 -110 */ CWORD_CWORD_CWORD_CWORD,
803 /* 21 -109 */ CWORD_CWORD_CWORD_CWORD,
804 /* 22 -108 */ CWORD_CWORD_CWORD_CWORD,
805 /* 23 -107 */ CWORD_CWORD_CWORD_CWORD,
806 /* 24 -106 */ CWORD_CWORD_CWORD_CWORD,
807 /* 25 -105 */ CWORD_CWORD_CWORD_CWORD,
808 /* 26 -104 */ CWORD_CWORD_CWORD_CWORD,
809 /* 27 -103 */ CWORD_CWORD_CWORD_CWORD,
810 /* 28 -102 */ CWORD_CWORD_CWORD_CWORD,
811 /* 29 -101 */ CWORD_CWORD_CWORD_CWORD,
812 /* 30 -100 */ CWORD_CWORD_CWORD_CWORD,
813 /* 31 -99 */ CWORD_CWORD_CWORD_CWORD,
814 /* 32 -98 */ CWORD_CWORD_CWORD_CWORD,
815 /* 33 -97 */ CWORD_CWORD_CWORD_CWORD,
816 /* 34 -96 */ CWORD_CWORD_CWORD_CWORD,
817 /* 35 -95 */ CWORD_CWORD_CWORD_CWORD,
818 /* 36 -94 */ CWORD_CWORD_CWORD_CWORD,
819 /* 37 -93 */ CWORD_CWORD_CWORD_CWORD,
820 /* 38 -92 */ CWORD_CWORD_CWORD_CWORD,
821 /* 39 -91 */ CWORD_CWORD_CWORD_CWORD,
822 /* 40 -90 */ CWORD_CWORD_CWORD_CWORD,
823 /* 41 -89 */ CWORD_CWORD_CWORD_CWORD,
824 /* 42 -88 */ CWORD_CWORD_CWORD_CWORD,
825 /* 43 -87 */ CWORD_CWORD_CWORD_CWORD,
826 /* 44 -86 */ CWORD_CWORD_CWORD_CWORD,
827 /* 45 -85 */ CWORD_CWORD_CWORD_CWORD,
828 /* 46 -84 */ CWORD_CWORD_CWORD_CWORD,
829 /* 47 -83 */ CWORD_CWORD_CWORD_CWORD,
830 /* 48 -82 */ CWORD_CWORD_CWORD_CWORD,
831 /* 49 -81 */ CWORD_CWORD_CWORD_CWORD,
832 /* 50 -80 */ CWORD_CWORD_CWORD_CWORD,
833 /* 51 -79 */ CWORD_CWORD_CWORD_CWORD,
834 /* 52 -78 */ CWORD_CWORD_CWORD_CWORD,
835 /* 53 -77 */ CWORD_CWORD_CWORD_CWORD,
836 /* 54 -76 */ CWORD_CWORD_CWORD_CWORD,
837 /* 55 -75 */ CWORD_CWORD_CWORD_CWORD,
838 /* 56 -74 */ CWORD_CWORD_CWORD_CWORD,
839 /* 57 -73 */ CWORD_CWORD_CWORD_CWORD,
840 /* 58 -72 */ CWORD_CWORD_CWORD_CWORD,
841 /* 59 -71 */ CWORD_CWORD_CWORD_CWORD,
842 /* 60 -70 */ CWORD_CWORD_CWORD_CWORD,
843 /* 61 -69 */ CWORD_CWORD_CWORD_CWORD,
844 /* 62 -68 */ CWORD_CWORD_CWORD_CWORD,
845 /* 63 -67 */ CWORD_CWORD_CWORD_CWORD,
846 /* 64 -66 */ CWORD_CWORD_CWORD_CWORD,
847 /* 65 -65 */ CWORD_CWORD_CWORD_CWORD,
848 /* 66 -64 */ CWORD_CWORD_CWORD_CWORD,
849 /* 67 -63 */ CWORD_CWORD_CWORD_CWORD,
850 /* 68 -62 */ CWORD_CWORD_CWORD_CWORD,
851 /* 69 -61 */ CWORD_CWORD_CWORD_CWORD,
852 /* 70 -60 */ CWORD_CWORD_CWORD_CWORD,
853 /* 71 -59 */ CWORD_CWORD_CWORD_CWORD,
854 /* 72 -58 */ CWORD_CWORD_CWORD_CWORD,
855 /* 73 -57 */ CWORD_CWORD_CWORD_CWORD,
856 /* 74 -56 */ CWORD_CWORD_CWORD_CWORD,
857 /* 75 -55 */ CWORD_CWORD_CWORD_CWORD,
858 /* 76 -54 */ CWORD_CWORD_CWORD_CWORD,
859 /* 77 -53 */ CWORD_CWORD_CWORD_CWORD,
860 /* 78 -52 */ CWORD_CWORD_CWORD_CWORD,
861 /* 79 -51 */ CWORD_CWORD_CWORD_CWORD,
862 /* 80 -50 */ CWORD_CWORD_CWORD_CWORD,
863 /* 81 -49 */ CWORD_CWORD_CWORD_CWORD,
864 /* 82 -48 */ CWORD_CWORD_CWORD_CWORD,
865 /* 83 -47 */ CWORD_CWORD_CWORD_CWORD,
866 /* 84 -46 */ CWORD_CWORD_CWORD_CWORD,
867 /* 85 -45 */ CWORD_CWORD_CWORD_CWORD,
868 /* 86 -44 */ CWORD_CWORD_CWORD_CWORD,
869 /* 87 -43 */ CWORD_CWORD_CWORD_CWORD,
870 /* 88 -42 */ CWORD_CWORD_CWORD_CWORD,
871 /* 89 -41 */ CWORD_CWORD_CWORD_CWORD,
872 /* 90 -40 */ CWORD_CWORD_CWORD_CWORD,
873 /* 91 -39 */ CWORD_CWORD_CWORD_CWORD,
874 /* 92 -38 */ CWORD_CWORD_CWORD_CWORD,
875 /* 93 -37 */ CWORD_CWORD_CWORD_CWORD,
876 /* 94 -36 */ CWORD_CWORD_CWORD_CWORD,
877 /* 95 -35 */ CWORD_CWORD_CWORD_CWORD,
878 /* 96 -34 */ CWORD_CWORD_CWORD_CWORD,
879 /* 97 -33 */ CWORD_CWORD_CWORD_CWORD,
880 /* 98 -32 */ CWORD_CWORD_CWORD_CWORD,
881 /* 99 -31 */ CWORD_CWORD_CWORD_CWORD,
882 /* 100 -30 */ CWORD_CWORD_CWORD_CWORD,
883 /* 101 -29 */ CWORD_CWORD_CWORD_CWORD,
884 /* 102 -28 */ CWORD_CWORD_CWORD_CWORD,
885 /* 103 -27 */ CWORD_CWORD_CWORD_CWORD,
886 /* 104 -26 */ CWORD_CWORD_CWORD_CWORD,
887 /* 105 -25 */ CWORD_CWORD_CWORD_CWORD,
888 /* 106 -24 */ CWORD_CWORD_CWORD_CWORD,
889 /* 107 -23 */ CWORD_CWORD_CWORD_CWORD,
890 /* 108 -22 */ CWORD_CWORD_CWORD_CWORD,
891 /* 109 -21 */ CWORD_CWORD_CWORD_CWORD,
892 /* 110 -20 */ CWORD_CWORD_CWORD_CWORD,
893 /* 111 -19 */ CWORD_CWORD_CWORD_CWORD,
894 /* 112 -18 */ CWORD_CWORD_CWORD_CWORD,
895 /* 113 -17 */ CWORD_CWORD_CWORD_CWORD,
896 /* 114 -16 */ CWORD_CWORD_CWORD_CWORD,
897 /* 115 -15 */ CWORD_CWORD_CWORD_CWORD,
898 /* 116 -14 */ CWORD_CWORD_CWORD_CWORD,
899 /* 117 -13 */ CWORD_CWORD_CWORD_CWORD,
900 /* 118 -12 */ CWORD_CWORD_CWORD_CWORD,
901 /* 119 -11 */ CWORD_CWORD_CWORD_CWORD,
902 /* 120 -10 */ CWORD_CWORD_CWORD_CWORD,
903 /* 121 -9 */ CWORD_CWORD_CWORD_CWORD,
904 /* 122 -8 */ CWORD_CWORD_CWORD_CWORD,
905 /* 123 -7 */ CWORD_CWORD_CWORD_CWORD,
906 /* 124 -6 */ CWORD_CWORD_CWORD_CWORD,
907 /* 125 -5 */ CWORD_CWORD_CWORD_CWORD,
908 /* 126 -4 */ CWORD_CWORD_CWORD_CWORD,
909 /* 127 -3 */ CWORD_CWORD_CWORD_CWORD,
910 /* 128 -2 */ CWORD_CWORD_CWORD_CWORD,
911 /* 129 -1 */ CWORD_CWORD_CWORD_CWORD,
912 /* 130 0 */ CWORD_CWORD_CWORD_CWORD,
913 /* 131 1 */ CWORD_CWORD_CWORD_CWORD,
914 /* 132 2 */ CWORD_CWORD_CWORD_CWORD,
915 /* 133 3 */ CWORD_CWORD_CWORD_CWORD,
916 /* 134 4 */ CWORD_CWORD_CWORD_CWORD,
917 /* 135 5 */ CWORD_CWORD_CWORD_CWORD,
918 /* 136 6 */ CWORD_CWORD_CWORD_CWORD,
919 /* 137 7 */ CWORD_CWORD_CWORD_CWORD,
920 /* 138 8 */ CWORD_CWORD_CWORD_CWORD,
921 /* 139 9 "\t" */ CSPCL_CWORD_CWORD_CWORD,
922 /* 140 10 "\n" */ CNL_CNL_CNL_CNL,
923 /* 141 11 */ CWORD_CWORD_CWORD_CWORD,
924 /* 142 12 */ CWORD_CWORD_CWORD_CWORD,
925 /* 143 13 */ CWORD_CWORD_CWORD_CWORD,
926 /* 144 14 */ CWORD_CWORD_CWORD_CWORD,
927 /* 145 15 */ CWORD_CWORD_CWORD_CWORD,
928 /* 146 16 */ CWORD_CWORD_CWORD_CWORD,
929 /* 147 17 */ CWORD_CWORD_CWORD_CWORD,
930 /* 148 18 */ CWORD_CWORD_CWORD_CWORD,
931 /* 149 19 */ CWORD_CWORD_CWORD_CWORD,
932 /* 150 20 */ CWORD_CWORD_CWORD_CWORD,
933 /* 151 21 */ CWORD_CWORD_CWORD_CWORD,
934 /* 152 22 */ CWORD_CWORD_CWORD_CWORD,
935 /* 153 23 */ CWORD_CWORD_CWORD_CWORD,
936 /* 154 24 */ CWORD_CWORD_CWORD_CWORD,
937 /* 155 25 */ CWORD_CWORD_CWORD_CWORD,
938 /* 156 26 */ CWORD_CWORD_CWORD_CWORD,
939 /* 157 27 */ CWORD_CWORD_CWORD_CWORD,
940 /* 158 28 */ CWORD_CWORD_CWORD_CWORD,
941 /* 159 29 */ CWORD_CWORD_CWORD_CWORD,
942 /* 160 30 */ CWORD_CWORD_CWORD_CWORD,
943 /* 161 31 */ CWORD_CWORD_CWORD_CWORD,
944 /* 162 32 " " */ CSPCL_CWORD_CWORD_CWORD,
945 /* 163 33 "!" */ CWORD_CCTL_CCTL_CWORD,
946 /* 164 34 """ */ CDQUOTE_CENDQUOTE_CWORD_CDQUOTE,
947 /* 165 35 "#" */ CWORD_CWORD_CWORD_CWORD,
948 /* 166 36 "$" */ CVAR_CVAR_CWORD_CVAR,
949 /* 167 37 "%" */ CWORD_CWORD_CWORD_CWORD,
950 /* 168 38 "&" */ CSPCL_CWORD_CWORD_CWORD,
951 /* 169 39 "'" */ CSQUOTE_CWORD_CENDQUOTE_CSQUOTE,
952 /* 170 40 "(" */ CSPCL_CWORD_CWORD_CLP,
953 /* 171 41 ")" */ CSPCL_CWORD_CWORD_CRP,
954 /* 172 42 "*" */ CWORD_CCTL_CCTL_CWORD,
955 /* 173 43 "+" */ CWORD_CWORD_CWORD_CWORD,
956 /* 174 44 "," */ CWORD_CWORD_CWORD_CWORD,
957 /* 175 45 "-" */ CWORD_CCTL_CCTL_CWORD,
958 /* 176 46 "." */ CWORD_CWORD_CWORD_CWORD,
959 /* 177 47 "/" */ CWORD_CCTL_CCTL_CWORD,
960 /* 178 48 "0" */ CWORD_CWORD_CWORD_CWORD,
961 /* 179 49 "1" */ CWORD_CWORD_CWORD_CWORD,
962 /* 180 50 "2" */ CWORD_CWORD_CWORD_CWORD,
963 /* 181 51 "3" */ CWORD_CWORD_CWORD_CWORD,
964 /* 182 52 "4" */ CWORD_CWORD_CWORD_CWORD,
965 /* 183 53 "5" */ CWORD_CWORD_CWORD_CWORD,
966 /* 184 54 "6" */ CWORD_CWORD_CWORD_CWORD,
967 /* 185 55 "7" */ CWORD_CWORD_CWORD_CWORD,
968 /* 186 56 "8" */ CWORD_CWORD_CWORD_CWORD,
969 /* 187 57 "9" */ CWORD_CWORD_CWORD_CWORD,
970 /* 188 58 ":" */ CWORD_CCTL_CCTL_CWORD,
971 /* 189 59 ";" */ CSPCL_CWORD_CWORD_CWORD,
972 /* 190 60 "<" */ CSPCL_CWORD_CWORD_CWORD,
973 /* 191 61 "=" */ CWORD_CCTL_CCTL_CWORD,
974 /* 192 62 ">" */ CSPCL_CWORD_CWORD_CWORD,
975 /* 193 63 "?" */ CWORD_CCTL_CCTL_CWORD,
976 /* 194 64 "@" */ CWORD_CWORD_CWORD_CWORD,
977 /* 195 65 "A" */ CWORD_CWORD_CWORD_CWORD,
978 /* 196 66 "B" */ CWORD_CWORD_CWORD_CWORD,
979 /* 197 67 "C" */ CWORD_CWORD_CWORD_CWORD,
980 /* 198 68 "D" */ CWORD_CWORD_CWORD_CWORD,
981 /* 199 69 "E" */ CWORD_CWORD_CWORD_CWORD,
982 /* 200 70 "F" */ CWORD_CWORD_CWORD_CWORD,
983 /* 201 71 "G" */ CWORD_CWORD_CWORD_CWORD,
984 /* 202 72 "H" */ CWORD_CWORD_CWORD_CWORD,
985 /* 203 73 "I" */ CWORD_CWORD_CWORD_CWORD,
986 /* 204 74 "J" */ CWORD_CWORD_CWORD_CWORD,
987 /* 205 75 "K" */ CWORD_CWORD_CWORD_CWORD,
988 /* 206 76 "L" */ CWORD_CWORD_CWORD_CWORD,
989 /* 207 77 "M" */ CWORD_CWORD_CWORD_CWORD,
990 /* 208 78 "N" */ CWORD_CWORD_CWORD_CWORD,
991 /* 209 79 "O" */ CWORD_CWORD_CWORD_CWORD,
992 /* 210 80 "P" */ CWORD_CWORD_CWORD_CWORD,
993 /* 211 81 "Q" */ CWORD_CWORD_CWORD_CWORD,
994 /* 212 82 "R" */ CWORD_CWORD_CWORD_CWORD,
995 /* 213 83 "S" */ CWORD_CWORD_CWORD_CWORD,
996 /* 214 84 "T" */ CWORD_CWORD_CWORD_CWORD,
997 /* 215 85 "U" */ CWORD_CWORD_CWORD_CWORD,
998 /* 216 86 "V" */ CWORD_CWORD_CWORD_CWORD,
999 /* 217 87 "W" */ CWORD_CWORD_CWORD_CWORD,
1000 /* 218 88 "X" */ CWORD_CWORD_CWORD_CWORD,
1001 /* 219 89 "Y" */ CWORD_CWORD_CWORD_CWORD,
1002 /* 220 90 "Z" */ CWORD_CWORD_CWORD_CWORD,
1003 /* 221 91 "[" */ CWORD_CCTL_CCTL_CWORD,
1004 /* 222 92 "\" */ CBACK_CBACK_CCTL_CBACK,
1005 /* 223 93 "]" */ CWORD_CCTL_CCTL_CWORD,
1006 /* 224 94 "^" */ CWORD_CWORD_CWORD_CWORD,
1007 /* 225 95 "_" */ CWORD_CWORD_CWORD_CWORD,
1008 /* 226 96 "`" */ CBQUOTE_CBQUOTE_CWORD_CBQUOTE,
1009 /* 227 97 "a" */ CWORD_CWORD_CWORD_CWORD,
1010 /* 228 98 "b" */ CWORD_CWORD_CWORD_CWORD,
1011 /* 229 99 "c" */ CWORD_CWORD_CWORD_CWORD,
1012 /* 230 100 "d" */ CWORD_CWORD_CWORD_CWORD,
1013 /* 231 101 "e" */ CWORD_CWORD_CWORD_CWORD,
1014 /* 232 102 "f" */ CWORD_CWORD_CWORD_CWORD,
1015 /* 233 103 "g" */ CWORD_CWORD_CWORD_CWORD,
1016 /* 234 104 "h" */ CWORD_CWORD_CWORD_CWORD,
1017 /* 235 105 "i" */ CWORD_CWORD_CWORD_CWORD,
1018 /* 236 106 "j" */ CWORD_CWORD_CWORD_CWORD,
1019 /* 237 107 "k" */ CWORD_CWORD_CWORD_CWORD,
1020 /* 238 108 "l" */ CWORD_CWORD_CWORD_CWORD,
1021 /* 239 109 "m" */ CWORD_CWORD_CWORD_CWORD,
1022 /* 240 110 "n" */ CWORD_CWORD_CWORD_CWORD,
1023 /* 241 111 "o" */ CWORD_CWORD_CWORD_CWORD,
1024 /* 242 112 "p" */ CWORD_CWORD_CWORD_CWORD,
1025 /* 243 113 "q" */ CWORD_CWORD_CWORD_CWORD,
1026 /* 244 114 "r" */ CWORD_CWORD_CWORD_CWORD,
1027 /* 245 115 "s" */ CWORD_CWORD_CWORD_CWORD,
1028 /* 246 116 "t" */ CWORD_CWORD_CWORD_CWORD,
1029 /* 247 117 "u" */ CWORD_CWORD_CWORD_CWORD,
1030 /* 248 118 "v" */ CWORD_CWORD_CWORD_CWORD,
1031 /* 249 119 "w" */ CWORD_CWORD_CWORD_CWORD,
1032 /* 250 120 "x" */ CWORD_CWORD_CWORD_CWORD,
1033 /* 251 121 "y" */ CWORD_CWORD_CWORD_CWORD,
1034 /* 252 122 "z" */ CWORD_CWORD_CWORD_CWORD,
1035 /* 253 123 "{" */ CWORD_CWORD_CWORD_CWORD,
1036 /* 254 124 "|" */ CSPCL_CWORD_CWORD_CWORD,
1037 /* 255 125 "}" */ CENDVAR_CENDVAR_CWORD_CENDVAR,
1038 /* 256 126 "~" */ CWORD_CCTL_CCTL_CWORD,
1039 /* 257 127 */ CWORD_CWORD_CWORD_CWORD,
1042 #endif /* USE_SIT_FUNCTION */
1045 /* first char is indicating which tokens mark the end of a list */
1046 static const char *const tokname_array[] = {
1061 #define KWDOFFSET 14
1062 /* the following are keywords */
1081 static const char *tokname(int tok)
1083 static char buf[16];
1087 sprintf(buf+(tok>=TSEMI), "%s%c",
1088 tokname_array[tok]+1, (tok>=TSEMI ? '"' : 0));
1092 static int plinno = 1; /* input line number */
1094 static int parselleft; /* copy of parsefile->lleft */
1096 static struct parsefile basepf; /* top level input file */
1097 static char basebuf[BUFSIZ]; /* buffer for top level input file */
1098 static struct parsefile *parsefile = &basepf; /* current input file */
1101 * NEOF is returned by parsecmd when it encounters an end of file. It
1102 * must be distinct from NULL, so we use the address of a variable that
1103 * happens to be handy.
1106 static int tokpushback; /* last token pushed back */
1107 #define NEOF ((union node *)&tokpushback)
1108 static int checkkwd; /* 1 == check for kwds, 2 == also eat newlines */
1111 static void error (const char *, ...) __attribute__((__noreturn__));
1112 static void exerror (int, const char *, ...) __attribute__((__noreturn__));
1113 static void shellexec (char **, char **, const char *, int)
1114 __attribute__((noreturn));
1115 static void exitshell (int) __attribute__((noreturn));
1117 static int goodname(const char *);
1118 static void ignoresig (int);
1119 static void onsig (int);
1120 static void dotrap (void);
1121 static int decode_signal (const char *, int);
1123 static void shprocvar(void);
1124 static void deletefuncs(void);
1125 static void setparam (char **);
1126 static void freeparam (volatile struct shparam *);
1128 /* reasons for skipping commands (see comment on breakcmd routine) */
1134 /* values of cmdtype */
1135 #define CMDUNKNOWN -1 /* no entry in table for command */
1136 #define CMDNORMAL 0 /* command is an executable program */
1137 #define CMDBUILTIN 1 /* command is a shell builtin */
1138 #define CMDFUNCTION 2 /* command is a shell function */
1140 #define DO_ERR 1 /* find_command prints errors */
1141 #define DO_ABS 2 /* find_command checks absolute paths */
1142 #define DO_NOFUN 4 /* find_command ignores functions */
1143 #define DO_BRUTE 8 /* find_command ignores hash table */
1150 #define VEXPORT 0x01 /* variable is exported */
1151 #define VREADONLY 0x02 /* variable cannot be modified */
1152 #define VSTRFIXED 0x04 /* variable struct is staticly allocated */
1153 #define VTEXTFIXED 0x08 /* text is staticly allocated */
1154 #define VSTACK 0x10 /* text is allocated on the stack */
1155 #define VUNSET 0x20 /* the variable is not set */
1156 #define VNOFUNC 0x40 /* don't call the callback function */
1160 struct var *next; /* next entry in hash list */
1161 int flags; /* flags are defined above */
1162 char *text; /* name=value */
1163 void (*func) (const char *);
1164 /* function to be called when */
1165 /* the variable gets set/unset */
1169 struct localvar *next; /* next local variable in list */
1170 struct var *vp; /* the variable that was made local */
1171 int flags; /* saved flags */
1172 char *text; /* saved text */
1176 #if defined(__GLIBC__) && __GLIBC__ >= 2 && !defined(FNMATCH_BROKEN)
1177 #define rmescapes(p) _rmescapes((p), 0)
1178 static char *_rmescapes (char *, int);
1180 static void rmescapes (char *);
1183 static int casematch (union node *, const char *);
1184 static void clearredir(void);
1185 static void popstring(void);
1186 static void readcmdfile (const char *);
1188 static int number (const char *);
1189 static int is_number (const char *, int *num);
1190 static char *single_quote (const char *);
1191 static int nextopt (const char *);
1193 static void redirect (union node *, int);
1194 static void popredir (void);
1195 static int dup_as_newfd (int, int);
1197 static void changepath(const char *newval);
1198 static void getoptsreset(const char *value);
1201 static int parsenleft; /* copy of parsefile->nleft */
1202 static char *parsenextc; /* copy of parsefile->nextc */
1203 static int rootpid; /* pid of main shell */
1204 static int rootshell; /* true if we aren't a child of the main shell */
1206 static const char spcstr[] = " ";
1207 static const char snlfmt[] = "%s\n";
1209 static int sstrnleft;
1210 static int herefd = -1;
1212 static struct localvar *localvars;
1214 static struct var vifs;
1215 static struct var vmail;
1216 static struct var vmpath;
1217 static struct var vpath;
1218 static struct var vps1;
1219 static struct var vps2;
1220 static struct var voptind;
1221 #ifdef CONFIG_LOCALE_SUPPORT
1222 static struct var vlc_all;
1223 static struct var vlc_ctype;
1230 void (*func) (const char *);
1233 static const char defpathvar[] =
1234 "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin";
1235 #define defpath (defpathvar + 5)
1238 static const char defifsvar[] = "IFS= \t\n";
1239 #define defifs (defifsvar + 4)
1241 static const char defifs[] = " \t\n";
1244 static const struct varinit varinit[] = {
1246 { &vifs, VSTRFIXED|VTEXTFIXED, defifsvar,
1248 { &vifs, VSTRFIXED|VTEXTFIXED|VUNSET, "IFS=",
1251 { &vmail, VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL=",
1253 { &vmpath, VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH=",
1255 { &vpath, VSTRFIXED|VTEXTFIXED, defpathvar,
1258 * vps1 depends on uid
1260 { &vps2, VSTRFIXED|VTEXTFIXED, "PS2=> ",
1262 { &voptind, VSTRFIXED|VTEXTFIXED, "OPTIND=1",
1264 #ifdef CONFIG_LOCALE_SUPPORT
1265 { &vlc_all, VSTRFIXED|VTEXTFIXED|VUNSET, "LC_ALL=",
1267 { &vlc_ctype, VSTRFIXED|VTEXTFIXED|VUNSET, "LC_CTYPE=",
1276 static struct var *vartab[VTABSIZE];
1279 * The following macros access the values of the above variables.
1280 * They have to skip over the name. They return the null string
1281 * for unset variables.
1284 #define ifsval() (vifs.text + 4)
1285 #define ifsset() ((vifs.flags & VUNSET) == 0)
1286 #define mailval() (vmail.text + 5)
1287 #define mpathval() (vmpath.text + 9)
1288 #define pathval() (vpath.text + 5)
1289 #define ps1val() (vps1.text + 4)
1290 #define ps2val() (vps2.text + 4)
1291 #define optindval() (voptind.text + 7)
1293 #define mpathset() ((vmpath.flags & VUNSET) == 0)
1295 static void initvar (void);
1296 static void setvar (const char *, const char *, int);
1297 static void setvareq (char *, int);
1298 static void listsetvar (struct strlist *);
1299 static const char *lookupvar (const char *);
1300 static const char *bltinlookup (const char *);
1301 static char **environment (void);
1302 static int showvarscmd (int, char **);
1303 static void mklocal (char *);
1304 static void poplocalvars (void);
1305 static int unsetvar (const char *);
1306 static int varequal (const char *, const char *);
1309 static char *arg0; /* value of $0 */
1310 static struct shparam shellparam; /* current positional parameters */
1311 static char **argptr; /* argument list for builtin commands */
1312 static char *optionarg; /* set by nextopt (like getopt) */
1313 static char *optptr; /* used by nextopt */
1314 static char *minusc; /* argument to -c option */
1319 #define ALIASINUSE 1
1331 static struct alias *atab[ATABSIZE];
1333 static void setalias (char *, char *);
1334 static struct alias **hashalias (const char *);
1335 static struct alias *freealias (struct alias *);
1336 static struct alias **__lookupalias (const char *);
1342 struct alias *ap, **app;
1344 app = __lookupalias(name);
1348 if (!(ap->flag & ALIASINUSE)) {
1351 ap->val = savestr(val);
1352 ap->flag &= ~ALIASDEAD;
1355 ap = ckmalloc(sizeof (struct alias));
1356 ap->name = savestr(name);
1357 ap->val = savestr(val);
1370 app = __lookupalias(name);
1374 *app = freealias(*app);
1385 struct alias *ap, **app;
1389 for (i = 0; i < ATABSIZE; i++) {
1391 for (ap = *app; ap; ap = *app) {
1392 *app = freealias(*app);
1401 static struct alias *
1402 lookupalias(const char *name, int check)
1404 struct alias *ap = *__lookupalias(name);
1406 if (check && ap && (ap->flag & ALIASINUSE))
1412 printalias(const struct alias *ap) {
1415 p = single_quote(ap->val);
1416 printf("alias %s=%s\n", ap->name, p);
1422 * TODO - sort output
1425 aliascmd(int argc, char **argv)
1434 for (i = 0; i < ATABSIZE; i++)
1435 for (ap = atab[i]; ap; ap = ap->next) {
1440 while ((n = *++argv) != NULL) {
1441 if ((v = strchr(n+1, '=')) == NULL) { /* n+1: funny ksh stuff */
1442 if ((ap = *__lookupalias(n)) == NULL) {
1443 out2fmt("%s: %s not found\n", "alias", n);
1458 unaliascmd(int argc, char **argv)
1462 while ((i = nextopt("a")) != '\0') {
1468 for (i = 0; *argptr; argptr++) {
1469 if (unalias(*argptr)) {
1470 out2fmt("%s: %s not found\n", "unalias", *argptr);
1478 static struct alias **
1482 unsigned int hashval;
1487 return &atab[hashval % ATABSIZE];
1490 static struct alias *
1491 freealias(struct alias *ap) {
1494 if (ap->flag & ALIASINUSE) {
1495 ap->flag |= ALIASDEAD;
1507 static struct alias **
1508 __lookupalias(const char *name) {
1509 struct alias **app = hashalias(name);
1511 for (; *app; app = &(*app)->next) {
1512 if (equal(name, (*app)->name)) {
1521 #ifdef ASH_MATH_SUPPORT
1522 /* The generated file arith.c has been replaced with a custom hand
1523 * written implementation written by Aaron Lehmann <aaronl@vitelus.com>.
1524 * This is now part of libbb, so that it can be used by all the shells
1526 static void expari (int);
1529 static char *trap[NSIG]; /* trap handler commands */
1530 static char sigmode[NSIG - 1]; /* current value of signal */
1531 static char gotsig[NSIG - 1]; /* indicates specified signal received */
1532 static int pendingsigs; /* indicates some signal received */
1535 * This file was generated by the mkbuiltins program.
1539 static int bgcmd (int, char **);
1540 static int fgcmd (int, char **);
1541 static int killcmd (int, char **);
1543 static int bltincmd (int, char **);
1544 static int cdcmd (int, char **);
1545 static int breakcmd (int, char **);
1547 static int commandcmd (int, char **);
1549 static int dotcmd (int, char **);
1550 static int evalcmd (int, char **);
1551 static int execcmd (int, char **);
1552 static int exitcmd (int, char **);
1553 static int exportcmd (int, char **);
1554 static int histcmd (int, char **);
1555 static int hashcmd (int, char **);
1556 static int helpcmd (int, char **);
1557 static int jobscmd (int, char **);
1558 static int localcmd (int, char **);
1560 static int pwdcmd (int, char **);
1562 static int readcmd (int, char **);
1563 static int returncmd (int, char **);
1564 static int setcmd (int, char **);
1565 static int setvarcmd (int, char **);
1566 static int shiftcmd (int, char **);
1567 static int trapcmd (int, char **);
1568 static int umaskcmd (int, char **);
1570 static int aliascmd (int, char **);
1571 static int unaliascmd (int, char **);
1573 static int unsetcmd (int, char **);
1574 static int waitcmd (int, char **);
1575 static int ulimitcmd (int, char **);
1576 static int timescmd (int, char **);
1577 #ifdef ASH_MATH_SUPPORT
1578 static int letcmd (int, char **);
1580 static int typecmd (int, char **);
1582 static int getoptscmd (int, char **);
1585 #ifndef CONFIG_TRUE_FALSE
1586 static int true_main (int, char **);
1587 static int false_main (int, char **);
1590 static void setpwd (const char *, int);
1593 #define BUILTIN_NOSPEC "0"
1594 #define BUILTIN_SPECIAL "1"
1595 #define BUILTIN_REGULAR "2"
1596 #define BUILTIN_ASSIGN "4"
1597 #define BUILTIN_SPEC_ASSG "5"
1598 #define BUILTIN_REG_ASSG "6"
1600 #define IS_BUILTIN_SPECIAL(builtincmd) ((builtincmd)->name[0] & 1)
1601 #define IS_BUILTIN_REGULAR(builtincmd) ((builtincmd)->name[0] & 2)
1602 #define IS_BUILTIN_ASSIGN(builtincmd) ((builtincmd)->name[0] & 4)
1606 int (*const builtinfunc) (int, char **);
1611 /* It is CRUCIAL that this listing be kept in ascii order, otherwise
1612 * the binary search in find_builtin() will stop working. If you value
1613 * your kneecaps, you'll be sure to *make sure* that any changes made
1614 * to this array result in the listing remaining in ascii order. You
1617 static const struct builtincmd builtincmds[] = {
1618 { BUILTIN_SPECIAL ".", dotcmd }, /* first, see declare DOTCMD */
1619 { BUILTIN_SPECIAL ":", true_main },
1621 { BUILTIN_REG_ASSG "alias", aliascmd },
1624 { BUILTIN_REGULAR "bg", bgcmd },
1626 { BUILTIN_SPECIAL "break", breakcmd },
1627 { BUILTIN_SPECIAL "builtin", bltincmd },
1628 { BUILTIN_REGULAR "cd", cdcmd },
1629 { BUILTIN_NOSPEC "chdir", cdcmd },
1631 { BUILTIN_REGULAR "command", commandcmd },
1633 { BUILTIN_SPECIAL "continue", breakcmd },
1634 { BUILTIN_SPECIAL "eval", evalcmd },
1635 { BUILTIN_SPECIAL "exec", execcmd },
1636 { BUILTIN_SPECIAL "exit", exitcmd },
1637 { BUILTIN_SPEC_ASSG "export", exportcmd },
1638 { BUILTIN_REGULAR "false", false_main },
1639 { BUILTIN_REGULAR "fc", histcmd },
1641 { BUILTIN_REGULAR "fg", fgcmd },
1644 { BUILTIN_REGULAR "getopts", getoptscmd },
1646 { BUILTIN_NOSPEC "hash", hashcmd },
1647 { BUILTIN_NOSPEC "help", helpcmd },
1648 { BUILTIN_REGULAR "jobs", jobscmd },
1650 { BUILTIN_REGULAR "kill", killcmd },
1652 #ifdef ASH_MATH_SUPPORT
1653 { BUILTIN_REGULAR "let", letcmd },
1655 { BUILTIN_ASSIGN "local", localcmd },
1657 { BUILTIN_NOSPEC "pwd", pwdcmd },
1659 { BUILTIN_REGULAR "read", readcmd },
1660 { BUILTIN_SPEC_ASSG "readonly", exportcmd },
1661 { BUILTIN_SPECIAL "return", returncmd },
1662 { BUILTIN_SPECIAL "set", setcmd },
1663 { BUILTIN_NOSPEC "setvar", setvarcmd },
1664 { BUILTIN_SPECIAL "shift", shiftcmd },
1665 { BUILTIN_SPECIAL "times", timescmd },
1666 { BUILTIN_SPECIAL "trap", trapcmd },
1667 { BUILTIN_REGULAR "true", true_main },
1668 { BUILTIN_NOSPEC "type", typecmd },
1669 { BUILTIN_NOSPEC "ulimit", ulimitcmd },
1670 { BUILTIN_REGULAR "umask", umaskcmd },
1672 { BUILTIN_REGULAR "unalias", unaliascmd },
1674 { BUILTIN_SPECIAL "unset", unsetcmd },
1675 { BUILTIN_REGULAR "wait", waitcmd },
1677 #define NUMBUILTINS (sizeof (builtincmds) / sizeof (struct builtincmd) )
1679 #define DOTCMD &builtincmds[0]
1680 static struct builtincmd *BLTINCMD;
1681 static struct builtincmd *EXECCMD;
1682 static struct builtincmd *EVALCMD;
1685 #define JOBSTOPPED 1 /* all procs are stopped */
1686 #define JOBDONE 2 /* all procs are completed */
1689 * A job structure contains information about a job. A job is either a
1690 * single process or a set of processes contained in a pipeline. In the
1691 * latter case, pidlist will be non-NULL, and will point to a -1 terminated
1696 pid_t pid; /* process id */
1697 int status; /* status flags (defined above) */
1698 char *cmd; /* text of command being run */
1702 static int job_warning; /* user was warned about stopped jobs */
1705 static void setjobctl(int enable);
1707 #define setjobctl(on) /* do nothing */
1712 struct procstat ps0; /* status of process */
1713 struct procstat *ps; /* status or processes when more than one */
1714 short nprocs; /* number of processes */
1715 short pgrp; /* process group of this job */
1716 char state; /* true if job is finished */
1717 char used; /* true if this entry is in used */
1718 char changed; /* true if status has changed */
1720 char jobctl; /* job running under job control */
1724 static struct job *jobtab; /* array of jobs */
1725 static int njobs; /* size of array */
1726 static int backgndpid = -1; /* pid of last background process */
1728 static int initialpgrp; /* pgrp of shell on invocation */
1729 static int curjob; /* current job */
1732 static int intreceived;
1734 static struct job *makejob (const union node *, int);
1735 static int forkshell (struct job *, const union node *, int);
1736 static int waitforjob (struct job *);
1738 static int docd (char *, int);
1739 static char *getcomponent (void);
1740 static void updatepwd (const char *);
1741 static void getpwd (void);
1743 static char *padvance (const char **, const char *);
1745 static char nullstr[1]; /* zero length string */
1746 static char *curdir = nullstr; /* current working directory */
1747 static char *cdcomppath;
1761 if ((dest = *argptr) == NULL && (dest = bltinlookup("HOME")) == NULL)
1762 error("HOME not set");
1765 if (dest[0] == '-' && dest[1] == '\0') {
1766 dest = bltinlookup("OLDPWD");
1767 if (!dest || !*dest) {
1776 if (*dest == '/' || (path = bltinlookup("CDPATH")) == NULL)
1778 while ((p = padvance(&path, dest)) != NULL) {
1779 if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
1784 if (p[0] == '.' && p[1] == '/' && p[2] != '\0')
1786 print = strcmp(p, dest);
1788 if (docd(p, print) >= 0)
1793 error("can't cd to %s", dest);
1799 * Actually do the chdir. In an interactive shell, print the
1800 * directory name if "print" is nonzero.
1815 TRACE(("docd(\"%s\", %d) called\n", dest, print));
1818 * Check each component of the path. If we find a symlink or
1819 * something we can't stat, clear curdir to force a getcwd()
1820 * next time we get the value of the current directory.
1823 cdcomppath = sstrdup(dest);
1830 while ((q = getcomponent()) != NULL) {
1831 if (q[0] == '\0' || (q[0] == '.' && q[1] == '\0'))
1839 if (equal(component, ".."))
1842 if ((lstat(stackblock(), &statb) < 0)
1843 || (S_ISLNK(statb.st_mode))) {
1851 if (chdir(dest) < 0) {
1855 updatepwd(badstat ? NULL : dest);
1858 printf(snlfmt, curdir);
1864 * Get the next component of the path name pointed to by cdcomppath.
1865 * This routine overwrites the string pointed to by cdcomppath.
1873 if ((p = cdcomppath) == NULL)
1876 while (*p != '/' && *p != '\0')
1890 * Update curdir (the name of the current directory) in response to a
1891 * cd command. We also call hashcd to let the routines in exec.c know
1892 * that the current directory has changed.
1895 static void hashcd (void);
1898 updatepwd(const char *dir)
1904 hashcd(); /* update command hash table */
1907 * If our argument is NULL, we don't know the current directory
1908 * any more because we traversed a symbolic link or something
1909 * we couldn't stat().
1911 if (dir == NULL || curdir == nullstr) {
1916 cdcomppath = sstrdup(dir);
1925 while ((p = getcomponent()) != NULL) {
1926 if (equal(p, "..")) {
1927 while (new > stackblock() && (STUNPUTC(new), *new) != '/');
1928 } else if (*p != '\0' && ! equal(p, ".")) {
1934 if (new == stackblock())
1937 setpwd(stackblock(), 1);
1947 printf(snlfmt, curdir);
1953 * Find out what the current directory is. If we already know the current
1954 * directory, this routine returns immediately.
1959 curdir = xgetcwd(0);
1965 setpwd(const char *val, int setold)
1968 setvar("OLDPWD", curdir, VEXPORT);
1971 if (curdir != nullstr) {
1978 curdir = savestr(val);
1981 setvar("PWD", curdir, VEXPORT);
1985 * Errors and exceptions.
1989 * Code to handle exceptions in C.
1993 * We enclose jmp_buf in a structure so that we can declare pointers to
1994 * jump locations. The global variable handler contains the location to
1995 * jump to when an exception occurs, and the global variable exception
1996 * contains a code identifying the exeception. To implement nested
1997 * exception handlers, the user should save the value of handler on entry
1998 * to an inner scope, set handler to point to a jmploc structure for the
1999 * inner scope, and restore handler on exit from the scope.
2007 #define EXINT 0 /* SIGINT received */
2008 #define EXERROR 1 /* a generic error */
2009 #define EXSHELLPROC 2 /* execute a shell procedure */
2010 #define EXEXEC 3 /* command execution failed */
2012 static struct jmploc *handler;
2013 static int exception;
2015 static void exverror (int, const char *, va_list)
2016 __attribute__((__noreturn__));
2019 * Called to raise an exception. Since C doesn't include exceptions, we
2020 * just do a longjmp to the exception handler. The type of exception is
2021 * stored in the global variable "exception".
2024 static void exraise (int) __attribute__((__noreturn__));
2030 if (handler == NULL)
2035 longjmp(handler->loc, 1);
2040 * Called from trap.c when a SIGINT is received. (If the user specifies
2041 * that SIGINT is to be trapped or ignored using the trap builtin, then
2042 * this routine is not called.) Suppressint is nonzero when interrupts
2043 * are held using the INTOFF macro. The call to _exit is necessary because
2044 * there is a short period after a fork before the signal handlers are
2045 * set to the appropriate value for the child. (The test for iflag is
2046 * just defensive programming.)
2058 sigemptyset(&mysigset);
2059 sigprocmask(SIG_SETMASK, &mysigset, NULL);
2060 if (rootshell && iflag)
2063 signal(SIGINT, SIG_DFL);
2070 static char *commandname; /* currently executing command */
2073 * Exverror is called to raise the error exception. If the first argument
2074 * is not NULL then error prints an error message using printf style
2075 * formatting. It then raises the error exception.
2078 exverror(int cond, const char *msg, va_list ap)
2085 TRACE(("exverror(%d, \"%s\") pid=%d\n", cond, msg, getpid()));
2087 TRACE(("exverror(%d, NULL) pid=%d\n", cond, getpid()));
2091 out2fmt("%s: ", commandname);
2092 vfprintf(stderr, msg, ap);
2101 error(const char *msg, ...)
2105 exverror(EXERROR, msg, ap);
2112 exerror(int cond, const char *msg, ...)
2116 exverror(cond, msg, ap);
2124 * Table of error messages.
2128 short errcode; /* error number */
2129 char action; /* operation which encountered the error */
2133 * Types of operations (passed to the errmsg routine).
2136 #define E_OPEN 01 /* opening a file */
2137 #define E_CREAT 02 /* creating a file */
2138 #define E_EXEC 04 /* executing a program */
2140 #define ALL (E_OPEN|E_CREAT|E_EXEC)
2142 static const struct errname errormsg[] = {
2147 { ENOENT, E_CREAT },
2149 { ENOTDIR, E_OPEN },
2150 { ENOTDIR, E_CREAT },
2151 { ENOTDIR, E_EXEC },
2153 { EEXIST, E_CREAT },
2192 { ELIBACC, E_EXEC },
2196 #define ERRNAME_SIZE (sizeof(errormsg)/sizeof(struct errname))
2199 * Return a string describing an error. The returned string may be a
2200 * pointer to a static buffer that will be overwritten on the next call.
2201 * Action describes the operation that got the error.
2205 errmsg(int e, int action)
2207 struct errname const *ep;
2208 static char buf[12];
2210 for (ep = errormsg ; ep < errormsg+ERRNAME_SIZE; ep++) {
2211 if (ep->errcode == e && (ep->action & action) != 0)
2215 snprintf(buf, sizeof buf, "error %d", e);
2220 #ifdef ASH_OPTIMIZE_FOR_SIZE
2223 if (--suppressint == 0 && intpending) {
2227 static void forceinton (void) {
2234 /* flags in argument to evaltree */
2235 #define EV_EXIT 01 /* exit after evaluating tree */
2236 #define EV_TESTED 02 /* exit status is checked; ignore -e flag */
2237 #define EV_BACKCMD 04 /* command executing within back quotes */
2239 static int evalskip; /* set if we are skipping commands */
2240 static int skipcount; /* number of levels to skip */
2241 static int loopnest; /* current loop nesting level */
2242 static int funcnest; /* depth of function calls */
2245 static struct strlist *cmdenviron; /* environment for builtin command */
2246 static int exitstatus; /* exit status of last command */
2247 static int oexitstatus; /* saved exit status */
2249 static void evalsubshell (const union node *, int);
2250 static void expredir (union node *);
2251 static void prehash (union node *);
2252 static void eprintlist (struct strlist *);
2254 static union node *parsecmd(int);
2256 * Called to reset things after an exception.
2260 * The eval commmand.
2262 static void evalstring (char *, int);
2276 STARTSTACKSTR(concat);
2280 STPUTC(*p++, concat);
2281 if ((p = *ap++) == NULL)
2283 STPUTC(' ', concat);
2285 STPUTC('\0', concat);
2286 p = grabstackstr(concat);
2288 evalstring(p, EV_TESTED);
2294 * Execute a command or commands contained in a string.
2297 static void evaltree (union node *, int);
2298 static void setinputstring (char *);
2299 static void popfile (void);
2300 static void setstackmark(struct stackmark *mark);
2301 static void popstackmark(struct stackmark *mark);
2305 evalstring(char *s, int flag)
2308 struct stackmark smark;
2310 setstackmark(&smark);
2312 while ((n = parsecmd(0)) != NEOF) {
2314 popstackmark(&smark);
2317 popstackmark(&smark);
2320 static struct builtincmd *find_builtin (const char *);
2321 static void expandarg (union node *, struct arglist *, int);
2322 static void calcsize (const union node *);
2323 static union node *copynode (const union node *);
2326 * Make a copy of a parse tree.
2329 static int funcblocksize; /* size of structures in function */
2330 static int funcstringsize; /* size of strings in node */
2331 static pointer funcblock; /* block to allocate function from */
2332 static char *funcstring; /* block to allocate strings from */
2335 static inline union node *
2336 copyfunc(union node *n)
2343 funcblock = ckmalloc(funcblocksize + funcstringsize);
2344 funcstring = (char *) funcblock + funcblocksize;
2349 * Free a parse tree.
2353 freefunc(union node *n)
2361 * Add a new command entry, replacing any existing command entry for
2366 addcmdentry(char *name, struct cmdentry *entry)
2368 struct tblentry *cmdp;
2371 cmdp = cmdlookup(name, 1);
2372 if (cmdp->cmdtype == CMDFUNCTION) {
2373 freefunc(cmdp->param.func);
2375 cmdp->cmdtype = entry->cmdtype;
2376 cmdp->param = entry->u;
2381 evalloop(const union node *n, int flags)
2388 evaltree(n->nbinary.ch1, EV_TESTED);
2390 skipping: if (evalskip == SKIPCONT && --skipcount <= 0) {
2394 if (evalskip == SKIPBREAK && --skipcount <= 0)
2398 if (n->type == NWHILE) {
2399 if (exitstatus != 0)
2402 if (exitstatus == 0)
2405 evaltree(n->nbinary.ch2, flags & EV_TESTED);
2406 status = exitstatus;
2411 exitstatus = status;
2415 evalfor(const union node *n, int flags)
2417 struct arglist arglist;
2420 struct stackmark smark;
2422 setstackmark(&smark);
2423 arglist.lastp = &arglist.list;
2424 for (argp = n->nfor.args ; argp ; argp = argp->narg.next) {
2425 oexitstatus = exitstatus;
2426 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE | EXP_RECORD);
2430 *arglist.lastp = NULL;
2434 for (sp = arglist.list ; sp ; sp = sp->next) {
2435 setvar(n->nfor.var, sp->text, 0);
2436 evaltree(n->nfor.body, flags & EV_TESTED);
2438 if (evalskip == SKIPCONT && --skipcount <= 0) {
2442 if (evalskip == SKIPBREAK && --skipcount <= 0)
2449 popstackmark(&smark);
2453 evalcase(const union node *n, int flags)
2457 struct arglist arglist;
2458 struct stackmark smark;
2460 setstackmark(&smark);
2461 arglist.lastp = &arglist.list;
2462 oexitstatus = exitstatus;
2463 expandarg(n->ncase.expr, &arglist, EXP_TILDE);
2464 for (cp = n->ncase.cases ; cp && evalskip == 0 ; cp = cp->nclist.next) {
2465 for (patp = cp->nclist.pattern ; patp ; patp = patp->narg.next) {
2466 if (casematch(patp, arglist.list->text)) {
2467 if (evalskip == 0) {
2468 evaltree(cp->nclist.body, flags);
2475 popstackmark(&smark);
2479 * Evaluate a pipeline. All the processes in the pipeline are children
2480 * of the process creating the pipeline. (This differs from some versions
2481 * of the shell, which make the last process in a pipeline the parent
2485 static inline void evalpipe(union node *n)
2488 struct nodelist *lp;
2493 TRACE(("evalpipe(0x%lx) called\n", (long)n));
2495 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next)
2498 jp = makejob(n, pipelen);
2500 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
2504 if (pipe(pip) < 0) {
2506 error("Pipe call failed");
2509 if (forkshell(jp, lp->n, n->npipe.backgnd) == 0) {
2513 dup_as_newfd(prevfd, 0);
2525 dup_as_newfd(pip[1], 1);
2529 evaltree(lp->n, EV_EXIT);
2537 if (n->npipe.backgnd == 0) {
2539 exitstatus = waitforjob(jp);
2540 TRACE(("evalpipe: job done exit status %d\n", exitstatus));
2545 static void find_command (const char *, struct cmdentry *, int, const char *);
2548 isassignment(const char *word) {
2549 if (!is_name(*word)) {
2554 } while (is_in_name(*word));
2555 return *word == '=';
2560 evalcommand(union node *cmd, int flags)
2562 struct stackmark smark;
2564 struct arglist arglist;
2565 struct arglist varlist;
2571 struct cmdentry cmdentry;
2573 char *volatile savecmdname;
2574 volatile struct shparam saveparam;
2575 struct localvar *volatile savelocalvars;
2579 const struct builtincmd *firstbltin;
2580 struct jmploc *volatile savehandler;
2581 struct jmploc jmploc;
2583 /* Avoid longjmp clobbering */
2590 /* First expand the arguments. */
2591 TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
2592 setstackmark(&smark);
2593 arglist.lastp = &arglist.list;
2594 varlist.lastp = &varlist.list;
2596 oexitstatus = exitstatus;
2599 for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
2600 expandarg(argp, &varlist, EXP_VARTILDE);
2603 argp = cmd->ncmd.args; argp && !arglist.list;
2604 argp = argp->narg.next
2606 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
2609 struct builtincmd *bcmd;
2611 bcmd = find_builtin(arglist.list->text);
2612 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
2613 for (; argp; argp = argp->narg.next) {
2614 if (pseudovarflag && isassignment(argp->narg.text)) {
2615 expandarg(argp, &arglist, EXP_VARTILDE);
2618 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
2621 *arglist.lastp = NULL;
2622 *varlist.lastp = NULL;
2623 expredir(cmd->ncmd.redirect);
2625 for (sp = arglist.list ; sp ; sp = sp->next)
2627 argv = stalloc(sizeof (char *) * (argc + 1));
2629 for (sp = arglist.list ; sp ; sp = sp->next) {
2630 TRACE(("evalcommand arg: %s\n", sp->text));
2635 if (iflag && funcnest == 0 && argc > 0)
2639 /* Print the command if xflag is set. */
2642 eprintlist(varlist.list);
2643 eprintlist(arglist.list);
2647 /* Now locate the command. */
2649 cmdentry.cmdtype = CMDBUILTIN;
2650 firstbltin = cmdentry.u.cmd = BLTINCMD;
2652 const char *oldpath;
2653 int findflag = DO_ERR;
2657 * Modify the command lookup path, if a PATH= assignment
2660 for (sp = varlist.list ; sp ; sp = sp->next)
2661 if (varequal(sp->text, defpathvar)) {
2662 path = sp->text + 5;
2663 findflag |= DO_BRUTE;
2666 oldfindflag = findflag;
2669 find_command(argv[0], &cmdentry, findflag, path);
2670 if (cmdentry.cmdtype == CMDUNKNOWN) { /* command not found */
2674 /* implement bltin and command here */
2675 if (cmdentry.cmdtype != CMDBUILTIN) {
2679 firstbltin = cmdentry.u.cmd;
2681 if (cmdentry.u.cmd == BLTINCMD) {
2683 struct builtincmd *bcmd;
2688 if (!(bcmd = find_builtin(*argv))) {
2689 out2fmt("%s: not found\n", *argv);
2693 cmdentry.u.cmd = bcmd;
2694 if (bcmd != BLTINCMD)
2698 if (cmdentry.u.cmd == find_builtin("command")) {
2703 if (*argv[0] == '-') {
2704 if (!equal(argv[0], "-p")) {
2714 findflag |= DO_BRUTE;
2717 findflag = oldfindflag;
2719 findflag |= DO_NOFUN;
2727 /* Fork off a child process if necessary. */
2728 if (cmd->ncmd.backgnd
2729 || (cmdentry.cmdtype == CMDNORMAL && (flags & EV_EXIT) == 0)
2731 jp = makejob(cmd, 1);
2732 mode = cmd->ncmd.backgnd;
2733 if (forkshell(jp, cmd, mode) != 0)
2734 goto parent; /* at end of routine */
2738 /* This is the child process if a fork occurred. */
2739 /* Execute the command. */
2740 if (cmdentry.cmdtype == CMDFUNCTION) {
2742 trputs("Shell function: "); trargs(argv);
2744 exitstatus = oexitstatus;
2745 redirect(cmd->ncmd.redirect, REDIR_PUSH);
2746 saveparam = shellparam;
2747 shellparam.malloc = 0;
2748 shellparam.nparam = argc - 1;
2749 shellparam.p = argv + 1;
2751 savelocalvars = localvars;
2754 if (setjmp(jmploc.loc)) {
2755 if (exception == EXSHELLPROC) {
2756 freeparam((volatile struct shparam *)
2759 saveparam.optind = shellparam.optind;
2760 saveparam.optoff = shellparam.optoff;
2761 freeparam(&shellparam);
2762 shellparam = saveparam;
2765 localvars = savelocalvars;
2766 handler = savehandler;
2767 longjmp(handler->loc, 1);
2769 savehandler = handler;
2771 for (sp = varlist.list ; sp ; sp = sp->next)
2774 evaltree(cmdentry.u.func, flags & EV_TESTED);
2778 localvars = savelocalvars;
2779 saveparam.optind = shellparam.optind;
2780 saveparam.optoff = shellparam.optoff;
2781 freeparam(&shellparam);
2782 shellparam = saveparam;
2783 handler = savehandler;
2786 if (evalskip == SKIPFUNC) {
2790 if (flags & EV_EXIT)
2791 exitshell(exitstatus);
2792 } else if (cmdentry.cmdtype == CMDBUILTIN) {
2794 trputs("builtin command: "); trargs(argv);
2796 mode = (cmdentry.u.cmd == EXECCMD)? 0 : REDIR_PUSH;
2797 redirect(cmd->ncmd.redirect, mode);
2798 savecmdname = commandname;
2799 if (IS_BUILTIN_SPECIAL(firstbltin)) {
2800 listsetvar(varlist.list);
2802 cmdenviron = varlist.list;
2805 if (setjmp(jmploc.loc)) {
2807 exitstatus = (e == EXINT)? SIGINT+128 : 2;
2810 savehandler = handler;
2812 commandname = argv[0];
2814 optptr = NULL; /* initialize nextopt */
2815 exitstatus = (*cmdentry.u.cmd->builtinfunc)(argc, argv);
2819 if (e != EXSHELLPROC) {
2820 commandname = savecmdname;
2821 if (flags & EV_EXIT)
2822 exitshell(exitstatus);
2824 handler = savehandler;
2826 if ((e != EXERROR && e != EXEXEC)
2827 || cmdentry.u.cmd == BLTINCMD
2828 || cmdentry.u.cmd == DOTCMD
2829 || cmdentry.u.cmd == EVALCMD
2830 || cmdentry.u.cmd == EXECCMD)
2834 if (cmdentry.u.cmd != EXECCMD)
2838 trputs("normal command: "); trargs(argv);
2840 redirect(cmd->ncmd.redirect, 0);
2842 for (sp = varlist.list ; sp ; sp = sp->next)
2843 setvareq(sp->text, VEXPORT|VSTACK);
2844 envp = environment();
2845 shellexec(argv, envp, path, cmdentry.u.index);
2849 parent: /* parent process gets here (if we forked) */
2850 if (mode == 0) { /* argument to fork */
2852 exitstatus = waitforjob(jp);
2858 setvar("_", lastarg, 0);
2859 popstackmark(&smark);
2863 * Evaluate a parse tree. The value is left in the global variable
2873 TRACE(("evaltree(NULL) called\n"));
2876 TRACE(("evaltree(0x%lx: %d) called\n", (long)n, n->type));
2879 evaltree(n->nbinary.ch1, flags & EV_TESTED);
2882 evaltree(n->nbinary.ch2, flags);
2885 evaltree(n->nbinary.ch1, EV_TESTED);
2886 if (evalskip || exitstatus != 0)
2888 evaltree(n->nbinary.ch2, flags);
2891 evaltree(n->nbinary.ch1, EV_TESTED);
2892 if (evalskip || exitstatus == 0)
2894 evaltree(n->nbinary.ch2, flags);
2897 expredir(n->nredir.redirect);
2898 redirect(n->nredir.redirect, REDIR_PUSH);
2899 evaltree(n->nredir.n, flags);
2903 evalsubshell(n, flags);
2906 evalsubshell(n, flags);
2909 evaltree(n->nif.test, EV_TESTED);
2912 if (exitstatus == 0)
2913 evaltree(n->nif.ifpart, flags);
2914 else if (n->nif.elsepart)
2915 evaltree(n->nif.elsepart, flags);
2931 struct builtincmd *bcmd;
2932 struct cmdentry entry;
2934 (bcmd = find_builtin(n->narg.text)) &&
2935 IS_BUILTIN_SPECIAL(bcmd)
2937 out2fmt("%s is a special built-in\n", n->narg.text);
2941 entry.cmdtype = CMDFUNCTION;
2942 entry.u.func = copyfunc(n->narg.next);
2943 addcmdentry(n->narg.text, &entry);
2948 evaltree(n->nnot.com, EV_TESTED);
2949 exitstatus = !exitstatus;
2957 evalcommand(n, flags);
2962 printf("Node type = %d\n", n->type);
2971 (checkexit && eflag && exitstatus && !(flags & EV_TESTED))
2973 exitshell(exitstatus);
2977 * Kick off a subshell to evaluate a tree.
2981 evalsubshell(const union node *n, int flags)
2984 int backgnd = (n->type == NBACKGND);
2986 expredir(n->nredir.redirect);
2988 if (forkshell(jp, n, backgnd) == 0) {
2990 flags &=~ EV_TESTED;
2991 redirect(n->nredir.redirect, 0);
2992 evaltree(n->nredir.n, flags | EV_EXIT); /* never returns */
2996 exitstatus = waitforjob(jp);
3002 * Compute the names of the files in a redirection list.
3005 static void fixredir(union node *n, const char *text, int err);
3008 expredir(union node *n)
3012 for (redir = n ; redir ; redir = redir->nfile.next) {
3014 fn.lastp = &fn.list;
3015 oexitstatus = exitstatus;
3016 switch (redir->type) {
3022 expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
3023 redir->nfile.expfname = fn.list->text;
3027 if (redir->ndup.vname) {
3028 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
3029 fixredir(redir, fn.list->text, 1);
3038 * Execute a command inside back quotes. If it's a builtin command, we
3039 * want to save its output in a block obtained from malloc. Otherwise
3040 * we fork off a subprocess and get the output of the command via a pipe.
3041 * Should be called with interrupts off.
3045 evalbackcmd(union node *n, struct backcmd *result)
3049 struct stackmark smark; /* unnecessary */
3051 setstackmark(&smark);
3062 error("Pipe call failed");
3064 if (forkshell(jp, n, FORK_NOJOB) == 0) {
3069 dup_as_newfd(pip[1], 1);
3073 evaltree(n, EV_EXIT);
3076 result->fd = pip[0];
3079 popstackmark(&smark);
3080 TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
3081 result->fd, result->buf, result->nleft, result->jp));
3086 * Execute a simple command.
3090 * Search for a command. This is called before we fork so that the
3091 * location of the command will be available in the parent as well as
3092 * the child. The check for "goodname" is an overly conservative
3093 * check that the name will not be subject to expansion.
3100 struct cmdentry entry;
3102 if (n->type == NCMD && n->ncmd.args)
3103 if (goodname(n->ncmd.args->narg.text))
3104 find_command(n->ncmd.args->narg.text, &entry, 0,
3110 * Builtin commands. Builtin commands whose functions are closely
3111 * tied to evaluation are implemented here.
3115 * No command given, or a bltin command with no arguments. Set the
3116 * specified variables.
3120 bltincmd(argc, argv)
3125 * Preserve exitstatus of a previous possible redirection
3133 * Handle break and continue commands. Break, continue, and return are
3134 * all handled by setting the evalskip flag. The evaluation routines
3135 * above all check this flag, and if it is set they start skipping
3136 * commands rather than executing them. The variable skipcount is
3137 * the number of loops to break/continue, or the number of function
3138 * levels to return. (The latter is always 1.) It should probably
3139 * be an error to break out of more loops than exist, but it isn't
3140 * in the standard shell so we don't make it one here.
3144 breakcmd(argc, argv)
3148 int n = argc > 1 ? number(argv[1]) : 1;
3153 evalskip = (**argv == 'c')? SKIPCONT : SKIPBREAK;
3161 * The return command.
3165 returncmd(argc, argv)
3169 int ret = argc > 1 ? number(argv[1]) : oexitstatus;
3172 evalskip = SKIPFUNC;
3177 /* Do what ksh does; skip the rest of the file */
3178 evalskip = SKIPFILE;
3185 #ifndef CONFIG_TRUE_FALSE
3187 false_main(argc, argv)
3196 true_main(argc, argv)
3205 * Controls whether the shell is interactive or not.
3208 static void setsignal(int signo);
3209 static void chkmail(int silent);
3213 setinteractive(int on)
3215 static int is_interactive;
3216 static int do_banner=0;
3218 if (on == is_interactive)
3224 is_interactive = on;
3225 if (do_banner==0 && is_interactive) {
3226 /* Looks like they want an interactive shell */
3227 #ifndef CONFIG_FEATURE_SH_EXTRA_QUIET
3228 printf( "\n\n" BB_BANNER " Built-in shell (ash)\n");
3229 printf( "Enter 'help' for a list of built-in commands.\n\n");
3238 setinteractive(iflag);
3251 iflag = 0; /* exit on error */
3254 for (sp = cmdenviron; sp ; sp = sp->next)
3255 setvareq(sp->text, VEXPORT|VSTACK);
3256 shellexec(argv + 1, environment(), pathval(), 0);
3262 eprintlist(struct strlist *sp)
3264 for (; sp; sp = sp->next) {
3265 out2fmt(" %s",sp->text);
3270 * Exec a program. Never returns. If you change this routine, you may
3271 * have to change the find_command routine as well.
3274 static const char *pathopt; /* set by padvance */
3277 shellexec(argv, envp, path, idx)
3278 char **argv, **envp;
3285 if (strchr(argv[0], '/') != NULL) {
3286 tryexec(argv[0], argv, envp);
3290 while ((cmdname = padvance(&path, argv[0])) != NULL) {
3291 if (--idx < 0 && pathopt == NULL) {
3292 tryexec(cmdname, argv, envp);
3293 if (errno != ENOENT && errno != ENOTDIR)
3300 /* Map to POSIX errors */
3312 exerror(EXEXEC, "%s: %s", argv[0], errmsg(e, E_EXEC));
3317 * Clear traps on a fork.
3323 for (tp = trap ; tp < &trap[NSIG] ; tp++) {
3324 if (*tp && **tp) { /* trap not NULL or SIG_IGN */
3329 setsignal(tp - trap);
3337 initshellproc(void) {
3363 /* from options.c: */
3367 for (i = 0; i < NOPTS; i++)
3383 for (sm = sigmode ; sm < sigmode + NSIG - 1; sm++) {
3395 static int preadbuffer(void);
3396 static void pushfile (void);
3399 * Read a character from the script, returning PEOF on end of file.
3400 * Nul characters in the input are silently discarded.
3403 #ifndef ASH_OPTIMIZE_FOR_SIZE
3404 #define pgetc_macro() (--parsenleft >= 0? *parsenextc++ : preadbuffer())
3408 return pgetc_macro();
3414 return --parsenleft >= 0? *parsenextc++ : preadbuffer();
3420 return pgetc_macro();
3426 * Undo the last call to pgetc. Only one character may be pushed back.
3427 * PEOF may be pushed back.
3430 static void pungetc(void)
3439 struct parsefile *pf = parsefile;
3448 parsefile = pf->prev;
3450 parsenleft = parsefile->nleft;
3451 parselleft = parsefile->lleft;
3452 parsenextc = parsefile->nextc;
3453 plinno = parsefile->linno;
3459 * Return to top level.
3464 while (parsefile != &basepf)
3469 * Close the file(s) that the shell is reading commands from. Called
3470 * after a fork is done.
3473 static void closescript(void)
3476 if (parsefile->fd > 0) {
3477 close(parsefile->fd);
3484 * Like setinputfile, but takes an open file descriptor. Call this with
3488 static void setinputfd(int fd, int push)
3490 (void) fcntl(fd, F_SETFD, FD_CLOEXEC);
3496 while (parsefile->strpush)
3500 if (parsefile->buf == NULL)
3501 parsefile->buf = ckmalloc(BUFSIZ);
3502 parselleft = parsenleft = 0;
3508 * Set the input to take input from a file. If push is set, push the
3509 * old input onto the stack first.
3513 setinputfile(const char *fname, int push)
3519 if ((fd = open(fname, O_RDONLY)) < 0)
3520 error("Can't open %s", fname);
3522 myfileno2 = dup_as_newfd(fd, 10);
3525 error("Out of file descriptors");
3528 setinputfd(fd, push);
3534 tryexec(char *cmd, char **argv, char **envp)
3538 #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
3542 #ifdef CONFIG_FEATURE_SH_APPLETS_ALWAYS_WIN
3543 name = get_last_path_component(name);
3546 for(argc_l=0;*argv_l!=NULL; argv_l++, argc_l++)
3549 for(argc_l=0;*argv_l!=NULL; argv_l++, argc_l++)
3551 run_applet_by_name(name, argc_l, argv);
3553 execve(cmd, argv, envp);
3558 setinputfile(cmd, 0);
3559 commandname = arg0 = savestr(argv[0]);
3561 exraise(EXSHELLPROC);
3566 static char *commandtext (const union node *);
3569 * Do a path search. The variable path (passed by reference) should be
3570 * set to the start of the path before the first call; padvance will update
3571 * this value as it proceeds. Successive calls to padvance will return
3572 * the possible path expansions in sequence. If an option (indicated by
3573 * a percent sign) appears in the path entry then the global variable
3574 * pathopt will be set to point to it; otherwise pathopt will be set to
3578 static const char *pathopt;
3580 static void growstackblock(void);
3584 padvance(const char **path, const char *name)
3594 for (p = start ; *p && *p != ':' && *p != '%' ; p++);
3595 len = p - start + strlen(name) + 2; /* "2" is for '/' and '\0' */
3596 while (stackblocksize() < len)
3600 memcpy(q, start, p - start);
3608 while (*p && *p != ':') p++;
3614 return stalloc(len);
3618 * Wrapper around strcmp for qsort/bsearch/...
3621 pstrcmp(const void *a, const void *b)
3623 return strcmp((const char *) a, (*(const char *const *) b) + 1);
3627 * Find a keyword is in a sorted array.
3630 static const char *const *
3631 findkwd(const char *s)
3633 return bsearch(s, tokname_array + KWDOFFSET,
3634 (sizeof(tokname_array)/sizeof(const char *)) - KWDOFFSET,
3635 sizeof(const char *), pstrcmp);
3639 /*** Command hashing code ***/
3647 struct tblentry **pp;
3648 struct tblentry *cmdp;
3651 struct cmdentry entry;
3654 const struct alias *ap;
3658 while ((c = nextopt("rvV")) != '\0') {
3662 } else if (c == 'v' || c == 'V') {
3666 if (*argptr == NULL) {
3667 for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
3668 for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
3669 if (cmdp->cmdtype != CMDBUILTIN) {
3670 printentry(cmdp, verbose);
3677 while ((name = *argptr++) != NULL) {
3678 if ((cmdp = cmdlookup(name, 0)) != NULL
3679 && (cmdp->cmdtype == CMDNORMAL
3680 || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0)))
3683 /* Then look at the aliases */
3684 if ((ap = lookupalias(name, 0)) != NULL) {
3686 printf("%s is an alias for %s\n", name, ap->val);
3692 /* First look at the keywords */
3693 if (findkwd(name)!=0) {
3695 printf("%s is a shell keyword\n", name);
3697 printf(snlfmt, name);
3701 find_command(name, &entry, DO_ERR, pathval());
3702 if (entry.cmdtype == CMDUNKNOWN) c = 1;
3704 cmdp = cmdlookup(name, 0);
3705 if (cmdp) printentry(cmdp, verbose=='v');
3713 printentry(cmdp, verbose)
3714 struct tblentry *cmdp;
3721 printf("%s%s", cmdp->cmdname, (verbose ? " is " : ""));
3722 if (cmdp->cmdtype == CMDNORMAL) {
3723 idx = cmdp->param.index;
3726 name = padvance(&path, cmdp->cmdname);
3728 } while (--idx >= 0);
3731 } else if (cmdp->cmdtype == CMDBUILTIN) {
3733 out1str("a shell builtin");
3734 } else if (cmdp->cmdtype == CMDFUNCTION) {
3737 out1str("a function\n");
3738 name = commandtext(cmdp->param.func);
3739 printf("%s() {\n %s\n}", cmdp->cmdname, name);
3745 error("internal error: cmdtype %d", cmdp->cmdtype);
3748 printf(snlfmt, cmdp->rehash ? "*" : nullstr);
3753 /*** List the available builtins ***/
3756 static int helpcmd(int argc, char** argv)
3760 printf("\nBuilt-in commands:\n-------------------\n");
3761 for (col=0, i=0; i < NUMBUILTINS; i++) {
3762 col += printf("%c%s", ((col == 0) ? '\t' : ' '),
3763 builtincmds[i].name+1);
3769 #ifdef CONFIG_FEATURE_SH_STANDALONE_SHELL
3771 extern const struct BB_applet applets[];
3772 extern const size_t NUM_APPLETS;
3774 for (i=0; i < NUM_APPLETS; i++) {
3776 col += printf("%c%s", ((col == 0) ? '\t' : ' '),
3786 return EXIT_SUCCESS;
3790 * Resolve a command name. If you change this routine, you may have to
3791 * change the shellexec routine as well.
3794 static int prefix (const char *, const char *);
3797 find_command(const char *name, struct cmdentry *entry, int act, const char *path)
3799 struct tblentry *cmdp;
3809 struct builtincmd *bcmd;
3811 /* If name contains a slash, don't use the hash table */
3812 if (strchr(name, '/') != NULL) {
3814 while (stat(name, &statb) < 0) {
3815 if (errno != ENOENT && errno != ENOTDIR)
3817 entry->cmdtype = CMDUNKNOWN;
3818 entry->u.index = -1;
3821 entry->cmdtype = CMDNORMAL;
3822 entry->u.index = -1;
3825 entry->cmdtype = CMDNORMAL;
3831 if (act & DO_BRUTE) {
3832 firstchange = path_change(path, &bltin);
3838 /* If name is in the table, and not invalidated by cd, we're done */
3839 if ((cmdp = cmdlookup(name, 0)) != NULL && cmdp->rehash == 0) {
3840 if (cmdp->cmdtype == CMDFUNCTION) {
3841 if (act & DO_NOFUN) {
3846 } else if (act & DO_BRUTE) {
3847 if ((cmdp->cmdtype == CMDNORMAL &&
3848 cmdp->param.index >= firstchange) ||
3849 (cmdp->cmdtype == CMDBUILTIN &&
3850 ((builtinloc < 0 && bltin >= 0) ?
3851 bltin : builtinloc) >= firstchange)) {
3852 /* need to recompute the entry */
3861 bcmd = find_builtin(name);
3862 regular = bcmd && IS_BUILTIN_REGULAR(bcmd);
3865 if (cmdp && (cmdp->cmdtype == CMDBUILTIN)) {
3868 } else if (act & DO_BRUTE) {
3869 if (firstchange == 0) {
3874 /* If %builtin not in path, check for builtin next */
3875 if (regular || (bltin < 0 && bcmd)) {
3878 entry->cmdtype = CMDBUILTIN;
3879 entry->u.cmd = bcmd;
3883 cmdp = cmdlookup(name, 1);
3884 cmdp->cmdtype = CMDBUILTIN;
3885 cmdp->param.cmd = bcmd;
3890 /* We have to search path. */
3891 prev = -1; /* where to start */
3892 if (cmdp && cmdp->rehash) { /* doing a rehash */
3893 if (cmdp->cmdtype == CMDBUILTIN)
3896 prev = cmdp->param.index;
3902 while ((fullname = padvance(&path, name)) != NULL) {
3903 stunalloc(fullname);
3905 if (idx >= firstchange) {
3909 if (prefix("builtin", pathopt)) {
3910 if ((bcmd = find_builtin(name))) {
3914 } else if (!(act & DO_NOFUN) &&
3915 prefix("func", pathopt)) {
3918 continue; /* ignore unimplemented options */
3921 /* if rehash, don't redo absolute path names */
3922 if (fullname[0] == '/' && idx <= prev &&
3923 idx < firstchange) {
3926 TRACE(("searchexec \"%s\": no change\n", name));
3929 while (stat(fullname, &statb) < 0) {
3930 if (errno != ENOENT && errno != ENOTDIR)
3934 e = EACCES; /* if we fail, this will be the error */
3935 if (!S_ISREG(statb.st_mode))
3937 if (pathopt) { /* this is a %func directory */
3938 stalloc(strlen(fullname) + 1);
3939 readcmdfile(fullname);
3940 if ((cmdp = cmdlookup(name, 0)) == NULL || cmdp->cmdtype != CMDFUNCTION)
3941 error("%s not defined in %s", name, fullname);
3942 stunalloc(fullname);
3945 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
3946 /* If we aren't called with DO_BRUTE and cmdp is set, it must
3947 be a function and we're being called with DO_NOFUN */
3949 entry->cmdtype = CMDNORMAL;
3950 entry->u.index = idx;
3954 cmdp = cmdlookup(name, 1);
3955 cmdp->cmdtype = CMDNORMAL;
3956 cmdp->param.index = idx;
3961 /* We failed. If there was an entry for this command, delete it */
3962 if (cmdp && updatetbl)
3965 out2fmt("%s: %s\n", name, errmsg(e, E_EXEC));
3966 entry->cmdtype = CMDUNKNOWN;
3971 entry->cmdtype = cmdp->cmdtype;
3972 entry->u = cmdp->param;
3978 * Search the table of builtin commands.
3982 bstrcmp(const void *name, const void *b)
3984 return strcmp((const char *)name, (*(const char *const *) b)+1);
3987 static struct builtincmd *
3988 find_builtin(const char *name)
3990 struct builtincmd *bp;
3992 bp = bsearch(name, builtincmds, NUMBUILTINS, sizeof(struct builtincmd),
4000 * Called when a cd is done. Marks all commands so the next time they
4001 * are executed they will be rehashed.
4006 struct tblentry **pp;
4007 struct tblentry *cmdp;
4009 for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
4010 for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
4011 if (cmdp->cmdtype == CMDNORMAL
4012 || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))
4021 * Called before PATH is changed. The argument is the new value of PATH;
4022 * pathval() still returns the old value at this point. Called with
4027 changepath(const char *newval)
4032 firstchange = path_change(newval, &bltin);
4033 if (builtinloc < 0 && bltin >= 0)
4034 builtinloc = bltin; /* zap builtins */
4035 clearcmdentry(firstchange);
4041 * Clear out command entries. The argument specifies the first entry in
4042 * PATH which has changed.
4046 clearcmdentry(firstchange)
4049 struct tblentry **tblp;
4050 struct tblentry **pp;
4051 struct tblentry *cmdp;
4054 for (tblp = cmdtable ; tblp < &cmdtable[CMDTABLESIZE] ; tblp++) {
4056 while ((cmdp = *pp) != NULL) {
4057 if ((cmdp->cmdtype == CMDNORMAL &&
4058 cmdp->param.index >= firstchange)
4059 || (cmdp->cmdtype == CMDBUILTIN &&
4060 builtinloc >= firstchange)) {
4073 * Delete all functions.
4078 struct tblentry **tblp;
4079 struct tblentry **pp;
4080 struct tblentry *cmdp;
4083 for (tblp = cmdtable ; tblp < &cmdtable[CMDTABLESIZE] ; tblp++) {
4085 while ((cmdp = *pp) != NULL) {
4086 if (cmdp->cmdtype == CMDFUNCTION) {
4088 freefunc(cmdp->param.func);
4101 * Locate a command in the command hash table. If "add" is nonzero,
4102 * add the command to the table if it is not already present. The
4103 * variable "lastcmdentry" is set to point to the address of the link
4104 * pointing to the entry, so that delete_cmd_entry can delete the
4108 static struct tblentry **lastcmdentry;
4110 static struct tblentry *
4111 cmdlookup(const char *name, int add)
4115 struct tblentry *cmdp;
4116 struct tblentry **pp;
4123 pp = &cmdtable[hashval % CMDTABLESIZE];
4124 for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
4125 if (equal(cmdp->cmdname, name))
4129 if (add && cmdp == NULL) {
4131 cmdp = *pp = ckmalloc(sizeof (struct tblentry) - ARB
4132 + strlen(name) + 1);
4134 cmdp->cmdtype = CMDUNKNOWN;
4136 strcpy(cmdp->cmdname, name);
4144 * Delete the command entry returned on the last lookup.
4148 delete_cmd_entry() {
4149 struct tblentry *cmdp;
4152 cmdp = *lastcmdentry;
4153 *lastcmdentry = cmdp->next;
4162 static const unsigned char nodesize[26] = {
4163 ALIGN(sizeof (struct nbinary)),
4164 ALIGN(sizeof (struct ncmd)),
4165 ALIGN(sizeof (struct npipe)),
4166 ALIGN(sizeof (struct nredir)),
4167 ALIGN(sizeof (struct nredir)),
4168 ALIGN(sizeof (struct nredir)),
4169 ALIGN(sizeof (struct nbinary)),
4170 ALIGN(sizeof (struct nbinary)),
4171 ALIGN(sizeof (struct nif)),
4172 ALIGN(sizeof (struct nbinary)),
4173 ALIGN(sizeof (struct nbinary)),
4174 ALIGN(sizeof (struct nfor)),
4175 ALIGN(sizeof (struct ncase)),
4176 ALIGN(sizeof (struct nclist)),
4177 ALIGN(sizeof (struct narg)),
4178 ALIGN(sizeof (struct narg)),
4179 ALIGN(sizeof (struct nfile)),
4180 ALIGN(sizeof (struct nfile)),
4181 ALIGN(sizeof (struct nfile)),
4182 ALIGN(sizeof (struct nfile)),
4183 ALIGN(sizeof (struct nfile)),
4184 ALIGN(sizeof (struct ndup)),
4185 ALIGN(sizeof (struct ndup)),
4186 ALIGN(sizeof (struct nhere)),
4187 ALIGN(sizeof (struct nhere)),
4188 ALIGN(sizeof (struct nnot)),
4194 * Delete a function if it exists.
4198 unsetfunc(char *name)
4200 struct tblentry *cmdp;
4202 if ((cmdp = cmdlookup(name, 0)) != NULL && cmdp->cmdtype == CMDFUNCTION) {
4203 freefunc(cmdp->param.func);
4210 * Locate and print what a word is...
4214 typecmd(int argc, char **argv)
4222 for (i = 1; i < argc; i++) {
4223 argv_a[0] = argv[i];
4226 err |= hashcmd(argc, argv);
4233 commandcmd(argc, argv)
4238 int default_path = 0;
4239 int verify_only = 0;
4240 int verbose_verify_only = 0;
4242 while ((c = nextopt("pvV")) != '\0')
4251 verbose_verify_only = 1;
4255 if (default_path + verify_only + verbose_verify_only > 1 ||
4258 "command [-p] command [arg ...]\n"
4259 "command {-v|-V} command\n");
4263 if (verify_only || verbose_verify_only) {
4267 argv_a[0] = *argptr;
4269 optptr = verbose_verify_only ? "v" : "V"; /* reverse special */
4270 return hashcmd(argc, argv);
4278 path_change(newval, bltin)
4282 const char *old, *new;
4288 firstchange = 9999; /* assume no change */
4294 if ((*old == '\0' && *new == ':')
4295 || (*old == ':' && *new == '\0'))
4297 old = new; /* ignore subsequent differences */
4301 if (*new == '%' && *bltin < 0 && prefix("builtin", new + 1))
4308 if (builtinloc >= 0 && *bltin < 0)
4313 * Routines to expand arguments to commands. We have to deal with
4314 * backquotes, shell variables, and file metacharacters.
4319 #define RMESCAPE_ALLOC 0x1 /* Allocate a new string */
4320 #define RMESCAPE_GLOB 0x2 /* Add backslashes for glob */
4323 * Structure specifying which parts of the string should be searched
4324 * for IFS characters.
4328 struct ifsregion *next; /* next region in list */
4329 int begoff; /* offset of start of region */
4330 int endoff; /* offset of end of region */
4331 int nulonly; /* search for nul bytes only */
4335 static char *expdest; /* output of current string */
4336 static struct nodelist *argbackq; /* list of back quote expressions */
4337 static struct ifsregion ifsfirst; /* first struct in list of ifs regions */
4338 static struct ifsregion *ifslastp; /* last struct in list */
4339 static struct arglist exparg; /* holds expanded arg list */
4341 static void argstr (char *, int);
4342 static char *exptilde (char *, int);
4343 static void expbackq (union node *, int, int);
4344 static int subevalvar (char *, char *, int, int, int, int, int);
4345 static int varisset (char *, int);
4346 static void strtodest (const char *, int, int);
4347 static void varvalue (char *, int, int);
4348 static void recordregion (int, int, int);
4349 static void removerecordregions (int);
4350 static void ifsbreakup (char *, struct arglist *);
4351 static void ifsfree (void);
4352 static void expandmeta (struct strlist *, int);
4353 #if defined(__GLIBC__) && __GLIBC__ >= 2 && !defined(FNMATCH_BROKEN)
4354 #define preglob(p) _rmescapes((p), RMESCAPE_ALLOC | RMESCAPE_GLOB)
4355 #if !defined(GLOB_BROKEN)
4356 static void addglob (const glob_t *);
4359 #if !(defined(__GLIBC__) && __GLIBC__ >= 2 && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN))
4360 static void expmeta (char *, char *);
4362 #if !(defined(__GLIBC__) && __GLIBC__ >= 2 && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN))
4363 static struct strlist *expsort (struct strlist *);
4364 static struct strlist *msort (struct strlist *, int);
4366 static int patmatch (char *, char *, int);
4367 #if defined(__GLIBC__) && __GLIBC__ >= 2 && !defined(FNMATCH_BROKEN)
4368 static int patmatch2 (char *, char *, int);
4370 static int pmatch (char *, char *, int);
4371 #define patmatch2 patmatch
4373 static char *cvtnum (int, char *);
4376 * Expand shell variables and backquotes inside a here document.
4379 /* arg: the document, fd: where to write the expanded version */
4381 expandhere(union node *arg, int fd)
4384 expandarg(arg, (struct arglist *)NULL, 0);
4385 xwrite(fd, stackblock(), expdest - stackblock());
4390 * Perform variable substitution and command substitution on an argument,
4391 * placing the resulting list of arguments in arglist. If EXP_FULL is true,
4392 * perform splitting and file name expansion. When arglist is NULL, perform
4393 * here document expansion.
4397 expandarg(arg, arglist, flag)
4399 struct arglist *arglist;
4405 argbackq = arg->narg.backquote;
4406 STARTSTACKSTR(expdest);
4407 ifsfirst.next = NULL;
4409 argstr(arg->narg.text, flag);
4410 if (arglist == NULL) {
4411 return; /* here document expanded */
4413 STPUTC('\0', expdest);
4414 p = grabstackstr(expdest);
4415 exparg.lastp = &exparg.list;
4419 if (flag & EXP_FULL) {
4420 ifsbreakup(p, &exparg);
4421 *exparg.lastp = NULL;
4422 exparg.lastp = &exparg.list;
4423 expandmeta(exparg.list, flag);
4425 if (flag & EXP_REDIR) /*XXX - for now, just remove escapes */
4427 sp = (struct strlist *)stalloc(sizeof (struct strlist));
4430 exparg.lastp = &sp->next;
4433 *exparg.lastp = NULL;
4435 *arglist->lastp = exparg.list;
4436 arglist->lastp = exparg.lastp;
4442 * Expand a variable, and return a pointer to the next character in the
4446 static inline char * evalvar(char *p, int flag)
4459 int quotes = flag & (EXP_FULL | EXP_CASE);
4462 subtype = varflags & VSTYPE;
4467 p = strchr(p, '=') + 1;
4468 again: /* jump here after setting a variable with ${var=text} */
4470 set = varisset(var, varflags & VSNUL);
4473 val = lookupvar(var);
4474 if (val == NULL || ((varflags & VSNUL) && val[0] == '\0')) {
4481 startloc = expdest - stackblock();
4482 if (set && subtype != VSPLUS) {
4483 /* insert the value of the variable */
4485 varvalue(var, varflags & VSQUOTE, flag);
4486 if (subtype == VSLENGTH) {
4487 varlen = expdest - stackblock() - startloc;
4488 STADJUST(-varlen, expdest);
4491 if (subtype == VSLENGTH) {
4492 varlen = strlen(val);
4496 varflags & VSQUOTE ?
4497 DQSYNTAX : BASESYNTAX,
4504 if (subtype == VSPLUS)
4507 easy = ((varflags & VSQUOTE) == 0 ||
4508 (*var == '@' && shellparam.nparam != 1));
4513 expdest = cvtnum(varlen, expdest);
4520 recordregion(startloc, expdest - stackblock(),
4521 varflags & VSQUOTE);
4537 case VSTRIMRIGHTMAX:
4541 * Terminate the string and start recording the pattern
4544 STPUTC('\0', expdest);
4545 patloc = expdest - stackblock();
4546 if (subevalvar(p, NULL, patloc, subtype,
4547 startloc, varflags, quotes) == 0) {
4548 int amount = (expdest - stackblock() - patloc) + 1;
4549 STADJUST(-amount, expdest);
4551 /* Remove any recorded regions beyond start of variable */
4552 removerecordregions(startloc);
4558 if (subevalvar(p, var, 0, subtype, startloc,
4559 varflags, quotes)) {
4562 * Remove any recorded regions beyond
4565 removerecordregions(startloc);
4580 if (subtype != VSNORMAL) { /* skip to end of alternative */
4583 if ((c = *p++) == CTLESC)
4585 else if (c == CTLBACKQ || c == (CTLBACKQ|CTLQUOTE)) {
4587 argbackq = argbackq->next;
4588 } else if (c == CTLVAR) {
4589 if ((*p++ & VSTYPE) != VSNORMAL)
4591 } else if (c == CTLENDVAR) {
4602 * Perform variable and command substitution. If EXP_FULL is set, output CTLESC
4603 * characters to allow for further processing. Otherwise treat
4604 * $@ like $* since no splitting will be performed.
4613 int quotes = flag & (EXP_FULL | EXP_CASE); /* do CTLESC */
4616 if (*p == '~' && (flag & (EXP_TILDE | EXP_VARTILDE)))
4617 p = exptilde(p, flag);
4621 case CTLENDVAR: /* ??? */
4624 /* "$@" syntax adherence hack */
4625 if (p[0] == CTLVAR && p[2] == '@' && p[3] == '=')
4627 if ((flag & EXP_FULL) != 0)
4637 p = evalvar(p, flag);
4640 case CTLBACKQ|CTLQUOTE:
4641 expbackq(argbackq->n, c & CTLQUOTE, flag);
4642 argbackq = argbackq->next;
4644 #ifdef ASH_MATH_SUPPORT
4652 * sort of a hack - expand tildes in variable
4653 * assignments (after the first '=' and after ':'s).
4656 if (flag & EXP_VARTILDE && *p == '~') {
4663 p = exptilde(p, flag);
4679 char c, *startp = p;
4682 int quotes = flag & (EXP_FULL | EXP_CASE);
4684 while ((c = *p) != '\0') {
4691 if (flag & EXP_VARTILDE)
4701 if (*(startp+1) == '\0') {
4702 if ((home = lookupvar("HOME")) == NULL)
4705 if ((pw = getpwnam(startp+1)) == NULL)
4712 strtodest(home, SQSYNTAX, quotes);
4721 removerecordregions(int endoff)
4723 if (ifslastp == NULL)
4726 if (ifsfirst.endoff > endoff) {
4727 while (ifsfirst.next != NULL) {
4728 struct ifsregion *ifsp;
4730 ifsp = ifsfirst.next->next;
4731 ckfree(ifsfirst.next);
4732 ifsfirst.next = ifsp;
4735 if (ifsfirst.begoff > endoff)
4738 ifslastp = &ifsfirst;
4739 ifsfirst.endoff = endoff;
4744 ifslastp = &ifsfirst;
4745 while (ifslastp->next && ifslastp->next->begoff < endoff)
4746 ifslastp=ifslastp->next;
4747 while (ifslastp->next != NULL) {
4748 struct ifsregion *ifsp;
4750 ifsp = ifslastp->next->next;
4751 ckfree(ifslastp->next);
4752 ifslastp->next = ifsp;
4755 if (ifslastp->endoff > endoff)
4756 ifslastp->endoff = endoff;
4760 #ifdef ASH_MATH_SUPPORT
4762 * Expand arithmetic expression. Backup to start of expression,
4763 * evaluate, place result in (backed up) result, adjust string position.
4772 int quotes = flag & (EXP_FULL | EXP_CASE);
4778 * This routine is slightly over-complicated for
4779 * efficiency. First we make sure there is
4780 * enough space for the result, which may be bigger
4781 * than the expression if we add exponentation. Next we
4782 * scan backwards looking for the start of arithmetic. If the
4783 * next previous character is a CTLESC character, then we
4784 * have to rescan starting from the beginning since CTLESC
4785 * characters have to be processed left to right.
4787 CHECKSTRSPACE(10, expdest);
4788 USTPUTC('\0', expdest);
4789 start = stackblock();
4791 while (*p != CTLARI && p >= start)
4794 error("missing CTLARI (shouldn't happen)");
4795 if (p > start && *(p-1) == CTLESC)
4796 for (p = start; *p != CTLARI; p++)
4805 removerecordregions(begoff);
4808 result = arith(p+2, &errcode);
4811 error("divide by zero");
4813 error("syntax error: \"%s\"\n", p+2);
4815 snprintf(p, 12, "%d", result);
4821 recordregion(begoff, p - 1 - start, 0);
4822 result = expdest - p + 1;
4823 STADJUST(-result, expdest);
4828 * Expand stuff in backwards quotes.
4832 expbackq(cmd, quoted, flag)
4837 volatile struct backcmd in;
4841 char *dest = expdest;
4842 volatile struct ifsregion saveifs;
4843 struct ifsregion *volatile savelastp;
4844 struct nodelist *volatile saveargbackq;
4846 int startloc = dest - stackblock();
4847 int syntax = quoted ? DQSYNTAX : BASESYNTAX;
4848 volatile int saveherefd;
4849 int quotes = flag & (EXP_FULL | EXP_CASE);
4850 struct jmploc jmploc;
4851 struct jmploc *volatile savehandler;
4855 /* Avoid longjmp clobbering */
4866 savelastp = ifslastp;
4867 saveargbackq = argbackq;
4868 saveherefd = herefd;
4870 if ((ex = setjmp(jmploc.loc))) {
4873 savehandler = handler;
4876 p = grabstackstr(dest);
4877 evalbackcmd(cmd, (struct backcmd *) &in);
4878 ungrabstackstr(p, dest);
4882 ifslastp = savelastp;
4883 argbackq = saveargbackq;
4884 herefd = saveherefd;
4892 if (--in.nleft < 0) {
4895 i = safe_read(in.fd, buf, sizeof buf);
4896 TRACE(("expbackq: read returns %d\n", i));
4903 if (lastc != '\0') {
4904 if (quotes && SIT(lastc, syntax) == CCTL)
4905 STPUTC(CTLESC, dest);
4906 STPUTC(lastc, dest);
4910 /* Eat all trailing newlines */
4911 for (; dest > stackblock() && dest[-1] == '\n';)
4920 exitstatus = waitforjob(in.jp);
4921 handler = savehandler;
4923 longjmp(handler->loc, 1);
4926 recordregion(startloc, dest - stackblock(), 0);
4927 TRACE(("evalbackq: size=%d: \"%.*s\"\n",
4928 (dest - stackblock()) - startloc,
4929 (dest - stackblock()) - startloc,
4930 stackblock() + startloc));
4936 subevalvar(p, str, strloc, subtype, startloc, varflags, quotes)
4949 int saveherefd = herefd;
4950 struct nodelist *saveargbackq = argbackq;
4954 argstr(p, subtype != VSASSIGN && subtype != VSQUESTION ? EXP_CASE : 0);
4955 STACKSTRNUL(expdest);
4956 herefd = saveherefd;
4957 argbackq = saveargbackq;
4958 startp = stackblock() + startloc;
4960 str = stackblock() + strloc;
4964 setvar(str, startp, 0);
4965 amount = startp - expdest;
4966 STADJUST(amount, expdest);
4973 if (*p != CTLENDVAR) {
4974 out2fmt(snlfmt, startp);
4975 error((char *)NULL);
4977 error("%.*s: parameter %snot set", p - str - 1,
4978 str, (varflags & VSNUL) ? "null or "
4983 for (loc = startp; loc < str; loc++) {
4986 if (patmatch2(str, startp, quotes))
4989 if (quotes && *loc == CTLESC)
4995 for (loc = str - 1; loc >= startp;) {
4998 if (patmatch2(str, startp, quotes))
5002 if (quotes && loc > startp && *(loc - 1) == CTLESC) {
5003 for (q = startp; q < loc; q++)
5013 for (loc = str - 1; loc >= startp;) {
5014 if (patmatch2(str, loc, quotes))
5017 if (quotes && loc > startp && *(loc - 1) == CTLESC) {
5018 for (q = startp; q < loc; q++)
5027 case VSTRIMRIGHTMAX:
5028 for (loc = startp; loc < str - 1; loc++) {
5029 if (patmatch2(str, loc, quotes))
5031 if (quotes && *loc == CTLESC)
5044 amount = ((str - 1) - (loc - startp)) - expdest;
5045 STADJUST(amount, expdest);
5046 while (loc != str - 1)
5051 amount = loc - expdest;
5052 STADJUST(amount, expdest);
5053 STPUTC('\0', expdest);
5054 STADJUST(-1, expdest);
5060 * Test whether a specialized variable is set.
5064 varisset(name, nulok)
5069 return backgndpid != -1;
5070 else if (*name == '@' || *name == '*') {
5071 if (*shellparam.p == NULL)
5077 for (av = shellparam.p; *av; av++)
5082 } else if (is_digit(*name)) {
5084 int num = atoi(name);
5086 if (num > shellparam.nparam)
5092 ap = shellparam.p[num - 1];
5094 if (nulok && (ap == NULL || *ap == '\0'))
5101 * Put a string on the stack.
5105 strtodest(const char *p, int syntax, int quotes)
5108 if (quotes && SIT(*p,syntax) == CCTL)
5109 STPUTC(CTLESC, expdest);
5110 STPUTC(*p++, expdest);
5115 * Add the value of a specialized variable to the stack string.
5119 varvalue(char *name, int quoted, int flags)
5128 int allow_split = flags & EXP_FULL;
5129 int quotes = flags & (EXP_FULL | EXP_CASE);
5131 syntax = quoted ? DQSYNTAX : BASESYNTAX;
5140 num = shellparam.nparam;
5145 expdest = cvtnum(num, expdest);
5148 for (i = 0 ; i < NOPTS ; i++) {
5150 STPUTC(optent_letter(optlist[i]), expdest);
5154 if (allow_split && quoted) {
5155 sep = 1 << CHAR_BIT;
5160 sep = ifsset() ? ifsval()[0] : ' ';
5162 sepq = SIT(sep,syntax) == CCTL;
5165 for (ap = shellparam.p ; (p = *ap++) != NULL ; ) {
5166 strtodest(p, syntax, quotes);
5169 STPUTC(CTLESC, expdest);
5170 STPUTC(sep, expdest);
5175 strtodest(arg0, syntax, quotes);
5179 if (num > 0 && num <= shellparam.nparam) {
5180 strtodest(shellparam.p[num - 1], syntax, quotes);
5188 * Record the fact that we have to scan this region of the
5189 * string for IFS characters.
5193 recordregion(start, end, nulonly)
5198 struct ifsregion *ifsp;
5200 if (ifslastp == NULL) {
5204 ifsp = (struct ifsregion *)ckmalloc(sizeof (struct ifsregion));
5206 ifslastp->next = ifsp;
5210 ifslastp->begoff = start;
5211 ifslastp->endoff = end;
5212 ifslastp->nulonly = nulonly;
5218 * Break the argument string into pieces based upon IFS and add the
5219 * strings to the argument list. The regions of the string to be
5220 * searched for IFS characters have been stored by recordregion.
5223 ifsbreakup(string, arglist)
5225 struct arglist *arglist;
5227 struct ifsregion *ifsp;
5232 const char *ifs, *realifs;
5240 realifs = ifsset() ? ifsval() : defifs;
5241 if (ifslastp != NULL) {
5244 p = string + ifsp->begoff;
5245 nulonly = ifsp->nulonly;
5246 ifs = nulonly ? nullstr : realifs;
5248 while (p < string + ifsp->endoff) {
5252 if (strchr(ifs, *p)) {
5254 ifsspc = (strchr(defifs, *p) != NULL);
5255 /* Ignore IFS whitespace at start */
5256 if (q == start && ifsspc) {
5262 sp = (struct strlist *)stalloc(sizeof *sp);
5264 *arglist->lastp = sp;
5265 arglist->lastp = &sp->next;
5269 if (p >= string + ifsp->endoff) {
5275 if (strchr(ifs, *p) == NULL ) {
5278 } else if (strchr(defifs, *p) == NULL) {
5294 } while ((ifsp = ifsp->next) != NULL);
5295 if (!(*start || (!ifsspc && start > string && nulonly))) {
5300 sp = (struct strlist *)stalloc(sizeof *sp);
5302 *arglist->lastp = sp;
5303 arglist->lastp = &sp->next;
5309 while (ifsfirst.next != NULL) {
5310 struct ifsregion *ifsp;
5312 ifsp = ifsfirst.next->next;
5313 ckfree(ifsfirst.next);
5314 ifsfirst.next = ifsp;
5318 ifsfirst.next = NULL;
5322 * Add a file name to the list.
5326 addfname(const char *name)
5332 sp = (struct strlist *)stalloc(sizeof *sp);
5335 exparg.lastp = &sp->next;
5339 * Expand shell metacharacters. At this point, the only control characters
5340 * should be escapes. The results are stored in the list exparg.
5343 #if defined(__GLIBC__) && __GLIBC__ >= 2 && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN)
5345 expandmeta(str, flag)
5346 struct strlist *str;
5351 /* TODO - EXP_REDIR */
5356 p = preglob(str->text);
5358 switch (glob(p, 0, 0, &pglob)) {
5360 if(pglob.gl_pathv[1]==0 && !strcmp(p, pglob.gl_pathv[0]))
5371 *exparg.lastp = str;
5372 rmescapes(str->text);
5373 exparg.lastp = &str->next;
5375 default: /* GLOB_NOSPACE */
5376 error("Out of space");
5384 * Add the result of glob(3) to the list.
5389 const glob_t *pglob;
5391 char **p = pglob->gl_pathv;
5399 #else /* defined(__GLIBC__) && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN) */
5400 static char *expdir;
5404 expandmeta(str, flag)
5405 struct strlist *str;
5409 struct strlist **savelastp;
5412 /* TODO - EXP_REDIR */
5418 for (;;) { /* fast check for meta chars */
5419 if ((c = *p++) == '\0')
5421 if (c == '*' || c == '?' || c == '[' || c == '!')
5424 savelastp = exparg.lastp;
5426 if (expdir == NULL) {
5427 int i = strlen(str->text);
5428 expdir = ckmalloc(i < 2048 ? 2048 : i); /* XXX */
5431 expmeta(expdir, str->text);
5435 if (exparg.lastp == savelastp) {
5440 *exparg.lastp = str;
5441 rmescapes(str->text);
5442 exparg.lastp = &str->next;
5444 *exparg.lastp = NULL;
5445 *savelastp = sp = expsort(*savelastp);
5446 while (sp->next != NULL)
5448 exparg.lastp = &sp->next;
5456 * Do metacharacter (i.e. *, ?, [...]) expansion.
5460 expmeta(enddir, name)
5478 for (p = name ; ; p++) {
5479 if (*p == '*' || *p == '?')
5481 else if (*p == '[') {
5486 while (*q == CTLQUOTEMARK)
5490 if (*q == '/' || *q == '\0')
5497 } else if (*p == '!' && p[1] == '!' && (p == name || p[-1] == '/')) {
5499 } else if (*p == '\0')
5501 else if (*p == CTLQUOTEMARK)
5503 else if (*p == CTLESC)
5511 if (metaflag == 0) { /* we've reached the end of the file name */
5512 if (enddir != expdir)
5514 for (p = name ; ; p++) {
5515 if (*p == CTLQUOTEMARK)
5523 if (metaflag == 0 || lstat(expdir, &statb) >= 0)
5528 if (start != name) {
5531 while (*p == CTLQUOTEMARK)
5538 if (enddir == expdir) {
5540 } else if (enddir == expdir + 1 && *expdir == '/') {
5546 if ((dirp = opendir(cp)) == NULL)
5548 if (enddir != expdir)
5550 if (*endname == 0) {
5558 while (*p == CTLQUOTEMARK)
5564 while (! int_pending() && (dp = readdir(dirp)) != NULL) {
5565 if (dp->d_name[0] == '.' && ! matchdot)
5567 if (patmatch(start, dp->d_name, 0)) {
5569 strcpy(enddir, dp->d_name);
5572 for (p = enddir, cp = dp->d_name;
5573 (*p++ = *cp++) != '\0';)
5576 expmeta(p, endname);
5584 #endif /* defined(__GLIBC__) && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN) */
5588 #if !(defined(__GLIBC__) && __GLIBC__ >= 2 && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN))
5590 * Sort the results of file name expansion. It calculates the number of
5591 * strings to sort and then calls msort (short for merge sort) to do the
5595 static struct strlist *
5597 struct strlist *str;
5603 for (sp = str ; sp ; sp = sp->next)
5605 return msort(str, len);
5609 static struct strlist *
5611 struct strlist *list;
5614 struct strlist *p, *q = NULL;
5615 struct strlist **lpp;
5623 for (n = half ; --n >= 0 ; ) {
5627 q->next = NULL; /* terminate first half of list */
5628 q = msort(list, half); /* sort first half of list */
5629 p = msort(p, len - half); /* sort second half */
5632 if (strcmp(p->text, q->text) < 0) {
5635 if ((p = *lpp) == NULL) {
5642 if ((q = *lpp) == NULL) {
5655 * Returns true if the pattern matches the string.
5658 #if defined(__GLIBC__) && __GLIBC__ >= 2 && !defined(FNMATCH_BROKEN)
5659 /* squoted: string might have quote chars */
5661 patmatch(char *pattern, char *string, int squoted)
5666 p = preglob(pattern);
5667 q = squoted ? _rmescapes(string, RMESCAPE_ALLOC) : string;
5669 return !fnmatch(p, q, 0);
5674 patmatch2(char *pattern, char *string, int squoted)
5680 p = grabstackstr(expdest);
5681 res = patmatch(pattern, string, squoted);
5682 ungrabstackstr(p, expdest);
5687 patmatch(char *pattern, char *string, int squoted) {
5688 return pmatch(pattern, string, squoted);
5693 pmatch(char *pattern, char *string, int squoted)
5705 if (squoted && *q == CTLESC)
5713 if (squoted && *q == CTLESC)
5720 while (c == CTLQUOTEMARK || c == '*')
5722 if (c != CTLESC && c != CTLQUOTEMARK &&
5723 c != '?' && c != '*' && c != '[') {
5725 if (squoted && *q == CTLESC &&
5730 if (squoted && *q == CTLESC)
5736 if (pmatch(p, q, squoted))
5738 if (squoted && *q == CTLESC)
5740 } while (*q++ != '\0');
5751 while (*endp == CTLQUOTEMARK)
5754 goto dft; /* no matching ] */
5755 if (*endp == CTLESC)
5767 if (squoted && chr == CTLESC)
5773 if (c == CTLQUOTEMARK)
5777 if (*p == '-' && p[1] != ']') {
5779 while (*p == CTLQUOTEMARK)
5783 if (chr >= c && chr <= *p)
5790 } while ((c = *p++) != ']');
5791 if (found == invert)
5796 if (squoted && *q == CTLESC)
5813 * Remove any CTLESC characters from a string.
5816 #if defined(__GLIBC__) && __GLIBC__ >= 2 && !defined(FNMATCH_BROKEN)
5818 _rmescapes(char *str, int flag)
5821 static const char qchars[] = { CTLESC, CTLQUOTEMARK, 0 };
5823 p = strpbrk(str, qchars);
5829 if (flag & RMESCAPE_ALLOC) {
5830 size_t len = p - str;
5831 q = r = stalloc(strlen(p) + len + 1);
5833 memcpy(q, str, len);
5838 if (*p == CTLQUOTEMARK) {
5844 if (flag & RMESCAPE_GLOB && *p != '/') {
5861 while (*p != CTLESC && *p != CTLQUOTEMARK) {
5867 if (*p == CTLQUOTEMARK) {
5882 * See if a pattern matches in a case statement.
5886 casematch(union node *pattern, const char *val)
5888 struct stackmark smark;
5892 setstackmark(&smark);
5893 argbackq = pattern->narg.backquote;
5894 STARTSTACKSTR(expdest);
5896 argstr(pattern->narg.text, EXP_TILDE | EXP_CASE);
5897 STPUTC('\0', expdest);
5898 p = grabstackstr(expdest);
5899 result = patmatch(p, (char *)val, 0);
5900 popstackmark(&smark);
5915 CHECKSTRSPACE(32, buf);
5916 len = sprintf(buf, "%d", num);
5921 * Editline and history functions (and glue).
5923 static int histcmd(argc, argv)
5927 error("not compiled with history support");
5933 struct redirtab *next;
5934 short renamed[10]; /* Current ash support only 0-9 descriptors */
5935 /* char on arm (and others) can't be negative */
5938 static struct redirtab *redirlist;
5940 extern char **environ;
5945 * Initialization code.
5958 basepf.nextc = basepf.buf = basebuf;
5967 for (envp = environ ; *envp ; envp++) {
5968 if (strchr(*envp, '=')) {
5969 setvareq(*envp, VEXPORT|VTEXTFIXED);
5973 snprintf(ppid, sizeof(ppid), "%d", (int) getppid());
5974 setvar("PPID", ppid, 0);
5981 * This routine is called when an error or an interrupt occurs in an
5982 * interactive shell and control is returned to the main command loop.
5985 /* 1 == check for aliases, 2 == also check for assignments */
5986 static int checkalias; /* also used in no alias mode for check assignments */
6000 if (exception != EXSHELLPROC)
6001 parselleft = parsenleft = 0; /* clear input buffer */
6005 /* from parser.c: */
6023 * This file implements the input routines used by the parser.
6026 #ifdef CONFIG_FEATURE_COMMAND_EDITING
6027 static const char * cmdedit_prompt;
6028 static inline void putprompt(const char *s) {
6032 static inline void putprompt(const char *s) {
6037 #define EOF_NLEFT -99 /* value of parsenleft when EOF pushed back */
6042 * Same as pgetc(), but ignores PEOA.
6052 } while (c == PEOA);
6056 static inline int pgetc2() { return pgetc_macro(); }
6060 * Read a line from the script.
6063 static inline char *
6064 pfgets(char *line, int len)
6070 while (--nleft > 0) {
6089 char *buf = parsefile->buf;
6093 #ifdef CONFIG_FEATURE_COMMAND_EDITING
6095 if (!iflag || parsefile->fd)
6096 nr = safe_read(parsefile->fd, buf, BUFSIZ - 1);
6098 nr = cmdedit_read_input((char*)cmdedit_prompt, buf);
6102 nr = safe_read(parsefile->fd, buf, BUFSIZ - 1);
6106 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
6107 int flags = fcntl(0, F_GETFL, 0);
6108 if (flags >= 0 && flags & O_NONBLOCK) {
6109 flags &=~ O_NONBLOCK;
6110 if (fcntl(0, F_SETFL, flags) >= 0) {
6111 out2str("sh: turning off NDELAY mode\n");
6123 struct strpush *sp = parsefile->strpush;
6128 if (parsenextc[-1] == ' ' || parsenextc[-1] == '\t') {
6133 if (sp->string != sp->ap->val) {
6137 sp->ap->flag &= ~ALIASINUSE;
6138 if (sp->ap->flag & ALIASDEAD) {
6139 unalias(sp->ap->name);
6143 parsenextc = sp->prevstring;
6144 parsenleft = sp->prevnleft;
6145 /*dprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/
6146 parsefile->strpush = sp->prev;
6147 if (sp != &(parsefile->basestrpush))
6154 * Refill the input buffer and return the next input character:
6156 * 1) If a string was pushed back on the input, pop it;
6157 * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading
6158 * from a string so we can't refill the buffer, return EOF.
6159 * 3) If the is more stuff in this buffer, use it else call read to fill it.
6160 * 4) Process input up to the next newline, deleting nul characters.
6170 while (parsefile->strpush) {
6172 if (parsenleft == -1 && parsefile->strpush->ap &&
6173 parsenextc[-1] != ' ' && parsenextc[-1] != '\t') {
6178 if (--parsenleft >= 0)
6179 return (*parsenextc++);
6181 if (parsenleft == EOF_NLEFT || parsefile->buf == NULL)
6186 if (parselleft <= 0) {
6187 if ((parselleft = preadfd()) <= 0) {
6188 parselleft = parsenleft = EOF_NLEFT;
6195 /* delete nul characters */
6196 for (more = 1; more;) {
6204 parsenleft = q - parsenextc;
6205 more = 0; /* Stop processing here */
6211 if (--parselleft <= 0 && more) {
6212 parsenleft = q - parsenextc - 1;
6223 out2str(parsenextc);
6228 return *parsenextc++;
6233 * Push a string back onto the input at this current parsefile level.
6234 * We handle aliases this way.
6237 pushstring(char *s, int len, void *ap)
6242 /*dprintf("*** calling pushstring: %s, %d\n", s, len);*/
6243 if (parsefile->strpush) {
6244 sp = ckmalloc(sizeof (struct strpush));
6245 sp->prev = parsefile->strpush;
6246 parsefile->strpush = sp;
6248 sp = parsefile->strpush = &(parsefile->basestrpush);
6249 sp->prevstring = parsenextc;
6250 sp->prevnleft = parsenleft;
6252 sp->ap = (struct alias *)ap;
6254 ((struct alias *)ap)->flag |= ALIASINUSE;
6265 * Like setinputfile, but takes input from a string.
6269 setinputstring(char *string)
6273 parsenextc = string;
6274 parsenleft = strlen(string);
6275 parsefile->buf = NULL;
6283 * To handle the "." command, a stack of input files is used. Pushfile
6284 * adds a new entry to the stack and popfile restores the previous level.
6289 struct parsefile *pf;
6291 parsefile->nleft = parsenleft;
6292 parsefile->lleft = parselleft;
6293 parsefile->nextc = parsenextc;
6294 parsefile->linno = plinno;
6295 pf = (struct parsefile *)ckmalloc(sizeof (struct parsefile));
6296 pf->prev = parsefile;
6299 pf->basestrpush.prev = NULL;
6304 static void restartjob (struct job *);
6306 static void freejob (struct job *);
6307 static struct job *getjob (const char *);
6308 static int dowait (int, struct job *);
6309 static void waitonint(int);
6313 * We keep track of whether or not fd0 has been redirected. This is for
6314 * background commands, where we want to redirect fd0 to /dev/null only
6315 * if it hasn't already been redirected.
6317 static int fd0_redirected = 0;
6319 /* Return true if fd 0 has already been redirected at least once. */
6321 fd0_redirected_p (void)
6323 return fd0_redirected != 0;
6326 static void dupredirect (const union node *, int, int fd1dup);
6330 * Turn job control on and off.
6332 * Note: This code assumes that the third arg to ioctl is a character
6333 * pointer, which is true on Berkeley systems but not System V. Since
6334 * System V doesn't have job control yet, this isn't a problem now.
6339 static void setjobctl(int enable)
6341 #ifdef OLD_TTY_DRIVER
6345 if (enable == jobctl || rootshell == 0)
6348 do { /* while we are in the background */
6349 #ifdef OLD_TTY_DRIVER
6350 if (ioctl(2, TIOCGPGRP, (char *)&initialpgrp) < 0) {
6352 initialpgrp = tcgetpgrp(2);
6353 if (initialpgrp < 0) {
6355 out2str("sh: can't access tty; job control turned off\n");
6359 if (initialpgrp == -1)
6360 initialpgrp = getpgrp();
6361 else if (initialpgrp != getpgrp()) {
6362 killpg(initialpgrp, SIGTTIN);
6366 #ifdef OLD_TTY_DRIVER
6367 if (ioctl(2, TIOCGETD, (char *)&ldisc) < 0 || ldisc != NTTYDISC) {
6368 out2str("sh: need new tty driver to run job control; job control turned off\n");
6376 setpgid(0, rootpid);
6377 #ifdef OLD_TTY_DRIVER
6378 ioctl(2, TIOCSPGRP, (char *)&rootpid);
6380 tcsetpgrp(2, rootpid);
6382 } else { /* turning job control off */
6383 setpgid(0, initialpgrp);
6384 #ifdef OLD_TTY_DRIVER
6385 ioctl(2, TIOCSPGRP, (char *)&initialpgrp);
6387 tcsetpgrp(2, initialpgrp);
6413 "Usage: kill [-s sigspec | -signum | -sigspec] [pid | job]... or\n"
6414 "kill -l [exitstatus]"
6418 if (*argv[1] == '-') {
6419 signo = decode_signal(argv[1] + 1, 1);
6423 while ((c = nextopt("ls:")) != '\0')
6429 signo = decode_signal(optionarg, 1);
6432 "invalid signal number or name: %s",
6440 "nextopt returned character code 0%o", c);
6447 if (!list && signo < 0)
6450 if ((signo < 0 || !*argptr) ^ list) {
6459 for (i = 1; i < NSIG; i++) {
6460 name = u_signal_names(0, &i, 1);
6462 printf(snlfmt, name);
6466 name = u_signal_names(*argptr, &signo, -1);
6468 printf(snlfmt, name);
6470 error("invalid signal number or exit status: %s",
6476 if (**argptr == '%') {
6477 jp = getjob(*argptr);
6478 if (jp->jobctl == 0)
6479 error("job %s not created under job control",
6481 pid = -jp->ps[0].pid;
6483 pid = atoi(*argptr);
6484 if (kill(pid, signo) != 0)
6485 error("%s: %m", *argptr);
6486 } while (*++argptr);
6500 jp = getjob(argv[1]);
6501 if (jp->jobctl == 0)
6502 error("job not created under job control");
6503 pgrp = jp->ps[0].pid;
6504 #ifdef OLD_TTY_DRIVER
6505 ioctl(2, TIOCSPGRP, (char *)&pgrp);
6511 status = waitforjob(jp);
6525 jp = getjob(*++argv);
6526 if (jp->jobctl == 0)
6527 error("job not created under job control");
6529 } while (--argc > 1);
6538 struct procstat *ps;
6541 if (jp->state == JOBDONE)
6544 killpg(jp->ps[0].pid, SIGCONT);
6545 for (ps = jp->ps, i = jp->nprocs ; --i >= 0 ; ps++) {
6546 if (WIFSTOPPED(ps->status)) {
6555 static void showjobs(int change);
6569 * Print a list of jobs. If "change" is nonzero, only print jobs whose
6570 * statuses have changed since the last call to showjobs.
6572 * If the shell is interrupted in the process of creating a job, the
6573 * result may be a job structure containing zero processes. Such structures
6574 * will be freed here.
6585 struct procstat *ps;
6589 TRACE(("showjobs(%d) called\n", change));
6590 while (dowait(0, (struct job *)NULL) > 0);
6591 for (jobno = 1, jp = jobtab ; jobno <= njobs ; jobno++, jp++) {
6594 if (jp->nprocs == 0) {
6598 if (change && ! jp->changed)
6600 procno = jp->nprocs;
6601 for (ps = jp->ps ; ; ps++) { /* for each process */
6603 snprintf(s, 64, "[%d] %ld ", jobno,
6606 snprintf(s, 64, " %ld ",
6611 if (ps->status == -1) {
6612 /* don't print anything */
6613 } else if (WIFEXITED(ps->status)) {
6614 snprintf(s, 64, "Exit %d",
6615 WEXITSTATUS(ps->status));
6618 if (WIFSTOPPED(ps->status))
6619 i = WSTOPSIG(ps->status);
6620 else /* WIFSIGNALED(ps->status) */
6622 i = WTERMSIG(ps->status);
6623 if ((i & 0x7F) < NSIG && sys_siglist[i & 0x7F])
6624 strcpy(s, sys_siglist[i & 0x7F]);
6626 snprintf(s, 64, "Signal %d", i & 0x7F);
6627 if (WCOREDUMP(ps->status))
6628 strcat(s, " (core dumped)");
6633 "%*c%s\n", 30 - col >= 0 ? 30 - col : 0, ' ',
6640 if (jp->state == JOBDONE) {
6648 * Mark a job structure as unused.
6652 freejob(struct job *jp)
6654 const struct procstat *ps;
6658 for (i = jp->nprocs, ps = jp->ps ; --i >= 0 ; ps++) {
6659 if (ps->cmd != nullstr)
6662 if (jp->ps != &jp->ps0)
6666 if (curjob == jp - jobtab + 1)
6685 job = getjob(*++argv);
6689 for (;;) { /* loop until process terminated or stopped */
6692 status = job->ps[job->nprocs - 1].status;
6698 if (WIFEXITED(status))
6699 retval = WEXITSTATUS(status);
6701 else if (WIFSTOPPED(status))
6702 retval = WSTOPSIG(status) + 128;
6705 /* XXX: limits number of signals */
6706 retval = WTERMSIG(status) + 128;
6711 for (jp = jobtab ; ; jp++) {
6712 if (jp >= jobtab + njobs) { /* no running procs */
6715 if (jp->used && jp->state == 0)
6719 if (dowait(2, 0) < 0 && errno == EINTR) {
6728 * Convert a job name to a job structure.
6732 getjob(const char *name)
6742 if ((jobno = curjob) == 0 || jobtab[jobno - 1].used == 0)
6743 error("No current job");
6744 return &jobtab[jobno - 1];
6746 error("No current job");
6748 } else if (name[0] == '%') {
6749 if (is_digit(name[1])) {
6750 jobno = number(name + 1);
6751 if (jobno > 0 && jobno <= njobs
6752 && jobtab[jobno - 1].used != 0)
6753 return &jobtab[jobno - 1];
6755 } else if (name[1] == '%' && name[2] == '\0') {
6759 struct job *found = NULL;
6760 for (jp = jobtab, i = njobs ; --i >= 0 ; jp++) {
6761 if (jp->used && jp->nprocs > 0
6762 && prefix(name + 1, jp->ps[0].cmd)) {
6764 error("%s: ambiguous", name);
6771 } else if (is_number(name, &pid)) {
6772 for (jp = jobtab, i = njobs ; --i >= 0 ; jp++) {
6773 if (jp->used && jp->nprocs > 0
6774 && jp->ps[jp->nprocs - 1].pid == pid)
6778 error("No such job: %s", name);
6785 * Return a new job structure,
6789 makejob(const union node *node, int nprocs)
6794 for (i = njobs, jp = jobtab ; ; jp++) {
6798 jobtab = ckmalloc(4 * sizeof jobtab[0]);
6800 jp = ckmalloc((njobs + 4) * sizeof jobtab[0]);
6801 memcpy(jp, jobtab, njobs * sizeof jp[0]);
6802 /* Relocate `ps' pointers */
6803 for (i = 0; i < njobs; i++)
6804 if (jp[i].ps == &jobtab[i].ps0)
6805 jp[i].ps = &jp[i].ps0;
6809 jp = jobtab + njobs;
6810 for (i = 4 ; --i >= 0 ; jobtab[njobs++].used = 0);
6823 jp->jobctl = jobctl;
6826 jp->ps = ckmalloc(nprocs * sizeof (struct procstat));
6831 TRACE(("makejob(0x%lx, %d) returns %%%d\n", (long)node, nprocs,
6838 * Fork of a subshell. If we are doing job control, give the subshell its
6839 * own process group. Jp is a job structure that the job is to be added to.
6840 * N is the command that will be evaluated by the child. Both jp and n may
6841 * be NULL. The mode parameter can be one of the following:
6842 * FORK_FG - Fork off a foreground process.
6843 * FORK_BG - Fork off a background process.
6844 * FORK_NOJOB - Like FORK_FG, but don't give the process its own
6845 * process group even if job control is on.
6847 * When job control is turned off, background processes have their standard
6848 * input redirected to /dev/null (except for the second and later processes
6855 forkshell(struct job *jp, const union node *n, int mode)
6861 const char *devnull = _PATH_DEVNULL;
6862 const char *nullerr = "Can't open %s";
6864 TRACE(("forkshell(%%%d, 0x%lx, %d) called\n", jp - jobtab, (long)n,
6869 TRACE(("Fork failed, errno=%d\n", errno));
6871 error("Cannot fork");
6878 TRACE(("Child shell %d\n", getpid()));
6879 wasroot = rootshell;
6885 jobctl = 0; /* do job control only in root shell */
6886 if (wasroot && mode != FORK_NOJOB && mflag) {
6887 if (jp == NULL || jp->nprocs == 0)
6890 pgrp = jp->ps[0].pid;
6892 if (mode == FORK_FG) {
6893 /*** this causes superfluous TIOCSPGRPS ***/
6894 #ifdef OLD_TTY_DRIVER
6895 if (ioctl(2, TIOCSPGRP, (char *)&pgrp) < 0)
6896 error("TIOCSPGRP failed, errno=%d", errno);
6898 if (tcsetpgrp(2, pgrp) < 0)
6899 error("tcsetpgrp failed, errno=%d", errno);
6904 } else if (mode == FORK_BG) {
6907 if ((jp == NULL || jp->nprocs == 0) &&
6908 ! fd0_redirected_p ()) {
6910 if (open(devnull, O_RDONLY) != 0)
6911 error(nullerr, devnull);
6915 if (mode == FORK_BG) {
6918 if ((jp == NULL || jp->nprocs == 0) &&
6919 ! fd0_redirected_p ()) {
6921 if (open(devnull, O_RDONLY) != 0)
6922 error(nullerr, devnull);
6926 for (i = njobs, p = jobtab ; --i >= 0 ; p++)
6929 if (wasroot && iflag) {
6937 if (rootshell && mode != FORK_NOJOB && mflag) {
6938 if (jp == NULL || jp->nprocs == 0)
6941 pgrp = jp->ps[0].pid;
6945 if (mode == FORK_BG)
6946 backgndpid = pid; /* set $! */
6948 struct procstat *ps = &jp->ps[jp->nprocs++];
6952 if (iflag && rootshell && n)
6953 ps->cmd = commandtext(n);
6956 TRACE(("In parent shell: child = %d\n", pid));
6963 * Wait for job to finish.
6965 * Under job control we have the problem that while a child process is
6966 * running interrupts generated by the user are sent to the child but not
6967 * to the shell. This means that an infinite loop started by an inter-
6968 * active user may be hard to kill. With job control turned off, an
6969 * interactive user may place an interactive program inside a loop. If
6970 * the interactive program catches interrupts, the user doesn't want
6971 * these interrupts to also abort the loop. The approach we take here
6972 * is to have the shell ignore interrupt signals while waiting for a
6973 * forground process to terminate, and then send itself an interrupt
6974 * signal if the child process was terminated by an interrupt signal.
6975 * Unfortunately, some programs want to do a bit of cleanup and then
6976 * exit on interrupt; unless these processes terminate themselves by
6977 * sending a signal to themselves (instead of calling exit) they will
6978 * confuse this approach.
6982 waitforjob(struct job *jp)
6985 int mypgrp = getpgrp();
6989 struct sigaction act, oact;
6998 sigaction(SIGINT, 0, &act);
6999 act.sa_handler = waitonint;
7000 sigaction(SIGINT, &act, &oact);
7002 TRACE(("waitforjob(%%%d) called\n", jp - jobtab + 1));
7003 while (jp->state == 0) {
7011 sigaction(SIGINT, &oact, 0);
7012 if (intreceived && trap[SIGINT]) kill(getpid(), SIGINT);
7016 #ifdef OLD_TTY_DRIVER
7017 if (ioctl(2, TIOCSPGRP, (char *)&mypgrp) < 0)
7018 error("TIOCSPGRP failed, errno=%d\n", errno);
7020 if (tcsetpgrp(2, mypgrp) < 0)
7021 error("tcsetpgrp failed, errno=%d\n", errno);
7024 if (jp->state == JOBSTOPPED)
7025 curjob = jp - jobtab + 1;
7027 status = jp->ps[jp->nprocs - 1].status;
7028 /* convert to 8 bits */
7029 if (WIFEXITED(status))
7030 st = WEXITSTATUS(status);
7032 else if (WIFSTOPPED(status))
7033 st = WSTOPSIG(status) + 128;
7036 st = WTERMSIG(status) + 128;
7040 * This is truly gross.
7041 * If we're doing job control, then we did a TIOCSPGRP which
7042 * caused us (the shell) to no longer be in the controlling
7043 * session -- so we wouldn't have seen any ^C/SIGINT. So, we
7044 * intuit from the subprocess exit status whether a SIGINT
7045 * occured, and if so interrupt ourselves. Yuck. - mycroft
7047 if (WIFSIGNALED(status) && WTERMSIG(status) == SIGINT)
7050 if (jp->state == JOBDONE)
7061 * Wait for a process to terminate.
7065 * Do a wait system call. If job control is compiled in, we accept
7066 * stopped processes. If block is zero, we return a value of zero
7067 * rather than blocking.
7069 * System V doesn't have a non-blocking wait system call. It does
7070 * have a SIGCLD signal that is sent to a process when one of it's
7071 * children dies. The obvious way to use SIGCLD would be to install
7072 * a handler for SIGCLD which simply bumped a counter when a SIGCLD
7073 * was received, and have waitproc bump another counter when it got
7074 * the status of a process. Waitproc would then know that a wait
7075 * system call would not block if the two counters were different.
7076 * This approach doesn't work because if a process has children that
7077 * have not been waited for, System V will send it a SIGCLD when it
7078 * installs a signal handler for SIGCLD. What this means is that when
7079 * a child exits, the shell will be sent SIGCLD signals continuously
7080 * until is runs out of stack space, unless it does a wait call before
7081 * restoring the signal handler. The code below takes advantage of
7082 * this (mis)feature by installing a signal handler for SIGCLD and
7083 * then checking to see whether it was called. If there are any
7084 * children to be waited for, it will be.
7089 waitproc(int block, int *status)
7100 return wait3(status, flags, (struct rusage *)NULL);
7104 dowait(int block, struct job *job)
7108 struct procstat *sp;
7110 struct job *thisjob;
7116 TRACE(("dowait(%d) called\n", block));
7118 pid = waitproc(block, &status);
7119 TRACE(("wait returns %d, status=%d\n", pid, status));
7120 } while (!(block & 2) && pid == -1 && errno == EINTR);
7125 for (jp = jobtab ; jp < jobtab + njobs ; jp++) {
7129 for (sp = jp->ps ; sp < jp->ps + jp->nprocs ; sp++) {
7132 if (sp->pid == pid) {
7133 TRACE(("Changing status of proc %d from 0x%x to 0x%x\n", pid, sp->status, status));
7134 sp->status = status;
7137 if (sp->status == -1)
7139 else if (WIFSTOPPED(sp->status))
7142 if (stopped) { /* stopped or done */
7143 int state = done? JOBDONE : JOBSTOPPED;
7144 if (jp->state != state) {
7145 TRACE(("Job %d: changing state from %d to %d\n", jp - jobtab + 1, jp->state, state));
7148 if (done && curjob == jp - jobtab + 1)
7149 curjob = 0; /* no current job */
7156 if (! rootshell || ! iflag || (job && thisjob == job)) {
7157 core = WCOREDUMP(status);
7159 if (WIFSTOPPED(status)) sig = WSTOPSIG(status);
7162 if (WIFEXITED(status)) sig = 0;
7163 else sig = WTERMSIG(status);
7165 if (sig != 0 && sig != SIGINT && sig != SIGPIPE) {
7167 out2fmt("%d: ", pid);
7169 if (sig == SIGTSTP && rootshell && iflag)
7171 (long)(job - jobtab + 1));
7173 if (sig < NSIG && sys_siglist[sig])
7174 out2str(sys_siglist[sig]);
7176 out2fmt("Signal %d", sig);
7178 out2str(" - core dumped");
7181 TRACE(("Not printing status: status=%d, sig=%d\n",
7185 TRACE(("Not printing status, rootshell=%d, job=0x%x\n", rootshell, job));
7187 thisjob->changed = 1;
7196 * return 1 if there are stopped jobs, otherwise 0
7206 for (jobno = 1, jp = jobtab; jobno <= njobs; jobno++, jp++) {
7209 if (jp->state == JOBSTOPPED) {
7210 out2str("You have stopped jobs.\n");
7220 * Return a string identifying a command (to be printed by the
7224 static char *cmdnextc;
7225 static int cmdnleft;
7226 #define MAXCMDTEXT 200
7229 cmdputs(const char *s)
7240 while ((c = *p++) != '\0') {
7243 else if (c == CTLVAR) {
7248 } else if (c == '=' && subtype != 0) {
7249 *q++ = "}-+?="[(subtype & VSTYPE) - VSNORMAL];
7251 } else if (c == CTLENDVAR) {
7253 } else if (c == CTLBACKQ || c == CTLBACKQ+CTLQUOTE)
7254 cmdnleft++; /* ignore it */
7257 if (--cmdnleft <= 0) {
7267 #define CMDTXT_TABLE
7270 * To collect a lot of redundant code in cmdtxt() case statements, we
7271 * implement a mini language here. Each type of node struct has an
7272 * associated instruction sequence that operates on its members via
7273 * their offsets. The instruction are pack in unsigned chars with
7274 * format IIDDDDDE where the bits are
7275 * I : part of the instruction opcode, which are
7276 * 00 : member is a pointer to another node -- process it recursively
7277 * 40 : member is a pointer to a char string -- output it
7278 * 80 : output the string whose index is stored in the data field
7279 * CC : flag signaling that this case needs external processing
7280 * D : data - either the (shifted) index of a fixed string to output or
7281 * the actual offset of the member to operate on in the struct
7282 * (since we assume bit 0 is set, the offset is not shifted)
7283 * E : flag signaling end of instruction sequence
7285 * WARNING: In order to handle larger offsets for 64bit archs, this code
7286 * assumes that no offset can be an odd number and stores the
7287 * end-of-instructions flag in bit 0.
7290 #define CMDTXT_NOMORE 0x01 /* NOTE: no offset should be odd */
7291 #define CMDTXT_CHARPTR 0x40
7292 #define CMDTXT_STRING 0x80
7293 #define CMDTXT_SPECIAL 0xC0
7294 #define CMDTXT_OFFSETMASK 0x3E
7296 static const char * const cmdtxt_strings[] = {
7297 /* 0 1 2 3 4 5 6 7 */
7298 "; ", "(", ")", " && ", " || ", "if ", "; then ", "...",
7299 /* 8 9 10 11 12 13 */
7300 "while ", "; do ", "; done", "until ", "for ", " in ...",
7302 "case ", "???", "() ...", "<<..."
7305 static const char * const redir_strings[] = {
7306 ">", "<", "<>", ">>", ">|", ">&", "<&"
7309 static const unsigned char cmdtxt_ops[] = {
7310 #define CMDTXT_NSEMI 0
7311 offsetof(union node, nbinary.ch1),
7313 offsetof(union node, nbinary.ch2)|CMDTXT_NOMORE,
7314 #define CMDTXT_NCMD (CMDTXT_NSEMI + 3)
7315 #define CMDTXT_NPIPE (CMDTXT_NCMD)
7316 #define CMDTXT_NCASE (CMDTXT_NCMD)
7317 #define CMDTXT_NTO (CMDTXT_NCMD)
7318 #define CMDTXT_NFROM (CMDTXT_NCMD)
7319 #define CMDTXT_NFROMTO (CMDTXT_NCMD)
7320 #define CMDTXT_NAPPEND (CMDTXT_NCMD)
7321 #define CMDTXT_NTOOV (CMDTXT_NCMD)
7322 #define CMDTXT_NTOFD (CMDTXT_NCMD)
7323 #define CMDTXT_NFROMFD (CMDTXT_NCMD)
7325 #define CMDTXT_NREDIR (CMDTXT_NPIPE + 1)
7326 #define CMDTXT_NBACKGND (CMDTXT_NREDIR)
7327 offsetof(union node, nredir.n)|CMDTXT_NOMORE,
7328 #define CMDTXT_NSUBSHELL (CMDTXT_NBACKGND + 1)
7329 (1*2)|CMDTXT_STRING,
7330 offsetof(union node, nredir.n),
7331 (2*2)|CMDTXT_STRING|CMDTXT_NOMORE,
7332 #define CMDTXT_NAND (CMDTXT_NSUBSHELL + 3)
7333 offsetof(union node, nbinary.ch1),
7334 (3*2)|CMDTXT_STRING,
7335 offsetof(union node, nbinary.ch2)|CMDTXT_NOMORE,
7336 #define CMDTXT_NOR (CMDTXT_NAND + 3)
7337 offsetof(union node, nbinary.ch1),
7338 (4*2)|CMDTXT_STRING,
7339 offsetof(union node, nbinary.ch2)|CMDTXT_NOMORE,
7340 #define CMDTXT_NIF (CMDTXT_NOR + 3)
7341 (5*2)|CMDTXT_STRING,
7342 offsetof(union node, nif.test),
7343 (6*2)|CMDTXT_STRING,
7344 offsetof(union node, nif.ifpart),
7345 (7*2)|CMDTXT_STRING|CMDTXT_NOMORE,
7346 #define CMDTXT_NWHILE (CMDTXT_NIF + 5)
7347 (8*2)|CMDTXT_STRING,
7348 offsetof(union node, nbinary.ch1),
7349 (9*2)|CMDTXT_STRING,
7350 offsetof(union node, nbinary.ch2),
7351 (10*2)|CMDTXT_STRING|CMDTXT_NOMORE,
7352 #define CMDTXT_NUNTIL (CMDTXT_NWHILE + 5)
7353 (11*2)|CMDTXT_STRING,
7354 offsetof(union node, nbinary.ch1),
7355 (9*2)|CMDTXT_STRING,
7356 offsetof(union node, nbinary.ch2),
7357 (10*2)|CMDTXT_STRING|CMDTXT_NOMORE,
7358 #define CMDTXT_NFOR (CMDTXT_NUNTIL + 5)
7359 (12*2)|CMDTXT_STRING,
7360 offsetof(union node, nfor.var)|CMDTXT_CHARPTR,
7361 (13*2)|CMDTXT_STRING|CMDTXT_NOMORE,
7362 #define CMDTXT_NCLIST (CMDTXT_NFOR + 3) /* TODO: IS THIS CORRECT??? */
7363 #define CMDTXT_NNOT (CMDTXT_NCLIST) /* TODO: IS THIS CORRECT??? */
7364 (15*2)|CMDTXT_STRING|CMDTXT_NOMORE,
7365 #define CMDTXT_NDEFUN (CMDTXT_NCLIST + 1)
7366 offsetof(union node, narg.text)|CMDTXT_CHARPTR,
7367 (16*2)|CMDTXT_STRING|CMDTXT_NOMORE,
7368 #define CMDTXT_NARG (CMDTXT_NDEFUN + 2)
7369 offsetof(union node, narg.text)|CMDTXT_CHARPTR|CMDTXT_NOMORE,
7370 #define CMDTXT_NHERE (CMDTXT_NARG + 1)
7371 #define CMDTXT_NXHERE (CMDTXT_NHERE)
7372 (17*2)|CMDTXT_STRING|CMDTXT_NOMORE,
7375 #if CMDTXT_NXHERE != 36
7376 #error CMDTXT_NXHERE
7379 static const unsigned char cmdtxt_ops_index[26] = {
7409 cmdtxt(const union node *n)
7416 p = cmdtxt_ops + (int) cmdtxt_ops_index[n->type];
7417 if ((*p & CMDTXT_SPECIAL) != CMDTXT_SPECIAL) { /* normal case */
7419 if (*p & CMDTXT_STRING) { /* output fixed string */
7420 cmdputs(cmdtxt_strings[((int)(*p & CMDTXT_OFFSETMASK) >> 1)]);
7422 const char *pf = ((const char *) n)
7423 + ((int)(*p & CMDTXT_OFFSETMASK));
7424 if (*p & CMDTXT_CHARPTR) { /* output dynamic string */
7425 cmdputs(*((const char **) pf));
7426 } else { /* output field */
7427 cmdtxt(*((const union node **) pf));
7430 } while (!(*p++ & CMDTXT_NOMORE));
7431 } else if (n->type == NCMD) {
7433 for (np = n->ncmd.args ; np ; np = np->narg.next) {
7438 for (np = n->ncmd.redirect ; np ; np = np->nfile.next) {
7442 } else if (n->type == NPIPE) {
7443 struct nodelist *lp;
7444 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
7449 } else if (n->type == NCASE) {
7450 cmdputs(cmdtxt_strings[14]);
7451 cmdputs(n->ncase.expr->narg.text);
7452 cmdputs(cmdtxt_strings[13]);
7454 #if (NTO != 16) || (NFROM != 17) || (NFROMTO != 18) || (NAPPEND != 19) || (NTOOV != 20) || (NTOFD != 21) || (NFROMFD != 22)
7455 #error Assumption violated regarding range and ordering of NTO ... NFROMFD!
7460 assert((n->type >= NTO) && (n->type <= NFROMFD));
7463 p = redir_strings[n->type - NTO];
7464 if (n->nfile.fd != ('>' == *p)) {
7465 s[0] = n->nfile.fd + '0';
7470 if (n->type >= NTOFD) {
7471 s[0] = n->ndup.dupfd + '0';
7475 cmdtxt(n->nfile.fname);
7479 #else /* CMDTXT_TABLE */
7481 cmdtxt(const union node *n)
7484 struct nodelist *lp;
7493 cmdtxt(n->nbinary.ch1);
7495 cmdtxt(n->nbinary.ch2);
7498 cmdtxt(n->nbinary.ch1);
7500 cmdtxt(n->nbinary.ch2);
7503 cmdtxt(n->nbinary.ch1);
7505 cmdtxt(n->nbinary.ch2);
7508 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
7516 cmdtxt(n->nredir.n);
7521 cmdtxt(n->nredir.n);
7525 cmdtxt(n->nif.test);
7527 cmdtxt(n->nif.ifpart);
7536 cmdtxt(n->nbinary.ch1);
7538 cmdtxt(n->nbinary.ch2);
7543 cmdputs(n->nfor.var);
7548 cmdputs(n->ncase.expr->narg.text);
7552 cmdputs(n->narg.text);
7556 for (np = n->ncmd.args ; np ; np = np->narg.next) {
7561 for (np = n->ncmd.redirect ; np ; np = np->nfile.next) {
7567 cmdputs(n->narg.text);
7570 p = ">"; i = 1; goto redir;
7572 p = ">>"; i = 1; goto redir;
7574 p = ">&"; i = 1; goto redir;
7576 p = ">|"; i = 1; goto redir;
7578 p = "<"; i = 0; goto redir;
7580 p = "<&"; i = 0; goto redir;
7582 p = "<>"; i = 0; goto redir;
7584 if (n->nfile.fd != i) {
7585 s[0] = n->nfile.fd + '0';
7590 if (n->type == NTOFD || n->type == NFROMFD) {
7591 s[0] = n->ndup.dupfd + '0';
7595 cmdtxt(n->nfile.fname);
7607 #endif /* CMDTXT_TABLE */
7610 commandtext(const union node *n)
7614 cmdnextc = name = ckmalloc(MAXCMDTEXT);
7615 cmdnleft = MAXCMDTEXT - 4;
7622 static void waitonint(int sig) {
7627 * Routines to check for mail. (Perhaps make part of main.c?)
7631 #define MAXMBOXES 10
7634 static int nmboxes; /* number of mailboxes */
7635 static time_t mailtime[MAXMBOXES]; /* times of mailboxes */
7640 * Print appropriate message(s) if mail has arrived. If the argument is
7641 * nozero, then the value of MAIL has changed, so we just update the
7652 struct stackmark smark;
7659 setstackmark(&smark);
7660 mpath = mpathset()? mpathval() : mailval();
7661 for (i = 0 ; i < nmboxes ; i++) {
7662 p = padvance(&mpath, nullstr);
7667 for (q = p ; *q ; q++);
7672 q[-1] = '\0'; /* delete trailing '/' */
7673 if (stat(p, &statb) < 0)
7675 if (statb.st_size > mailtime[i] && ! silent) {
7677 pathopt? pathopt : "you have mail");
7679 mailtime[i] = statb.st_size;
7682 popstackmark(&smark);
7688 static short profile_buf[16384];
7692 static void read_profile (const char *);
7693 static void cmdloop (int);
7694 static void options (int);
7695 static void setoption (int, int);
7696 static void procargs (int, char **);
7700 * Main routine. We initialize things, parse the arguments, execute
7701 * profiles if we're a login shell, and then call cmdloop to execute
7702 * commands. The setjmp call sets up the location to jump to when an
7703 * exception occurs. When an exception occurs the variable "state"
7704 * is used to figure out how far we had gotten.
7708 ash_main(argc, argv)
7712 struct jmploc jmploc;
7713 struct stackmark smark;
7717 BLTINCMD = find_builtin("builtin");
7718 EXECCMD = find_builtin("exec");
7719 EVALCMD = find_builtin("eval");
7721 #ifndef CONFIG_FEATURE_SH_FANCY_PROMPT
7727 monitor(4, etext, profile_buf, sizeof profile_buf, 50);
7729 #if defined(linux) || defined(__GNU__)
7730 signal(SIGCHLD, SIG_DFL);
7733 if (setjmp(jmploc.loc)) {
7736 * When a shell procedure is executed, we raise the
7737 * exception EXSHELLPROC to clean up before executing
7738 * the shell procedure.
7740 if (exception == EXSHELLPROC) {
7746 if (exception == EXEXEC) {
7747 exitstatus = exerrno;
7748 } else if (exception == EXERROR) {
7751 if (state == 0 || iflag == 0 || ! rootshell)
7752 exitshell(exitstatus);
7755 if (exception == EXINT) {
7758 popstackmark(&smark);
7759 FORCEINTON; /* enable interrupts */
7762 else if (state == 2)
7764 else if (state == 3)
7772 trputs("Shell args: "); trargs(argv);
7777 setstackmark(&smark);
7778 procargs(argc, argv);
7779 if (argv[0] && argv[0][0] == '-') {
7781 read_profile("/etc/profile");
7784 read_profile(".profile");
7789 if (getuid() == geteuid() && getgid() == getegid()) {
7791 if ((shinit = lookupvar("ENV")) != NULL && *shinit != '\0') {
7793 read_profile(shinit);
7800 if (sflag == 0 || minusc) {
7801 static const char sigs[] = {
7802 SIGINT, SIGQUIT, SIGHUP,
7808 #define SIGSSIZE ((sizeof(sigs)/sizeof(sigs[0])) - 1) /* trailing nul */
7811 for (i = 0; i < SIGSSIZE; i++)
7816 evalstring(minusc, 0);
7818 if (sflag || minusc == NULL) {
7819 state4: /* XXX ??? - why isn't this before the "if" statement */
7825 exitshell(exitstatus);
7831 * Read and execute commands. "Top" is nonzero for the top level command
7832 * loop; it turns on prompting if the shell is interactive.
7839 struct stackmark smark;
7843 TRACE(("cmdloop(%d) called\n", top));
7844 setstackmark(&smark);
7855 n = parsecmd(inter);
7856 /* showtree(n); DEBUG */
7858 if (!top || numeof >= 50)
7860 if (!stoppedjobs()) {
7863 out2str("\nUse \"exit\" to leave shell.\n");
7866 } else if (n != NULL && nflag == 0) {
7867 job_warning = (job_warning == 2) ? 1 : 0;
7871 popstackmark(&smark);
7872 setstackmark(&smark);
7873 if (evalskip == SKIPFILE) {
7878 popstackmark(&smark);
7884 * Read /etc/profile or .profile. Return on error.
7896 if ((fd = open(name, O_RDONLY)) >= 0)
7901 /* -q turns off -x and -v just when executing init files */
7902 /* Note: Might do a little redundant work, but reduces code size. */
7917 * Read a file containing shell functions.
7921 readcmdfile(const char *name)
7926 if ((fd = open(name, O_RDONLY)) >= 0)
7929 error("Can't open %s", name);
7938 * Take commands from a file. To be compatable we should do a path
7939 * search for the file, which is necessary to find sub-commands.
7943 static inline char *
7944 find_dot_file(char *mybasename)
7947 const char *path = pathval();
7950 /* don't try this for absolute or relative paths */
7951 if (strchr(mybasename, '/'))
7954 while ((fullname = padvance(&path, mybasename)) != NULL) {
7955 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
7957 * Don't bother freeing here, since it will
7958 * be freed by the caller.
7962 stunalloc(fullname);
7965 /* not found in the PATH */
7966 error("%s: not found", mybasename);
7978 for (sp = cmdenviron; sp ; sp = sp->next)
7979 setvareq(savestr(sp->text), VSTRFIXED|VTEXTFIXED);
7981 if (argc >= 2) { /* That's what SVR2 does */
7983 struct stackmark smark;
7985 setstackmark(&smark);
7986 fullname = find_dot_file(argv[1]);
7987 setinputfile(fullname, 1);
7988 commandname = fullname;
7991 popstackmark(&smark);
8005 exitstatus = number(argv[1]);
8007 exitstatus = oexitstatus;
8008 exitshell(exitstatus);
8017 nbytes = ALIGN(nbytes);
8018 if (nbytes > stacknleft) {
8020 struct stack_block *sp;
8023 if (blocksize < MINSIZE)
8024 blocksize = MINSIZE;
8026 sp = ckmalloc(sizeof(struct stack_block) - MINSIZE + blocksize);
8028 stacknxt = sp->space;
8029 stacknleft = blocksize;
8035 stacknleft -= nbytes;
8041 stunalloc(pointer p)
8044 if (p == NULL) { /*DEBUG */
8045 write(2, "stunalloc\n", 10);
8049 if (!(stacknxt >= (char *)p && (char *)p >= stackp->space)) {
8052 stacknleft += stacknxt - (char *)p;
8058 setstackmark(struct stackmark *mark)
8060 mark->stackp = stackp;
8061 mark->stacknxt = stacknxt;
8062 mark->stacknleft = stacknleft;
8063 mark->marknext = markp;
8069 popstackmark(struct stackmark *mark)
8071 struct stack_block *sp;
8074 markp = mark->marknext;
8075 while (stackp != mark->stackp) {
8080 stacknxt = mark->stacknxt;
8081 stacknleft = mark->stacknleft;
8087 * When the parser reads in a string, it wants to stick the string on the
8088 * stack and only adjust the stack pointer when it knows how big the
8089 * string is. Stackblock (defined in stack.h) returns a pointer to a block
8090 * of space on top of the stack and stackblocklen returns the length of
8091 * this block. Growstackblock will grow this space by at least one byte,
8092 * possibly moving it (like realloc). Grabstackblock actually allocates the
8093 * part of the block that has been used.
8097 growstackblock(void) {
8099 int newlen = ALIGN(stacknleft * 2 + 100);
8100 char *oldspace = stacknxt;
8101 int oldlen = stacknleft;
8102 struct stack_block *sp;
8103 struct stack_block *oldstackp;
8105 if (stacknxt == stackp->space && stackp != &stackbase) {
8110 sp = ckrealloc((pointer)sp, sizeof(struct stack_block) - MINSIZE + newlen);
8113 stacknxt = sp->space;
8114 stacknleft = newlen;
8116 /* Stack marks pointing to the start of the old block
8117 * must be relocated to point to the new block
8119 struct stackmark *xmark;
8121 while (xmark != NULL && xmark->stackp == oldstackp) {
8122 xmark->stackp = stackp;
8123 xmark->stacknxt = stacknxt;
8124 xmark->stacknleft = stacknleft;
8125 xmark = xmark->marknext;
8130 p = stalloc(newlen);
8131 memcpy(p, oldspace, oldlen);
8132 stacknxt = p; /* free the space */
8133 stacknleft += newlen; /* we just allocated */
8140 grabstackblock(int len)
8150 * The following routines are somewhat easier to use that the above.
8151 * The user declares a variable of type STACKSTR, which may be declared
8152 * to be a register. The macro STARTSTACKSTR initializes things. Then
8153 * the user uses the macro STPUTC to add characters to the string. In
8154 * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
8155 * grown as necessary. When the user is done, she can just leave the
8156 * string there and refer to it using stackblock(). Or she can allocate
8157 * the space for it using grabstackstr(). If it is necessary to allow
8158 * someone else to use the stack temporarily and then continue to grow
8159 * the string, the user should use grabstack to allocate the space, and
8160 * then call ungrabstr(p) to return to the previous mode of operation.
8162 * USTPUTC is like STPUTC except that it doesn't check for overflow.
8163 * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
8164 * is space for at least one character.
8169 growstackstr(void) {
8170 int len = stackblocksize();
8171 if (herefd >= 0 && len >= 1024) {
8172 xwrite(herefd, stackblock(), len);
8173 sstrnleft = len - 1;
8174 return stackblock();
8177 sstrnleft = stackblocksize() - len - 1;
8178 return stackblock() + len;
8183 * Called from CHECKSTRSPACE.
8187 makestrspace(size_t newlen) {
8188 int len = stackblocksize() - sstrnleft;
8191 sstrnleft = stackblocksize() - len;
8192 } while (sstrnleft < newlen);
8193 return stackblock() + len;
8199 ungrabstackstr(char *s, char *p)
8201 stacknleft += stacknxt - s;
8203 sstrnleft = stacknleft - (p - s);
8206 * Miscelaneous builtins.
8212 #if !defined(__GLIBC__) || __GLIBC__ == 2 && __GLIBC_MINOR__ < 1
8213 typedef long rlim_t;
8219 * The read builtin. The -e option causes backslashes to escape the
8220 * following character.
8222 * This uses unbuffered input, which may be avoidable in some cases.
8226 readcmd(int argc, char **argv)
8241 while ((i = nextopt("p:r")) != '\0') {
8247 if (prompt && isatty(0)) {
8248 out2str(prompt); /* read without cmdedit */
8251 if (*(ap = argptr) == NULL)
8253 if ((ifs = bltinlookup("IFS")) == NULL)
8260 if (read(0, &c, 1) != 1) {
8272 if (!rflag && c == '\\') {
8278 if (startword && *ifs == ' ' && strchr(ifs, c)) {
8282 if (backslash && c == '\\') {
8283 if (read(0, &c, 1) != 1) {
8288 } else if (ap[1] != NULL && strchr(ifs, c) != NULL) {
8290 setvar(*ap, stackblock(), 0);
8299 /* Remove trailing blanks */
8300 while (stackblock() <= --p && strchr(ifs, *p) != NULL)
8302 setvar(*ap, stackblock(), 0);
8303 while (*++ap != NULL)
8304 setvar(*ap, nullstr, 0);
8311 umaskcmd(argc, argv)
8315 static const char permuser[3] = "ugo";
8316 static const char permmode[3] = "rwx";
8317 static const short int permmask[] = {
8318 S_IRUSR, S_IWUSR, S_IXUSR,
8319 S_IRGRP, S_IWGRP, S_IXGRP,
8320 S_IROTH, S_IWOTH, S_IXOTH
8326 int symbolic_mode = 0;
8328 while (nextopt("S") != '\0') {
8337 if ((ap = *argptr) == NULL) {
8338 if (symbolic_mode) {
8341 for (i=0 ; i<3 ; i++) {
8345 for (j=0 ; j<3 ; j++) {
8346 if ((mask & permmask[3*i+j]) == 0) {
8355 printf("%.4o\n", mask);
8358 if (is_digit((unsigned char)*ap)) {
8361 if (*ap >= '8' || *ap < '0')
8362 error("Illegal number: %s", argv[1]);
8363 mask = (mask << 3) + (*ap - '0');
8364 } while (*++ap != '\0');
8367 mask = ~mask & 0777;
8368 if (parse_mode(ap, &mask) == FALSE) {
8369 error("Illegal mode: %s", ap);
8371 umask(~mask & 0777);
8380 * This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and
8381 * Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with
8382 * ash by J.T. Conklin.
8390 short factor; /* multiply by to get rlim_{cur,max} values */
8393 static const struct limits limits[] = {
8395 { "time(seconds)", RLIMIT_CPU, 1 },
8398 { "file(blocks)", RLIMIT_FSIZE, 512 },
8401 { "data(kbytes)", RLIMIT_DATA, 1024 },
8404 { "stack(kbytes)", RLIMIT_STACK, 1024 },
8407 { "coredump(blocks)", RLIMIT_CORE, 512 },
8410 { "memory(kbytes)", RLIMIT_RSS, 1024 },
8412 #ifdef RLIMIT_MEMLOCK
8413 { "locked memory(kbytes)", RLIMIT_MEMLOCK, 1024 },
8416 { "process(processes)", RLIMIT_NPROC, 1 },
8418 #ifdef RLIMIT_NOFILE
8419 { "nofiles(descriptors)", RLIMIT_NOFILE, 1 },
8422 { "vmemory(kbytes)", RLIMIT_VMEM, 1024 },
8425 { "swap(kbytes)", RLIMIT_SWAP, 1024 },
8431 ulimitcmd(argc, argv)
8435 static const char unlimited_string[] = "unlimited";
8438 enum { SOFT = 0x1, HARD = 0x2 }
8440 const struct limits *l;
8443 struct rlimit limit;
8447 while ((optc = nextopt("HSa"
8466 #ifdef RLIMIT_MEMLOCK
8472 #ifdef RLIMIT_NOFILE
8484 } else if (optc == 'S') {
8486 } else if (optc == 'a') {
8493 for (l = limits; l->name; l++) {
8494 if(l->name[0] == what)
8496 if(l->name[1]=='w' && what=='w')
8500 set = *argptr ? 1 : 0;
8504 if (all || argptr[1])
8505 error("too many arguments");
8506 if (strcmp(p, unlimited_string) == 0)
8507 val = RLIM_INFINITY;
8511 while ((c = *p++) >= '0' && c <= '9')
8513 val = (val * 10) + (long)(c - '0');
8514 if (val < (rlim_t) 0)
8518 error("bad number");
8524 for (l = limits; l->name; l++) {
8525 printf("%-20s ", l->name);
8526 getrlimit(l->cmd, &limit);
8529 val = limit.rlim_cur;
8530 else if (how & HARD)
8531 val = limit.rlim_max;
8533 if (val == RLIM_INFINITY)
8534 puts(unlimited_string);
8538 printf("%lld\n", (long long) val);
8551 getrlimit(l->cmd, &limit);
8553 limit.rlim_max = val;
8555 limit.rlim_cur = val;
8556 if (setrlimit(l->cmd, &limit) < 0)
8557 error("error setting limit (%m)");
8561 * prefix -- see if pfx is a prefix of string.
8565 prefix(char const *pfx, char const *string)
8568 if (*pfx++ != *string++)
8575 * Return true if s is a string of digits, and save munber in intptr
8580 is_number(const char *p, int *intptr)
8588 ret += digit_val(*p);
8590 } while (*p != '\0');
8597 * Convert a string of digits to an integer, printing an error message on
8602 number(const char *s)
8605 if (! is_number(s, &i))
8606 error("Illegal number: %s", s);
8611 * Produce a possibly single quoted string suitable as input to the shell.
8612 * The return string is allocated on the stack.
8616 single_quote(const char *s) {
8623 size_t len1, len1p, len2, len2p;
8625 len1 = strcspn(s, "'");
8626 len2 = strspn(s + len1, "'");
8628 len1p = len1 ? len1 + 2 : len1;
8629 len2p = len2 + ((len2 < 2) ? len2 : 2);
8631 CHECKSTRSPACE(len1p + len2p + 1, p);
8636 memcpy(p + 1, s, len1);
8644 memcpy(q + 1, s, len2);
8647 } else if (len2 == 1) {
8653 STADJUST(len1p + len2p, p);
8658 return grabstackstr(p);
8662 * Like strdup but works with the ash stack.
8666 sstrdup(const char *p)
8668 size_t len = strlen(p) + 1;
8669 return memcpy(stalloc(len), p, len);
8674 * Routine for dealing with parsed shell commands.
8678 static void sizenodelist (const struct nodelist *);
8679 static struct nodelist *copynodelist (const struct nodelist *);
8680 static char *nodesavestr (const char *);
8682 #define CALCSIZE_TABLE
8683 #define COPYNODE_TABLE
8684 #if defined(CALCSIZE_TABLE) || defined(COPYNODE_TABLE)
8686 * To collect a lot of redundant code in case statements for copynode()
8687 * and calcsize(), we implement a mini language here. Each type of node
8688 * struct has an associated instruction sequence that operates on its
8689 * members via their offsets. The instruction are pack in unsigned chars
8690 * with format IIDDDDDE where the bits are
8691 * I : part of the instruction opcode, which are
8692 * 00 : member is a pointer to another node
8693 * 40 : member is an integer
8694 * 80 : member is a pointer to a nodelist
8695 * CC : member is a pointer to a char string
8696 * D : data - the actual offset of the member to operate on in the struct
8697 * (since we assume bit 0 is set, it is not shifted)
8698 * E : flag signaling end of instruction sequence
8700 * WARNING: In order to handle larger offsets for 64bit archs, this code
8701 * assumes that no offset can be an odd number and stores the
8702 * end-of-instructions flag in bit 0.
8705 #define NODE_INTEGER 0x40
8706 #define NODE_NODELIST 0x80
8707 #define NODE_CHARPTR 0xC0
8708 #define NODE_NOMORE 0x01 /* Note: no offset should be odd (aligned)*/
8709 #define NODE_MBRMASK 0xC0
8710 #define NODE_OFFSETMASK 0x3E
8712 static const unsigned char copynode_ops[35] = {
8713 #define COPYNODE_OPS0 0
8714 offsetof(union node, nbinary.ch2),
8715 offsetof(union node, nbinary.ch1)|NODE_NOMORE,
8716 #define COPYNODE_OPS1 (COPYNODE_OPS0 + 2)
8717 offsetof(union node, ncmd.redirect),
8718 offsetof(union node, ncmd.args),
8719 offsetof(union node, ncmd.assign),
8720 offsetof(union node, ncmd.backgnd)|NODE_INTEGER|NODE_NOMORE,
8721 #define COPYNODE_OPS2 (COPYNODE_OPS1 + 4)
8722 offsetof(union node, npipe.cmdlist)|NODE_NODELIST,
8723 offsetof(union node, npipe.backgnd)|NODE_INTEGER|NODE_NOMORE,
8724 #define COPYNODE_OPS3 (COPYNODE_OPS2 + 2)
8725 offsetof(union node, nredir.redirect),
8726 offsetof(union node, nredir.n)|NODE_NOMORE,
8727 #define COPYNODE_OPS4 (COPYNODE_OPS3 + 2)
8728 offsetof(union node, nif.elsepart),
8729 offsetof(union node, nif.ifpart),
8730 offsetof(union node, nif.test)|NODE_NOMORE,
8731 #define COPYNODE_OPS5 (COPYNODE_OPS4 + 3)
8732 offsetof(union node, nfor.var)|NODE_CHARPTR,
8733 offsetof(union node, nfor.body),
8734 offsetof(union node, nfor.args)|NODE_NOMORE,
8735 #define COPYNODE_OPS6 (COPYNODE_OPS5 + 3)
8736 offsetof(union node, ncase.cases),
8737 offsetof(union node, ncase.expr)|NODE_NOMORE,
8738 #define COPYNODE_OPS7 (COPYNODE_OPS6 + 2)
8739 offsetof(union node, nclist.body),
8740 offsetof(union node, nclist.pattern),
8741 offsetof(union node, nclist.next)|NODE_NOMORE,
8742 #define COPYNODE_OPS8 (COPYNODE_OPS7 + 3)
8743 offsetof(union node, narg.backquote)|NODE_NODELIST,
8744 offsetof(union node, narg.text)|NODE_CHARPTR,
8745 offsetof(union node, narg.next)|NODE_NOMORE,
8746 #define COPYNODE_OPS9 (COPYNODE_OPS8 + 3)
8747 offsetof(union node, nfile.fname),
8748 offsetof(union node, nfile.fd)|NODE_INTEGER,
8749 offsetof(union node, nfile.next)|NODE_NOMORE,
8750 #define COPYNODE_OPS10 (COPYNODE_OPS9 + 3)
8751 offsetof(union node, ndup.vname),
8752 offsetof(union node, ndup.dupfd)|NODE_INTEGER,
8753 offsetof(union node, ndup.fd)|NODE_INTEGER,
8754 offsetof(union node, ndup.next)|NODE_NOMORE,
8755 #define COPYNODE_OPS11 (COPYNODE_OPS10 + 4)
8756 offsetof(union node, nhere.doc),
8757 offsetof(union node, nhere.fd)|NODE_INTEGER,
8758 offsetof(union node, nhere.next)|NODE_NOMORE,
8759 #define COPYNODE_OPS12 (COPYNODE_OPS11 + 3)
8760 offsetof(union node, nnot.com)|NODE_NOMORE,
8763 #if COPYNODE_OPS12 != 34
8764 #error COPYNODE_OPS12 is incorrect
8767 static const unsigned char copynode_ops_index[26] = {
8768 COPYNODE_OPS0, /* NSEMI */
8769 COPYNODE_OPS1, /* NCMD */
8770 COPYNODE_OPS2, /* NPIPE */
8771 COPYNODE_OPS3, /* NREDIR */
8772 COPYNODE_OPS3, /* NBACKGND */
8773 COPYNODE_OPS3, /* NSUBSHELL */
8774 COPYNODE_OPS0, /* NAND */
8775 COPYNODE_OPS0, /* NOR */
8776 COPYNODE_OPS4, /* NIF */
8777 COPYNODE_OPS0, /* NWHILE */
8778 COPYNODE_OPS0, /* NUNTIL */
8779 COPYNODE_OPS5, /* NFOR */
8780 COPYNODE_OPS6, /* NCASE */
8781 COPYNODE_OPS7, /* NCLIST */
8782 COPYNODE_OPS8, /* NDEFUN */
8783 COPYNODE_OPS8, /* NARG */
8784 COPYNODE_OPS9, /* NTO */
8785 COPYNODE_OPS9, /* NFROM */
8786 COPYNODE_OPS9, /* NFROMTO */
8787 COPYNODE_OPS9, /* NAPPEND */
8788 COPYNODE_OPS9, /* NTOOV */
8789 COPYNODE_OPS10, /* NTOFD */
8790 COPYNODE_OPS10, /* NFROMFD */
8791 COPYNODE_OPS11, /* NHERE */
8792 COPYNODE_OPS11, /* NXHERE */
8793 COPYNODE_OPS12, /* NNOT */
8796 #if NODE_CHARPTR != NODE_MBRMASK
8797 #error NODE_CHARPTR != NODE_MBRMASK!!!
8799 #endif /* defined(CALCSIZE_TABLE) || defined(COPYNODE_TABLE) */
8801 #ifdef COPYNODE_TABLE
8803 copynode(const union node *n)
8806 const unsigned char *p;
8812 new->type = n->type;
8813 funcblock = (char *) funcblock + (int) nodesize[n->type];
8814 p = copynode_ops + (int) copynode_ops_index[n->type];
8816 char *nn = ((char *) new) + ((int)(*p & NODE_OFFSETMASK));
8817 const char *no = ((const char *) n) + ((int)(*p & NODE_OFFSETMASK));
8819 if (!(*p & NODE_MBRMASK)) { /* standard node */
8820 *((union node **)nn) = copynode(*((const union node **) no));
8821 } else if ((*p & NODE_MBRMASK) == NODE_CHARPTR) { /* string */
8822 *((const char **)nn) = nodesavestr(*((const char **)no));
8823 } else if (*p & NODE_NODELIST) { /* nodelist */
8824 *((struct nodelist **)nn)
8825 = copynodelist(*((const struct nodelist **) no));
8826 } else { /* integer */
8827 *((int *) nn) = *((int *) no);
8829 } while (!(*p++ & NODE_NOMORE));
8832 #else /* COPYNODE_TABLE */
8834 copynode(const union node *n)
8841 funcblock = (char *) funcblock + nodesize[n->type];
8848 new->nbinary.ch2 = copynode(n->nbinary.ch2);
8849 new->nbinary.ch1 = copynode(n->nbinary.ch1);
8852 new->ncmd.redirect = copynode(n->ncmd.redirect);
8853 new->ncmd.args = copynode(n->ncmd.args);
8854 new->ncmd.assign = copynode(n->ncmd.assign);
8855 new->ncmd.backgnd = n->ncmd.backgnd;
8858 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
8859 new->npipe.backgnd = n->npipe.backgnd;
8864 new->nredir.redirect = copynode(n->nredir.redirect);
8865 new->nredir.n = copynode(n->nredir.n);
8868 new->nif.elsepart = copynode(n->nif.elsepart);
8869 new->nif.ifpart = copynode(n->nif.ifpart);
8870 new->nif.test = copynode(n->nif.test);
8873 new->nfor.var = nodesavestr(n->nfor.var);
8874 new->nfor.body = copynode(n->nfor.body);
8875 new->nfor.args = copynode(n->nfor.args);
8878 new->ncase.cases = copynode(n->ncase.cases);
8879 new->ncase.expr = copynode(n->ncase.expr);
8882 new->nclist.body = copynode(n->nclist.body);
8883 new->nclist.pattern = copynode(n->nclist.pattern);
8884 new->nclist.next = copynode(n->nclist.next);
8888 new->narg.backquote = copynodelist(n->narg.backquote);
8889 new->narg.text = nodesavestr(n->narg.text);
8890 new->narg.next = copynode(n->narg.next);
8897 new->nfile.fname = copynode(n->nfile.fname);
8898 new->nfile.fd = n->nfile.fd;
8899 new->nfile.next = copynode(n->nfile.next);
8903 new->ndup.vname = copynode(n->ndup.vname);
8904 new->ndup.dupfd = n->ndup.dupfd;
8905 new->ndup.fd = n->ndup.fd;
8906 new->ndup.next = copynode(n->ndup.next);
8910 new->nhere.doc = copynode(n->nhere.doc);
8911 new->nhere.fd = n->nhere.fd;
8912 new->nhere.next = copynode(n->nhere.next);
8915 new->nnot.com = copynode(n->nnot.com);
8918 new->type = n->type;
8921 #endif /* COPYNODE_TABLE */
8923 #ifdef CALCSIZE_TABLE
8925 calcsize(const union node *n)
8927 const unsigned char *p;
8931 funcblocksize += (int) nodesize[n->type];
8933 p = copynode_ops + (int) copynode_ops_index[n->type];
8935 const char *no = ((const char *) n) + ((int)(*p & NODE_OFFSETMASK));
8937 if (!(*p & NODE_MBRMASK)) { /* standard node */
8938 calcsize(*((const union node **) no));
8939 } else if ((*p & NODE_MBRMASK) == NODE_CHARPTR) { /* string */
8940 funcstringsize += strlen(*((const char **)no)) + 1;
8941 } else if (*p & NODE_NODELIST) { /* nodelist */
8942 sizenodelist(*((const struct nodelist **) no));
8943 } /* else integer -- ignore */
8944 } while (!(*p++ & NODE_NOMORE));
8946 #else /* CALCSIZE_TABLE */
8948 calcsize(const union node *n)
8952 funcblocksize += nodesize[n->type];
8959 calcsize(n->nbinary.ch2);
8960 calcsize(n->nbinary.ch1);
8963 calcsize(n->ncmd.redirect);
8964 calcsize(n->ncmd.args);
8965 calcsize(n->ncmd.assign);
8968 sizenodelist(n->npipe.cmdlist);
8973 calcsize(n->nredir.redirect);
8974 calcsize(n->nredir.n);
8977 calcsize(n->nif.elsepart);
8978 calcsize(n->nif.ifpart);
8979 calcsize(n->nif.test);
8982 funcstringsize += strlen(n->nfor.var) + 1;
8983 calcsize(n->nfor.body);
8984 calcsize(n->nfor.args);
8987 calcsize(n->ncase.cases);
8988 calcsize(n->ncase.expr);
8991 calcsize(n->nclist.body);
8992 calcsize(n->nclist.pattern);
8993 calcsize(n->nclist.next);
8997 sizenodelist(n->narg.backquote);
8998 funcstringsize += strlen(n->narg.text) + 1;
8999 calcsize(n->narg.next);
9006 calcsize(n->nfile.fname);
9007 calcsize(n->nfile.next);
9011 calcsize(n->ndup.vname);
9012 calcsize(n->ndup.next);
9016 calcsize(n->nhere.doc);
9017 calcsize(n->nhere.next);
9020 calcsize(n->nnot.com);
9024 #endif /* CALCSIZE_TABLE */
9027 sizenodelist(const struct nodelist *lp)
9030 funcblocksize += ALIGN(sizeof(struct nodelist));
9037 static struct nodelist *
9038 copynodelist(const struct nodelist *lp)
9040 struct nodelist *start;
9041 struct nodelist **lpp;
9046 funcblock = (char *) funcblock + ALIGN(sizeof(struct nodelist));
9047 (*lpp)->n = copynode(lp->n);
9049 lpp = &(*lpp)->next;
9057 nodesavestr(const char *s)
9060 char *q = funcstring;
9061 char *rtn = funcstring;
9063 while ((*q++ = *p++) != '\0')
9070 static int getopts (char *, char *, char **, int *, int *);
9075 * Process the shell command line arguments.
9079 procargs(argc, argv)
9088 for (i = 0; i < NOPTS; i++)
9091 if (*argptr == NULL && minusc == NULL)
9093 if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
9097 for (i = 0; i < NOPTS; i++)
9098 if (optent_val(i) == 2)
9101 if (sflag == 0 && minusc == NULL) {
9102 commandname = argv[0];
9104 setinputfile(arg0, 0);
9107 /* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
9108 if (argptr && minusc && *argptr)
9111 shellparam.p = argptr;
9112 shellparam.optind = 1;
9113 shellparam.optoff = -1;
9114 /* assert(shellparam.malloc == 0 && shellparam.nparam == 0); */
9116 shellparam.nparam++;
9125 * Process shell options. The global variable argptr contains a pointer
9126 * to the argument list; we advance it past the options.
9130 minus_o(const char *name, int val)
9135 out1str("Current option settings\n");
9136 for (i = 0; i < NOPTS; i++)
9137 printf("%-16s%s\n", optent_name(optlist[i]),
9138 optent_val(i) ? "on" : "off");
9140 for (i = 0; i < NOPTS; i++)
9141 if (equal(name, optent_name(optlist[i]))) {
9142 setoption(optent_letter(optlist[i]), val);
9145 error("Illegal option -o %s", name);
9151 options(int cmdline)
9159 while ((p = *argptr) != NULL) {
9161 if ((c = *p++) == '-') {
9163 if (p[0] == '\0' || (p[0] == '-' && p[1] == '\0')) {
9165 /* "-" means turn off -x and -v */
9168 /* "--" means reset params */
9169 else if (*argptr == NULL)
9172 break; /* "-" or "--" terminates options */
9174 } else if (c == '+') {
9180 while ((c = *p++) != '\0') {
9181 if (c == 'c' && cmdline) {
9183 #ifdef NOHACK /* removing this code allows sh -ce 'foo' for compat */
9187 if (q == NULL || minusc != NULL)
9188 error("Bad -c option");
9193 } else if (c == 'o') {
9194 minus_o(*argptr, val);
9206 setoption(int flag, int val)
9210 for (i = 0; i < NOPTS; i++)
9211 if (optent_letter(optlist[i]) == flag) {
9212 optent_val(i) = val;
9214 /* #%$ hack for ksh semantics */
9217 else if (flag == 'E')
9222 error("Illegal option -%c", flag);
9229 * Set the shell parameters.
9233 setparam(char **argv)
9239 for (nparam = 0 ; argv[nparam] ; nparam++);
9240 ap = newparam = ckmalloc((nparam + 1) * sizeof *ap);
9242 *ap++ = savestr(*argv++);
9245 freeparam(&shellparam);
9246 shellparam.malloc = 1;
9247 shellparam.nparam = nparam;
9248 shellparam.p = newparam;
9249 shellparam.optind = 1;
9250 shellparam.optoff = -1;
9255 * Free the list of positional parameters.
9259 freeparam(volatile struct shparam *param)
9263 if (param->malloc) {
9264 for (ap = param->p ; *ap ; ap++)
9273 * The shift builtin command.
9277 shiftcmd(argc, argv)
9286 n = number(argv[1]);
9287 if (n > shellparam.nparam)
9288 error("can't shift that many");
9290 shellparam.nparam -= n;
9291 for (ap1 = shellparam.p ; --n >= 0 ; ap1++) {
9292 if (shellparam.malloc)
9296 while ((*ap2++ = *ap1++) != NULL);
9297 shellparam.optind = 1;
9298 shellparam.optoff = -1;
9306 * The set command builtin.
9315 return showvarscmd(argc, argv);
9319 if (*argptr != NULL) {
9328 getoptsreset(const char *value)
9330 shellparam.optind = number(value);
9331 shellparam.optoff = -1;
9334 #ifdef CONFIG_LOCALE_SUPPORT
9335 static void change_lc_all(const char *value)
9337 if(value != 0 && *value != 0)
9338 setlocale(LC_ALL, value);
9341 static void change_lc_ctype(const char *value)
9343 if(value != 0 && *value != 0)
9344 setlocale(LC_CTYPE, value);
9351 * The getopts builtin. Shellparam.optnext points to the next argument
9352 * to be processed. Shellparam.optptr points to the next character to
9353 * be processed in the current argument. If shellparam.optnext is NULL,
9354 * then it's the first time getopts has been called.
9358 getoptscmd(argc, argv)
9365 error("Usage: getopts optstring var [arg]");
9366 else if (argc == 3) {
9367 optbase = shellparam.p;
9368 if (shellparam.optind > shellparam.nparam + 1) {
9369 shellparam.optind = 1;
9370 shellparam.optoff = -1;
9375 if (shellparam.optind > argc - 2) {
9376 shellparam.optind = 1;
9377 shellparam.optoff = -1;
9381 return getopts(argv[1], argv[2], optbase, &shellparam.optind,
9382 &shellparam.optoff);
9386 * Safe version of setvar, returns 1 on success 0 on failure.
9390 setvarsafe(name, val, flags)
9391 const char *name, *val;
9394 struct jmploc jmploc;
9395 struct jmploc *volatile savehandler = handler;
9401 if (setjmp(jmploc.loc))
9405 setvar(name, val, flags);
9407 handler = savehandler;
9412 getopts(optstr, optvar, optfirst, myoptind, optoff)
9424 char **optnext = optfirst + *myoptind - 1;
9426 if (*myoptind <= 1 || *optoff < 0 || !(*(optnext - 1)) ||
9427 strlen(*(optnext - 1)) < *optoff)
9430 p = *(optnext - 1) + *optoff;
9431 if (p == NULL || *p == '\0') {
9432 /* Current word is done, advance */
9433 if (optnext == NULL)
9436 if (p == NULL || *p != '-' || *++p == '\0') {
9438 *myoptind = optnext - optfirst + 1;
9444 if (p[0] == '-' && p[1] == '\0') /* check for "--" */
9449 for (q = optstr; *q != c; ) {
9451 if (optstr[0] == ':') {
9454 err |= setvarsafe("OPTARG", s, 0);
9457 out2fmt("Illegal option -%c\n", c);
9458 (void) unsetvar("OPTARG");
9468 if (*p == '\0' && (p = *optnext) == NULL) {
9469 if (optstr[0] == ':') {
9472 err |= setvarsafe("OPTARG", s, 0);
9476 out2fmt("No arg for -%c option\n", c);
9477 (void) unsetvar("OPTARG");
9485 setvarsafe("OPTARG", p, 0);
9489 setvarsafe("OPTARG", "", 0);
9490 *myoptind = optnext - optfirst + 1;
9497 *optoff = p ? p - *(optnext - 1) : -1;
9498 snprintf(s, sizeof(s), "%d", *myoptind);
9499 err |= setvarsafe("OPTIND", s, VNOFUNC);
9502 err |= setvarsafe(optvar, s, 0);
9513 * XXX - should get rid of. have all builtins use getopt(3). the
9514 * library getopt must have the BSD extension static variable "optreset"
9515 * otherwise it can't be used within the shell safely.
9517 * Standard option processing (a la getopt) for builtin routines. The
9518 * only argument that is passed to nextopt is the option string; the
9519 * other arguments are unnecessary. It return the character, or '\0' on
9524 nextopt(const char *optstring)
9530 if ((p = optptr) == NULL || *p == '\0') {
9532 if (p == NULL || *p != '-' || *++p == '\0')
9535 if (p[0] == '-' && p[1] == '\0') /* check for "--" */
9539 for (q = optstring ; *q != c ; ) {
9541 error("Illegal option -%c", c);
9546 if (*p == '\0' && (p = *argptr++) == NULL)
9547 error("No arg for -%c option", c);
9564 out2fmt(const char *fmt, ...)
9568 vfprintf(stderr, fmt, ap);
9573 * Version of write which resumes after a signal is caught.
9577 xwrite(int fd, const char *buf, int nbytes)
9586 i = write(fd, buf, n);
9592 } else if (i == 0) {
9595 } else if (errno != EINTR) {
9603 * Shell command parser.
9606 #define EOFMARKLEN 79
9611 struct heredoc *next; /* next here document in list */
9612 union node *here; /* redirection node */
9613 char *eofmark; /* string indicating end of input */
9614 int striptabs; /* if set, strip leading tabs */
9617 static struct heredoc *heredoclist; /* list of here documents to read */
9618 static int parsebackquote; /* nonzero if we are inside backquotes */
9619 static int doprompt; /* if set, prompt the user */
9620 static int needprompt; /* true if interactive and at start of line */
9621 static int lasttoken; /* last token read */
9623 static char *wordtext; /* text of last word returned by readtoken */
9625 static struct nodelist *backquotelist;
9626 static union node *redirnode;
9627 static struct heredoc *heredoc;
9628 static int quoteflag; /* set if (part of) last token was quoted */
9629 static int startlinno; /* line # where last token started */
9632 static union node *list (int);
9633 static union node *andor (void);
9634 static union node *pipeline (void);
9635 static union node *command (void);
9636 static union node *simplecmd (void);
9637 static void parsefname (void);
9638 static void parseheredoc (void);
9639 static char peektoken (void);
9640 static int readtoken (void);
9641 static int xxreadtoken (void);
9642 static int readtoken1 (int, int, const char *, int);
9643 static int noexpand (char *);
9644 static void synexpect (int) __attribute__((noreturn));
9645 static void synerror (const char *) __attribute__((noreturn));
9646 static void setprompt (int);
9650 * Read and parse a command. Returns NEOF on end of file. (NULL is a
9651 * valid parse tree indicating a blank line.)
9655 parsecmd(int interact)
9660 doprompt = interact;
9680 union node *n1, *n2, *n3;
9684 if (nlflag == 0 && peektoken())
9690 if (tok == TBACKGND) {
9691 if (n2->type == NCMD || n2->type == NPIPE) {
9692 n2->ncmd.backgnd = 1;
9693 } else if (n2->type == NREDIR) {
9694 n2->type = NBACKGND;
9696 n3 = (union node *)stalloc(sizeof (struct nredir));
9697 n3->type = NBACKGND;
9699 n3->nredir.redirect = NULL;
9707 n3 = (union node *)stalloc(sizeof (struct nbinary));
9709 n3->nbinary.ch1 = n1;
9710 n3->nbinary.ch2 = n2;
9734 pungetc(); /* push back EOF on input */
9749 union node *n1, *n2, *n3;
9755 if ((t = readtoken()) == TAND) {
9757 } else if (t == TOR) {
9765 n3 = (union node *)stalloc(sizeof (struct nbinary));
9767 n3->nbinary.ch1 = n1;
9768 n3->nbinary.ch2 = n2;
9777 union node *n1, *n2, *pipenode;
9778 struct nodelist *lp, *prev;
9782 TRACE(("pipeline: entered\n"));
9783 if (readtoken() == TNOT) {
9789 if (readtoken() == TPIPE) {
9790 pipenode = (union node *)stalloc(sizeof (struct npipe));
9791 pipenode->type = NPIPE;
9792 pipenode->npipe.backgnd = 0;
9793 lp = (struct nodelist *)stalloc(sizeof (struct nodelist));
9794 pipenode->npipe.cmdlist = lp;
9798 lp = (struct nodelist *)stalloc(sizeof (struct nodelist));
9802 } while (readtoken() == TPIPE);
9808 n2 = (union node *)stalloc(sizeof (struct nnot));
9820 union node *n1, *n2;
9821 union node *ap, **app;
9822 union node *cp, **cpp;
9823 union node *redir, **rpp;
9830 /* Check for redirection which may precede command */
9831 while (readtoken() == TREDIR) {
9832 *rpp = n2 = redirnode;
9833 rpp = &n2->nfile.next;
9838 switch (readtoken()) {
9840 n1 = (union node *)stalloc(sizeof (struct nif));
9842 n1->nif.test = list(0);
9843 if (readtoken() != TTHEN)
9845 n1->nif.ifpart = list(0);
9847 while (readtoken() == TELIF) {
9848 n2->nif.elsepart = (union node *)stalloc(sizeof (struct nif));
9849 n2 = n2->nif.elsepart;
9851 n2->nif.test = list(0);
9852 if (readtoken() != TTHEN)
9854 n2->nif.ifpart = list(0);
9856 if (lasttoken == TELSE)
9857 n2->nif.elsepart = list(0);
9859 n2->nif.elsepart = NULL;
9862 if (readtoken() != TFI)
9869 n1 = (union node *)stalloc(sizeof (struct nbinary));
9870 n1->type = (lasttoken == TWHILE)? NWHILE : NUNTIL;
9871 n1->nbinary.ch1 = list(0);
9872 if ((got=readtoken()) != TDO) {
9873 TRACE(("expecting DO got %s %s\n", tokname(got), got == TWORD ? wordtext : ""));
9876 n1->nbinary.ch2 = list(0);
9877 if (readtoken() != TDONE)
9883 if (readtoken() != TWORD || quoteflag || ! goodname(wordtext))
9884 synerror("Bad for loop variable");
9885 n1 = (union node *)stalloc(sizeof (struct nfor));
9887 n1->nfor.var = wordtext;
9889 if (readtoken() == TIN) {
9891 while (readtoken() == TWORD) {
9892 n2 = (union node *)stalloc(sizeof (struct narg));
9894 n2->narg.text = wordtext;
9895 n2->narg.backquote = backquotelist;
9897 app = &n2->narg.next;
9901 if (lasttoken != TNL && lasttoken != TSEMI)
9904 static char argvars[5] = {CTLVAR, VSNORMAL|VSQUOTE,
9906 n2 = (union node *)stalloc(sizeof (struct narg));
9908 n2->narg.text = argvars;
9909 n2->narg.backquote = NULL;
9910 n2->narg.next = NULL;
9913 * Newline or semicolon here is optional (but note
9914 * that the original Bourne shell only allowed NL).
9916 if (lasttoken != TNL && lasttoken != TSEMI)
9920 if (readtoken() != TDO)
9922 n1->nfor.body = list(0);
9923 if (readtoken() != TDONE)
9928 n1 = (union node *)stalloc(sizeof (struct ncase));
9930 if (readtoken() != TWORD)
9932 n1->ncase.expr = n2 = (union node *)stalloc(sizeof (struct narg));
9934 n2->narg.text = wordtext;
9935 n2->narg.backquote = backquotelist;
9936 n2->narg.next = NULL;
9939 } while (readtoken() == TNL);
9940 if (lasttoken != TIN)
9941 synerror("expecting \"in\"");
9942 cpp = &n1->ncase.cases;
9943 checkkwd = 2, readtoken();
9945 if (lasttoken == TLP)
9947 *cpp = cp = (union node *)stalloc(sizeof (struct nclist));
9949 app = &cp->nclist.pattern;
9951 *app = ap = (union node *)stalloc(sizeof (struct narg));
9953 ap->narg.text = wordtext;
9954 ap->narg.backquote = backquotelist;
9955 if (checkkwd = 2, readtoken() != TPIPE)
9957 app = &ap->narg.next;
9960 ap->narg.next = NULL;
9961 if (lasttoken != TRP)
9963 cp->nclist.body = list(0);
9966 if ((t = readtoken()) != TESAC) {
9968 synexpect(TENDCASE);
9970 checkkwd = 2, readtoken();
9972 cpp = &cp->nclist.next;
9973 } while(lasttoken != TESAC);
9978 n1 = (union node *)stalloc(sizeof (struct nredir));
9979 n1->type = NSUBSHELL;
9980 n1->nredir.n = list(0);
9981 n1->nredir.redirect = NULL;
9982 if (readtoken() != TRP)
9988 if (readtoken() != TEND)
9992 /* Handle an empty command like other simple commands. */
10001 * An empty command before a ; doesn't make much sense, and
10002 * should certainly be disallowed in the case of `if ;'.
10015 /* Now check for redirection which may follow command */
10016 while (readtoken() == TREDIR) {
10017 *rpp = n2 = redirnode;
10018 rpp = &n2->nfile.next;
10024 if (n1->type != NSUBSHELL) {
10025 n2 = (union node *)stalloc(sizeof (struct nredir));
10030 n1->nredir.redirect = redir;
10037 static union node *
10039 union node *args, **app;
10040 union node *n = NULL;
10041 union node *vars, **vpp;
10042 union node **rpp, *redir;
10053 switch (readtoken()) {
10056 n = (union node *)stalloc(sizeof (struct narg));
10058 n->narg.text = wordtext;
10059 n->narg.backquote = backquotelist;
10060 if (lasttoken == TWORD) {
10062 app = &n->narg.next;
10065 vpp = &n->narg.next;
10069 *rpp = n = redirnode;
10070 rpp = &n->nfile.next;
10071 parsefname(); /* read name of redirection file */
10075 args && app == &args->narg.next &&
10078 /* We have a function */
10079 if (readtoken() != TRP)
10083 n->narg.next = command();
10096 n = (union node *)stalloc(sizeof (struct ncmd));
10098 n->ncmd.backgnd = 0;
10099 n->ncmd.args = args;
10100 n->ncmd.assign = vars;
10101 n->ncmd.redirect = redir;
10105 static union node *
10109 n = (union node *)stalloc(sizeof (struct narg));
10111 n->narg.next = NULL;
10112 n->narg.text = wordtext;
10113 n->narg.backquote = backquotelist;
10117 static void fixredir(union node *n, const char *text, int err)
10119 TRACE(("Fix redir %s %d\n", text, err));
10121 n->ndup.vname = NULL;
10123 if (is_digit(text[0]) && text[1] == '\0')
10124 n->ndup.dupfd = digit_val(text[0]);
10125 else if (text[0] == '-' && text[1] == '\0')
10126 n->ndup.dupfd = -1;
10130 synerror("Bad fd number");
10132 n->ndup.vname = makename();
10139 union node *n = redirnode;
10141 if (readtoken() != TWORD)
10143 if (n->type == NHERE) {
10144 struct heredoc *here = heredoc;
10148 if (quoteflag == 0)
10150 TRACE(("Here document %d\n", n->type));
10151 if (here->striptabs) {
10152 while (*wordtext == '\t')
10155 if (! noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)
10156 synerror("Illegal eof marker for << redirection");
10157 rmescapes(wordtext);
10158 here->eofmark = wordtext;
10160 if (heredoclist == NULL)
10161 heredoclist = here;
10163 for (p = heredoclist ; p->next ; p = p->next);
10166 } else if (n->type == NTOFD || n->type == NFROMFD) {
10167 fixredir(n, wordtext, 0);
10169 n->nfile.fname = makename();
10175 * Input any here documents.
10180 struct heredoc *here;
10183 while (heredoclist) {
10184 here = heredoclist;
10185 heredoclist = here->next;
10190 readtoken1(pgetc(), here->here->type == NHERE? SQSYNTAX : DQSYNTAX,
10191 here->eofmark, here->striptabs);
10192 n = (union node *)stalloc(sizeof (struct narg));
10193 n->narg.type = NARG;
10194 n->narg.next = NULL;
10195 n->narg.text = wordtext;
10196 n->narg.backquote = backquotelist;
10197 here->here->nhere.doc = n;
10207 return tokname_array[t][0];
10215 int savecheckalias = checkalias;
10216 int savecheckkwd = checkkwd;
10221 int alreadyseen = tokpushback;
10231 checkalias = savecheckalias;
10238 if (checkkwd == 2) {
10247 * check for keywords
10249 if (t == TWORD && !quoteflag)
10251 const char *const *pp;
10253 if ((pp = findkwd(wordtext))) {
10254 lasttoken = t = pp - tokname_array;
10255 TRACE(("keyword %s recognized\n", tokname(t)));
10266 } else if (checkalias == 2 && isassignment(wordtext)) {
10267 lasttoken = t = TASSIGN;
10269 } else if (checkalias) {
10270 if (!quoteflag && (ap = lookupalias(wordtext, 1)) != NULL) {
10272 pushstring(ap->val, strlen(ap->val), ap);
10274 checkkwd = savecheckkwd;
10283 TRACE(("token %s %s\n", tokname(t), t == TWORD || t == TASSIGN ? wordtext : ""));
10285 TRACE(("reread token %s %s\n", tokname(t), t == TWORD || t == TASSIGN ? wordtext : ""));
10292 * Read the next input token.
10293 * If the token is a word, we set backquotelist to the list of cmds in
10294 * backquotes. We set quoteflag to true if any part of the word was
10296 * If the token is TREDIR, then we set redirnode to a structure containing
10298 * In all cases, the variable startlinno is set to the number of the line
10299 * on which the token starts.
10301 * [Change comment: here documents and internal procedures]
10302 * [Readtoken shouldn't have any arguments. Perhaps we should make the
10303 * word parsing code into a separate routine. In this case, readtoken
10304 * doesn't need to have any internal procedures, but parseword does.
10305 * We could also make parseoperator in essence the main routine, and
10306 * have parseword (readtoken1?) handle both words and redirection.]
10309 #define NEW_xxreadtoken
10310 #ifdef NEW_xxreadtoken
10312 static const char xxreadtoken_chars[] = "\n()&|;"; /* singles must be first! */
10313 static const char xxreadtoken_tokens[] = {
10314 TNL, TLP, TRP, /* only single occurrence allowed */
10315 TBACKGND, TPIPE, TSEMI, /* if single occurrence */
10316 TEOF, /* corresponds to trailing nul */
10317 TAND, TOR, TENDCASE, /* if double occurrence */
10320 #define xxreadtoken_doubles \
10321 (sizeof(xxreadtoken_tokens) - sizeof(xxreadtoken_chars))
10322 #define xxreadtoken_singles \
10323 (sizeof(xxreadtoken_chars) - xxreadtoken_doubles - 1)
10337 startlinno = plinno;
10338 for (;;) { /* until token or start of word found */
10341 if ((c!=' ') && (c!='\t')
10347 while ((c = pgetc()) != '\n' && c != PEOF);
10349 } else if (c=='\\') {
10350 if (pgetc() != '\n') {
10354 startlinno = ++plinno;
10355 setprompt(doprompt ? 2 : 0);
10358 = xxreadtoken_chars + sizeof(xxreadtoken_chars) - 1;
10363 needprompt = doprompt;
10366 p = strchr(xxreadtoken_chars, c);
10369 return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
10372 if (p-xxreadtoken_chars >= xxreadtoken_singles) {
10373 if (pgetc() == *p) { /* double occurrence? */
10374 p += xxreadtoken_doubles + 1;
10381 return lasttoken = xxreadtoken_tokens[p-xxreadtoken_chars];
10389 #define RETURN(token) return lasttoken = token
10403 startlinno = plinno;
10404 for (;;) { /* until token or start of word found */
10407 case ' ': case '\t':
10413 while ((c = pgetc()) != '\n' && c != PEOF);
10417 if (pgetc() == '\n') {
10418 startlinno = ++plinno;
10429 needprompt = doprompt;
10434 if (pgetc() == '&')
10439 if (pgetc() == '|')
10444 if (pgetc() == ';')
10457 return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
10464 * If eofmark is NULL, read a word or a redirection symbol. If eofmark
10465 * is not NULL, read a here document. In the latter case, eofmark is the
10466 * word which marks the end of the document and striptabs is true if
10467 * leading tabs should be stripped from the document. The argument firstc
10468 * is the first character of the input token or document.
10470 * Because C does not have internal subroutines, I have simulated them
10471 * using goto's to implement the subroutine linkage. The following macros
10472 * will run code that appears at the end of readtoken1.
10475 #define CHECKEND() {goto checkend; checkend_return:;}
10476 #define PARSEREDIR() {goto parseredir; parseredir_return:;}
10477 #define PARSESUB() {goto parsesub; parsesub_return:;}
10478 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
10479 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
10480 #define PARSEARITH() {goto parsearith; parsearith_return:;}
10483 readtoken1(int firstc, int syntax, const char *eofmark, int striptabs)
10488 char line[EOFMARKLEN + 1];
10489 struct nodelist *bqlist;
10492 int varnest; /* levels of variables expansion */
10493 int arinest; /* levels of arithmetic expansion */
10494 int parenlevel; /* levels of parens in arithmetic */
10495 int dqvarnest; /* levels of variables expansion within double quotes */
10497 int prevsyntax; /* syntax before arithmetic */
10499 /* Avoid longjmp clobbering */
10505 (void) &parenlevel;
10508 (void) &prevsyntax;
10512 startlinno = plinno;
10514 if (syntax == DQSYNTAX)
10523 STARTSTACKSTR(out);
10524 loop: { /* for each line, until end of word */
10525 CHECKEND(); /* set c to PEOF if at end of here document */
10526 for (;;) { /* until end of line or end of word */
10527 CHECKSTRSPACE(3, out); /* permit 3 calls to USTPUTC */
10528 switch(SIT(c,syntax)) {
10529 case CNL: /* '\n' */
10530 if (syntax == BASESYNTAX)
10531 goto endword; /* exit outer loop */
10539 goto loop; /* continue outer loop */
10544 if ((eofmark == NULL || dblquote) &&
10546 USTPUTC(CTLESC, out);
10549 case CBACK: /* backslash */
10552 USTPUTC('\\', out);
10554 } else if (c == '\n') {
10560 if (dblquote && c != '\\' && c != '`' && c != '$'
10561 && (c != '"' || eofmark != NULL))
10562 USTPUTC('\\', out);
10563 if (SIT(c,SQSYNTAX) == CCTL)
10564 USTPUTC(CTLESC, out);
10565 else if (eofmark == NULL)
10566 USTPUTC(CTLQUOTEMARK, out);
10572 if (eofmark == NULL)
10573 USTPUTC(CTLQUOTEMARK, out);
10577 if (eofmark == NULL)
10578 USTPUTC(CTLQUOTEMARK, out);
10583 if (eofmark != NULL && arinest == 0 &&
10588 syntax = ARISYNTAX;
10590 } else if (eofmark == NULL &&
10592 syntax = BASESYNTAX;
10598 case CVAR: /* '$' */
10599 PARSESUB(); /* parse substitution */
10601 case CENDVAR: /* '}' */
10604 if (dqvarnest > 0) {
10607 USTPUTC(CTLENDVAR, out);
10612 #ifdef ASH_MATH_SUPPORT
10613 case CLP: /* '(' in arithmetic */
10617 case CRP: /* ')' in arithmetic */
10618 if (parenlevel > 0) {
10622 if (pgetc() == ')') {
10623 if (--arinest == 0) {
10624 USTPUTC(CTLENDARI, out);
10625 syntax = prevsyntax;
10626 if (syntax == DQSYNTAX)
10634 * unbalanced parens
10635 * (don't 2nd guess - no error)
10643 case CBQUOTE: /* '`' */
10647 goto endword; /* exit outer loop */
10652 goto endword; /* exit outer loop */
10663 if (syntax == ARISYNTAX)
10664 synerror("Missing '))'");
10665 if (syntax != BASESYNTAX && ! parsebackquote && eofmark == NULL)
10666 synerror("Unterminated quoted string");
10667 if (varnest != 0) {
10668 startlinno = plinno;
10669 synerror("Missing '}'");
10671 USTPUTC('\0', out);
10672 len = out - stackblock();
10673 out = stackblock();
10674 if (eofmark == NULL) {
10675 if ((c == '>' || c == '<')
10678 && (*out == '\0' || is_digit(*out))) {
10680 return lasttoken = TREDIR;
10685 quoteflag = quotef;
10686 backquotelist = bqlist;
10687 grabstackblock(len);
10689 return lasttoken = TWORD;
10690 /* end of readtoken routine */
10695 * Check to see whether we are at the end of the here document. When this
10696 * is called, c is set to the first character of the next input line. If
10697 * we are at the end of the here document, this routine sets the c to PEOF.
10708 while (c == '\t') {
10712 if (c == *eofmark) {
10713 if (pfgets(line, sizeof line) != NULL) {
10717 for (q = eofmark + 1 ; *q && *p == *q ; p++, q++);
10718 if (*p == '\n' && *q == '\0') {
10721 needprompt = doprompt;
10723 pushstring(line, strlen(line), NULL);
10728 goto checkend_return;
10733 * Parse a redirection operator. The variable "out" points to a string
10734 * specifying the fd to be redirected. The variable "c" contains the
10735 * first character of the redirection operator.
10742 np = (union node *)stalloc(sizeof (struct nfile));
10747 np->type = NAPPEND;
10756 } else { /* c == '<' */
10758 switch (c = pgetc()) {
10760 if (sizeof (struct nfile) != sizeof (struct nhere)) {
10761 np = (union node *)stalloc(sizeof (struct nhere));
10765 heredoc = (struct heredoc *)stalloc(sizeof (struct heredoc));
10766 heredoc->here = np;
10767 if ((c = pgetc()) == '-') {
10768 heredoc->striptabs = 1;
10770 heredoc->striptabs = 0;
10776 np->type = NFROMFD;
10780 np->type = NFROMTO;
10790 np->nfile.fd = digit_val(fd);
10792 goto parseredir_return;
10797 * Parse a substitution. At this point, we have read the dollar sign
10798 * and nothing else.
10806 static const char types[] = "}-+?=";
10811 (c != '(' && c != '{' && !is_name(c) && !is_special(c))
10815 } else if (c == '(') { /* $(command) or $((arith)) */
10816 if (pgetc() == '(') {
10823 USTPUTC(CTLVAR, out);
10824 typeloc = out - stackblock();
10825 USTPUTC(VSNORMAL, out);
10826 subtype = VSNORMAL;
10830 if ((c = pgetc()) == '}')
10833 subtype = VSLENGTH;
10838 if (c > PEOA && is_name(c)) {
10842 } while (c > PEOA && is_in_name(c));
10843 } else if (is_digit(c)) {
10847 } while (is_digit(c));
10849 else if (is_special(c)) {
10854 badsub: synerror("Bad substitution");
10858 if (subtype == 0) {
10865 p = strchr(types, c);
10868 subtype = p - types + VSNORMAL;
10874 subtype = c == '#' ? VSTRIMLEFT :
10887 if (dblquote || arinest)
10889 *(stackblock() + typeloc) = subtype | flags;
10890 if (subtype != VSNORMAL) {
10897 goto parsesub_return;
10902 * Called to parse command substitutions. Newstyle is set if the command
10903 * is enclosed inside $(...); nlpp is a pointer to the head of the linked
10904 * list of commands (passed by reference), and savelen is the number of
10905 * characters on the top of the stack which must be preserved.
10909 struct nodelist **nlpp;
10912 char *volatile str;
10913 struct jmploc jmploc;
10914 struct jmploc *volatile savehandler;
10918 (void) &saveprompt;
10921 savepbq = parsebackquote;
10922 if (setjmp(jmploc.loc)) {
10925 parsebackquote = 0;
10926 handler = savehandler;
10927 longjmp(handler->loc, 1);
10931 savelen = out - stackblock();
10933 str = ckmalloc(savelen);
10934 memcpy(str, stackblock(), savelen);
10936 savehandler = handler;
10940 /* We must read until the closing backquote, giving special
10941 treatment to some slashes, and then push the string and
10942 reread it as input, interpreting it normally. */
10949 STARTSTACKSTR(pout);
10955 switch (pc = pgetc()) {
10960 if ((pc = pgetc()) == '\n') {
10967 * If eating a newline, avoid putting
10968 * the newline into the new character
10969 * stream (via the STPUTC after the
10974 if (pc != '\\' && pc != '`' && pc != '$'
10975 && (!dblquote || pc != '"'))
10976 STPUTC('\\', pout);
10986 startlinno = plinno;
10987 synerror("EOF in backquote substitution");
10991 needprompt = doprompt;
11000 STPUTC('\0', pout);
11001 psavelen = pout - stackblock();
11002 if (psavelen > 0) {
11003 pstr = grabstackstr(pout);
11004 setinputstring(pstr);
11009 nlpp = &(*nlpp)->next;
11010 *nlpp = (struct nodelist *)stalloc(sizeof (struct nodelist));
11011 (*nlpp)->next = NULL;
11012 parsebackquote = oldstyle;
11015 saveprompt = doprompt;
11022 doprompt = saveprompt;
11024 if (readtoken() != TRP)
11031 * Start reading from old file again, ignoring any pushed back
11032 * tokens left from the backquote parsing
11037 while (stackblocksize() <= savelen)
11039 STARTSTACKSTR(out);
11041 memcpy(out, str, savelen);
11042 STADJUST(savelen, out);
11048 parsebackquote = savepbq;
11049 handler = savehandler;
11050 if (arinest || dblquote)
11051 USTPUTC(CTLBACKQ | CTLQUOTE, out);
11053 USTPUTC(CTLBACKQ, out);
11055 goto parsebackq_oldreturn;
11057 goto parsebackq_newreturn;
11061 * Parse an arithmetic expansion (indicate start of one and set state)
11065 if (++arinest == 1) {
11066 prevsyntax = syntax;
11067 syntax = ARISYNTAX;
11068 USTPUTC(CTLARI, out);
11075 * we collapse embedded arithmetic expansion to
11076 * parenthesis, which should be equivalent
11080 goto parsearith_return;
11083 } /* end of readtoken */
11087 * Returns true if the text contains nothing to expand (no dollar signs
11099 while ((c = *p++) != '\0') {
11100 if (c == CTLQUOTEMARK)
11104 else if (SIT(c,BASESYNTAX) == CCTL)
11112 * Return true if the argument is a legal variable name (a letter or
11113 * underscore followed by zero or more letters, underscores, and digits).
11117 goodname(const char *name)
11125 if (! is_in_name(*p))
11133 * Called when an unexpected token is read during the parse. The argument
11134 * is the token that is expected, or -1 if more than one type of token can
11135 * occur at this point.
11145 l = sprintf(msg, "%s unexpected", tokname(lasttoken));
11147 sprintf(msg+l, " (expecting %s)", tokname(token));
11154 synerror(const char *msg)
11157 out2fmt("%s: %d: ", commandname, startlinno);
11158 out2fmt("Syntax error: %s\n", msg);
11159 error((char *)NULL);
11165 * called by editline -- any expansions to the prompt
11166 * should be added here.
11169 setprompt(int whichprompt)
11172 switch (whichprompt) {
11187 * Code for dealing with input/output redirection.
11190 #define EMPTY -2 /* marks an unused slot in redirtab */
11192 # define PIPESIZE 4096 /* amount of buffering in a pipe */
11194 # define PIPESIZE PIPE_BUF
11199 * Open a file in noclobber mode.
11200 * The code was copied from bash.
11203 noclobberopen(const char *fname)
11206 struct stat finfo, finfo2;
11209 * If the file exists and is a regular file, return an error
11212 r = stat(fname, &finfo);
11213 if (r == 0 && S_ISREG(finfo.st_mode)) {
11219 * If the file was not present (r != 0), make sure we open it
11220 * exclusively so that if it is created before we open it, our open
11221 * will fail. Make sure that we do not truncate an existing file.
11222 * Note that we don't turn on O_EXCL unless the stat failed -- if the
11223 * file was not a regular file, we leave O_EXCL off.
11226 return open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
11227 fd = open(fname, O_WRONLY|O_CREAT, 0666);
11229 /* If the open failed, return the file descriptor right away. */
11234 * OK, the open succeeded, but the file may have been changed from a
11235 * non-regular file to a regular file between the stat and the open.
11236 * We are assuming that the O_EXCL open handles the case where FILENAME
11237 * did not exist and is symlinked to an existing file between the stat
11242 * If we can open it and fstat the file descriptor, and neither check
11243 * revealed that it was a regular file, and the file has not been
11244 * replaced, return the file descriptor.
11246 if (fstat(fd, &finfo2) == 0 && !S_ISREG(finfo2.st_mode) &&
11247 finfo.st_dev == finfo2.st_dev && finfo.st_ino == finfo2.st_ino)
11250 /* The file has been replaced. badness. */
11257 * Handle here documents. Normally we fork off a process to write the
11258 * data to a pipe. If the document is short, we can stuff the data in
11259 * the pipe without forking.
11263 openhere(const union node *redir)
11269 error("Pipe call failed");
11270 if (redir->type == NHERE) {
11271 len = strlen(redir->nhere.doc->narg.text);
11272 if (len <= PIPESIZE) {
11273 xwrite(pip[1], redir->nhere.doc->narg.text, len);
11277 if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
11279 signal(SIGINT, SIG_IGN);
11280 signal(SIGQUIT, SIG_IGN);
11281 signal(SIGHUP, SIG_IGN);
11283 signal(SIGTSTP, SIG_IGN);
11285 signal(SIGPIPE, SIG_DFL);
11286 if (redir->type == NHERE)
11287 xwrite(pip[1], redir->nhere.doc->narg.text, len);
11289 expandhere(redir->nhere.doc, pip[1]);
11299 openredirect(const union node *redir)
11304 switch (redir->nfile.type) {
11306 fname = redir->nfile.expfname;
11307 if ((f = open(fname, O_RDONLY)) < 0)
11311 fname = redir->nfile.expfname;
11312 if ((f = open(fname, O_RDWR|O_CREAT|O_TRUNC, 0666)) < 0)
11316 /* Take care of noclobber mode. */
11318 fname = redir->nfile.expfname;
11319 if ((f = noclobberopen(fname)) < 0)
11324 fname = redir->nfile.expfname;
11326 if ((f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0)
11329 if ((f = creat(fname, 0666)) < 0)
11334 fname = redir->nfile.expfname;
11336 if ((f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666)) < 0)
11339 if ((f = open(fname, O_WRONLY)) < 0
11340 && (f = creat(fname, 0666)) < 0)
11342 lseek(f, (off_t)0, 2);
11349 /* Fall through to eliminate warning. */
11356 f = openhere(redir);
11362 error("cannot create %s: %s", fname, errmsg(errno, E_CREAT));
11364 error("cannot open %s: %s", fname, errmsg(errno, E_OPEN));
11369 * Process a list of redirection commands. If the REDIR_PUSH flag is set,
11370 * old file descriptors are stashed away so that the redirection can be
11371 * undone by calling popredir. If the REDIR_BACKQ flag is set, then the
11372 * standard output, and the standard error if it becomes a duplicate of
11377 redirect(union node *redir, int flags)
11380 struct redirtab *sv = NULL;
11385 int fd1dup = flags & REDIR_BACKQ;; /* stdout `cmd` redir to pipe */
11387 if (flags & REDIR_PUSH) {
11388 sv = ckmalloc(sizeof (struct redirtab));
11389 for (i = 0 ; i < 10 ; i++)
11390 sv->renamed[i] = EMPTY;
11391 sv->next = redirlist;
11394 for (n = redir ; n ; n = n->nfile.next) {
11397 if ((n->nfile.type == NTOFD || n->nfile.type == NFROMFD) &&
11398 n->ndup.dupfd == fd)
11399 continue; /* redirect from/to same file descriptor */
11402 newfd = openredirect(n);
11403 if ((flags & REDIR_PUSH) && sv->renamed[fd] == EMPTY) {
11406 } else if ((i = fcntl(fd, F_DUPFD, 10)) == -1) {
11410 dupredirect(n, newfd, fd1dup);
11420 error("%d: %m", fd);
11426 if (flags & REDIR_PUSH) {
11427 sv->renamed[fd] = i;
11430 } else if (fd != newfd) {
11436 dupredirect(n, newfd, fd1dup);
11443 dupredirect(const union node *redir, int f, int fd1dup)
11445 int fd = redir->nfile.fd;
11449 if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
11450 if (redir->ndup.dupfd >= 0) { /* if not ">&-" */
11451 if (redir->ndup.dupfd!=1 || fd1dup!=1)
11452 dup_as_newfd(redir->ndup.dupfd, fd);
11458 dup_as_newfd(f, fd);
11467 * Undo the effects of the last redirection.
11473 struct redirtab *rp = redirlist;
11477 for (i = 0 ; i < 10 ; i++) {
11478 if (rp->renamed[i] != EMPTY) {
11482 if (rp->renamed[i] >= 0) {
11483 dup_as_newfd(rp->renamed[i], i);
11484 close(rp->renamed[i]);
11488 redirlist = rp->next;
11494 * Discard all saved file descriptors.
11499 struct redirtab *rp;
11502 for (rp = redirlist ; rp ; rp = rp->next) {
11503 for (i = 0 ; i < 10 ; i++) {
11504 if (rp->renamed[i] >= 0) {
11505 close(rp->renamed[i]);
11507 rp->renamed[i] = EMPTY;
11514 * Copy a file descriptor to be >= to. Returns -1
11515 * if the source file descriptor is closed, EMPTY if there are no unused
11516 * file descriptors left.
11520 dup_as_newfd(from, to)
11526 newfd = fcntl(from, F_DUPFD, to);
11528 if (errno == EMFILE)
11531 error("%d: %m", from);
11537 static void shtree (union node *, int, char *, FILE*);
11538 static void shcmd (union node *, FILE *);
11539 static void sharg (union node *, FILE *);
11540 static void indent (int, char *, FILE *);
11541 static void trstring (char *);
11548 trputs("showtree called\n");
11549 shtree(n, 1, NULL, stdout);
11554 shtree(n, ind, pfx, fp)
11560 struct nodelist *lp;
11566 indent(ind, pfx, fp);
11577 shtree(n->nbinary.ch1, ind, NULL, fp);
11580 shtree(n->nbinary.ch2, ind, NULL, fp);
11588 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
11593 if (n->npipe.backgnd)
11599 fprintf(fp, "<node type %d>", n->type);
11619 for (np = cmd->ncmd.args ; np ; np = np->narg.next) {
11625 for (np = cmd->ncmd.redirect ; np ; np = np->nfile.next) {
11631 if ((np->nfile.type <= NFROMFD) && (np->nfile.type >= NTO)) {
11632 s = redir_strings[np->nfile.type - NTO];
11638 switch (np->nfile.type) {
11639 case NTO: s = ">"; dftfd = 1; break;
11640 case NAPPEND: s = ">>"; dftfd = 1; break;
11641 case NTOFD: s = ">&"; dftfd = 1; break;
11642 case NTOOV: s = ">|"; dftfd = 1; break;
11643 case NFROM: s = "<"; dftfd = 0; break;
11644 case NFROMFD: s = "<&"; dftfd = 0; break;
11645 case NFROMTO: s = "<>"; dftfd = 0; break;
11646 default: s = "*error*"; dftfd = 0; break;
11649 if (np->nfile.fd != dftfd)
11650 fprintf(fp, "%d", np->nfile.fd);
11652 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
11653 fprintf(fp, "%d", np->ndup.dupfd);
11655 sharg(np->nfile.fname, fp);
11669 struct nodelist *bqlist;
11672 if (arg->type != NARG) {
11673 printf("<node type %d>\n", arg->type);
11677 bqlist = arg->narg.backquote;
11678 for (p = arg->narg.text ; *p ; p++) {
11687 if (subtype == VSLENGTH)
11693 if (subtype & VSNUL)
11696 switch (subtype & VSTYPE) {
11715 case VSTRIMLEFTMAX:
11722 case VSTRIMRIGHTMAX:
11729 printf("<subtype %d>", subtype);
11736 case CTLBACKQ|CTLQUOTE:
11739 shtree(bqlist->n, -1, NULL, fp);
11751 indent(amount, pfx, fp)
11758 for (i = 0 ; i < amount ; i++) {
11759 if (pfx && i == amount - 1)
11777 static int debug = 1;
11779 static int debug = 0;
11787 if (tracefile == NULL)
11789 putc(c, tracefile);
11795 trace(const char *fmt, ...)
11799 if (tracefile != NULL) {
11800 (void) vfprintf(tracefile, fmt, va);
11801 if (strchr(fmt, '\n'))
11802 (void) fflush(tracefile);
11812 if (tracefile == NULL)
11814 fputs(s, tracefile);
11815 if (strchr(s, '\n'))
11827 if (tracefile == NULL)
11829 putc('"', tracefile);
11830 for (p = s ; *p ; p++) {
11832 case '\n': c = 'n'; goto backslash;
11833 case '\t': c = 't'; goto backslash;
11834 case '\r': c = 'r'; goto backslash;
11835 case '"': c = '"'; goto backslash;
11836 case '\\': c = '\\'; goto backslash;
11837 case CTLESC: c = 'e'; goto backslash;
11838 case CTLVAR: c = 'v'; goto backslash;
11839 case CTLVAR+CTLQUOTE: c = 'V'; goto backslash;
11840 case CTLBACKQ: c = 'q'; goto backslash;
11841 case CTLBACKQ+CTLQUOTE: c = 'Q'; goto backslash;
11842 backslash: putc('\\', tracefile);
11843 putc(c, tracefile);
11846 if (*p >= ' ' && *p <= '~')
11847 putc(*p, tracefile);
11849 putc('\\', tracefile);
11850 putc(*p >> 6 & 03, tracefile);
11851 putc(*p >> 3 & 07, tracefile);
11852 putc(*p & 07, tracefile);
11857 putc('"', tracefile);
11865 if (tracefile == NULL)
11870 putc(' ', tracefile);
11872 putc('\n', tracefile);
11887 #ifdef not_this_way
11890 if ((p = getenv("HOME")) == NULL) {
11891 if (geteuid() == 0)
11897 strcat(s, "/trace");
11900 strcpy(s, "./trace");
11901 #endif /* not_this_way */
11902 if ((tracefile = fopen(s, "a")) == NULL) {
11903 fprintf(stderr, "Can't open %s\n", s);
11907 if ((flags = fcntl(fileno(tracefile), F_GETFL, 0)) >= 0)
11908 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
11910 fputs("\nTracing started.\n", tracefile);
11917 * The trap builtin.
11921 trapcmd(argc, argv)
11930 for (signo = 0 ; signo < NSIG ; signo++) {
11931 if (trap[signo] != NULL) {
11935 p = single_quote(trap[signo]);
11936 sn = sys_siglist[signo];
11938 sn = u_signal_names(0, &signo, 0);
11941 printf("trap -- %s %s\n", p, sn);
11953 if ((signo = decode_signal(*ap, 0)) < 0)
11954 error("%s: bad trap", *ap);
11957 if (action[0] == '-' && action[1] == '\0')
11960 action = savestr(action);
11963 ckfree(trap[signo]);
11964 trap[signo] = action;
11979 * Set the signal handler for the specified signal. The routine figures
11980 * out what it should be set to.
11984 setsignal(int signo)
11988 struct sigaction act;
11990 if ((t = trap[signo]) == NULL)
11992 else if (*t != '\0')
11996 if (rootshell && action == S_DFL) {
11999 if (iflag || minusc || sflag == 0)
12025 t = &sigmode[signo - 1];
12028 * current setting unknown
12030 if (sigaction(signo, 0, &act) == -1) {
12032 * Pretend it worked; maybe we should give a warning
12033 * here, but other shells don't. We don't alter
12034 * sigmode, so that we retry every time.
12038 if (act.sa_handler == SIG_IGN) {
12039 if (mflag && (signo == SIGTSTP ||
12040 signo == SIGTTIN || signo == SIGTTOU)) {
12041 *t = S_IGN; /* don't hard ignore these */
12045 *t = S_RESET; /* force to be set */
12048 if (*t == S_HARD_IGN || *t == action)
12050 act.sa_handler = ((action == S_CATCH) ? onsig
12051 : ((action == S_IGN) ? SIG_IGN : SIG_DFL));
12054 sigemptyset(&act.sa_mask);
12055 sigaction(signo, &act, 0);
12066 if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
12067 signal(signo, SIG_IGN);
12069 sigmode[signo - 1] = S_HARD_IGN;
12080 if (signo == SIGINT && trap[SIGINT] == NULL) {
12084 gotsig[signo - 1] = 1;
12090 * Called to execute a trap. Perhaps we should avoid entering new trap
12091 * handlers while we are executing a trap handler.
12101 for (i = 1 ; ; i++) {
12108 savestatus=exitstatus;
12109 evalstring(trap[i], 0);
12110 exitstatus=savestatus;
12117 * Called to exit the shell.
12121 exitshell(int status)
12123 struct jmploc loc1, loc2;
12126 TRACE(("exitshell(%d) pid=%d\n", status, getpid()));
12127 if (setjmp(loc1.loc)) {
12130 if (setjmp(loc2.loc)) {
12134 if ((p = trap[0]) != NULL && *p != '\0') {
12138 l1: handler = &loc2; /* probably unnecessary */
12147 static int decode_signal(const char *string, int minsig)
12150 const char *name = u_signal_names(string, &signo, minsig);
12152 return name ? signo : -1;
12155 static struct var **hashvar (const char *);
12156 static void showvars (const char *, int, int);
12157 static struct var **findvar (struct var **, const char *);
12160 * Initialize the varable symbol tables and import the environment
12164 * This routine initializes the builtin variables. It is called when the
12165 * shell is initialized and again when a shell procedure is spawned.
12170 const struct varinit *ip;
12174 for (ip = varinit ; (vp = ip->var) != NULL ; ip++) {
12175 if ((vp->flags & VEXPORT) == 0) {
12176 vpp = hashvar(ip->text);
12179 vp->text = strdup(ip->text);
12180 vp->flags = ip->flags;
12181 vp->func = ip->func;
12185 * PS1 depends on uid
12187 if ((vps1.flags & VEXPORT) == 0) {
12188 vpp = hashvar("PS1=");
12191 vps1.text = strdup(geteuid() ? "PS1=$ " : "PS1=# ");
12192 vps1.flags = VSTRFIXED|VTEXTFIXED;
12197 * Set the value of a variable. The flags argument is ored with the
12198 * flags of the variable. If val is NULL, the variable is unset.
12202 setvar(name, val, flags)
12203 const char *name, *val;
12219 if (! is_in_name(*p)) {
12220 if (*p == '\0' || *p == '=')
12226 namelen = p - name;
12228 error("%.*s: bad variable name", namelen, name);
12229 len = namelen + 2; /* 2 is space for '=' and '\0' */
12233 len += vallen = strlen(val);
12236 nameeq = ckmalloc(len);
12237 memcpy(nameeq, name, namelen);
12238 nameeq[namelen] = '=';
12240 memcpy(nameeq + namelen + 1, val, vallen + 1);
12242 nameeq[namelen + 1] = '\0';
12244 setvareq(nameeq, flags);
12251 * Same as setvar except that the variable and value are passed in
12252 * the first argument as name=value. Since the first argument will
12253 * be actually stored in the table, it should not be a string that
12262 struct var *vp, **vpp;
12265 flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
12266 if ((vp = *findvar(vpp, s))) {
12267 if (vp->flags & VREADONLY) {
12268 size_t len = strchr(s, '=') - s;
12269 error("%.*s: is read only", len, s);
12273 if (vp->func && (flags & VNOFUNC) == 0)
12274 (*vp->func)(strchr(s, '=') + 1);
12276 if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
12279 vp->flags &= ~(VTEXTFIXED|VSTACK|VUNSET);
12280 vp->flags |= flags;
12284 * We could roll this to a function, to handle it as
12285 * a regular variable function callback, but why bother?
12287 if (iflag && (vp == &vmpath || (vp == &vmail && !mpathset())))
12293 vp = ckmalloc(sizeof (*vp));
12304 * Process a linked list of variable assignments.
12309 struct strlist *mylist;
12311 struct strlist *lp;
12314 for (lp = mylist ; lp ; lp = lp->next) {
12315 setvareq(savestr(lp->text), 0);
12323 * Find the value of a variable. Returns NULL if not set.
12326 static const char *
12332 if ((v = *findvar(hashvar(name), name)) && !(v->flags & VUNSET)) {
12333 return strchr(v->text, '=') + 1;
12341 * Search the environment of a builtin command.
12344 static const char *
12345 bltinlookup(const char *name)
12347 const struct strlist *sp;
12349 for (sp = cmdenviron ; sp ; sp = sp->next) {
12350 if (varequal(sp->text, name))
12351 return strchr(sp->text, '=') + 1;
12353 return lookupvar(name);
12359 * Generate a list of exported variables. This routine is used to construct
12360 * the third argument to execve when executing a program.
12372 for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
12373 for (vp = *vpp ; vp ; vp = vp->next)
12374 if (vp->flags & VEXPORT)
12377 ep = env = stalloc((nenv + 1) * sizeof *env);
12378 for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
12379 for (vp = *vpp ; vp ; vp = vp->next)
12380 if (vp->flags & VEXPORT)
12389 * Called when a shell procedure is invoked to clear out nonexported
12390 * variables. It is also necessary to reallocate variables of with
12391 * VSTACK set since these are currently allocated on the stack.
12397 struct var *vp, **prev;
12399 for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
12400 for (prev = vpp ; (vp = *prev) != NULL ; ) {
12401 if ((vp->flags & VEXPORT) == 0) {
12403 if ((vp->flags & VTEXTFIXED) == 0)
12405 if ((vp->flags & VSTRFIXED) == 0)
12408 if (vp->flags & VSTACK) {
12409 vp->text = savestr(vp->text);
12410 vp->flags &=~ VSTACK;
12422 * Command to list all variables which are set. Currently this command
12423 * is invoked from the set command when the set command is called without
12428 showvarscmd(argc, argv)
12432 showvars(nullstr, VUNSET, VUNSET);
12439 * The export and readonly commands.
12443 exportcmd(argc, argv)
12450 int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT;
12453 listsetvar(cmdenviron);
12454 pflag = (nextopt("p") == 'p');
12455 if (argc > 1 && !pflag) {
12456 while ((name = *argptr++) != NULL) {
12457 if ((p = strchr(name, '=')) != NULL) {
12460 if ((vp = *findvar(hashvar(name), name))) {
12465 setvar(name, p, flag);
12469 showvars(argv[0], flag, 0);
12476 * The "local" command.
12479 /* funcnest nonzero if we are currently evaluating a function */
12482 localcmd(argc, argv)
12489 error("Not in a function");
12490 while ((name = *argptr++) != NULL) {
12498 * Make a variable a local variable. When a variable is made local, it's
12499 * value and flags are saved in a localvar structure. The saved values
12500 * will be restored when the shell function returns. We handle the name
12501 * "-" as a special case.
12508 struct localvar *lvp;
12513 lvp = ckmalloc(sizeof (struct localvar));
12514 if (name[0] == '-' && name[1] == '\0') {
12516 p = ckmalloc(sizeof optet_vals);
12517 lvp->text = memcpy(p, optet_vals, sizeof optet_vals);
12520 vpp = hashvar(name);
12521 vp = *findvar(vpp, name);
12523 if (strchr(name, '='))
12524 setvareq(savestr(name), VSTRFIXED);
12526 setvar(name, NULL, VSTRFIXED);
12527 vp = *vpp; /* the new variable */
12529 lvp->flags = VUNSET;
12531 lvp->text = vp->text;
12532 lvp->flags = vp->flags;
12533 vp->flags |= VSTRFIXED|VTEXTFIXED;
12534 if (strchr(name, '='))
12535 setvareq(savestr(name), 0);
12539 lvp->next = localvars;
12546 * Called after a function returns.
12551 struct localvar *lvp;
12554 while ((lvp = localvars) != NULL) {
12555 localvars = lvp->next;
12557 if (vp == NULL) { /* $- saved */
12558 memcpy(optet_vals, lvp->text, sizeof optet_vals);
12560 } else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
12561 (void)unsetvar(vp->text);
12563 if ((vp->flags & VTEXTFIXED) == 0)
12565 vp->flags = lvp->flags;
12566 vp->text = lvp->text;
12574 setvarcmd(argc, argv)
12579 return unsetcmd(argc, argv);
12580 else if (argc == 3)
12581 setvar(argv[1], argv[2], 0);
12583 error("List assignment not implemented");
12589 * The unset builtin command. We unset the function before we unset the
12590 * variable to allow a function to be unset when there is a readonly variable
12591 * with the same name.
12595 unsetcmd(argc, argv)
12605 while ((i = nextopt("vf")) != '\0') {
12611 if (flg_func == 0 && flg_var == 0)
12614 for (ap = argptr; *ap ; ap++) {
12618 ret |= unsetvar(*ap);
12625 * Unset the specified variable.
12629 unsetvar(const char *s)
12634 vpp = findvar(hashvar(s), s);
12637 if (vp->flags & VREADONLY)
12640 if (*(strchr(vp->text, '=') + 1) != '\0')
12641 setvar(s, nullstr, 0);
12642 vp->flags &= ~VEXPORT;
12643 vp->flags |= VUNSET;
12644 if ((vp->flags & VSTRFIXED) == 0) {
12645 if ((vp->flags & VTEXTFIXED) == 0)
12660 * Find the appropriate entry in the hash table from the name.
12663 static struct var **
12664 hashvar(const char *p)
12666 unsigned int hashval;
12668 hashval = ((unsigned char) *p) << 4;
12669 while (*p && *p != '=')
12670 hashval += (unsigned char) *p++;
12671 return &vartab[hashval % VTABSIZE];
12677 * Returns true if the two strings specify the same varable. The first
12678 * variable name is terminated by '='; the second may be terminated by
12679 * either '=' or '\0'.
12683 varequal(const char *p, const char *q)
12685 while (*p == *q++) {
12689 if (*p == '=' && *(q - 1) == '\0')
12695 showvars(const char *myprefix, int mask, int xor)
12699 const char *sep = myprefix == nullstr ? myprefix : spcstr;
12701 for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
12702 for (vp = *vpp ; vp ; vp = vp->next) {
12703 if ((vp->flags & mask) ^ xor) {
12707 p = strchr(vp->text, '=') + 1;
12708 len = p - vp->text;
12709 p = single_quote(p);
12711 printf("%s%s%.*s%s\n", myprefix, sep, len,
12719 static struct var **
12720 findvar(struct var **vpp, const char *name)
12722 for (; *vpp; vpp = &(*vpp)->next) {
12723 if (varequal((*vpp)->text, name)) {
12731 * Copyright (c) 1999 Herbert Xu <herbert@debian.org>
12732 * This file contains code for the times builtin.
12733 * $Id: ash.c,v 1.29 2001/10/24 05:00:16 andersen Exp $
12735 static int timescmd (int argc, char **argv)
12738 long int clk_tck = sysconf(_SC_CLK_TCK);
12741 printf("%dm%fs %dm%fs\n%dm%fs %dm%fs\n",
12742 (int) (buf.tms_utime / clk_tck / 60),
12743 ((double) buf.tms_utime) / clk_tck,
12744 (int) (buf.tms_stime / clk_tck / 60),
12745 ((double) buf.tms_stime) / clk_tck,
12746 (int) (buf.tms_cutime / clk_tck / 60),
12747 ((double) buf.tms_cutime) / clk_tck,
12748 (int) (buf.tms_cstime / clk_tck / 60),
12749 ((double) buf.tms_cstime) / clk_tck);
12753 #ifdef ASH_MATH_SUPPORT
12754 /* The let builtin. */
12755 int letcmd(int argc, char **argv)
12760 char *tmp, *expression, p[13];
12761 expression = strchr(argv[1], '=');
12763 /* Cannot use 'error()' here, or the return code
12764 * will be incorrect */
12765 out2fmt("sh: let: syntax error: \"%s\"\n", argv[1]);
12768 *expression = '\0';
12769 tmp = ++expression;
12770 result = arith(tmp, &errcode);
12772 /* Cannot use 'error()' here, or the return code
12773 * will be incorrect */
12774 out2fmt("sh: let: ");
12776 out2fmt("divide by zero");
12778 out2fmt("syntax error: \"%s=%s\"\n", argv[1], expression);
12781 snprintf(p, 12, "%ld", result);
12782 setvar(argv[1], savestr(p), 0);
12783 } else if (argc >= 3)
12784 synerror("invalid operand");
12792 * Copyright (c) 1989, 1991, 1993, 1994
12793 * The Regents of the University of California. All rights reserved.
12795 * This code is derived from software contributed to Berkeley by
12796 * Kenneth Almquist.
12798 * Redistribution and use in source and binary forms, with or without
12799 * modification, are permitted provided that the following conditions
12801 * 1. Redistributions of source code must retain the above copyright
12802 * notice, this list of conditions and the following disclaimer.
12803 * 2. Redistributions in binary form must reproduce the above copyright
12804 * notice, this list of conditions and the following disclaimer in the
12805 * documentation and/or other materials provided with the distribution.
12807 * 3. <BSD Advertising Clause omitted per the July 22, 1999 licensing change
12808 * ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change>
12810 * 4. Neither the name of the University nor the names of its contributors
12811 * may be used to endorse or promote products derived from this software
12812 * without specific prior written permission.
12814 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
12815 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
12816 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
12817 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
12818 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
12819 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
12820 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
12821 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
12822 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
12823 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF