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 option needs some work, since it
55 * doesn't compile right now... */
56 #undef 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... */
100 #include <sys/stat.h>
101 #include <sys/cdefs.h>
102 #include <sys/ioctl.h>
103 #include <sys/param.h>
104 #include <sys/resource.h>
105 #include <sys/time.h>
106 #include <sys/times.h>
107 #include <sys/types.h>
108 #include <sys/wait.h>
111 #if !defined(FNMATCH_BROKEN)
114 #if !defined(GLOB_BROKEN)
126 * This file was generated by the mksyntax program.
130 #define CWORD 0 /* character is nothing special */
131 #define CNL 1 /* newline character */
132 #define CBACK 2 /* a backslash character */
133 #define CSQUOTE 3 /* single quote */
134 #define CDQUOTE 4 /* double quote */
135 #define CENDQUOTE 5 /* a terminating quote */
136 #define CBQUOTE 6 /* backwards single quote */
137 #define CVAR 7 /* a dollar sign */
138 #define CENDVAR 8 /* a '}' character */
139 #define CLP 9 /* a left paren in arithmetic */
140 #define CRP 10 /* a right paren in arithmetic */
141 #define CENDFILE 11 /* end of file */
142 #define CCTL 12 /* like CWORD, except it must be escaped */
143 #define CSPCL 13 /* these terminate a word */
144 #define CIGN 14 /* character should be ignored */
146 /* Syntax classes for is_ functions */
147 #define ISDIGIT 01 /* a digit */
148 #define ISUPPER 02 /* an upper case letter */
149 #define ISLOWER 04 /* a lower case letter */
150 #define ISUNDER 010 /* an underscore */
151 #define ISSPECL 020 /* the name of a special parameter */
168 #define TENDBQUOTE 10
190 #define BASESYNTAX (basesyntax + SYNBASE)
191 #define DQSYNTAX (dqsyntax + SYNBASE)
192 #define SQSYNTAX (sqsyntax + SYNBASE)
193 #define ARISYNTAX (arisyntax + SYNBASE)
195 /* control characters in argument strings */
196 #define CTLESC '\201'
197 #define CTLVAR '\202'
198 #define CTLENDVAR '\203'
199 #define CTLBACKQ '\204'
200 #define CTLQUOTE 01 /* ored with CTLBACKQ code if in quotes */
201 /* CTLBACKQ | CTLQUOTE == '\205' */
202 #define CTLARI '\206'
203 #define CTLENDARI '\207'
204 #define CTLQUOTEMARK '\210'
206 #define is_digit(c) ((c)>='0' && (c)<='9')
207 #define is_alpha(c) (((c) < CTLESC || (c) > CTLENDARI) && isalpha((unsigned char) (c)))
208 #define is_name(c) (((c) < CTLESC || (c) > CTLENDARI) && ((c) == '_' || isalpha((unsigned char) (c))))
209 #define is_in_name(c) (((c) < CTLESC || (c) > CTLENDARI) && ((c) == '_' || isalnum((unsigned char) (c))))
210 #define is_special(c) ((is_type+SYNBASE)[c] & (ISSPECL|ISDIGIT))
211 #define digit_val(c) ((c) - '0')
214 #define _DIAGASSERT(x)
218 #define S_DFL 1 /* default signal handling (SIG_DFL) */
219 #define S_CATCH 2 /* signal is caught */
220 #define S_IGN 3 /* signal is ignored (SIG_IGN) */
221 #define S_HARD_IGN 4 /* signal is ignored permenantly */
222 #define S_RESET 5 /* temporary - to reset a hard ignored sig */
225 /* variable substitution byte (follows CTLVAR) */
226 #define VSTYPE 0x0f /* type of variable substitution */
227 #define VSNUL 0x10 /* colon--treat the empty string as unset */
228 #define VSQUOTE 0x80 /* inside double quotes--suppress splitting */
230 /* values of VSTYPE field */
231 #define VSNORMAL 0x1 /* normal variable: $var or ${var} */
232 #define VSMINUS 0x2 /* ${var-text} */
233 #define VSPLUS 0x3 /* ${var+text} */
234 #define VSQUESTION 0x4 /* ${var?message} */
235 #define VSASSIGN 0x5 /* ${var=text} */
236 #define VSTRIMLEFT 0x6 /* ${var#pattern} */
237 #define VSTRIMLEFTMAX 0x7 /* ${var##pattern} */
238 #define VSTRIMRIGHT 0x8 /* ${var%pattern} */
239 #define VSTRIMRIGHTMAX 0x9 /* ${var%%pattern} */
240 #define VSLENGTH 0xa /* ${#var} */
242 /* flags passed to redirect */
243 #define REDIR_PUSH 01 /* save previous values of file descriptors */
244 #define REDIR_BACKQ 02 /* save the command output to pipe */
247 * BSD setjmp saves the signal mask, which violates ANSI C and takes time,
248 * so we use _setjmp instead.
252 #define setjmp(jmploc) _setjmp(jmploc)
253 #define longjmp(jmploc, val) _longjmp(jmploc, val)
257 * Most machines require the value returned from malloc to be aligned
258 * in some way. The following macro will get this right on many machines.
267 #define ALIGN(nbytes) (((nbytes) + sizeof(union align) - 1) & ~(sizeof(union align) - 1))
270 #ifdef BB_LOCALE_SUPPORT
272 static void change_lc_all(const char *value);
273 static void change_lc_ctype(const char *value);
277 * These macros allow the user to suspend the handling of interrupt signals
278 * over a period of time. This is similar to SIGHOLD to or sigblock, but
279 * much more efficient and portable. (But hacking the kernel is so much
280 * more fun than worrying about efficiency and portability. :-))
283 static void onint (void);
284 static volatile int suppressint;
285 static volatile int intpending;
287 #define INTOFF suppressint++
288 #ifndef ASH_OPTIMIZE_FOR_SIZE
289 #define INTON { if (--suppressint == 0 && intpending) onint(); }
290 #define FORCEINTON {suppressint = 0; if (intpending) onint();}
292 static void __inton (void);
293 static void forceinton (void);
294 #define INTON __inton()
295 #define FORCEINTON forceinton()
298 #define CLEAR_PENDING_INT intpending = 0
299 #define int_pending() intpending
302 typedef void *pointer;
304 #define NULL (void *)0
307 static inline pointer ckmalloc (int sz) { return xmalloc(sz); }
308 static inline pointer ckrealloc(void *p, int sz) { return xrealloc(p, sz); }
309 static inline char * savestr (const char *s) { return xstrdup(s); }
311 static pointer stalloc (int);
312 static void stunalloc (pointer);
313 static void ungrabstackstr (char *, char *);
314 static char * growstackstr(void);
315 static char * makestrspace(size_t newlen);
316 static char *sstrdup (const char *);
319 * Parse trees for commands are allocated in lifo order, so we use a stack
320 * to make this more efficient, and also to avoid all sorts of exception
321 * handling code to handle interrupts in the middle of a parse.
323 * The size 504 was chosen because the Ultrix malloc handles that size
327 #define MINSIZE 504 /* minimum size of a block */
331 struct stack_block *prev;
335 static struct stack_block stackbase;
336 static struct stack_block *stackp = &stackbase;
337 static struct stackmark *markp;
338 static char *stacknxt = stackbase.space;
339 static int stacknleft = MINSIZE;
342 #define equal(s1, s2) (strcmp(s1, s2) == 0)
344 #define stackblock() stacknxt
345 #define stackblocksize() stacknleft
346 #define STARTSTACKSTR(p) p = stackblock(), sstrnleft = stackblocksize()
348 #define STPUTC(c, p) (--sstrnleft >= 0? (*p++ = (c)) : (p = growstackstr(), *p++ = (c)))
349 #define CHECKSTRSPACE(n, p) { if (sstrnleft < n) p = makestrspace(n); }
350 #define STACKSTRNUL(p) (sstrnleft == 0? (p = growstackstr(), *p = '\0') : (*p = '\0'))
353 #define USTPUTC(c, p) (--sstrnleft, *p++ = (c))
354 #define STUNPUTC(p) (++sstrnleft, --p)
355 #define STTOPC(p) p[-1]
356 #define STADJUST(amount, p) (p += (amount), sstrnleft -= (amount))
357 #define grabstackstr(p) stalloc(stackblocksize() - sstrnleft)
359 #define ckfree(p) free((pointer)(p))
363 #define TRACE(param) trace param
364 static void trace (const char *, ...);
365 static void trargs (char **);
366 static void showtree (union node *);
367 static void trputc (int);
368 static void trputs (const char *);
369 static void opentrace (void);
404 #define EXP_FULL 0x1 /* perform word splitting & file globbing */
405 #define EXP_TILDE 0x2 /* do normal tilde expansion */
406 #define EXP_VARTILDE 0x4 /* expand tildes in an assignment */
407 #define EXP_REDIR 0x8 /* file glob for a redirection (1 match only) */
408 #define EXP_CASE 0x10 /* keeps quotes around for CASE pattern */
409 #define EXP_RECORD 0x20 /* need to record arguments for ifs breakup */
414 static char optet_vals[NOPTS];
416 static const char * const optlist[NOPTS] = {
435 #define optent_name(optent) (optent+1)
436 #define optent_letter(optent) optent[0]
437 #define optent_val(optent) optet_vals[optent]
439 #define eflag optent_val(0)
440 #define fflag optent_val(1)
441 #define Iflag optent_val(2)
442 #define iflag optent_val(3)
443 #define mflag optent_val(4)
444 #define nflag optent_val(5)
445 #define sflag optent_val(6)
446 #define xflag optent_val(7)
447 #define vflag optent_val(8)
448 #define Vflag optent_val(9)
449 #define Eflag optent_val(10)
450 #define Cflag optent_val(11)
451 #define aflag optent_val(12)
452 #define bflag optent_val(13)
453 #define uflag optent_val(14)
454 #define qflag optent_val(15)
457 /* Mode argument to forkshell. Don't change FORK_FG or FORK_BG. */
475 union node *redirect;
482 struct nodelist *cmdlist;
489 union node *redirect;
497 union node *elsepart;
528 struct nodelist *backquote;
566 struct nbinary nbinary;
569 struct nredir nredir;
573 struct nclist nclist;
583 struct nodelist *next;
587 struct backcmd { /* result of evalbackcmd */
588 int fd; /* file descriptor to read from */
589 char *buf; /* buffer */
590 int nleft; /* number of chars in buffer */
591 struct job *jp; /* job structure for command */
599 const struct builtincmd *cmd;
604 struct strlist *next;
610 struct strlist *list;
611 struct strlist **lastp;
615 struct strpush *prev; /* preceding string on stack */
619 struct alias *ap; /* if push was associated with an alias */
621 char *string; /* remember the string since it may change */
625 struct parsefile *prev; /* preceding file on stack */
626 int linno; /* current line */
627 int fd; /* file descriptor (or -1 if string) */
628 int nleft; /* number of chars left in this line */
629 int lleft; /* number of chars left in this buffer */
630 char *nextc; /* next char in buffer */
631 char *buf; /* input buffer */
632 struct strpush *strpush; /* for pushing strings at this level */
633 struct strpush basestrpush; /* so pushing one is fast */
637 struct stack_block *stackp;
640 struct stackmark *marknext;
644 int nparam; /* # of positional parameters (without $0) */
645 unsigned char malloc; /* if parameter list dynamically allocated */
646 char **p; /* parameter list */
647 int optind; /* next parameter to be processed by getopts */
648 int optoff; /* used by getopts */
652 * When commands are first encountered, they are entered in a hash table.
653 * This ensures that a full path search will not have to be done for them
654 * on each invocation.
656 * We should investigate converting to a linear search, even though that
657 * would make the command name "hash" a misnomer.
659 #define CMDTABLESIZE 31 /* should be prime */
660 #define ARB 1 /* actual size determined at run time */
665 struct tblentry *next; /* next entry in hash chain */
666 union param param; /* definition of builtin function */
667 short cmdtype; /* index identifying command */
668 char rehash; /* if set, cd done since entry created */
669 char cmdname[ARB]; /* name of command */
673 static struct tblentry *cmdtable[CMDTABLESIZE];
674 static int builtinloc = -1; /* index in path of %builtin, or -1 */
675 static int exerrno = 0; /* Last exec error */
678 static void tryexec (char *, char **, char **);
679 static void printentry (struct tblentry *, int);
680 static void clearcmdentry (int);
681 static struct tblentry *cmdlookup (const char *, int);
682 static void delete_cmd_entry (void);
683 static int path_change (const char *, int *);
686 static void flushall (void);
687 static void out2fmt (const char *, ...)
688 __attribute__((__format__(__printf__,1,2)));
689 static int xwrite (int, const char *, int);
691 static void outstr (const char *p, FILE *file) { fputs(p, file); }
692 static void out1str(const char *p) { outstr(p, stdout); }
693 static void out2str(const char *p) { outstr(p, stderr); }
695 #ifndef ASH_OPTIMIZE_FOR_SIZE
696 #define out2c(c) putc((c), stderr)
698 static void out2c(int c) { putc(c, stderr); }
701 /* syntax table used when not in quotes */
702 static const char basesyntax[257] = {
703 CENDFILE, CSPCL, CWORD, CCTL,
704 CCTL, CCTL, CCTL, CCTL,
705 CCTL, CCTL, CCTL, CWORD,
706 CWORD, CWORD, CWORD, CWORD,
707 CWORD, CWORD, CWORD, CWORD,
708 CWORD, CWORD, CWORD, CWORD,
709 CWORD, CWORD, CWORD, CWORD,
710 CWORD, CWORD, CWORD, CWORD,
711 CWORD, CWORD, CWORD, CWORD,
712 CWORD, CWORD, CWORD, CWORD,
713 CWORD, CWORD, CWORD, CWORD,
714 CWORD, CWORD, CWORD, CWORD,
715 CWORD, CWORD, CWORD, CWORD,
716 CWORD, CWORD, CWORD, CWORD,
717 CWORD, CWORD, CWORD, CWORD,
718 CWORD, CWORD, CWORD, CWORD,
719 CWORD, CWORD, CWORD, CWORD,
720 CWORD, CWORD, CWORD, CWORD,
721 CWORD, CWORD, CWORD, CWORD,
722 CWORD, CWORD, CWORD, CWORD,
723 CWORD, CWORD, CWORD, CWORD,
724 CWORD, CWORD, CWORD, CWORD,
725 CWORD, CWORD, CWORD, CWORD,
726 CWORD, CWORD, CWORD, CWORD,
727 CWORD, CWORD, CWORD, CWORD,
728 CWORD, CWORD, CWORD, CWORD,
729 CWORD, CWORD, CWORD, CWORD,
730 CWORD, CWORD, CWORD, CWORD,
731 CWORD, CWORD, CWORD, CWORD,
732 CWORD, CWORD, CWORD, CWORD,
733 CWORD, CWORD, CWORD, CWORD,
734 CWORD, CWORD, CWORD, CWORD,
735 CWORD, CWORD, CWORD, CWORD,
736 CWORD, CWORD, CWORD, CWORD,
737 CWORD, CWORD, CWORD, CSPCL,
738 CNL, CWORD, CWORD, CWORD,
739 CWORD, CWORD, CWORD, CWORD,
740 CWORD, CWORD, CWORD, CWORD,
741 CWORD, CWORD, CWORD, CWORD,
742 CWORD, CWORD, CWORD, CWORD,
743 CWORD, CWORD, CSPCL, CWORD,
744 CDQUOTE, CWORD, CVAR, CWORD,
745 CSPCL, CSQUOTE, CSPCL, CSPCL,
746 CWORD, CWORD, CWORD, CWORD,
747 CWORD, CWORD, CWORD, CWORD,
748 CWORD, CWORD, CWORD, CWORD,
749 CWORD, CWORD, CWORD, CWORD,
750 CWORD, CSPCL, CSPCL, CWORD,
751 CSPCL, CWORD, CWORD, CWORD,
752 CWORD, CWORD, CWORD, CWORD,
753 CWORD, CWORD, CWORD, CWORD,
754 CWORD, CWORD, CWORD, CWORD,
755 CWORD, CWORD, CWORD, CWORD,
756 CWORD, CWORD, CWORD, CWORD,
757 CWORD, CWORD, CWORD, CWORD,
758 CWORD, CWORD, CBACK, CWORD,
759 CWORD, CWORD, CBQUOTE, CWORD,
760 CWORD, CWORD, CWORD, CWORD,
761 CWORD, CWORD, CWORD, CWORD,
762 CWORD, CWORD, CWORD, CWORD,
763 CWORD, CWORD, CWORD, CWORD,
764 CWORD, CWORD, CWORD, CWORD,
765 CWORD, CWORD, CWORD, CWORD,
766 CWORD, CWORD, CSPCL, CENDVAR,
770 /* syntax table used when in double quotes */
771 static const char dqsyntax[257] = {
772 CENDFILE, CIGN, CWORD, CCTL,
773 CCTL, CCTL, CCTL, CCTL,
774 CCTL, CCTL, CCTL, CWORD,
775 CWORD, CWORD, CWORD, CWORD,
776 CWORD, CWORD, CWORD, CWORD,
777 CWORD, CWORD, CWORD, CWORD,
778 CWORD, CWORD, CWORD, CWORD,
779 CWORD, CWORD, CWORD, CWORD,
780 CWORD, CWORD, CWORD, CWORD,
781 CWORD, CWORD, CWORD, CWORD,
782 CWORD, CWORD, CWORD, CWORD,
783 CWORD, CWORD, CWORD, CWORD,
784 CWORD, CWORD, CWORD, CWORD,
785 CWORD, CWORD, CWORD, CWORD,
786 CWORD, CWORD, CWORD, CWORD,
787 CWORD, CWORD, CWORD, CWORD,
788 CWORD, CWORD, CWORD, CWORD,
789 CWORD, CWORD, CWORD, CWORD,
790 CWORD, CWORD, CWORD, CWORD,
791 CWORD, CWORD, CWORD, CWORD,
792 CWORD, CWORD, CWORD, CWORD,
793 CWORD, CWORD, CWORD, CWORD,
794 CWORD, CWORD, CWORD, CWORD,
795 CWORD, CWORD, CWORD, CWORD,
796 CWORD, CWORD, CWORD, CWORD,
797 CWORD, CWORD, CWORD, CWORD,
798 CWORD, CWORD, CWORD, CWORD,
799 CWORD, CWORD, CWORD, CWORD,
800 CWORD, CWORD, CWORD, CWORD,
801 CWORD, CWORD, CWORD, CWORD,
802 CWORD, CWORD, CWORD, CWORD,
803 CWORD, CWORD, CWORD, CWORD,
804 CWORD, CWORD, CWORD, CWORD,
805 CWORD, CWORD, CWORD, CWORD,
806 CWORD, CWORD, CWORD, CWORD,
807 CNL, CWORD, CWORD, CWORD,
808 CWORD, CWORD, CWORD, CWORD,
809 CWORD, CWORD, CWORD, CWORD,
810 CWORD, CWORD, CWORD, CWORD,
811 CWORD, CWORD, CWORD, CWORD,
812 CWORD, CWORD, CWORD, CCTL,
813 CENDQUOTE,CWORD, CVAR, CWORD,
814 CWORD, CWORD, CWORD, CWORD,
815 CCTL, CWORD, CWORD, CCTL,
816 CWORD, CCTL, CWORD, CWORD,
817 CWORD, CWORD, CWORD, CWORD,
818 CWORD, CWORD, CWORD, CWORD,
819 CCTL, CWORD, CWORD, CCTL,
820 CWORD, CCTL, CWORD, CWORD,
821 CWORD, CWORD, CWORD, CWORD,
822 CWORD, CWORD, CWORD, CWORD,
823 CWORD, CWORD, CWORD, CWORD,
824 CWORD, CWORD, CWORD, CWORD,
825 CWORD, CWORD, CWORD, CWORD,
826 CWORD, CWORD, CWORD, CWORD,
827 CWORD, CCTL, CBACK, CCTL,
828 CWORD, CWORD, CBQUOTE, CWORD,
829 CWORD, CWORD, CWORD, CWORD,
830 CWORD, CWORD, CWORD, CWORD,
831 CWORD, CWORD, CWORD, CWORD,
832 CWORD, CWORD, CWORD, CWORD,
833 CWORD, CWORD, CWORD, CWORD,
834 CWORD, CWORD, CWORD, CWORD,
835 CWORD, CWORD, CWORD, CENDVAR,
839 /* syntax table used when in single quotes */
840 static const char sqsyntax[257] = {
841 CENDFILE, CIGN, CWORD, CCTL,
842 CCTL, CCTL, CCTL, CCTL,
843 CCTL, CCTL, CCTL, CWORD,
844 CWORD, CWORD, CWORD, CWORD,
845 CWORD, CWORD, CWORD, CWORD,
846 CWORD, CWORD, CWORD, CWORD,
847 CWORD, CWORD, CWORD, CWORD,
848 CWORD, CWORD, CWORD, CWORD,
849 CWORD, CWORD, CWORD, CWORD,
850 CWORD, CWORD, CWORD, CWORD,
851 CWORD, CWORD, CWORD, CWORD,
852 CWORD, CWORD, CWORD, CWORD,
853 CWORD, CWORD, CWORD, CWORD,
854 CWORD, CWORD, CWORD, CWORD,
855 CWORD, CWORD, CWORD, CWORD,
856 CWORD, CWORD, CWORD, CWORD,
857 CWORD, CWORD, CWORD, CWORD,
858 CWORD, CWORD, CWORD, CWORD,
859 CWORD, CWORD, CWORD, CWORD,
860 CWORD, CWORD, CWORD, CWORD,
861 CWORD, CWORD, CWORD, CWORD,
862 CWORD, CWORD, CWORD, CWORD,
863 CWORD, CWORD, CWORD, CWORD,
864 CWORD, CWORD, CWORD, CWORD,
865 CWORD, CWORD, CWORD, CWORD,
866 CWORD, CWORD, CWORD, CWORD,
867 CWORD, CWORD, CWORD, CWORD,
868 CWORD, CWORD, CWORD, CWORD,
869 CWORD, CWORD, CWORD, CWORD,
870 CWORD, CWORD, CWORD, CWORD,
871 CWORD, CWORD, CWORD, CWORD,
872 CWORD, CWORD, CWORD, CWORD,
873 CWORD, CWORD, CWORD, CWORD,
874 CWORD, CWORD, CWORD, CWORD,
875 CWORD, CWORD, CWORD, CWORD,
876 CNL, CWORD, CWORD, CWORD,
877 CWORD, CWORD, CWORD, CWORD,
878 CWORD, CWORD, CWORD, CWORD,
879 CWORD, CWORD, CWORD, CWORD,
880 CWORD, CWORD, CWORD, CWORD,
881 CWORD, CWORD, CWORD, CCTL,
882 CWORD, CWORD, CWORD, CWORD,
883 CWORD, CENDQUOTE,CWORD, CWORD,
884 CCTL, CWORD, CWORD, CCTL,
885 CWORD, CCTL, CWORD, CWORD,
886 CWORD, CWORD, CWORD, CWORD,
887 CWORD, CWORD, CWORD, CWORD,
888 CCTL, CWORD, CWORD, CCTL,
889 CWORD, CCTL, CWORD, CWORD,
890 CWORD, CWORD, CWORD, CWORD,
891 CWORD, CWORD, CWORD, CWORD,
892 CWORD, CWORD, CWORD, CWORD,
893 CWORD, CWORD, CWORD, CWORD,
894 CWORD, CWORD, CWORD, CWORD,
895 CWORD, CWORD, CWORD, CWORD,
896 CWORD, CCTL, CCTL, CCTL,
897 CWORD, CWORD, CWORD, CWORD,
898 CWORD, CWORD, CWORD, CWORD,
899 CWORD, CWORD, CWORD, CWORD,
900 CWORD, CWORD, CWORD, CWORD,
901 CWORD, CWORD, CWORD, CWORD,
902 CWORD, CWORD, CWORD, CWORD,
903 CWORD, CWORD, CWORD, CWORD,
904 CWORD, CWORD, CWORD, CWORD,
908 /* syntax table used when in arithmetic */
909 static const char arisyntax[257] = {
910 CENDFILE, CIGN, CWORD, CCTL,
911 CCTL, CCTL, CCTL, CCTL,
912 CCTL, CCTL, CCTL, CWORD,
913 CWORD, CWORD, CWORD, CWORD,
914 CWORD, CWORD, CWORD, CWORD,
915 CWORD, CWORD, CWORD, CWORD,
916 CWORD, CWORD, CWORD, CWORD,
917 CWORD, CWORD, CWORD, CWORD,
918 CWORD, CWORD, CWORD, CWORD,
919 CWORD, CWORD, CWORD, CWORD,
920 CWORD, CWORD, CWORD, CWORD,
921 CWORD, CWORD, CWORD, CWORD,
922 CWORD, CWORD, CWORD, CWORD,
923 CWORD, CWORD, CWORD, CWORD,
924 CWORD, CWORD, CWORD, CWORD,
925 CWORD, CWORD, CWORD, CWORD,
926 CWORD, CWORD, CWORD, CWORD,
927 CWORD, CWORD, CWORD, CWORD,
928 CWORD, CWORD, CWORD, CWORD,
929 CWORD, CWORD, CWORD, CWORD,
930 CWORD, CWORD, CWORD, CWORD,
931 CWORD, CWORD, CWORD, CWORD,
932 CWORD, CWORD, CWORD, CWORD,
933 CWORD, CWORD, CWORD, CWORD,
934 CWORD, CWORD, CWORD, CWORD,
935 CWORD, CWORD, CWORD, CWORD,
936 CWORD, CWORD, CWORD, CWORD,
937 CWORD, CWORD, CWORD, CWORD,
938 CWORD, CWORD, CWORD, CWORD,
939 CWORD, CWORD, CWORD, CWORD,
940 CWORD, CWORD, CWORD, CWORD,
941 CWORD, CWORD, CWORD, CWORD,
942 CWORD, CWORD, CWORD, CWORD,
943 CWORD, CWORD, CWORD, CWORD,
944 CWORD, CWORD, CWORD, CWORD,
945 CNL, CWORD, CWORD, CWORD,
946 CWORD, CWORD, CWORD, CWORD,
947 CWORD, CWORD, CWORD, CWORD,
948 CWORD, CWORD, CWORD, CWORD,
949 CWORD, CWORD, CWORD, CWORD,
950 CWORD, CWORD, CWORD, CWORD,
951 CDQUOTE, CWORD, CVAR, CWORD,
952 CWORD, CSQUOTE, CLP, CRP,
953 CWORD, CWORD, CWORD, CWORD,
954 CWORD, CWORD, CWORD, CWORD,
955 CWORD, CWORD, CWORD, CWORD,
956 CWORD, CWORD, CWORD, CWORD,
957 CWORD, CWORD, CWORD, CWORD,
958 CWORD, CWORD, CWORD, CWORD,
959 CWORD, CWORD, CWORD, CWORD,
960 CWORD, CWORD, CWORD, CWORD,
961 CWORD, CWORD, CWORD, CWORD,
962 CWORD, CWORD, CWORD, CWORD,
963 CWORD, CWORD, CWORD, CWORD,
964 CWORD, CWORD, CWORD, CWORD,
965 CWORD, CWORD, CBACK, CWORD,
966 CWORD, CWORD, CBQUOTE, CWORD,
967 CWORD, CWORD, CWORD, CWORD,
968 CWORD, CWORD, CWORD, CWORD,
969 CWORD, CWORD, CWORD, CWORD,
970 CWORD, CWORD, CWORD, CWORD,
971 CWORD, CWORD, CWORD, CWORD,
972 CWORD, CWORD, CWORD, CWORD,
973 CWORD, CWORD, CWORD, CENDVAR,
977 /* character classification table */
978 static const char is_type[257] = {
1020 0, ISSPECL, ISSPECL, 0,
1022 ISSPECL, 0, 0, ISSPECL,
1023 0, 0, ISDIGIT, ISDIGIT,
1024 ISDIGIT, ISDIGIT, ISDIGIT, ISDIGIT,
1025 ISDIGIT, ISDIGIT, ISDIGIT, ISDIGIT,
1027 0, ISSPECL, ISSPECL, ISUPPER,
1028 ISUPPER, ISUPPER, ISUPPER, ISUPPER,
1029 ISUPPER, ISUPPER, ISUPPER, ISUPPER,
1030 ISUPPER, ISUPPER, ISUPPER, ISUPPER,
1031 ISUPPER, ISUPPER, ISUPPER, ISUPPER,
1032 ISUPPER, ISUPPER, ISUPPER, ISUPPER,
1033 ISUPPER, ISUPPER, ISUPPER, ISUPPER,
1035 0, ISUNDER, 0, ISLOWER,
1036 ISLOWER, ISLOWER, ISLOWER, ISLOWER,
1037 ISLOWER, ISLOWER, ISLOWER, ISLOWER,
1038 ISLOWER, ISLOWER, ISLOWER, ISLOWER,
1039 ISLOWER, ISLOWER, ISLOWER, ISLOWER,
1040 ISLOWER, ISLOWER, ISLOWER, ISLOWER,
1041 ISLOWER, ISLOWER, ISLOWER, ISLOWER,
1046 /* Array indicating which tokens mark the end of a list */
1047 static const char tokendlist[] = {
1080 static const char *const tokname[] = {
1113 #define KWDOFFSET 14
1115 static const char *const parsekwd[] = {
1135 static int plinno = 1; /* input line number */
1137 static int parselleft; /* copy of parsefile->lleft */
1139 static struct parsefile basepf; /* top level input file */
1140 static char basebuf[BUFSIZ]; /* buffer for top level input file */
1141 static struct parsefile *parsefile = &basepf; /* current input file */
1144 * NEOF is returned by parsecmd when it encounters an end of file. It
1145 * must be distinct from NULL, so we use the address of a variable that
1146 * happens to be handy.
1149 static int tokpushback; /* last token pushed back */
1150 #define NEOF ((union node *)&tokpushback)
1151 static int checkkwd; /* 1 == check for kwds, 2 == also eat newlines */
1154 static void error (const char *, ...) __attribute__((__noreturn__));
1155 static void exerror (int, const char *, ...) __attribute__((__noreturn__));
1156 static void shellexec (char **, char **, const char *, int)
1157 __attribute__((noreturn));
1158 static void exitshell (int) __attribute__((noreturn));
1160 static int goodname(const char *);
1161 static void ignoresig (int);
1162 static void onsig (int);
1163 static void dotrap (void);
1164 static int decode_signal (const char *, int);
1166 static void shprocvar(void);
1167 static void deletefuncs(void);
1168 static void setparam (char **);
1169 static void freeparam (volatile struct shparam *);
1171 /* reasons for skipping commands (see comment on breakcmd routine) */
1177 /* values of cmdtype */
1178 #define CMDUNKNOWN -1 /* no entry in table for command */
1179 #define CMDNORMAL 0 /* command is an executable program */
1180 #define CMDBUILTIN 1 /* command is a shell builtin */
1181 #define CMDFUNCTION 2 /* command is a shell function */
1183 #define DO_ERR 1 /* find_command prints errors */
1184 #define DO_ABS 2 /* find_command checks absolute paths */
1185 #define DO_NOFUN 4 /* find_command ignores functions */
1186 #define DO_BRUTE 8 /* find_command ignores hash table */
1193 #define VEXPORT 0x01 /* variable is exported */
1194 #define VREADONLY 0x02 /* variable cannot be modified */
1195 #define VSTRFIXED 0x04 /* variable struct is staticly allocated */
1196 #define VTEXTFIXED 0x08 /* text is staticly allocated */
1197 #define VSTACK 0x10 /* text is allocated on the stack */
1198 #define VUNSET 0x20 /* the variable is not set */
1199 #define VNOFUNC 0x40 /* don't call the callback function */
1203 struct var *next; /* next entry in hash list */
1204 int flags; /* flags are defined above */
1205 char *text; /* name=value */
1206 void (*func) (const char *);
1207 /* function to be called when */
1208 /* the variable gets set/unset */
1212 struct localvar *next; /* next local variable in list */
1213 struct var *vp; /* the variable that was made local */
1214 int flags; /* saved flags */
1215 char *text; /* saved text */
1219 #if defined(__GLIBC__) && __GLIBC__ >= 2 && !defined(FNMATCH_BROKEN)
1220 #define rmescapes(p) _rmescapes((p), 0)
1221 static char *_rmescapes (char *, int);
1223 static void rmescapes (char *);
1226 static int casematch (union node *, const char *);
1227 static void clearredir(void);
1228 static void popstring(void);
1229 static void readcmdfile (const char *);
1231 static int number (const char *);
1232 static int is_number (const char *, int *num);
1233 static char *single_quote (const char *);
1234 static int nextopt (const char *);
1236 static void redirect (union node *, int);
1237 static void popredir (void);
1238 static int dup_as_newfd (int, int);
1240 static void changepath(const char *newval);
1241 static void getoptsreset(const char *value);
1244 static int parsenleft; /* copy of parsefile->nleft */
1245 static char *parsenextc; /* copy of parsefile->nextc */
1246 static int rootpid; /* pid of main shell */
1247 static int rootshell; /* true if we aren't a child of the main shell */
1249 static const char spcstr[] = " ";
1250 static const char snlfmt[] = "%s\n";
1252 static int sstrnleft;
1253 static int herefd = -1;
1255 static struct localvar *localvars;
1257 static struct var vifs;
1258 static struct var vmail;
1259 static struct var vmpath;
1260 static struct var vpath;
1261 static struct var vps1;
1262 static struct var vps2;
1263 static struct var voptind;
1264 #ifdef BB_LOCALE_SUPPORT
1265 static struct var vlc_all;
1266 static struct var vlc_ctype;
1273 void (*func) (const char *);
1276 static const char defpathvar[] =
1277 "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin";
1278 #define defpath (defpathvar + 5)
1281 static const char defifsvar[] = "IFS= \t\n";
1282 #define defifs (defifsvar + 4)
1284 static const char defifs[] = " \t\n";
1287 static const struct varinit varinit[] = {
1289 { &vifs, VSTRFIXED|VTEXTFIXED, defifsvar,
1291 { &vifs, VSTRFIXED|VTEXTFIXED|VUNSET, "IFS=",
1294 { &vmail, VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL=",
1296 { &vmpath, VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH=",
1298 { &vpath, VSTRFIXED|VTEXTFIXED, defpathvar,
1301 * vps1 depends on uid
1303 { &vps2, VSTRFIXED|VTEXTFIXED, "PS2=> ",
1305 { &voptind, VSTRFIXED|VTEXTFIXED, "OPTIND=1",
1307 #ifdef BB_LOCALE_SUPPORT
1308 { &vlc_all, VSTRFIXED|VTEXTFIXED|VUNSET, "LC_ALL=",
1310 { &vlc_ctype, VSTRFIXED|VTEXTFIXED|VUNSET, "LC_CTYPE=",
1319 static struct var *vartab[VTABSIZE];
1322 * The following macros access the values of the above variables.
1323 * They have to skip over the name. They return the null string
1324 * for unset variables.
1327 #define ifsval() (vifs.text + 4)
1328 #define ifsset() ((vifs.flags & VUNSET) == 0)
1329 #define mailval() (vmail.text + 5)
1330 #define mpathval() (vmpath.text + 9)
1331 #define pathval() (vpath.text + 5)
1332 #define ps1val() (vps1.text + 4)
1333 #define ps2val() (vps2.text + 4)
1334 #define optindval() (voptind.text + 7)
1336 #define mpathset() ((vmpath.flags & VUNSET) == 0)
1338 static void initvar (void);
1339 static void setvar (const char *, const char *, int);
1340 static void setvareq (char *, int);
1341 static void listsetvar (struct strlist *);
1342 static const char *lookupvar (const char *);
1343 static const char *bltinlookup (const char *);
1344 static char **environment (void);
1345 static int showvarscmd (int, char **);
1346 static void mklocal (char *);
1347 static void poplocalvars (void);
1348 static int unsetvar (const char *);
1349 static int varequal (const char *, const char *);
1352 static char *arg0; /* value of $0 */
1353 static struct shparam shellparam; /* current positional parameters */
1354 static char **argptr; /* argument list for builtin commands */
1355 static char *optionarg; /* set by nextopt (like getopt) */
1356 static char *optptr; /* used by nextopt */
1357 static char *minusc; /* argument to -c option */
1362 #define ALIASINUSE 1
1374 static struct alias *atab[ATABSIZE];
1376 static void setalias (char *, char *);
1377 static struct alias **hashalias (const char *);
1378 static struct alias *freealias (struct alias *);
1379 static struct alias **__lookupalias (const char *);
1385 struct alias *ap, **app;
1387 app = __lookupalias(name);
1391 if (!(ap->flag & ALIASINUSE)) {
1394 ap->val = savestr(val);
1395 ap->flag &= ~ALIASDEAD;
1398 ap = ckmalloc(sizeof (struct alias));
1399 ap->name = savestr(name);
1400 ap->val = savestr(val);
1413 app = __lookupalias(name);
1417 *app = freealias(*app);
1428 struct alias *ap, **app;
1432 for (i = 0; i < ATABSIZE; i++) {
1434 for (ap = *app; ap; ap = *app) {
1435 *app = freealias(*app);
1444 static struct alias *
1445 lookupalias(const char *name, int check)
1447 struct alias *ap = *__lookupalias(name);
1449 if (check && ap && (ap->flag & ALIASINUSE))
1455 printalias(const struct alias *ap) {
1458 p = single_quote(ap->val);
1459 printf("alias %s=%s\n", ap->name, p);
1465 * TODO - sort output
1468 aliascmd(int argc, char **argv)
1477 for (i = 0; i < ATABSIZE; i++)
1478 for (ap = atab[i]; ap; ap = ap->next) {
1483 while ((n = *++argv) != NULL) {
1484 if ((v = strchr(n+1, '=')) == NULL) { /* n+1: funny ksh stuff */
1485 if ((ap = *__lookupalias(n)) == NULL) {
1486 out2fmt("%s: %s not found\n", "alias", n);
1501 unaliascmd(int argc, char **argv)
1505 while ((i = nextopt("a")) != '\0') {
1511 for (i = 0; *argptr; argptr++) {
1512 if (unalias(*argptr)) {
1513 out2fmt("%s: %s not found\n", "unalias", *argptr);
1521 static struct alias **
1525 unsigned int hashval;
1530 return &atab[hashval % ATABSIZE];
1533 static struct alias *
1534 freealias(struct alias *ap) {
1537 if (ap->flag & ALIASINUSE) {
1538 ap->flag |= ALIASDEAD;
1550 static struct alias **
1551 __lookupalias(const char *name) {
1552 struct alias **app = hashalias(name);
1554 for (; *app; app = &(*app)->next) {
1555 if (equal(name, (*app)->name)) {
1564 #ifdef ASH_MATH_SUPPORT
1565 /* The generated file arith.c has been snipped. If you want this
1566 * stuff back in, feel free to add it to your own copy. */
1567 #define ARITH_NUM 257
1568 #define ARITH_LPAREN 258
1569 #define ARITH_RPAREN 259
1570 #define ARITH_OR 260
1571 #define ARITH_AND 261
1572 #define ARITH_BOR 262
1573 #define ARITH_BXOR 263
1574 #define ARITH_BAND 264
1575 #define ARITH_EQ 265
1576 #define ARITH_NE 266
1577 #define ARITH_LT 267
1578 #define ARITH_GT 268
1579 #define ARITH_GE 269
1580 #define ARITH_LE 270
1581 #define ARITH_LSHIFT 271
1582 #define ARITH_RSHIFT 272
1583 #define ARITH_ADD 273
1584 #define ARITH_SUB 274
1585 #define ARITH_MUL 275
1586 #define ARITH_DIV 276
1587 #define ARITH_REM 277
1588 #define ARITH_UNARYMINUS 278
1589 #define ARITH_UNARYPLUS 279
1590 #define ARITH_NOT 280
1591 #define ARITH_BNOT 281
1593 static void expari (int);
1595 static int arith (const char *);
1596 static int expcmd (int , char **);
1597 static void arith_lex_reset (void);
1598 static int yylex (void);
1602 static char *trap[NSIG]; /* trap handler commands */
1603 static char sigmode[NSIG - 1]; /* current value of signal */
1604 static char gotsig[NSIG - 1]; /* indicates specified signal received */
1605 static int pendingsigs; /* indicates some signal received */
1608 * This file was generated by the mkbuiltins program.
1612 static int bgcmd (int, char **);
1613 static int fgcmd (int, char **);
1614 static int killcmd (int, char **);
1616 static int bltincmd (int, char **);
1617 static int cdcmd (int, char **);
1618 static int breakcmd (int, char **);
1620 static int commandcmd (int, char **);
1622 static int dotcmd (int, char **);
1623 static int evalcmd (int, char **);
1624 static int execcmd (int, char **);
1625 static int exitcmd (int, char **);
1626 static int exportcmd (int, char **);
1627 static int histcmd (int, char **);
1628 static int hashcmd (int, char **);
1629 static int helpcmd (int, char **);
1630 static int jobscmd (int, char **);
1631 static int localcmd (int, char **);
1633 static int pwdcmd (int, char **);
1635 static int readcmd (int, char **);
1636 static int returncmd (int, char **);
1637 static int setcmd (int, char **);
1638 static int setvarcmd (int, char **);
1639 static int shiftcmd (int, char **);
1640 static int trapcmd (int, char **);
1641 static int umaskcmd (int, char **);
1643 static int aliascmd (int, char **);
1644 static int unaliascmd (int, char **);
1646 static int unsetcmd (int, char **);
1647 static int waitcmd (int, char **);
1648 static int ulimitcmd (int, char **);
1649 static int timescmd (int, char **);
1650 #ifdef ASH_MATH_SUPPORT
1651 static int expcmd (int, char **);
1653 static int typecmd (int, char **);
1655 static int getoptscmd (int, char **);
1658 #ifndef BB_TRUE_FALSE
1659 static int true_main (int, char **);
1660 static int false_main (int, char **);
1663 static void setpwd (const char *, int);
1666 #define BUILTIN_NOSPEC "0"
1667 #define BUILTIN_SPECIAL "1"
1668 #define BUILTIN_REGULAR "2"
1669 #define BUILTIN_ASSIGN "4"
1670 #define BUILTIN_SPEC_ASSG "5"
1671 #define BUILTIN_REG_ASSG "6"
1673 #define IS_BUILTIN_SPECIAL(builtincmd) ((builtincmd)->name[0] & 1)
1674 #define IS_BUILTIN_REGULAR(builtincmd) ((builtincmd)->name[0] & 2)
1675 #define IS_BUILTIN_ASSIGN(builtincmd) ((builtincmd)->name[0] & 4)
1679 int (*const builtinfunc) (int, char **);
1684 /* It is CRUCIAL that this listing be kept in ascii order, otherwise
1685 * the binary search in find_builtin() will stop working. If you value
1686 * your kneecaps, you'll be sure to *make sure* that any changes made
1687 * to this array result in the listing remaining in ascii order. You
1690 static const struct builtincmd builtincmds[] = {
1691 { BUILTIN_SPECIAL ".", dotcmd }, /* first, see declare DOTCMD */
1692 { BUILTIN_SPECIAL ":", true_main },
1694 { BUILTIN_REG_ASSG "alias", aliascmd },
1697 { BUILTIN_REGULAR "bg", bgcmd },
1699 { BUILTIN_SPECIAL "break", breakcmd },
1700 { BUILTIN_SPECIAL "builtin", bltincmd },
1701 { BUILTIN_REGULAR "cd", cdcmd },
1702 { BUILTIN_NOSPEC "chdir", cdcmd },
1704 { BUILTIN_REGULAR "command", commandcmd },
1706 { BUILTIN_SPECIAL "continue", breakcmd },
1707 { BUILTIN_SPECIAL "eval", evalcmd },
1708 { BUILTIN_SPECIAL "exec", execcmd },
1709 { BUILTIN_SPECIAL "exit", exitcmd },
1710 #ifdef ASH_MATH_SUPPORT
1711 { BUILTIN_NOSPEC "exp", expcmd },
1713 { BUILTIN_SPEC_ASSG "export", exportcmd },
1714 { BUILTIN_REGULAR "false", false_main },
1715 { BUILTIN_REGULAR "fc", histcmd },
1717 { BUILTIN_REGULAR "fg", fgcmd },
1720 { BUILTIN_REGULAR "getopts", getoptscmd },
1722 { BUILTIN_NOSPEC "hash", hashcmd },
1723 { BUILTIN_NOSPEC "help", helpcmd },
1724 { BUILTIN_REGULAR "jobs", jobscmd },
1726 { BUILTIN_REGULAR "kill", killcmd },
1728 #ifdef ASH_MATH_SUPPORT
1729 { BUILTIN_NOSPEC "let", expcmd },
1731 { BUILTIN_ASSIGN "local", localcmd },
1733 { BUILTIN_NOSPEC "pwd", pwdcmd },
1735 { BUILTIN_REGULAR "read", readcmd },
1736 { BUILTIN_SPEC_ASSG "readonly", exportcmd },
1737 { BUILTIN_SPECIAL "return", returncmd },
1738 { BUILTIN_SPECIAL "set", setcmd },
1739 { BUILTIN_NOSPEC "setvar", setvarcmd },
1740 { BUILTIN_SPECIAL "shift", shiftcmd },
1741 { BUILTIN_SPECIAL "times", timescmd },
1742 { BUILTIN_SPECIAL "trap", trapcmd },
1743 { BUILTIN_REGULAR "true", true_main },
1744 { BUILTIN_NOSPEC "type", typecmd },
1745 { BUILTIN_NOSPEC "ulimit", ulimitcmd },
1746 { BUILTIN_REGULAR "umask", umaskcmd },
1748 { BUILTIN_REGULAR "unalias", unaliascmd },
1750 { BUILTIN_SPECIAL "unset", unsetcmd },
1751 { BUILTIN_REGULAR "wait", waitcmd },
1753 #define NUMBUILTINS (sizeof (builtincmds) / sizeof (struct builtincmd) )
1755 static const struct builtincmd *DOTCMD = &builtincmds[0];
1756 static struct builtincmd *BLTINCMD;
1757 static struct builtincmd *EXECCMD;
1758 static struct builtincmd *EVALCMD;
1761 #define JOBSTOPPED 1 /* all procs are stopped */
1762 #define JOBDONE 2 /* all procs are completed */
1765 * A job structure contains information about a job. A job is either a
1766 * single process or a set of processes contained in a pipeline. In the
1767 * latter case, pidlist will be non-NULL, and will point to a -1 terminated
1772 pid_t pid; /* process id */
1773 int status; /* status flags (defined above) */
1774 char *cmd; /* text of command being run */
1778 static int job_warning; /* user was warned about stopped jobs */
1781 static void setjobctl(int enable);
1783 #define setjobctl(on) /* do nothing */
1788 struct procstat ps0; /* status of process */
1789 struct procstat *ps; /* status or processes when more than one */
1790 short nprocs; /* number of processes */
1791 short pgrp; /* process group of this job */
1792 char state; /* true if job is finished */
1793 char used; /* true if this entry is in used */
1794 char changed; /* true if status has changed */
1796 char jobctl; /* job running under job control */
1800 static struct job *jobtab; /* array of jobs */
1801 static int njobs; /* size of array */
1802 static int backgndpid = -1; /* pid of last background process */
1804 static int initialpgrp; /* pgrp of shell on invocation */
1805 static int curjob; /* current job */
1808 static int intreceived;
1810 static struct job *makejob (const union node *, int);
1811 static int forkshell (struct job *, const union node *, int);
1812 static int waitforjob (struct job *);
1814 static int docd (char *, int);
1815 static char *getcomponent (void);
1816 static void updatepwd (const char *);
1817 static void getpwd (void);
1819 static char *padvance (const char **, const char *);
1821 static char nullstr[1]; /* zero length string */
1822 static char *curdir = nullstr; /* current working directory */
1823 static char *cdcomppath;
1837 if ((dest = *argptr) == NULL && (dest = bltinlookup("HOME")) == NULL)
1838 error("HOME not set");
1841 if (dest[0] == '-' && dest[1] == '\0') {
1842 dest = bltinlookup("OLDPWD");
1843 if (!dest || !*dest) {
1852 if (*dest == '/' || (path = bltinlookup("CDPATH")) == NULL)
1854 while ((p = padvance(&path, dest)) != NULL) {
1855 if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
1860 if (p[0] == '.' && p[1] == '/' && p[2] != '\0')
1862 print = strcmp(p, dest);
1864 if (docd(p, print) >= 0)
1869 error("can't cd to %s", dest);
1875 * Actually do the chdir. In an interactive shell, print the
1876 * directory name if "print" is nonzero.
1891 TRACE(("docd(\"%s\", %d) called\n", dest, print));
1894 * Check each component of the path. If we find a symlink or
1895 * something we can't stat, clear curdir to force a getcwd()
1896 * next time we get the value of the current directory.
1899 cdcomppath = sstrdup(dest);
1906 while ((q = getcomponent()) != NULL) {
1907 if (q[0] == '\0' || (q[0] == '.' && q[1] == '\0'))
1915 if (equal(component, ".."))
1918 if ((lstat(stackblock(), &statb) < 0)
1919 || (S_ISLNK(statb.st_mode))) {
1927 if (chdir(dest) < 0) {
1931 updatepwd(badstat ? NULL : dest);
1934 printf(snlfmt, curdir);
1940 * Get the next component of the path name pointed to by cdcomppath.
1941 * This routine overwrites the string pointed to by cdcomppath.
1949 if ((p = cdcomppath) == NULL)
1952 while (*p != '/' && *p != '\0')
1966 * Update curdir (the name of the current directory) in response to a
1967 * cd command. We also call hashcd to let the routines in exec.c know
1968 * that the current directory has changed.
1971 static void hashcd (void);
1974 updatepwd(const char *dir)
1980 hashcd(); /* update command hash table */
1983 * If our argument is NULL, we don't know the current directory
1984 * any more because we traversed a symbolic link or something
1985 * we couldn't stat().
1987 if (dir == NULL || curdir == nullstr) {
1992 cdcomppath = sstrdup(dir);
2001 while ((p = getcomponent()) != NULL) {
2002 if (equal(p, "..")) {
2003 while (new > stackblock() && (STUNPUTC(new), *new) != '/');
2004 } else if (*p != '\0' && ! equal(p, ".")) {
2010 if (new == stackblock())
2013 setpwd(stackblock(), 1);
2023 printf(snlfmt, curdir);
2029 * Find out what the current directory is. If we already know the current
2030 * directory, this routine returns immediately.
2035 curdir = xgetcwd(0);
2041 setpwd(const char *val, int setold)
2044 setvar("OLDPWD", curdir, VEXPORT);
2047 if (curdir != nullstr) {
2054 curdir = savestr(val);
2057 setvar("PWD", curdir, VEXPORT);
2061 * Errors and exceptions.
2065 * Code to handle exceptions in C.
2069 * We enclose jmp_buf in a structure so that we can declare pointers to
2070 * jump locations. The global variable handler contains the location to
2071 * jump to when an exception occurs, and the global variable exception
2072 * contains a code identifying the exeception. To implement nested
2073 * exception handlers, the user should save the value of handler on entry
2074 * to an inner scope, set handler to point to a jmploc structure for the
2075 * inner scope, and restore handler on exit from the scope.
2083 #define EXINT 0 /* SIGINT received */
2084 #define EXERROR 1 /* a generic error */
2085 #define EXSHELLPROC 2 /* execute a shell procedure */
2086 #define EXEXEC 3 /* command execution failed */
2088 static struct jmploc *handler;
2089 static int exception;
2091 static void exverror (int, const char *, va_list)
2092 __attribute__((__noreturn__));
2095 * Called to raise an exception. Since C doesn't include exceptions, we
2096 * just do a longjmp to the exception handler. The type of exception is
2097 * stored in the global variable "exception".
2100 static void exraise (int) __attribute__((__noreturn__));
2106 if (handler == NULL)
2111 longjmp(handler->loc, 1);
2116 * Called from trap.c when a SIGINT is received. (If the user specifies
2117 * that SIGINT is to be trapped or ignored using the trap builtin, then
2118 * this routine is not called.) Suppressint is nonzero when interrupts
2119 * are held using the INTOFF macro. The call to _exit is necessary because
2120 * there is a short period after a fork before the signal handlers are
2121 * set to the appropriate value for the child. (The test for iflag is
2122 * just defensive programming.)
2134 sigemptyset(&mysigset);
2135 sigprocmask(SIG_SETMASK, &mysigset, NULL);
2136 if (rootshell && iflag)
2139 signal(SIGINT, SIG_DFL);
2146 static char *commandname; /* currently executing command */
2149 * Exverror is called to raise the error exception. If the first argument
2150 * is not NULL then error prints an error message using printf style
2151 * formatting. It then raises the error exception.
2154 exverror(int cond, const char *msg, va_list ap)
2161 TRACE(("exverror(%d, \"%s\") pid=%d\n", cond, msg, getpid()));
2163 TRACE(("exverror(%d, NULL) pid=%d\n", cond, getpid()));
2167 out2fmt("%s: ", commandname);
2168 vfprintf(stderr, msg, ap);
2178 error(const char *msg, ...)
2193 msg = va_arg(ap, const char *);
2195 exverror(EXERROR, msg, ap);
2203 exerror(int cond, const char *msg, ...)
2219 cond = va_arg(ap, int);
2220 msg = va_arg(ap, const char *);
2222 exverror(cond, msg, ap);
2230 * Table of error messages.
2234 short errcode; /* error number */
2235 char action; /* operation which encountered the error */
2239 * Types of operations (passed to the errmsg routine).
2242 #define E_OPEN 01 /* opening a file */
2243 #define E_CREAT 02 /* creating a file */
2244 #define E_EXEC 04 /* executing a program */
2246 #define ALL (E_OPEN|E_CREAT|E_EXEC)
2248 static const struct errname errormsg[] = {
2253 { ENOENT, E_CREAT },
2255 { ENOTDIR, E_OPEN },
2256 { ENOTDIR, E_CREAT },
2257 { ENOTDIR, E_EXEC },
2259 { EEXIST, E_CREAT },
2298 { ELIBACC, E_EXEC },
2302 #define ERRNAME_SIZE (sizeof(errormsg)/sizeof(struct errname))
2305 * Return a string describing an error. The returned string may be a
2306 * pointer to a static buffer that will be overwritten on the next call.
2307 * Action describes the operation that got the error.
2311 errmsg(int e, int action)
2313 struct errname const *ep;
2314 static char buf[12];
2316 for (ep = errormsg ; ep < errormsg+ERRNAME_SIZE; ep++) {
2317 if (ep->errcode == e && (ep->action & action) != 0)
2321 snprintf(buf, sizeof buf, "error %d", e);
2326 #ifdef ASH_OPTIMIZE_FOR_SIZE
2329 if (--suppressint == 0 && intpending) {
2333 static void forceinton (void) {
2340 /* flags in argument to evaltree */
2341 #define EV_EXIT 01 /* exit after evaluating tree */
2342 #define EV_TESTED 02 /* exit status is checked; ignore -e flag */
2343 #define EV_BACKCMD 04 /* command executing within back quotes */
2345 static int evalskip; /* set if we are skipping commands */
2346 static int skipcount; /* number of levels to skip */
2347 static int loopnest; /* current loop nesting level */
2348 static int funcnest; /* depth of function calls */
2351 static struct strlist *cmdenviron; /* environment for builtin command */
2352 static int exitstatus; /* exit status of last command */
2353 static int oexitstatus; /* saved exit status */
2355 static void evalsubshell (const union node *, int);
2356 static void expredir (union node *);
2357 static void prehash (union node *);
2358 static void eprintlist (struct strlist *);
2360 static union node *parsecmd(int);
2362 * Called to reset things after an exception.
2366 * The eval commmand.
2368 static void evalstring (char *, int);
2382 STARTSTACKSTR(concat);
2386 STPUTC(*p++, concat);
2387 if ((p = *ap++) == NULL)
2389 STPUTC(' ', concat);
2391 STPUTC('\0', concat);
2392 p = grabstackstr(concat);
2394 evalstring(p, EV_TESTED);
2400 * Execute a command or commands contained in a string.
2403 static void evaltree (union node *, int);
2404 static void setinputstring (char *);
2405 static void popfile (void);
2406 static void setstackmark(struct stackmark *mark);
2407 static void popstackmark(struct stackmark *mark);
2411 evalstring(char *s, int flag)
2414 struct stackmark smark;
2416 setstackmark(&smark);
2418 while ((n = parsecmd(0)) != NEOF) {
2420 popstackmark(&smark);
2423 popstackmark(&smark);
2426 static struct builtincmd *find_builtin (const char *);
2427 static void expandarg (union node *, struct arglist *, int);
2428 static void calcsize (const union node *);
2429 static union node *copynode (const union node *);
2432 * Make a copy of a parse tree.
2435 static int funcblocksize; /* size of structures in function */
2436 static int funcstringsize; /* size of strings in node */
2437 static pointer funcblock; /* block to allocate function from */
2438 static char *funcstring; /* block to allocate strings from */
2441 static inline union node *
2442 copyfunc(union node *n)
2449 funcblock = ckmalloc(funcblocksize + funcstringsize);
2450 funcstring = (char *) funcblock + funcblocksize;
2455 * Free a parse tree.
2459 freefunc(union node *n)
2467 * Add a new command entry, replacing any existing command entry for
2472 addcmdentry(char *name, struct cmdentry *entry)
2474 struct tblentry *cmdp;
2477 cmdp = cmdlookup(name, 1);
2478 if (cmdp->cmdtype == CMDFUNCTION) {
2479 freefunc(cmdp->param.func);
2481 cmdp->cmdtype = entry->cmdtype;
2482 cmdp->param = entry->u;
2487 evalloop(const union node *n, int flags)
2494 evaltree(n->nbinary.ch1, EV_TESTED);
2496 skipping: if (evalskip == SKIPCONT && --skipcount <= 0) {
2500 if (evalskip == SKIPBREAK && --skipcount <= 0)
2504 if (n->type == NWHILE) {
2505 if (exitstatus != 0)
2508 if (exitstatus == 0)
2511 evaltree(n->nbinary.ch2, flags & EV_TESTED);
2512 status = exitstatus;
2517 exitstatus = status;
2521 evalfor(const union node *n, int flags)
2523 struct arglist arglist;
2526 struct stackmark smark;
2528 setstackmark(&smark);
2529 arglist.lastp = &arglist.list;
2530 for (argp = n->nfor.args ; argp ; argp = argp->narg.next) {
2531 oexitstatus = exitstatus;
2532 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE | EXP_RECORD);
2536 *arglist.lastp = NULL;
2540 for (sp = arglist.list ; sp ; sp = sp->next) {
2541 setvar(n->nfor.var, sp->text, 0);
2542 evaltree(n->nfor.body, flags & EV_TESTED);
2544 if (evalskip == SKIPCONT && --skipcount <= 0) {
2548 if (evalskip == SKIPBREAK && --skipcount <= 0)
2555 popstackmark(&smark);
2559 evalcase(const union node *n, int flags)
2563 struct arglist arglist;
2564 struct stackmark smark;
2566 setstackmark(&smark);
2567 arglist.lastp = &arglist.list;
2568 oexitstatus = exitstatus;
2569 expandarg(n->ncase.expr, &arglist, EXP_TILDE);
2570 for (cp = n->ncase.cases ; cp && evalskip == 0 ; cp = cp->nclist.next) {
2571 for (patp = cp->nclist.pattern ; patp ; patp = patp->narg.next) {
2572 if (casematch(patp, arglist.list->text)) {
2573 if (evalskip == 0) {
2574 evaltree(cp->nclist.body, flags);
2581 popstackmark(&smark);
2585 * Evaluate a pipeline. All the processes in the pipeline are children
2586 * of the process creating the pipeline. (This differs from some versions
2587 * of the shell, which make the last process in a pipeline the parent
2596 struct nodelist *lp;
2601 TRACE(("evalpipe(0x%lx) called\n", (long)n));
2603 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next)
2606 jp = makejob(n, pipelen);
2608 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
2612 if (pipe(pip) < 0) {
2614 error("Pipe call failed");
2617 if (forkshell(jp, lp->n, n->npipe.backgnd) == 0) {
2621 dup_as_newfd(prevfd, 0);
2633 dup_as_newfd(pip[1], 1);
2637 evaltree(lp->n, EV_EXIT);
2645 if (n->npipe.backgnd == 0) {
2647 exitstatus = waitforjob(jp);
2648 TRACE(("evalpipe: job done exit status %d\n", exitstatus));
2653 static void find_command (const char *, struct cmdentry *, int, const char *);
2656 isassignment(const char *word) {
2657 if (!is_name(*word)) {
2662 } while (is_in_name(*word));
2663 return *word == '=';
2668 evalcommand(union node *cmd, int flags)
2670 struct stackmark smark;
2672 struct arglist arglist;
2673 struct arglist varlist;
2679 struct cmdentry cmdentry;
2681 char *volatile savecmdname;
2682 volatile struct shparam saveparam;
2683 struct localvar *volatile savelocalvars;
2687 const struct builtincmd *firstbltin;
2688 struct jmploc *volatile savehandler;
2689 struct jmploc jmploc;
2691 /* Avoid longjmp clobbering */
2698 /* First expand the arguments. */
2699 TRACE(("evalcommand(0x%lx, %d) called\n", (long)cmd, flags));
2700 setstackmark(&smark);
2701 arglist.lastp = &arglist.list;
2702 varlist.lastp = &varlist.list;
2704 oexitstatus = exitstatus;
2707 for (argp = cmd->ncmd.assign; argp; argp = argp->narg.next) {
2708 expandarg(argp, &varlist, EXP_VARTILDE);
2711 argp = cmd->ncmd.args; argp && !arglist.list;
2712 argp = argp->narg.next
2714 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
2717 struct builtincmd *bcmd;
2719 bcmd = find_builtin(arglist.list->text);
2720 pseudovarflag = bcmd && IS_BUILTIN_ASSIGN(bcmd);
2721 for (; argp; argp = argp->narg.next) {
2722 if (pseudovarflag && isassignment(argp->narg.text)) {
2723 expandarg(argp, &arglist, EXP_VARTILDE);
2726 expandarg(argp, &arglist, EXP_FULL | EXP_TILDE);
2729 *arglist.lastp = NULL;
2730 *varlist.lastp = NULL;
2731 expredir(cmd->ncmd.redirect);
2733 for (sp = arglist.list ; sp ; sp = sp->next)
2735 argv = stalloc(sizeof (char *) * (argc + 1));
2737 for (sp = arglist.list ; sp ; sp = sp->next) {
2738 TRACE(("evalcommand arg: %s\n", sp->text));
2743 if (iflag && funcnest == 0 && argc > 0)
2747 /* Print the command if xflag is set. */
2750 eprintlist(varlist.list);
2751 eprintlist(arglist.list);
2755 /* Now locate the command. */
2757 cmdentry.cmdtype = CMDBUILTIN;
2758 firstbltin = cmdentry.u.cmd = BLTINCMD;
2760 const char *oldpath;
2761 int findflag = DO_ERR;
2765 * Modify the command lookup path, if a PATH= assignment
2768 for (sp = varlist.list ; sp ; sp = sp->next)
2769 if (varequal(sp->text, defpathvar)) {
2770 path = sp->text + 5;
2771 findflag |= DO_BRUTE;
2774 oldfindflag = findflag;
2777 find_command(argv[0], &cmdentry, findflag, path);
2778 if (cmdentry.cmdtype == CMDUNKNOWN) { /* command not found */
2782 /* implement bltin and command here */
2783 if (cmdentry.cmdtype != CMDBUILTIN) {
2787 firstbltin = cmdentry.u.cmd;
2789 if (cmdentry.u.cmd == BLTINCMD) {
2791 struct builtincmd *bcmd;
2796 if (!(bcmd = find_builtin(*argv))) {
2797 out2fmt("%s: not found\n", *argv);
2801 cmdentry.u.cmd = bcmd;
2802 if (bcmd != BLTINCMD)
2806 if (cmdentry.u.cmd == find_builtin("command")) {
2811 if (*argv[0] == '-') {
2812 if (!equal(argv[0], "-p")) {
2822 findflag |= DO_BRUTE;
2825 findflag = oldfindflag;
2827 findflag |= DO_NOFUN;
2835 /* Fork off a child process if necessary. */
2836 if (cmd->ncmd.backgnd
2837 || (cmdentry.cmdtype == CMDNORMAL && (flags & EV_EXIT) == 0)
2839 jp = makejob(cmd, 1);
2840 mode = cmd->ncmd.backgnd;
2841 if (forkshell(jp, cmd, mode) != 0)
2842 goto parent; /* at end of routine */
2846 /* This is the child process if a fork occurred. */
2847 /* Execute the command. */
2848 if (cmdentry.cmdtype == CMDFUNCTION) {
2850 trputs("Shell function: "); trargs(argv);
2852 exitstatus = oexitstatus;
2853 redirect(cmd->ncmd.redirect, REDIR_PUSH);
2854 saveparam = shellparam;
2855 shellparam.malloc = 0;
2856 shellparam.nparam = argc - 1;
2857 shellparam.p = argv + 1;
2859 savelocalvars = localvars;
2862 if (setjmp(jmploc.loc)) {
2863 if (exception == EXSHELLPROC) {
2864 freeparam((volatile struct shparam *)
2867 saveparam.optind = shellparam.optind;
2868 saveparam.optoff = shellparam.optoff;
2869 freeparam(&shellparam);
2870 shellparam = saveparam;
2873 localvars = savelocalvars;
2874 handler = savehandler;
2875 longjmp(handler->loc, 1);
2877 savehandler = handler;
2879 for (sp = varlist.list ; sp ; sp = sp->next)
2882 evaltree(cmdentry.u.func, flags & EV_TESTED);
2886 localvars = savelocalvars;
2887 saveparam.optind = shellparam.optind;
2888 saveparam.optoff = shellparam.optoff;
2889 freeparam(&shellparam);
2890 shellparam = saveparam;
2891 handler = savehandler;
2894 if (evalskip == SKIPFUNC) {
2898 if (flags & EV_EXIT)
2899 exitshell(exitstatus);
2900 } else if (cmdentry.cmdtype == CMDBUILTIN) {
2902 trputs("builtin command: "); trargs(argv);
2904 mode = (cmdentry.u.cmd == EXECCMD)? 0 : REDIR_PUSH;
2905 redirect(cmd->ncmd.redirect, mode);
2906 savecmdname = commandname;
2907 if (IS_BUILTIN_SPECIAL(firstbltin)) {
2908 listsetvar(varlist.list);
2910 cmdenviron = varlist.list;
2913 if (setjmp(jmploc.loc)) {
2915 exitstatus = (e == EXINT)? SIGINT+128 : 2;
2918 savehandler = handler;
2920 commandname = argv[0];
2922 optptr = NULL; /* initialize nextopt */
2923 exitstatus = (*cmdentry.u.cmd->builtinfunc)(argc, argv);
2927 if (e != EXSHELLPROC) {
2928 commandname = savecmdname;
2929 if (flags & EV_EXIT)
2930 exitshell(exitstatus);
2932 handler = savehandler;
2934 if ((e != EXERROR && e != EXEXEC)
2935 || cmdentry.u.cmd == BLTINCMD
2936 || cmdentry.u.cmd == DOTCMD
2937 || cmdentry.u.cmd == EVALCMD
2938 || cmdentry.u.cmd == EXECCMD)
2942 if (cmdentry.u.cmd != EXECCMD)
2946 trputs("normal command: "); trargs(argv);
2948 redirect(cmd->ncmd.redirect, 0);
2950 for (sp = varlist.list ; sp ; sp = sp->next)
2951 setvareq(sp->text, VEXPORT|VSTACK);
2952 envp = environment();
2953 shellexec(argv, envp, path, cmdentry.u.index);
2957 parent: /* parent process gets here (if we forked) */
2958 if (mode == 0) { /* argument to fork */
2960 exitstatus = waitforjob(jp);
2966 setvar("_", lastarg, 0);
2967 popstackmark(&smark);
2971 * Evaluate a parse tree. The value is left in the global variable
2981 TRACE(("evaltree(NULL) called\n"));
2984 TRACE(("evaltree(0x%lx: %d) called\n", (long)n, n->type));
2987 evaltree(n->nbinary.ch1, flags & EV_TESTED);
2990 evaltree(n->nbinary.ch2, flags);
2993 evaltree(n->nbinary.ch1, EV_TESTED);
2994 if (evalskip || exitstatus != 0)
2996 evaltree(n->nbinary.ch2, flags);
2999 evaltree(n->nbinary.ch1, EV_TESTED);
3000 if (evalskip || exitstatus == 0)
3002 evaltree(n->nbinary.ch2, flags);
3005 expredir(n->nredir.redirect);
3006 redirect(n->nredir.redirect, REDIR_PUSH);
3007 evaltree(n->nredir.n, flags);
3011 evalsubshell(n, flags);
3014 evalsubshell(n, flags);
3017 evaltree(n->nif.test, EV_TESTED);
3020 if (exitstatus == 0)
3021 evaltree(n->nif.ifpart, flags);
3022 else if (n->nif.elsepart)
3023 evaltree(n->nif.elsepart, flags);
3039 struct builtincmd *bcmd;
3040 struct cmdentry entry;
3042 (bcmd = find_builtin(n->narg.text)) &&
3043 IS_BUILTIN_SPECIAL(bcmd)
3045 out2fmt("%s is a special built-in\n", n->narg.text);
3049 entry.cmdtype = CMDFUNCTION;
3050 entry.u.func = copyfunc(n->narg.next);
3051 addcmdentry(n->narg.text, &entry);
3056 evaltree(n->nnot.com, EV_TESTED);
3057 exitstatus = !exitstatus;
3065 evalcommand(n, flags);
3070 printf("Node type = %d\n", n->type);
3079 (checkexit && eflag && exitstatus && !(flags & EV_TESTED))
3081 exitshell(exitstatus);
3085 * Kick off a subshell to evaluate a tree.
3089 evalsubshell(const union node *n, int flags)
3092 int backgnd = (n->type == NBACKGND);
3094 expredir(n->nredir.redirect);
3096 if (forkshell(jp, n, backgnd) == 0) {
3098 flags &=~ EV_TESTED;
3099 redirect(n->nredir.redirect, 0);
3100 evaltree(n->nredir.n, flags | EV_EXIT); /* never returns */
3104 exitstatus = waitforjob(jp);
3110 * Compute the names of the files in a redirection list.
3113 static void fixredir(union node *n, const char *text, int err);
3116 expredir(union node *n)
3120 for (redir = n ; redir ; redir = redir->nfile.next) {
3122 fn.lastp = &fn.list;
3123 oexitstatus = exitstatus;
3124 switch (redir->type) {
3130 expandarg(redir->nfile.fname, &fn, EXP_TILDE | EXP_REDIR);
3131 redir->nfile.expfname = fn.list->text;
3135 if (redir->ndup.vname) {
3136 expandarg(redir->ndup.vname, &fn, EXP_FULL | EXP_TILDE);
3137 fixredir(redir, fn.list->text, 1);
3146 * Execute a command inside back quotes. If it's a builtin command, we
3147 * want to save its output in a block obtained from malloc. Otherwise
3148 * we fork off a subprocess and get the output of the command via a pipe.
3149 * Should be called with interrupts off.
3153 evalbackcmd(union node *n, struct backcmd *result)
3157 struct stackmark smark; /* unnecessary */
3159 setstackmark(&smark);
3170 error("Pipe call failed");
3172 if (forkshell(jp, n, FORK_NOJOB) == 0) {
3177 dup_as_newfd(pip[1], 1);
3181 evaltree(n, EV_EXIT);
3184 result->fd = pip[0];
3187 popstackmark(&smark);
3188 TRACE(("evalbackcmd done: fd=%d buf=0x%x nleft=%d jp=0x%x\n",
3189 result->fd, result->buf, result->nleft, result->jp));
3194 * Execute a simple command.
3198 * Search for a command. This is called before we fork so that the
3199 * location of the command will be available in the parent as well as
3200 * the child. The check for "goodname" is an overly conservative
3201 * check that the name will not be subject to expansion.
3208 struct cmdentry entry;
3210 if (n->type == NCMD && n->ncmd.args)
3211 if (goodname(n->ncmd.args->narg.text))
3212 find_command(n->ncmd.args->narg.text, &entry, 0,
3218 * Builtin commands. Builtin commands whose functions are closely
3219 * tied to evaluation are implemented here.
3223 * No command given, or a bltin command with no arguments. Set the
3224 * specified variables.
3228 bltincmd(argc, argv)
3233 * Preserve exitstatus of a previous possible redirection
3241 * Handle break and continue commands. Break, continue, and return are
3242 * all handled by setting the evalskip flag. The evaluation routines
3243 * above all check this flag, and if it is set they start skipping
3244 * commands rather than executing them. The variable skipcount is
3245 * the number of loops to break/continue, or the number of function
3246 * levels to return. (The latter is always 1.) It should probably
3247 * be an error to break out of more loops than exist, but it isn't
3248 * in the standard shell so we don't make it one here.
3252 breakcmd(argc, argv)
3256 int n = argc > 1 ? number(argv[1]) : 1;
3261 evalskip = (**argv == 'c')? SKIPCONT : SKIPBREAK;
3269 * The return command.
3273 returncmd(argc, argv)
3277 int ret = argc > 1 ? number(argv[1]) : oexitstatus;
3280 evalskip = SKIPFUNC;
3285 /* Do what ksh does; skip the rest of the file */
3286 evalskip = SKIPFILE;
3293 #ifndef BB_TRUE_FALSE
3295 false_main(argc, argv)
3304 true_main(argc, argv)
3313 * Controls whether the shell is interactive or not.
3316 static void setsignal(int signo);
3317 static void chkmail(int silent);
3321 setinteractive(int on)
3323 static int is_interactive;
3324 static int do_banner=0;
3326 if (on == is_interactive)
3332 is_interactive = on;
3333 if (do_banner==0 && is_interactive) {
3334 /* Looks like they want an interactive shell */
3335 printf( "\n\n" BB_BANNER " Built-in shell (ash)\n");
3336 printf( "Enter 'help' for a list of built-in commands.\n\n");
3344 setinteractive(iflag);
3357 iflag = 0; /* exit on error */
3360 for (sp = cmdenviron; sp ; sp = sp->next)
3361 setvareq(sp->text, VEXPORT|VSTACK);
3362 shellexec(argv + 1, environment(), pathval(), 0);
3368 eprintlist(struct strlist *sp)
3370 for (; sp; sp = sp->next) {
3371 out2fmt(" %s",sp->text);
3376 * Exec a program. Never returns. If you change this routine, you may
3377 * have to change the find_command routine as well.
3380 static const char *pathopt; /* set by padvance */
3383 shellexec(argv, envp, path, idx)
3384 char **argv, **envp;
3391 if (strchr(argv[0], '/') != NULL) {
3392 tryexec(argv[0], argv, envp);
3396 while ((cmdname = padvance(&path, argv[0])) != NULL) {
3397 if (--idx < 0 && pathopt == NULL) {
3398 tryexec(cmdname, argv, envp);
3399 if (errno != ENOENT && errno != ENOTDIR)
3406 /* Map to POSIX errors */
3418 exerror(EXEXEC, "%s: %s", argv[0], errmsg(e, E_EXEC));
3423 * Clear traps on a fork.
3429 for (tp = trap ; tp < &trap[NSIG] ; tp++) {
3430 if (*tp && **tp) { /* trap not NULL or SIG_IGN */
3435 setsignal(tp - trap);
3443 initshellproc(void) {
3469 /* from options.c: */
3473 for (i = 0; i < NOPTS; i++)
3489 for (sm = sigmode ; sm < sigmode + NSIG - 1; sm++) {
3501 static int preadbuffer(void);
3502 static void pushfile (void);
3505 * Read a character from the script, returning PEOF on end of file.
3506 * Nul characters in the input are silently discarded.
3509 #ifndef ASH_OPTIMIZE_FOR_SIZE
3510 #define pgetc_macro() (--parsenleft >= 0? *parsenextc++ : preadbuffer())
3514 return pgetc_macro();
3520 return --parsenleft >= 0? *parsenextc++ : preadbuffer();
3526 return pgetc_macro();
3532 * Undo the last call to pgetc. Only one character may be pushed back.
3533 * PEOF may be pushed back.
3545 struct parsefile *pf = parsefile;
3554 parsefile = pf->prev;
3556 parsenleft = parsefile->nleft;
3557 parselleft = parsefile->lleft;
3558 parsenextc = parsefile->nextc;
3559 plinno = parsefile->linno;
3565 * Return to top level.
3570 while (parsefile != &basepf)
3575 * Close the file(s) that the shell is reading commands from. Called
3576 * after a fork is done.
3582 if (parsefile->fd > 0) {
3583 close(parsefile->fd);
3590 * Like setinputfile, but takes an open file descriptor. Call this with
3595 setinputfd(fd, push)
3598 (void) fcntl(fd, F_SETFD, FD_CLOEXEC);
3604 while (parsefile->strpush)
3608 if (parsefile->buf == NULL)
3609 parsefile->buf = ckmalloc(BUFSIZ);
3610 parselleft = parsenleft = 0;
3616 * Set the input to take input from a file. If push is set, push the
3617 * old input onto the stack first.
3621 setinputfile(const char *fname, int push)
3627 if ((fd = open(fname, O_RDONLY)) < 0)
3628 error("Can't open %s", fname);
3630 myfileno2 = dup_as_newfd(fd, 10);
3633 error("Out of file descriptors");
3636 setinputfd(fd, push);
3642 tryexec(char *cmd, char **argv, char **envp)
3646 #ifdef BB_FEATURE_SH_STANDALONE_SHELL
3650 #ifdef BB_FEATURE_SH_APPLETS_ALWAYS_WIN
3651 name = get_last_path_component(name);
3654 for(argc_l=0;*argv_l!=NULL; argv_l++, argc_l++)
3657 for(argc_l=0;*argv_l!=NULL; argv_l++, argc_l++)
3659 run_applet_by_name(name, argc_l, argv);
3661 execve(cmd, argv, envp);
3666 setinputfile(cmd, 0);
3667 commandname = arg0 = savestr(argv[0]);
3669 exraise(EXSHELLPROC);
3674 static char *commandtext (const union node *);
3677 * Do a path search. The variable path (passed by reference) should be
3678 * set to the start of the path before the first call; padvance will update
3679 * this value as it proceeds. Successive calls to padvance will return
3680 * the possible path expansions in sequence. If an option (indicated by
3681 * a percent sign) appears in the path entry then the global variable
3682 * pathopt will be set to point to it; otherwise pathopt will be set to
3686 static const char *pathopt;
3688 static void growstackblock(void);
3692 padvance(const char **path, const char *name)
3702 for (p = start ; *p && *p != ':' && *p != '%' ; p++);
3703 len = p - start + strlen(name) + 2; /* "2" is for '/' and '\0' */
3704 while (stackblocksize() < len)
3708 memcpy(q, start, p - start);
3716 while (*p && *p != ':') p++;
3722 return stalloc(len);
3726 * Wrapper around strcmp for qsort/bsearch/...
3729 pstrcmp(const void *a, const void *b)
3731 return strcmp((const char *) a, *(const char *const *) b);
3735 * Find a keyword is in a sorted array.
3738 static const char *const *
3739 findkwd(const char *s)
3741 return bsearch(s, parsekwd, sizeof(parsekwd) / sizeof(const char *),
3742 sizeof(const char *), pstrcmp);
3746 /*** Command hashing code ***/
3754 struct tblentry **pp;
3755 struct tblentry *cmdp;
3758 struct cmdentry entry;
3761 const struct alias *ap;
3765 while ((c = nextopt("rvV")) != '\0') {
3769 } else if (c == 'v' || c == 'V') {
3773 if (*argptr == NULL) {
3774 for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
3775 for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
3776 if (cmdp->cmdtype != CMDBUILTIN) {
3777 printentry(cmdp, verbose);
3784 while ((name = *argptr++) != NULL) {
3785 if ((cmdp = cmdlookup(name, 0)) != NULL
3786 && (cmdp->cmdtype == CMDNORMAL
3787 || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0)))
3790 /* Then look at the aliases */
3791 if ((ap = lookupalias(name, 0)) != NULL) {
3793 printf("%s is an alias for %s\n", name, ap->val);
3799 /* First look at the keywords */
3800 if (findkwd(name)!=0) {
3802 printf("%s is a shell keyword\n", name);
3804 printf(snlfmt, name);
3808 find_command(name, &entry, DO_ERR, pathval());
3809 if (entry.cmdtype == CMDUNKNOWN) c = 1;
3811 cmdp = cmdlookup(name, 0);
3812 if (cmdp) printentry(cmdp, verbose=='v');
3820 printentry(cmdp, verbose)
3821 struct tblentry *cmdp;
3828 printf("%s%s", cmdp->cmdname, (verbose ? " is " : ""));
3829 if (cmdp->cmdtype == CMDNORMAL) {
3830 idx = cmdp->param.index;
3833 name = padvance(&path, cmdp->cmdname);
3835 } while (--idx >= 0);
3838 } else if (cmdp->cmdtype == CMDBUILTIN) {
3840 out1str("a shell builtin");
3841 } else if (cmdp->cmdtype == CMDFUNCTION) {
3844 out1str("a function\n");
3845 name = commandtext(cmdp->param.func);
3846 printf("%s() {\n %s\n}", cmdp->cmdname, name);
3852 error("internal error: cmdtype %d", cmdp->cmdtype);
3855 printf(snlfmt, cmdp->rehash ? "*" : nullstr);
3860 /*** List the available builtins ***/
3863 static int helpcmd(int argc, char** argv)
3867 printf("\nBuilt-in commands:\n-------------------\n");
3868 for (col=0, i=0; i < NUMBUILTINS; i++) {
3869 col += printf("%c%s", ((col == 0) ? '\t' : ' '),
3870 builtincmds[i].name+1);
3876 #ifdef BB_FEATURE_SH_STANDALONE_SHELL
3878 extern const struct BB_applet applets[];
3879 extern const size_t NUM_APPLETS;
3881 for (i=0; i < NUM_APPLETS; i++) {
3883 col += printf("%c%s", ((col == 0) ? '\t' : ' '),
3893 return EXIT_SUCCESS;
3897 * Resolve a command name. If you change this routine, you may have to
3898 * change the shellexec routine as well.
3901 static int prefix (const char *, const char *);
3904 find_command(const char *name, struct cmdentry *entry, int act, const char *path)
3906 struct tblentry *cmdp;
3916 struct builtincmd *bcmd;
3918 /* If name contains a slash, don't use the hash table */
3919 if (strchr(name, '/') != NULL) {
3921 while (stat(name, &statb) < 0) {
3922 if (errno != ENOENT && errno != ENOTDIR)
3924 entry->cmdtype = CMDUNKNOWN;
3925 entry->u.index = -1;
3928 entry->cmdtype = CMDNORMAL;
3929 entry->u.index = -1;
3932 entry->cmdtype = CMDNORMAL;
3938 if (act & DO_BRUTE) {
3939 firstchange = path_change(path, &bltin);
3945 /* If name is in the table, and not invalidated by cd, we're done */
3946 if ((cmdp = cmdlookup(name, 0)) != NULL && cmdp->rehash == 0) {
3947 if (cmdp->cmdtype == CMDFUNCTION) {
3948 if (act & DO_NOFUN) {
3953 } else if (act & DO_BRUTE) {
3954 if ((cmdp->cmdtype == CMDNORMAL &&
3955 cmdp->param.index >= firstchange) ||
3956 (cmdp->cmdtype == CMDBUILTIN &&
3957 ((builtinloc < 0 && bltin >= 0) ?
3958 bltin : builtinloc) >= firstchange)) {
3959 /* need to recompute the entry */
3968 bcmd = find_builtin(name);
3969 regular = bcmd && IS_BUILTIN_REGULAR(bcmd);
3972 if (cmdp && (cmdp->cmdtype == CMDBUILTIN)) {
3975 } else if (act & DO_BRUTE) {
3976 if (firstchange == 0) {
3981 /* If %builtin not in path, check for builtin next */
3982 if (regular || (bltin < 0 && bcmd)) {
3985 entry->cmdtype = CMDBUILTIN;
3986 entry->u.cmd = bcmd;
3990 cmdp = cmdlookup(name, 1);
3991 cmdp->cmdtype = CMDBUILTIN;
3992 cmdp->param.cmd = bcmd;
3997 /* We have to search path. */
3998 prev = -1; /* where to start */
3999 if (cmdp && cmdp->rehash) { /* doing a rehash */
4000 if (cmdp->cmdtype == CMDBUILTIN)
4003 prev = cmdp->param.index;
4009 while ((fullname = padvance(&path, name)) != NULL) {
4010 stunalloc(fullname);
4012 if (idx >= firstchange) {
4016 if (prefix("builtin", pathopt)) {
4017 if ((bcmd = find_builtin(name))) {
4021 } else if (!(act & DO_NOFUN) &&
4022 prefix("func", pathopt)) {
4025 continue; /* ignore unimplemented options */
4028 /* if rehash, don't redo absolute path names */
4029 if (fullname[0] == '/' && idx <= prev &&
4030 idx < firstchange) {
4033 TRACE(("searchexec \"%s\": no change\n", name));
4036 while (stat(fullname, &statb) < 0) {
4037 if (errno != ENOENT && errno != ENOTDIR)
4041 e = EACCES; /* if we fail, this will be the error */
4042 if (!S_ISREG(statb.st_mode))
4044 if (pathopt) { /* this is a %func directory */
4045 stalloc(strlen(fullname) + 1);
4046 readcmdfile(fullname);
4047 if ((cmdp = cmdlookup(name, 0)) == NULL || cmdp->cmdtype != CMDFUNCTION)
4048 error("%s not defined in %s", name, fullname);
4049 stunalloc(fullname);
4052 TRACE(("searchexec \"%s\" returns \"%s\"\n", name, fullname));
4053 /* If we aren't called with DO_BRUTE and cmdp is set, it must
4054 be a function and we're being called with DO_NOFUN */
4056 entry->cmdtype = CMDNORMAL;
4057 entry->u.index = idx;
4061 cmdp = cmdlookup(name, 1);
4062 cmdp->cmdtype = CMDNORMAL;
4063 cmdp->param.index = idx;
4068 /* We failed. If there was an entry for this command, delete it */
4069 if (cmdp && updatetbl)
4072 out2fmt("%s: %s\n", name, errmsg(e, E_EXEC));
4073 entry->cmdtype = CMDUNKNOWN;
4078 entry->cmdtype = cmdp->cmdtype;
4079 entry->u = cmdp->param;
4085 * Search the table of builtin commands.
4089 bstrcmp(const void *name, const void *b)
4091 return strcmp((const char *)name, (*(const char *const *) b)+1);
4094 static struct builtincmd *
4095 find_builtin(const char *name)
4097 struct builtincmd *bp;
4099 bp = bsearch(name, builtincmds, NUMBUILTINS, sizeof(struct builtincmd),
4107 * Called when a cd is done. Marks all commands so the next time they
4108 * are executed they will be rehashed.
4113 struct tblentry **pp;
4114 struct tblentry *cmdp;
4116 for (pp = cmdtable ; pp < &cmdtable[CMDTABLESIZE] ; pp++) {
4117 for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
4118 if (cmdp->cmdtype == CMDNORMAL
4119 || (cmdp->cmdtype == CMDBUILTIN && builtinloc >= 0))
4128 * Called before PATH is changed. The argument is the new value of PATH;
4129 * pathval() still returns the old value at this point. Called with
4134 changepath(const char *newval)
4139 firstchange = path_change(newval, &bltin);
4140 if (builtinloc < 0 && bltin >= 0)
4141 builtinloc = bltin; /* zap builtins */
4142 clearcmdentry(firstchange);
4148 * Clear out command entries. The argument specifies the first entry in
4149 * PATH which has changed.
4153 clearcmdentry(firstchange)
4156 struct tblentry **tblp;
4157 struct tblentry **pp;
4158 struct tblentry *cmdp;
4161 for (tblp = cmdtable ; tblp < &cmdtable[CMDTABLESIZE] ; tblp++) {
4163 while ((cmdp = *pp) != NULL) {
4164 if ((cmdp->cmdtype == CMDNORMAL &&
4165 cmdp->param.index >= firstchange)
4166 || (cmdp->cmdtype == CMDBUILTIN &&
4167 builtinloc >= firstchange)) {
4180 * Delete all functions.
4185 struct tblentry **tblp;
4186 struct tblentry **pp;
4187 struct tblentry *cmdp;
4190 for (tblp = cmdtable ; tblp < &cmdtable[CMDTABLESIZE] ; tblp++) {
4192 while ((cmdp = *pp) != NULL) {
4193 if (cmdp->cmdtype == CMDFUNCTION) {
4195 freefunc(cmdp->param.func);
4208 * Locate a command in the command hash table. If "add" is nonzero,
4209 * add the command to the table if it is not already present. The
4210 * variable "lastcmdentry" is set to point to the address of the link
4211 * pointing to the entry, so that delete_cmd_entry can delete the
4215 static struct tblentry **lastcmdentry;
4217 static struct tblentry *
4218 cmdlookup(const char *name, int add)
4222 struct tblentry *cmdp;
4223 struct tblentry **pp;
4230 pp = &cmdtable[hashval % CMDTABLESIZE];
4231 for (cmdp = *pp ; cmdp ; cmdp = cmdp->next) {
4232 if (equal(cmdp->cmdname, name))
4236 if (add && cmdp == NULL) {
4238 cmdp = *pp = ckmalloc(sizeof (struct tblentry) - ARB
4239 + strlen(name) + 1);
4241 cmdp->cmdtype = CMDUNKNOWN;
4243 strcpy(cmdp->cmdname, name);
4251 * Delete the command entry returned on the last lookup.
4255 delete_cmd_entry() {
4256 struct tblentry *cmdp;
4259 cmdp = *lastcmdentry;
4260 *lastcmdentry = cmdp->next;
4269 static const short nodesize[26] = {
4270 ALIGN(sizeof (struct nbinary)),
4271 ALIGN(sizeof (struct ncmd)),
4272 ALIGN(sizeof (struct npipe)),
4273 ALIGN(sizeof (struct nredir)),
4274 ALIGN(sizeof (struct nredir)),
4275 ALIGN(sizeof (struct nredir)),
4276 ALIGN(sizeof (struct nbinary)),
4277 ALIGN(sizeof (struct nbinary)),
4278 ALIGN(sizeof (struct nif)),
4279 ALIGN(sizeof (struct nbinary)),
4280 ALIGN(sizeof (struct nbinary)),
4281 ALIGN(sizeof (struct nfor)),
4282 ALIGN(sizeof (struct ncase)),
4283 ALIGN(sizeof (struct nclist)),
4284 ALIGN(sizeof (struct narg)),
4285 ALIGN(sizeof (struct narg)),
4286 ALIGN(sizeof (struct nfile)),
4287 ALIGN(sizeof (struct nfile)),
4288 ALIGN(sizeof (struct nfile)),
4289 ALIGN(sizeof (struct nfile)),
4290 ALIGN(sizeof (struct nfile)),
4291 ALIGN(sizeof (struct ndup)),
4292 ALIGN(sizeof (struct ndup)),
4293 ALIGN(sizeof (struct nhere)),
4294 ALIGN(sizeof (struct nhere)),
4295 ALIGN(sizeof (struct nnot)),
4301 * Delete a function if it exists.
4305 unsetfunc(char *name)
4307 struct tblentry *cmdp;
4309 if ((cmdp = cmdlookup(name, 0)) != NULL && cmdp->cmdtype == CMDFUNCTION) {
4310 freefunc(cmdp->param.func);
4317 * Locate and print what a word is...
4321 typecmd(int argc, char **argv)
4329 for (i = 1; i < argc; i++) {
4330 argv_a[0] = argv[i];
4333 err |= hashcmd(argc, argv);
4340 commandcmd(argc, argv)
4345 int default_path = 0;
4346 int verify_only = 0;
4347 int verbose_verify_only = 0;
4349 while ((c = nextopt("pvV")) != '\0')
4358 verbose_verify_only = 1;
4362 if (default_path + verify_only + verbose_verify_only > 1 ||
4365 "command [-p] command [arg ...]\n"
4366 "command {-v|-V} command\n");
4370 if (verify_only || verbose_verify_only) {
4374 argv_a[0] = *argptr;
4376 optptr = verbose_verify_only ? "v" : "V"; /* reverse special */
4377 return hashcmd(argc, argv);
4385 path_change(newval, bltin)
4389 const char *old, *new;
4395 firstchange = 9999; /* assume no change */
4401 if ((*old == '\0' && *new == ':')
4402 || (*old == ':' && *new == '\0'))
4404 old = new; /* ignore subsequent differences */
4408 if (*new == '%' && *bltin < 0 && prefix("builtin", new + 1))
4415 if (builtinloc >= 0 && *bltin < 0)
4420 * Routines to expand arguments to commands. We have to deal with
4421 * backquotes, shell variables, and file metacharacters.
4426 #define RMESCAPE_ALLOC 0x1 /* Allocate a new string */
4427 #define RMESCAPE_GLOB 0x2 /* Add backslashes for glob */
4430 * Structure specifying which parts of the string should be searched
4431 * for IFS characters.
4435 struct ifsregion *next; /* next region in list */
4436 int begoff; /* offset of start of region */
4437 int endoff; /* offset of end of region */
4438 int nulonly; /* search for nul bytes only */
4442 static char *expdest; /* output of current string */
4443 static struct nodelist *argbackq; /* list of back quote expressions */
4444 static struct ifsregion ifsfirst; /* first struct in list of ifs regions */
4445 static struct ifsregion *ifslastp; /* last struct in list */
4446 static struct arglist exparg; /* holds expanded arg list */
4448 static void argstr (char *, int);
4449 static char *exptilde (char *, int);
4450 static void expbackq (union node *, int, int);
4451 static int subevalvar (char *, char *, int, int, int, int, int);
4452 static int varisset (char *, int);
4453 static void strtodest (const char *, const char *, int);
4454 static void varvalue (char *, int, int);
4455 static void recordregion (int, int, int);
4456 static void removerecordregions (int);
4457 static void ifsbreakup (char *, struct arglist *);
4458 static void ifsfree (void);
4459 static void expandmeta (struct strlist *, int);
4460 #if defined(__GLIBC__) && __GLIBC__ >= 2 && !defined(FNMATCH_BROKEN)
4461 #define preglob(p) _rmescapes((p), RMESCAPE_ALLOC | RMESCAPE_GLOB)
4462 #if !defined(GLOB_BROKEN)
4463 static void addglob (const glob_t *);
4466 #if !(defined(__GLIBC__) && __GLIBC__ >= 2 && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN))
4467 static void expmeta (char *, char *);
4469 #if !(defined(__GLIBC__) && __GLIBC__ >= 2 && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN))
4470 static struct strlist *expsort (struct strlist *);
4471 static struct strlist *msort (struct strlist *, int);
4473 static int patmatch (char *, char *, int);
4474 #if defined(__GLIBC__) && __GLIBC__ >= 2 && !defined(FNMATCH_BROKEN)
4475 static int patmatch2 (char *, char *, int);
4477 static int pmatch (char *, char *, int);
4478 #define patmatch2 patmatch
4480 static char *cvtnum (int, char *);
4483 * Expand shell variables and backquotes inside a here document.
4486 /* arg: the document, fd: where to write the expanded version */
4488 expandhere(union node *arg, int fd)
4491 expandarg(arg, (struct arglist *)NULL, 0);
4492 xwrite(fd, stackblock(), expdest - stackblock());
4497 * Perform variable substitution and command substitution on an argument,
4498 * placing the resulting list of arguments in arglist. If EXP_FULL is true,
4499 * perform splitting and file name expansion. When arglist is NULL, perform
4500 * here document expansion.
4504 expandarg(arg, arglist, flag)
4506 struct arglist *arglist;
4512 argbackq = arg->narg.backquote;
4513 STARTSTACKSTR(expdest);
4514 ifsfirst.next = NULL;
4516 argstr(arg->narg.text, flag);
4517 if (arglist == NULL) {
4518 return; /* here document expanded */
4520 STPUTC('\0', expdest);
4521 p = grabstackstr(expdest);
4522 exparg.lastp = &exparg.list;
4526 if (flag & EXP_FULL) {
4527 ifsbreakup(p, &exparg);
4528 *exparg.lastp = NULL;
4529 exparg.lastp = &exparg.list;
4530 expandmeta(exparg.list, flag);
4532 if (flag & EXP_REDIR) /*XXX - for now, just remove escapes */
4534 sp = (struct strlist *)stalloc(sizeof (struct strlist));
4537 exparg.lastp = &sp->next;
4540 *exparg.lastp = NULL;
4542 *arglist->lastp = exparg.list;
4543 arglist->lastp = exparg.lastp;
4549 * Expand a variable, and return a pointer to the next character in the
4553 static inline char *
4569 int quotes = flag & (EXP_FULL | EXP_CASE);
4572 subtype = varflags & VSTYPE;
4577 p = strchr(p, '=') + 1;
4578 again: /* jump here after setting a variable with ${var=text} */
4580 set = varisset(var, varflags & VSNUL);
4583 val = lookupvar(var);
4584 if (val == NULL || ((varflags & VSNUL) && val[0] == '\0')) {
4591 startloc = expdest - stackblock();
4592 if (set && subtype != VSPLUS) {
4593 /* insert the value of the variable */
4595 varvalue(var, varflags & VSQUOTE, flag);
4596 if (subtype == VSLENGTH) {
4597 varlen = expdest - stackblock() - startloc;
4598 STADJUST(-varlen, expdest);
4601 if (subtype == VSLENGTH) {
4602 varlen = strlen(val);
4606 varflags & VSQUOTE ?
4607 DQSYNTAX : BASESYNTAX,
4614 if (subtype == VSPLUS)
4617 easy = ((varflags & VSQUOTE) == 0 ||
4618 (*var == '@' && shellparam.nparam != 1));
4623 expdest = cvtnum(varlen, expdest);
4630 recordregion(startloc, expdest - stackblock(),
4631 varflags & VSQUOTE);
4647 case VSTRIMRIGHTMAX:
4651 * Terminate the string and start recording the pattern
4654 STPUTC('\0', expdest);
4655 patloc = expdest - stackblock();
4656 if (subevalvar(p, NULL, patloc, subtype,
4657 startloc, varflags, quotes) == 0) {
4658 int amount = (expdest - stackblock() - patloc) + 1;
4659 STADJUST(-amount, expdest);
4661 /* Remove any recorded regions beyond start of variable */
4662 removerecordregions(startloc);
4668 if (subevalvar(p, var, 0, subtype, startloc,
4669 varflags, quotes)) {
4672 * Remove any recorded regions beyond
4675 removerecordregions(startloc);
4690 if (subtype != VSNORMAL) { /* skip to end of alternative */
4693 if ((c = *p++) == CTLESC)
4695 else if (c == CTLBACKQ || c == (CTLBACKQ|CTLQUOTE)) {
4697 argbackq = argbackq->next;
4698 } else if (c == CTLVAR) {
4699 if ((*p++ & VSTYPE) != VSNORMAL)
4701 } else if (c == CTLENDVAR) {
4712 * Perform variable and command substitution. If EXP_FULL is set, output CTLESC
4713 * characters to allow for further processing. Otherwise treat
4714 * $@ like $* since no splitting will be performed.
4723 int quotes = flag & (EXP_FULL | EXP_CASE); /* do CTLESC */
4726 if (*p == '~' && (flag & (EXP_TILDE | EXP_VARTILDE)))
4727 p = exptilde(p, flag);
4731 case CTLENDVAR: /* ??? */
4734 /* "$@" syntax adherence hack */
4735 if (p[0] == CTLVAR && p[2] == '@' && p[3] == '=')
4737 if ((flag & EXP_FULL) != 0)
4747 p = evalvar(p, flag);
4750 case CTLBACKQ|CTLQUOTE:
4751 expbackq(argbackq->n, c & CTLQUOTE, flag);
4752 argbackq = argbackq->next;
4754 #ifdef ASH_MATH_SUPPORT
4762 * sort of a hack - expand tildes in variable
4763 * assignments (after the first '=' and after ':'s).
4766 if (flag & EXP_VARTILDE && *p == '~') {
4773 p = exptilde(p, flag);
4789 char c, *startp = p;
4792 int quotes = flag & (EXP_FULL | EXP_CASE);
4794 while ((c = *p) != '\0') {
4801 if (flag & EXP_VARTILDE)
4811 if (*(startp+1) == '\0') {
4812 if ((home = lookupvar("HOME")) == NULL)
4815 if ((pw = getpwnam(startp+1)) == NULL)
4822 strtodest(home, SQSYNTAX, quotes);
4831 removerecordregions(int endoff)
4833 if (ifslastp == NULL)
4836 if (ifsfirst.endoff > endoff) {
4837 while (ifsfirst.next != NULL) {
4838 struct ifsregion *ifsp;
4840 ifsp = ifsfirst.next->next;
4841 ckfree(ifsfirst.next);
4842 ifsfirst.next = ifsp;
4845 if (ifsfirst.begoff > endoff)
4848 ifslastp = &ifsfirst;
4849 ifsfirst.endoff = endoff;
4854 ifslastp = &ifsfirst;
4855 while (ifslastp->next && ifslastp->next->begoff < endoff)
4856 ifslastp=ifslastp->next;
4857 while (ifslastp->next != NULL) {
4858 struct ifsregion *ifsp;
4860 ifsp = ifslastp->next->next;
4861 ckfree(ifslastp->next);
4862 ifslastp->next = ifsp;
4865 if (ifslastp->endoff > endoff)
4866 ifslastp->endoff = endoff;
4870 #ifdef ASH_MATH_SUPPORT
4872 * Expand arithmetic expression. Backup to start of expression,
4873 * evaluate, place result in (backed up) result, adjust string position.
4881 int quotes = flag & (EXP_FULL | EXP_CASE);
4887 * This routine is slightly over-complicated for
4888 * efficiency. First we make sure there is
4889 * enough space for the result, which may be bigger
4890 * than the expression if we add exponentation. Next we
4891 * scan backwards looking for the start of arithmetic. If the
4892 * next previous character is a CTLESC character, then we
4893 * have to rescan starting from the beginning since CTLESC
4894 * characters have to be processed left to right.
4896 CHECKSTRSPACE(10, expdest);
4897 USTPUTC('\0', expdest);
4898 start = stackblock();
4900 while (*p != CTLARI && p >= start)
4903 error("missing CTLARI (shouldn't happen)");
4904 if (p > start && *(p-1) == CTLESC)
4905 for (p = start; *p != CTLARI; p++)
4914 removerecordregions(begoff);
4917 result = arith(p+2);
4918 snprintf(p, 12, "%d", result);
4924 recordregion(begoff, p - 1 - start, 0);
4925 result = expdest - p + 1;
4926 STADJUST(-result, expdest);
4931 * Expand stuff in backwards quotes.
4935 expbackq(cmd, quoted, flag)
4940 volatile struct backcmd in;
4944 char *dest = expdest;
4945 volatile struct ifsregion saveifs;
4946 struct ifsregion *volatile savelastp;
4947 struct nodelist *volatile saveargbackq;
4949 int startloc = dest - stackblock();
4950 char const *syntax = quoted? DQSYNTAX : BASESYNTAX;
4951 volatile int saveherefd;
4952 int quotes = flag & (EXP_FULL | EXP_CASE);
4953 struct jmploc jmploc;
4954 struct jmploc *volatile savehandler;
4958 /* Avoid longjmp clobbering */
4969 savelastp = ifslastp;
4970 saveargbackq = argbackq;
4971 saveherefd = herefd;
4973 if ((ex = setjmp(jmploc.loc))) {
4976 savehandler = handler;
4979 p = grabstackstr(dest);
4980 evalbackcmd(cmd, (struct backcmd *) &in);
4981 ungrabstackstr(p, dest);
4985 ifslastp = savelastp;
4986 argbackq = saveargbackq;
4987 herefd = saveherefd;
4995 if (--in.nleft < 0) {
4998 i = safe_read(in.fd, buf, sizeof buf);
4999 TRACE(("expbackq: read returns %d\n", i));
5006 if (lastc != '\0') {
5007 if (quotes && syntax[(int)lastc] == CCTL)
5008 STPUTC(CTLESC, dest);
5009 STPUTC(lastc, dest);
5013 /* Eat all trailing newlines */
5014 for (; dest > stackblock() && dest[-1] == '\n';)
5023 exitstatus = waitforjob(in.jp);
5024 handler = savehandler;
5026 longjmp(handler->loc, 1);
5029 recordregion(startloc, dest - stackblock(), 0);
5030 TRACE(("evalbackq: size=%d: \"%.*s\"\n",
5031 (dest - stackblock()) - startloc,
5032 (dest - stackblock()) - startloc,
5033 stackblock() + startloc));
5039 subevalvar(p, str, strloc, subtype, startloc, varflags, quotes)
5052 int saveherefd = herefd;
5053 struct nodelist *saveargbackq = argbackq;
5057 argstr(p, subtype != VSASSIGN && subtype != VSQUESTION ? EXP_CASE : 0);
5058 STACKSTRNUL(expdest);
5059 herefd = saveherefd;
5060 argbackq = saveargbackq;
5061 startp = stackblock() + startloc;
5063 str = stackblock() + strloc;
5067 setvar(str, startp, 0);
5068 amount = startp - expdest;
5069 STADJUST(amount, expdest);
5076 if (*p != CTLENDVAR) {
5077 out2fmt(snlfmt, startp);
5078 error((char *)NULL);
5080 error("%.*s: parameter %snot set", p - str - 1,
5081 str, (varflags & VSNUL) ? "null or "
5086 for (loc = startp; loc < str; loc++) {
5089 if (patmatch2(str, startp, quotes))
5092 if (quotes && *loc == CTLESC)
5098 for (loc = str - 1; loc >= startp;) {
5101 if (patmatch2(str, startp, quotes))
5105 if (quotes && loc > startp && *(loc - 1) == CTLESC) {
5106 for (q = startp; q < loc; q++)
5116 for (loc = str - 1; loc >= startp;) {
5117 if (patmatch2(str, loc, quotes))
5120 if (quotes && loc > startp && *(loc - 1) == CTLESC) {
5121 for (q = startp; q < loc; q++)
5130 case VSTRIMRIGHTMAX:
5131 for (loc = startp; loc < str - 1; loc++) {
5132 if (patmatch2(str, loc, quotes))
5134 if (quotes && *loc == CTLESC)
5147 amount = ((str - 1) - (loc - startp)) - expdest;
5148 STADJUST(amount, expdest);
5149 while (loc != str - 1)
5154 amount = loc - expdest;
5155 STADJUST(amount, expdest);
5156 STPUTC('\0', expdest);
5157 STADJUST(-1, expdest);
5163 * Test whether a specialized variable is set.
5167 varisset(name, nulok)
5172 return backgndpid != -1;
5173 else if (*name == '@' || *name == '*') {
5174 if (*shellparam.p == NULL)
5180 for (av = shellparam.p; *av; av++)
5185 } else if (is_digit(*name)) {
5187 int num = atoi(name);
5189 if (num > shellparam.nparam)
5195 ap = shellparam.p[num - 1];
5197 if (nulok && (ap == NULL || *ap == '\0'))
5204 * Put a string on the stack.
5208 strtodest(p, syntax, quotes)
5214 if (quotes && syntax[(int) *p] == CCTL)
5215 STPUTC(CTLESC, expdest);
5216 STPUTC(*p++, expdest);
5221 * Add the value of a specialized variable to the stack string.
5225 varvalue(name, quoted, flags)
5237 int allow_split = flags & EXP_FULL;
5238 int quotes = flags & (EXP_FULL | EXP_CASE);
5240 syntax = quoted ? DQSYNTAX : BASESYNTAX;
5249 num = shellparam.nparam;
5254 expdest = cvtnum(num, expdest);
5257 for (i = 0 ; i < NOPTS ; i++) {
5259 STPUTC(optent_letter(optlist[i]), expdest);
5263 if (allow_split && quoted) {
5264 sep = 1 << CHAR_BIT;
5269 sep = ifsset() ? ifsval()[0] : ' ';
5271 sepq = syntax[(int) sep] == CCTL;
5274 for (ap = shellparam.p ; (p = *ap++) != NULL ; ) {
5275 strtodest(p, syntax, quotes);
5278 STPUTC(CTLESC, expdest);
5279 STPUTC(sep, expdest);
5284 strtodest(arg0, syntax, quotes);
5288 if (num > 0 && num <= shellparam.nparam) {
5289 strtodest(shellparam.p[num - 1], syntax, quotes);
5297 * Record the fact that we have to scan this region of the
5298 * string for IFS characters.
5302 recordregion(start, end, nulonly)
5307 struct ifsregion *ifsp;
5309 if (ifslastp == NULL) {
5313 ifsp = (struct ifsregion *)ckmalloc(sizeof (struct ifsregion));
5315 ifslastp->next = ifsp;
5319 ifslastp->begoff = start;
5320 ifslastp->endoff = end;
5321 ifslastp->nulonly = nulonly;
5327 * Break the argument string into pieces based upon IFS and add the
5328 * strings to the argument list. The regions of the string to be
5329 * searched for IFS characters have been stored by recordregion.
5332 ifsbreakup(string, arglist)
5334 struct arglist *arglist;
5336 struct ifsregion *ifsp;
5341 const char *ifs, *realifs;
5349 realifs = ifsset() ? ifsval() : defifs;
5350 if (ifslastp != NULL) {
5353 p = string + ifsp->begoff;
5354 nulonly = ifsp->nulonly;
5355 ifs = nulonly ? nullstr : realifs;
5357 while (p < string + ifsp->endoff) {
5361 if (strchr(ifs, *p)) {
5363 ifsspc = (strchr(defifs, *p) != NULL);
5364 /* Ignore IFS whitespace at start */
5365 if (q == start && ifsspc) {
5371 sp = (struct strlist *)stalloc(sizeof *sp);
5373 *arglist->lastp = sp;
5374 arglist->lastp = &sp->next;
5378 if (p >= string + ifsp->endoff) {
5384 if (strchr(ifs, *p) == NULL ) {
5387 } else if (strchr(defifs, *p) == NULL) {
5403 } while ((ifsp = ifsp->next) != NULL);
5404 if (!(*start || (!ifsspc && start > string && nulonly))) {
5409 sp = (struct strlist *)stalloc(sizeof *sp);
5411 *arglist->lastp = sp;
5412 arglist->lastp = &sp->next;
5418 while (ifsfirst.next != NULL) {
5419 struct ifsregion *ifsp;
5421 ifsp = ifsfirst.next->next;
5422 ckfree(ifsfirst.next);
5423 ifsfirst.next = ifsp;
5427 ifsfirst.next = NULL;
5431 * Add a file name to the list.
5435 addfname(const char *name)
5441 sp = (struct strlist *)stalloc(sizeof *sp);
5444 exparg.lastp = &sp->next;
5448 * Expand shell metacharacters. At this point, the only control characters
5449 * should be escapes. The results are stored in the list exparg.
5452 #if defined(__GLIBC__) && __GLIBC__ >= 2 && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN)
5454 expandmeta(str, flag)
5455 struct strlist *str;
5460 /* TODO - EXP_REDIR */
5465 p = preglob(str->text);
5467 switch (glob(p, GLOB_NOMAGIC, 0, &pglob)) {
5469 if (!(pglob.gl_flags & GLOB_MAGCHAR))
5480 *exparg.lastp = str;
5481 rmescapes(str->text);
5482 exparg.lastp = &str->next;
5484 default: /* GLOB_NOSPACE */
5485 error("Out of space");
5493 * Add the result of glob(3) to the list.
5498 const glob_t *pglob;
5500 char **p = pglob->gl_pathv;
5508 #else /* defined(__GLIBC__) && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN) */
5509 static char *expdir;
5513 expandmeta(str, flag)
5514 struct strlist *str;
5518 struct strlist **savelastp;
5521 /* TODO - EXP_REDIR */
5527 for (;;) { /* fast check for meta chars */
5528 if ((c = *p++) == '\0')
5530 if (c == '*' || c == '?' || c == '[' || c == '!')
5533 savelastp = exparg.lastp;
5535 if (expdir == NULL) {
5536 int i = strlen(str->text);
5537 expdir = ckmalloc(i < 2048 ? 2048 : i); /* XXX */
5540 expmeta(expdir, str->text);
5544 if (exparg.lastp == savelastp) {
5549 *exparg.lastp = str;
5550 rmescapes(str->text);
5551 exparg.lastp = &str->next;
5553 *exparg.lastp = NULL;
5554 *savelastp = sp = expsort(*savelastp);
5555 while (sp->next != NULL)
5557 exparg.lastp = &sp->next;
5565 * Do metacharacter (i.e. *, ?, [...]) expansion.
5569 expmeta(enddir, name)
5587 for (p = name ; ; p++) {
5588 if (*p == '*' || *p == '?')
5590 else if (*p == '[') {
5595 while (*q == CTLQUOTEMARK)
5599 if (*q == '/' || *q == '\0')
5606 } else if (*p == '!' && p[1] == '!' && (p == name || p[-1] == '/')) {
5608 } else if (*p == '\0')
5610 else if (*p == CTLQUOTEMARK)
5612 else if (*p == CTLESC)
5620 if (metaflag == 0) { /* we've reached the end of the file name */
5621 if (enddir != expdir)
5623 for (p = name ; ; p++) {
5624 if (*p == CTLQUOTEMARK)
5632 if (metaflag == 0 || lstat(expdir, &statb) >= 0)
5637 if (start != name) {
5640 while (*p == CTLQUOTEMARK)
5647 if (enddir == expdir) {
5649 } else if (enddir == expdir + 1 && *expdir == '/') {
5655 if ((dirp = opendir(cp)) == NULL)
5657 if (enddir != expdir)
5659 if (*endname == 0) {
5667 while (*p == CTLQUOTEMARK)
5673 while (! int_pending() && (dp = readdir(dirp)) != NULL) {
5674 if (dp->d_name[0] == '.' && ! matchdot)
5676 if (patmatch(start, dp->d_name, 0)) {
5678 strcpy(enddir, dp->d_name);
5681 for (p = enddir, cp = dp->d_name;
5682 (*p++ = *cp++) != '\0';)
5685 expmeta(p, endname);
5693 #endif /* defined(__GLIBC__) && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN) */
5697 #if !(defined(__GLIBC__) && __GLIBC__ >= 2 && !defined(FNMATCH_BROKEN) && !defined(GLOB_BROKEN))
5699 * Sort the results of file name expansion. It calculates the number of
5700 * strings to sort and then calls msort (short for merge sort) to do the
5704 static struct strlist *
5706 struct strlist *str;
5712 for (sp = str ; sp ; sp = sp->next)
5714 return msort(str, len);
5718 static struct strlist *
5720 struct strlist *list;
5723 struct strlist *p, *q = NULL;
5724 struct strlist **lpp;
5732 for (n = half ; --n >= 0 ; ) {
5736 q->next = NULL; /* terminate first half of list */
5737 q = msort(list, half); /* sort first half of list */
5738 p = msort(p, len - half); /* sort second half */
5741 if (strcmp(p->text, q->text) < 0) {
5744 if ((p = *lpp) == NULL) {
5751 if ((q = *lpp) == NULL) {
5764 * Returns true if the pattern matches the string.
5767 #if defined(__GLIBC__) && __GLIBC__ >= 2 && !defined(FNMATCH_BROKEN)
5768 /* squoted: string might have quote chars */
5770 patmatch(char *pattern, char *string, int squoted)
5775 p = preglob(pattern);
5776 q = squoted ? _rmescapes(string, RMESCAPE_ALLOC) : string;
5778 return !fnmatch(p, q, 0);
5783 patmatch2(char *pattern, char *string, int squoted)
5789 p = grabstackstr(expdest);
5790 res = patmatch(pattern, string, squoted);
5791 ungrabstackstr(p, expdest);
5796 patmatch(char *pattern, char *string, int squoted) {
5797 return pmatch(pattern, string, squoted);
5802 pmatch(char *pattern, char *string, int squoted)
5814 if (squoted && *q == CTLESC)
5822 if (squoted && *q == CTLESC)
5829 while (c == CTLQUOTEMARK || c == '*')
5831 if (c != CTLESC && c != CTLQUOTEMARK &&
5832 c != '?' && c != '*' && c != '[') {
5834 if (squoted && *q == CTLESC &&
5839 if (squoted && *q == CTLESC)
5845 if (pmatch(p, q, squoted))
5847 if (squoted && *q == CTLESC)
5849 } while (*q++ != '\0');
5860 while (*endp == CTLQUOTEMARK)
5863 goto dft; /* no matching ] */
5864 if (*endp == CTLESC)
5876 if (squoted && chr == CTLESC)
5882 if (c == CTLQUOTEMARK)
5886 if (*p == '-' && p[1] != ']') {
5888 while (*p == CTLQUOTEMARK)
5892 if (chr >= c && chr <= *p)
5899 } while ((c = *p++) != ']');
5900 if (found == invert)
5905 if (squoted && *q == CTLESC)
5922 * Remove any CTLESC characters from a string.
5925 #if defined(__GLIBC__) && __GLIBC__ >= 2 && !defined(FNMATCH_BROKEN)
5927 _rmescapes(char *str, int flag)
5930 static const char qchars[] = { CTLESC, CTLQUOTEMARK, 0 };
5932 p = strpbrk(str, qchars);
5938 if (flag & RMESCAPE_ALLOC) {
5939 size_t len = p - str;
5940 q = r = stalloc(strlen(p) + len + 1);
5942 memcpy(q, str, len);
5947 if (*p == CTLQUOTEMARK) {
5953 if (flag & RMESCAPE_GLOB && *p != '/') {
5970 while (*p != CTLESC && *p != CTLQUOTEMARK) {
5976 if (*p == CTLQUOTEMARK) {
5991 * See if a pattern matches in a case statement.
5995 casematch(union node *pattern, const char *val)
5997 struct stackmark smark;
6001 setstackmark(&smark);
6002 argbackq = pattern->narg.backquote;
6003 STARTSTACKSTR(expdest);
6005 argstr(pattern->narg.text, EXP_TILDE | EXP_CASE);
6006 STPUTC('\0', expdest);
6007 p = grabstackstr(expdest);
6008 result = patmatch(p, (char *)val, 0);
6009 popstackmark(&smark);
6024 CHECKSTRSPACE(32, buf);
6025 len = sprintf(buf, "%d", num);
6030 * Editline and history functions (and glue).
6032 static int histcmd(argc, argv)
6036 error("not compiled with history support");
6042 struct redirtab *next;
6043 short renamed[10]; /* Current ash support only 0-9 descriptors */
6044 /* char renamed[10]; */ /* char on arm (and others) can't be negative */
6047 static struct redirtab *redirlist;
6049 extern char **environ;
6054 * Initialization code.
6067 basepf.nextc = basepf.buf = basebuf;
6076 for (envp = environ ; *envp ; envp++) {
6077 if (strchr(*envp, '=')) {
6078 setvareq(*envp, VEXPORT|VTEXTFIXED);
6082 snprintf(ppid, sizeof(ppid), "%d", (int) getppid());
6083 setvar("PPID", ppid, 0);
6090 * This routine is called when an error or an interrupt occurs in an
6091 * interactive shell and control is returned to the main command loop.
6094 /* 1 == check for aliases, 2 == also check for assignments */
6095 static int checkalias; /* also used in no alias mode for check assignments */
6109 if (exception != EXSHELLPROC)
6110 parselleft = parsenleft = 0; /* clear input buffer */
6114 /* from parser.c: */
6132 * This file implements the input routines used by the parser.
6135 #ifdef BB_FEATURE_COMMAND_EDITING
6136 static const char * cmdedit_prompt;
6137 static inline void putprompt(const char *s) {
6141 static inline void putprompt(const char *s) {
6146 #define EOF_NLEFT -99 /* value of parsenleft when EOF pushed back */
6151 * Same as pgetc(), but ignores PEOA.
6161 } while (c == PEOA);
6165 static inline int pgetc2() { return pgetc_macro(); }
6169 * Read a line from the script.
6172 static inline char *
6173 pfgets(char *line, int len)
6179 while (--nleft > 0) {
6198 char *buf = parsefile->buf;
6202 #ifdef BB_FEATURE_COMMAND_EDITING
6205 nr = safe_read(parsefile->fd, buf, BUFSIZ - 1);
6207 nr = cmdedit_read_input((char*)cmdedit_prompt, buf);
6211 nr = safe_read(parsefile->fd, buf, BUFSIZ - 1);
6215 if (parsefile->fd == 0 && errno == EWOULDBLOCK) {
6216 int flags = fcntl(0, F_GETFL, 0);
6217 if (flags >= 0 && flags & O_NONBLOCK) {
6218 flags &=~ O_NONBLOCK;
6219 if (fcntl(0, F_SETFL, flags) >= 0) {
6220 out2str("sh: turning off NDELAY mode\n");
6232 struct strpush *sp = parsefile->strpush;
6237 if (parsenextc[-1] == ' ' || parsenextc[-1] == '\t') {
6242 if (sp->string != sp->ap->val) {
6246 sp->ap->flag &= ~ALIASINUSE;
6247 if (sp->ap->flag & ALIASDEAD) {
6248 unalias(sp->ap->name);
6252 parsenextc = sp->prevstring;
6253 parsenleft = sp->prevnleft;
6254 /*dprintf("*** calling popstring: restoring to '%s'\n", parsenextc);*/
6255 parsefile->strpush = sp->prev;
6256 if (sp != &(parsefile->basestrpush))
6263 * Refill the input buffer and return the next input character:
6265 * 1) If a string was pushed back on the input, pop it;
6266 * 2) If an EOF was pushed back (parsenleft == EOF_NLEFT) or we are reading
6267 * from a string so we can't refill the buffer, return EOF.
6268 * 3) If the is more stuff in this buffer, use it else call read to fill it.
6269 * 4) Process input up to the next newline, deleting nul characters.
6279 while (parsefile->strpush) {
6281 if (parsenleft == -1 && parsefile->strpush->ap &&
6282 parsenextc[-1] != ' ' && parsenextc[-1] != '\t') {
6287 if (--parsenleft >= 0)
6288 return (*parsenextc++);
6290 if (parsenleft == EOF_NLEFT || parsefile->buf == NULL)
6295 if (parselleft <= 0) {
6296 if ((parselleft = preadfd()) <= 0) {
6297 parselleft = parsenleft = EOF_NLEFT;
6304 /* delete nul characters */
6305 for (more = 1; more;) {
6313 parsenleft = q - parsenextc;
6314 more = 0; /* Stop processing here */
6320 if (--parselleft <= 0 && more) {
6321 parsenleft = q - parsenextc - 1;
6332 out2str(parsenextc);
6337 return *parsenextc++;
6342 * Push a string back onto the input at this current parsefile level.
6343 * We handle aliases this way.
6346 pushstring(char *s, int len, void *ap)
6351 /*dprintf("*** calling pushstring: %s, %d\n", s, len);*/
6352 if (parsefile->strpush) {
6353 sp = ckmalloc(sizeof (struct strpush));
6354 sp->prev = parsefile->strpush;
6355 parsefile->strpush = sp;
6357 sp = parsefile->strpush = &(parsefile->basestrpush);
6358 sp->prevstring = parsenextc;
6359 sp->prevnleft = parsenleft;
6361 sp->ap = (struct alias *)ap;
6363 ((struct alias *)ap)->flag |= ALIASINUSE;
6374 * Like setinputfile, but takes input from a string.
6378 setinputstring(char *string)
6382 parsenextc = string;
6383 parsenleft = strlen(string);
6384 parsefile->buf = NULL;
6392 * To handle the "." command, a stack of input files is used. Pushfile
6393 * adds a new entry to the stack and popfile restores the previous level.
6398 struct parsefile *pf;
6400 parsefile->nleft = parsenleft;
6401 parsefile->lleft = parselleft;
6402 parsefile->nextc = parsenextc;
6403 parsefile->linno = plinno;
6404 pf = (struct parsefile *)ckmalloc(sizeof (struct parsefile));
6405 pf->prev = parsefile;
6408 pf->basestrpush.prev = NULL;
6413 static void restartjob (struct job *);
6415 static void freejob (struct job *);
6416 static struct job *getjob (const char *);
6417 static int dowait (int, struct job *);
6418 static void waitonint(int);
6422 * We keep track of whether or not fd0 has been redirected. This is for
6423 * background commands, where we want to redirect fd0 to /dev/null only
6424 * if it hasn't already been redirected.
6426 static int fd0_redirected = 0;
6428 /* Return true if fd 0 has already been redirected at least once. */
6430 fd0_redirected_p () {
6431 return fd0_redirected != 0;
6434 static void dupredirect (const union node *, int, int fd1dup);
6438 * Turn job control on and off.
6440 * Note: This code assumes that the third arg to ioctl is a character
6441 * pointer, which is true on Berkeley systems but not System V. Since
6442 * System V doesn't have job control yet, this isn't a problem now.
6447 static void setjobctl(int enable)
6449 #ifdef OLD_TTY_DRIVER
6453 if (enable == jobctl || rootshell == 0)
6456 do { /* while we are in the background */
6457 #ifdef OLD_TTY_DRIVER
6458 if (ioctl(2, TIOCGPGRP, (char *)&initialpgrp) < 0) {
6460 initialpgrp = tcgetpgrp(2);
6461 if (initialpgrp < 0) {
6463 out2str("sh: can't access tty; job control turned off\n");
6467 if (initialpgrp == -1)
6468 initialpgrp = getpgrp();
6469 else if (initialpgrp != getpgrp()) {
6470 killpg(initialpgrp, SIGTTIN);
6474 #ifdef OLD_TTY_DRIVER
6475 if (ioctl(2, TIOCGETD, (char *)&ldisc) < 0 || ldisc != NTTYDISC) {
6476 out2str("sh: need new tty driver to run job control; job control turned off\n");
6484 setpgid(0, rootpid);
6485 #ifdef OLD_TTY_DRIVER
6486 ioctl(2, TIOCSPGRP, (char *)&rootpid);
6488 tcsetpgrp(2, rootpid);
6490 } else { /* turning job control off */
6491 setpgid(0, initialpgrp);
6492 #ifdef OLD_TTY_DRIVER
6493 ioctl(2, TIOCSPGRP, (char *)&initialpgrp);
6495 tcsetpgrp(2, initialpgrp);
6506 /* A translation list so we can be polite to our users. */
6507 static char *signal_names[NSIG + 2] = {
6595 "Usage: kill [-s sigspec | -signum | -sigspec] [pid | job]... or\n"
6596 "kill -l [exitstatus]"
6600 if (*argv[1] == '-') {
6601 signo = decode_signal(argv[1] + 1, 1);
6605 while ((c = nextopt("ls:")) != '\0')
6611 signo = decode_signal(optionarg, 1);
6614 "invalid signal number or name: %s",
6622 "nextopt returned character code 0%o", c);
6629 if (!list && signo < 0)
6632 if ((signo < 0 || !*argptr) ^ list) {
6639 for (i = 1; i < NSIG; i++) {
6640 printf(snlfmt, signal_names[i] + 3);
6644 signo = atoi(*argptr);
6647 if (0 < signo && signo < NSIG)
6648 printf(snlfmt, signal_names[signo] + 3);
6650 error("invalid signal number or exit status: %s",
6656 if (**argptr == '%') {
6657 jp = getjob(*argptr);
6658 if (jp->jobctl == 0)
6659 error("job %s not created under job control",
6661 pid = -jp->ps[0].pid;
6663 pid = atoi(*argptr);
6664 if (kill(pid, signo) != 0)
6665 error("%s: %m", *argptr);
6666 } while (*++argptr);
6680 jp = getjob(argv[1]);
6681 if (jp->jobctl == 0)
6682 error("job not created under job control");
6683 pgrp = jp->ps[0].pid;
6684 #ifdef OLD_TTY_DRIVER
6685 ioctl(2, TIOCSPGRP, (char *)&pgrp);
6691 status = waitforjob(jp);
6705 jp = getjob(*++argv);
6706 if (jp->jobctl == 0)
6707 error("job not created under job control");
6709 } while (--argc > 1);
6718 struct procstat *ps;
6721 if (jp->state == JOBDONE)
6724 killpg(jp->ps[0].pid, SIGCONT);
6725 for (ps = jp->ps, i = jp->nprocs ; --i >= 0 ; ps++) {
6726 if (WIFSTOPPED(ps->status)) {
6735 static void showjobs(int change);
6749 * Print a list of jobs. If "change" is nonzero, only print jobs whose
6750 * statuses have changed since the last call to showjobs.
6752 * If the shell is interrupted in the process of creating a job, the
6753 * result may be a job structure containing zero processes. Such structures
6754 * will be freed here.
6765 struct procstat *ps;
6769 TRACE(("showjobs(%d) called\n", change));
6770 while (dowait(0, (struct job *)NULL) > 0);
6771 for (jobno = 1, jp = jobtab ; jobno <= njobs ; jobno++, jp++) {
6774 if (jp->nprocs == 0) {
6778 if (change && ! jp->changed)
6780 procno = jp->nprocs;
6781 for (ps = jp->ps ; ; ps++) { /* for each process */
6783 snprintf(s, 64, "[%d] %ld ", jobno,
6786 snprintf(s, 64, " %ld ",
6791 if (ps->status == -1) {
6792 /* don't print anything */
6793 } else if (WIFEXITED(ps->status)) {
6794 snprintf(s, 64, "Exit %d",
6795 WEXITSTATUS(ps->status));
6798 if (WIFSTOPPED(ps->status))
6799 i = WSTOPSIG(ps->status);
6800 else /* WIFSIGNALED(ps->status) */
6802 i = WTERMSIG(ps->status);
6803 if ((i & 0x7F) < NSIG && sys_siglist[i & 0x7F])
6804 strcpy(s, sys_siglist[i & 0x7F]);
6806 snprintf(s, 64, "Signal %d", i & 0x7F);
6807 if (WCOREDUMP(ps->status))
6808 strcat(s, " (core dumped)");
6813 "%*c%s\n", 30 - col >= 0 ? 30 - col : 0, ' ',
6820 if (jp->state == JOBDONE) {
6828 * Mark a job structure as unused.
6832 freejob(struct job *jp)
6834 const struct procstat *ps;
6838 for (i = jp->nprocs, ps = jp->ps ; --i >= 0 ; ps++) {
6839 if (ps->cmd != nullstr)
6842 if (jp->ps != &jp->ps0)
6846 if (curjob == jp - jobtab + 1)
6865 job = getjob(*++argv);
6869 for (;;) { /* loop until process terminated or stopped */
6872 status = job->ps[job->nprocs - 1].status;
6878 if (WIFEXITED(status))
6879 retval = WEXITSTATUS(status);
6881 else if (WIFSTOPPED(status))
6882 retval = WSTOPSIG(status) + 128;
6885 /* XXX: limits number of signals */
6886 retval = WTERMSIG(status) + 128;
6891 for (jp = jobtab ; ; jp++) {
6892 if (jp >= jobtab + njobs) { /* no running procs */
6895 if (jp->used && jp->state == 0)
6899 if (dowait(2, 0) < 0 && errno == EINTR) {
6908 * Convert a job name to a job structure.
6912 getjob(const char *name)
6922 if ((jobno = curjob) == 0 || jobtab[jobno - 1].used == 0)
6923 error("No current job");
6924 return &jobtab[jobno - 1];
6926 error("No current job");
6928 } else if (name[0] == '%') {
6929 if (is_digit(name[1])) {
6930 jobno = number(name + 1);
6931 if (jobno > 0 && jobno <= njobs
6932 && jobtab[jobno - 1].used != 0)
6933 return &jobtab[jobno - 1];
6935 } else if (name[1] == '%' && name[2] == '\0') {
6939 struct job *found = NULL;
6940 for (jp = jobtab, i = njobs ; --i >= 0 ; jp++) {
6941 if (jp->used && jp->nprocs > 0
6942 && prefix(name + 1, jp->ps[0].cmd)) {
6944 error("%s: ambiguous", name);
6951 } else if (is_number(name, &pid)) {
6952 for (jp = jobtab, i = njobs ; --i >= 0 ; jp++) {
6953 if (jp->used && jp->nprocs > 0
6954 && jp->ps[jp->nprocs - 1].pid == pid)
6958 error("No such job: %s", name);
6965 * Return a new job structure,
6969 makejob(const union node *node, int nprocs)
6974 for (i = njobs, jp = jobtab ; ; jp++) {
6978 jobtab = ckmalloc(4 * sizeof jobtab[0]);
6980 jp = ckmalloc((njobs + 4) * sizeof jobtab[0]);
6981 memcpy(jp, jobtab, njobs * sizeof jp[0]);
6982 /* Relocate `ps' pointers */
6983 for (i = 0; i < njobs; i++)
6984 if (jp[i].ps == &jobtab[i].ps0)
6985 jp[i].ps = &jp[i].ps0;
6989 jp = jobtab + njobs;
6990 for (i = 4 ; --i >= 0 ; jobtab[njobs++].used = 0);
7003 jp->jobctl = jobctl;
7006 jp->ps = ckmalloc(nprocs * sizeof (struct procstat));
7011 TRACE(("makejob(0x%lx, %d) returns %%%d\n", (long)node, nprocs,
7018 * Fork of a subshell. If we are doing job control, give the subshell its
7019 * own process group. Jp is a job structure that the job is to be added to.
7020 * N is the command that will be evaluated by the child. Both jp and n may
7021 * be NULL. The mode parameter can be one of the following:
7022 * FORK_FG - Fork off a foreground process.
7023 * FORK_BG - Fork off a background process.
7024 * FORK_NOJOB - Like FORK_FG, but don't give the process its own
7025 * process group even if job control is on.
7027 * When job control is turned off, background processes have their standard
7028 * input redirected to /dev/null (except for the second and later processes
7035 forkshell(struct job *jp, const union node *n, int mode)
7041 const char *devnull = _PATH_DEVNULL;
7042 const char *nullerr = "Can't open %s";
7044 TRACE(("forkshell(%%%d, 0x%lx, %d) called\n", jp - jobtab, (long)n,
7049 TRACE(("Fork failed, errno=%d\n", errno));
7051 error("Cannot fork");
7058 TRACE(("Child shell %d\n", getpid()));
7059 wasroot = rootshell;
7065 jobctl = 0; /* do job control only in root shell */
7066 if (wasroot && mode != FORK_NOJOB && mflag) {
7067 if (jp == NULL || jp->nprocs == 0)
7070 pgrp = jp->ps[0].pid;
7072 if (mode == FORK_FG) {
7073 /*** this causes superfluous TIOCSPGRPS ***/
7074 #ifdef OLD_TTY_DRIVER
7075 if (ioctl(2, TIOCSPGRP, (char *)&pgrp) < 0)
7076 error("TIOCSPGRP failed, errno=%d", errno);
7078 if (tcsetpgrp(2, pgrp) < 0)
7079 error("tcsetpgrp failed, errno=%d", errno);
7084 } else if (mode == FORK_BG) {
7087 if ((jp == NULL || jp->nprocs == 0) &&
7088 ! fd0_redirected_p ()) {
7090 if (open(devnull, O_RDONLY) != 0)
7091 error(nullerr, devnull);
7095 if (mode == FORK_BG) {
7098 if ((jp == NULL || jp->nprocs == 0) &&
7099 ! fd0_redirected_p ()) {
7101 if (open(devnull, O_RDONLY) != 0)
7102 error(nullerr, devnull);
7106 for (i = njobs, p = jobtab ; --i >= 0 ; p++)
7109 if (wasroot && iflag) {
7117 if (rootshell && mode != FORK_NOJOB && mflag) {
7118 if (jp == NULL || jp->nprocs == 0)
7121 pgrp = jp->ps[0].pid;
7125 if (mode == FORK_BG)
7126 backgndpid = pid; /* set $! */
7128 struct procstat *ps = &jp->ps[jp->nprocs++];
7132 if (iflag && rootshell && n)
7133 ps->cmd = commandtext(n);
7136 TRACE(("In parent shell: child = %d\n", pid));
7143 * Wait for job to finish.
7145 * Under job control we have the problem that while a child process is
7146 * running interrupts generated by the user are sent to the child but not
7147 * to the shell. This means that an infinite loop started by an inter-
7148 * active user may be hard to kill. With job control turned off, an
7149 * interactive user may place an interactive program inside a loop. If
7150 * the interactive program catches interrupts, the user doesn't want
7151 * these interrupts to also abort the loop. The approach we take here
7152 * is to have the shell ignore interrupt signals while waiting for a
7153 * forground process to terminate, and then send itself an interrupt
7154 * signal if the child process was terminated by an interrupt signal.
7155 * Unfortunately, some programs want to do a bit of cleanup and then
7156 * exit on interrupt; unless these processes terminate themselves by
7157 * sending a signal to themselves (instead of calling exit) they will
7158 * confuse this approach.
7162 waitforjob(struct job *jp)
7165 int mypgrp = getpgrp();
7169 struct sigaction act, oact;
7178 sigaction(SIGINT, 0, &act);
7179 act.sa_handler = waitonint;
7180 sigaction(SIGINT, &act, &oact);
7182 TRACE(("waitforjob(%%%d) called\n", jp - jobtab + 1));
7183 while (jp->state == 0) {
7191 sigaction(SIGINT, &oact, 0);
7192 if (intreceived && trap[SIGINT]) kill(getpid(), SIGINT);
7196 #ifdef OLD_TTY_DRIVER
7197 if (ioctl(2, TIOCSPGRP, (char *)&mypgrp) < 0)
7198 error("TIOCSPGRP failed, errno=%d\n", errno);
7200 if (tcsetpgrp(2, mypgrp) < 0)
7201 error("tcsetpgrp failed, errno=%d\n", errno);
7204 if (jp->state == JOBSTOPPED)
7205 curjob = jp - jobtab + 1;
7207 status = jp->ps[jp->nprocs - 1].status;
7208 /* convert to 8 bits */
7209 if (WIFEXITED(status))
7210 st = WEXITSTATUS(status);
7212 else if (WIFSTOPPED(status))
7213 st = WSTOPSIG(status) + 128;
7216 st = WTERMSIG(status) + 128;
7220 * This is truly gross.
7221 * If we're doing job control, then we did a TIOCSPGRP which
7222 * caused us (the shell) to no longer be in the controlling
7223 * session -- so we wouldn't have seen any ^C/SIGINT. So, we
7224 * intuit from the subprocess exit status whether a SIGINT
7225 * occured, and if so interrupt ourselves. Yuck. - mycroft
7227 if (WIFSIGNALED(status) && WTERMSIG(status) == SIGINT)
7230 if (jp->state == JOBDONE)
7241 * Wait for a process to terminate.
7245 * Do a wait system call. If job control is compiled in, we accept
7246 * stopped processes. If block is zero, we return a value of zero
7247 * rather than blocking.
7249 * System V doesn't have a non-blocking wait system call. It does
7250 * have a SIGCLD signal that is sent to a process when one of it's
7251 * children dies. The obvious way to use SIGCLD would be to install
7252 * a handler for SIGCLD which simply bumped a counter when a SIGCLD
7253 * was received, and have waitproc bump another counter when it got
7254 * the status of a process. Waitproc would then know that a wait
7255 * system call would not block if the two counters were different.
7256 * This approach doesn't work because if a process has children that
7257 * have not been waited for, System V will send it a SIGCLD when it
7258 * installs a signal handler for SIGCLD. What this means is that when
7259 * a child exits, the shell will be sent SIGCLD signals continuously
7260 * until is runs out of stack space, unless it does a wait call before
7261 * restoring the signal handler. The code below takes advantage of
7262 * this (mis)feature by installing a signal handler for SIGCLD and
7263 * then checking to see whether it was called. If there are any
7264 * children to be waited for, it will be.
7269 waitproc(int block, int *status)
7280 return wait3(status, flags, (struct rusage *)NULL);
7284 dowait(int block, struct job *job)
7288 struct procstat *sp;
7290 struct job *thisjob;
7296 TRACE(("dowait(%d) called\n", block));
7298 pid = waitproc(block, &status);
7299 TRACE(("wait returns %d, status=%d\n", pid, status));
7300 } while (!(block & 2) && pid == -1 && errno == EINTR);
7305 for (jp = jobtab ; jp < jobtab + njobs ; jp++) {
7309 for (sp = jp->ps ; sp < jp->ps + jp->nprocs ; sp++) {
7312 if (sp->pid == pid) {
7313 TRACE(("Changing status of proc %d from 0x%x to 0x%x\n", pid, sp->status, status));
7314 sp->status = status;
7317 if (sp->status == -1)
7319 else if (WIFSTOPPED(sp->status))
7322 if (stopped) { /* stopped or done */
7323 int state = done? JOBDONE : JOBSTOPPED;
7324 if (jp->state != state) {
7325 TRACE(("Job %d: changing state from %d to %d\n", jp - jobtab + 1, jp->state, state));
7328 if (done && curjob == jp - jobtab + 1)
7329 curjob = 0; /* no current job */
7336 if (! rootshell || ! iflag || (job && thisjob == job)) {
7337 core = WCOREDUMP(status);
7339 if (WIFSTOPPED(status)) sig = WSTOPSIG(status);
7342 if (WIFEXITED(status)) sig = 0;
7343 else sig = WTERMSIG(status);
7345 if (sig != 0 && sig != SIGINT && sig != SIGPIPE) {
7347 out2fmt("%d: ", pid);
7349 if (sig == SIGTSTP && rootshell && iflag)
7351 (long)(job - jobtab + 1));
7353 if (sig < NSIG && sys_siglist[sig])
7354 out2str(sys_siglist[sig]);
7356 out2fmt("Signal %d", sig);
7358 out2str(" - core dumped");
7361 TRACE(("Not printing status: status=%d, sig=%d\n",
7365 TRACE(("Not printing status, rootshell=%d, job=0x%x\n", rootshell, job));
7367 thisjob->changed = 1;
7376 * return 1 if there are stopped jobs, otherwise 0
7386 for (jobno = 1, jp = jobtab; jobno <= njobs; jobno++, jp++) {
7389 if (jp->state == JOBSTOPPED) {
7390 out2str("You have stopped jobs.\n");
7400 * Return a string identifying a command (to be printed by the
7404 static char *cmdnextc;
7405 static int cmdnleft;
7406 #define MAXCMDTEXT 200
7409 cmdputs(const char *s)
7420 while ((c = *p++) != '\0') {
7423 else if (c == CTLVAR) {
7428 } else if (c == '=' && subtype != 0) {
7429 *q++ = "}-+?="[(subtype & VSTYPE) - VSNORMAL];
7431 } else if (c == CTLENDVAR) {
7433 } else if (c == CTLBACKQ || c == CTLBACKQ+CTLQUOTE)
7434 cmdnleft++; /* ignore it */
7437 if (--cmdnleft <= 0) {
7449 cmdtxt(const union node *n)
7452 struct nodelist *lp;
7461 cmdtxt(n->nbinary.ch1);
7463 cmdtxt(n->nbinary.ch2);
7466 cmdtxt(n->nbinary.ch1);
7468 cmdtxt(n->nbinary.ch2);
7471 cmdtxt(n->nbinary.ch1);
7473 cmdtxt(n->nbinary.ch2);
7476 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
7484 cmdtxt(n->nredir.n);
7489 cmdtxt(n->nredir.n);
7493 cmdtxt(n->nif.test);
7495 cmdtxt(n->nif.ifpart);
7504 cmdtxt(n->nbinary.ch1);
7506 cmdtxt(n->nbinary.ch2);
7511 cmdputs(n->nfor.var);
7516 cmdputs(n->ncase.expr->narg.text);
7520 cmdputs(n->narg.text);
7524 for (np = n->ncmd.args ; np ; np = np->narg.next) {
7529 for (np = n->ncmd.redirect ; np ; np = np->nfile.next) {
7535 cmdputs(n->narg.text);
7538 p = ">"; i = 1; goto redir;
7540 p = ">>"; i = 1; goto redir;
7542 p = ">&"; i = 1; goto redir;
7544 p = ">|"; i = 1; goto redir;
7546 p = "<"; i = 0; goto redir;
7548 p = "<&"; i = 0; goto redir;
7550 p = "<>"; i = 0; goto redir;
7552 if (n->nfile.fd != i) {
7553 s[0] = n->nfile.fd + '0';
7558 if (n->type == NTOFD || n->type == NFROMFD) {
7559 s[0] = n->ndup.dupfd + '0';
7563 cmdtxt(n->nfile.fname);
7578 commandtext(const union node *n)
7582 cmdnextc = name = ckmalloc(MAXCMDTEXT);
7583 cmdnleft = MAXCMDTEXT - 4;
7590 static void waitonint(int sig) {
7595 * Routines to check for mail. (Perhaps make part of main.c?)
7599 #define MAXMBOXES 10
7602 static int nmboxes; /* number of mailboxes */
7603 static time_t mailtime[MAXMBOXES]; /* times of mailboxes */
7608 * Print appropriate message(s) if mail has arrived. If the argument is
7609 * nozero, then the value of MAIL has changed, so we just update the
7620 struct stackmark smark;
7627 setstackmark(&smark);
7628 mpath = mpathset()? mpathval() : mailval();
7629 for (i = 0 ; i < nmboxes ; i++) {
7630 p = padvance(&mpath, nullstr);
7635 for (q = p ; *q ; q++);
7640 q[-1] = '\0'; /* delete trailing '/' */
7641 if (stat(p, &statb) < 0)
7643 if (statb.st_size > mailtime[i] && ! silent) {
7645 pathopt? pathopt : "you have mail");
7647 mailtime[i] = statb.st_size;
7650 popstackmark(&smark);
7656 static short profile_buf[16384];
7660 static void read_profile (const char *);
7661 static void cmdloop (int);
7662 static void options (int);
7663 static void setoption (int, int);
7664 static void procargs (int, char **);
7668 * Main routine. We initialize things, parse the arguments, execute
7669 * profiles if we're a login shell, and then call cmdloop to execute
7670 * commands. The setjmp call sets up the location to jump to when an
7671 * exception occurs. When an exception occurs the variable "state"
7672 * is used to figure out how far we had gotten.
7676 shell_main(argc, argv)
7680 struct jmploc jmploc;
7681 struct stackmark smark;
7685 BLTINCMD = find_builtin("builtin");
7686 EXECCMD = find_builtin("exec");
7687 EVALCMD = find_builtin("eval");
7689 #ifndef BB_FEATURE_SH_FANCY_PROMPT
7695 monitor(4, etext, profile_buf, sizeof profile_buf, 50);
7697 #if defined(linux) || defined(__GNU__)
7698 signal(SIGCHLD, SIG_DFL);
7701 if (setjmp(jmploc.loc)) {
7704 * When a shell procedure is executed, we raise the
7705 * exception EXSHELLPROC to clean up before executing
7706 * the shell procedure.
7708 switch (exception) {
7717 exitstatus = exerrno;
7728 if (exception != EXSHELLPROC) {
7729 if (state == 0 || iflag == 0 || ! rootshell)
7730 exitshell(exitstatus);
7733 if (exception == EXINT) {
7736 popstackmark(&smark);
7737 FORCEINTON; /* enable interrupts */
7740 else if (state == 2)
7742 else if (state == 3)
7750 trputs("Shell args: "); trargs(argv);
7755 setstackmark(&smark);
7756 procargs(argc, argv);
7757 if (argv[0] && argv[0][0] == '-') {
7759 read_profile("/etc/profile");
7762 read_profile(".profile");
7767 if (getuid() == geteuid() && getgid() == getegid()) {
7769 if ((shinit = lookupvar("ENV")) != NULL && *shinit != '\0') {
7771 read_profile(shinit);
7778 if (sflag == 0 || minusc) {
7779 static int sigs[] = {
7780 SIGINT, SIGQUIT, SIGHUP,
7786 #define SIGSSIZE (sizeof(sigs)/sizeof(sigs[0]))
7789 for (i = 0; i < SIGSSIZE; i++)
7794 evalstring(minusc, 0);
7796 if (sflag || minusc == NULL) {
7797 state4: /* XXX ??? - why isn't this before the "if" statement */
7803 exitshell(exitstatus);
7809 * Read and execute commands. "Top" is nonzero for the top level command
7810 * loop; it turns on prompting if the shell is interactive.
7817 struct stackmark smark;
7821 TRACE(("cmdloop(%d) called\n", top));
7822 setstackmark(&smark);
7833 n = parsecmd(inter);
7834 /* showtree(n); DEBUG */
7836 if (!top || numeof >= 50)
7838 if (!stoppedjobs()) {
7841 out2str("\nUse \"exit\" to leave shell.\n");
7844 } else if (n != NULL && nflag == 0) {
7845 job_warning = (job_warning == 2) ? 1 : 0;
7849 popstackmark(&smark);
7850 setstackmark(&smark);
7851 if (evalskip == SKIPFILE) {
7856 popstackmark(&smark);
7862 * Read /etc/profile or .profile. Return on error.
7874 if ((fd = open(name, O_RDONLY)) >= 0)
7879 /* -q turns off -x and -v just when executing init files */
7882 xflag = 0, xflag_set = 1;
7884 vflag = 0, vflag_set = 1;
7899 * Read a file containing shell functions.
7903 readcmdfile(const char *name)
7908 if ((fd = open(name, O_RDONLY)) >= 0)
7911 error("Can't open %s", name);
7920 * Take commands from a file. To be compatable we should do a path
7921 * search for the file, which is necessary to find sub-commands.
7925 static inline char *
7926 find_dot_file(mybasename)
7930 const char *path = pathval();
7933 /* don't try this for absolute or relative paths */
7934 if (strchr(mybasename, '/'))
7937 while ((fullname = padvance(&path, mybasename)) != NULL) {
7938 if ((stat(fullname, &statb) == 0) && S_ISREG(statb.st_mode)) {
7940 * Don't bother freeing here, since it will
7941 * be freed by the caller.
7945 stunalloc(fullname);
7948 /* not found in the PATH */
7949 error("%s: not found", mybasename);
7961 for (sp = cmdenviron; sp ; sp = sp->next)
7962 setvareq(savestr(sp->text), VSTRFIXED|VTEXTFIXED);
7964 if (argc >= 2) { /* That's what SVR2 does */
7966 struct stackmark smark;
7968 setstackmark(&smark);
7969 fullname = find_dot_file(argv[1]);
7970 setinputfile(fullname, 1);
7971 commandname = fullname;
7974 popstackmark(&smark);
7988 exitstatus = number(argv[1]);
7990 exitstatus = oexitstatus;
7991 exitshell(exitstatus);
8000 nbytes = ALIGN(nbytes);
8001 if (nbytes > stacknleft) {
8003 struct stack_block *sp;
8006 if (blocksize < MINSIZE)
8007 blocksize = MINSIZE;
8009 sp = ckmalloc(sizeof(struct stack_block) - MINSIZE + blocksize);
8011 stacknxt = sp->space;
8012 stacknleft = blocksize;
8018 stacknleft -= nbytes;
8024 stunalloc(pointer p)
8027 if (p == NULL) { /*DEBUG */
8028 write(2, "stunalloc\n", 10);
8032 if (!(stacknxt >= (char *)p && (char *)p >= stackp->space)) {
8035 stacknleft += stacknxt - (char *)p;
8041 setstackmark(struct stackmark *mark)
8043 mark->stackp = stackp;
8044 mark->stacknxt = stacknxt;
8045 mark->stacknleft = stacknleft;
8046 mark->marknext = markp;
8052 popstackmark(struct stackmark *mark)
8054 struct stack_block *sp;
8057 markp = mark->marknext;
8058 while (stackp != mark->stackp) {
8063 stacknxt = mark->stacknxt;
8064 stacknleft = mark->stacknleft;
8070 * When the parser reads in a string, it wants to stick the string on the
8071 * stack and only adjust the stack pointer when it knows how big the
8072 * string is. Stackblock (defined in stack.h) returns a pointer to a block
8073 * of space on top of the stack and stackblocklen returns the length of
8074 * this block. Growstackblock will grow this space by at least one byte,
8075 * possibly moving it (like realloc). Grabstackblock actually allocates the
8076 * part of the block that has been used.
8080 growstackblock(void) {
8082 int newlen = ALIGN(stacknleft * 2 + 100);
8083 char *oldspace = stacknxt;
8084 int oldlen = stacknleft;
8085 struct stack_block *sp;
8086 struct stack_block *oldstackp;
8088 if (stacknxt == stackp->space && stackp != &stackbase) {
8093 sp = ckrealloc((pointer)sp, sizeof(struct stack_block) - MINSIZE + newlen);
8096 stacknxt = sp->space;
8097 stacknleft = newlen;
8099 /* Stack marks pointing to the start of the old block
8100 * must be relocated to point to the new block
8102 struct stackmark *xmark;
8104 while (xmark != NULL && xmark->stackp == oldstackp) {
8105 xmark->stackp = stackp;
8106 xmark->stacknxt = stacknxt;
8107 xmark->stacknleft = stacknleft;
8108 xmark = xmark->marknext;
8113 p = stalloc(newlen);
8114 memcpy(p, oldspace, oldlen);
8115 stacknxt = p; /* free the space */
8116 stacknleft += newlen; /* we just allocated */
8123 grabstackblock(int len)
8133 * The following routines are somewhat easier to use that the above.
8134 * The user declares a variable of type STACKSTR, which may be declared
8135 * to be a register. The macro STARTSTACKSTR initializes things. Then
8136 * the user uses the macro STPUTC to add characters to the string. In
8137 * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
8138 * grown as necessary. When the user is done, she can just leave the
8139 * string there and refer to it using stackblock(). Or she can allocate
8140 * the space for it using grabstackstr(). If it is necessary to allow
8141 * someone else to use the stack temporarily and then continue to grow
8142 * the string, the user should use grabstack to allocate the space, and
8143 * then call ungrabstr(p) to return to the previous mode of operation.
8145 * USTPUTC is like STPUTC except that it doesn't check for overflow.
8146 * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
8147 * is space for at least one character.
8152 growstackstr(void) {
8153 int len = stackblocksize();
8154 if (herefd >= 0 && len >= 1024) {
8155 xwrite(herefd, stackblock(), len);
8156 sstrnleft = len - 1;
8157 return stackblock();
8160 sstrnleft = stackblocksize() - len - 1;
8161 return stackblock() + len;
8166 * Called from CHECKSTRSPACE.
8170 makestrspace(size_t newlen) {
8171 int len = stackblocksize() - sstrnleft;
8174 sstrnleft = stackblocksize() - len;
8175 } while (sstrnleft < newlen);
8176 return stackblock() + len;
8182 ungrabstackstr(char *s, char *p)
8184 stacknleft += stacknxt - s;
8186 sstrnleft = stacknleft - (p - s);
8189 * Miscelaneous builtins.
8196 static mode_t getmode(const void *, mode_t);
8197 static void *setmode(const char *);
8200 #if !defined(__GLIBC__) || __GLIBC__ == 2 && __GLIBC_MINOR__ < 1
8201 typedef long rlim_t;
8207 * The read builtin. The -e option causes backslashes to escape the
8208 * following character.
8210 * This uses unbuffered input, which may be avoidable in some cases.
8231 while ((i = nextopt("p:r")) != '\0') {
8237 if (prompt && isatty(0)) {
8241 if (*(ap = argptr) == NULL)
8243 if ((ifs = bltinlookup("IFS")) == NULL)
8250 if (read(0, &c, 1) != 1) {
8262 if (!rflag && c == '\\') {
8268 if (startword && *ifs == ' ' && strchr(ifs, c)) {
8272 if (backslash && c == '\\') {
8273 if (read(0, &c, 1) != 1) {
8278 } else if (ap[1] != NULL && strchr(ifs, c) != NULL) {
8280 setvar(*ap, stackblock(), 0);
8289 /* Remove trailing blanks */
8290 while (stackblock() <= --p && strchr(ifs, *p) != NULL)
8292 setvar(*ap, stackblock(), 0);
8293 while (*++ap != NULL)
8294 setvar(*ap, nullstr, 0);
8301 umaskcmd(argc, argv)
8308 int symbolic_mode = 0;
8310 while (nextopt("S") != '\0') {
8319 if ((ap = *argptr) == NULL) {
8320 if (symbolic_mode) {
8321 char u[4], g[4], o[4];
8324 if ((mask & S_IRUSR) == 0)
8326 if ((mask & S_IWUSR) == 0)
8328 if ((mask & S_IXUSR) == 0)
8333 if ((mask & S_IRGRP) == 0)
8335 if ((mask & S_IWGRP) == 0)
8337 if ((mask & S_IXGRP) == 0)
8342 if ((mask & S_IROTH) == 0)
8344 if ((mask & S_IWOTH) == 0)
8346 if ((mask & S_IXOTH) == 0)
8350 printf("u=%s,g=%s,o=%s\n", u, g, o);
8352 printf("%.4o\n", mask);
8355 if (is_digit((unsigned char)*ap)) {
8358 if (*ap >= '8' || *ap < '0')
8359 error("Illegal number: %s", argv[1]);
8360 mask = (mask << 3) + (*ap - '0');
8361 } while (*++ap != '\0');
8367 if ((set = setmode(ap)) != 0) {
8368 mask = getmode(set, ~mask & 0777);
8373 error("Illegal mode: %s", ap);
8375 umask(~mask & 0777);
8384 * This code, originally by Doug Gwyn, Doug Kingston, Eric Gisin, and
8385 * Michael Rendell was ripped from pdksh 5.0.8 and hacked for use with
8386 * ash by J.T. Conklin.
8394 int factor; /* multiply by to get rlim_{cur,max} values */
8398 static const struct limits limits[] = {
8400 { "time(seconds)", RLIMIT_CPU, 1, 't' },
8403 { "file(blocks)", RLIMIT_FSIZE, 512, 'f' },
8406 { "data(kbytes)", RLIMIT_DATA, 1024, 'd' },
8409 { "stack(kbytes)", RLIMIT_STACK, 1024, 's' },
8412 { "coredump(blocks)", RLIMIT_CORE, 512, 'c' },
8415 { "memory(kbytes)", RLIMIT_RSS, 1024, 'm' },
8417 #ifdef RLIMIT_MEMLOCK
8418 { "locked memory(kbytes)", RLIMIT_MEMLOCK, 1024, 'l' },
8421 { "process(processes)", RLIMIT_NPROC, 1, 'p' },
8423 #ifdef RLIMIT_NOFILE
8424 { "nofiles(descriptors)", RLIMIT_NOFILE, 1, 'n' },
8427 { "vmemory(kbytes)", RLIMIT_VMEM, 1024, 'v' },
8430 { "swap(kbytes)", RLIMIT_SWAP, 1024, 'w' },
8432 { (char *) 0, 0, 0, '\0' }
8436 ulimitcmd(argc, argv)
8442 enum { SOFT = 0x1, HARD = 0x2 }
8444 const struct limits *l;
8447 struct rlimit limit;
8450 while ((optc = nextopt("HSatfdsmcnpl")) != '\0')
8465 for (l = limits; l->name && l->option != what; l++)
8468 error("internal error (%c)", what);
8470 set = *argptr ? 1 : 0;
8474 if (all || argptr[1])
8475 error("too many arguments");
8476 if (strcmp(p, "unlimited") == 0)
8477 val = RLIM_INFINITY;
8481 while ((c = *p++) >= '0' && c <= '9')
8483 val = (val * 10) + (long)(c - '0');
8484 if (val < (rlim_t) 0)
8488 error("bad number");
8493 for (l = limits; l->name; l++) {
8494 getrlimit(l->cmd, &limit);
8496 val = limit.rlim_cur;
8497 else if (how & HARD)
8498 val = limit.rlim_max;
8500 printf("%-20s ", l->name);
8501 if (val == RLIM_INFINITY)
8502 printf("unlimited\n");
8506 printf("%lld\n", (long long) val);
8512 getrlimit(l->cmd, &limit);
8515 limit.rlim_max = val;
8517 limit.rlim_cur = val;
8518 if (setrlimit(l->cmd, &limit) < 0)
8519 error("error setting limit (%m)");
8522 val = limit.rlim_cur;
8523 else if (how & HARD)
8524 val = limit.rlim_max;
8526 if (val == RLIM_INFINITY)
8527 printf("unlimited\n");
8531 printf("%lld\n", (long long) val);
8537 * prefix -- see if pfx is a prefix of string.
8541 prefix(char const *pfx, char const *string)
8544 if (*pfx++ != *string++)
8551 * Return true if s is a string of digits, and save munber in intptr
8556 is_number(const char *p, int *intptr)
8564 ret += digit_val(*p);
8566 } while (*p != '\0');
8573 * Convert a string of digits to an integer, printing an error message on
8578 number(const char *s)
8581 if (! is_number(s, &i))
8582 error("Illegal number: %s", s);
8587 * Produce a possibly single quoted string suitable as input to the shell.
8588 * The return string is allocated on the stack.
8592 single_quote(const char *s) {
8599 size_t len1, len1p, len2, len2p;
8601 len1 = strcspn(s, "'");
8602 len2 = strspn(s + len1, "'");
8604 len1p = len1 ? len1 + 2 : len1;
8616 CHECKSTRSPACE(len1p + len2p + 1, p);
8621 memcpy(p + 1, s, len1);
8637 memcpy(q + 1, s, len2);
8642 STADJUST(len1p + len2p, p);
8647 return grabstackstr(p);
8651 * Like strdup but works with the ash stack.
8655 sstrdup(const char *p)
8657 size_t len = strlen(p) + 1;
8658 return memcpy(stalloc(len), p, len);
8663 * Routine for dealing with parsed shell commands.
8667 static void sizenodelist (const struct nodelist *);
8668 static struct nodelist *copynodelist (const struct nodelist *);
8669 static char *nodesavestr (const char *);
8672 calcsize(const union node *n)
8676 funcblocksize += nodesize[n->type];
8683 calcsize(n->nbinary.ch2);
8684 calcsize(n->nbinary.ch1);
8687 calcsize(n->ncmd.redirect);
8688 calcsize(n->ncmd.args);
8689 calcsize(n->ncmd.assign);
8692 sizenodelist(n->npipe.cmdlist);
8697 calcsize(n->nredir.redirect);
8698 calcsize(n->nredir.n);
8701 calcsize(n->nif.elsepart);
8702 calcsize(n->nif.ifpart);
8703 calcsize(n->nif.test);
8706 funcstringsize += strlen(n->nfor.var) + 1;
8707 calcsize(n->nfor.body);
8708 calcsize(n->nfor.args);
8711 calcsize(n->ncase.cases);
8712 calcsize(n->ncase.expr);
8715 calcsize(n->nclist.body);
8716 calcsize(n->nclist.pattern);
8717 calcsize(n->nclist.next);
8721 sizenodelist(n->narg.backquote);
8722 funcstringsize += strlen(n->narg.text) + 1;
8723 calcsize(n->narg.next);
8730 calcsize(n->nfile.fname);
8731 calcsize(n->nfile.next);
8735 calcsize(n->ndup.vname);
8736 calcsize(n->ndup.next);
8740 calcsize(n->nhere.doc);
8741 calcsize(n->nhere.next);
8744 calcsize(n->nnot.com);
8750 sizenodelist(const struct nodelist *lp)
8753 funcblocksize += ALIGN(sizeof(struct nodelist));
8761 copynode(const union node *n)
8768 funcblock = (char *) funcblock + nodesize[n->type];
8775 new->nbinary.ch2 = copynode(n->nbinary.ch2);
8776 new->nbinary.ch1 = copynode(n->nbinary.ch1);
8779 new->ncmd.redirect = copynode(n->ncmd.redirect);
8780 new->ncmd.args = copynode(n->ncmd.args);
8781 new->ncmd.assign = copynode(n->ncmd.assign);
8782 new->ncmd.backgnd = n->ncmd.backgnd;
8785 new->npipe.cmdlist = copynodelist(n->npipe.cmdlist);
8786 new->npipe.backgnd = n->npipe.backgnd;
8791 new->nredir.redirect = copynode(n->nredir.redirect);
8792 new->nredir.n = copynode(n->nredir.n);
8795 new->nif.elsepart = copynode(n->nif.elsepart);
8796 new->nif.ifpart = copynode(n->nif.ifpart);
8797 new->nif.test = copynode(n->nif.test);
8800 new->nfor.var = nodesavestr(n->nfor.var);
8801 new->nfor.body = copynode(n->nfor.body);
8802 new->nfor.args = copynode(n->nfor.args);
8805 new->ncase.cases = copynode(n->ncase.cases);
8806 new->ncase.expr = copynode(n->ncase.expr);
8809 new->nclist.body = copynode(n->nclist.body);
8810 new->nclist.pattern = copynode(n->nclist.pattern);
8811 new->nclist.next = copynode(n->nclist.next);
8815 new->narg.backquote = copynodelist(n->narg.backquote);
8816 new->narg.text = nodesavestr(n->narg.text);
8817 new->narg.next = copynode(n->narg.next);
8824 new->nfile.fname = copynode(n->nfile.fname);
8825 new->nfile.fd = n->nfile.fd;
8826 new->nfile.next = copynode(n->nfile.next);
8830 new->ndup.vname = copynode(n->ndup.vname);
8831 new->ndup.dupfd = n->ndup.dupfd;
8832 new->ndup.fd = n->ndup.fd;
8833 new->ndup.next = copynode(n->ndup.next);
8837 new->nhere.doc = copynode(n->nhere.doc);
8838 new->nhere.fd = n->nhere.fd;
8839 new->nhere.next = copynode(n->nhere.next);
8842 new->nnot.com = copynode(n->nnot.com);
8845 new->type = n->type;
8850 static struct nodelist *
8851 copynodelist(const struct nodelist *lp)
8853 struct nodelist *start;
8854 struct nodelist **lpp;
8859 funcblock = (char *) funcblock + ALIGN(sizeof(struct nodelist));
8860 (*lpp)->n = copynode(lp->n);
8862 lpp = &(*lpp)->next;
8870 nodesavestr(const char *s)
8873 char *rtn = funcstring;
8875 funcstring = stpcpy(funcstring, s) + 1;
8879 char *q = funcstring;
8880 char *rtn = funcstring;
8882 while ((*q++ = *p++) != '\0')
8890 static int getopts (char *, char *, char **, int *, int *);
8895 * Process the shell command line arguments.
8899 procargs(argc, argv)
8908 for (i = 0; i < NOPTS; i++)
8911 if (*argptr == NULL && minusc == NULL)
8913 if (iflag == 2 && sflag == 1 && isatty(0) && isatty(1))
8917 for (i = 0; i < NOPTS; i++)
8918 if (optent_val(i) == 2)
8921 if (sflag == 0 && minusc == NULL) {
8922 commandname = argv[0];
8924 setinputfile(arg0, 0);
8927 /* POSIX 1003.2: first arg after -c cmd is $0, remainder $1... */
8928 if (argptr && minusc && *argptr)
8931 shellparam.p = argptr;
8932 shellparam.optind = 1;
8933 shellparam.optoff = -1;
8934 /* assert(shellparam.malloc == 0 && shellparam.nparam == 0); */
8936 shellparam.nparam++;
8945 * Process shell options. The global variable argptr contains a pointer
8946 * to the argument list; we advance it past the options.
8950 minus_o(const char *name, int val)
8955 out1str("Current option settings\n");
8956 for (i = 0; i < NOPTS; i++)
8957 printf("%-16s%s\n", optent_name(optlist[i]),
8958 optent_val(i) ? "on" : "off");
8960 for (i = 0; i < NOPTS; i++)
8961 if (equal(name, optent_name(optlist[i]))) {
8962 setoption(optent_letter(optlist[i]), val);
8965 error("Illegal option -o %s", name);
8971 options(int cmdline)
8979 while ((p = *argptr) != NULL) {
8981 if ((c = *p++) == '-') {
8983 if (p[0] == '\0' || (p[0] == '-' && p[1] == '\0')) {
8985 /* "-" means turn off -x and -v */
8988 /* "--" means reset params */
8989 else if (*argptr == NULL)
8992 break; /* "-" or "--" terminates options */
8994 } else if (c == '+') {
9000 while ((c = *p++) != '\0') {
9001 if (c == 'c' && cmdline) {
9003 #ifdef NOHACK /* removing this code allows sh -ce 'foo' for compat */
9007 if (q == NULL || minusc != NULL)
9008 error("Bad -c option");
9013 } else if (c == 'o') {
9014 minus_o(*argptr, val);
9026 setoption(int flag, int val)
9030 for (i = 0; i < NOPTS; i++)
9031 if (optent_letter(optlist[i]) == flag) {
9032 optent_val(i) = val;
9034 /* #%$ hack for ksh semantics */
9037 else if (flag == 'E')
9042 error("Illegal option -%c", flag);
9049 * Set the shell parameters.
9053 setparam(char **argv)
9059 for (nparam = 0 ; argv[nparam] ; nparam++);
9060 ap = newparam = ckmalloc((nparam + 1) * sizeof *ap);
9062 *ap++ = savestr(*argv++);
9065 freeparam(&shellparam);
9066 shellparam.malloc = 1;
9067 shellparam.nparam = nparam;
9068 shellparam.p = newparam;
9069 shellparam.optind = 1;
9070 shellparam.optoff = -1;
9075 * Free the list of positional parameters.
9079 freeparam(volatile struct shparam *param)
9083 if (param->malloc) {
9084 for (ap = param->p ; *ap ; ap++)
9093 * The shift builtin command.
9097 shiftcmd(argc, argv)
9106 n = number(argv[1]);
9107 if (n > shellparam.nparam)
9108 error("can't shift that many");
9110 shellparam.nparam -= n;
9111 for (ap1 = shellparam.p ; --n >= 0 ; ap1++) {
9112 if (shellparam.malloc)
9116 while ((*ap2++ = *ap1++) != NULL);
9117 shellparam.optind = 1;
9118 shellparam.optoff = -1;
9126 * The set command builtin.
9135 return showvarscmd(argc, argv);
9139 if (*argptr != NULL) {
9148 getoptsreset(const char *value)
9150 shellparam.optind = number(value);
9151 shellparam.optoff = -1;
9154 #ifdef BB_LOCALE_SUPPORT
9155 static void change_lc_all(const char *value)
9157 if(value != 0 && *value != 0)
9158 setlocale(LC_ALL, value);
9161 static void change_lc_ctype(const char *value)
9163 if(value != 0 && *value != 0)
9164 setlocale(LC_CTYPE, value);
9171 * The getopts builtin. Shellparam.optnext points to the next argument
9172 * to be processed. Shellparam.optptr points to the next character to
9173 * be processed in the current argument. If shellparam.optnext is NULL,
9174 * then it's the first time getopts has been called.
9178 getoptscmd(argc, argv)
9185 error("Usage: getopts optstring var [arg]");
9186 else if (argc == 3) {
9187 optbase = shellparam.p;
9188 if (shellparam.optind > shellparam.nparam + 1) {
9189 shellparam.optind = 1;
9190 shellparam.optoff = -1;
9195 if (shellparam.optind > argc - 2) {
9196 shellparam.optind = 1;
9197 shellparam.optoff = -1;
9201 return getopts(argv[1], argv[2], optbase, &shellparam.optind,
9202 &shellparam.optoff);
9206 * Safe version of setvar, returns 1 on success 0 on failure.
9210 setvarsafe(name, val, flags)
9211 const char *name, *val;
9214 struct jmploc jmploc;
9215 struct jmploc *volatile savehandler = handler;
9221 if (setjmp(jmploc.loc))
9225 setvar(name, val, flags);
9227 handler = savehandler;
9232 getopts(optstr, optvar, optfirst, myoptind, optoff)
9244 char **optnext = optfirst + *myoptind - 1;
9246 if (*myoptind <= 1 || *optoff < 0 || !(*(optnext - 1)) ||
9247 strlen(*(optnext - 1)) < *optoff)
9250 p = *(optnext - 1) + *optoff;
9251 if (p == NULL || *p == '\0') {
9252 /* Current word is done, advance */
9253 if (optnext == NULL)
9256 if (p == NULL || *p != '-' || *++p == '\0') {
9258 *myoptind = optnext - optfirst + 1;
9264 if (p[0] == '-' && p[1] == '\0') /* check for "--" */
9269 for (q = optstr; *q != c; ) {
9271 if (optstr[0] == ':') {
9274 err |= setvarsafe("OPTARG", s, 0);
9277 out2fmt("Illegal option -%c\n", c);
9278 (void) unsetvar("OPTARG");
9288 if (*p == '\0' && (p = *optnext) == NULL) {
9289 if (optstr[0] == ':') {
9292 err |= setvarsafe("OPTARG", s, 0);
9296 out2fmt("No arg for -%c option\n", c);
9297 (void) unsetvar("OPTARG");
9305 setvarsafe("OPTARG", p, 0);
9309 setvarsafe("OPTARG", "", 0);
9310 *myoptind = optnext - optfirst + 1;
9317 *optoff = p ? p - *(optnext - 1) : -1;
9318 snprintf(s, sizeof(s), "%d", *myoptind);
9319 err |= setvarsafe("OPTIND", s, VNOFUNC);
9322 err |= setvarsafe(optvar, s, 0);
9333 * XXX - should get rid of. have all builtins use getopt(3). the
9334 * library getopt must have the BSD extension static variable "optreset"
9335 * otherwise it can't be used within the shell safely.
9337 * Standard option processing (a la getopt) for builtin routines. The
9338 * only argument that is passed to nextopt is the option string; the
9339 * other arguments are unnecessary. It return the character, or '\0' on
9344 nextopt(const char *optstring)
9350 if ((p = optptr) == NULL || *p == '\0') {
9352 if (p == NULL || *p != '-' || *++p == '\0')
9355 if (p[0] == '-' && p[1] == '\0') /* check for "--" */
9359 for (q = optstring ; *q != c ; ) {
9361 error("Illegal option -%c", c);
9366 if (*p == '\0' && (p = *argptr++) == NULL)
9367 error("No arg for -%c option", c);
9384 out2fmt(const char *fmt, ...)
9388 vfprintf(stderr, fmt, ap);
9393 * Version of write which resumes after a signal is caught.
9397 xwrite(int fd, const char *buf, int nbytes)
9406 i = write(fd, buf, n);
9412 } else if (i == 0) {
9415 } else if (errno != EINTR) {
9423 * Shell command parser.
9426 #define EOFMARKLEN 79
9431 struct heredoc *next; /* next here document in list */
9432 union node *here; /* redirection node */
9433 char *eofmark; /* string indicating end of input */
9434 int striptabs; /* if set, strip leading tabs */
9437 static struct heredoc *heredoclist; /* list of here documents to read */
9438 static int parsebackquote; /* nonzero if we are inside backquotes */
9439 static int doprompt; /* if set, prompt the user */
9440 static int needprompt; /* true if interactive and at start of line */
9441 static int lasttoken; /* last token read */
9443 static char *wordtext; /* text of last word returned by readtoken */
9445 static struct nodelist *backquotelist;
9446 static union node *redirnode;
9447 static struct heredoc *heredoc;
9448 static int quoteflag; /* set if (part of) last token was quoted */
9449 static int startlinno; /* line # where last token started */
9452 static union node *list (int);
9453 static union node *andor (void);
9454 static union node *pipeline (void);
9455 static union node *command (void);
9456 static union node *simplecmd (void);
9457 static void parsefname (void);
9458 static void parseheredoc (void);
9459 static int peektoken (void);
9460 static int readtoken (void);
9461 static int xxreadtoken (void);
9462 static int readtoken1 (int, char const *, char *, int);
9463 static int noexpand (char *);
9464 static void synexpect (int) __attribute__((noreturn));
9465 static void synerror (const char *) __attribute__((noreturn));
9466 static void setprompt (int);
9470 * Read and parse a command. Returns NEOF on end of file. (NULL is a
9471 * valid parse tree indicating a blank line.)
9475 parsecmd(int interact)
9480 doprompt = interact;
9500 union node *n1, *n2, *n3;
9504 if (nlflag == 0 && tokendlist[peektoken()])
9510 if (tok == TBACKGND) {
9511 if (n2->type == NCMD || n2->type == NPIPE) {
9512 n2->ncmd.backgnd = 1;
9513 } else if (n2->type == NREDIR) {
9514 n2->type = NBACKGND;
9516 n3 = (union node *)stalloc(sizeof (struct nredir));
9517 n3->type = NBACKGND;
9519 n3->nredir.redirect = NULL;
9527 n3 = (union node *)stalloc(sizeof (struct nbinary));
9529 n3->nbinary.ch1 = n1;
9530 n3->nbinary.ch2 = n2;
9547 if (tokendlist[peektoken()])
9554 pungetc(); /* push back EOF on input */
9569 union node *n1, *n2, *n3;
9575 if ((t = readtoken()) == TAND) {
9577 } else if (t == TOR) {
9585 n3 = (union node *)stalloc(sizeof (struct nbinary));
9587 n3->nbinary.ch1 = n1;
9588 n3->nbinary.ch2 = n2;
9597 union node *n1, *n2, *pipenode;
9598 struct nodelist *lp, *prev;
9602 TRACE(("pipeline: entered\n"));
9603 if (readtoken() == TNOT) {
9609 if (readtoken() == TPIPE) {
9610 pipenode = (union node *)stalloc(sizeof (struct npipe));
9611 pipenode->type = NPIPE;
9612 pipenode->npipe.backgnd = 0;
9613 lp = (struct nodelist *)stalloc(sizeof (struct nodelist));
9614 pipenode->npipe.cmdlist = lp;
9618 lp = (struct nodelist *)stalloc(sizeof (struct nodelist));
9622 } while (readtoken() == TPIPE);
9628 n2 = (union node *)stalloc(sizeof (struct nnot));
9640 union node *n1, *n2;
9641 union node *ap, **app;
9642 union node *cp, **cpp;
9643 union node *redir, **rpp;
9650 switch (readtoken()) {
9652 n1 = (union node *)stalloc(sizeof (struct nif));
9654 n1->nif.test = list(0);
9655 if (readtoken() != TTHEN)
9657 n1->nif.ifpart = list(0);
9659 while (readtoken() == TELIF) {
9660 n2->nif.elsepart = (union node *)stalloc(sizeof (struct nif));
9661 n2 = n2->nif.elsepart;
9663 n2->nif.test = list(0);
9664 if (readtoken() != TTHEN)
9666 n2->nif.ifpart = list(0);
9668 if (lasttoken == TELSE)
9669 n2->nif.elsepart = list(0);
9671 n2->nif.elsepart = NULL;
9674 if (readtoken() != TFI)
9681 n1 = (union node *)stalloc(sizeof (struct nbinary));
9682 n1->type = (lasttoken == TWHILE)? NWHILE : NUNTIL;
9683 n1->nbinary.ch1 = list(0);
9684 if ((got=readtoken()) != TDO) {
9685 TRACE(("expecting DO got %s %s\n", tokname[got], got == TWORD ? wordtext : ""));
9688 n1->nbinary.ch2 = list(0);
9689 if (readtoken() != TDONE)
9695 if (readtoken() != TWORD || quoteflag || ! goodname(wordtext))
9696 synerror("Bad for loop variable");
9697 n1 = (union node *)stalloc(sizeof (struct nfor));
9699 n1->nfor.var = wordtext;
9701 if (readtoken() == TIN) {
9703 while (readtoken() == TWORD) {
9704 n2 = (union node *)stalloc(sizeof (struct narg));
9706 n2->narg.text = wordtext;
9707 n2->narg.backquote = backquotelist;
9709 app = &n2->narg.next;
9713 if (lasttoken != TNL && lasttoken != TSEMI)
9716 static char argvars[5] = {CTLVAR, VSNORMAL|VSQUOTE,
9718 n2 = (union node *)stalloc(sizeof (struct narg));
9720 n2->narg.text = argvars;
9721 n2->narg.backquote = NULL;
9722 n2->narg.next = NULL;
9725 * Newline or semicolon here is optional (but note
9726 * that the original Bourne shell only allowed NL).
9728 if (lasttoken != TNL && lasttoken != TSEMI)
9732 if (readtoken() != TDO)
9734 n1->nfor.body = list(0);
9735 if (readtoken() != TDONE)
9740 n1 = (union node *)stalloc(sizeof (struct ncase));
9742 if (readtoken() != TWORD)
9744 n1->ncase.expr = n2 = (union node *)stalloc(sizeof (struct narg));
9746 n2->narg.text = wordtext;
9747 n2->narg.backquote = backquotelist;
9748 n2->narg.next = NULL;
9751 } while (readtoken() == TNL);
9752 if (lasttoken != TIN)
9753 synerror("expecting \"in\"");
9754 cpp = &n1->ncase.cases;
9755 checkkwd = 2, readtoken();
9757 if (lasttoken == TLP)
9759 *cpp = cp = (union node *)stalloc(sizeof (struct nclist));
9761 app = &cp->nclist.pattern;
9763 *app = ap = (union node *)stalloc(sizeof (struct narg));
9765 ap->narg.text = wordtext;
9766 ap->narg.backquote = backquotelist;
9767 if (checkkwd = 2, readtoken() != TPIPE)
9769 app = &ap->narg.next;
9772 ap->narg.next = NULL;
9773 if (lasttoken != TRP)
9775 cp->nclist.body = list(0);
9778 if ((t = readtoken()) != TESAC) {
9780 synexpect(TENDCASE);
9782 checkkwd = 2, readtoken();
9784 cpp = &cp->nclist.next;
9785 } while(lasttoken != TESAC);
9790 n1 = (union node *)stalloc(sizeof (struct nredir));
9791 n1->type = NSUBSHELL;
9792 n1->nredir.n = list(0);
9793 n1->nredir.redirect = NULL;
9794 if (readtoken() != TRP)
9800 if (readtoken() != TEND)
9804 /* Handle an empty command like other simple commands. */
9813 * An empty command before a ; doesn't make much sense, and
9814 * should certainly be disallowed in the case of `if ;'.
9828 /* Now check for redirection which may follow command */
9829 while (readtoken() == TREDIR) {
9830 *rpp = n2 = redirnode;
9831 rpp = &n2->nfile.next;
9837 if (n1->type != NSUBSHELL) {
9838 n2 = (union node *)stalloc(sizeof (struct nredir));
9843 n1->nredir.redirect = redir;
9852 union node *args, **app;
9853 union node *n = NULL;
9854 union node *vars, **vpp;
9855 union node **rpp, *redir;
9866 switch (readtoken()) {
9869 n = (union node *)stalloc(sizeof (struct narg));
9871 n->narg.text = wordtext;
9872 n->narg.backquote = backquotelist;
9873 if (lasttoken == TWORD) {
9875 app = &n->narg.next;
9878 vpp = &n->narg.next;
9882 *rpp = n = redirnode;
9883 rpp = &n->nfile.next;
9884 parsefname(); /* read name of redirection file */
9888 args && app == &args->narg.next &&
9891 /* We have a function */
9892 if (readtoken() != TRP)
9896 n->narg.next = command();
9909 n = (union node *)stalloc(sizeof (struct ncmd));
9911 n->ncmd.backgnd = 0;
9912 n->ncmd.args = args;
9913 n->ncmd.assign = vars;
9914 n->ncmd.redirect = redir;
9922 n = (union node *)stalloc(sizeof (struct narg));
9924 n->narg.next = NULL;
9925 n->narg.text = wordtext;
9926 n->narg.backquote = backquotelist;
9930 static void fixredir(union node *n, const char *text, int err)
9932 TRACE(("Fix redir %s %d\n", text, err));
9934 n->ndup.vname = NULL;
9936 if (is_digit(text[0]) && text[1] == '\0')
9937 n->ndup.dupfd = digit_val(text[0]);
9938 else if (text[0] == '-' && text[1] == '\0')
9943 synerror("Bad fd number");
9945 n->ndup.vname = makename();
9952 union node *n = redirnode;
9954 if (readtoken() != TWORD)
9956 if (n->type == NHERE) {
9957 struct heredoc *here = heredoc;
9963 TRACE(("Here document %d\n", n->type));
9964 if (here->striptabs) {
9965 while (*wordtext == '\t')
9968 if (! noexpand(wordtext) || (i = strlen(wordtext)) == 0 || i > EOFMARKLEN)
9969 synerror("Illegal eof marker for << redirection");
9970 rmescapes(wordtext);
9971 here->eofmark = wordtext;
9973 if (heredoclist == NULL)
9976 for (p = heredoclist ; p->next ; p = p->next);
9979 } else if (n->type == NTOFD || n->type == NFROMFD) {
9980 fixredir(n, wordtext, 0);
9982 n->nfile.fname = makename();
9988 * Input any here documents.
9993 struct heredoc *here;
9996 while (heredoclist) {
9998 heredoclist = here->next;
10003 readtoken1(pgetc(), here->here->type == NHERE? SQSYNTAX : DQSYNTAX,
10004 here->eofmark, here->striptabs);
10005 n = (union node *)stalloc(sizeof (struct narg));
10006 n->narg.type = NARG;
10007 n->narg.next = NULL;
10008 n->narg.text = wordtext;
10009 n->narg.backquote = backquotelist;
10010 here->here->nhere.doc = n;
10028 int savecheckalias = checkalias;
10029 int savecheckkwd = checkkwd;
10034 int alreadyseen = tokpushback;
10044 checkalias = savecheckalias;
10051 if (checkkwd == 2) {
10060 * check for keywords
10062 if (t == TWORD && !quoteflag)
10064 const char *const *pp;
10066 if ((pp = findkwd(wordtext))) {
10067 lasttoken = t = pp - parsekwd + KWDOFFSET;
10068 TRACE(("keyword %s recognized\n", tokname[t]));
10079 } else if (checkalias == 2 && isassignment(wordtext)) {
10080 lasttoken = t = TASSIGN;
10082 } else if (checkalias) {
10083 if (!quoteflag && (ap = lookupalias(wordtext, 1)) != NULL) {
10085 pushstring(ap->val, strlen(ap->val), ap);
10087 checkkwd = savecheckkwd;
10096 TRACE(("token %s %s\n", tokname[t], t == TWORD || t == TASSIGN ? wordtext : ""));
10098 TRACE(("reread token %s %s\n", tokname[t], t == TWORD || t == TASSIGN ? wordtext : ""));
10105 * Read the next input token.
10106 * If the token is a word, we set backquotelist to the list of cmds in
10107 * backquotes. We set quoteflag to true if any part of the word was
10109 * If the token is TREDIR, then we set redirnode to a structure containing
10111 * In all cases, the variable startlinno is set to the number of the line
10112 * on which the token starts.
10114 * [Change comment: here documents and internal procedures]
10115 * [Readtoken shouldn't have any arguments. Perhaps we should make the
10116 * word parsing code into a separate routine. In this case, readtoken
10117 * doesn't need to have any internal procedures, but parseword does.
10118 * We could also make parseoperator in essence the main routine, and
10119 * have parseword (readtoken1?) handle both words and redirection.]
10122 #define RETURN(token) return lasttoken = token
10136 startlinno = plinno;
10137 for (;;) { /* until token or start of word found */
10140 case ' ': case '\t':
10146 while ((c = pgetc()) != '\n' && c != PEOF);
10150 if (pgetc() == '\n') {
10151 startlinno = ++plinno;
10162 needprompt = doprompt;
10167 if (pgetc() == '&')
10172 if (pgetc() == '|')
10177 if (pgetc() == ';')
10190 return readtoken1(c, BASESYNTAX, (char *)NULL, 0);
10197 * If eofmark is NULL, read a word or a redirection symbol. If eofmark
10198 * is not NULL, read a here document. In the latter case, eofmark is the
10199 * word which marks the end of the document and striptabs is true if
10200 * leading tabs should be stripped from the document. The argument firstc
10201 * is the first character of the input token or document.
10203 * Because C does not have internal subroutines, I have simulated them
10204 * using goto's to implement the subroutine linkage. The following macros
10205 * will run code that appears at the end of readtoken1.
10208 #define CHECKEND() {goto checkend; checkend_return:;}
10209 #define PARSEREDIR() {goto parseredir; parseredir_return:;}
10210 #define PARSESUB() {goto parsesub; parsesub_return:;}
10211 #define PARSEBACKQOLD() {oldstyle = 1; goto parsebackq; parsebackq_oldreturn:;}
10212 #define PARSEBACKQNEW() {oldstyle = 0; goto parsebackq; parsebackq_newreturn:;}
10213 #define PARSEARITH() {goto parsearith; parsearith_return:;}
10216 readtoken1(firstc, syntax, eofmark, striptabs)
10218 char const *syntax;
10225 char line[EOFMARKLEN + 1];
10226 struct nodelist *bqlist;
10229 int varnest; /* levels of variables expansion */
10230 int arinest; /* levels of arithmetic expansion */
10231 int parenlevel; /* levels of parens in arithmetic */
10232 int dqvarnest; /* levels of variables expansion within double quotes */
10234 char const *prevsyntax; /* syntax before arithmetic */
10236 /* Avoid longjmp clobbering */
10242 (void) &parenlevel;
10245 (void) &prevsyntax;
10249 startlinno = plinno;
10251 if (syntax == DQSYNTAX)
10260 STARTSTACKSTR(out);
10261 loop: { /* for each line, until end of word */
10262 CHECKEND(); /* set c to PEOF if at end of here document */
10263 for (;;) { /* until end of line or end of word */
10264 CHECKSTRSPACE(3, out); /* permit 3 calls to USTPUTC */
10265 switch(syntax[c]) {
10266 case CNL: /* '\n' */
10267 if (syntax == BASESYNTAX)
10268 goto endword; /* exit outer loop */
10276 goto loop; /* continue outer loop */
10281 if ((eofmark == NULL || dblquote) &&
10283 USTPUTC(CTLESC, out);
10286 case CBACK: /* backslash */
10289 USTPUTC('\\', out);
10291 } else if (c == '\n') {
10297 if (dblquote && c != '\\' && c != '`' && c != '$'
10298 && (c != '"' || eofmark != NULL))
10299 USTPUTC('\\', out);
10300 if (SQSYNTAX[c] == CCTL)
10301 USTPUTC(CTLESC, out);
10302 else if (eofmark == NULL)
10303 USTPUTC(CTLQUOTEMARK, out);
10309 if (eofmark == NULL)
10310 USTPUTC(CTLQUOTEMARK, out);
10314 if (eofmark == NULL)
10315 USTPUTC(CTLQUOTEMARK, out);
10320 if (eofmark != NULL && arinest == 0 &&
10325 syntax = ARISYNTAX;
10327 } else if (eofmark == NULL &&
10329 syntax = BASESYNTAX;
10335 case CVAR: /* '$' */
10336 PARSESUB(); /* parse substitution */
10338 case CENDVAR: /* '}' */
10341 if (dqvarnest > 0) {
10344 USTPUTC(CTLENDVAR, out);
10349 #ifdef ASH_MATH_SUPPORT
10350 case CLP: /* '(' in arithmetic */
10354 case CRP: /* ')' in arithmetic */
10355 if (parenlevel > 0) {
10359 if (pgetc() == ')') {
10360 if (--arinest == 0) {
10361 USTPUTC(CTLENDARI, out);
10362 syntax = prevsyntax;
10363 if (syntax == DQSYNTAX)
10371 * unbalanced parens
10372 * (don't 2nd guess - no error)
10380 case CBQUOTE: /* '`' */
10384 goto endword; /* exit outer loop */
10389 goto endword; /* exit outer loop */
10400 if (syntax == ARISYNTAX)
10401 synerror("Missing '))'");
10402 if (syntax != BASESYNTAX && ! parsebackquote && eofmark == NULL)
10403 synerror("Unterminated quoted string");
10404 if (varnest != 0) {
10405 startlinno = plinno;
10406 synerror("Missing '}'");
10408 USTPUTC('\0', out);
10409 len = out - stackblock();
10410 out = stackblock();
10411 if (eofmark == NULL) {
10412 if ((c == '>' || c == '<')
10415 && (*out == '\0' || is_digit(*out))) {
10417 return lasttoken = TREDIR;
10422 quoteflag = quotef;
10423 backquotelist = bqlist;
10424 grabstackblock(len);
10426 return lasttoken = TWORD;
10427 /* end of readtoken routine */
10432 * Check to see whether we are at the end of the here document. When this
10433 * is called, c is set to the first character of the next input line. If
10434 * we are at the end of the here document, this routine sets the c to PEOF.
10445 while (c == '\t') {
10449 if (c == *eofmark) {
10450 if (pfgets(line, sizeof line) != NULL) {
10454 for (q = eofmark + 1 ; *q && *p == *q ; p++, q++);
10455 if (*p == '\n' && *q == '\0') {
10458 needprompt = doprompt;
10460 pushstring(line, strlen(line), NULL);
10465 goto checkend_return;
10470 * Parse a redirection operator. The variable "out" points to a string
10471 * specifying the fd to be redirected. The variable "c" contains the
10472 * first character of the redirection operator.
10479 np = (union node *)stalloc(sizeof (struct nfile));
10484 np->type = NAPPEND;
10493 } else { /* c == '<' */
10495 switch (c = pgetc()) {
10497 if (sizeof (struct nfile) != sizeof (struct nhere)) {
10498 np = (union node *)stalloc(sizeof (struct nhere));
10502 heredoc = (struct heredoc *)stalloc(sizeof (struct heredoc));
10503 heredoc->here = np;
10504 if ((c = pgetc()) == '-') {
10505 heredoc->striptabs = 1;
10507 heredoc->striptabs = 0;
10513 np->type = NFROMFD;
10517 np->type = NFROMTO;
10527 np->nfile.fd = digit_val(fd);
10529 goto parseredir_return;
10534 * Parse a substitution. At this point, we have read the dollar sign
10535 * and nothing else.
10543 static const char types[] = "}-+?=";
10548 (c != '(' && c != '{' && !is_name(c) && !is_special(c))
10552 } else if (c == '(') { /* $(command) or $((arith)) */
10553 if (pgetc() == '(') {
10560 USTPUTC(CTLVAR, out);
10561 typeloc = out - stackblock();
10562 USTPUTC(VSNORMAL, out);
10563 subtype = VSNORMAL;
10567 if ((c = pgetc()) == '}')
10570 subtype = VSLENGTH;
10575 if (c > PEOA && is_name(c)) {
10579 } while (c > PEOA && is_in_name(c));
10580 } else if (is_digit(c)) {
10584 } while (is_digit(c));
10586 else if (is_special(c)) {
10591 badsub: synerror("Bad substitution");
10595 if (subtype == 0) {
10602 p = strchr(types, c);
10605 subtype = p - types + VSNORMAL;
10611 subtype = c == '#' ? VSTRIMLEFT :
10624 if (dblquote || arinest)
10626 *(stackblock() + typeloc) = subtype | flags;
10627 if (subtype != VSNORMAL) {
10634 goto parsesub_return;
10639 * Called to parse command substitutions. Newstyle is set if the command
10640 * is enclosed inside $(...); nlpp is a pointer to the head of the linked
10641 * list of commands (passed by reference), and savelen is the number of
10642 * characters on the top of the stack which must be preserved.
10646 struct nodelist **nlpp;
10649 char *volatile str;
10650 struct jmploc jmploc;
10651 struct jmploc *volatile savehandler;
10655 (void) &saveprompt;
10658 savepbq = parsebackquote;
10659 if (setjmp(jmploc.loc)) {
10662 parsebackquote = 0;
10663 handler = savehandler;
10664 longjmp(handler->loc, 1);
10668 savelen = out - stackblock();
10670 str = ckmalloc(savelen);
10671 memcpy(str, stackblock(), savelen);
10673 savehandler = handler;
10677 /* We must read until the closing backquote, giving special
10678 treatment to some slashes, and then push the string and
10679 reread it as input, interpreting it normally. */
10686 STARTSTACKSTR(pout);
10692 switch (pc = pgetc()) {
10697 if ((pc = pgetc()) == '\n') {
10704 * If eating a newline, avoid putting
10705 * the newline into the new character
10706 * stream (via the STPUTC after the
10711 if (pc != '\\' && pc != '`' && pc != '$'
10712 && (!dblquote || pc != '"'))
10713 STPUTC('\\', pout);
10723 startlinno = plinno;
10724 synerror("EOF in backquote substitution");
10728 needprompt = doprompt;
10737 STPUTC('\0', pout);
10738 psavelen = pout - stackblock();
10739 if (psavelen > 0) {
10740 pstr = grabstackstr(pout);
10741 setinputstring(pstr);
10746 nlpp = &(*nlpp)->next;
10747 *nlpp = (struct nodelist *)stalloc(sizeof (struct nodelist));
10748 (*nlpp)->next = NULL;
10749 parsebackquote = oldstyle;
10752 saveprompt = doprompt;
10759 doprompt = saveprompt;
10761 if (readtoken() != TRP)
10768 * Start reading from old file again, ignoring any pushed back
10769 * tokens left from the backquote parsing
10774 while (stackblocksize() <= savelen)
10776 STARTSTACKSTR(out);
10778 memcpy(out, str, savelen);
10779 STADJUST(savelen, out);
10785 parsebackquote = savepbq;
10786 handler = savehandler;
10787 if (arinest || dblquote)
10788 USTPUTC(CTLBACKQ | CTLQUOTE, out);
10790 USTPUTC(CTLBACKQ, out);
10792 goto parsebackq_oldreturn;
10794 goto parsebackq_newreturn;
10798 * Parse an arithmetic expansion (indicate start of one and set state)
10802 if (++arinest == 1) {
10803 prevsyntax = syntax;
10804 syntax = ARISYNTAX;
10805 USTPUTC(CTLARI, out);
10812 * we collapse embedded arithmetic expansion to
10813 * parenthesis, which should be equivalent
10817 goto parsearith_return;
10820 } /* end of readtoken */
10824 * Returns true if the text contains nothing to expand (no dollar signs
10836 while ((c = *p++) != '\0') {
10837 if (c == CTLQUOTEMARK)
10841 else if (BASESYNTAX[(int)c] == CCTL)
10849 * Return true if the argument is a legal variable name (a letter or
10850 * underscore followed by zero or more letters, underscores, and digits).
10854 goodname(const char *name)
10862 if (! is_in_name(*p))
10870 * Called when an unexpected token is read during the parse. The argument
10871 * is the token that is expected, or -1 if more than one type of token can
10872 * occur at this point.
10882 snprintf(msg, 64, "%s unexpected (expecting %s)",
10883 tokname[lasttoken], tokname[token]);
10885 snprintf(msg, 64, "%s unexpected", tokname[lasttoken]);
10893 synerror(const char *msg)
10896 out2fmt("%s: %d: ", commandname, startlinno);
10897 out2fmt("Syntax error: %s\n", msg);
10898 error((char *)NULL);
10904 * called by editline -- any expansions to the prompt
10905 * should be added here.
10908 setprompt(int whichprompt)
10911 switch (whichprompt) {
10926 * Code for dealing with input/output redirection.
10929 #define EMPTY -2 /* marks an unused slot in redirtab */
10931 # define PIPESIZE 4096 /* amount of buffering in a pipe */
10933 # define PIPESIZE PIPE_BUF
10938 * Open a file in noclobber mode.
10939 * The code was copied from bash.
10942 noclobberopen(const char *fname)
10945 struct stat finfo, finfo2;
10948 * If the file exists and is a regular file, return an error
10951 r = stat(fname, &finfo);
10952 if (r == 0 && S_ISREG(finfo.st_mode)) {
10958 * If the file was not present (r != 0), make sure we open it
10959 * exclusively so that if it is created before we open it, our open
10960 * will fail. Make sure that we do not truncate an existing file.
10961 * Note that we don't turn on O_EXCL unless the stat failed -- if the
10962 * file was not a regular file, we leave O_EXCL off.
10965 return open(fname, O_WRONLY|O_CREAT|O_EXCL, 0666);
10966 fd = open(fname, O_WRONLY|O_CREAT, 0666);
10968 /* If the open failed, return the file descriptor right away. */
10973 * OK, the open succeeded, but the file may have been changed from a
10974 * non-regular file to a regular file between the stat and the open.
10975 * We are assuming that the O_EXCL open handles the case where FILENAME
10976 * did not exist and is symlinked to an existing file between the stat
10981 * If we can open it and fstat the file descriptor, and neither check
10982 * revealed that it was a regular file, and the file has not been
10983 * replaced, return the file descriptor.
10985 if (fstat(fd, &finfo2) == 0 && !S_ISREG(finfo2.st_mode) &&
10986 finfo.st_dev == finfo2.st_dev && finfo.st_ino == finfo2.st_ino)
10989 /* The file has been replaced. badness. */
10996 * Handle here documents. Normally we fork off a process to write the
10997 * data to a pipe. If the document is short, we can stuff the data in
10998 * the pipe without forking.
11002 openhere(const union node *redir)
11008 error("Pipe call failed");
11009 if (redir->type == NHERE) {
11010 len = strlen(redir->nhere.doc->narg.text);
11011 if (len <= PIPESIZE) {
11012 xwrite(pip[1], redir->nhere.doc->narg.text, len);
11016 if (forkshell((struct job *)NULL, (union node *)NULL, FORK_NOJOB) == 0) {
11018 signal(SIGINT, SIG_IGN);
11019 signal(SIGQUIT, SIG_IGN);
11020 signal(SIGHUP, SIG_IGN);
11022 signal(SIGTSTP, SIG_IGN);
11024 signal(SIGPIPE, SIG_DFL);
11025 if (redir->type == NHERE)
11026 xwrite(pip[1], redir->nhere.doc->narg.text, len);
11028 expandhere(redir->nhere.doc, pip[1]);
11038 openredirect(const union node *redir)
11043 switch (redir->nfile.type) {
11045 fname = redir->nfile.expfname;
11046 if ((f = open(fname, O_RDONLY)) < 0)
11050 fname = redir->nfile.expfname;
11051 if ((f = open(fname, O_RDWR|O_CREAT|O_TRUNC, 0666)) < 0)
11055 /* Take care of noclobber mode. */
11057 fname = redir->nfile.expfname;
11058 if ((f = noclobberopen(fname)) < 0)
11063 fname = redir->nfile.expfname;
11065 if ((f = open(fname, O_WRONLY|O_CREAT|O_TRUNC, 0666)) < 0)
11068 if ((f = creat(fname, 0666)) < 0)
11073 fname = redir->nfile.expfname;
11075 if ((f = open(fname, O_WRONLY|O_CREAT|O_APPEND, 0666)) < 0)
11078 if ((f = open(fname, O_WRONLY)) < 0
11079 && (f = creat(fname, 0666)) < 0)
11081 lseek(f, (off_t)0, 2);
11088 /* Fall through to eliminate warning. */
11095 f = openhere(redir);
11101 error("cannot create %s: %s", fname, errmsg(errno, E_CREAT));
11103 error("cannot open %s: %s", fname, errmsg(errno, E_OPEN));
11108 * Process a list of redirection commands. If the REDIR_PUSH flag is set,
11109 * old file descriptors are stashed away so that the redirection can be
11110 * undone by calling popredir. If the REDIR_BACKQ flag is set, then the
11111 * standard output, and the standard error if it becomes a duplicate of
11116 redirect(union node *redir, int flags)
11119 struct redirtab *sv = NULL;
11124 int fd1dup = flags & REDIR_BACKQ;; /* stdout `cmd` redir to pipe */
11126 if (flags & REDIR_PUSH) {
11127 sv = ckmalloc(sizeof (struct redirtab));
11128 for (i = 0 ; i < 10 ; i++)
11129 sv->renamed[i] = EMPTY;
11130 sv->next = redirlist;
11133 for (n = redir ; n ; n = n->nfile.next) {
11136 if ((n->nfile.type == NTOFD || n->nfile.type == NFROMFD) &&
11137 n->ndup.dupfd == fd)
11138 continue; /* redirect from/to same file descriptor */
11141 newfd = openredirect(n);
11142 if ((flags & REDIR_PUSH) && sv->renamed[fd] == EMPTY) {
11145 } else if ((i = fcntl(fd, F_DUPFD, 10)) == -1) {
11149 dupredirect(n, newfd, fd1dup);
11159 error("%d: %m", fd);
11165 if (flags & REDIR_PUSH) {
11166 sv->renamed[fd] = i;
11169 } else if (fd != newfd) {
11175 dupredirect(n, newfd, fd1dup);
11182 dupredirect(const union node *redir, int f, int fd1dup)
11184 int fd = redir->nfile.fd;
11188 if (redir->nfile.type == NTOFD || redir->nfile.type == NFROMFD) {
11189 if (redir->ndup.dupfd >= 0) { /* if not ">&-" */
11190 if (redir->ndup.dupfd!=1 || fd1dup!=1)
11191 dup_as_newfd(redir->ndup.dupfd, fd);
11197 dup_as_newfd(f, fd);
11206 * Undo the effects of the last redirection.
11212 struct redirtab *rp = redirlist;
11216 for (i = 0 ; i < 10 ; i++) {
11217 if (rp->renamed[i] != EMPTY) {
11221 if (rp->renamed[i] >= 0) {
11222 dup_as_newfd(rp->renamed[i], i);
11223 close(rp->renamed[i]);
11227 redirlist = rp->next;
11233 * Discard all saved file descriptors.
11238 struct redirtab *rp;
11241 for (rp = redirlist ; rp ; rp = rp->next) {
11242 for (i = 0 ; i < 10 ; i++) {
11243 if (rp->renamed[i] >= 0) {
11244 close(rp->renamed[i]);
11246 rp->renamed[i] = EMPTY;
11253 * Copy a file descriptor to be >= to. Returns -1
11254 * if the source file descriptor is closed, EMPTY if there are no unused
11255 * file descriptors left.
11259 dup_as_newfd(from, to)
11265 newfd = fcntl(from, F_DUPFD, to);
11267 if (errno == EMFILE)
11270 error("%d: %m", from);
11275 /*#ifdef __weak_alias
11276 __weak_alias(getmode,_getmode)
11277 __weak_alias(setmode,_setmode)
11281 #if defined(__GLIBC__) && __GLIBC__ >= 2
11282 #define S_ISTXT __S_ISVTX
11284 #define S_ISTXT S_ISVTX
11288 #define SET_LEN 6 /* initial # of bitcmd struct to malloc */
11289 #define SET_LEN_INCR 4 /* # of bitcmd structs to add as needed */
11291 typedef struct bitcmd {
11297 #define CMD2_CLR 0x01
11298 #define CMD2_SET 0x02
11299 #define CMD2_GBITS 0x04
11300 #define CMD2_OBITS 0x08
11301 #define CMD2_UBITS 0x10
11303 static BITCMD *addcmd (BITCMD *, int, int, int, u_int);
11304 static void compress_mode (BITCMD *);
11305 #ifdef SETMODE_DEBUG
11306 static void dumpmode (BITCMD *);
11310 * Given the old mode and an array of bitcmd structures, apply the operations
11311 * described in the bitcmd structures to the old mode, and return the new mode.
11312 * Note that there is no '=' command; a strict assignment is just a '-' (clear
11313 * bits) followed by a '+' (set bits).
11316 getmode(bbox, omode)
11321 mode_t clrval, newmode, value;
11323 _DIAGASSERT(bbox != NULL);
11325 set = (const BITCMD *)bbox;
11327 for (value = 0;; set++)
11330 * When copying the user, group or other bits around, we "know"
11331 * where the bits are in the mode so that we can do shifts to
11332 * copy them around. If we don't use shifts, it gets real
11333 * grundgy with lots of single bit checks and bit sets.
11336 value = (newmode & S_IRWXU) >> 6;
11340 value = (newmode & S_IRWXG) >> 3;
11344 value = newmode & S_IRWXO;
11345 common: if (set->cmd2 & CMD2_CLR) {
11347 (set->cmd2 & CMD2_SET) ? S_IRWXO : value;
11348 if (set->cmd2 & CMD2_UBITS)
11349 newmode &= ~((clrval<<6) & set->bits);
11350 if (set->cmd2 & CMD2_GBITS)
11351 newmode &= ~((clrval<<3) & set->bits);
11352 if (set->cmd2 & CMD2_OBITS)
11353 newmode &= ~(clrval & set->bits);
11355 if (set->cmd2 & CMD2_SET) {
11356 if (set->cmd2 & CMD2_UBITS)
11357 newmode |= (value<<6) & set->bits;
11358 if (set->cmd2 & CMD2_GBITS)
11359 newmode |= (value<<3) & set->bits;
11360 if (set->cmd2 & CMD2_OBITS)
11361 newmode |= value & set->bits;
11366 newmode |= set->bits;
11370 newmode &= ~set->bits;
11374 if (omode & (S_IFDIR|S_IXUSR|S_IXGRP|S_IXOTH))
11375 newmode |= set->bits;
11380 #ifdef SETMODE_DEBUG
11381 (void)printf("getmode:%04o -> %04o\n", omode, newmode);
11387 #define ADDCMD(a, b, c, d) do { \
11388 if (set >= endset) { \
11390 setlen += SET_LEN_INCR; \
11391 newset = realloc(saveset, sizeof(BITCMD) * setlen); \
11392 if (newset == NULL) { \
11396 set = newset + (set - saveset); \
11397 saveset = newset; \
11398 endset = newset + (setlen - 2); \
11400 set = addcmd(set, (a), (b), (c), (d)); \
11401 } while (/*CONSTCOND*/0)
11403 #define STANDARD_BITS (S_ISUID|S_ISGID|S_IRWXU|S_IRWXG|S_IRWXO)
11411 BITCMD *set, *saveset, *endset;
11412 sigset_t mysigset, sigoset;
11414 int equalopdone = 0; /* pacify gcc */
11415 int permXbits, setlen;
11421 * Get a copy of the mask for the permissions that are mask relative.
11422 * Flip the bits, we want what's not set. Since it's possible that
11423 * the caller is opening files inside a signal handler, protect them
11426 sigfillset(&mysigset);
11427 (void)sigprocmask(SIG_BLOCK, &mysigset, &sigoset);
11428 (void)umask(mask = umask(0));
11430 (void)sigprocmask(SIG_SETMASK, &sigoset, NULL);
11432 setlen = SET_LEN + 2;
11434 if ((set = malloc((u_int)(sizeof(BITCMD) * setlen))) == NULL)
11437 endset = set + (setlen - 2);
11440 * If an absolute number, get it and return; disallow non-octal digits
11443 if (is_digit((unsigned char)*p)) {
11444 perm = (mode_t)strtol(p, &ep, 8);
11445 if (*ep || perm & ~(STANDARD_BITS|S_ISTXT)) {
11449 ADDCMD('=', (STANDARD_BITS|S_ISTXT), perm, mask);
11455 * Build list of structures to set/clear/copy bits as described by
11456 * each clause of the symbolic mode.
11459 /* First, find out which bits might be modified. */
11460 for (who = 0;; ++p) {
11463 who |= STANDARD_BITS;
11466 who |= S_ISUID|S_IRWXU;
11469 who |= S_ISGID|S_IRWXG;
11479 getop: if ((op = *p++) != '+' && op != '-' && op != '=') {
11487 for (perm = 0, permXbits = 0;; ++p) {
11490 perm |= S_IRUSR|S_IRGRP|S_IROTH;
11494 * If specific bits where requested and
11495 * only "other" bits ignore set-id.
11497 if (who == 0 || (who & ~S_IRWXO))
11498 perm |= S_ISUID|S_ISGID;
11502 * If specific bits where requested and
11503 * only "other" bits ignore set-id.
11505 if (who == 0 || (who & ~S_IRWXO)) {
11511 perm |= S_IWUSR|S_IWGRP|S_IWOTH;
11514 permXbits = S_IXUSR|S_IXGRP|S_IXOTH;
11517 perm |= S_IXUSR|S_IXGRP|S_IXOTH;
11523 * When ever we hit 'u', 'g', or 'o', we have
11524 * to flush out any partial mode that we have,
11525 * and then do the copying of the mode bits.
11528 ADDCMD(op, who, perm, mask);
11533 if (op == '+' && permXbits) {
11534 ADDCMD('X', who, permXbits, mask);
11537 ADDCMD(*p, who, op, mask);
11542 * Add any permissions that we haven't already
11545 if (perm || (op == '=' && !equalopdone)) {
11548 ADDCMD(op, who, perm, mask);
11552 ADDCMD('X', who, permXbits, mask);
11566 #ifdef SETMODE_DEBUG
11567 (void)printf("Before compress_mode()\n");
11570 compress_mode(saveset);
11571 #ifdef SETMODE_DEBUG
11572 (void)printf("After compress_mode()\n");
11579 addcmd(set, op, who, oparg, mask)
11586 _DIAGASSERT(set != NULL);
11591 set->bits = who ? who : STANDARD_BITS;
11600 set->bits = (who ? who : mask) & oparg;
11608 set->cmd2 = ((who & S_IRUSR) ? CMD2_UBITS : 0) |
11609 ((who & S_IRGRP) ? CMD2_GBITS : 0) |
11610 ((who & S_IROTH) ? CMD2_OBITS : 0);
11611 set->bits = (mode_t)~0;
11613 set->cmd2 = CMD2_UBITS | CMD2_GBITS | CMD2_OBITS;
11618 set->cmd2 |= CMD2_SET;
11619 else if (oparg == '-')
11620 set->cmd2 |= CMD2_CLR;
11621 else if (oparg == '=')
11622 set->cmd2 |= CMD2_SET|CMD2_CLR;
11628 #ifdef SETMODE_DEBUG
11634 _DIAGASSERT(set != NULL);
11636 for (; set->cmd; ++set)
11637 (void)printf("cmd: '%c' bits %04o%s%s%s%s%s%s\n",
11638 set->cmd, set->bits, set->cmd2 ? " cmd2:" : "",
11639 set->cmd2 & CMD2_CLR ? " CLR" : "",
11640 set->cmd2 & CMD2_SET ? " SET" : "",
11641 set->cmd2 & CMD2_UBITS ? " UBITS" : "",
11642 set->cmd2 & CMD2_GBITS ? " GBITS" : "",
11643 set->cmd2 & CMD2_OBITS ? " OBITS" : "");
11648 * Given an array of bitcmd structures, compress by compacting consecutive
11649 * '+', '-' and 'X' commands into at most 3 commands, one of each. The 'u',
11650 * 'g' and 'o' commands continue to be separate. They could probably be
11651 * compacted, but it's not worth the effort.
11658 int setbits, clrbits, Xbits, op;
11660 _DIAGASSERT(set != NULL);
11662 for (nset = set;;) {
11663 /* Copy over any 'u', 'g' and 'o' commands. */
11664 while ((op = nset->cmd) != '+' && op != '-' && op != 'X') {
11670 for (setbits = clrbits = Xbits = 0;; nset++) {
11671 if ((op = nset->cmd) == '-') {
11672 clrbits |= nset->bits;
11673 setbits &= ~nset->bits;
11674 Xbits &= ~nset->bits;
11675 } else if (op == '+') {
11676 setbits |= nset->bits;
11677 clrbits &= ~nset->bits;
11678 Xbits &= ~nset->bits;
11679 } else if (op == 'X')
11680 Xbits |= nset->bits & ~setbits;
11687 set->bits = clrbits;
11693 set->bits = setbits;
11705 static void shtree (union node *, int, char *, FILE*);
11706 static void shcmd (union node *, FILE *);
11707 static void sharg (union node *, FILE *);
11708 static void indent (int, char *, FILE *);
11709 static void trstring (char *);
11716 trputs("showtree called\n");
11717 shtree(n, 1, NULL, stdout);
11722 shtree(n, ind, pfx, fp)
11728 struct nodelist *lp;
11734 indent(ind, pfx, fp);
11745 shtree(n->nbinary.ch1, ind, NULL, fp);
11748 shtree(n->nbinary.ch2, ind, NULL, fp);
11756 for (lp = n->npipe.cmdlist ; lp ; lp = lp->next) {
11761 if (n->npipe.backgnd)
11767 fprintf(fp, "<node type %d>", n->type);
11787 for (np = cmd->ncmd.args ; np ; np = np->narg.next) {
11793 for (np = cmd->ncmd.redirect ; np ; np = np->nfile.next) {
11796 switch (np->nfile.type) {
11797 case NTO: s = ">"; dftfd = 1; break;
11798 case NAPPEND: s = ">>"; dftfd = 1; break;
11799 case NTOFD: s = ">&"; dftfd = 1; break;
11800 case NTOOV: s = ">|"; dftfd = 1; break;
11801 case NFROM: s = "<"; dftfd = 0; break;
11802 case NFROMFD: s = "<&"; dftfd = 0; break;
11803 case NFROMTO: s = "<>"; dftfd = 0; break;
11804 default: s = "*error*"; dftfd = 0; break;
11806 if (np->nfile.fd != dftfd)
11807 fprintf(fp, "%d", np->nfile.fd);
11809 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
11810 fprintf(fp, "%d", np->ndup.dupfd);
11812 sharg(np->nfile.fname, fp);
11826 struct nodelist *bqlist;
11829 if (arg->type != NARG) {
11830 printf("<node type %d>\n", arg->type);
11834 bqlist = arg->narg.backquote;
11835 for (p = arg->narg.text ; *p ; p++) {
11844 if (subtype == VSLENGTH)
11850 if (subtype & VSNUL)
11853 switch (subtype & VSTYPE) {
11872 case VSTRIMLEFTMAX:
11879 case VSTRIMRIGHTMAX:
11886 printf("<subtype %d>", subtype);
11893 case CTLBACKQ|CTLQUOTE:
11896 shtree(bqlist->n, -1, NULL, fp);
11908 indent(amount, pfx, fp)
11915 for (i = 0 ; i < amount ; i++) {
11916 if (pfx && i == amount - 1)
11934 static int debug = 1;
11936 static int debug = 0;
11944 if (tracefile == NULL)
11946 putc(c, tracefile);
11952 trace(const char *fmt, ...)
11960 fmt = va_arg(va, char *);
11962 if (tracefile != NULL) {
11963 (void) vfprintf(tracefile, fmt, va);
11964 if (strchr(fmt, '\n'))
11965 (void) fflush(tracefile);
11975 if (tracefile == NULL)
11977 fputs(s, tracefile);
11978 if (strchr(s, '\n'))
11990 if (tracefile == NULL)
11992 putc('"', tracefile);
11993 for (p = s ; *p ; p++) {
11995 case '\n': c = 'n'; goto backslash;
11996 case '\t': c = 't'; goto backslash;
11997 case '\r': c = 'r'; goto backslash;
11998 case '"': c = '"'; goto backslash;
11999 case '\\': c = '\\'; goto backslash;
12000 case CTLESC: c = 'e'; goto backslash;
12001 case CTLVAR: c = 'v'; goto backslash;
12002 case CTLVAR+CTLQUOTE: c = 'V'; goto backslash;
12003 case CTLBACKQ: c = 'q'; goto backslash;
12004 case CTLBACKQ+CTLQUOTE: c = 'Q'; goto backslash;
12005 backslash: putc('\\', tracefile);
12006 putc(c, tracefile);
12009 if (*p >= ' ' && *p <= '~')
12010 putc(*p, tracefile);
12012 putc('\\', tracefile);
12013 putc(*p >> 6 & 03, tracefile);
12014 putc(*p >> 3 & 07, tracefile);
12015 putc(*p & 07, tracefile);
12020 putc('"', tracefile);
12028 if (tracefile == NULL)
12033 putc(' ', tracefile);
12035 putc('\n', tracefile);
12050 #ifdef not_this_way
12053 if ((p = getenv("HOME")) == NULL) {
12054 if (geteuid() == 0)
12060 strcat(s, "/trace");
12063 strcpy(s, "./trace");
12064 #endif /* not_this_way */
12065 if ((tracefile = fopen(s, "a")) == NULL) {
12066 fprintf(stderr, "Can't open %s\n", s);
12070 if ((flags = fcntl(fileno(tracefile), F_GETFL, 0)) >= 0)
12071 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
12073 fputs("\nTracing started.\n", tracefile);
12080 * The trap builtin.
12084 trapcmd(argc, argv)
12093 for (signo = 0 ; signo < NSIG ; signo++) {
12094 if (trap[signo] != NULL) {
12097 p = single_quote(trap[signo]);
12098 printf("trap -- %s %s\n", p,
12099 signal_names[signo] + (signo ? 3 : 0)
12112 if ((signo = decode_signal(*ap, 0)) < 0)
12113 error("%s: bad trap", *ap);
12116 if (action[0] == '-' && action[1] == '\0')
12119 action = savestr(action);
12122 ckfree(trap[signo]);
12123 trap[signo] = action;
12138 * Set the signal handler for the specified signal. The routine figures
12139 * out what it should be set to.
12143 setsignal(int signo)
12147 struct sigaction act;
12149 if ((t = trap[signo]) == NULL)
12151 else if (*t != '\0')
12155 if (rootshell && action == S_DFL) {
12158 if (iflag || minusc || sflag == 0)
12184 t = &sigmode[signo - 1];
12187 * current setting unknown
12189 if (sigaction(signo, 0, &act) == -1) {
12191 * Pretend it worked; maybe we should give a warning
12192 * here, but other shells don't. We don't alter
12193 * sigmode, so that we retry every time.
12197 if (act.sa_handler == SIG_IGN) {
12198 if (mflag && (signo == SIGTSTP ||
12199 signo == SIGTTIN || signo == SIGTTOU)) {
12200 *t = S_IGN; /* don't hard ignore these */
12204 *t = S_RESET; /* force to be set */
12207 if (*t == S_HARD_IGN || *t == action)
12211 act.sa_handler = onsig;
12214 act.sa_handler = SIG_IGN;
12217 act.sa_handler = SIG_DFL;
12221 sigemptyset(&act.sa_mask);
12222 sigaction(signo, &act, 0);
12233 if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
12234 signal(signo, SIG_IGN);
12236 sigmode[signo - 1] = S_HARD_IGN;
12247 if (signo == SIGINT && trap[SIGINT] == NULL) {
12251 gotsig[signo - 1] = 1;
12257 * Called to execute a trap. Perhaps we should avoid entering new trap
12258 * handlers while we are executing a trap handler.
12268 for (i = 1 ; ; i++) {
12275 savestatus=exitstatus;
12276 evalstring(trap[i], 0);
12277 exitstatus=savestatus;
12284 * Called to exit the shell.
12288 exitshell(int status)
12290 struct jmploc loc1, loc2;
12293 TRACE(("exitshell(%d) pid=%d\n", status, getpid()));
12294 if (setjmp(loc1.loc)) {
12297 if (setjmp(loc2.loc)) {
12301 if ((p = trap[0]) != NULL && *p != '\0') {
12305 l1: handler = &loc2; /* probably unnecessary */
12314 static int decode_signal(const char *string, int minsig)
12318 if (is_number(string, &signo)) {
12319 if (signo >= NSIG) {
12329 for (; signo < NSIG; signo++) {
12330 if (!strcasecmp(string, &(signal_names[signo])[3])) {
12334 if (!strcasecmp(string, signal_names[signo])) {
12341 static struct var **hashvar (const char *);
12342 static void showvars (const char *, int, int);
12343 static struct var **findvar (struct var **, const char *);
12346 * Initialize the varable symbol tables and import the environment
12350 * This routine initializes the builtin variables. It is called when the
12351 * shell is initialized and again when a shell procedure is spawned.
12356 const struct varinit *ip;
12360 for (ip = varinit ; (vp = ip->var) != NULL ; ip++) {
12361 if ((vp->flags & VEXPORT) == 0) {
12362 vpp = hashvar(ip->text);
12365 vp->text = strdup(ip->text);
12366 vp->flags = ip->flags;
12367 vp->func = ip->func;
12371 * PS1 depends on uid
12373 if ((vps1.flags & VEXPORT) == 0) {
12374 vpp = hashvar("PS1=");
12377 vps1.text = strdup(geteuid() ? "PS1=$ " : "PS1=# ");
12378 vps1.flags = VSTRFIXED|VTEXTFIXED;
12383 * Set the value of a variable. The flags argument is ored with the
12384 * flags of the variable. If val is NULL, the variable is unset.
12388 setvar(name, val, flags)
12389 const char *name, *val;
12405 if (! is_in_name(*p)) {
12406 if (*p == '\0' || *p == '=')
12412 namelen = p - name;
12414 error("%.*s: bad variable name", namelen, name);
12415 len = namelen + 2; /* 2 is space for '=' and '\0' */
12419 len += vallen = strlen(val);
12422 nameeq = ckmalloc(len);
12423 memcpy(nameeq, name, namelen);
12424 nameeq[namelen] = '=';
12426 memcpy(nameeq + namelen + 1, val, vallen + 1);
12428 nameeq[namelen + 1] = '\0';
12430 setvareq(nameeq, flags);
12437 * Same as setvar except that the variable and value are passed in
12438 * the first argument as name=value. Since the first argument will
12439 * be actually stored in the table, it should not be a string that
12448 struct var *vp, **vpp;
12451 flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
12452 if ((vp = *findvar(vpp, s))) {
12453 if (vp->flags & VREADONLY) {
12454 size_t len = strchr(s, '=') - s;
12455 error("%.*s: is read only", len, s);
12459 if (vp->func && (flags & VNOFUNC) == 0)
12460 (*vp->func)(strchr(s, '=') + 1);
12462 if ((vp->flags & (VTEXTFIXED|VSTACK)) == 0)
12465 vp->flags &= ~(VTEXTFIXED|VSTACK|VUNSET);
12466 vp->flags |= flags;
12470 * We could roll this to a function, to handle it as
12471 * a regular variable function callback, but why bother?
12473 if (iflag && (vp == &vmpath || (vp == &vmail && !mpathset())))
12479 vp = ckmalloc(sizeof (*vp));
12490 * Process a linked list of variable assignments.
12495 struct strlist *mylist;
12497 struct strlist *lp;
12500 for (lp = mylist ; lp ; lp = lp->next) {
12501 setvareq(savestr(lp->text), 0);
12509 * Find the value of a variable. Returns NULL if not set.
12512 static const char *
12518 if ((v = *findvar(hashvar(name), name)) && !(v->flags & VUNSET)) {
12519 return strchr(v->text, '=') + 1;
12527 * Search the environment of a builtin command.
12530 static const char *
12531 bltinlookup(const char *name)
12533 const struct strlist *sp;
12535 for (sp = cmdenviron ; sp ; sp = sp->next) {
12536 if (varequal(sp->text, name))
12537 return strchr(sp->text, '=') + 1;
12539 return lookupvar(name);
12545 * Generate a list of exported variables. This routine is used to construct
12546 * the third argument to execve when executing a program.
12558 for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
12559 for (vp = *vpp ; vp ; vp = vp->next)
12560 if (vp->flags & VEXPORT)
12563 ep = env = stalloc((nenv + 1) * sizeof *env);
12564 for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
12565 for (vp = *vpp ; vp ; vp = vp->next)
12566 if (vp->flags & VEXPORT)
12575 * Called when a shell procedure is invoked to clear out nonexported
12576 * variables. It is also necessary to reallocate variables of with
12577 * VSTACK set since these are currently allocated on the stack.
12583 struct var *vp, **prev;
12585 for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
12586 for (prev = vpp ; (vp = *prev) != NULL ; ) {
12587 if ((vp->flags & VEXPORT) == 0) {
12589 if ((vp->flags & VTEXTFIXED) == 0)
12591 if ((vp->flags & VSTRFIXED) == 0)
12594 if (vp->flags & VSTACK) {
12595 vp->text = savestr(vp->text);
12596 vp->flags &=~ VSTACK;
12608 * Command to list all variables which are set. Currently this command
12609 * is invoked from the set command when the set command is called without
12614 showvarscmd(argc, argv)
12618 showvars(nullstr, VUNSET, VUNSET);
12625 * The export and readonly commands.
12629 exportcmd(argc, argv)
12636 int flag = argv[0][0] == 'r'? VREADONLY : VEXPORT;
12639 listsetvar(cmdenviron);
12640 pflag = (nextopt("p") == 'p');
12641 if (argc > 1 && !pflag) {
12642 while ((name = *argptr++) != NULL) {
12643 if ((p = strchr(name, '=')) != NULL) {
12646 if ((vp = *findvar(hashvar(name), name))) {
12651 setvar(name, p, flag);
12655 showvars(argv[0], flag, 0);
12662 * The "local" command.
12665 /* funcnest nonzero if we are currently evaluating a function */
12668 localcmd(argc, argv)
12675 error("Not in a function");
12676 while ((name = *argptr++) != NULL) {
12684 * Make a variable a local variable. When a variable is made local, it's
12685 * value and flags are saved in a localvar structure. The saved values
12686 * will be restored when the shell function returns. We handle the name
12687 * "-" as a special case.
12694 struct localvar *lvp;
12699 lvp = ckmalloc(sizeof (struct localvar));
12700 if (name[0] == '-' && name[1] == '\0') {
12702 p = ckmalloc(sizeof optet_vals);
12703 lvp->text = memcpy(p, optet_vals, sizeof optet_vals);
12706 vpp = hashvar(name);
12707 vp = *findvar(vpp, name);
12709 if (strchr(name, '='))
12710 setvareq(savestr(name), VSTRFIXED);
12712 setvar(name, NULL, VSTRFIXED);
12713 vp = *vpp; /* the new variable */
12715 lvp->flags = VUNSET;
12717 lvp->text = vp->text;
12718 lvp->flags = vp->flags;
12719 vp->flags |= VSTRFIXED|VTEXTFIXED;
12720 if (strchr(name, '='))
12721 setvareq(savestr(name), 0);
12725 lvp->next = localvars;
12732 * Called after a function returns.
12737 struct localvar *lvp;
12740 while ((lvp = localvars) != NULL) {
12741 localvars = lvp->next;
12743 if (vp == NULL) { /* $- saved */
12744 memcpy(optet_vals, lvp->text, sizeof optet_vals);
12746 } else if ((lvp->flags & (VUNSET|VSTRFIXED)) == VUNSET) {
12747 (void)unsetvar(vp->text);
12749 if ((vp->flags & VTEXTFIXED) == 0)
12751 vp->flags = lvp->flags;
12752 vp->text = lvp->text;
12760 setvarcmd(argc, argv)
12765 return unsetcmd(argc, argv);
12766 else if (argc == 3)
12767 setvar(argv[1], argv[2], 0);
12769 error("List assignment not implemented");
12775 * The unset builtin command. We unset the function before we unset the
12776 * variable to allow a function to be unset when there is a readonly variable
12777 * with the same name.
12781 unsetcmd(argc, argv)
12791 while ((i = nextopt("vf")) != '\0') {
12797 if (flg_func == 0 && flg_var == 0)
12800 for (ap = argptr; *ap ; ap++) {
12804 ret |= unsetvar(*ap);
12811 * Unset the specified variable.
12815 unsetvar(const char *s)
12820 vpp = findvar(hashvar(s), s);
12823 if (vp->flags & VREADONLY)
12826 if (*(strchr(vp->text, '=') + 1) != '\0')
12827 setvar(s, nullstr, 0);
12828 vp->flags &= ~VEXPORT;
12829 vp->flags |= VUNSET;
12830 if ((vp->flags & VSTRFIXED) == 0) {
12831 if ((vp->flags & VTEXTFIXED) == 0)
12846 * Find the appropriate entry in the hash table from the name.
12849 static struct var **
12850 hashvar(const char *p)
12852 unsigned int hashval;
12854 hashval = ((unsigned char) *p) << 4;
12855 while (*p && *p != '=')
12856 hashval += (unsigned char) *p++;
12857 return &vartab[hashval % VTABSIZE];
12863 * Returns true if the two strings specify the same varable. The first
12864 * variable name is terminated by '='; the second may be terminated by
12865 * either '=' or '\0'.
12869 varequal(const char *p, const char *q)
12871 while (*p == *q++) {
12875 if (*p == '=' && *(q - 1) == '\0')
12881 showvars(const char *myprefix, int mask, int xor)
12885 const char *sep = myprefix == nullstr ? myprefix : spcstr;
12887 for (vpp = vartab ; vpp < vartab + VTABSIZE ; vpp++) {
12888 for (vp = *vpp ; vp ; vp = vp->next) {
12889 if ((vp->flags & mask) ^ xor) {
12893 p = strchr(vp->text, '=') + 1;
12894 len = p - vp->text;
12895 p = single_quote(p);
12897 printf("%s%s%.*s%s\n", myprefix, sep, len,
12905 static struct var **
12906 findvar(struct var **vpp, const char *name)
12908 for (; *vpp; vpp = &(*vpp)->next) {
12909 if (varequal((*vpp)->text, name)) {
12917 * Copyright (c) 1999 Herbert Xu <herbert@debian.org>
12918 * This file contains code for the times builtin.
12919 * $Id: ash.c,v 1.13 2001/07/26 05:58:40 russ Exp $
12921 static int timescmd (int argc, char **argv)
12924 long int clk_tck = sysconf(_SC_CLK_TCK);
12927 printf("%dm%fs %dm%fs\n%dm%fs %dm%fs\n",
12928 (int) (buf.tms_utime / clk_tck / 60),
12929 ((double) buf.tms_utime) / clk_tck,
12930 (int) (buf.tms_stime / clk_tck / 60),
12931 ((double) buf.tms_stime) / clk_tck,
12932 (int) (buf.tms_cutime / clk_tck / 60),
12933 ((double) buf.tms_cutime) / clk_tck,
12934 (int) (buf.tms_cstime / clk_tck / 60),
12935 ((double) buf.tms_cstime) / clk_tck);
12941 * Copyright (c) 1989, 1991, 1993, 1994
12942 * The Regents of the University of California. All rights reserved.
12944 * This code is derived from software contributed to Berkeley by
12945 * Kenneth Almquist.
12947 * Redistribution and use in source and binary forms, with or without
12948 * modification, are permitted provided that the following conditions
12950 * 1. Redistributions of source code must retain the above copyright
12951 * notice, this list of conditions and the following disclaimer.
12952 * 2. Redistributions in binary form must reproduce the above copyright
12953 * notice, this list of conditions and the following disclaimer in the
12954 * documentation and/or other materials provided with the distribution.
12956 * 3. <BSD Advertising Clause omitted per the July 22, 1999 licensing change
12957 * ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change>
12959 * 4. Neither the name of the University nor the names of its contributors
12960 * may be used to endorse or promote products derived from this software
12961 * without specific prior written permission.
12963 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
12964 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
12965 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
12966 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
12967 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
12968 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
12969 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
12970 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
12971 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
12972 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF