Busybox: Upgrade to 1.21.1 (stable). lsof active.
[tomato.git] / release / src / router / busybox / shell / ash.c
blob31fbc550a62532ecb99a831a71ae7c31b7e2c312
1 /* vi: set sw=4 ts=4: */
2 /*
3 * ash shell port for busybox
5 * This code is derived from software contributed to Berkeley by
6 * Kenneth Almquist.
8 * Original BSD copyright notice is retained at the end of this file.
10 * Copyright (c) 1989, 1991, 1993, 1994
11 * The Regents of the University of California. All rights reserved.
13 * Copyright (c) 1997-2005 Herbert Xu <herbert@gondor.apana.org.au>
14 * was re-ported from NetBSD and debianized.
16 * Licensed under GPLv2 or later, see file LICENSE in this source tree.
20 * The following should be set to reflect the type of system you have:
21 * JOBS -> 1 if you have Berkeley job control, 0 otherwise.
22 * define SYSV if you are running under System V.
23 * define DEBUG=1 to compile in debugging ('set -o debug' to turn on)
24 * define DEBUG=2 to compile in and turn on debugging.
26 * When debugging is on (DEBUG is 1 and "set -o debug" was executed),
27 * debugging info will be written to ./trace and a quit signal
28 * will generate a core dump.
30 #define DEBUG 0
31 /* Tweak debug output verbosity here */
32 #define DEBUG_TIME 0
33 #define DEBUG_PID 1
34 #define DEBUG_SIG 1
36 #define PROFILE 0
38 #define JOBS ENABLE_ASH_JOB_CONTROL
40 #include <paths.h>
41 #include <setjmp.h>
42 #include <fnmatch.h>
43 #include <sys/times.h>
45 #include "busybox.h" /* for applet_names */
46 #include "unicode.h"
48 #include "shell_common.h"
49 #if ENABLE_SH_MATH_SUPPORT
50 # include "math.h"
51 #endif
52 #if ENABLE_ASH_RANDOM_SUPPORT
53 # include "random.h"
54 #else
55 # define CLEAR_RANDOM_T(rnd) ((void)0)
56 #endif
58 #include "NUM_APPLETS.h"
59 #if NUM_APPLETS == 1
60 /* STANDALONE does not make sense, and won't compile */
61 # undef CONFIG_FEATURE_SH_STANDALONE
62 # undef ENABLE_FEATURE_SH_STANDALONE
63 # undef IF_FEATURE_SH_STANDALONE
64 # undef IF_NOT_FEATURE_SH_STANDALONE
65 # define ENABLE_FEATURE_SH_STANDALONE 0
66 # define IF_FEATURE_SH_STANDALONE(...)
67 # define IF_NOT_FEATURE_SH_STANDALONE(...) __VA_ARGS__
68 #endif
70 #ifndef PIPE_BUF
71 # define PIPE_BUF 4096 /* amount of buffering in a pipe */
72 #endif
74 #if !BB_MMU
75 # error "Do not even bother, ash will not run on NOMMU machine"
76 #endif
78 //config:config ASH
79 //config: bool "ash"
80 //config: default y
81 //config: depends on !NOMMU
82 //config: help
83 //config: Tha 'ash' shell adds about 60k in the default configuration and is
84 //config: the most complete and most pedantically correct shell included with
85 //config: busybox. This shell is actually a derivative of the Debian 'dash'
86 //config: shell (by Herbert Xu), which was created by porting the 'ash' shell
87 //config: (written by Kenneth Almquist) from NetBSD.
88 //config:
89 //config:config ASH_BASH_COMPAT
90 //config: bool "bash-compatible extensions"
91 //config: default y
92 //config: depends on ASH
93 //config: help
94 //config: Enable bash-compatible extensions.
95 //config:
96 //config:config ASH_IDLE_TIMEOUT
97 //config: bool "Idle timeout variable"
98 //config: default n
99 //config: depends on ASH
100 //config: help
101 //config: Enables bash-like auto-logout after $TMOUT seconds of idle time.
102 //config:
103 //config:config ASH_JOB_CONTROL
104 //config: bool "Job control"
105 //config: default y
106 //config: depends on ASH
107 //config: help
108 //config: Enable job control in the ash shell.
109 //config:
110 //config:config ASH_ALIAS
111 //config: bool "Alias support"
112 //config: default y
113 //config: depends on ASH
114 //config: help
115 //config: Enable alias support in the ash shell.
116 //config:
117 //config:config ASH_GETOPTS
118 //config: bool "Builtin getopt to parse positional parameters"
119 //config: default y
120 //config: depends on ASH
121 //config: help
122 //config: Enable support for getopts builtin in ash.
123 //config:
124 //config:config ASH_BUILTIN_ECHO
125 //config: bool "Builtin version of 'echo'"
126 //config: default y
127 //config: depends on ASH
128 //config: help
129 //config: Enable support for echo builtin in ash.
130 //config:
131 //config:config ASH_BUILTIN_PRINTF
132 //config: bool "Builtin version of 'printf'"
133 //config: default y
134 //config: depends on ASH
135 //config: help
136 //config: Enable support for printf builtin in ash.
137 //config:
138 //config:config ASH_BUILTIN_TEST
139 //config: bool "Builtin version of 'test'"
140 //config: default y
141 //config: depends on ASH
142 //config: help
143 //config: Enable support for test builtin in ash.
144 //config:
145 //config:config ASH_CMDCMD
146 //config: bool "'command' command to override shell builtins"
147 //config: default y
148 //config: depends on ASH
149 //config: help
150 //config: Enable support for the ash 'command' builtin, which allows
151 //config: you to run the specified command with the specified arguments,
152 //config: even when there is an ash builtin command with the same name.
153 //config:
154 //config:config ASH_MAIL
155 //config: bool "Check for new mail on interactive shells"
156 //config: default n
157 //config: depends on ASH
158 //config: help
159 //config: Enable "check for new mail" function in the ash shell.
160 //config:
161 //config:config ASH_OPTIMIZE_FOR_SIZE
162 //config: bool "Optimize for size instead of speed"
163 //config: default y
164 //config: depends on ASH
165 //config: help
166 //config: Compile ash for reduced size at the price of speed.
167 //config:
168 //config:config ASH_RANDOM_SUPPORT
169 //config: bool "Pseudorandom generator and $RANDOM variable"
170 //config: default y
171 //config: depends on ASH
172 //config: help
173 //config: Enable pseudorandom generator and dynamic variable "$RANDOM".
174 //config: Each read of "$RANDOM" will generate a new pseudorandom value.
175 //config: You can reset the generator by using a specified start value.
176 //config: After "unset RANDOM" the generator will switch off and this
177 //config: variable will no longer have special treatment.
178 //config:
179 //config:config ASH_EXPAND_PRMT
180 //config: bool "Expand prompt string"
181 //config: default y
182 //config: depends on ASH
183 //config: help
184 //config: "PS#" may contain volatile content, such as backquote commands.
185 //config: This option recreates the prompt string from the environment
186 //config: variable each time it is displayed.
187 //config:
189 //applet:IF_ASH(APPLET(ash, BB_DIR_BIN, BB_SUID_DROP))
190 //applet:IF_FEATURE_SH_IS_ASH(APPLET_ODDNAME(sh, ash, BB_DIR_BIN, BB_SUID_DROP, sh))
191 //applet:IF_FEATURE_BASH_IS_ASH(APPLET_ODDNAME(bash, ash, BB_DIR_BIN, BB_SUID_DROP, bash))
193 //kbuild:lib-$(CONFIG_ASH) += ash.o ash_ptr_hack.o shell_common.o
194 //kbuild:lib-$(CONFIG_ASH_RANDOM_SUPPORT) += random.o
197 /* ============ Hash table sizes. Configurable. */
199 #define VTABSIZE 39
200 #define ATABSIZE 39
201 #define CMDTABLESIZE 31 /* should be prime */
204 /* ============ Shell options */
206 static const char *const optletters_optnames[] = {
207 "e" "errexit",
208 "f" "noglob",
209 "I" "ignoreeof",
210 "i" "interactive",
211 "m" "monitor",
212 "n" "noexec",
213 "s" "stdin",
214 "x" "xtrace",
215 "v" "verbose",
216 "C" "noclobber",
217 "a" "allexport",
218 "b" "notify",
219 "u" "nounset",
220 "\0" "vi"
221 #if ENABLE_ASH_BASH_COMPAT
222 ,"\0" "pipefail"
223 #endif
224 #if DEBUG
225 ,"\0" "nolog"
226 ,"\0" "debug"
227 #endif
230 #define optletters(n) optletters_optnames[n][0]
231 #define optnames(n) (optletters_optnames[n] + 1)
233 enum { NOPTS = ARRAY_SIZE(optletters_optnames) };
236 /* ============ Misc data */
238 #define msg_illnum "Illegal number: %s"
241 * We enclose jmp_buf in a structure so that we can declare pointers to
242 * jump locations. The global variable handler contains the location to
243 * jump to when an exception occurs, and the global variable exception_type
244 * contains a code identifying the exception. To implement nested
245 * exception handlers, the user should save the value of handler on entry
246 * to an inner scope, set handler to point to a jmploc structure for the
247 * inner scope, and restore handler on exit from the scope.
249 struct jmploc {
250 jmp_buf loc;
253 struct globals_misc {
254 /* pid of main shell */
255 int rootpid;
256 /* shell level: 0 for the main shell, 1 for its children, and so on */
257 int shlvl;
258 #define rootshell (!shlvl)
259 char *minusc; /* argument to -c option */
261 char *curdir; // = nullstr; /* current working directory */
262 char *physdir; // = nullstr; /* physical working directory */
264 char *arg0; /* value of $0 */
266 struct jmploc *exception_handler;
268 volatile int suppress_int; /* counter */
269 volatile /*sig_atomic_t*/ smallint pending_int; /* 1 = got SIGINT */
270 /* last pending signal */
271 volatile /*sig_atomic_t*/ smallint pending_sig;
272 smallint exception_type; /* kind of exception (0..5) */
273 /* exceptions */
274 #define EXINT 0 /* SIGINT received */
275 #define EXERROR 1 /* a generic error */
276 #define EXSHELLPROC 2 /* execute a shell procedure */
277 #define EXEXEC 3 /* command execution failed */
278 #define EXEXIT 4 /* exit the shell */
279 #define EXSIG 5 /* trapped signal in wait(1) */
281 smallint isloginsh;
282 char nullstr[1]; /* zero length string */
284 char optlist[NOPTS];
285 #define eflag optlist[0]
286 #define fflag optlist[1]
287 #define Iflag optlist[2]
288 #define iflag optlist[3]
289 #define mflag optlist[4]
290 #define nflag optlist[5]
291 #define sflag optlist[6]
292 #define xflag optlist[7]
293 #define vflag optlist[8]
294 #define Cflag optlist[9]
295 #define aflag optlist[10]
296 #define bflag optlist[11]
297 #define uflag optlist[12]
298 #define viflag optlist[13]
299 #if ENABLE_ASH_BASH_COMPAT
300 # define pipefail optlist[14]
301 #else
302 # define pipefail 0
303 #endif
304 #if DEBUG
305 # define nolog optlist[14 + ENABLE_ASH_BASH_COMPAT]
306 # define debug optlist[15 + ENABLE_ASH_BASH_COMPAT]
307 #endif
309 /* trap handler commands */
311 * Sigmode records the current value of the signal handlers for the various
312 * modes. A value of zero means that the current handler is not known.
313 * S_HARD_IGN indicates that the signal was ignored on entry to the shell.
315 char sigmode[NSIG - 1];
316 #define S_DFL 1 /* default signal handling (SIG_DFL) */
317 #define S_CATCH 2 /* signal is caught */
318 #define S_IGN 3 /* signal is ignored (SIG_IGN) */
319 #define S_HARD_IGN 4 /* signal is ignored permenantly */
321 /* indicates specified signal received */
322 uint8_t gotsig[NSIG - 1]; /* offset by 1: "signal" 0 is meaningless */
323 uint8_t may_have_traps; /* 0: definitely no traps are set, 1: some traps may be set */
324 char *trap[NSIG];
325 char **trap_ptr; /* used only by "trap hack" */
327 /* Rarely referenced stuff */
328 #if ENABLE_ASH_RANDOM_SUPPORT
329 random_t random_gen;
330 #endif
331 pid_t backgndpid; /* pid of last background process */
332 smallint job_warning; /* user was warned about stopped jobs (can be 2, 1 or 0). */
334 extern struct globals_misc *const ash_ptr_to_globals_misc;
335 #define G_misc (*ash_ptr_to_globals_misc)
336 #define rootpid (G_misc.rootpid )
337 #define shlvl (G_misc.shlvl )
338 #define minusc (G_misc.minusc )
339 #define curdir (G_misc.curdir )
340 #define physdir (G_misc.physdir )
341 #define arg0 (G_misc.arg0 )
342 #define exception_handler (G_misc.exception_handler)
343 #define exception_type (G_misc.exception_type )
344 #define suppress_int (G_misc.suppress_int )
345 #define pending_int (G_misc.pending_int )
346 #define pending_sig (G_misc.pending_sig )
347 #define isloginsh (G_misc.isloginsh )
348 #define nullstr (G_misc.nullstr )
349 #define optlist (G_misc.optlist )
350 #define sigmode (G_misc.sigmode )
351 #define gotsig (G_misc.gotsig )
352 #define may_have_traps (G_misc.may_have_traps )
353 #define trap (G_misc.trap )
354 #define trap_ptr (G_misc.trap_ptr )
355 #define random_gen (G_misc.random_gen )
356 #define backgndpid (G_misc.backgndpid )
357 #define job_warning (G_misc.job_warning)
358 #define INIT_G_misc() do { \
359 (*(struct globals_misc**)&ash_ptr_to_globals_misc) = xzalloc(sizeof(G_misc)); \
360 barrier(); \
361 curdir = nullstr; \
362 physdir = nullstr; \
363 trap_ptr = trap; \
364 } while (0)
367 /* ============ DEBUG */
368 #if DEBUG
369 static void trace_printf(const char *fmt, ...);
370 static void trace_vprintf(const char *fmt, va_list va);
371 # define TRACE(param) trace_printf param
372 # define TRACEV(param) trace_vprintf param
373 # define close(fd) do { \
374 int dfd = (fd); \
375 if (close(dfd) < 0) \
376 bb_error_msg("bug on %d: closing %d(0x%x)", \
377 __LINE__, dfd, dfd); \
378 } while (0)
379 #else
380 # define TRACE(param)
381 # define TRACEV(param)
382 #endif
385 /* ============ Utility functions */
386 #define xbarrier() do { __asm__ __volatile__ ("": : :"memory"); } while (0)
388 static int isdigit_str9(const char *str)
390 int maxlen = 9 + 1; /* max 9 digits: 999999999 */
391 while (--maxlen && isdigit(*str))
392 str++;
393 return (*str == '\0');
396 static const char *var_end(const char *var)
398 while (*var)
399 if (*var++ == '=')
400 break;
401 return var;
405 /* ============ Interrupts / exceptions */
407 static void exitshell(void) NORETURN;
410 * These macros allow the user to suspend the handling of interrupt signals
411 * over a period of time. This is similar to SIGHOLD or to sigblock, but
412 * much more efficient and portable. (But hacking the kernel is so much
413 * more fun than worrying about efficiency and portability. :-))
415 #define INT_OFF do { \
416 suppress_int++; \
417 xbarrier(); \
418 } while (0)
421 * Called to raise an exception. Since C doesn't include exceptions, we
422 * just do a longjmp to the exception handler. The type of exception is
423 * stored in the global variable "exception_type".
425 static void raise_exception(int) NORETURN;
426 static void
427 raise_exception(int e)
429 #if DEBUG
430 if (exception_handler == NULL)
431 abort();
432 #endif
433 INT_OFF;
434 exception_type = e;
435 longjmp(exception_handler->loc, 1);
437 #if DEBUG
438 #define raise_exception(e) do { \
439 TRACE(("raising exception %d on line %d\n", (e), __LINE__)); \
440 raise_exception(e); \
441 } while (0)
442 #endif
445 * Called from trap.c when a SIGINT is received. (If the user specifies
446 * that SIGINT is to be trapped or ignored using the trap builtin, then
447 * this routine is not called.) Suppressint is nonzero when interrupts
448 * are held using the INT_OFF macro. (The test for iflag is just
449 * defensive programming.)
451 static void raise_interrupt(void) NORETURN;
452 static void
453 raise_interrupt(void)
455 int ex_type;
457 pending_int = 0;
458 /* Signal is not automatically unmasked after it is raised,
459 * do it ourself - unmask all signals */
460 sigprocmask_allsigs(SIG_UNBLOCK);
461 /* pending_sig = 0; - now done in signal_handler() */
463 ex_type = EXSIG;
464 if (gotsig[SIGINT - 1] && !trap[SIGINT]) {
465 if (!(rootshell && iflag)) {
466 /* Kill ourself with SIGINT */
467 signal(SIGINT, SIG_DFL);
468 raise(SIGINT);
470 ex_type = EXINT;
472 raise_exception(ex_type);
473 /* NOTREACHED */
475 #if DEBUG
476 #define raise_interrupt() do { \
477 TRACE(("raising interrupt on line %d\n", __LINE__)); \
478 raise_interrupt(); \
479 } while (0)
480 #endif
482 static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
483 int_on(void)
485 xbarrier();
486 if (--suppress_int == 0 && pending_int) {
487 raise_interrupt();
490 #define INT_ON int_on()
491 static IF_ASH_OPTIMIZE_FOR_SIZE(inline) void
492 force_int_on(void)
494 xbarrier();
495 suppress_int = 0;
496 if (pending_int)
497 raise_interrupt();
499 #define FORCE_INT_ON force_int_on()
501 #define SAVE_INT(v) ((v) = suppress_int)
503 #define RESTORE_INT(v) do { \
504 xbarrier(); \
505 suppress_int = (v); \
506 if (suppress_int == 0 && pending_int) \
507 raise_interrupt(); \
508 } while (0)
511 /* ============ Stdout/stderr output */
513 static void
514 outstr(const char *p, FILE *file)
516 INT_OFF;
517 fputs(p, file);
518 INT_ON;
521 static void
522 flush_stdout_stderr(void)
524 INT_OFF;
525 fflush_all();
526 INT_ON;
529 static void
530 outcslow(int c, FILE *dest)
532 INT_OFF;
533 putc(c, dest);
534 fflush(dest);
535 INT_ON;
538 static int out1fmt(const char *, ...) __attribute__((__format__(__printf__,1,2)));
539 static int
540 out1fmt(const char *fmt, ...)
542 va_list ap;
543 int r;
545 INT_OFF;
546 va_start(ap, fmt);
547 r = vprintf(fmt, ap);
548 va_end(ap);
549 INT_ON;
550 return r;
553 static int fmtstr(char *, size_t, const char *, ...) __attribute__((__format__(__printf__,3,4)));
554 static int
555 fmtstr(char *outbuf, size_t length, const char *fmt, ...)
557 va_list ap;
558 int ret;
560 va_start(ap, fmt);
561 INT_OFF;
562 ret = vsnprintf(outbuf, length, fmt, ap);
563 va_end(ap);
564 INT_ON;
565 return ret;
568 static void
569 out1str(const char *p)
571 outstr(p, stdout);
574 static void
575 out2str(const char *p)
577 outstr(p, stderr);
578 flush_stdout_stderr();
582 /* ============ Parser structures */
584 /* control characters in argument strings */
585 #define CTL_FIRST CTLESC
586 #define CTLESC ((unsigned char)'\201') /* escape next character */
587 #define CTLVAR ((unsigned char)'\202') /* variable defn */
588 #define CTLENDVAR ((unsigned char)'\203')
589 #define CTLBACKQ ((unsigned char)'\204')
590 #define CTLQUOTE 01 /* ored with CTLBACKQ code if in quotes */
591 /* CTLBACKQ | CTLQUOTE == '\205' */
592 #define CTLARI ((unsigned char)'\206') /* arithmetic expression */
593 #define CTLENDARI ((unsigned char)'\207')
594 #define CTLQUOTEMARK ((unsigned char)'\210')
595 #define CTL_LAST CTLQUOTEMARK
597 /* variable substitution byte (follows CTLVAR) */
598 #define VSTYPE 0x0f /* type of variable substitution */
599 #define VSNUL 0x10 /* colon--treat the empty string as unset */
600 #define VSQUOTE 0x80 /* inside double quotes--suppress splitting */
602 /* values of VSTYPE field */
603 #define VSNORMAL 0x1 /* normal variable: $var or ${var} */
604 #define VSMINUS 0x2 /* ${var-text} */
605 #define VSPLUS 0x3 /* ${var+text} */
606 #define VSQUESTION 0x4 /* ${var?message} */
607 #define VSASSIGN 0x5 /* ${var=text} */
608 #define VSTRIMRIGHT 0x6 /* ${var%pattern} */
609 #define VSTRIMRIGHTMAX 0x7 /* ${var%%pattern} */
610 #define VSTRIMLEFT 0x8 /* ${var#pattern} */
611 #define VSTRIMLEFTMAX 0x9 /* ${var##pattern} */
612 #define VSLENGTH 0xa /* ${#var} */
613 #if ENABLE_ASH_BASH_COMPAT
614 #define VSSUBSTR 0xc /* ${var:position:length} */
615 #define VSREPLACE 0xd /* ${var/pattern/replacement} */
616 #define VSREPLACEALL 0xe /* ${var//pattern/replacement} */
617 #endif
619 static const char dolatstr[] ALIGN1 = {
620 CTLVAR, VSNORMAL|VSQUOTE, '@', '=', '\0'
623 #define NCMD 0
624 #define NPIPE 1
625 #define NREDIR 2
626 #define NBACKGND 3
627 #define NSUBSHELL 4
628 #define NAND 5
629 #define NOR 6
630 #define NSEMI 7
631 #define NIF 8
632 #define NWHILE 9
633 #define NUNTIL 10
634 #define NFOR 11
635 #define NCASE 12
636 #define NCLIST 13
637 #define NDEFUN 14
638 #define NARG 15
639 #define NTO 16
640 #if ENABLE_ASH_BASH_COMPAT
641 #define NTO2 17
642 #endif
643 #define NCLOBBER 18
644 #define NFROM 19
645 #define NFROMTO 20
646 #define NAPPEND 21
647 #define NTOFD 22
648 #define NFROMFD 23
649 #define NHERE 24
650 #define NXHERE 25
651 #define NNOT 26
652 #define N_NUMBER 27
654 union node;
656 struct ncmd {
657 smallint type; /* Nxxxx */
658 union node *assign;
659 union node *args;
660 union node *redirect;
663 struct npipe {
664 smallint type;
665 smallint pipe_backgnd;
666 struct nodelist *cmdlist;
669 struct nredir {
670 smallint type;
671 union node *n;
672 union node *redirect;
675 struct nbinary {
676 smallint type;
677 union node *ch1;
678 union node *ch2;
681 struct nif {
682 smallint type;
683 union node *test;
684 union node *ifpart;
685 union node *elsepart;
688 struct nfor {
689 smallint type;
690 union node *args;
691 union node *body;
692 char *var;
695 struct ncase {
696 smallint type;
697 union node *expr;
698 union node *cases;
701 struct nclist {
702 smallint type;
703 union node *next;
704 union node *pattern;
705 union node *body;
708 struct narg {
709 smallint type;
710 union node *next;
711 char *text;
712 struct nodelist *backquote;
715 /* nfile and ndup layout must match!
716 * NTOFD (>&fdnum) uses ndup structure, but we may discover mid-flight
717 * that it is actually NTO2 (>&file), and change its type.
719 struct nfile {
720 smallint type;
721 union node *next;
722 int fd;
723 int _unused_dupfd;
724 union node *fname;
725 char *expfname;
728 struct ndup {
729 smallint type;
730 union node *next;
731 int fd;
732 int dupfd;
733 union node *vname;
734 char *_unused_expfname;
737 struct nhere {
738 smallint type;
739 union node *next;
740 int fd;
741 union node *doc;
744 struct nnot {
745 smallint type;
746 union node *com;
749 union node {
750 smallint type;
751 struct ncmd ncmd;
752 struct npipe npipe;
753 struct nredir nredir;
754 struct nbinary nbinary;
755 struct nif nif;
756 struct nfor nfor;
757 struct ncase ncase;
758 struct nclist nclist;
759 struct narg narg;
760 struct nfile nfile;
761 struct ndup ndup;
762 struct nhere nhere;
763 struct nnot nnot;
767 * NODE_EOF is returned by parsecmd when it encounters an end of file.
768 * It must be distinct from NULL.
770 #define NODE_EOF ((union node *) -1L)
772 struct nodelist {
773 struct nodelist *next;
774 union node *n;
777 struct funcnode {
778 int count;
779 union node n;
783 * Free a parse tree.
785 static void
786 freefunc(struct funcnode *f)
788 if (f && --f->count < 0)
789 free(f);
793 /* ============ Debugging output */
795 #if DEBUG
797 static FILE *tracefile;
799 static void
800 trace_printf(const char *fmt, ...)
802 va_list va;
804 if (debug != 1)
805 return;
806 if (DEBUG_TIME)
807 fprintf(tracefile, "%u ", (int) time(NULL));
808 if (DEBUG_PID)
809 fprintf(tracefile, "[%u] ", (int) getpid());
810 if (DEBUG_SIG)
811 fprintf(tracefile, "pending s:%d i:%d(supp:%d) ", pending_sig, pending_int, suppress_int);
812 va_start(va, fmt);
813 vfprintf(tracefile, fmt, va);
814 va_end(va);
817 static void
818 trace_vprintf(const char *fmt, va_list va)
820 if (debug != 1)
821 return;
822 if (DEBUG_TIME)
823 fprintf(tracefile, "%u ", (int) time(NULL));
824 if (DEBUG_PID)
825 fprintf(tracefile, "[%u] ", (int) getpid());
826 if (DEBUG_SIG)
827 fprintf(tracefile, "pending s:%d i:%d(supp:%d) ", pending_sig, pending_int, suppress_int);
828 vfprintf(tracefile, fmt, va);
831 static void
832 trace_puts(const char *s)
834 if (debug != 1)
835 return;
836 fputs(s, tracefile);
839 static void
840 trace_puts_quoted(char *s)
842 char *p;
843 char c;
845 if (debug != 1)
846 return;
847 putc('"', tracefile);
848 for (p = s; *p; p++) {
849 switch ((unsigned char)*p) {
850 case '\n': c = 'n'; goto backslash;
851 case '\t': c = 't'; goto backslash;
852 case '\r': c = 'r'; goto backslash;
853 case '\"': c = '\"'; goto backslash;
854 case '\\': c = '\\'; goto backslash;
855 case CTLESC: c = 'e'; goto backslash;
856 case CTLVAR: c = 'v'; goto backslash;
857 case CTLVAR+CTLQUOTE: c = 'V'; goto backslash;
858 case CTLBACKQ: c = 'q'; goto backslash;
859 case CTLBACKQ+CTLQUOTE: c = 'Q'; goto backslash;
860 backslash:
861 putc('\\', tracefile);
862 putc(c, tracefile);
863 break;
864 default:
865 if (*p >= ' ' && *p <= '~')
866 putc(*p, tracefile);
867 else {
868 putc('\\', tracefile);
869 putc((*p >> 6) & 03, tracefile);
870 putc((*p >> 3) & 07, tracefile);
871 putc(*p & 07, tracefile);
873 break;
876 putc('"', tracefile);
879 static void
880 trace_puts_args(char **ap)
882 if (debug != 1)
883 return;
884 if (!*ap)
885 return;
886 while (1) {
887 trace_puts_quoted(*ap);
888 if (!*++ap) {
889 putc('\n', tracefile);
890 break;
892 putc(' ', tracefile);
896 static void
897 opentrace(void)
899 char s[100];
900 #ifdef O_APPEND
901 int flags;
902 #endif
904 if (debug != 1) {
905 if (tracefile)
906 fflush(tracefile);
907 /* leave open because libedit might be using it */
908 return;
910 strcpy(s, "./trace");
911 if (tracefile) {
912 if (!freopen(s, "a", tracefile)) {
913 fprintf(stderr, "Can't re-open %s\n", s);
914 debug = 0;
915 return;
917 } else {
918 tracefile = fopen(s, "a");
919 if (tracefile == NULL) {
920 fprintf(stderr, "Can't open %s\n", s);
921 debug = 0;
922 return;
925 #ifdef O_APPEND
926 flags = fcntl(fileno(tracefile), F_GETFL);
927 if (flags >= 0)
928 fcntl(fileno(tracefile), F_SETFL, flags | O_APPEND);
929 #endif
930 setlinebuf(tracefile);
931 fputs("\nTracing started.\n", tracefile);
934 static void
935 indent(int amount, char *pfx, FILE *fp)
937 int i;
939 for (i = 0; i < amount; i++) {
940 if (pfx && i == amount - 1)
941 fputs(pfx, fp);
942 putc('\t', fp);
946 /* little circular references here... */
947 static void shtree(union node *n, int ind, char *pfx, FILE *fp);
949 static void
950 sharg(union node *arg, FILE *fp)
952 char *p;
953 struct nodelist *bqlist;
954 unsigned char subtype;
956 if (arg->type != NARG) {
957 out1fmt("<node type %d>\n", arg->type);
958 abort();
960 bqlist = arg->narg.backquote;
961 for (p = arg->narg.text; *p; p++) {
962 switch ((unsigned char)*p) {
963 case CTLESC:
964 p++;
965 putc(*p, fp);
966 break;
967 case CTLVAR:
968 putc('$', fp);
969 putc('{', fp);
970 subtype = *++p;
971 if (subtype == VSLENGTH)
972 putc('#', fp);
974 while (*p != '=') {
975 putc(*p, fp);
976 p++;
979 if (subtype & VSNUL)
980 putc(':', fp);
982 switch (subtype & VSTYPE) {
983 case VSNORMAL:
984 putc('}', fp);
985 break;
986 case VSMINUS:
987 putc('-', fp);
988 break;
989 case VSPLUS:
990 putc('+', fp);
991 break;
992 case VSQUESTION:
993 putc('?', fp);
994 break;
995 case VSASSIGN:
996 putc('=', fp);
997 break;
998 case VSTRIMLEFT:
999 putc('#', fp);
1000 break;
1001 case VSTRIMLEFTMAX:
1002 putc('#', fp);
1003 putc('#', fp);
1004 break;
1005 case VSTRIMRIGHT:
1006 putc('%', fp);
1007 break;
1008 case VSTRIMRIGHTMAX:
1009 putc('%', fp);
1010 putc('%', fp);
1011 break;
1012 case VSLENGTH:
1013 break;
1014 default:
1015 out1fmt("<subtype %d>", subtype);
1017 break;
1018 case CTLENDVAR:
1019 putc('}', fp);
1020 break;
1021 case CTLBACKQ:
1022 case CTLBACKQ|CTLQUOTE:
1023 putc('$', fp);
1024 putc('(', fp);
1025 shtree(bqlist->n, -1, NULL, fp);
1026 putc(')', fp);
1027 break;
1028 default:
1029 putc(*p, fp);
1030 break;
1035 static void
1036 shcmd(union node *cmd, FILE *fp)
1038 union node *np;
1039 int first;
1040 const char *s;
1041 int dftfd;
1043 first = 1;
1044 for (np = cmd->ncmd.args; np; np = np->narg.next) {
1045 if (!first)
1046 putc(' ', fp);
1047 sharg(np, fp);
1048 first = 0;
1050 for (np = cmd->ncmd.redirect; np; np = np->nfile.next) {
1051 if (!first)
1052 putc(' ', fp);
1053 dftfd = 0;
1054 switch (np->nfile.type) {
1055 case NTO: s = ">>"+1; dftfd = 1; break;
1056 case NCLOBBER: s = ">|"; dftfd = 1; break;
1057 case NAPPEND: s = ">>"; dftfd = 1; break;
1058 #if ENABLE_ASH_BASH_COMPAT
1059 case NTO2:
1060 #endif
1061 case NTOFD: s = ">&"; dftfd = 1; break;
1062 case NFROM: s = "<"; break;
1063 case NFROMFD: s = "<&"; break;
1064 case NFROMTO: s = "<>"; break;
1065 default: s = "*error*"; break;
1067 if (np->nfile.fd != dftfd)
1068 fprintf(fp, "%d", np->nfile.fd);
1069 fputs(s, fp);
1070 if (np->nfile.type == NTOFD || np->nfile.type == NFROMFD) {
1071 fprintf(fp, "%d", np->ndup.dupfd);
1072 } else {
1073 sharg(np->nfile.fname, fp);
1075 first = 0;
1079 static void
1080 shtree(union node *n, int ind, char *pfx, FILE *fp)
1082 struct nodelist *lp;
1083 const char *s;
1085 if (n == NULL)
1086 return;
1088 indent(ind, pfx, fp);
1090 if (n == NODE_EOF) {
1091 fputs("<EOF>", fp);
1092 return;
1095 switch (n->type) {
1096 case NSEMI:
1097 s = "; ";
1098 goto binop;
1099 case NAND:
1100 s = " && ";
1101 goto binop;
1102 case NOR:
1103 s = " || ";
1104 binop:
1105 shtree(n->nbinary.ch1, ind, NULL, fp);
1106 /* if (ind < 0) */
1107 fputs(s, fp);
1108 shtree(n->nbinary.ch2, ind, NULL, fp);
1109 break;
1110 case NCMD:
1111 shcmd(n, fp);
1112 if (ind >= 0)
1113 putc('\n', fp);
1114 break;
1115 case NPIPE:
1116 for (lp = n->npipe.cmdlist; lp; lp = lp->next) {
1117 shtree(lp->n, 0, NULL, fp);
1118 if (lp->next)
1119 fputs(" | ", fp);
1121 if (n->npipe.pipe_backgnd)
1122 fputs(" &", fp);
1123 if (ind >= 0)
1124 putc('\n', fp);
1125 break;
1126 default:
1127 fprintf(fp, "<node type %d>", n->type);
1128 if (ind >= 0)
1129 putc('\n', fp);
1130 break;
1134 static void
1135 showtree(union node *n)
1137 trace_puts("showtree called\n");
1138 shtree(n, 1, NULL, stderr);
1141 #endif /* DEBUG */
1144 /* ============ Parser data */
1147 * ash_vmsg() needs parsefile->fd, hence parsefile definition is moved up.
1149 struct strlist {
1150 struct strlist *next;
1151 char *text;
1154 struct alias;
1156 struct strpush {
1157 struct strpush *prev; /* preceding string on stack */
1158 char *prev_string;
1159 int prev_left_in_line;
1160 #if ENABLE_ASH_ALIAS
1161 struct alias *ap; /* if push was associated with an alias */
1162 #endif
1163 char *string; /* remember the string since it may change */
1166 struct parsefile {
1167 struct parsefile *prev; /* preceding file on stack */
1168 int linno; /* current line */
1169 int pf_fd; /* file descriptor (or -1 if string) */
1170 int left_in_line; /* number of chars left in this line */
1171 int left_in_buffer; /* number of chars left in this buffer past the line */
1172 char *next_to_pgetc; /* next char in buffer */
1173 char *buf; /* input buffer */
1174 struct strpush *strpush; /* for pushing strings at this level */
1175 struct strpush basestrpush; /* so pushing one is fast */
1178 static struct parsefile basepf; /* top level input file */
1179 static struct parsefile *g_parsefile = &basepf; /* current input file */
1180 static int startlinno; /* line # where last token started */
1181 static char *commandname; /* currently executing command */
1182 static struct strlist *cmdenviron; /* environment for builtin command */
1183 static uint8_t exitstatus; /* exit status of last command */
1186 /* ============ Message printing */
1188 static void
1189 ash_vmsg(const char *msg, va_list ap)
1191 fprintf(stderr, "%s: ", arg0);
1192 if (commandname) {
1193 if (strcmp(arg0, commandname))
1194 fprintf(stderr, "%s: ", commandname);
1195 if (!iflag || g_parsefile->pf_fd > 0)
1196 fprintf(stderr, "line %d: ", startlinno);
1198 vfprintf(stderr, msg, ap);
1199 outcslow('\n', stderr);
1203 * Exverror is called to raise the error exception. If the second argument
1204 * is not NULL then error prints an error message using printf style
1205 * formatting. It then raises the error exception.
1207 static void ash_vmsg_and_raise(int, const char *, va_list) NORETURN;
1208 static void
1209 ash_vmsg_and_raise(int cond, const char *msg, va_list ap)
1211 #if DEBUG
1212 if (msg) {
1213 TRACE(("ash_vmsg_and_raise(%d, \"", cond));
1214 TRACEV((msg, ap));
1215 TRACE(("\") pid=%d\n", getpid()));
1216 } else
1217 TRACE(("ash_vmsg_and_raise(%d, NULL) pid=%d\n", cond, getpid()));
1218 if (msg)
1219 #endif
1220 ash_vmsg(msg, ap);
1222 flush_stdout_stderr();
1223 raise_exception(cond);
1224 /* NOTREACHED */
1227 static void ash_msg_and_raise_error(const char *, ...) NORETURN;
1228 static void
1229 ash_msg_and_raise_error(const char *msg, ...)
1231 va_list ap;
1233 va_start(ap, msg);
1234 ash_vmsg_and_raise(EXERROR, msg, ap);
1235 /* NOTREACHED */
1236 va_end(ap);
1239 static void raise_error_syntax(const char *) NORETURN;
1240 static void
1241 raise_error_syntax(const char *msg)
1243 ash_msg_and_raise_error("syntax error: %s", msg);
1244 /* NOTREACHED */
1247 static void ash_msg_and_raise(int, const char *, ...) NORETURN;
1248 static void
1249 ash_msg_and_raise(int cond, const char *msg, ...)
1251 va_list ap;
1253 va_start(ap, msg);
1254 ash_vmsg_and_raise(cond, msg, ap);
1255 /* NOTREACHED */
1256 va_end(ap);
1260 * error/warning routines for external builtins
1262 static void
1263 ash_msg(const char *fmt, ...)
1265 va_list ap;
1267 va_start(ap, fmt);
1268 ash_vmsg(fmt, ap);
1269 va_end(ap);
1273 * Return a string describing an error. The returned string may be a
1274 * pointer to a static buffer that will be overwritten on the next call.
1275 * Action describes the operation that got the error.
1277 static const char *
1278 errmsg(int e, const char *em)
1280 if (e == ENOENT || e == ENOTDIR) {
1281 return em;
1283 return strerror(e);
1287 /* ============ Memory allocation */
1289 #if 0
1290 /* I consider these wrappers nearly useless:
1291 * ok, they return you to nearest exception handler, but
1292 * how much memory do you leak in the process, making
1293 * memory starvation worse?
1295 static void *
1296 ckrealloc(void * p, size_t nbytes)
1298 p = realloc(p, nbytes);
1299 if (!p)
1300 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1301 return p;
1304 static void *
1305 ckmalloc(size_t nbytes)
1307 return ckrealloc(NULL, nbytes);
1310 static void *
1311 ckzalloc(size_t nbytes)
1313 return memset(ckmalloc(nbytes), 0, nbytes);
1316 static char *
1317 ckstrdup(const char *s)
1319 char *p = strdup(s);
1320 if (!p)
1321 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1322 return p;
1324 #else
1325 /* Using bbox equivalents. They exit if out of memory */
1326 # define ckrealloc xrealloc
1327 # define ckmalloc xmalloc
1328 # define ckzalloc xzalloc
1329 # define ckstrdup xstrdup
1330 #endif
1333 * It appears that grabstackstr() will barf with such alignments
1334 * because stalloc() will return a string allocated in a new stackblock.
1336 #define SHELL_ALIGN(nbytes) (((nbytes) + SHELL_SIZE) & ~SHELL_SIZE)
1337 enum {
1338 /* Most machines require the value returned from malloc to be aligned
1339 * in some way. The following macro will get this right
1340 * on many machines. */
1341 SHELL_SIZE = sizeof(union { int i; char *cp; double d; }) - 1,
1342 /* Minimum size of a block */
1343 MINSIZE = SHELL_ALIGN(504),
1346 struct stack_block {
1347 struct stack_block *prev;
1348 char space[MINSIZE];
1351 struct stackmark {
1352 struct stack_block *stackp;
1353 char *stacknxt;
1354 size_t stacknleft;
1355 struct stackmark *marknext;
1359 struct globals_memstack {
1360 struct stack_block *g_stackp; // = &stackbase;
1361 struct stackmark *markp;
1362 char *g_stacknxt; // = stackbase.space;
1363 char *sstrend; // = stackbase.space + MINSIZE;
1364 size_t g_stacknleft; // = MINSIZE;
1365 int herefd; // = -1;
1366 struct stack_block stackbase;
1368 extern struct globals_memstack *const ash_ptr_to_globals_memstack;
1369 #define G_memstack (*ash_ptr_to_globals_memstack)
1370 #define g_stackp (G_memstack.g_stackp )
1371 #define markp (G_memstack.markp )
1372 #define g_stacknxt (G_memstack.g_stacknxt )
1373 #define sstrend (G_memstack.sstrend )
1374 #define g_stacknleft (G_memstack.g_stacknleft)
1375 #define herefd (G_memstack.herefd )
1376 #define stackbase (G_memstack.stackbase )
1377 #define INIT_G_memstack() do { \
1378 (*(struct globals_memstack**)&ash_ptr_to_globals_memstack) = xzalloc(sizeof(G_memstack)); \
1379 barrier(); \
1380 g_stackp = &stackbase; \
1381 g_stacknxt = stackbase.space; \
1382 g_stacknleft = MINSIZE; \
1383 sstrend = stackbase.space + MINSIZE; \
1384 herefd = -1; \
1385 } while (0)
1388 #define stackblock() ((void *)g_stacknxt)
1389 #define stackblocksize() g_stacknleft
1392 * Parse trees for commands are allocated in lifo order, so we use a stack
1393 * to make this more efficient, and also to avoid all sorts of exception
1394 * handling code to handle interrupts in the middle of a parse.
1396 * The size 504 was chosen because the Ultrix malloc handles that size
1397 * well.
1399 static void *
1400 stalloc(size_t nbytes)
1402 char *p;
1403 size_t aligned;
1405 aligned = SHELL_ALIGN(nbytes);
1406 if (aligned > g_stacknleft) {
1407 size_t len;
1408 size_t blocksize;
1409 struct stack_block *sp;
1411 blocksize = aligned;
1412 if (blocksize < MINSIZE)
1413 blocksize = MINSIZE;
1414 len = sizeof(struct stack_block) - MINSIZE + blocksize;
1415 if (len < blocksize)
1416 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1417 INT_OFF;
1418 sp = ckmalloc(len);
1419 sp->prev = g_stackp;
1420 g_stacknxt = sp->space;
1421 g_stacknleft = blocksize;
1422 sstrend = g_stacknxt + blocksize;
1423 g_stackp = sp;
1424 INT_ON;
1426 p = g_stacknxt;
1427 g_stacknxt += aligned;
1428 g_stacknleft -= aligned;
1429 return p;
1432 static void *
1433 stzalloc(size_t nbytes)
1435 return memset(stalloc(nbytes), 0, nbytes);
1438 static void
1439 stunalloc(void *p)
1441 #if DEBUG
1442 if (!p || (g_stacknxt < (char *)p) || ((char *)p < g_stackp->space)) {
1443 write(STDERR_FILENO, "stunalloc\n", 10);
1444 abort();
1446 #endif
1447 g_stacknleft += g_stacknxt - (char *)p;
1448 g_stacknxt = p;
1452 * Like strdup but works with the ash stack.
1454 static char *
1455 ststrdup(const char *p)
1457 size_t len = strlen(p) + 1;
1458 return memcpy(stalloc(len), p, len);
1461 static void
1462 setstackmark(struct stackmark *mark)
1464 mark->stackp = g_stackp;
1465 mark->stacknxt = g_stacknxt;
1466 mark->stacknleft = g_stacknleft;
1467 mark->marknext = markp;
1468 markp = mark;
1471 static void
1472 popstackmark(struct stackmark *mark)
1474 struct stack_block *sp;
1476 if (!mark->stackp)
1477 return;
1479 INT_OFF;
1480 markp = mark->marknext;
1481 while (g_stackp != mark->stackp) {
1482 sp = g_stackp;
1483 g_stackp = sp->prev;
1484 free(sp);
1486 g_stacknxt = mark->stacknxt;
1487 g_stacknleft = mark->stacknleft;
1488 sstrend = mark->stacknxt + mark->stacknleft;
1489 INT_ON;
1493 * When the parser reads in a string, it wants to stick the string on the
1494 * stack and only adjust the stack pointer when it knows how big the
1495 * string is. Stackblock (defined in stack.h) returns a pointer to a block
1496 * of space on top of the stack and stackblocklen returns the length of
1497 * this block. Growstackblock will grow this space by at least one byte,
1498 * possibly moving it (like realloc). Grabstackblock actually allocates the
1499 * part of the block that has been used.
1501 static void
1502 growstackblock(void)
1504 size_t newlen;
1506 newlen = g_stacknleft * 2;
1507 if (newlen < g_stacknleft)
1508 ash_msg_and_raise_error(bb_msg_memory_exhausted);
1509 if (newlen < 128)
1510 newlen += 128;
1512 if (g_stacknxt == g_stackp->space && g_stackp != &stackbase) {
1513 struct stack_block *oldstackp;
1514 struct stackmark *xmark;
1515 struct stack_block *sp;
1516 struct stack_block *prevstackp;
1517 size_t grosslen;
1519 INT_OFF;
1520 oldstackp = g_stackp;
1521 sp = g_stackp;
1522 prevstackp = sp->prev;
1523 grosslen = newlen + sizeof(struct stack_block) - MINSIZE;
1524 sp = ckrealloc(sp, grosslen);
1525 sp->prev = prevstackp;
1526 g_stackp = sp;
1527 g_stacknxt = sp->space;
1528 g_stacknleft = newlen;
1529 sstrend = sp->space + newlen;
1532 * Stack marks pointing to the start of the old block
1533 * must be relocated to point to the new block
1535 xmark = markp;
1536 while (xmark != NULL && xmark->stackp == oldstackp) {
1537 xmark->stackp = g_stackp;
1538 xmark->stacknxt = g_stacknxt;
1539 xmark->stacknleft = g_stacknleft;
1540 xmark = xmark->marknext;
1542 INT_ON;
1543 } else {
1544 char *oldspace = g_stacknxt;
1545 size_t oldlen = g_stacknleft;
1546 char *p = stalloc(newlen);
1548 /* free the space we just allocated */
1549 g_stacknxt = memcpy(p, oldspace, oldlen);
1550 g_stacknleft += newlen;
1554 static void
1555 grabstackblock(size_t len)
1557 len = SHELL_ALIGN(len);
1558 g_stacknxt += len;
1559 g_stacknleft -= len;
1563 * The following routines are somewhat easier to use than the above.
1564 * The user declares a variable of type STACKSTR, which may be declared
1565 * to be a register. The macro STARTSTACKSTR initializes things. Then
1566 * the user uses the macro STPUTC to add characters to the string. In
1567 * effect, STPUTC(c, p) is the same as *p++ = c except that the stack is
1568 * grown as necessary. When the user is done, she can just leave the
1569 * string there and refer to it using stackblock(). Or she can allocate
1570 * the space for it using grabstackstr(). If it is necessary to allow
1571 * someone else to use the stack temporarily and then continue to grow
1572 * the string, the user should use grabstack to allocate the space, and
1573 * then call ungrabstr(p) to return to the previous mode of operation.
1575 * USTPUTC is like STPUTC except that it doesn't check for overflow.
1576 * CHECKSTACKSPACE can be called before USTPUTC to ensure that there
1577 * is space for at least one character.
1579 static void *
1580 growstackstr(void)
1582 size_t len = stackblocksize();
1583 if (herefd >= 0 && len >= 1024) {
1584 full_write(herefd, stackblock(), len);
1585 return stackblock();
1587 growstackblock();
1588 return (char *)stackblock() + len;
1592 * Called from CHECKSTRSPACE.
1594 static char *
1595 makestrspace(size_t newlen, char *p)
1597 size_t len = p - g_stacknxt;
1598 size_t size = stackblocksize();
1600 for (;;) {
1601 size_t nleft;
1603 size = stackblocksize();
1604 nleft = size - len;
1605 if (nleft >= newlen)
1606 break;
1607 growstackblock();
1609 return (char *)stackblock() + len;
1612 static char *
1613 stack_nputstr(const char *s, size_t n, char *p)
1615 p = makestrspace(n, p);
1616 p = (char *)memcpy(p, s, n) + n;
1617 return p;
1620 static char *
1621 stack_putstr(const char *s, char *p)
1623 return stack_nputstr(s, strlen(s), p);
1626 static char *
1627 _STPUTC(int c, char *p)
1629 if (p == sstrend)
1630 p = growstackstr();
1631 *p++ = c;
1632 return p;
1635 #define STARTSTACKSTR(p) ((p) = stackblock())
1636 #define STPUTC(c, p) ((p) = _STPUTC((c), (p)))
1637 #define CHECKSTRSPACE(n, p) do { \
1638 char *q = (p); \
1639 size_t l = (n); \
1640 size_t m = sstrend - q; \
1641 if (l > m) \
1642 (p) = makestrspace(l, q); \
1643 } while (0)
1644 #define USTPUTC(c, p) (*(p)++ = (c))
1645 #define STACKSTRNUL(p) do { \
1646 if ((p) == sstrend) \
1647 (p) = growstackstr(); \
1648 *(p) = '\0'; \
1649 } while (0)
1650 #define STUNPUTC(p) (--(p))
1651 #define STTOPC(p) ((p)[-1])
1652 #define STADJUST(amount, p) ((p) += (amount))
1654 #define grabstackstr(p) stalloc((char *)(p) - (char *)stackblock())
1655 #define ungrabstackstr(s, p) stunalloc(s)
1656 #define stackstrend() ((void *)sstrend)
1659 /* ============ String helpers */
1662 * prefix -- see if pfx is a prefix of string.
1664 static char *
1665 prefix(const char *string, const char *pfx)
1667 while (*pfx) {
1668 if (*pfx++ != *string++)
1669 return NULL;
1671 return (char *) string;
1675 * Check for a valid number. This should be elsewhere.
1677 static int
1678 is_number(const char *p)
1680 do {
1681 if (!isdigit(*p))
1682 return 0;
1683 } while (*++p != '\0');
1684 return 1;
1688 * Convert a string of digits to an integer, printing an error message on
1689 * failure.
1691 static int
1692 number(const char *s)
1694 if (!is_number(s))
1695 ash_msg_and_raise_error(msg_illnum, s);
1696 return atoi(s);
1700 * Produce a possibly single quoted string suitable as input to the shell.
1701 * The return string is allocated on the stack.
1703 static char *
1704 single_quote(const char *s)
1706 char *p;
1708 STARTSTACKSTR(p);
1710 do {
1711 char *q;
1712 size_t len;
1714 len = strchrnul(s, '\'') - s;
1716 q = p = makestrspace(len + 3, p);
1718 *q++ = '\'';
1719 q = (char *)memcpy(q, s, len) + len;
1720 *q++ = '\'';
1721 s += len;
1723 STADJUST(q - p, p);
1725 if (*s != '\'')
1726 break;
1727 len = 0;
1728 do len++; while (*++s == '\'');
1730 q = p = makestrspace(len + 3, p);
1732 *q++ = '"';
1733 q = (char *)memcpy(q, s - len, len) + len;
1734 *q++ = '"';
1736 STADJUST(q - p, p);
1737 } while (*s);
1739 USTPUTC('\0', p);
1741 return stackblock();
1745 /* ============ nextopt */
1747 static char **argptr; /* argument list for builtin commands */
1748 static char *optionarg; /* set by nextopt (like getopt) */
1749 static char *optptr; /* used by nextopt */
1752 * XXX - should get rid of. Have all builtins use getopt(3).
1753 * The library getopt must have the BSD extension static variable
1754 * "optreset", otherwise it can't be used within the shell safely.
1756 * Standard option processing (a la getopt) for builtin routines.
1757 * The only argument that is passed to nextopt is the option string;
1758 * the other arguments are unnecessary. It returns the character,
1759 * or '\0' on end of input.
1761 static int
1762 nextopt(const char *optstring)
1764 char *p;
1765 const char *q;
1766 char c;
1768 p = optptr;
1769 if (p == NULL || *p == '\0') {
1770 /* We ate entire "-param", take next one */
1771 p = *argptr;
1772 if (p == NULL)
1773 return '\0';
1774 if (*p != '-')
1775 return '\0';
1776 if (*++p == '\0') /* just "-" ? */
1777 return '\0';
1778 argptr++;
1779 if (LONE_DASH(p)) /* "--" ? */
1780 return '\0';
1781 /* p => next "-param" */
1783 /* p => some option char in the middle of a "-param" */
1784 c = *p++;
1785 for (q = optstring; *q != c;) {
1786 if (*q == '\0')
1787 ash_msg_and_raise_error("illegal option -%c", c);
1788 if (*++q == ':')
1789 q++;
1791 if (*++q == ':') {
1792 if (*p == '\0') {
1793 p = *argptr++;
1794 if (p == NULL)
1795 ash_msg_and_raise_error("no arg for -%c option", c);
1797 optionarg = p;
1798 p = NULL;
1800 optptr = p;
1801 return c;
1805 /* ============ Shell variables */
1808 * The parsefile structure pointed to by the global variable parsefile
1809 * contains information about the current file being read.
1811 struct shparam {
1812 int nparam; /* # of positional parameters (without $0) */
1813 #if ENABLE_ASH_GETOPTS
1814 int optind; /* next parameter to be processed by getopts */
1815 int optoff; /* used by getopts */
1816 #endif
1817 unsigned char malloced; /* if parameter list dynamically allocated */
1818 char **p; /* parameter list */
1822 * Free the list of positional parameters.
1824 static void
1825 freeparam(volatile struct shparam *param)
1827 if (param->malloced) {
1828 char **ap, **ap1;
1829 ap = ap1 = param->p;
1830 while (*ap)
1831 free(*ap++);
1832 free(ap1);
1836 #if ENABLE_ASH_GETOPTS
1837 static void FAST_FUNC getoptsreset(const char *value);
1838 #endif
1840 struct var {
1841 struct var *next; /* next entry in hash list */
1842 int flags; /* flags are defined above */
1843 const char *var_text; /* name=value */
1844 void (*var_func)(const char *) FAST_FUNC; /* function to be called when */
1845 /* the variable gets set/unset */
1848 struct localvar {
1849 struct localvar *next; /* next local variable in list */
1850 struct var *vp; /* the variable that was made local */
1851 int flags; /* saved flags */
1852 const char *text; /* saved text */
1855 /* flags */
1856 #define VEXPORT 0x01 /* variable is exported */
1857 #define VREADONLY 0x02 /* variable cannot be modified */
1858 #define VSTRFIXED 0x04 /* variable struct is statically allocated */
1859 #define VTEXTFIXED 0x08 /* text is statically allocated */
1860 #define VSTACK 0x10 /* text is allocated on the stack */
1861 #define VUNSET 0x20 /* the variable is not set */
1862 #define VNOFUNC 0x40 /* don't call the callback function */
1863 #define VNOSET 0x80 /* do not set variable - just readonly test */
1864 #define VNOSAVE 0x100 /* when text is on the heap before setvareq */
1865 #if ENABLE_ASH_RANDOM_SUPPORT
1866 # define VDYNAMIC 0x200 /* dynamic variable */
1867 #else
1868 # define VDYNAMIC 0
1869 #endif
1872 /* Need to be before varinit_data[] */
1873 #if ENABLE_LOCALE_SUPPORT
1874 static void FAST_FUNC
1875 change_lc_all(const char *value)
1877 if (value && *value != '\0')
1878 setlocale(LC_ALL, value);
1880 static void FAST_FUNC
1881 change_lc_ctype(const char *value)
1883 if (value && *value != '\0')
1884 setlocale(LC_CTYPE, value);
1886 #endif
1887 #if ENABLE_ASH_MAIL
1888 static void chkmail(void);
1889 static void changemail(const char *var_value) FAST_FUNC;
1890 #else
1891 # define chkmail() ((void)0)
1892 #endif
1893 static void changepath(const char *) FAST_FUNC;
1894 #if ENABLE_ASH_RANDOM_SUPPORT
1895 static void change_random(const char *) FAST_FUNC;
1896 #endif
1898 static const struct {
1899 int flags;
1900 const char *var_text;
1901 void (*var_func)(const char *) FAST_FUNC;
1902 } varinit_data[] = {
1904 * Note: VEXPORT would not work correctly here for NOFORK applets:
1905 * some environment strings may be constant.
1907 { VSTRFIXED|VTEXTFIXED , defifsvar , NULL },
1908 #if ENABLE_ASH_MAIL
1909 { VSTRFIXED|VTEXTFIXED|VUNSET, "MAIL" , changemail },
1910 { VSTRFIXED|VTEXTFIXED|VUNSET, "MAILPATH" , changemail },
1911 #endif
1912 { VSTRFIXED|VTEXTFIXED , bb_PATH_root_path, changepath },
1913 { VSTRFIXED|VTEXTFIXED , "PS1=$ " , NULL },
1914 { VSTRFIXED|VTEXTFIXED , "PS2=> " , NULL },
1915 { VSTRFIXED|VTEXTFIXED , "PS4=+ " , NULL },
1916 #if ENABLE_ASH_GETOPTS
1917 { VSTRFIXED|VTEXTFIXED , "OPTIND=1" , getoptsreset },
1918 #endif
1919 #if ENABLE_ASH_RANDOM_SUPPORT
1920 { VSTRFIXED|VTEXTFIXED|VUNSET|VDYNAMIC, "RANDOM", change_random },
1921 #endif
1922 #if ENABLE_LOCALE_SUPPORT
1923 { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_ALL" , change_lc_all },
1924 { VSTRFIXED|VTEXTFIXED|VUNSET, "LC_CTYPE" , change_lc_ctype },
1925 #endif
1926 #if ENABLE_FEATURE_EDITING_SAVEHISTORY
1927 { VSTRFIXED|VTEXTFIXED|VUNSET, "HISTFILE" , NULL },
1928 #endif
1931 struct redirtab;
1933 struct globals_var {
1934 struct shparam shellparam; /* $@ current positional parameters */
1935 struct redirtab *redirlist;
1936 int g_nullredirs;
1937 int preverrout_fd; /* save fd2 before print debug if xflag is set. */
1938 struct var *vartab[VTABSIZE];
1939 struct var varinit[ARRAY_SIZE(varinit_data)];
1941 extern struct globals_var *const ash_ptr_to_globals_var;
1942 #define G_var (*ash_ptr_to_globals_var)
1943 #define shellparam (G_var.shellparam )
1944 //#define redirlist (G_var.redirlist )
1945 #define g_nullredirs (G_var.g_nullredirs )
1946 #define preverrout_fd (G_var.preverrout_fd)
1947 #define vartab (G_var.vartab )
1948 #define varinit (G_var.varinit )
1949 #define INIT_G_var() do { \
1950 unsigned i; \
1951 (*(struct globals_var**)&ash_ptr_to_globals_var) = xzalloc(sizeof(G_var)); \
1952 barrier(); \
1953 for (i = 0; i < ARRAY_SIZE(varinit_data); i++) { \
1954 varinit[i].flags = varinit_data[i].flags; \
1955 varinit[i].var_text = varinit_data[i].var_text; \
1956 varinit[i].var_func = varinit_data[i].var_func; \
1958 } while (0)
1960 #define vifs varinit[0]
1961 #if ENABLE_ASH_MAIL
1962 # define vmail (&vifs)[1]
1963 # define vmpath (&vmail)[1]
1964 # define vpath (&vmpath)[1]
1965 #else
1966 # define vpath (&vifs)[1]
1967 #endif
1968 #define vps1 (&vpath)[1]
1969 #define vps2 (&vps1)[1]
1970 #define vps4 (&vps2)[1]
1971 #if ENABLE_ASH_GETOPTS
1972 # define voptind (&vps4)[1]
1973 # if ENABLE_ASH_RANDOM_SUPPORT
1974 # define vrandom (&voptind)[1]
1975 # endif
1976 #else
1977 # if ENABLE_ASH_RANDOM_SUPPORT
1978 # define vrandom (&vps4)[1]
1979 # endif
1980 #endif
1983 * The following macros access the values of the above variables.
1984 * They have to skip over the name. They return the null string
1985 * for unset variables.
1987 #define ifsval() (vifs.var_text + 4)
1988 #define ifsset() ((vifs.flags & VUNSET) == 0)
1989 #if ENABLE_ASH_MAIL
1990 # define mailval() (vmail.var_text + 5)
1991 # define mpathval() (vmpath.var_text + 9)
1992 # define mpathset() ((vmpath.flags & VUNSET) == 0)
1993 #endif
1994 #define pathval() (vpath.var_text + 5)
1995 #define ps1val() (vps1.var_text + 4)
1996 #define ps2val() (vps2.var_text + 4)
1997 #define ps4val() (vps4.var_text + 4)
1998 #if ENABLE_ASH_GETOPTS
1999 # define optindval() (voptind.var_text + 7)
2000 #endif
2002 #if ENABLE_ASH_GETOPTS
2003 static void FAST_FUNC
2004 getoptsreset(const char *value)
2006 shellparam.optind = number(value);
2007 shellparam.optoff = -1;
2009 #endif
2011 /* math.h has these, otherwise define our private copies */
2012 #if !ENABLE_SH_MATH_SUPPORT
2013 #define is_name(c) ((c) == '_' || isalpha((unsigned char)(c)))
2014 #define is_in_name(c) ((c) == '_' || isalnum((unsigned char)(c)))
2016 * Return the pointer to the first char which is not part of a legal variable name
2017 * (a letter or underscore followed by letters, underscores, and digits).
2019 static const char*
2020 endofname(const char *name)
2022 if (!is_name(*name))
2023 return name;
2024 while (*++name) {
2025 if (!is_in_name(*name))
2026 break;
2028 return name;
2030 #endif
2033 * Compares two strings up to the first = or '\0'. The first
2034 * string must be terminated by '='; the second may be terminated by
2035 * either '=' or '\0'.
2037 static int
2038 varcmp(const char *p, const char *q)
2040 int c, d;
2042 while ((c = *p) == (d = *q)) {
2043 if (!c || c == '=')
2044 goto out;
2045 p++;
2046 q++;
2048 if (c == '=')
2049 c = '\0';
2050 if (d == '=')
2051 d = '\0';
2052 out:
2053 return c - d;
2057 * Find the appropriate entry in the hash table from the name.
2059 static struct var **
2060 hashvar(const char *p)
2062 unsigned hashval;
2064 hashval = ((unsigned char) *p) << 4;
2065 while (*p && *p != '=')
2066 hashval += (unsigned char) *p++;
2067 return &vartab[hashval % VTABSIZE];
2070 static int
2071 vpcmp(const void *a, const void *b)
2073 return varcmp(*(const char **)a, *(const char **)b);
2077 * This routine initializes the builtin variables.
2079 static void
2080 initvar(void)
2082 struct var *vp;
2083 struct var *end;
2084 struct var **vpp;
2087 * PS1 depends on uid
2089 #if ENABLE_FEATURE_EDITING && ENABLE_FEATURE_EDITING_FANCY_PROMPT
2090 vps1.var_text = "PS1=\\w \\$ ";
2091 #else
2092 if (!geteuid())
2093 vps1.var_text = "PS1=# ";
2094 #endif
2095 vp = varinit;
2096 end = vp + ARRAY_SIZE(varinit);
2097 do {
2098 vpp = hashvar(vp->var_text);
2099 vp->next = *vpp;
2100 *vpp = vp;
2101 } while (++vp < end);
2104 static struct var **
2105 findvar(struct var **vpp, const char *name)
2107 for (; *vpp; vpp = &(*vpp)->next) {
2108 if (varcmp((*vpp)->var_text, name) == 0) {
2109 break;
2112 return vpp;
2116 * Find the value of a variable. Returns NULL if not set.
2118 static const char* FAST_FUNC
2119 lookupvar(const char *name)
2121 struct var *v;
2123 v = *findvar(hashvar(name), name);
2124 if (v) {
2125 #if ENABLE_ASH_RANDOM_SUPPORT
2127 * Dynamic variables are implemented roughly the same way they are
2128 * in bash. Namely, they're "special" so long as they aren't unset.
2129 * As soon as they're unset, they're no longer dynamic, and dynamic
2130 * lookup will no longer happen at that point. -- PFM.
2132 if (v->flags & VDYNAMIC)
2133 v->var_func(NULL);
2134 #endif
2135 if (!(v->flags & VUNSET))
2136 return var_end(v->var_text);
2138 return NULL;
2142 * Search the environment of a builtin command.
2144 static const char *
2145 bltinlookup(const char *name)
2147 struct strlist *sp;
2149 for (sp = cmdenviron; sp; sp = sp->next) {
2150 if (varcmp(sp->text, name) == 0)
2151 return var_end(sp->text);
2153 return lookupvar(name);
2157 * Same as setvar except that the variable and value are passed in
2158 * the first argument as name=value. Since the first argument will
2159 * be actually stored in the table, it should not be a string that
2160 * will go away.
2161 * Called with interrupts off.
2163 static void
2164 setvareq(char *s, int flags)
2166 struct var *vp, **vpp;
2168 vpp = hashvar(s);
2169 flags |= (VEXPORT & (((unsigned) (1 - aflag)) - 1));
2170 vp = *findvar(vpp, s);
2171 if (vp) {
2172 if ((vp->flags & (VREADONLY|VDYNAMIC)) == VREADONLY) {
2173 const char *n;
2175 if (flags & VNOSAVE)
2176 free(s);
2177 n = vp->var_text;
2178 ash_msg_and_raise_error("%.*s: is read only", strchrnul(n, '=') - n, n);
2181 if (flags & VNOSET)
2182 return;
2184 if (vp->var_func && !(flags & VNOFUNC))
2185 vp->var_func(var_end(s));
2187 if (!(vp->flags & (VTEXTFIXED|VSTACK)))
2188 free((char*)vp->var_text);
2190 flags |= vp->flags & ~(VTEXTFIXED|VSTACK|VNOSAVE|VUNSET);
2191 } else {
2192 /* variable s is not found */
2193 if (flags & VNOSET)
2194 return;
2195 vp = ckzalloc(sizeof(*vp));
2196 vp->next = *vpp;
2197 /*vp->func = NULL; - ckzalloc did it */
2198 *vpp = vp;
2200 if (!(flags & (VTEXTFIXED|VSTACK|VNOSAVE)))
2201 s = ckstrdup(s);
2202 vp->var_text = s;
2203 vp->flags = flags;
2207 * Set the value of a variable. The flags argument is ored with the
2208 * flags of the variable. If val is NULL, the variable is unset.
2210 static void
2211 setvar(const char *name, const char *val, int flags)
2213 const char *q;
2214 char *p;
2215 char *nameeq;
2216 size_t namelen;
2217 size_t vallen;
2219 q = endofname(name);
2220 p = strchrnul(q, '=');
2221 namelen = p - name;
2222 if (!namelen || p != q)
2223 ash_msg_and_raise_error("%.*s: bad variable name", namelen, name);
2224 vallen = 0;
2225 if (val == NULL) {
2226 flags |= VUNSET;
2227 } else {
2228 vallen = strlen(val);
2231 INT_OFF;
2232 nameeq = ckmalloc(namelen + vallen + 2);
2233 p = memcpy(nameeq, name, namelen) + namelen;
2234 if (val) {
2235 *p++ = '=';
2236 p = memcpy(p, val, vallen) + vallen;
2238 *p = '\0';
2239 setvareq(nameeq, flags | VNOSAVE);
2240 INT_ON;
2243 static void FAST_FUNC
2244 setvar2(const char *name, const char *val)
2246 setvar(name, val, 0);
2249 #if ENABLE_ASH_GETOPTS
2251 * Safe version of setvar, returns 1 on success 0 on failure.
2253 static int
2254 setvarsafe(const char *name, const char *val, int flags)
2256 int err;
2257 volatile int saveint;
2258 struct jmploc *volatile savehandler = exception_handler;
2259 struct jmploc jmploc;
2261 SAVE_INT(saveint);
2262 if (setjmp(jmploc.loc))
2263 err = 1;
2264 else {
2265 exception_handler = &jmploc;
2266 setvar(name, val, flags);
2267 err = 0;
2269 exception_handler = savehandler;
2270 RESTORE_INT(saveint);
2271 return err;
2273 #endif
2276 * Unset the specified variable.
2278 static int
2279 unsetvar(const char *s)
2281 struct var **vpp;
2282 struct var *vp;
2283 int retval;
2285 vpp = findvar(hashvar(s), s);
2286 vp = *vpp;
2287 retval = 2;
2288 if (vp) {
2289 int flags = vp->flags;
2291 retval = 1;
2292 if (flags & VREADONLY)
2293 goto out;
2294 #if ENABLE_ASH_RANDOM_SUPPORT
2295 vp->flags &= ~VDYNAMIC;
2296 #endif
2297 if (flags & VUNSET)
2298 goto ok;
2299 if ((flags & VSTRFIXED) == 0) {
2300 INT_OFF;
2301 if ((flags & (VTEXTFIXED|VSTACK)) == 0)
2302 free((char*)vp->var_text);
2303 *vpp = vp->next;
2304 free(vp);
2305 INT_ON;
2306 } else {
2307 setvar(s, 0, 0);
2308 vp->flags &= ~VEXPORT;
2311 retval = 0;
2313 out:
2314 return retval;
2318 * Process a linked list of variable assignments.
2320 static void
2321 listsetvar(struct strlist *list_set_var, int flags)
2323 struct strlist *lp = list_set_var;
2325 if (!lp)
2326 return;
2327 INT_OFF;
2328 do {
2329 setvareq(lp->text, flags);
2330 lp = lp->next;
2331 } while (lp);
2332 INT_ON;
2336 * Generate a list of variables satisfying the given conditions.
2338 static char **
2339 listvars(int on, int off, char ***end)
2341 struct var **vpp;
2342 struct var *vp;
2343 char **ep;
2344 int mask;
2346 STARTSTACKSTR(ep);
2347 vpp = vartab;
2348 mask = on | off;
2349 do {
2350 for (vp = *vpp; vp; vp = vp->next) {
2351 if ((vp->flags & mask) == on) {
2352 if (ep == stackstrend())
2353 ep = growstackstr();
2354 *ep++ = (char*)vp->var_text;
2357 } while (++vpp < vartab + VTABSIZE);
2358 if (ep == stackstrend())
2359 ep = growstackstr();
2360 if (end)
2361 *end = ep;
2362 *ep++ = NULL;
2363 return grabstackstr(ep);
2367 /* ============ Path search helper
2369 * The variable path (passed by reference) should be set to the start
2370 * of the path before the first call; path_advance will update
2371 * this value as it proceeds. Successive calls to path_advance will return
2372 * the possible path expansions in sequence. If an option (indicated by
2373 * a percent sign) appears in the path entry then the global variable
2374 * pathopt will be set to point to it; otherwise pathopt will be set to
2375 * NULL.
2377 static const char *pathopt; /* set by path_advance */
2379 static char *
2380 path_advance(const char **path, const char *name)
2382 const char *p;
2383 char *q;
2384 const char *start;
2385 size_t len;
2387 if (*path == NULL)
2388 return NULL;
2389 start = *path;
2390 for (p = start; *p && *p != ':' && *p != '%'; p++)
2391 continue;
2392 len = p - start + strlen(name) + 2; /* "2" is for '/' and '\0' */
2393 while (stackblocksize() < len)
2394 growstackblock();
2395 q = stackblock();
2396 if (p != start) {
2397 memcpy(q, start, p - start);
2398 q += p - start;
2399 *q++ = '/';
2401 strcpy(q, name);
2402 pathopt = NULL;
2403 if (*p == '%') {
2404 pathopt = ++p;
2405 while (*p && *p != ':')
2406 p++;
2408 if (*p == ':')
2409 *path = p + 1;
2410 else
2411 *path = NULL;
2412 return stalloc(len);
2416 /* ============ Prompt */
2418 static smallint doprompt; /* if set, prompt the user */
2419 static smallint needprompt; /* true if interactive and at start of line */
2421 #if ENABLE_FEATURE_EDITING
2422 static line_input_t *line_input_state;
2423 static const char *cmdedit_prompt;
2424 static void
2425 putprompt(const char *s)
2427 if (ENABLE_ASH_EXPAND_PRMT) {
2428 free((char*)cmdedit_prompt);
2429 cmdedit_prompt = ckstrdup(s);
2430 return;
2432 cmdedit_prompt = s;
2434 #else
2435 static void
2436 putprompt(const char *s)
2438 out2str(s);
2440 #endif
2442 #if ENABLE_ASH_EXPAND_PRMT
2443 /* expandstr() needs parsing machinery, so it is far away ahead... */
2444 static const char *expandstr(const char *ps);
2445 #else
2446 #define expandstr(s) s
2447 #endif
2449 static void
2450 setprompt_if(smallint do_set, int whichprompt)
2452 const char *prompt;
2453 IF_ASH_EXPAND_PRMT(struct stackmark smark;)
2455 if (!do_set)
2456 return;
2458 needprompt = 0;
2460 switch (whichprompt) {
2461 case 1:
2462 prompt = ps1val();
2463 break;
2464 case 2:
2465 prompt = ps2val();
2466 break;
2467 default: /* 0 */
2468 prompt = nullstr;
2470 #if ENABLE_ASH_EXPAND_PRMT
2471 setstackmark(&smark);
2472 stalloc(stackblocksize());
2473 #endif
2474 putprompt(expandstr(prompt));
2475 #if ENABLE_ASH_EXPAND_PRMT
2476 popstackmark(&smark);
2477 #endif
2481 /* ============ The cd and pwd commands */
2483 #define CD_PHYSICAL 1
2484 #define CD_PRINT 2
2486 static int
2487 cdopt(void)
2489 int flags = 0;
2490 int i, j;
2492 j = 'L';
2493 while ((i = nextopt("LP")) != '\0') {
2494 if (i != j) {
2495 flags ^= CD_PHYSICAL;
2496 j = i;
2500 return flags;
2504 * Update curdir (the name of the current directory) in response to a
2505 * cd command.
2507 static const char *
2508 updatepwd(const char *dir)
2510 char *new;
2511 char *p;
2512 char *cdcomppath;
2513 const char *lim;
2515 cdcomppath = ststrdup(dir);
2516 STARTSTACKSTR(new);
2517 if (*dir != '/') {
2518 if (curdir == nullstr)
2519 return 0;
2520 new = stack_putstr(curdir, new);
2522 new = makestrspace(strlen(dir) + 2, new);
2523 lim = (char *)stackblock() + 1;
2524 if (*dir != '/') {
2525 if (new[-1] != '/')
2526 USTPUTC('/', new);
2527 if (new > lim && *lim == '/')
2528 lim++;
2529 } else {
2530 USTPUTC('/', new);
2531 cdcomppath++;
2532 if (dir[1] == '/' && dir[2] != '/') {
2533 USTPUTC('/', new);
2534 cdcomppath++;
2535 lim++;
2538 p = strtok(cdcomppath, "/");
2539 while (p) {
2540 switch (*p) {
2541 case '.':
2542 if (p[1] == '.' && p[2] == '\0') {
2543 while (new > lim) {
2544 STUNPUTC(new);
2545 if (new[-1] == '/')
2546 break;
2548 break;
2550 if (p[1] == '\0')
2551 break;
2552 /* fall through */
2553 default:
2554 new = stack_putstr(p, new);
2555 USTPUTC('/', new);
2557 p = strtok(0, "/");
2559 if (new > lim)
2560 STUNPUTC(new);
2561 *new = 0;
2562 return stackblock();
2566 * Find out what the current directory is. If we already know the current
2567 * directory, this routine returns immediately.
2569 static char *
2570 getpwd(void)
2572 char *dir = getcwd(NULL, 0); /* huh, using glibc extension? */
2573 return dir ? dir : nullstr;
2576 static void
2577 setpwd(const char *val, int setold)
2579 char *oldcur, *dir;
2581 oldcur = dir = curdir;
2583 if (setold) {
2584 setvar("OLDPWD", oldcur, VEXPORT);
2586 INT_OFF;
2587 if (physdir != nullstr) {
2588 if (physdir != oldcur)
2589 free(physdir);
2590 physdir = nullstr;
2592 if (oldcur == val || !val) {
2593 char *s = getpwd();
2594 physdir = s;
2595 if (!val)
2596 dir = s;
2597 } else
2598 dir = ckstrdup(val);
2599 if (oldcur != dir && oldcur != nullstr) {
2600 free(oldcur);
2602 curdir = dir;
2603 INT_ON;
2604 setvar("PWD", dir, VEXPORT);
2607 static void hashcd(void);
2610 * Actually do the chdir. We also call hashcd to let the routines in exec.c
2611 * know that the current directory has changed.
2613 static int
2614 docd(const char *dest, int flags)
2616 const char *dir = NULL;
2617 int err;
2619 TRACE(("docd(\"%s\", %d) called\n", dest, flags));
2621 INT_OFF;
2622 if (!(flags & CD_PHYSICAL)) {
2623 dir = updatepwd(dest);
2624 if (dir)
2625 dest = dir;
2627 err = chdir(dest);
2628 if (err)
2629 goto out;
2630 setpwd(dir, 1);
2631 hashcd();
2632 out:
2633 INT_ON;
2634 return err;
2637 static int FAST_FUNC
2638 cdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2640 const char *dest;
2641 const char *path;
2642 const char *p;
2643 char c;
2644 struct stat statb;
2645 int flags;
2647 flags = cdopt();
2648 dest = *argptr;
2649 if (!dest)
2650 dest = bltinlookup("HOME");
2651 else if (LONE_DASH(dest)) {
2652 dest = bltinlookup("OLDPWD");
2653 flags |= CD_PRINT;
2655 if (!dest)
2656 dest = nullstr;
2657 if (*dest == '/')
2658 goto step7;
2659 if (*dest == '.') {
2660 c = dest[1];
2661 dotdot:
2662 switch (c) {
2663 case '\0':
2664 case '/':
2665 goto step6;
2666 case '.':
2667 c = dest[2];
2668 if (c != '.')
2669 goto dotdot;
2672 if (!*dest)
2673 dest = ".";
2674 path = bltinlookup("CDPATH");
2675 if (!path) {
2676 step6:
2677 step7:
2678 p = dest;
2679 goto docd;
2681 do {
2682 c = *path;
2683 p = path_advance(&path, dest);
2684 if (stat(p, &statb) >= 0 && S_ISDIR(statb.st_mode)) {
2685 if (c && c != ':')
2686 flags |= CD_PRINT;
2687 docd:
2688 if (!docd(p, flags))
2689 goto out;
2690 break;
2692 } while (path);
2693 ash_msg_and_raise_error("can't cd to %s", dest);
2694 /* NOTREACHED */
2695 out:
2696 if (flags & CD_PRINT)
2697 out1fmt("%s\n", curdir);
2698 return 0;
2701 static int FAST_FUNC
2702 pwdcmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
2704 int flags;
2705 const char *dir = curdir;
2707 flags = cdopt();
2708 if (flags) {
2709 if (physdir == nullstr)
2710 setpwd(dir, 0);
2711 dir = physdir;
2713 out1fmt("%s\n", dir);
2714 return 0;
2718 /* ============ ... */
2721 #define IBUFSIZ (ENABLE_FEATURE_EDITING ? CONFIG_FEATURE_EDITING_MAX_LEN : 1024)
2723 /* Syntax classes */
2724 #define CWORD 0 /* character is nothing special */
2725 #define CNL 1 /* newline character */
2726 #define CBACK 2 /* a backslash character */
2727 #define CSQUOTE 3 /* single quote */
2728 #define CDQUOTE 4 /* double quote */
2729 #define CENDQUOTE 5 /* a terminating quote */
2730 #define CBQUOTE 6 /* backwards single quote */
2731 #define CVAR 7 /* a dollar sign */
2732 #define CENDVAR 8 /* a '}' character */
2733 #define CLP 9 /* a left paren in arithmetic */
2734 #define CRP 10 /* a right paren in arithmetic */
2735 #define CENDFILE 11 /* end of file */
2736 #define CCTL 12 /* like CWORD, except it must be escaped */
2737 #define CSPCL 13 /* these terminate a word */
2738 #define CIGN 14 /* character should be ignored */
2740 #define PEOF 256
2741 #if ENABLE_ASH_ALIAS
2742 # define PEOA 257
2743 #endif
2745 #define USE_SIT_FUNCTION ENABLE_ASH_OPTIMIZE_FOR_SIZE
2747 #if ENABLE_SH_MATH_SUPPORT
2748 # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8) | (d << 12))
2749 #else
2750 # define SIT_ITEM(a,b,c,d) (a | (b << 4) | (c << 8))
2751 #endif
2752 static const uint16_t S_I_T[] = {
2753 #if ENABLE_ASH_ALIAS
2754 SIT_ITEM(CSPCL , CIGN , CIGN , CIGN ), /* 0, PEOA */
2755 #endif
2756 SIT_ITEM(CSPCL , CWORD , CWORD, CWORD ), /* 1, ' ' */
2757 SIT_ITEM(CNL , CNL , CNL , CNL ), /* 2, \n */
2758 SIT_ITEM(CWORD , CCTL , CCTL , CWORD ), /* 3, !*-/:=?[]~ */
2759 SIT_ITEM(CDQUOTE , CENDQUOTE, CWORD, CWORD ), /* 4, '"' */
2760 SIT_ITEM(CVAR , CVAR , CWORD, CVAR ), /* 5, $ */
2761 SIT_ITEM(CSQUOTE , CWORD , CENDQUOTE, CWORD), /* 6, "'" */
2762 SIT_ITEM(CSPCL , CWORD , CWORD, CLP ), /* 7, ( */
2763 SIT_ITEM(CSPCL , CWORD , CWORD, CRP ), /* 8, ) */
2764 SIT_ITEM(CBACK , CBACK , CCTL , CBACK ), /* 9, \ */
2765 SIT_ITEM(CBQUOTE , CBQUOTE , CWORD, CBQUOTE), /* 10, ` */
2766 SIT_ITEM(CENDVAR , CENDVAR , CWORD, CENDVAR), /* 11, } */
2767 #if !USE_SIT_FUNCTION
2768 SIT_ITEM(CENDFILE, CENDFILE , CENDFILE, CENDFILE),/* 12, PEOF */
2769 SIT_ITEM(CWORD , CWORD , CWORD, CWORD ), /* 13, 0-9A-Za-z */
2770 SIT_ITEM(CCTL , CCTL , CCTL , CCTL ) /* 14, CTLESC ... */
2771 #endif
2772 #undef SIT_ITEM
2774 /* Constants below must match table above */
2775 enum {
2776 #if ENABLE_ASH_ALIAS
2777 CSPCL_CIGN_CIGN_CIGN , /* 0 */
2778 #endif
2779 CSPCL_CWORD_CWORD_CWORD , /* 1 */
2780 CNL_CNL_CNL_CNL , /* 2 */
2781 CWORD_CCTL_CCTL_CWORD , /* 3 */
2782 CDQUOTE_CENDQUOTE_CWORD_CWORD , /* 4 */
2783 CVAR_CVAR_CWORD_CVAR , /* 5 */
2784 CSQUOTE_CWORD_CENDQUOTE_CWORD , /* 6 */
2785 CSPCL_CWORD_CWORD_CLP , /* 7 */
2786 CSPCL_CWORD_CWORD_CRP , /* 8 */
2787 CBACK_CBACK_CCTL_CBACK , /* 9 */
2788 CBQUOTE_CBQUOTE_CWORD_CBQUOTE , /* 10 */
2789 CENDVAR_CENDVAR_CWORD_CENDVAR , /* 11 */
2790 CENDFILE_CENDFILE_CENDFILE_CENDFILE, /* 12 */
2791 CWORD_CWORD_CWORD_CWORD , /* 13 */
2792 CCTL_CCTL_CCTL_CCTL , /* 14 */
2795 /* c in SIT(c, syntax) must be an *unsigned char* or PEOA or PEOF,
2796 * caller must ensure proper cast on it if c is *char_ptr!
2798 /* Values for syntax param */
2799 #define BASESYNTAX 0 /* not in quotes */
2800 #define DQSYNTAX 1 /* in double quotes */
2801 #define SQSYNTAX 2 /* in single quotes */
2802 #define ARISYNTAX 3 /* in arithmetic */
2803 #define PSSYNTAX 4 /* prompt. never passed to SIT() */
2805 #if USE_SIT_FUNCTION
2807 static int
2808 SIT(int c, int syntax)
2810 static const char spec_symbls[] ALIGN1 = "\t\n !\"$&'()*-/:;<=>?[\\]`|}~";
2811 # if ENABLE_ASH_ALIAS
2812 static const uint8_t syntax_index_table[] ALIGN1 = {
2813 1, 2, 1, 3, 4, 5, 1, 6, /* "\t\n !\"$&'" */
2814 7, 8, 3, 3, 3, 3, 1, 1, /* "()*-/:;<" */
2815 3, 1, 3, 3, 9, 3, 10, 1, /* "=>?[\\]`|" */
2816 11, 3 /* "}~" */
2818 # else
2819 static const uint8_t syntax_index_table[] ALIGN1 = {
2820 0, 1, 0, 2, 3, 4, 0, 5, /* "\t\n !\"$&'" */
2821 6, 7, 2, 2, 2, 2, 0, 0, /* "()*-/:;<" */
2822 2, 0, 2, 2, 8, 2, 9, 0, /* "=>?[\\]`|" */
2823 10, 2 /* "}~" */
2825 # endif
2826 const char *s;
2827 int indx;
2829 if (c == PEOF)
2830 return CENDFILE;
2831 # if ENABLE_ASH_ALIAS
2832 if (c == PEOA)
2833 indx = 0;
2834 else
2835 # endif
2837 /* Cast is purely for paranoia here,
2838 * just in case someone passed signed char to us */
2839 if ((unsigned char)c >= CTL_FIRST
2840 && (unsigned char)c <= CTL_LAST
2842 return CCTL;
2844 s = strchrnul(spec_symbls, c);
2845 if (*s == '\0')
2846 return CWORD;
2847 indx = syntax_index_table[s - spec_symbls];
2849 return (S_I_T[indx] >> (syntax*4)) & 0xf;
2852 #else /* !USE_SIT_FUNCTION */
2854 static const uint8_t syntax_index_table[] = {
2855 /* BASESYNTAX_DQSYNTAX_SQSYNTAX_ARISYNTAX */
2856 /* 0 */ CWORD_CWORD_CWORD_CWORD,
2857 /* 1 */ CWORD_CWORD_CWORD_CWORD,
2858 /* 2 */ CWORD_CWORD_CWORD_CWORD,
2859 /* 3 */ CWORD_CWORD_CWORD_CWORD,
2860 /* 4 */ CWORD_CWORD_CWORD_CWORD,
2861 /* 5 */ CWORD_CWORD_CWORD_CWORD,
2862 /* 6 */ CWORD_CWORD_CWORD_CWORD,
2863 /* 7 */ CWORD_CWORD_CWORD_CWORD,
2864 /* 8 */ CWORD_CWORD_CWORD_CWORD,
2865 /* 9 "\t" */ CSPCL_CWORD_CWORD_CWORD,
2866 /* 10 "\n" */ CNL_CNL_CNL_CNL,
2867 /* 11 */ CWORD_CWORD_CWORD_CWORD,
2868 /* 12 */ CWORD_CWORD_CWORD_CWORD,
2869 /* 13 */ CWORD_CWORD_CWORD_CWORD,
2870 /* 14 */ CWORD_CWORD_CWORD_CWORD,
2871 /* 15 */ CWORD_CWORD_CWORD_CWORD,
2872 /* 16 */ CWORD_CWORD_CWORD_CWORD,
2873 /* 17 */ CWORD_CWORD_CWORD_CWORD,
2874 /* 18 */ CWORD_CWORD_CWORD_CWORD,
2875 /* 19 */ CWORD_CWORD_CWORD_CWORD,
2876 /* 20 */ CWORD_CWORD_CWORD_CWORD,
2877 /* 21 */ CWORD_CWORD_CWORD_CWORD,
2878 /* 22 */ CWORD_CWORD_CWORD_CWORD,
2879 /* 23 */ CWORD_CWORD_CWORD_CWORD,
2880 /* 24 */ CWORD_CWORD_CWORD_CWORD,
2881 /* 25 */ CWORD_CWORD_CWORD_CWORD,
2882 /* 26 */ CWORD_CWORD_CWORD_CWORD,
2883 /* 27 */ CWORD_CWORD_CWORD_CWORD,
2884 /* 28 */ CWORD_CWORD_CWORD_CWORD,
2885 /* 29 */ CWORD_CWORD_CWORD_CWORD,
2886 /* 30 */ CWORD_CWORD_CWORD_CWORD,
2887 /* 31 */ CWORD_CWORD_CWORD_CWORD,
2888 /* 32 " " */ CSPCL_CWORD_CWORD_CWORD,
2889 /* 33 "!" */ CWORD_CCTL_CCTL_CWORD,
2890 /* 34 """ */ CDQUOTE_CENDQUOTE_CWORD_CWORD,
2891 /* 35 "#" */ CWORD_CWORD_CWORD_CWORD,
2892 /* 36 "$" */ CVAR_CVAR_CWORD_CVAR,
2893 /* 37 "%" */ CWORD_CWORD_CWORD_CWORD,
2894 /* 38 "&" */ CSPCL_CWORD_CWORD_CWORD,
2895 /* 39 "'" */ CSQUOTE_CWORD_CENDQUOTE_CWORD,
2896 /* 40 "(" */ CSPCL_CWORD_CWORD_CLP,
2897 /* 41 ")" */ CSPCL_CWORD_CWORD_CRP,
2898 /* 42 "*" */ CWORD_CCTL_CCTL_CWORD,
2899 /* 43 "+" */ CWORD_CWORD_CWORD_CWORD,
2900 /* 44 "," */ CWORD_CWORD_CWORD_CWORD,
2901 /* 45 "-" */ CWORD_CCTL_CCTL_CWORD,
2902 /* 46 "." */ CWORD_CWORD_CWORD_CWORD,
2903 /* 47 "/" */ CWORD_CCTL_CCTL_CWORD,
2904 /* 48 "0" */ CWORD_CWORD_CWORD_CWORD,
2905 /* 49 "1" */ CWORD_CWORD_CWORD_CWORD,
2906 /* 50 "2" */ CWORD_CWORD_CWORD_CWORD,
2907 /* 51 "3" */ CWORD_CWORD_CWORD_CWORD,
2908 /* 52 "4" */ CWORD_CWORD_CWORD_CWORD,
2909 /* 53 "5" */ CWORD_CWORD_CWORD_CWORD,
2910 /* 54 "6" */ CWORD_CWORD_CWORD_CWORD,
2911 /* 55 "7" */ CWORD_CWORD_CWORD_CWORD,
2912 /* 56 "8" */ CWORD_CWORD_CWORD_CWORD,
2913 /* 57 "9" */ CWORD_CWORD_CWORD_CWORD,
2914 /* 58 ":" */ CWORD_CCTL_CCTL_CWORD,
2915 /* 59 ";" */ CSPCL_CWORD_CWORD_CWORD,
2916 /* 60 "<" */ CSPCL_CWORD_CWORD_CWORD,
2917 /* 61 "=" */ CWORD_CCTL_CCTL_CWORD,
2918 /* 62 ">" */ CSPCL_CWORD_CWORD_CWORD,
2919 /* 63 "?" */ CWORD_CCTL_CCTL_CWORD,
2920 /* 64 "@" */ CWORD_CWORD_CWORD_CWORD,
2921 /* 65 "A" */ CWORD_CWORD_CWORD_CWORD,
2922 /* 66 "B" */ CWORD_CWORD_CWORD_CWORD,
2923 /* 67 "C" */ CWORD_CWORD_CWORD_CWORD,
2924 /* 68 "D" */ CWORD_CWORD_CWORD_CWORD,
2925 /* 69 "E" */ CWORD_CWORD_CWORD_CWORD,
2926 /* 70 "F" */ CWORD_CWORD_CWORD_CWORD,
2927 /* 71 "G" */ CWORD_CWORD_CWORD_CWORD,
2928 /* 72 "H" */ CWORD_CWORD_CWORD_CWORD,
2929 /* 73 "I" */ CWORD_CWORD_CWORD_CWORD,
2930 /* 74 "J" */ CWORD_CWORD_CWORD_CWORD,
2931 /* 75 "K" */ CWORD_CWORD_CWORD_CWORD,
2932 /* 76 "L" */ CWORD_CWORD_CWORD_CWORD,
2933 /* 77 "M" */ CWORD_CWORD_CWORD_CWORD,
2934 /* 78 "N" */ CWORD_CWORD_CWORD_CWORD,
2935 /* 79 "O" */ CWORD_CWORD_CWORD_CWORD,
2936 /* 80 "P" */ CWORD_CWORD_CWORD_CWORD,
2937 /* 81 "Q" */ CWORD_CWORD_CWORD_CWORD,
2938 /* 82 "R" */ CWORD_CWORD_CWORD_CWORD,
2939 /* 83 "S" */ CWORD_CWORD_CWORD_CWORD,
2940 /* 84 "T" */ CWORD_CWORD_CWORD_CWORD,
2941 /* 85 "U" */ CWORD_CWORD_CWORD_CWORD,
2942 /* 86 "V" */ CWORD_CWORD_CWORD_CWORD,
2943 /* 87 "W" */ CWORD_CWORD_CWORD_CWORD,
2944 /* 88 "X" */ CWORD_CWORD_CWORD_CWORD,
2945 /* 89 "Y" */ CWORD_CWORD_CWORD_CWORD,
2946 /* 90 "Z" */ CWORD_CWORD_CWORD_CWORD,
2947 /* 91 "[" */ CWORD_CCTL_CCTL_CWORD,
2948 /* 92 "\" */ CBACK_CBACK_CCTL_CBACK,
2949 /* 93 "]" */ CWORD_CCTL_CCTL_CWORD,
2950 /* 94 "^" */ CWORD_CWORD_CWORD_CWORD,
2951 /* 95 "_" */ CWORD_CWORD_CWORD_CWORD,
2952 /* 96 "`" */ CBQUOTE_CBQUOTE_CWORD_CBQUOTE,
2953 /* 97 "a" */ CWORD_CWORD_CWORD_CWORD,
2954 /* 98 "b" */ CWORD_CWORD_CWORD_CWORD,
2955 /* 99 "c" */ CWORD_CWORD_CWORD_CWORD,
2956 /* 100 "d" */ CWORD_CWORD_CWORD_CWORD,
2957 /* 101 "e" */ CWORD_CWORD_CWORD_CWORD,
2958 /* 102 "f" */ CWORD_CWORD_CWORD_CWORD,
2959 /* 103 "g" */ CWORD_CWORD_CWORD_CWORD,
2960 /* 104 "h" */ CWORD_CWORD_CWORD_CWORD,
2961 /* 105 "i" */ CWORD_CWORD_CWORD_CWORD,
2962 /* 106 "j" */ CWORD_CWORD_CWORD_CWORD,
2963 /* 107 "k" */ CWORD_CWORD_CWORD_CWORD,
2964 /* 108 "l" */ CWORD_CWORD_CWORD_CWORD,
2965 /* 109 "m" */ CWORD_CWORD_CWORD_CWORD,
2966 /* 110 "n" */ CWORD_CWORD_CWORD_CWORD,
2967 /* 111 "o" */ CWORD_CWORD_CWORD_CWORD,
2968 /* 112 "p" */ CWORD_CWORD_CWORD_CWORD,
2969 /* 113 "q" */ CWORD_CWORD_CWORD_CWORD,
2970 /* 114 "r" */ CWORD_CWORD_CWORD_CWORD,
2971 /* 115 "s" */ CWORD_CWORD_CWORD_CWORD,
2972 /* 116 "t" */ CWORD_CWORD_CWORD_CWORD,
2973 /* 117 "u" */ CWORD_CWORD_CWORD_CWORD,
2974 /* 118 "v" */ CWORD_CWORD_CWORD_CWORD,
2975 /* 119 "w" */ CWORD_CWORD_CWORD_CWORD,
2976 /* 120 "x" */ CWORD_CWORD_CWORD_CWORD,
2977 /* 121 "y" */ CWORD_CWORD_CWORD_CWORD,
2978 /* 122 "z" */ CWORD_CWORD_CWORD_CWORD,
2979 /* 123 "{" */ CWORD_CWORD_CWORD_CWORD,
2980 /* 124 "|" */ CSPCL_CWORD_CWORD_CWORD,
2981 /* 125 "}" */ CENDVAR_CENDVAR_CWORD_CENDVAR,
2982 /* 126 "~" */ CWORD_CCTL_CCTL_CWORD,
2983 /* 127 del */ CWORD_CWORD_CWORD_CWORD,
2984 /* 128 0x80 */ CWORD_CWORD_CWORD_CWORD,
2985 /* 129 CTLESC */ CCTL_CCTL_CCTL_CCTL,
2986 /* 130 CTLVAR */ CCTL_CCTL_CCTL_CCTL,
2987 /* 131 CTLENDVAR */ CCTL_CCTL_CCTL_CCTL,
2988 /* 132 CTLBACKQ */ CCTL_CCTL_CCTL_CCTL,
2989 /* 133 CTLQUOTE */ CCTL_CCTL_CCTL_CCTL,
2990 /* 134 CTLARI */ CCTL_CCTL_CCTL_CCTL,
2991 /* 135 CTLENDARI */ CCTL_CCTL_CCTL_CCTL,
2992 /* 136 CTLQUOTEMARK */ CCTL_CCTL_CCTL_CCTL,
2993 /* 137 */ CWORD_CWORD_CWORD_CWORD,
2994 /* 138 */ CWORD_CWORD_CWORD_CWORD,
2995 /* 139 */ CWORD_CWORD_CWORD_CWORD,
2996 /* 140 */ CWORD_CWORD_CWORD_CWORD,
2997 /* 141 */ CWORD_CWORD_CWORD_CWORD,
2998 /* 142 */ CWORD_CWORD_CWORD_CWORD,
2999 /* 143 */ CWORD_CWORD_CWORD_CWORD,
3000 /* 144 */ CWORD_CWORD_CWORD_CWORD,
3001 /* 145 */ CWORD_CWORD_CWORD_CWORD,
3002 /* 146 */ CWORD_CWORD_CWORD_CWORD,
3003 /* 147 */ CWORD_CWORD_CWORD_CWORD,
3004 /* 148 */ CWORD_CWORD_CWORD_CWORD,
3005 /* 149 */ CWORD_CWORD_CWORD_CWORD,
3006 /* 150 */ CWORD_CWORD_CWORD_CWORD,
3007 /* 151 */ CWORD_CWORD_CWORD_CWORD,
3008 /* 152 */ CWORD_CWORD_CWORD_CWORD,
3009 /* 153 */ CWORD_CWORD_CWORD_CWORD,
3010 /* 154 */ CWORD_CWORD_CWORD_CWORD,
3011 /* 155 */ CWORD_CWORD_CWORD_CWORD,
3012 /* 156 */ CWORD_CWORD_CWORD_CWORD,
3013 /* 157 */ CWORD_CWORD_CWORD_CWORD,
3014 /* 158 */ CWORD_CWORD_CWORD_CWORD,
3015 /* 159 */ CWORD_CWORD_CWORD_CWORD,
3016 /* 160 */ CWORD_CWORD_CWORD_CWORD,
3017 /* 161 */ CWORD_CWORD_CWORD_CWORD,
3018 /* 162 */ CWORD_CWORD_CWORD_CWORD,
3019 /* 163 */ CWORD_CWORD_CWORD_CWORD,
3020 /* 164 */ CWORD_CWORD_CWORD_CWORD,
3021 /* 165 */ CWORD_CWORD_CWORD_CWORD,
3022 /* 166 */ CWORD_CWORD_CWORD_CWORD,
3023 /* 167 */ CWORD_CWORD_CWORD_CWORD,
3024 /* 168 */ CWORD_CWORD_CWORD_CWORD,
3025 /* 169 */ CWORD_CWORD_CWORD_CWORD,
3026 /* 170 */ CWORD_CWORD_CWORD_CWORD,
3027 /* 171 */ CWORD_CWORD_CWORD_CWORD,
3028 /* 172 */ CWORD_CWORD_CWORD_CWORD,
3029 /* 173 */ CWORD_CWORD_CWORD_CWORD,
3030 /* 174 */ CWORD_CWORD_CWORD_CWORD,
3031 /* 175 */ CWORD_CWORD_CWORD_CWORD,
3032 /* 176 */ CWORD_CWORD_CWORD_CWORD,
3033 /* 177 */ CWORD_CWORD_CWORD_CWORD,
3034 /* 178 */ CWORD_CWORD_CWORD_CWORD,
3035 /* 179 */ CWORD_CWORD_CWORD_CWORD,
3036 /* 180 */ CWORD_CWORD_CWORD_CWORD,
3037 /* 181 */ CWORD_CWORD_CWORD_CWORD,
3038 /* 182 */ CWORD_CWORD_CWORD_CWORD,
3039 /* 183 */ CWORD_CWORD_CWORD_CWORD,
3040 /* 184 */ CWORD_CWORD_CWORD_CWORD,
3041 /* 185 */ CWORD_CWORD_CWORD_CWORD,
3042 /* 186 */ CWORD_CWORD_CWORD_CWORD,
3043 /* 187 */ CWORD_CWORD_CWORD_CWORD,
3044 /* 188 */ CWORD_CWORD_CWORD_CWORD,
3045 /* 189 */ CWORD_CWORD_CWORD_CWORD,
3046 /* 190 */ CWORD_CWORD_CWORD_CWORD,
3047 /* 191 */ CWORD_CWORD_CWORD_CWORD,
3048 /* 192 */ CWORD_CWORD_CWORD_CWORD,
3049 /* 193 */ CWORD_CWORD_CWORD_CWORD,
3050 /* 194 */ CWORD_CWORD_CWORD_CWORD,
3051 /* 195 */ CWORD_CWORD_CWORD_CWORD,
3052 /* 196 */ CWORD_CWORD_CWORD_CWORD,
3053 /* 197 */ CWORD_CWORD_CWORD_CWORD,
3054 /* 198 */ CWORD_CWORD_CWORD_CWORD,
3055 /* 199 */ CWORD_CWORD_CWORD_CWORD,
3056 /* 200 */ CWORD_CWORD_CWORD_CWORD,
3057 /* 201 */ CWORD_CWORD_CWORD_CWORD,
3058 /* 202 */ CWORD_CWORD_CWORD_CWORD,
3059 /* 203 */ CWORD_CWORD_CWORD_CWORD,
3060 /* 204 */ CWORD_CWORD_CWORD_CWORD,
3061 /* 205 */ CWORD_CWORD_CWORD_CWORD,
3062 /* 206 */ CWORD_CWORD_CWORD_CWORD,
3063 /* 207 */ CWORD_CWORD_CWORD_CWORD,
3064 /* 208 */ CWORD_CWORD_CWORD_CWORD,
3065 /* 209 */ CWORD_CWORD_CWORD_CWORD,
3066 /* 210 */ CWORD_CWORD_CWORD_CWORD,
3067 /* 211 */ CWORD_CWORD_CWORD_CWORD,
3068 /* 212 */ CWORD_CWORD_CWORD_CWORD,
3069 /* 213 */ CWORD_CWORD_CWORD_CWORD,
3070 /* 214 */ CWORD_CWORD_CWORD_CWORD,
3071 /* 215 */ CWORD_CWORD_CWORD_CWORD,
3072 /* 216 */ CWORD_CWORD_CWORD_CWORD,
3073 /* 217 */ CWORD_CWORD_CWORD_CWORD,
3074 /* 218 */ CWORD_CWORD_CWORD_CWORD,
3075 /* 219 */ CWORD_CWORD_CWORD_CWORD,
3076 /* 220 */ CWORD_CWORD_CWORD_CWORD,
3077 /* 221 */ CWORD_CWORD_CWORD_CWORD,
3078 /* 222 */ CWORD_CWORD_CWORD_CWORD,
3079 /* 223 */ CWORD_CWORD_CWORD_CWORD,
3080 /* 224 */ CWORD_CWORD_CWORD_CWORD,
3081 /* 225 */ CWORD_CWORD_CWORD_CWORD,
3082 /* 226 */ CWORD_CWORD_CWORD_CWORD,
3083 /* 227 */ CWORD_CWORD_CWORD_CWORD,
3084 /* 228 */ CWORD_CWORD_CWORD_CWORD,
3085 /* 229 */ CWORD_CWORD_CWORD_CWORD,
3086 /* 230 */ CWORD_CWORD_CWORD_CWORD,
3087 /* 231 */ CWORD_CWORD_CWORD_CWORD,
3088 /* 232 */ CWORD_CWORD_CWORD_CWORD,
3089 /* 233 */ CWORD_CWORD_CWORD_CWORD,
3090 /* 234 */ CWORD_CWORD_CWORD_CWORD,
3091 /* 235 */ CWORD_CWORD_CWORD_CWORD,
3092 /* 236 */ CWORD_CWORD_CWORD_CWORD,
3093 /* 237 */ CWORD_CWORD_CWORD_CWORD,
3094 /* 238 */ CWORD_CWORD_CWORD_CWORD,
3095 /* 239 */ CWORD_CWORD_CWORD_CWORD,
3096 /* 230 */ CWORD_CWORD_CWORD_CWORD,
3097 /* 241 */ CWORD_CWORD_CWORD_CWORD,
3098 /* 242 */ CWORD_CWORD_CWORD_CWORD,
3099 /* 243 */ CWORD_CWORD_CWORD_CWORD,
3100 /* 244 */ CWORD_CWORD_CWORD_CWORD,
3101 /* 245 */ CWORD_CWORD_CWORD_CWORD,
3102 /* 246 */ CWORD_CWORD_CWORD_CWORD,
3103 /* 247 */ CWORD_CWORD_CWORD_CWORD,
3104 /* 248 */ CWORD_CWORD_CWORD_CWORD,
3105 /* 249 */ CWORD_CWORD_CWORD_CWORD,
3106 /* 250 */ CWORD_CWORD_CWORD_CWORD,
3107 /* 251 */ CWORD_CWORD_CWORD_CWORD,
3108 /* 252 */ CWORD_CWORD_CWORD_CWORD,
3109 /* 253 */ CWORD_CWORD_CWORD_CWORD,
3110 /* 254 */ CWORD_CWORD_CWORD_CWORD,
3111 /* 255 */ CWORD_CWORD_CWORD_CWORD,
3112 /* PEOF */ CENDFILE_CENDFILE_CENDFILE_CENDFILE,
3113 # if ENABLE_ASH_ALIAS
3114 /* PEOA */ CSPCL_CIGN_CIGN_CIGN,
3115 # endif
3118 # define SIT(c, syntax) ((S_I_T[syntax_index_table[c]] >> ((syntax)*4)) & 0xf)
3120 #endif /* !USE_SIT_FUNCTION */
3123 /* ============ Alias handling */
3125 #if ENABLE_ASH_ALIAS
3127 #define ALIASINUSE 1
3128 #define ALIASDEAD 2
3130 struct alias {
3131 struct alias *next;
3132 char *name;
3133 char *val;
3134 int flag;
3138 static struct alias **atab; // [ATABSIZE];
3139 #define INIT_G_alias() do { \
3140 atab = xzalloc(ATABSIZE * sizeof(atab[0])); \
3141 } while (0)
3144 static struct alias **
3145 __lookupalias(const char *name) {
3146 unsigned int hashval;
3147 struct alias **app;
3148 const char *p;
3149 unsigned int ch;
3151 p = name;
3153 ch = (unsigned char)*p;
3154 hashval = ch << 4;
3155 while (ch) {
3156 hashval += ch;
3157 ch = (unsigned char)*++p;
3159 app = &atab[hashval % ATABSIZE];
3161 for (; *app; app = &(*app)->next) {
3162 if (strcmp(name, (*app)->name) == 0) {
3163 break;
3167 return app;
3170 static struct alias *
3171 lookupalias(const char *name, int check)
3173 struct alias *ap = *__lookupalias(name);
3175 if (check && ap && (ap->flag & ALIASINUSE))
3176 return NULL;
3177 return ap;
3180 static struct alias *
3181 freealias(struct alias *ap)
3183 struct alias *next;
3185 if (ap->flag & ALIASINUSE) {
3186 ap->flag |= ALIASDEAD;
3187 return ap;
3190 next = ap->next;
3191 free(ap->name);
3192 free(ap->val);
3193 free(ap);
3194 return next;
3197 static void
3198 setalias(const char *name, const char *val)
3200 struct alias *ap, **app;
3202 app = __lookupalias(name);
3203 ap = *app;
3204 INT_OFF;
3205 if (ap) {
3206 if (!(ap->flag & ALIASINUSE)) {
3207 free(ap->val);
3209 ap->val = ckstrdup(val);
3210 ap->flag &= ~ALIASDEAD;
3211 } else {
3212 /* not found */
3213 ap = ckzalloc(sizeof(struct alias));
3214 ap->name = ckstrdup(name);
3215 ap->val = ckstrdup(val);
3216 /*ap->flag = 0; - ckzalloc did it */
3217 /*ap->next = NULL;*/
3218 *app = ap;
3220 INT_ON;
3223 static int
3224 unalias(const char *name)
3226 struct alias **app;
3228 app = __lookupalias(name);
3230 if (*app) {
3231 INT_OFF;
3232 *app = freealias(*app);
3233 INT_ON;
3234 return 0;
3237 return 1;
3240 static void
3241 rmaliases(void)
3243 struct alias *ap, **app;
3244 int i;
3246 INT_OFF;
3247 for (i = 0; i < ATABSIZE; i++) {
3248 app = &atab[i];
3249 for (ap = *app; ap; ap = *app) {
3250 *app = freealias(*app);
3251 if (ap == *app) {
3252 app = &ap->next;
3256 INT_ON;
3259 static void
3260 printalias(const struct alias *ap)
3262 out1fmt("%s=%s\n", ap->name, single_quote(ap->val));
3266 * TODO - sort output
3268 static int FAST_FUNC
3269 aliascmd(int argc UNUSED_PARAM, char **argv)
3271 char *n, *v;
3272 int ret = 0;
3273 struct alias *ap;
3275 if (!argv[1]) {
3276 int i;
3278 for (i = 0; i < ATABSIZE; i++) {
3279 for (ap = atab[i]; ap; ap = ap->next) {
3280 printalias(ap);
3283 return 0;
3285 while ((n = *++argv) != NULL) {
3286 v = strchr(n+1, '=');
3287 if (v == NULL) { /* n+1: funny ksh stuff */
3288 ap = *__lookupalias(n);
3289 if (ap == NULL) {
3290 fprintf(stderr, "%s: %s not found\n", "alias", n);
3291 ret = 1;
3292 } else
3293 printalias(ap);
3294 } else {
3295 *v++ = '\0';
3296 setalias(n, v);
3300 return ret;
3303 static int FAST_FUNC
3304 unaliascmd(int argc UNUSED_PARAM, char **argv UNUSED_PARAM)
3306 int i;
3308 while ((i = nextopt("a")) != '\0') {
3309 if (i == 'a') {
3310 rmaliases();
3311 return 0;
3314 for (i = 0; *argptr; argptr++) {
3315 if (unalias(*argptr)) {
3316 fprintf(stderr, "%s: %s not found\n", "unalias", *argptr);
3317 i = 1;
3321 return i;
3324 #endif /* ASH_ALIAS */
3327 /* ============ jobs.c */
3329 /* Mode argument to forkshell. Don't change FORK_FG or FORK_BG. */
3330 #define FORK_FG 0
3331 #define FORK_BG 1
3332 #define FORK_NOJOB 2
3334 /* mode flags for showjob(s) */
3335 #define SHOW_ONLY_PGID 0x01 /* show only pgid (jobs -p) */
3336 #define SHOW_PIDS 0x02 /* show individual pids, not just one line per job */
3337 #define SHOW_CHANGED 0x04 /* only jobs whose state has changed */
3340 * A job structure contains information about a job. A job is either a
3341 * single process or a set of processes contained in a pipeline. In the
3342 * latter case, pidlist will be non-NULL, and will point to a -1 terminated
3343 * array of pids.
3345 struct procstat {
3346 pid_t ps_pid; /* process id */
3347 int ps_status; /* last process status from wait() */
3348 char *ps_cmd; /* text of command being run */
3351 struct job {
3352 struct procstat ps0; /* status of process */
3353 struct procstat *ps; /* status or processes when more than one */
3354 #if JOBS
3355 int stopstatus; /* status of a stopped job */
3356 #endif
3357 uint32_t
3358 nprocs: 16, /* number of processes */
3359 state: 8,
3360 #define JOBRUNNING 0 /* at least one proc running */
3361 #define JOBSTOPPED 1 /* all procs are stopped */
3362 #define JOBDONE 2 /* all procs are completed */
3363 #if JOBS
3364 sigint: 1, /* job was killed by SIGINT */
3365 jobctl: 1, /* job running under job control */
3366 #endif
3367 waited: 1, /* true if this entry has been waited for */
3368 used: 1, /* true if this entry is in used */
3369 changed: 1; /* true if status has changed */
3370 struct job *prev_job; /* previous job */
3373 static struct job *makejob(/*union node *,*/ int);
3374 static int forkshell(struct job *, union node *, int);
3375 static int waitforjob(struct job *);
3377 #if !JOBS
3378 enum { doing_jobctl = 0 };
3379 #define setjobctl(on) do {} while (0)
3380 #else
3381 static smallint doing_jobctl; //references:8
3382 static void setjobctl(int);
3383 #endif
3386 * Ignore a signal.
3388 static void
3389 ignoresig(int signo)
3391 /* Avoid unnecessary system calls. Is it already SIG_IGNed? */
3392 if (sigmode[signo - 1] != S_IGN && sigmode[signo - 1] != S_HARD_IGN) {
3393 /* No, need to do it */
3394 signal(signo, SIG_IGN);
3396 sigmode[signo - 1] = S_HARD_IGN;
3400 * Only one usage site - in setsignal()
3402 static void
3403 signal_handler(int signo)
3405 gotsig[signo - 1] = 1;
3407 if (signo == SIGINT && !trap[SIGINT]) {
3408 if (!suppress_int) {
3409 pending_sig = 0;
3410 raise_interrupt(); /* does not return */
3412 pending_int = 1;
3413 } else {
3414 pending_sig = signo;
3419 * Set the signal handler for the specified signal. The routine figures
3420 * out what it should be set to.
3422 static void
3423 setsignal(int signo)
3425 char *t;
3426 char cur_act, new_act;
3427 struct sigaction act;
3429 t = trap[signo];
3430 new_act = S_DFL;
3431 if (t != NULL) { /* trap for this sig is set */
3432 new_act = S_CATCH;
3433 if (t[0] == '\0') /* trap is "": ignore this sig */
3434 new_act = S_IGN;
3437 if (rootshell && new_act == S_DFL) {
3438 switch (signo) {
3439 case SIGINT:
3440 if (iflag || minusc || sflag == 0)
3441 new_act = S_CATCH;
3442 break;
3443 case SIGQUIT:
3444 #if DEBUG
3445 if (debug)
3446 break;
3447 #endif
3448 /* man bash:
3449 * "In all cases, bash ignores SIGQUIT. Non-builtin
3450 * commands run by bash have signal handlers
3451 * set to the values inherited by the shell
3452 * from its parent". */
3453 new_act = S_IGN;
3454 break;
3455 case SIGTERM:
3456 if (iflag)
3457 new_act = S_IGN;
3458 break;
3459 #if JOBS
3460 case SIGTSTP:
3461 case SIGTTOU:
3462 if (mflag)
3463 new_act = S_IGN;
3464 break;
3465 #endif
3468 //TODO: if !rootshell, we reset SIGQUIT to DFL,
3469 //whereas we have to restore it to what shell got on entry
3470 //from the parent. See comment above
3472 t = &sigmode[signo - 1];
3473 cur_act = *t;
3474 if (cur_act == 0) {
3475 /* current setting is not yet known */
3476 if (sigaction(signo, NULL, &act)) {
3477 /* pretend it worked; maybe we should give a warning,
3478 * but other shells don't. We don't alter sigmode,
3479 * so we retry every time.
3480 * btw, in Linux it never fails. --vda */
3481 return;
3483 if (act.sa_handler == SIG_IGN) {
3484 cur_act = S_HARD_IGN;
3485 if (mflag
3486 && (signo == SIGTSTP || signo == SIGTTIN || signo == SIGTTOU)
3488 cur_act = S_IGN; /* don't hard ignore these */
3492 if (cur_act == S_HARD_IGN || cur_act == new_act)
3493 return;
3495 act.sa_handler = SIG_DFL;
3496 switch (new_act) {
3497 case S_CATCH:
3498 act.sa_handler = signal_handler;
3499 break;
3500 case S_IGN:
3501 act.sa_handler = SIG_IGN;
3502 break;
3505 /* flags and mask matter only if !DFL and !IGN, but we do it
3506 * for all cases for more deterministic behavior:
3508 act.sa_flags = 0;
3509 sigfillset(&act.sa_mask);
3511 sigaction_set(signo, &act);
3513 *t = new_act;
3516 /* mode flags for set_curjob */
3517 #define CUR_DELETE 2
3518 #define CUR_RUNNING 1
3519 #define CUR_STOPPED 0
3521 /* mode flags for dowait */
3522 #define DOWAIT_NONBLOCK WNOHANG
3523 #define DOWAIT_BLOCK 0
3525 #if JOBS
3526 /* pgrp of shell on invocation */
3527 static int initialpgrp; //references:2
3528 static int ttyfd = -1; //5
3529 #endif
3530 /* array of jobs */
3531 static struct job *jobtab; //5
3532 /* size of array */
3533 static unsigned njobs; //4
3534 /* current job */
3535 static struct job *curjob; //lots
3536 /* number of presumed living untracked jobs */
3537 static int jobless; //4
3539 static void
3540 set_curjob(struct job *jp, unsigned mode)
3542 struct job *jp1;
3543 struct job **jpp, **curp;
3545 /* first remove from list */
3546 jpp = curp = &curjob;
3547 while (1) {
3548 jp1 = *jpp;
3549 if (jp1 == jp)
3550 break;
3551 jpp = &jp1->prev_job;
3553 *jpp = jp1->prev_job;
3555 /* Then re-insert in correct position */
3556 jpp = curp;
3557 switch (mode) {
3558 default:
3559 #if DEBUG
3560 abort();
3561 #endif
3562 case CUR_DELETE:
3563 /* job being deleted */
3564 break;
3565 case CUR_RUNNING:
3566 /* newly created job or backgrounded job,
3567 * put after all stopped jobs.
3569 while (1) {
3570 jp1 = *jpp;
3571 #if JOBS
3572 if (!jp1 || jp1->state != JOBSTOPPED)
3573 #endif
3574 break;
3575 jpp = &jp1->prev_job;
3577 /* FALLTHROUGH */
3578 #if JOBS
3579 case CUR_STOPPED:
3580 #endif
3581 /* newly stopped job - becomes curjob */
3582 jp->prev_job = *jpp;
3583 *jpp = jp;
3584 break;
3588 #if JOBS || DEBUG
3589 static int
3590 jobno(const struct job *jp)
3592 return jp - jobtab + 1;
3594 #endif
3597 * Convert a job name to a job structure.
3599 #if !JOBS
3600 #define getjob(name, getctl) getjob(name)
3601 #endif
3602 static struct job *
3603 getjob(const char *name, int getctl)
3605 struct job *jp;
3606 struct job *found;
3607 const char *err_msg = "%s: no such job";
3608 unsigned num;
3609 int c;
3610 const char *p;
3611 char *(*match)(const char *, const char *);
3613 jp = curjob;
3614 p = name;
3615 if (!p)
3616 goto currentjob;
3618 if (*p != '%')
3619 goto err;
3621 c = *++p;
3622 if (!c)
3623 goto currentjob;
3625 if (!p[1]) {
3626 if (c == '+' || c == '%') {
3627 currentjob:
3628 err_msg = "No current job";
3629 goto check;
3631 if (c == '-') {
3632 if (jp)
3633 jp = jp->prev_job;
3634 err_msg = "No previous job";
3635 check:
3636 if (!jp)
3637 goto err;
3638 goto gotit;
3642 if (is_number(p)) {
3643 num = atoi(p);
3644 if (num < njobs) {
3645 jp = jobtab + num - 1;
3646 if (jp->used)
3647 goto gotit;
3648 goto err;
3652 match = prefix;
3653 if (*p == '?') {
3654 match = strstr;
3655 p++;
3658 found = NULL;
3659 while (jp) {
3660 if (match(jp->ps[0].ps_cmd, p)) {
3661 if (found)
3662 goto err;
3663 found = jp;
3664 err_msg = "%s: ambiguous";
3666 jp = jp->prev_job;
3668 if (!found)
3669 goto err;
3670 jp = found;
3672 gotit:
3673 #if JOBS
3674 err_msg = "job %s not created under job control";
3675 if (getctl && jp->jobctl == 0)
3676 goto err;
3677 #endif
3678 return jp;
3679 err:
3680 ash_msg_and_raise_error(err_msg, name);
3684 * Mark a job structure as unused.
3686 static void
3687 freejob(struct job *jp)
3689 struct procstat *ps;
3690 int i;
3692 INT_OFF;
3693 for (i = jp->nprocs, ps = jp->ps; --i >= 0; ps++) {
3694 if (ps->ps_cmd != nullstr)
3695 free(ps->ps_cmd);
3697 if (jp->ps != &jp->ps0)
3698 free(jp->ps);
3699 jp->used = 0;
3700 set_curjob(jp, CUR_DELETE);
3701 INT_ON;
3704 #if JOBS
3705 static void
3706 xtcsetpgrp(int fd, pid_t pgrp)
3708 if (tcsetpgrp(fd, pgrp))
3709 ash_msg_and_raise_error("can't set tty process group (%m)");
3713 * Turn job control on and off.
3715 * Note: This code assumes that the third arg to ioctl is a character
3716 * pointer, which is true on Berkeley systems but not System V. Since
3717 * System V doesn't have job control yet, this isn't a problem now.
3719 * Called with interrupts off.
3721 static void
3722 setjobctl(int on)
3724 int fd;
3725 int pgrp;
3727 if (on == doing_jobctl || rootshell == 0)
3728 return;
3729 if (on) {
3730 int ofd;
3731 ofd = fd = open(_PATH_TTY, O_RDWR);
3732 if (fd < 0) {
3733 /* BTW, bash will try to open(ttyname(0)) if open("/dev/tty") fails.
3734 * That sometimes helps to acquire controlling tty.
3735 * Obviously, a workaround for bugs when someone
3736 * failed to provide a controlling tty to bash! :) */
3737 fd = 2;
3738 while (!isatty(fd))
3739 if (--fd < 0)
3740 goto out;
3742 fd = fcntl(fd, F_DUPFD, 10);
3743 if (ofd >= 0)
3744 close(ofd);
3745 if (fd < 0)
3746 goto out;
3747 /* fd is a tty at this point */
3748 close_on_exec_on(fd);
3749 while (1) { /* while we are in the background */
3750 pgrp = tcgetpgrp(fd);
3751 if (pgrp < 0) {
3752 out:
3753 ash_msg("can't access tty; job control turned off");
3754 mflag = on = 0;
3755 goto close;
3757 if (pgrp == getpgrp())
3758 break;
3759 killpg(0, SIGTTIN);
3761 initialpgrp = pgrp;
3763 setsignal(SIGTSTP);
3764 setsignal(SIGTTOU);
3765 setsignal(SIGTTIN);
3766 pgrp = rootpid;
3767 setpgid(0, pgrp);
3768 xtcsetpgrp(fd, pgrp);
3769 } else {
3770 /* turning job control off */
3771 fd = ttyfd;
3772 pgrp = initialpgrp;
3773 /* was xtcsetpgrp, but this can make exiting ash
3774 * loop forever if pty is already deleted */
3775 tcsetpgrp(fd, pgrp);
3776 setpgid(0, pgrp);
3777 setsignal(SIGTSTP);
3778 setsignal(SIGTTOU);
3779 setsignal(SIGTTIN);
3780 close:
3781 if (fd >= 0)
3782 close(fd);
3783 fd = -1;
3785 ttyfd = fd;
3786 doing_jobctl = on;
3789 static int FAST_FUNC
3790 killcmd(int argc, char **argv)
3792 if (argv[1] && strcmp(argv[1], "-l") != 0) {
3793 int i = 1;
3794 do {
3795 if (argv[i][0] == '%') {
3797 * "kill %N" - job kill
3798 * Converting to pgrp / pid kill
3800 struct job *jp;
3801 char *dst;
3802 int j, n;
3804 jp = getjob(argv[i], 0);
3806 * In jobs started under job control, we signal
3807 * entire process group by kill -PGRP_ID.
3808 * This happens, f.e., in interactive shell.
3810 * Otherwise, we signal each child via
3811 * kill PID1 PID2 PID3.
3812 * Testcases:
3813 * sh -c 'sleep 1|sleep 1 & kill %1'
3814 * sh -c 'true|sleep 2 & sleep 1; kill %1'
3815 * sh -c 'true|sleep 1 & sleep 2; kill %1'
3817 n = jp->nprocs; /* can't be 0 (I hope) */
3818 if (jp->jobctl)
3819 n = 1;
3820 dst = alloca(n * sizeof(int)*4);
3821 argv[i] = dst;
3822 for (j = 0; j < n; j++) {
3823 struct procstat *ps = &jp->ps[j];
3824 /* Skip non-running and not-stopped members
3825 * (i.e. dead members) of the job
3827 if (ps->ps_status != -1 && !WIFSTOPPED(ps->ps_status))
3828 continue;
3830 * kill_main has matching code to expect
3831 * leading space. Needed to not confuse
3832 * negative pids with "kill -SIGNAL_NO" syntax
3834 dst += sprintf(dst, jp->jobctl ? " -%u" : " %u", (int)ps->ps_pid);
3836 *dst = '\0';
3838 } while (argv[++i]);
3840 return kill_main(argc, argv);
3843 static void
3844 showpipe(struct job *jp /*, FILE *out*/)
3846 struct procstat *ps;
3847 struct procstat *psend;
3849 psend = jp->ps + jp->nprocs;
3850 for (ps = jp->ps + 1; ps < psend; ps++)
3851 printf(" | %s", ps->ps_cmd);
3852 outcslow('\n', stdout);
3853 flush_stdout_stderr();
3857 static int
3858 restartjob(struct job *jp, int mode)
3860 struct procstat *ps;
3861 int i;
3862 int status;
3863 pid_t pgid;
3865 INT_OFF;
3866 if (jp->state == JOBDONE)
3867 goto out;
3868 jp->state = JOBRUNNING;
3869 pgid = jp->ps[0].ps_pid;
3870 if (mode == FORK_FG)
3871 xtcsetpgrp(ttyfd, pgid);
3872 killpg(pgid, SIGCONT);
3873 ps = jp->ps;
3874 i = jp->nprocs;
3875 do {
3876 if (WIFSTOPPED(ps->ps_status)) {
3877 ps->ps_status = -1;
3879 ps++;
3880 } while (--i);
3881 out: