xref: /aosp_15_r20/external/toybox/toys/pending/sh.c (revision cf5a6c84e2b8763fc1a7db14496fd4742913b199)
1 /* sh.c - toybox shell
2  *
3  * Copyright 2006 Rob Landley <[email protected]>
4  *
5  * This shell aims for bash compatibility. The bash man page is at:
6  * http://man7.org/linux/man-pages/man1/bash.1.html
7  *
8  * The POSIX-2008/SUSv4 shell spec is at:
9  * http://opengroup.org/onlinepubs/9699919799/utilities/V3_chap02.html
10  * and http://opengroup.org/onlinepubs/9699919799/utilities/sh.html
11  *
12  * deviations from posix: don't care about $LANG or $LC_ALL
13  * deviations from bash:
14  *   redirect+expansion in one pass so we can't report errors between them.
15  *   Trailing redirects error at runtime, not parse time.
16 
17  * builtins: alias bg command fc fg getopts jobs newgrp read umask unalias wait
18  *          disown suspend source pushd popd dirs logout times trap cd hash exit
19  *           unset local export readonly set : . let history declare ulimit type
20  * "special" builtins: break continue eval exec return shift
21  * external with extra shell behavior: kill pwd time test
22 
23  * * ? [ # ~ = % [[ ]] function select exit label:
24 
25  * TODO: case, wildcard +(*|?), job control (find_plus_minus), ${x//}, $(())
26 
27  * TODO: support case in $() because $(case a in a) ;; ; esac) stops at first )
28  * TODO: test exit from "trap EXIT" doesn't recurse
29  * TODO: ! history expansion
30  * TODO: getuid() vs geteuid()
31  * TODO: test that $PS1 color changes work without stupid \[ \] hack
32  * TODO: Handle embedded NUL bytes in the command line? (When/how?)
33  * TODO: set -e -o pipefail, shopt -s nullglob
34  * TODO: utf8 isspace
35  *
36  * bash man page:
37  * control operators || & && ; ;; ;& ;;& ( ) | |& <newline>
38  * reserved words
39  *   ! case  coproc  do done elif else esac fi for  function  if  in  select
40  *   then until while { } time [[ ]]
41  *
42  * Flow control statements:
43  *
44  * if/then/elif/else/fi, for select while until/do/done, case/esac,
45  * {/}, [[/]], (/), function assignment
46 
47 USE_SH(NEWTOY(break, ">1", TOYFLAG_NOFORK))
48 USE_SH(NEWTOY(cd, ">1LP[-LP]", TOYFLAG_NOFORK))
49 USE_SH(NEWTOY(continue, ">1", TOYFLAG_NOFORK))
50 USE_SH(NEWTOY(declare, "pAailunxr", TOYFLAG_NOFORK))
51  // TODO tpgfF
52 USE_SH(NEWTOY(eval, 0, TOYFLAG_NOFORK))
53 USE_SH(NEWTOY(exec, "^cla:", TOYFLAG_NOFORK))
54 USE_SH(NEWTOY(exit, 0, TOYFLAG_NOFORK))
55 USE_SH(NEWTOY(export, "np", TOYFLAG_NOFORK))
56 USE_SH(NEWTOY(jobs, "lnprs", TOYFLAG_NOFORK))
57 USE_SH(NEWTOY(local, 0, TOYFLAG_NOFORK))
58 USE_SH(NEWTOY(return, ">1", TOYFLAG_NOFORK))
59 USE_SH(NEWTOY(set, 0, TOYFLAG_NOFORK))
60 USE_SH(NEWTOY(shift, ">1", TOYFLAG_NOFORK))
61 USE_SH(NEWTOY(source, "<1", TOYFLAG_NOFORK))
62 USE_SH(OLDTOY(., source, TOYFLAG_NOFORK))
63 USE_SH(NEWTOY(unset, "fvn[!fv]", TOYFLAG_NOFORK))
64 USE_SH(NEWTOY(wait, "n", TOYFLAG_NOFORK))
65 
66 USE_SH(NEWTOY(sh, "0^(noediting)(noprofile)(norc)sc:i", TOYFLAG_BIN))
67 USE_SH(OLDTOY(toysh, sh, TOYFLAG_BIN))
68 USE_SH(OLDTOY(bash, sh, TOYFLAG_BIN))
69 // Login lies in argv[0], so add some aliases to catch that
70 USE_SH(OLDTOY(-sh, sh, 0))
71 USE_SH(OLDTOY(-toysh, sh, 0))
72 USE_SH(OLDTOY(-bash, sh, 0))
73 
74 config SH
75   bool "sh (toysh)"
76   default n
77   help
78     usage: sh [-c command] [script]
79 
80     Command shell.  Runs a shell script, or reads input interactively
81     and responds to it. Roughly compatible with "bash". Run "help" for
82     list of built-in commands.
83 
84     -c	command line to execute
85     -i	interactive mode (default when STDIN is a tty)
86     -s	don't run script (args set $* parameters but read commands from stdin)
87 
88     Command shells parse each line of input (prompting when interactive), perform
89     variable expansion and redirection, execute commands (spawning child processes
90     and background jobs), and perform flow control based on the return code.
91 
92     Parsing:
93       syntax errors
94 
95     Interactive prompts:
96       line continuation
97 
98     Variable expansion:
99       Note: can cause syntax errors at runtime
100 
101     Redirection:
102       HERE documents (parsing)
103       Pipelines (flow control and job control)
104 
105     Running commands:
106       process state
107       builtins
108         cd [[ ]] (( ))
109         ! : [ # TODO: help for these?
110         true false help echo kill printf pwd test
111       child processes
112 
113     Job control:
114       &    Background process
115       Ctrl-C kill process
116       Ctrl-Z suspend process
117       bg fg jobs kill
118 
119     Flow control:
120     ;    End statement (same as newline)
121     &    Background process (returns true unless syntax error)
122     &&   If this fails, next command fails without running
123     ||   If this succeeds, next command succeeds without running
124     |    Pipelines! (Can of worms...)
125     for {name [in...]}|((;;)) do; BODY; done
126     if TEST; then BODY; fi
127     while TEST; do BODY; done
128     case a in X);; esac
129     [[ TEST ]]
130     ((MATH))
131 
132     Job control:
133     &    Background process
134     Ctrl-C kill process
135     Ctrl-Z suspend process
136     bg fg jobs kill
137 
138 # These are here for the help text, they're not selectable and control nothing
139 config BREAK
140   bool
141   default n
142   depends on SH
143   help
144     usage: break [N]
145 
146     End N levels of for/while/until loop immediately (default 1).
147 
148 config CD
149   bool
150   default n
151   depends on SH
152   help
153     usage: cd [-PL] [-] [path]
154 
155     Change current directory. With no arguments, go $HOME. Sets $OLDPWD to
156     previous directory: cd - to return to $OLDPWD.
157 
158     -P	Physical path: resolve symlinks in path
159     -L	Local path: .. trims directories off $PWD (default)
160 
161 config CONTINUE
162   bool
163   default n
164   depends on SH
165   help
166     usage: continue [N]
167 
168     Start next entry in for/while/until loop (or Nth outer loop, default 1).
169 
170 config DECLARE
171   bool
172   default n
173   depends on SH
174   help
175     usage: declare [-pAailunxr] [NAME...]
176 
177     Set or print variable attributes and values.
178 
179     -p	Print variables instead of setting
180     -A	Associative array
181     -a	Indexed array
182     -i	Integer
183     -l	Lower case
184     -n	Name reference (symlink)
185     -r	Readonly
186     -u	Uppercase
187     -x	Export
188 
189 config EXIT
190   bool
191   default n
192   depends on SH
193   help
194     usage: exit [status]
195 
196     Exit shell.  If no return value supplied on command line, use value
197     of most recent command, or 0 if none.
198 
199 config SET
200   bool
201   default n
202   depends on SH
203   help
204     usage: set [+a] [+o OPTION] [VAR...]
205 
206     Set variables and shell attributes. Use + to disable and - to enable.
207     NAME=VALUE arguments assign to the variable, any leftovers set $1, $2...
208     With no arguments, prints current variables.
209 
210     -f	NAME is a function
211     -v	NAME is a variable
212     -n	don't follow name reference
213 
214     OPTIONs:
215       history - enable command history
216 
217 config UNSET
218   bool
219   default n
220   depends on SH
221   help
222     usage: unset [-fvn] NAME...
223 
224     -f	NAME is a function
225     -v	NAME is a variable
226     -n	dereference NAME and unset that
227 
228 config EVAL
229   bool
230   default n
231   depends on SH
232   help
233     usage: eval COMMAND...
234 
235     Execute (combined) arguments as a shell command.
236 
237 config EXEC
238   bool
239   default n
240   depends on SH
241   help
242     usage: exec [-cl] [-a NAME] COMMAND...
243 
244     -a	set argv[0] to NAME
245     -c	clear environment
246     -l	prepend - to argv[0]
247 
248 config EXPORT
249   bool
250   default n
251   depends on SH
252   help
253     usage: export [-n] [NAME[=VALUE]...]
254 
255     Make variables available to child processes. NAME exports existing local
256     variable(s), NAME=VALUE sets and exports.
257 
258     -n	Unexport. Turn listed variable(s) into local variables.
259 
260     With no arguments list exported variables/attributes as "declare" statements.
261 
262 config JOBS
263   bool
264   default n
265   depends on SH
266   help
267     usage: jobs [-lnprs] [%JOB | -x COMMAND...]
268 
269     List running/stopped background jobs.
270 
271     -l Include process ID in list
272     -n Show only new/changed processes
273     -p Show process IDs only
274     -r Show running processes
275     -s Show stopped processes
276 
277 config LOCAL
278   bool
279   default n
280   depends on SH
281   help
282     usage: local [NAME[=VALUE]...]
283 
284     Create a local variable that lasts until return from this function.
285     With no arguments lists local variables in current function context.
286     TODO: implement "declare" options.
287 
288 config RETURN
289   bool
290   default n
291   depends on SH
292   help
293     usage: return [#]
294 
295     Return from function/source with specified value or last command's exit val.
296 
297 config SHIFT
298   bool
299   default n
300   depends on SH
301   help
302     usage: shift [N]
303 
304     Skip N (default 1) positional parameters, moving $1 and friends along the list.
305     Does not affect $0.
306 
307 config SOURCE
308   bool
309   default n
310   depends on SH
311   help
312     usage: source FILE [ARGS...]
313 
314     Read FILE and execute commands. Any ARGS become positional parameters.
315 
316 config WAIT
317   bool
318   default n
319   depends on SH
320   help
321     usage: wait [-n] [ID...]
322 
323     Wait for background processes to exit, returning its exit code.
324     ID can be PID or job, with no IDs waits for all backgrounded processes.
325 
326     -n	Wait for next process to exit
327 */
328 
329 #define FOR_sh
330 #include "toys.h"
331 
332 GLOBALS(
333   union {
334     struct {
335       char *c;
336     } sh;
337     struct {
338       char *a;
339     } exec;
340   };
341 
342   // keep SECONDS here: used to work around compiler limitation in run_command()
343   long long SECONDS;
344   char *isexec, *wcpat;
345   unsigned options, jobcnt, LINENO;
346   int hfd, pid, bangpid, srclvl, recursion, recfile[50+200*CFG_TOYBOX_FORK];
347 
348   // Callable function array
349   struct sh_function {
350     char *name;
351     struct sh_pipeline {  // pipeline segments: linked list of arg w/metadata
352       struct sh_pipeline *next, *prev, *end;
353       int count, here, type, lineno;
354       struct sh_arg {
355         char **v;
356         int c;
357       } arg[1];
358     } *pipeline;
359     unsigned long refcount;
360   } **functions;
361   long funcslen;
362 
363   // runtime function call stack
364   struct sh_fcall {
365     struct sh_fcall *next, *prev;
366 
367     // This dlist in reverse order: TT.ff current function, TT.ff->prev globals
368     struct sh_vars {
369       long flags;
370       char *str;
371     } *vars;
372     long varslen, varscap, shift, oldlineno;
373 
374     struct sh_function *func; // TODO wire this up
375     struct sh_pipeline *pl;
376     char *ifs, *omnom;
377     struct sh_arg arg;
378     struct arg_list *delete;
379 
380     // Runtime stack of nested if/else/fi and for/do/done contexts.
381     struct sh_blockstack {
382       struct sh_blockstack *next;
383       struct sh_pipeline *start, *middle;
384       struct sh_process *pp;       // list of processes piping in to us
385       int run, loop, *urd, pout, pipe;
386       struct sh_arg farg;          // for/select arg stack, case wildcard deck
387       struct arg_list *fdelete;    // farg's cleanup list
388       char *fvar;                  // for/select's iteration variable name
389     } *blk;
390   } *ff;
391 
392 // TODO ctrl-Z suspend should stop script
393   struct sh_process {
394     struct sh_process *next, *prev; // | && ||
395     struct arg_list *delete;   // expanded strings
396     // undo redirects, a=b at start, child PID, exit status, has !, job #
397     int *urd, envlen, pid, exit, flags, job, dash;
398     long long when; // when job backgrounded/suspended
399     struct sh_arg *raw, arg;
400   } *pp; // currently running process
401 
402   // job list, command line for $*, scratch space for do_wildcard_files()
403   struct sh_arg jobs, *wcdeck;
404   FILE *script;
405 )
406 
407 // Prototype because $($($(blah))) nests, leading to run->parse->run loop
408 int do_source(char *name, FILE *ff);
409 // functions contain pipelines contain functions: prototype because loop
410 static void free_pipeline(void *pipeline);
411 // recalculate needs to get/set variables, but setvar_found calls recalculate
412 static struct sh_vars *setvar(char *str);
413 
414 // ordered for greedy matching, so >&; becomes >& ; not > &;
415 // making these const means I need to typecast the const away later to
416 // avoid endless warnings.
417 static const char *redirectors[] = {"<<<", "<<-", "<<", "<&", "<>", "<", ">>",
418   ">&", ">|", ">", "&>>", "&>", 0};
419 
420 // The order of these has to match the string in set_main()
421 #define OPT_B	0x100
422 #define OPT_C	0x200
423 #define OPT_x	0x400
424 #define OPT_u	0x800
425 
426 // only export $PWD and $OLDPWD on first cd
427 #define OPT_cd  0x80000000
428 
429 // struct sh_process->flags
430 #define PFLAG_NOT    1
431 
syntax_err(char * s)432 static void syntax_err(char *s)
433 {
434   struct sh_fcall *ff = TT.ff;
435 // TODO: script@line only for script not interactive.
436   for (ff = TT.ff; ff != TT.ff->prev; ff = ff->next) if (ff->omnom) break;
437   error_msg("syntax error '%s'@%u: %s", ff->omnom ? : "-c", TT.LINENO, s);
438   toys.exitval = 2;
439   if (!(TT.options&FLAG_i)) xexit();
440 }
441 
debug_show_fds()442 void debug_show_fds()
443 {
444   int x = 0, fd = open("/proc/self/fd", O_RDONLY);
445   DIR *X = fdopendir(fd);
446   struct dirent *DE;
447   char *s, *ss = 0, buf[4096], *sss = buf;
448 
449   if (!X) return;
450   for (; (DE = readdir(X));) {
451     if (atoi(DE->d_name) == fd) continue;
452     s = xreadlink(ss = xmprintf("/proc/self/fd/%s", DE->d_name));
453     if (s && *s != '.') sss += sprintf(sss, ", %s=%s"+2*!x++, DE->d_name, s);
454     free(s); free(ss);
455   }
456   *sss = 0;
457   dprintf(2, "%d fd:%s\n", getpid(), buf);
458   closedir(X);
459 }
460 
nospace(char ** ss)461 static char **nospace(char **ss)
462 {
463   while (isspace(**ss)) ++*ss;
464 
465   return ss;
466 }
467 
468 // append to array with null terminator and realloc as necessary
arg_add(struct sh_arg * arg,char * data)469 static void arg_add(struct sh_arg *arg, char *data)
470 {
471   // expand with stride 32. Micro-optimization: don't realloc empty stack
472   if (!(arg->c&31) && (arg->c || !arg->v))
473     arg->v = xrealloc(arg->v, sizeof(char *)*(arg->c+33));
474   arg->v[arg->c++] = data;
475   arg->v[arg->c] = 0;
476 }
477 
478 // add argument to an arg_list
push_arg(struct arg_list ** list,void * arg)479 static void *push_arg(struct arg_list **list, void *arg)
480 {
481   struct arg_list *al;
482 
483   if (list) {
484     al = xmalloc(sizeof(struct arg_list));
485     al->next = *list;
486     al->arg = arg;
487     *list = al;
488   }
489 
490   return arg;
491 }
492 
arg_add_del(struct sh_arg * arg,char * data,struct arg_list ** delete)493 static void arg_add_del(struct sh_arg *arg, char *data,struct arg_list **delete)
494 {
495   arg_add(arg, push_arg(delete, data));
496 }
497 
498 // Assign one variable from malloced key=val string, returns var struct
499 // TODO implement remaining types
500 #define VAR_NOFREE    (1<<10)
501 #define VAR_WHITEOUT  (1<<9)
502 #define VAR_DICT      (1<<8)
503 #define VAR_ARRAY     (1<<7)
504 #define VAR_INT       (1<<6)
505 #define VAR_TOLOWER   (1<<5)
506 #define VAR_TOUPPER   (1<<4)
507 #define VAR_NAMEREF   (1<<3)
508 #define VAR_EXPORT    (1<<2)
509 #define VAR_READONLY  (1<<1)
510 #define VAR_MAGIC     (1<<0)
511 
512 // return length of valid variable name
varend(char * s)513 static char *varend(char *s)
514 {
515   if (isdigit(*s)) return s;
516   while (*s>' ' && (*s=='_' || !ispunct(*s))) s++;
517 
518   return s;
519 }
520 
521 // TODO: this has to handle VAR_NAMEREF, but return dangling symlink
522 // Also, unset -n, also "local ISLINK" to parent var.
523 // Return sh_vars * or 0 if not found.
524 // Sets *pff to function (only if found), only returns whiteouts if pff not NULL
findvar(char * name,struct sh_fcall ** pff)525 static struct sh_vars *findvar(char *name, struct sh_fcall **pff)
526 {
527   int len = varend(name)-name;
528   struct sh_fcall *ff = TT.ff;
529 
530   // advance through locals to global context, ignoring whiteouts
531   if (len) do {
532     struct sh_vars *var = ff->vars+ff->varslen;
533 
534     if (var) while (var--!=ff->vars) {
535       if (strncmp(var->str, name, len) || var->str[len]!='=') continue;
536       if (pff) *pff = ff;
537       else if (var->flags&VAR_WHITEOUT) return 0;
538 
539       return var;
540     }
541   } while ((ff = ff->next)!=TT.ff);
542 
543   return 0;
544 }
545 
546 // get value of variable starting at s.
getvar(char * s)547 static char *getvar(char *s)
548 {
549   struct sh_vars *var = findvar(s, 0);
550 
551   if (!var) return 0;
552 
553   if (var->flags & VAR_MAGIC) {
554     char c = *var->str;
555 
556     if (c == 'S') sprintf(toybuf, "%lld", (millitime()-TT.SECONDS)/1000);
557     else if (c == 'R') sprintf(toybuf, "%ld", random()&((1<<16)-1));
558     else if (c == 'L') sprintf(toybuf, "%u", TT.ff->pl->lineno);
559     else if (c == 'G') sprintf(toybuf, "TODO: GROUPS");
560     else if (c == 'B') sprintf(toybuf, "%d", getpid());
561     else if (c == 'E') {
562       struct timespec ts;
563 
564       clock_gettime(CLOCK_REALTIME, &ts);
565       sprintf(toybuf, "%lld%c%06ld", (long long)ts.tv_sec, (s[5]=='R')*'.',
566               ts.tv_nsec/1000);
567     }
568 
569     return toybuf;
570   }
571 
572   return varend(var->str)+1;
573 }
574 
575 // Append variable to ff->vars, returning *struct. Does not check duplicates.
addvar(char * s,struct sh_fcall * ff)576 static struct sh_vars *addvar(char *s, struct sh_fcall *ff)
577 {
578   if (ff->varslen == ff->varscap) {
579     ff->varscap += 32;
580     ff->vars = xrealloc(ff->vars, (ff->varscap)*sizeof(*ff->vars));
581   }
582   if (!s) return ff->vars;
583   ff->vars[ff->varslen].flags = 0;
584   ff->vars[ff->varslen].str = s;
585 
586   return ff->vars+ff->varslen++;
587 }
588 
589 // Recursively calculate string into dd, returns 0 if failed, ss = error point
590 // Recursion resolves operators of lower priority level to a value
591 // Loops through operators at same priority
592 #define NO_ASSIGN 128
recalculate(long long * dd,char ** ss,int lvl)593 static int recalculate(long long *dd, char **ss, int lvl)
594 {
595   long long ee, ff;
596   char *var = 0, *val, cc = **nospace(ss);
597   int ii, noa = lvl&NO_ASSIGN;
598   lvl &= NO_ASSIGN-1;
599 
600   // Unary prefixes can only occur at the start of a parse context
601   if (cc=='!' || cc=='~') {
602     ++*ss;
603     if (!recalculate(dd, ss, noa|15)) return 0;
604     *dd = (cc=='!') ? !*dd : ~*dd;
605   } else if (cc=='+' || cc=='-') {
606     // Is this actually preincrement/decrement? (Requires assignable var.)
607     if (*++*ss==cc) {
608       val = (*ss)++;
609       nospace(ss);
610       if (*ss==(var = varend(*ss))) {
611         *ss = val;
612         var = 0;
613       }
614     }
615     if (!var) {
616       if (!recalculate(dd, ss, noa|15)) return 0;
617       if (cc=='-') *dd = -*dd;
618     }
619   } else if (cc=='(') {
620     ++*ss;
621     if (!recalculate(dd, ss, noa|1)) return 0;
622     if (**ss!=')') return 0;
623     else ++*ss;
624   } else if (isdigit(cc)) {
625     *dd = strtoll(*ss, ss, 0);
626     if (**ss=='#') {
627       if (!*++*ss || isspace(**ss) || ispunct(**ss)) return 0;
628       *dd = strtoll(val = *ss, ss, *dd);
629       if (val == *ss) return 0;
630     }
631   } else if ((var = varend(*ss))==*ss) {
632     // At lvl 0 "" is ok, anything higher needs a non-empty equation
633     if (lvl || (cc && cc!=')')) return 0;
634     *dd = 0;
635 
636     return 1;
637   }
638 
639   // If we got a variable, evaluate its contents to set *dd
640   if (var) {
641     // Recursively evaluate, catching x=y; y=x; echo $((x))
642     TT.recfile[TT.recursion++] = 0;
643     if (TT.recursion == ARRAY_LEN(TT.recfile)) {
644       perror_msg("recursive occlusion");
645       --TT.recursion;
646 
647       return 0;
648     }
649     val = getvar(var = *ss) ? : "";
650     ii = recalculate(dd, &val, noa);
651     TT.recursion--;
652     if (!ii) return 0;
653     if (*val) {
654       perror_msg("bad math: %s @ %d", var, (int)(val-var));
655 
656       return 0;
657     }
658     val = *ss = varend(var);
659 
660     // Operators that assign to a varible must be adjacent to one:
661 
662     // Handle preincrement/predecrement (only gets here if var set before else)
663     if (cc=='+' || cc=='-') {
664       if (cc=='+') ee = ++*dd;
665       else ee = --*dd;
666     } else cc = 0;
667 
668     // handle postinc/postdec
669     if ((**nospace(ss)=='+' || **ss=='-') && (*ss)[1]==**ss) {
670       ee = ((cc = **ss)=='+') ? 1+*dd : -1+*dd;
671       *ss += 2;
672 
673     // Assignment operators: = *= /= %= += -= <<= >>= &= ^= |=
674     } else if (lvl<=2 && (*ss)[ii = (-1 != stridx("*/%+-", **ss))
675                +2*!smemcmp(*ss, "<<", 2)+2*!smemcmp(*ss, ">>", 2)]=='=')
676     {
677       // TODO: assignments are lower priority BUT must go after variable,
678       // come up with precedence checking tests?
679       cc = **ss;
680       *ss += ii+1;
681       if (!recalculate(&ee, ss, noa|1)) return 0; // TODO lvl instead of 1?
682       if (cc=='*') *dd *= ee;
683       else if (cc=='+') *dd += ee;
684       else if (cc=='-') *dd -= ee;
685       else if (cc=='<') *dd <<= ee;
686       else if (cc=='>') *dd >>= ee;
687       else if (cc=='&') *dd &= ee;
688       else if (cc=='^') *dd ^= ee;
689       else if (cc=='|') *dd |= ee;
690       else if (!cc) *dd = ee;
691       else if (!ee) {
692         perror_msg("%c0", cc);
693 
694         return 0;
695       } else if (cc=='/') *dd /= ee;
696       else if (cc=='%') *dd %= ee;
697       ee = *dd;
698     }
699     if (cc && !noa) setvar(xmprintf("%.*s=%lld", (int)(val-var), var, ee));
700   }
701 
702   // x**y binds first
703   if (lvl<=14) while (strstart(nospace(ss), "**")) {
704     if (!recalculate(&ee, ss, noa|15)) return 0;
705     if (ee<0) perror_msg("** < 0");
706     for (ff = *dd, *dd = 1; ee; ee--) *dd *= ff;
707   }
708 
709   // w*x/y%z bind next
710   if (lvl<=13) while ((cc = **nospace(ss)) && strchr("*/%", cc)) {
711     ++*ss;
712     if (!recalculate(&ee, ss, noa|14)) return 0;
713     if (cc=='*') *dd *= ee;
714     else if (!ee) {
715       perror_msg("%c0", cc);
716 
717       return 0;
718     } else if (cc=='%') *dd %= ee;
719     else *dd /= ee;
720   }
721 
722   // x+y-z
723   if (lvl<=12) while ((cc = **nospace(ss)) && strchr("+-", cc)) {
724     ++*ss;
725     if (!recalculate(&ee, ss, noa|13)) return 0;
726     if (cc=='+') *dd += ee;
727     else *dd -= ee;
728   }
729 
730   // x<<y >>
731 
732   if (lvl<=11) while ((cc = **nospace(ss)) && strchr("<>", cc) && cc==(*ss)[1]){
733     *ss += 2;
734     if (!recalculate(&ee, ss, noa|12)) return 0;
735     if (cc == '<') *dd <<= ee;
736     else *dd >>= ee;
737   }
738 
739   // x<y <= > >=
740   if (lvl<=10) while ((cc = **nospace(ss)) && strchr("<>", cc)) {
741     if ((ii = *++*ss=='=')) ++*ss;
742     if (!recalculate(&ee, ss, noa|11)) return 0;
743     if (cc=='<') *dd = ii ? (*dd<=ee) : (*dd<ee);
744     else *dd = ii ? (*dd>=ee) : (*dd>ee);
745   }
746 
747   if (lvl<=9) while ((cc = **nospace(ss)) && strchr("=!", cc) && (*ss)[1]=='='){
748     *ss += 2;
749     if (!recalculate(&ee, ss, noa|10)) return 0;
750     *dd = (cc=='!') ? *dd != ee : *dd == ee;
751   }
752 
753   if (lvl<=8) while (**nospace(ss)=='&' && (*ss)[1]!='&') {
754     ++*ss;
755     if (!recalculate(&ee, ss, noa|9)) return 0;
756     *dd &= ee;
757   }
758 
759   if (lvl<=7) while (**nospace(ss)=='^') {
760     ++*ss;
761     if (!recalculate(&ee, ss, noa|8)) return 0;
762     *dd ^= ee;
763   }
764 
765   if (lvl<=6) while (**nospace(ss)=='|' && (*ss)[1]!='|') {
766     ++*ss;
767     if (!recalculate(&ee, ss, noa|7)) return 0;
768     *dd |= ee;
769   }
770 
771   if (lvl<=5) while (strstart(nospace(ss), "&&")) {
772     if (!recalculate(&ee, ss, noa|6|NO_ASSIGN*!*dd)) return 0;
773     *dd = *dd && ee;
774   }
775 
776   if (lvl<=4) while (strstart(nospace(ss), "||")) {
777     if (!recalculate(&ee, ss, noa|5|NO_ASSIGN*!!*dd)) return 0;
778     *dd = *dd || ee;
779   }
780 
781   // ? : slightly weird: recurses with lower priority instead of looping
782   // because a ? b ? c : d ? e : f : g == a ? (b ? c : (d ? e : f) : g)
783   if (lvl<=3) if (**nospace(ss)=='?') {
784     ++*ss;
785     if (**nospace(ss)==':' && *dd) ee = *dd;
786     else if (!recalculate(&ee, ss, noa|1|NO_ASSIGN*!*dd) || **nospace(ss)!=':')
787       return 0;
788     ++*ss;
789     if (!recalculate(&ff, ss, noa|1|NO_ASSIGN*!!*dd)) return 0;
790     *dd = *dd ? ee : ff;
791   }
792 
793   // lvl<=2 assignment would go here, but handled above because variable
794 
795   // , (slightly weird, replaces dd instead of modifying it via ee/ff)
796   if (lvl<=1) while (**nospace(ss)==',') {
797     ++*ss;
798     if (!recalculate(dd, ss, noa|2)) return 0;
799   }
800 
801   return 1;
802 }
803 
804 // Return length of utf8 char @s fitting in len, writing value into *cc
getutf8(char * s,int len,int * cc)805 static int getutf8(char *s, int len, int *cc)
806 {
807   unsigned wc;
808 
809   if (len<0) wc = len = 0;
810   else if (1>(len = utf8towc(&wc, s, len))) wc = *s, len = 1;
811   if (cc) *cc = wc;
812 
813   return len;
814 }
815 
816 // utf8 strchr: return wide char matched at wc from chrs, or 0 if not matched
817 // if len, save length of next wc (whether or not it's in list)
utf8chr(char * wc,char * chrs,int * len)818 static int utf8chr(char *wc, char *chrs, int *len)
819 {
820   unsigned wc1, wc2;
821   int ll;
822 
823   if (len) *len = 1;
824   if (!*wc) return 0;
825   if (0<(ll = utf8towc(&wc1, wc, 99))) {
826     if (len) *len = ll;
827     while (*chrs) {
828       if(1>(ll = utf8towc(&wc2, chrs, 99))) chrs++;
829       else {
830         if (wc1 == wc2) return wc1;
831         chrs += ll;
832       }
833     }
834   }
835 
836   return 0;
837 }
838 
839 // does this entire string match one of the strings in try[]
anystr(char * s,char ** try)840 static int anystr(char *s, char **try)
841 {
842   while (*try) if (!strcmp(s, *try++)) return 1;
843 
844   return 0;
845 }
846 
847 // Update $IFS cache in function call stack after variable assignment
cache_ifs(char * s,struct sh_fcall * ff)848 static void cache_ifs(char *s, struct sh_fcall *ff)
849 {
850   if (strstart(&s, "IFS="))
851     do ff->ifs = s; while ((ff = ff->next) != TT.ff->prev);
852 }
853 
854 // declare -aAilnrux
855 // ft
856 // TODO VAR_ARRAY VAR_DICT
857 
858 // Assign new name=value string for existing variable. s takes x=y or x+=y
setvar_found(char * s,int freeable,struct sh_vars * var)859 static struct sh_vars *setvar_found(char *s, int freeable, struct sh_vars *var)
860 {
861   char *ss, *sss, *sd, buf[24];
862   long ii, jj, kk, flags = var->flags&~VAR_WHITEOUT;
863   long long ll;
864   int cc, vlen = varend(s)-s;
865 
866   if (flags&VAR_READONLY) {
867     error_msg("%.*s: read only", vlen, s);
868     goto bad;
869   }
870 
871   // If += has no old value (addvar placeholder or empty old var) yank the +
872   if (s[vlen]=='+' && (var->str==s || !strchr(var->str, '=')[1])) {
873     ss = xmprintf("%.*s%s", vlen, s, s+vlen+1);
874     if (var->str==s) {
875       if (!freeable++) var->flags |= VAR_NOFREE;
876     } else if (freeable++) free(s);
877     s = ss;
878   }
879 
880   // Handle VAR_NAMEREF mismatch by replacing name
881   if (strncmp(var->str, s, vlen)) {
882     ss = s+vlen+(s[vlen]=='+')+1;
883     ss = xmprintf("%.*s%s", (vlen = varend(var->str)-var->str)+1, var->str, ss);
884     if (freeable++) free(s);
885     s = ss;
886   }
887 
888   // utf8 aware case conversion, two pass (measure, allocate, convert) because
889   // unicode IS stupid enough for upper/lower case to be different utf8 byte
890   // lengths, for example lowercase of U+023a (c8 ba) is U+2c65 (e2 b1 a5)
891   if (flags&(VAR_TOUPPER|VAR_TOLOWER)) {
892     for (jj = kk = 0, sss = 0; jj<2; jj++, sss = sd = xmalloc(vlen+kk+2)) {
893       sd = jj ? stpncpy(sss, s, vlen+1) : (void *)&sss;
894       for (ss = s+vlen+1; (ii = getutf8(ss, 4, &cc)); ss += ii) {
895         kk += wctoutf8(sd, (flags&VAR_TOUPPER) ? towupper(cc) : towlower(cc));
896         if (jj) {
897           sd += kk;
898           kk = 0;
899         }
900       }
901     }
902     *sd = 0;
903     if (freeable++) free(s);
904     s = sss;
905   }
906 
907   // integer variables treat += differently
908   ss = s+vlen+(s[vlen]=='+')+1;
909   if (flags&VAR_INT) {
910     sd = ss;
911     if (!recalculate(&ll, &sd, 0) || *sd) {
912       perror_msg("bad math: %s @ %d", ss, (int)(sd-ss));
913 
914       goto bad;
915     }
916 
917     sprintf(buf, "%lld", ll);
918     if (flags&VAR_MAGIC) {
919       if (*s == 'S') {
920         ll *= 1000;
921         TT.SECONDS = (s[vlen]=='+') ? TT.SECONDS+ll : millitime()-ll;
922       } else if (*s == 'R') srandom(ll);
923       if (freeable) free(s);
924 
925       // magic can't be whiteout or nofree, and keeps old string
926       return var;
927     } else if (s[vlen]=='+' || strcmp(buf, ss)) {
928       if (s[vlen]=='+') ll += atoll(strchr(var->str, '=')+1);
929       ss = xmprintf("%.*s=%lld", vlen, s, ll);
930       if (freeable++) free(s);
931       s = ss;
932     }
933   } else if (s[vlen]=='+' && !(flags&VAR_MAGIC)) {
934     ss = xmprintf("%s%s", var->str, ss);
935     if (freeable++) free(s);
936     s = ss;
937   }
938 
939   // Replace old string with new one, adjusting nofree status
940   if (flags&VAR_NOFREE) flags ^= VAR_NOFREE;
941   else free(var->str);
942   if (!freeable) flags |= VAR_NOFREE;
943   var->str = s;
944   var->flags = flags;
945 
946   return var;
947 bad:
948   if (freeable) free(s);
949 
950   return 0;
951 }
952 
953 // Creates new variables (local or global) and handles +=
954 // returns 0 on error, else sh_vars of new entry. Adds at ff if not found.
setvar_long(char * s,int freeable,struct sh_fcall * ff)955 static struct sh_vars *setvar_long(char *s, int freeable, struct sh_fcall *ff)
956 {
957   struct sh_vars *vv = 0, *was;
958   char *ss;
959 
960   if (!s) return 0;
961   ss = varend(s);
962   if (ss[*ss=='+']!='=') {
963     error_msg("bad setvar %s\n", s);
964     if (freeable) free(s);
965 
966     return 0;
967   }
968 
969   // Add if necessary, set value, and remove again if we added but set failed
970   if (!(was = vv = findvar(s, &ff))) (vv = addvar(s, ff))->flags = VAR_NOFREE;
971   if (!setvar_found(s, freeable, vv)) {
972     if (!was) memmove(vv, vv+1, sizeof(ff->vars)*(--ff->varslen-(vv-ff->vars)));
973 
974     return 0;
975   }
976   cache_ifs(vv->str, ff);
977 
978   return vv;
979 }
980 
981 // Set variable via a malloced "name=value" (or "name+=value") string.
982 // Returns sh_vars * or 0 for failure (readonly, etc)
setvar(char * str)983 static struct sh_vars *setvar(char *str)
984 {
985   return setvar_long(str, 1, TT.ff->prev);
986 }
987 
988 
989 // returns whether variable found (whiteout doesn't count)
unsetvar(char * name)990 static int unsetvar(char *name)
991 {
992   struct sh_fcall *ff;
993   struct sh_vars *var = findvar(name, &ff);
994   int len = varend(name)-name;
995 
996   if (!var || (var->flags&VAR_WHITEOUT)) return 0;
997   if (var->flags&VAR_READONLY) error_msg("readonly %.*s", len, name);
998   else {
999     // turn local into whiteout
1000     if (ff != TT.ff->prev) {
1001       var->flags = VAR_WHITEOUT;
1002       if (!(var->flags&VAR_NOFREE))
1003         (var->str = xrealloc(var->str, len+2))[len+1] = 0;
1004     // free from global context
1005     } else {
1006       if (!(var->flags&VAR_NOFREE)) free(var->str);
1007       memmove(var, var+1, sizeof(ff->vars)*(ff->varslen-- -(var-ff->vars)));
1008     }
1009     if (!strcmp(name, "IFS"))
1010       do ff->ifs = " \t\n"; while ((ff = ff->next) != TT.ff->prev);
1011   }
1012 
1013   return 1;
1014 }
1015 
setvarval(char * name,char * val)1016 static struct sh_vars *setvarval(char *name, char *val)
1017 {
1018   return setvar(xmprintf("%s=%s", name, val));
1019 }
1020 
1021 // TODO: keep variable arrays sorted for binary search
1022 
1023 // create array of variables visible in current function.
visible_vars(void)1024 static struct sh_vars **visible_vars(void)
1025 {
1026   struct sh_arg arg;
1027   struct sh_fcall *ff;
1028   struct sh_vars *vv;
1029   unsigned ii, jj, len;
1030 
1031   arg.c = 0;
1032   arg.v = 0;
1033 
1034   // Find non-duplicate entries: TODO, sort and binary search
1035   for (ff = TT.ff; ; ff = ff->next) {
1036     if (ff->vars) for (ii = ff->varslen; ii--;) {
1037       vv = ff->vars+ii;
1038       len = 1+(varend(vv->str)-vv->str);
1039       for (jj = 0; ;jj++) {
1040         if (jj == arg.c) arg_add(&arg, (void *)vv);
1041         else if (strncmp(arg.v[jj], vv->str, len)) continue;
1042 
1043         break;
1044       }
1045     }
1046     if (ff->next == TT.ff) break;
1047   }
1048 
1049   return (void *)arg.v;
1050 }
1051 
1052 // malloc declare -x "escaped string"
declarep(struct sh_vars * var)1053 static char *declarep(struct sh_vars *var)
1054 {
1055   char *types = "rxnuliaA", *esc = "$\"\\`", *in, flags[16], *out = flags, *ss;
1056   int len;
1057 
1058   for (len = 0; types[len]; len++) if (var->flags&(2<<len)) *out++ = types[len];
1059   if (out==flags) *out++ = '-';
1060   *out = 0;
1061   len = out-flags;
1062 
1063   for (in = var->str; *in; in++) len += !!strchr(esc, *in);
1064   len += in-var->str;
1065   ss = xmalloc(len+15);
1066 
1067   len = varend(var->str)-var->str;
1068   out = ss + sprintf(ss, "declare -%s %.*s", flags, len, var->str);
1069   if (var->flags != VAR_MAGIC)  {
1070     out = stpcpy(out, "=\"");
1071     for (in = var->str+len+1; *in; *out++ = *in++)
1072       if (strchr(esc, *in)) *out++ = '\\';
1073     *out++ = '"';
1074   }
1075   *out = 0;
1076 
1077   return ss;
1078 }
1079 
1080 // Skip past valid prefix that could go before redirect
skip_redir_prefix(char * word)1081 static char *skip_redir_prefix(char *word)
1082 {
1083   char *s = word;
1084 
1085   if (*s == '{') {
1086     if (*(s = varend(s+1)) == '}' && s != word+1) s++;
1087     else s = word;
1088   } else while (isdigit(*s)) s++;
1089 
1090   return s;
1091 }
1092 
1093 // parse next word from command line. Returns end, or 0 if need continuation
1094 // caller eats leading spaces. early = skip one quote block (or return start)
parse_word(char * start,int early)1095 static char *parse_word(char *start, int early)
1096 {
1097   int ii, qq, qc = 0, quote = 0;
1098   char *end = start, *ss;
1099 
1100   // Handle redirections, <(), (( )) that only count at the start of word
1101   ss = skip_redir_prefix(end); // 123<<file- parses as 2 args: "123<<" "file-"
1102   if (strstart(&ss, "<(") || strstart(&ss, ">(")) {
1103     toybuf[quote++]=')';
1104     end = ss;
1105   } else if ((ii = anystart(ss, (void *)redirectors))) return ss+ii;
1106   if (strstart(&end, "((")) toybuf[quote++] = 254;
1107 
1108   // Loop to find end of this word
1109   while (*end) {
1110     // If we're stopping early and already handled a symbol...
1111     if (early && end!=start && !quote) break;
1112 
1113     // barf if we're near overloading quote stack (nesting ridiculously deep)
1114     if (quote>4000) {
1115       syntax_err("bad quote depth");
1116       return (void *)1;
1117     }
1118 
1119     // Are we in a quote context?
1120     if ((qq = quote ? toybuf[quote-1] : 0)) {
1121       ii = *end++;
1122       if ((qq==')' || qq>=254) && (ii=='(' || ii==')')) { // parentheses nest
1123         if (ii=='(') qc++;
1124         else if (qc) qc--;
1125         else if (qq>=254) {
1126           // (( can end with )) or retroactively become two (( if we hit one )
1127           if (ii==')' && *end==')') quote--, end++;
1128           else if (qq==254) return start+1;
1129           else if (qq==255) toybuf[quote-1] = ')';
1130         } else if (ii==')') quote--;
1131       } else if (ii==(qq&127)) quote--;        // matching end quote
1132       else if (qq!='\'') end--, ii = 0;  // single quote claims everything
1133       if (ii) continue;                  // fall through for other quote types
1134 
1135     // space and flow control chars only end word when not quoted in any way
1136     } else {
1137       if (isspace(*end)) break;
1138       ss = end + anystart(end, (char *[]){";;&", ";;", ";&", ";", "||",
1139         "|&", "|", "&&", "&", "(", ")", 0});
1140       if (ss==end) ss += anystart(end, (void *)redirectors);
1141       if (ss!=end) return (end==start) ? ss : end;
1142     }
1143 
1144     // start new quote context? (' not special within ")
1145     if (strchr("'\"`"+(qq=='"'), ii = *end++)) toybuf[quote++] = ii;
1146 
1147     // \? $() ${} $[] ?() *() +() @() !()
1148     else {
1149       if (ii=='$' && qq != 0247 && -1!=(qq = stridx("({['", *end))) {
1150         if (strstart(&end, "((")) {
1151           end--;
1152           toybuf[quote++] = 255;
1153         } else toybuf[quote++] = ")}]\247"[qq]; // last is '+128
1154       } else if (*end=='(' && strchr("?*+@!", ii)) toybuf[quote++] = ')';
1155       else {
1156         if (ii!='\\') end--;
1157         else if (!end[*end=='\n']) return (*end && !early) ? 0 : end;
1158         if (early && !quote) return end;
1159       }
1160       end++;
1161     }
1162   }
1163 
1164   return (quote && !early) ? 0 : end;
1165 }
1166 
1167 // Return next available high (>=10) file descriptor
next_hfd()1168 static int next_hfd()
1169 {
1170   int hfd;
1171 
1172   for (; TT.hfd<=99999; TT.hfd++) if (-1 == fcntl(TT.hfd, F_GETFL)) break;
1173   hfd = TT.hfd;
1174   if (TT.hfd>99999) {
1175     hfd = -1;
1176     if (!errno) errno = EMFILE;
1177   }
1178 
1179   return hfd;
1180 }
1181 
1182 // Perform a redirect, saving displaced filehandle to a high (>10) fd
1183 // rd is an int array: [0] = count, followed by from/to pairs to restore later.
1184 // If from >= 0 dup from->to after saving to. If from == -1 just save to.
1185 // if from == -2 schedule "to" to be closed by unredirect.
save_redirect(int ** rd,int from,int to)1186 static int save_redirect(int **rd, int from, int to)
1187 {
1188   int cnt, hfd, *rr;
1189 
1190 //dprintf(2, "%d redir %d to %d\n", getpid(), from, to);
1191   if (from == to) return 0;
1192   // save displaced to, copying to high (>=10) file descriptor to undo later
1193   // except if we're saving to environment variable instead (don't undo that)
1194   if (from>-2) {
1195     if ((hfd = next_hfd())==-1) return 1;
1196     if (hfd != dup2(to, hfd)) hfd = -1;
1197     else fcntl(hfd, F_SETFD, FD_CLOEXEC);
1198 
1199     // dup "to"
1200     if (from >= 0 && to != dup2(from, to)) {
1201       if (hfd >= 0) close(hfd);
1202 
1203       return 1;
1204     }
1205   } else {
1206     hfd = to;
1207     to = -1;
1208   }
1209 
1210   // Append undo information to redirect list so we can restore saved hfd later.
1211   if (!((cnt = *rd ? **rd : 0)&31)) *rd = xrealloc(*rd, (cnt+33)*2*sizeof(int));
1212   *(rr = *rd) = ++cnt;
1213   rr[2*cnt-1] = hfd;
1214   rr[2*cnt] = to;
1215 
1216   return 0;
1217 }
1218 
1219 // restore displaced filehandles, closing high filehandles they were copied to
unredirect(int * urd)1220 static void unredirect(int *urd)
1221 {
1222   int *rr = urd+1, i;
1223 
1224   if (!urd) return;
1225 
1226   for (i = 0; i<*urd; i++, rr += 2) if (rr[0] != -1) {
1227     // No idea what to do about fd exhaustion here, so Steinbach's Guideline.
1228     dup2(rr[0], rr[1]);
1229     close(rr[0]);
1230   }
1231   free(urd);
1232 }
1233 
1234 // TODO: waitpid(WNOHANG) to clean up zombies and catch background& ending
subshell_callback(char ** argv)1235 static void subshell_callback(char **argv)
1236 {
1237   int i;
1238 
1239   // Don't leave open filehandles to scripts in children
1240   for (i = 0; i<TT.recursion; i++)  if (TT.recfile[i]>0) close(TT.recfile[i]);
1241 
1242   // This depends on environ having been replaced by caller
1243   environ[1] = xmprintf("@%d,%d", getpid(), getppid());
1244   environ[2] = xmprintf("$=%d", TT.pid);
1245 // TODO: test $$ in (nommu)
1246 }
1247 
1248 // TODO what happens when you background a function?
1249 // turn a parsed pipeline back into a string.
pl2str(struct sh_pipeline * pl,int one)1250 static char *pl2str(struct sh_pipeline *pl, int one)
1251 {
1252   struct sh_pipeline *end = 0, *pp;
1253   int len QUIET, i;
1254   char *ss;
1255 
1256   // Find end of block (or one argument)
1257   if (one) end = pl->next;
1258   else for (end = pl, len = 0; end; end = end->next)
1259     if (end->type == 1) len++;
1260     else if (end->type == 3 && --len<0) break;
1261 
1262   // measure, then allocate
1263   for (ss = 0;; ss = xmalloc(len+1)) {
1264     for (pp = pl; pp != end; pp = pp->next) {
1265       if (pp->type == 'F') continue; // TODO fix this
1266       for (i = len = 0; i<=pp->arg->c; i++)
1267         len += snprintf(ss+len, ss ? INT_MAX : 0, " %s"+!i,
1268            pp->arg->v[i] ? : ";"+(pp->next==end));
1269     }
1270     if (ss) return ss;
1271   }
1272 
1273 // TODO test output with case and function
1274 // TODO add HERE documents back in
1275 // TODO handle functions
1276 }
1277 
clear_block(struct sh_blockstack * blk)1278 static struct sh_blockstack *clear_block(struct sh_blockstack *blk)
1279 {
1280   memset(blk, 0, sizeof(*blk));
1281   blk->start = TT.ff->pl;
1282   blk->run = 1;
1283   blk->pout = -1;
1284 
1285   return blk;
1286 }
1287 
1288 // when ending a block, free, cleanup redirects and pop stack.
pop_block(void)1289 static struct sh_pipeline *pop_block(void)
1290 {
1291   struct sh_pipeline *pl = 0;
1292   struct sh_blockstack *blk = TT.ff->blk;
1293 
1294   // when ending a block, free, cleanup redirects and pop stack.
1295   if (blk->pout != -1) close(blk->pout);
1296   unredirect(blk->urd);
1297   llist_traverse(blk->fdelete, llist_free_arg);
1298   free(blk->farg.v);
1299   if (TT.ff->blk->next) {
1300     pl = blk->start->end;
1301     free(llist_pop(&TT.ff->blk));
1302   } else clear_block(blk);
1303 
1304   return pl;
1305 }
1306 
1307 // Push a new empty block to the stack
add_block(void)1308 static void add_block(void)
1309 {
1310   struct sh_blockstack *blk = clear_block(xmalloc(sizeof(*blk)));
1311 
1312   blk->next = TT.ff->blk;
1313   TT.ff->blk = blk;
1314 }
1315 
1316 // Add entry to runtime function call stack
call_function(void)1317 static void call_function(void)
1318 {
1319   // dlist in reverse order: TT.ff = current function, TT.ff->prev = globals
1320   dlist_add_nomalloc((void *)&TT.ff, xzalloc(sizeof(struct sh_fcall)));
1321   TT.ff = TT.ff->prev;
1322   add_block();
1323 
1324 // TODO caller needs to set pl, vars, func
1325   // default $* is to copy previous
1326   TT.ff->arg.v = TT.ff->next->arg.v;
1327   TT.ff->arg.c = TT.ff->next->arg.c;
1328   TT.ff->ifs = TT.ff->next->ifs;
1329 }
1330 
free_function(struct sh_function * funky)1331 static void free_function(struct sh_function *funky)
1332 {
1333   if (!funky || --funky->refcount) return;
1334 
1335   free(funky->name);
1336   llist_traverse(funky->pipeline, free_pipeline);
1337   free(funky);
1338 }
1339 
1340 // TODO: old function-vs-source definition is "has variables", but no ff->func?
1341 // returns 0 if source popped, nonzero if function popped
end_fcall(int funconly)1342 static int end_fcall(int funconly)
1343 {
1344   struct sh_fcall *ff = TT.ff;
1345   int func = ff->next!=ff && ff->vars;
1346 
1347   if (!func && funconly) return 0;
1348   llist_traverse(ff->delete, llist_free_arg);
1349   ff->delete = 0;
1350   while (ff->blk->next) pop_block();
1351   pop_block();
1352 
1353   // for a function, free variables and pop context
1354   if (!func) return 0;
1355   while (ff->varslen)
1356     if (!(ff->vars[--ff->varslen].flags&VAR_NOFREE))
1357       free(ff->vars[ff->varslen].str);
1358   free(ff->vars);
1359   free(ff->blk);
1360   free_function(ff->func);
1361   free(dlist_pop(&TT.ff));
1362 
1363   return 1;
1364 }
1365 
1366 // TODO check every caller of run_subshell for error, or syntax_error() here
1367 // from pipe() failure
1368 
1369 // TODO need CLOFORK? CLOEXEC doesn't help if we don't exec...
1370 
1371 // Pass environment and command string to child shell, return PID of child
run_subshell(char * str,int len)1372 static int run_subshell(char *str, int len)
1373 {
1374   pid_t pid;
1375 //dprintf(2, "%d run_subshell %.*s\n", getpid(), len, str); debug_show_fds();
1376   // The with-mmu path is significantly faster.
1377   if (CFG_TOYBOX_FORK) {
1378     if ((pid = fork())<0) perror_msg("fork");
1379     else if (!pid) {
1380       call_function();
1381       if (str) {
1382         do_source(0, fmemopen(str, len, "r"));
1383         _exit(toys.exitval);
1384       }
1385     }
1386 
1387   // On nommu vfork, exec /proc/self/exe, and pipe state data to ourselves.
1388   } else {
1389     int pipes[2];
1390     unsigned i;
1391     char **oldenv = environ, *ss = str ? : pl2str(TT.ff->pl->next, 0);
1392     struct sh_vars **vv;
1393 
1394     // open pipe to child
1395     if (pipe(pipes) || 254 != dup2(pipes[0], 254)) return 1;
1396     close(pipes[0]);
1397     fcntl(pipes[1], F_SETFD, FD_CLOEXEC);
1398 
1399     // vfork child with clean environment
1400     environ = xzalloc(4*sizeof(char *));
1401     *environ = getvar("PATH") ? : "PATH=";
1402     pid = xpopen_setup(0, 0, subshell_callback);
1403 // TODO what if pid -1? Handle process exhaustion.
1404     // free entries added to end of environment by callback (shared heap)
1405     free(environ[1]);
1406     free(environ[2]);
1407     free(environ);
1408     environ = oldenv;
1409 
1410     // marshall context to child
1411     close(254);
1412     dprintf(pipes[1], "%lld %u %u %u %u\n", TT.SECONDS,
1413       TT.options, TT.LINENO, TT.pid, TT.bangpid);
1414 
1415     for (i = 0, vv = visible_vars(); vv[i]; i++)
1416       dprintf(pipes[1], "%u %lu\n%.*s", (unsigned)strlen(vv[i]->str),
1417               vv[i]->flags, (int)strlen(vv[i]->str), vv[i]->str);
1418     free(vv);
1419 
1420     // send command
1421     dprintf(pipes[1], "0 0\n%.*s\n", len, ss);
1422     if (!str) free(ss);
1423     close(pipes[1]);
1424   }
1425 
1426   return pid;
1427 }
1428 
1429 // Call subshell with either stdin/stdout redirected, return other end of pipe
pipe_subshell(char * s,int len,int out)1430 static int pipe_subshell(char *s, int len, int out)
1431 {
1432   int pipes[2], *uu = 0, in = !out;
1433 
1434   // Grab subshell data
1435   if (pipe(pipes)) {
1436     perror_msg("%.*s", len, s);
1437 
1438     return -1;
1439   }
1440 
1441   // Perform input or output redirect and launch process (ignoring errors)
1442   save_redirect(&uu, pipes[in], in);
1443   close(pipes[in]);
1444   fcntl(pipes[!in], F_SETFD, FD_CLOEXEC);
1445   run_subshell(s, len);
1446   fcntl(pipes[!in], F_SETFD, 0);
1447   unredirect(uu);
1448 
1449   return pipes[out];
1450 }
1451 
1452 // grab variable or special param (ala $$) up to len bytes. Return value.
1453 // set *used to length consumed. Does not handle $* and $@
getvar_special(char * str,int len,int * used,struct arg_list ** delete)1454 char *getvar_special(char *str, int len, int *used, struct arg_list **delete)
1455 {
1456   char *s = 0, *ss, cc = *str;
1457   unsigned uu;
1458 
1459   *used = 1;
1460   if (cc == '-') {
1461     s = ss = xmalloc(8);
1462     if (TT.options&FLAG_i) *ss++ = 'i';
1463     if (TT.options&OPT_B) *ss++ = 'B';
1464     if (TT.options&FLAG_s) *ss++ = 's';
1465     if (TT.options&FLAG_c) *ss++ = 'c';
1466     *ss = 0;
1467   } else if (cc == '?') s = xmprintf("%d", toys.exitval);
1468   else if (cc == '$') s = xmprintf("%d", TT.pid);
1469   else if (cc == '#') s = xmprintf("%d", TT.ff->arg.c ? TT.ff->arg.c-1 : 0);
1470   else if (cc == '!') s = xmprintf("%d"+2*!TT.bangpid, TT.bangpid);
1471   else {
1472     delete = 0;
1473     for (*used = uu = 0; *used<len && isdigit(str[*used]); ++*used)
1474       uu = (10*uu)+str[*used]-'0';
1475     if (*used) {
1476       if (uu) uu += TT.ff->shift;
1477       if (uu<TT.ff->arg.c) s = TT.ff->arg.v[uu];
1478     } else if ((*used = varend(str)-str)) return getvar(str);
1479   }
1480   if (s) push_arg(delete, s);
1481 
1482   return s;
1483 }
1484 
1485 #define WILD_SHORT 1 // else longest match
1486 #define WILD_CASE  2 // case insensitive
1487 #define WILD_ANY   4 // advance through pattern instead of str
1488 // Returns length of str matched by pattern, or -1 if not all pattern consumed
wildcard_matchlen(char * str,int len,char * pattern,int plen,struct sh_arg * deck,int flags)1489 static int wildcard_matchlen(char *str, int len, char *pattern, int plen,
1490   struct sh_arg *deck, int flags)
1491 {
1492   struct sh_arg ant = {0};    // stack: of str offsets
1493   long ss, pp, dd, best = -1;
1494   int i, j, c, not;
1495 
1496   // Loop through wildcards in pattern.
1497   for (ss = pp = dd = 0; ;) {
1498     if ((flags&WILD_ANY) && best!=-1) break;
1499 
1500     // did we consume pattern?
1501     if (pp==plen) {
1502       if (ss>best) best = ss;
1503       if (ss==len || (flags&WILD_SHORT)) break;
1504     // attempt literal match?
1505     } else if (dd>=deck->c || pp!=(long)deck->v[dd]) {
1506       if (ss<len) {
1507         if (flags&WILD_CASE) {
1508           ss += getutf8(str+ss, len-ss, &c);
1509           c = towupper(c);
1510           pp += getutf8(pattern+pp, pp-plen, &i);
1511           i = towupper(i);
1512         } else c = str[ss++], i = pattern[pp++];
1513         if (c==i) continue;
1514       }
1515 
1516     // Wildcard chars: |+@!*?()[]
1517     } else {
1518       c = pattern[pp++];
1519       dd++;
1520       if (c=='?' || ((flags&WILD_ANY) && c=='*')) {
1521         ss += (i = getutf8(str+ss, len-ss, 0));
1522         if (i) continue;
1523       } else if (c=='*') {
1524 
1525         // start with zero length match, don't record consecutive **
1526         if (dd==1 || pp-2!=(long)deck->v[dd-1] || pattern[pp-2]!='*') {
1527           arg_add(&ant, (void *)ss);
1528           arg_add(&ant, 0);
1529         }
1530 
1531         continue;
1532       } else if (c == '[') {
1533         pp += (not = !!strchr("!^", pattern[pp]));
1534         ss += getutf8(str+ss, len-ss, &c);
1535         for (i = 0; pp<(long)deck->v[dd]; i = 0) {
1536           pp += getutf8(pattern+pp, plen-pp, &i);
1537           if (pattern[pp]=='-') {
1538             ++pp;
1539             pp += getutf8(pattern+pp, plen-pp, &j);
1540             if (not^(i<=c && j>=c)) break;
1541           } else if (not^(i==c)) break;
1542         }
1543         if (i) {
1544           pp = 1+(long)deck->v[dd++];
1545 
1546           continue;
1547         }
1548 
1549       // ( preceded by +@!*?
1550 
1551       } else { // TODO ( ) |
1552         dd++;
1553         continue;
1554       }
1555     }
1556 
1557     // match failure
1558     if (flags&WILD_ANY) {
1559       ss = 0;
1560       if (plen==pp) break;
1561       continue;
1562     }
1563 
1564     // pop retry stack or return failure (TODO: seek to next | in paren)
1565     while (ant.c) {
1566       if ((c = pattern[(long)deck->v[--dd]])=='*') {
1567         if (len<(ss = (long)ant.v[ant.c-2]+(long)++ant.v[ant.c-1])) ant.c -= 2;
1568         else {
1569           pp = (long)deck->v[dd++]+1;
1570           break;
1571         }
1572       } else if (c == '(') dprintf(2, "TODO: (");
1573     }
1574 
1575     if (!ant.c) break;
1576   }
1577   free (ant.v);
1578 
1579   return best;
1580 }
1581 
wildcard_match(char * s,char * p,struct sh_arg * deck,int flags)1582 static int wildcard_match(char *s, char *p, struct sh_arg *deck, int flags)
1583 {
1584   return wildcard_matchlen(s, strlen(s), p, strlen(p), deck, flags);
1585 }
1586 
1587 
1588 // TODO: test that * matches ""
1589 
1590 // skip to next slash in wildcard path, passing count active ranges.
1591 // start at pattern[off] and deck[*idx], return pattern pos and update *idx
wildcard_path(char * pattern,int off,struct sh_arg * deck,int * idx,int count)1592 char *wildcard_path(char *pattern, int off, struct sh_arg *deck, int *idx,
1593   int count)
1594 {
1595   char *p, *old;
1596   int i = 0, j = 0;
1597 
1598   // Skip [] and nested () ranges within deck until / or NUL
1599   for (p = old = pattern+off;; p++) {
1600     if (!*p) return p;
1601     while (*p=='/') {
1602       old = p++;
1603       if (j && !count) return old;
1604       j = 0;
1605     }
1606 
1607     // Got wildcard? Return start of name if out of count, else skip [] ()
1608     if (*idx<deck->c && p-pattern == (long)deck->v[*idx]) {
1609       if (!j++ && !count--) return old;
1610       ++*idx;
1611       if (*p=='[') p = pattern+(long)deck->v[(*idx)++];
1612       else if (*p=='(') while (*++p) if (p-pattern == (long)deck->v[*idx]) {
1613         ++*idx;
1614         if (*p == ')') {
1615           if (!i) break;
1616           i--;
1617         } else if (*p == '(') i++;
1618       }
1619     }
1620   }
1621 }
1622 
1623 // TODO ** means this directory as well as ones below it, shopt -s globstar
1624 
1625 // Filesystem traversal callback
1626 // pass on: filename, portion of deck, portion of pattern,
1627 // input: pattern+offset, deck+offset. Need to update offsets.
do_wildcard_files(struct dirtree * node)1628 int do_wildcard_files(struct dirtree *node)
1629 {
1630   struct dirtree *nn;
1631   char *pattern, *patend;
1632   int lvl, ll = 0, ii = 0, rc;
1633   struct sh_arg ant;
1634 
1635   // Top level entry has no pattern in it
1636   if (!node->parent) return DIRTREE_RECURSE;
1637 
1638   // Find active pattern range
1639   for (nn = node->parent; nn; nn = nn->parent) if (nn->parent) ii++;
1640   pattern = wildcard_path(TT.wcpat, 0, TT.wcdeck, &ll, ii);
1641   while (*pattern=='/') pattern++;
1642   lvl = ll;
1643   patend = wildcard_path(TT.wcpat, pattern-TT.wcpat, TT.wcdeck, &ll, 1);
1644 
1645   // Don't include . entries unless explicitly asked for them
1646   if (*node->name=='.' && *pattern!='.') return 0;
1647 
1648   // Don't descend into non-directory (was called with DIRTREE_SYMFOLLOW)
1649   if (*patend && !S_ISDIR(node->st.st_mode) && *node->name) return 0;
1650 
1651   // match this filename from pattern to p in deck from lvl to ll
1652   ant.c = ll-lvl;
1653   ant.v = TT.wcdeck->v+lvl;
1654   for (ii = 0; ii<ant.c; ii++) TT.wcdeck->v[lvl+ii] -= pattern-TT.wcpat;
1655   rc = wildcard_matchlen(node->name, strlen(node->name), pattern,
1656     patend-pattern, &ant, 0);
1657   for (ii = 0; ii<ant.c; ii++) TT.wcdeck->v[lvl+ii] += pattern-TT.wcpat;
1658 
1659   // Return failure or save exact match.
1660   if (rc<0 || node->name[rc]) return 0;
1661   if (!*patend) return DIRTREE_SAVE;
1662 
1663   // Are there more wildcards to test children against?
1664   if (TT.wcdeck->c!=ll) return DIRTREE_RECURSE;
1665 
1666   // No more wildcards: check for child and return failure if it isn't there.
1667   pattern = xmprintf("%s%s", node->name, patend);
1668   rc = faccessat(dirtree_parentfd(node), pattern, F_OK, AT_SYMLINK_NOFOLLOW);
1669   free(pattern);
1670   if (rc) return 0;
1671 
1672   // Save child and self. (Child could be trailing / but only one saved.)
1673   while (*patend=='/' && patend[1]) patend++;
1674   node->child = xzalloc(sizeof(struct dirtree)+1+strlen(patend));
1675   node->child->parent = node;
1676   strcpy(node->child->name, patend);
1677 
1678   return DIRTREE_SAVE;
1679 }
1680 
1681 // Record active wildcard chars in output string
1682 // *new start of string, oo offset into string, deck is found wildcards,
collect_wildcards(char * new,long oo,struct sh_arg * deck)1683 static void collect_wildcards(char *new, long oo, struct sh_arg *deck)
1684 {
1685   long bracket, *vv;
1686   char cc = new[oo];
1687 
1688   // Record unescaped/unquoted wildcard metadata for later processing
1689 
1690   if (!deck->c) arg_add(deck, 0);
1691   vv = (long *)deck->v;
1692 
1693   // vv[0] used for paren level (bottom 16 bits) + bracket start offset<<16
1694 
1695   // at end loop backwards through live wildcards to remove pending unmatched (
1696   if (!cc) {
1697     long ii = 0, jj = 65535&*vv, kk;
1698 
1699     for (kk = deck->c; jj;) {
1700       if (')' == (cc = new[vv[--kk]])) ii++;
1701       else if ('(' == cc) {
1702         if (ii) ii--;
1703         else {
1704           memmove(vv+kk, vv+kk+1, sizeof(long)*(deck->c-- -kk));
1705           jj--;
1706         }
1707       }
1708     }
1709     if (deck->c) memmove(vv, vv+1, sizeof(long)*deck->c--);
1710 
1711     return;
1712   }
1713 
1714   // Start +( range, or remove first char that isn't wildcard without (
1715   if (deck->c>1 && vv[deck->c-1] == oo-1 && strchr("+@!*?", new[oo-1])) {
1716     if (cc == '(') {
1717       vv[deck->c-1] = oo;
1718       return;
1719     } else if (!strchr("*?", new[oo-1])) deck->c--;
1720   }
1721 
1722   // fall through to add wildcard, popping parentheses stack as necessary
1723   if (strchr("|+@!*?", cc));
1724   else if (cc == ')' && (65535&*vv)) --*vv;
1725 
1726   // complete [range], discard wildcards within, add [, fall through to add ]
1727   else if (cc == ']' && (bracket = *vv>>16)) {
1728 
1729     // don't end range yet for [] or [^]
1730     if (bracket+1 == oo || (bracket+2 == oo && strchr("!^", new[oo-1]))) return;
1731     while (deck->c>1 && vv[deck->c-1]>=bracket) deck->c--;
1732     *vv &= 65535;
1733     arg_add(deck, (void *)bracket);
1734 
1735   // Not a wildcard
1736   } else {
1737     // [ is speculative, don't add to deck yet, just record we saw it
1738     if (cc == '[' && !(*vv>>16)) *vv = (oo<<16)+(65535&*vv);
1739     return;
1740   }
1741 
1742   // add active wildcard location
1743   arg_add(deck, (void *)oo);
1744 }
1745 
1746 // wildcard expand data against filesystem, and add results to arg list
1747 // Note: this wildcard deck has extra argument at start (leftover from parsing)
wildcard_add_files(struct sh_arg * arg,char * pattern,struct sh_arg * deck,struct arg_list ** delete)1748 static void wildcard_add_files(struct sh_arg *arg, char *pattern,
1749   struct sh_arg *deck, struct arg_list **delete)
1750 {
1751   struct dirtree *dt;
1752   char *pp;
1753   int ll = 0;
1754 
1755   // fast path: when no wildcards, add pattern verbatim
1756   collect_wildcards("", 0, deck);
1757   if (!deck->c) return arg_add(arg, pattern);
1758 
1759   // Traverse starting with leading patternless path.
1760   pp = wildcard_path(TT.wcpat = pattern, 0, TT.wcdeck = deck, &ll, 0);
1761   pp = (pp==pattern) ? 0 : xstrndup(pattern, pp-pattern);
1762   dt = dirtree_flagread(pp, DIRTREE_STATLESS|DIRTREE_SYMFOLLOW,
1763     do_wildcard_files);
1764   free(pp);
1765   deck->c = 0;
1766 
1767   // If no match save pattern, else free tree saving each path found.
1768   if (!dt) return arg_add(arg, pattern);
1769   while (dt) {
1770     while (dt->child) dt = dt->child;
1771     arg_add(arg, push_arg(delete, dirtree_path(dt, 0)));
1772     do {
1773       pp = (void *)dt;
1774       if ((dt = dt->parent)) dt->child = dt->child->next;
1775       free(pp);
1776     } while (dt && !dt->child);
1777   }
1778 // TODO: test .*/../
1779 }
1780 
1781 // Copy string until } including escaped }
1782 // if deck collect wildcards, and store terminator at deck->v[deck->c]
slashcopy(char * s,char * c,struct sh_arg * deck)1783 char *slashcopy(char *s, char *c, struct sh_arg *deck)
1784 {
1785   char *ss;
1786   long ii, jj;
1787 
1788   for (ii = 0; !strchr(c, s[ii]); ii++) if (s[ii] == '\\') ii++;
1789   ss = xmalloc(ii+1);
1790   for (ii = jj = 0; !strchr(c, s[jj]); ii++)
1791     if ('\\'==(ss[ii] = s[jj++])) ss[ii] = s[jj++];
1792     else if (deck) collect_wildcards(ss, ii, deck);
1793   ss[ii] = 0;
1794   if (deck) {
1795     arg_add(deck, 0);
1796     deck->v[--deck->c] = (void *)jj;
1797     collect_wildcards("", 0, deck);
1798   }
1799 
1800   return ss;
1801 }
1802 
1803 #define NO_QUOTE (1<<0)    // quote removal
1804 #define NO_PATH  (1<<1)    // path expansion (wildcards)
1805 #define NO_SPLIT (1<<2)    // word splitting
1806 #define NO_BRACE (1<<3)    // {brace,expansion}
1807 #define NO_TILDE (1<<4)    // ~username/path
1808 #define NO_NULL  (1<<5)    // Expand to "" instead of NULL
1809 #define SEMI_IFS (1<<6)    // Use ' ' instead of IFS to combine $*
1810 // expand str appending to arg using above flag defines, add mallocs to delete
1811 // if ant not null, save wildcard deck there instead of expanding vs filesystem
1812 // returns 0 for success, 1 for error.
1813 // If measure stop at *measure and return input bytes consumed in *measure
expand_arg_nobrace(struct sh_arg * arg,char * str,unsigned flags,struct arg_list ** delete,struct sh_arg * ant,long * measure)1814 static int expand_arg_nobrace(struct sh_arg *arg, char *str, unsigned flags,
1815   struct arg_list **delete, struct sh_arg *ant, long *measure)
1816 {
1817   char cc, qq = flags&NO_QUOTE, sep[6], *new = str, *s, *ss = ss, *ifs, *slice;
1818   int ii = 0, oo = 0, xx, yy, dd, jj, kk, ll, mm;
1819   struct sh_arg deck = {0};
1820 
1821   // Tilde expansion
1822   if (!(flags&NO_TILDE) && *str == '~') {
1823     struct passwd *pw = 0;
1824 
1825     ss = 0;
1826     while (str[ii] && str[ii]!=':' && str[ii]!='/') ii++;
1827     if (ii==1) {
1828       if (!(ss = getvar("HOME")) || !*ss) pw = bufgetpwuid(getuid());
1829     } else {
1830       // TODO bufgetpwnam
1831       pw = getpwnam(s = xstrndup(str+1, ii-1));
1832       free(s);
1833     }
1834     if (pw) {
1835       ss = pw->pw_dir;
1836       if (!ss || !*ss) ss = "/";
1837     }
1838     if (ss) {
1839       oo = strlen(ss);
1840       s = xmprintf("%s%s", ss, str+ii);
1841       if (str != new) free(new);
1842       new = s;
1843     }
1844   }
1845 
1846   // parameter/variable expansion and dequoting
1847   if (!ant) ant = &deck;
1848   for (; (cc = str[ii++]); str!=new && (new[oo] = 0)) {
1849     struct sh_arg aa = {0};
1850     int nosplit = 0;
1851 
1852     if (measure && cc==*measure) break;
1853 
1854     // skip literal chars
1855     if (!strchr("'\"\\$`"+2*(flags&NO_QUOTE), cc)) {
1856       if (str != new) new[oo] = cc;
1857       if (!(flags&NO_PATH) && !(qq&1)) collect_wildcards(new, oo, ant);
1858       oo++;
1859       continue;
1860     }
1861 
1862     // allocate snapshot if we just started modifying
1863     if (str == new) {
1864       new = xstrdup(new);
1865       new[oo] = 0;
1866     }
1867     ifs = slice = 0;
1868 
1869     // handle escapes and quoting
1870     if (cc == '"') qq++;
1871     else if (cc == '\'') {
1872       if (qq&1) new[oo++] = cc;
1873       else {
1874         qq += 2;
1875         while ((cc = str[ii++]) != '\'') new[oo++] = cc;
1876       }
1877 
1878     // both types of subshell work the same, so do $( here not in '$' below
1879 // TODO $((echo hello) | cat) ala $(( becomes $( ( retroactively
1880     } else if (cc == '`' || (cc == '$' && (str[ii]=='(' || str[ii]=='['))) {
1881       off_t pp = 0;
1882 
1883       s = str+ii-1;
1884       kk = parse_word(s, 1)-s;
1885       if (str[ii] == '[' || *toybuf == 255) { // (( parsed together, not (( ) )
1886         struct sh_arg aa = {0};
1887         long long ll;
1888 
1889         // Expand $VARS in math string
1890         ss = str+ii+1+(str[ii]=='(');
1891         push_arg(delete, ss = xstrndup(ss, kk - (3+2*(str[ii]!='['))));
1892         expand_arg_nobrace(&aa, ss, NO_PATH|NO_SPLIT, delete, 0, 0);
1893         s = ss = (aa.v && *aa.v) ? *aa.v : "";
1894         free(aa.v);
1895 
1896         // Recursively calculate result
1897         if (!recalculate(&ll, &s, 0) || *s) {
1898           error_msg("bad math: %s @ %ld", ss, (long)(s-ss)+1);
1899           goto fail;
1900         }
1901         ii += kk-1;
1902         push_arg(delete, ifs = xmprintf("%lld", ll));
1903       } else {
1904         // Run subshell and trim trailing newlines
1905         s += (jj = 1+(cc == '$'));
1906         ii += --kk;
1907         kk -= jj;
1908 
1909         // Special case echo $(<input)
1910         for (ss = s; isspace(*ss); ss++);
1911         if (*ss != '<') ss = 0;
1912         else {
1913           while (isspace(*++ss));
1914           // Can't return NULL because guaranteed ) context end
1915           if (!(ll = parse_word(ss, 0)-ss)) ss = 0;
1916           else {
1917             jj = ll+(ss-s);
1918             while (isspace(s[jj])) jj++;
1919             if (jj != kk) ss = 0;
1920             else {
1921               jj = xcreate_stdio(ss = xstrndup(ss, ll), O_RDONLY|WARN_ONLY, 0);
1922               free(ss);
1923             }
1924           }
1925         }
1926 
1927 // TODO what does \ in `` mean? What is echo `printf %s \$x` supposed to do?
1928         // This has to be async so pipe buffer doesn't fill up
1929         if (!ss) jj = pipe_subshell(s, kk, 0); // TODO $(true &&) syntax_err()
1930         if ((ifs = readfd(jj, 0, &pp)))
1931           for (kk = strlen(ifs); kk && ifs[kk-1]=='\n'; ifs[--kk] = 0);
1932         close(jj);
1933       }
1934     } else if (!str[ii]) new[oo++] = cc;
1935     else if (cc=='\\') {
1936       if (str[ii]=='\n') ii++;
1937       else new[oo++] = (!(qq&1) || strchr("\"\\$`", str[ii])) ? str[ii++] : cc;
1938     }
1939 
1940     // $VARIABLE expansions
1941 
1942     else if (cc == '$') {
1943       cc = *(ss = str+ii++);
1944       if (cc=='\'') {
1945         for (s = str+ii; *s != '\''; oo += wcrtomb(new+oo, unescape2(&s, 0),0));
1946         ii = s-str+1;
1947 
1948         continue;
1949       } else if (cc=='"' && !(qq&1)) {
1950         qq++;
1951 
1952         continue;
1953       } else if (cc == '{') {
1954 
1955         // Skip escapes to find }, parse_word() guarantees ${} terminates
1956         for (cc = *++ss; str[ii] != '}'; ii++) if (str[ii]=='\\') ii++;
1957         ii++;
1958 
1959         if (cc == '}') ifs = (void *)1;
1960         else if (strchr("#!", cc)) ss++;
1961         if (!(jj = varend(ss)-ss)) while (isdigit(ss[jj])) jj++;
1962         if (!jj && strchr("#$_*", *ss)) jj++;
1963         // parameter or operator? Maybe not a prefix: ${#-} vs ${#-x}
1964         if (!jj && strchr("-?@", *ss)) if (ss[++jj]!='}' && ss[-1]!='{') ss--;
1965         slice = ss+jj;        // start of :operation
1966 
1967         if (!jj) {
1968           // literal ${#} or ${!} wasn't a prefix
1969           if (strchr("#!", cc)) ifs = getvar_special(--ss, 1, &kk, delete);
1970           else ifs = (void *)1;  // unrecognized char ala ${~}
1971         } else if (ss[-1]=='{'); // not prefix, fall through
1972         else if (cc == '#') {  // TODO ${#x[@]}
1973           dd = !!strchr("@*", *ss);  // For ${#@} or ${#*} do normal ${#}
1974           if (!(ifs = getvar_special(ss-dd, jj, &kk, delete))) {
1975             if (TT.options&OPT_u) goto barf;
1976             ifs = "";
1977           }
1978           if (!dd) push_arg(delete, ifs = xmprintf("%zu", strlen(ifs)));
1979         // ${!@} ${!@Q} ${!x} ${!x@} ${!x@Q} ${!x#} ${!x[} ${!x[*]}
1980         } else if (cc == '!') {  // TODO: ${var[@]} array
1981 
1982           // special case: normal varname followed by @} or *} = prefix list
1983           if (ss[jj] == '*' || (ss[jj] == '@' && !isalpha(ss[jj+1]))) {
1984             struct sh_vars **vv = visible_vars();
1985 
1986             for (slice++, kk = 0; vv[kk]; kk++) {
1987               if (vv[kk]->flags&VAR_WHITEOUT) continue;
1988               if (!strncmp(s = vv[kk]->str, ss, jj))
1989                 arg_add(&aa, push_arg(delete, s = xstrndup(s, stridx(s, '='))));
1990             }
1991             if (aa.c) push_arg(delete, aa.v);
1992             free(vv);
1993 
1994           // else dereference to get new varname, discarding if none, check err
1995           } else {
1996             // First expansion
1997             if (strchr("@*", *ss)) { // special case ${!*}/${!@}
1998               expand_arg_nobrace(&aa, "\"$*\"", NO_PATH|NO_SPLIT, delete, 0, 0);
1999               ifs = *aa.v;
2000               free(aa.v);
2001               memset(&aa, 0, sizeof(aa));
2002               jj = 1;
2003             } else ifs = getvar_special(ss, jj, &jj, delete);
2004             slice = ss+jj;
2005 
2006             // Second expansion
2007             if (!jj) ifs = (void *)1;
2008             else if (ifs && *(ss = ifs)) {
2009               if (strchr("@*", cc)) {
2010                 aa.c = TT.ff->arg.c-1;
2011                 aa.v = TT.ff->arg.v+1;
2012                 jj = 1;
2013               } else ifs = getvar_special(ifs, strlen(ifs), &jj, delete);
2014               if (ss && ss[jj]) {
2015                 ifs = (void *)1;
2016                 slice = ss+strlen(ss);
2017               }
2018             }
2019           }
2020         }
2021 
2022         // Substitution error?
2023         if (ifs == (void *)1) {
2024 barf:
2025           if (!(((unsigned long)ifs)>>1)) ifs = "bad substitution";
2026           error_msg("%.*s: %s", (int)(slice-ss), ss, ifs);
2027           goto fail;
2028         }
2029       } else jj = 1;
2030 
2031       // Resolve unprefixed variables
2032       if (strchr("{$", ss[-1])) {
2033         if (strchr("@*", cc)) {
2034           aa.c = TT.ff->arg.c-1;
2035           aa.v = TT.ff->arg.v+1;
2036         } else {
2037           ifs = getvar_special(ss, jj, &jj, delete);
2038           if (!ifs && (TT.options&OPT_u)) goto barf;
2039           if (!jj) {
2040             if (ss[-1] == '{') goto barf;
2041             new[oo++] = '$';
2042             ii--;
2043             continue;
2044           } else if (ss[-1] != '{') ii += jj-1;
2045         }
2046       }
2047     }
2048 
2049     // combine before/ifs/after sections & split words on $IFS in ifs
2050     // keep oo bytes of str before (already parsed)
2051     // insert ifs (active for wildcards+splitting)
2052     // keep str+ii after (still to parse)
2053 
2054     // Fetch separator to glue string back together with
2055     *sep = 0;
2056     if (((qq&1) && cc=='*') || (flags&NO_SPLIT)) {
2057       unsigned wc;
2058 
2059       nosplit++;
2060       if (flags&SEMI_IFS) strcpy(sep, " ");
2061 // TODO what if separator is bigger? Need to grab 1 column of combining chars
2062       else if (0<(dd = utf8towc(&wc, TT.ff->ifs, 4)))
2063         sprintf(sep, "%.*s", dd, TT.ff->ifs);
2064     }
2065 
2066     // when aa proceed through entries until NULL, else process ifs once
2067     mm = yy = 0;
2068     do {
2069       // get next argument
2070       if (aa.c) ifs = aa.v[mm++] ? : "";
2071 
2072       // Are we performing surgery on this argument?
2073       if (slice && *slice != '}') {
2074         dd = slice[xx = (*slice == ':')];
2075         if (!ifs || (xx && !*ifs)) {
2076           if (strchr("-?=", dd)) { // - use default = assign default ? error
2077             push_arg(delete, ifs = slashcopy(slice+xx+1, "}", 0));
2078             if (dd == '?' || (dd == '=' &&
2079               !(setvar(s = xmprintf("%.*s=%s", (int)(slice-ss), ss, ifs)))))
2080                 goto barf; // TODO ? exits past "source" boundary
2081           }
2082         } else if (dd == '-'); // NOP when ifs not empty
2083         // use alternate value
2084         else if (dd == '+')
2085           push_arg(delete, ifs = slashcopy(slice+xx+1, "}", 0));
2086         else if (xx) { // ${x::}
2087           long long la = 0, lb = LLONG_MAX, lc = 1;
2088 
2089           ss = ++slice;
2090           nospace(&ss);
2091           if ((*ss==':' ? 1 : (lc = recalculate(&la, &ss, 0))) && *ss == ':') {
2092             ss++;
2093             if (**nospace(&ss)=='}') lb = 0;
2094             else lc = recalculate(&lb, &ss, 0);
2095           }
2096           if (!lc || *ss != '}') {
2097             // Find ${blah} context for error message
2098             while (*slice!='$') slice--;
2099             error_msg("bad %.*s @ %ld", (int)(strchr(ss, '}')+1-slice), slice,
2100               (long)(ss-slice));
2101             goto fail;
2102           }
2103 
2104           // This isn't quite what bash does, but close enough.
2105           if (!(lc = aa.c)) lc = strlen(ifs);
2106           else if (!la && !yy && strchr("@*", *slice)) {
2107             aa.v--; // ${*:0} shows $0 even though default is 1-indexed
2108             aa.c++;
2109             yy++;
2110           }
2111           if (la<0 && (la += lc)<0) continue;
2112           if (lb<0) lb = lc+lb-la;
2113           if (aa.c) {
2114             if (mm<la || mm>=la+lb) continue;
2115           } else if (la>=lc || lb<0) ifs = "";
2116           else if (la+lb>=lc) ifs += la;
2117           else if (!*delete || ifs != (*delete)->arg)
2118             push_arg(delete, ifs = xmprintf("%.*s", (int)lb, ifs+la));
2119           else {
2120             for (dd = 0; dd<lb ; dd++) if (!(ifs[dd] = ifs[dd+la])) break;
2121             ifs[dd] = 0;
2122           }
2123         } else if (strchr("#%^,", *slice)) {
2124           struct sh_arg wild = {0};
2125           char buf[8];
2126 
2127           s = slashcopy(slice+(xx = slice[1]==*slice)+1, "}", &wild);
2128 
2129           // ${x^pat} ${x^^pat} uppercase ${x,} ${x,,} lowercase (no pat = ?)
2130           if (strchr("^,", *slice)) {
2131             for (ss = ifs; *ss; ss += dd) {
2132               dd = getutf8(ss, 4, &jj);
2133               if (!*s || 0<wildcard_match(ss, s, &wild, WILD_ANY)) {
2134                 ll = ((*slice=='^') ? towupper : towlower)(jj);
2135 
2136                 // Of COURSE unicode case switch can change utf8 encoding length
2137                 // Lower case U+0069 becomes u+0130 in turkish.
2138                 // Greek U+0390 becomes 3 characters TODO test this
2139                 if (ll != jj) {
2140                   yy = ss-ifs;
2141                   if (!*delete || (*delete)->arg!=ifs)
2142                     push_arg(delete, ifs = xstrdup(ifs));
2143                   if (dd != (ll = wctoutf8(buf, ll))) {
2144                     if (dd<ll)
2145                       ifs = (*delete)->arg = xrealloc(ifs, strlen(ifs)+1+dd-ll);
2146                     memmove(ifs+yy+dd-ll, ifs+yy+ll, strlen(ifs+yy+ll)+1);
2147                   }
2148                   memcpy(ss = ifs+yy, buf, dd = ll);
2149                 }
2150               }
2151               if (!xx) break;
2152             }
2153           // ${x#y} remove shortest prefix ${x##y} remove longest prefix
2154           } else if (*slice=='#') {
2155             if (0<(dd = wildcard_match(ifs, s, &wild, WILD_SHORT*!xx)))
2156               ifs += dd;
2157           // ${x%y} ${x%%y} suffix
2158           } else if (*slice=='%') {
2159             for (ss = ifs+strlen(ifs), yy = -1; ss>=ifs; ss--) {
2160               if (0<(dd = wildcard_match(ss, s, &wild, WILD_SHORT*xx))&&!ss[dd])
2161               {
2162                 yy = ss-ifs;
2163                 if (!xx) break;
2164               }
2165             }
2166 
2167             if (yy != -1) {
2168               if (delete && *delete && (*delete)->arg==ifs) ifs[yy] = 0;
2169               else push_arg(delete, ifs = xstrndup(ifs, yy));
2170             }
2171           }
2172           free(s);
2173           free(wild.v);
2174 
2175         // ${x/pat/sub} substitute ${x//pat/sub} global ${x/#pat/sub} begin
2176         // ${x/%pat/sub} end ${x/pat} delete pat (x can be @ or *)
2177         } else if (*slice=='/') {
2178           struct sh_arg wild = {0};
2179 
2180           xx = !!strchr("/#%", slice[1]);
2181           s = slashcopy(ss = slice+xx+1, "/}", &wild);
2182           ss += (long)wild.v[wild.c];
2183           ss = (*ss == '/') ? slashcopy(ss+1, "}", 0) : 0;
2184           jj = ss ? strlen(ss) : 0;
2185           for (ll = 0; ifs[ll];) {
2186             // TODO nocasematch option
2187             if (0<(dd = wildcard_match(ifs+ll, s, &wild, 0))) {
2188               char *bird = 0;
2189 
2190               if (slice[1]=='%' && ifs[ll+dd]) {
2191                 ll++;
2192                 continue;
2193               }
2194               if (delete && *delete && (*delete)->arg==ifs) {
2195                 if (jj==dd) memcpy(ifs+ll, ss, jj);
2196                 else if (jj<dd) sprintf(ifs+ll, "%s%s", ss, ifs+ll+dd);
2197                 else bird = ifs;
2198               } else bird = (void *)1;
2199               if (bird) {
2200                 ifs = xmprintf("%.*s%s%s", ll, ifs, ss ? : "", ifs+ll+dd);
2201                 if (bird != (void *)1) {
2202                   free(bird);
2203                   (*delete)->arg = ifs;
2204                 } else push_arg(delete, ifs);
2205               }
2206               if (slice[1]!='/') break;
2207             } else ll++;
2208             if (slice[1]=='#') break;
2209           }
2210 
2211 // ${x@QEPAa} Q=$'blah' E=blah without the $'' wrap, P=expand as $PS1
2212 //   A=declare that recreates var a=attribute flags
2213 //   x can be @*
2214 //      } else if (*slice=='@') {
2215 
2216 // TODO test x can be @ or *
2217         } else {
2218 // TODO test ${-abc} as error
2219           ifs = slice;
2220           goto barf;
2221         }
2222 
2223 // TODO: $((a=42)) can change var, affect lifetime
2224 // must replace ifs AND any previous output arg[] within pointer strlen()
2225 // also x=;echo $x${x:=4}$x
2226       }
2227 
2228       // Nothing left to do?
2229       if (!ifs) break;
2230       if (!*ifs && !qq) continue;
2231 
2232       // loop within current ifs checking region to split words
2233       do {
2234 
2235         // find end of (split) word
2236         if ((qq&1) || nosplit) ss = ifs+strlen(ifs);
2237         else for (ss = ifs; *ss; ss += kk)
2238           if (utf8chr(ss, TT.ff->ifs, &kk)) break;
2239 
2240         // when no prefix, not splitting, no suffix: use existing memory
2241         if (!oo && !*ss && !((mm==aa.c) ? str[ii] : nosplit)) {
2242           if (qq || ss!=ifs) {
2243             if (!(flags&NO_PATH))
2244               for (jj = 0; ifs[jj]; jj++) collect_wildcards(ifs, jj, ant);
2245             wildcard_add_files(arg, ifs, &deck, delete);
2246           }
2247           continue;
2248         }
2249 
2250         // resize allocation and copy next chunk of IFS-free data
2251         jj = (mm == aa.c) && !*ss;
2252         new = xrealloc(new, oo + (ss-ifs) + ((nosplit&!jj) ? strlen(sep) : 0) +
2253                        (jj ? strlen(str+ii) : 0) + 1);
2254         dd = sprintf(new + oo, "%.*s%s", (int)(ss-ifs), ifs,
2255           (nosplit&!jj) ? sep : "");
2256         if (flags&NO_PATH) oo += dd;
2257         else while (dd--) collect_wildcards(new, oo++, ant);
2258         if (jj) break;
2259 
2260         // If splitting, keep quoted, non-blank, or non-whitespace separator
2261         if (!nosplit) {
2262           if (qq || *new || *ss) {
2263             push_arg(delete, new = xrealloc(new, strlen(new)+1));
2264             wildcard_add_files(arg, new, &deck, delete);
2265             new = xstrdup(str+ii);
2266           }
2267           qq &= 1;
2268           oo = 0;
2269         }
2270 
2271         // Skip trailing seperator (combining whitespace)
2272         kk = 0;
2273         while ((jj = utf8chr(ss, TT.ff->ifs, &ll))) {
2274           if (!iswspace(jj) && kk++) break;
2275           ss += ll;
2276         }
2277       } while (*(ifs = ss));
2278     } while (!(mm == aa.c));
2279   }
2280 
2281 // TODO globbing * ? [] +() happens after variable resolution
2282 
2283 // TODO test word splitting completely eliminating argument when no non-$IFS data left
2284 // wordexp keeps pattern when no matches
2285 
2286 // TODO test NO_SPLIT cares about IFS, see also trailing \n
2287 
2288   // Record result.
2289   if (*new || qq) {
2290     if (str != new) push_arg(delete, new);
2291     wildcard_add_files(arg, new, &deck, delete);
2292     new = 0;
2293   }
2294 
2295   // return success after freeing
2296   arg = 0;
2297 
2298 fail:
2299   if (str != new) free(new);
2300   free(deck.v);
2301   if (ant!=&deck && ant->v) collect_wildcards("", 0, ant);
2302   if (measure) *measure = --ii;
2303 
2304   return !!arg;
2305 }
2306 
2307 struct sh_brace {
2308   struct sh_brace *next, *prev, *stack;
2309   int active, cnt, idx, commas[];
2310 };
2311 
brace_end(struct sh_brace * bb)2312 static int brace_end(struct sh_brace *bb)
2313 {
2314   return bb->commas[(bb->cnt<0 ? 0 : bb->cnt)+1];
2315 }
2316 
2317 // expand braces (ala {a,b,c}) and call expand_arg_nobrace() each permutation
expand_arg(struct sh_arg * arg,char * old,unsigned flags,struct arg_list ** delete)2318 static int expand_arg(struct sh_arg *arg, char *old, unsigned flags,
2319   struct arg_list **delete)
2320 {
2321   struct sh_brace *bb = 0, *blist = 0, *bstk, *bnext;
2322   int i, j, k, x;
2323   char *s, *ss;
2324 
2325   // collect brace spans
2326   if ((TT.options&OPT_B) && !(flags&NO_BRACE)) for (i = 0; ; i++) {
2327     // skip quoted/escaped text
2328     while ((s = parse_word(old+i, 1)) != old+i) i += s-(old+i);
2329 
2330     // start a new span
2331     if (old[i] == '{') {
2332       dlist_add_nomalloc((void *)&blist,
2333         (void *)(bb = xzalloc(sizeof(struct sh_brace)+34*4)));
2334       bb->commas[0] = i;
2335     // end of string: abort unfinished spans and end loop
2336     } else if (!old[i]) {
2337       for (bb = blist; bb;) {
2338         if (!bb->active) {
2339           if (bb==blist) {
2340             dlist_pop(&blist);
2341             bb = blist;
2342           } else dlist_pop(&bb);
2343         } else bb = (bb->next==blist) ? 0 : bb->next;
2344       }
2345       break;
2346     // no active span?
2347     } else if (!bb) continue;
2348     // end current span
2349     else if (old[i] == '}') {
2350       bb->active = bb->commas[bb->cnt+1] = i;
2351       // Is this a .. span?
2352       j = 1+*bb->commas;
2353       if (!bb->cnt && i-j>=4) {
2354         // a..z span? Single digit numbers handled here too. TODO: utf8
2355         if (old[j+1]=='.' && old[j+2]=='.') {
2356           bb->commas[2] = old[j];
2357           bb->commas[3] = old[j+3];
2358           k = 0;
2359           if (old[j+4]=='}' ||
2360             (sscanf(old+j+4, "..%u}%n", bb->commas+4, &k) && k))
2361               bb->cnt = -1;
2362         }
2363         // 3..11 numeric span?
2364         if (!bb->cnt) {
2365           for (k=0, j = 1+*bb->commas; k<3; k++, j += x)
2366             if (!sscanf(old+j, "..%u%n"+2*!k, bb->commas+2+k, &x)) break;
2367           if (old[j]=='}') bb->cnt = -2;
2368         }
2369         // Increment goes in the right direction by at least 1
2370         if (bb->cnt) {
2371           if (!bb->commas[4]) bb->commas[4] = 1;
2372           if ((bb->commas[3]-bb->commas[2]>0) != (bb->commas[4]>0))
2373             bb->commas[4] *= -1;
2374         }
2375       }
2376       // discard commaless span that wasn't x..y
2377       if (!bb->cnt) free(dlist_pop((blist==bb) ? &blist : &bb));
2378       // Set bb to last unfinished brace (if any)
2379       for (bb = blist ? blist->prev : 0; bb && bb->active;
2380            bb = (bb==blist) ? 0 : bb->prev);
2381     // add a comma to current span
2382     } else if (old[i] == ',') {
2383       if (bb->cnt && !(bb->cnt&31)) {
2384         dlist_lpop(&blist);
2385         dlist_add_nomalloc((void *)&blist,
2386           (void *)(bb = xrealloc(bb, sizeof(struct sh_brace)+(bb->cnt+34)*4)));
2387       }
2388       bb->commas[++bb->cnt] = i;
2389     }
2390   }
2391 
2392 // TODO NO_SPLIT with braces? (Collate with spaces?)
2393   // If none, pass on verbatim
2394   if (!blist) return expand_arg_nobrace(arg, old, flags, delete, 0, 0);
2395 
2396   // enclose entire range in top level brace.
2397   (bstk = xzalloc(sizeof(struct sh_brace)+8))->commas[1] = strlen(old)+1;
2398   bstk->commas[0] = -1;
2399 
2400   // loop through each combination
2401   for (;;) {
2402 
2403     // Brace expansion can't be longer than original string. Keep start to {
2404     s = ss = xmalloc(bstk->commas[1]);
2405 
2406     // Append output from active braces to string
2407     for (bb = blist; bb; bb = (bnext == blist) ? 0 : bnext) {
2408 
2409       // If this brace already tip of stack, pop it. (We'll re-add in a moment.)
2410       if (bstk == bb) bstk = bstk->stack;
2411       // if bb is within bstk, save prefix text from bstk's "," to bb's "{"
2412       if (brace_end(bstk)>bb->commas[0]) {
2413         i = bstk->commas[bstk->idx]+1;
2414         s = stpncpy(s, old+i, bb->commas[0]-i);
2415       }
2416       else bstk = bstk->stack; // bb past bstk so done with old bstk, pop it
2417       // push self onto stack as active
2418       bb->stack = bstk;
2419       bb->active = 1;
2420       bstk = bnext = bb;
2421 
2422       // Find next active range: skip inactive spans from earlier/later commas
2423       while ((bnext = (bnext->next==blist) ? 0 : bnext->next)) {
2424 
2425         // past end of this brace (always true for a..b ranges)
2426         if ((i = bnext->commas[0])>brace_end(bb)) break;
2427 
2428         // in this brace but not this section
2429         if (i<bb->commas[bb->idx] || i>bb->commas[bb->idx+1]) {
2430           bnext->active = 0;
2431           bnext->stack = 0;
2432 
2433         // in this section
2434         } else break;
2435       }
2436 
2437       // is next span past this range?
2438       if (!bnext || bb->cnt<0 || bnext->commas[0]>bb->commas[bb->idx+1]) {
2439 
2440         // output uninterrupted span
2441         if (bb->cnt<0) {
2442           k = bb->commas[2]+bb->commas[4]*bb->idx;
2443           s += sprintf(s, (bb->cnt==-1) ? "\\%c"+!ispunct(k) : "%d", k);
2444         } else {
2445           i = bb->commas[bstk->idx]+1;
2446           s = stpncpy(s, old+i, bb->commas[bb->idx+1]-i);
2447         }
2448 
2449         // While not sibling, output tail and pop
2450         while (!bnext || bnext->commas[0]>brace_end(bstk)) {
2451           if (!(bb = bstk->stack)) break;
2452           i = brace_end(bstk)+1; // start of span
2453           j = bb->commas[bb->idx+1]; // enclosing comma span (can't be a..b)
2454 
2455           while (bnext) {
2456             if (bnext->commas[0]<j) {
2457               j = bnext->commas[0];// sibling
2458               break;
2459             } else if (brace_end(bb)>bnext->commas[0])
2460               bnext = (bnext->next == blist) ? 0 : bnext->next;
2461             else break;
2462           }
2463           s = stpncpy(s, old+i, j-i);
2464 
2465           // if next is sibling but parent _not_ a sibling, don't pop
2466           if (bnext && bnext->commas[0]<brace_end(bb)) break;
2467           bstk = bb;
2468         }
2469       }
2470     }
2471 
2472     // Save result, aborting on expand error
2473     if (expand_arg_nobrace(arg, push_arg(delete, ss), flags, delete, 0, 0)) {
2474       llist_traverse(blist, free);
2475 
2476       return 1;
2477     }
2478 
2479     // increment
2480     for (bb = blist->prev; bb; bb = (bb == blist) ? 0 : bb->prev) {
2481       if (!bb->stack) continue;
2482       else if (bb->cnt<0) {
2483         if (abs(bb->commas[2]-bb->commas[3]) < abs(++bb->idx*bb->commas[4]))
2484           bb->idx = 0;
2485         else break;
2486       } else if (++bb->idx > bb->cnt) bb->idx = 0;
2487       else break;
2488     }
2489 
2490     // if increment went off left edge, done expanding
2491     if (!bb) break;
2492   }
2493   llist_traverse(blist, free);
2494 
2495   return 0;
2496 }
2497 
2498 // Expand exactly one arg, returning NULL on error.
expand_one_arg(char * new,unsigned flags)2499 static char *expand_one_arg(char *new, unsigned flags)
2500 {
2501   struct arg_list *del = 0, *dd;
2502   struct sh_arg arg = {0};
2503   char *s = 0;
2504 
2505   // TODO: ${var:?error} here?
2506   if (!expand_arg(&arg, new, flags|NO_PATH|NO_SPLIT, &del))
2507     if (!(s = *arg.v) && (flags&(SEMI_IFS|NO_NULL))) s = "";
2508 
2509   // Free non-returned allocations.
2510   while (del) {
2511     dd = del->next;
2512     if (del->arg != s) free(del->arg);
2513     free(del);
2514     del = dd;
2515   }
2516   free(arg.v);
2517 
2518   return s;
2519 }
2520 
2521 // TODO |&
2522 
2523 // Expand arguments and perform redirections. Return new process object with
2524 // expanded args. This can be called from command or block context.
expand_redir(struct sh_arg * arg,int skip,int * urd)2525 static struct sh_process *expand_redir(struct sh_arg *arg, int skip, int *urd)
2526 {
2527   struct sh_process *pp;
2528   char *s = s, *ss, *sss, *cv = 0;
2529   int j, to, from, here = 0;
2530 
2531   TT.hfd = 10;
2532   pp = xzalloc(sizeof(struct sh_process));
2533   pp->urd = urd;
2534   pp->raw = arg;
2535 
2536   // When redirecting, copy each displaced filehandle to restore it later.
2537   // Expand arguments and perform redirections
2538   for (j = skip; j<arg->c; j++) {
2539     int saveclose = 0, bad = 0;
2540 
2541     if (!strcmp(s = arg->v[j], "!")) {
2542       pp->flags ^= PFLAG_NOT;
2543 
2544       continue;
2545     }
2546 
2547     // Handle <() >() redirectionss
2548     if ((*s == '<' || *s == '>') && s[1] == '(') {
2549       int new = pipe_subshell(s+2, strlen(s+2)-1, *s == '>');
2550 
2551       // Grab subshell data
2552       if (new == -1) {
2553         pp->exit = 1;
2554 
2555         return pp;
2556       }
2557       save_redirect(&pp->urd, -2, new);
2558 
2559       // bash uses /dev/fd/%d which requires /dev/fd to be a symlink to
2560       // /proc/self/fd so we just produce that directly.
2561       arg_add_del(&pp->arg, ss = xmprintf("/proc/self/fd/%d", new),&pp->delete);
2562 
2563       continue;
2564     }
2565 
2566     // Is this a redirect? s = prefix, ss = operator
2567     ss = skip_redir_prefix(s);
2568     sss = ss + anystart(ss, (void *)redirectors);
2569     if (ss == sss) {
2570       // Nope: save/expand argument and loop
2571       if (expand_arg(&pp->arg, s, 0, &pp->delete)) {
2572         pp->exit = 1;
2573 
2574         return pp;
2575       }
2576       continue;
2577     } else if (j+1 >= arg->c) {
2578       // redirect needs one argument
2579       s = "\\n";
2580       break;
2581     }
2582     sss = arg->v[++j];
2583 
2584     // It's a redirect: for [to]<from s = start of [to], ss = <, sss = from
2585     if (isdigit(*s) && ss-s>5) break;
2586 
2587     // expand arguments for everything but HERE docs
2588     if (strncmp(ss, "<<", 2)) {
2589       struct sh_arg tmp = {0};
2590 
2591       if (!expand_arg(&tmp, sss, 0, &pp->delete) && tmp.c == 1) sss = *tmp.v;
2592       else {
2593         if (tmp.c > 1) error_msg("%s: ambiguous redirect", sss);
2594         s = 0;
2595       }
2596       free(tmp.v);
2597       if (!s) break;
2598     }
2599 
2600     // Parse the [fd] part of [fd]<name
2601     to = *ss != '<';
2602     if (isdigit(*s)) to = atoi(s);
2603     else if (*s == '{') {
2604       if (*varend(s+1) != '}') break;
2605       // when we close a filehandle, we _read_ from {var}, not write to it
2606       if ((!strcmp(ss, "<&") || !strcmp(ss, ">&")) && !strcmp(sss, "-")) {
2607         if (!(ss = getvar(s+1))) break;
2608         to = atoi(ss); // TODO trailing garbage?
2609         if (save_redirect(&pp->urd, -1, to)) break;
2610         close(to);
2611 
2612         continue;
2613       // record high file descriptor in {to}<from environment variable
2614       } else {
2615         // we don't save this, it goes in the env var and user can close it.
2616         if (-1 == (to = next_hfd())) break;
2617         cv = xmprintf("%.*s=%d", (int)(ss-s-2), s+1, to);
2618       }
2619     }
2620 
2621     // HERE documents?
2622     if (!strncmp(ss, "<<", 2)) {
2623       char *tmp = xmprintf("%s/sh-XXXXXX", getvar("TMPDIR") ? : "/tmp");
2624       int i, h, len, zap = (ss[2] == '-'), x = !sss[strcspn(sss, "\\\"'")];
2625 
2626       // store contents in open-but-deleted /tmp file: write then lseek(start)
2627       if ((from = mkstemp(tmp))>=0) {
2628         if (unlink(tmp)) bad++;
2629         else if (ss[2] == '<') { // not stored in arg[here]
2630           if (!(ss = expand_one_arg(sss, 0))) {
2631             s = 0;
2632             break;
2633           }
2634           len = strlen(ss);
2635           if (len != writeall(from, ss, len) || 1 != writeall(from, "\n", 1))
2636             bad++;
2637           if (ss != sss) free(ss);
2638         } else {
2639           struct sh_arg *hh = arg+ ++here;
2640 
2641           for (i = 0; i<hh->c; i++) {
2642             sss = ss = hh->v[i];
2643             while (zap && *ss == '\t') ss++;
2644 // TODO audit this ala man page
2645             // expand_parameter, commands, and arithmetic
2646             if (x && !(sss = expand_one_arg(ss, ~SEMI_IFS))) {
2647               s = 0;
2648               break;
2649             }
2650 
2651             h = writeall(from, sss, len = strlen(sss));
2652             if (ss != sss) free(sss);
2653             if (len != h) break;
2654           }
2655           if (i != hh->c) bad++;
2656         }
2657         if (!bad && lseek(from, 0, SEEK_SET)) bad++;
2658         if (bad) close(from);
2659       } else bad++;
2660       free(tmp);
2661       if (bad) break;
2662 
2663     // from is fd<<2 (new fd to dup2() after vfork()) plus
2664     // 2 if we should close(from>>2) after dup2(from>>2, to),
2665     // 1 if we should close but dup for nofork recovery (ala <&2-)
2666 
2667     // Handle file descriptor duplication/close (&> &>> <& >& with number or -)
2668     // These redirect existing fd so nothing to open()
2669     } else if (*ss == '&' || ss[1] == '&') {
2670 
2671       // is there an explicit fd?
2672       for (ss = sss; isdigit(*ss); ss++);
2673       if (ss-sss>5 || (*ss && (*ss != '-' || ss[1]))) {
2674         if (*ss=='&') ss++;
2675         saveclose = 4;
2676         goto notfd;
2677       }
2678 
2679       from = (ss==sss) ? to : atoi(sss);
2680       saveclose = 2-(*ss == '-');
2681     } else {
2682 notfd:
2683       // Permissions to open external file with: < > >> <& >& <> >| &>> &>
2684       if (!strcmp(ss, "<>")) from = O_CREAT|O_RDWR;
2685       else if (strstr(ss, ">>")) from = O_CREAT|O_APPEND|O_WRONLY;
2686       else {
2687         from = (*ss == '<') ? O_RDONLY : O_CREAT|O_WRONLY|O_TRUNC;
2688         if (!strcmp(ss, ">") && (TT.options&OPT_C)) {
2689           struct stat st;
2690 
2691           // Not _just_ O_EXCL: > /dev/null allowed
2692           if (stat(sss, &st) || !S_ISREG(st.st_mode)) from |= O_EXCL;
2693         }
2694       }
2695 
2696       // we expect /dev/fd/# and /dev/{stdin,stdout,stderr} to be in /dev
2697 
2698 // TODO: /dev/{tcp,udp}/host/port
2699 
2700       // Open the file
2701       if (-1 == (from = xcreate_stdio(sss, from|WARN_ONLY, 0666))) {
2702         s = 0;
2703 
2704         break;
2705       } else if (from==to) saveclose |= 2;
2706     }
2707 
2708     // perform redirect, saving displaced "to".
2709     if (save_redirect(&pp->urd, from, to)) bad++;
2710     // Do we save displaced "to" in env variable instead of undo list?
2711     if (cv) {
2712       --*pp->urd;
2713       if (!setvar(cv)) bad++;
2714       cv = 0;
2715     }
2716     if ((saveclose&1) && save_redirect(&pp->urd, -1, from)) bad++;
2717     if ((saveclose&4) && save_redirect(&pp->urd, from, 2)) bad++;
2718     if (!(saveclose&2)) close(from);
2719     if (bad) break;
2720   }
2721 
2722   // didn't parse everything?
2723   if (j != arg->c) {
2724     if (s) syntax_err(s);
2725     if (!pp->exit) pp->exit = 1;
2726     free(cv);
2727   }
2728 
2729   return pp;
2730 }
2731 
2732 // Call binary, or run script via xexec("sh --")
sh_exec(char ** argv)2733 static void sh_exec(char **argv)
2734 {
2735   char *pp = getvar("PATH" ? : _PATH_DEFPATH), *ss = TT.isexec ? : *argv,
2736     **sss = 0, **oldenv = environ, **argv2;
2737   int norecurse = CFG_TOYBOX_NORECURSE || !toys.stacktop || TT.isexec, ii;
2738   struct string_list *sl = 0;
2739   struct toy_list *tl = 0;
2740 
2741   if (getpid() != TT.pid) signal(SIGINT, SIG_DFL); // TODO: restore all?
2742   errno = ENOENT;
2743   if (strchr(ss, '/')) {
2744     if (access(ss, X_OK)) ss = 0;
2745   } else if (norecurse || !(tl = toy_find(ss)))
2746     for (sl = find_in_path(pp, ss); sl || (ss = 0); free(llist_pop(&sl)))
2747       if (!access(ss = sl->str, X_OK)) break;
2748 
2749   if (ss) {
2750     struct sh_vars **vv = visible_vars();
2751     struct sh_arg aa;
2752     unsigned uu, argc;
2753 
2754     // convert vars in-place and use original sh_arg alloc to add one more
2755     aa.v = environ = (void *)vv;
2756     for (aa.c = uu = 0; vv[uu]; uu++) {
2757       if ((vv[uu]->flags&(VAR_WHITEOUT|VAR_EXPORT))==VAR_EXPORT) {
2758         if (*(pp = vv[uu]->str)=='_' && pp[1]=='=') sss = aa.v+aa.c;
2759         aa.v[aa.c++] = pp;
2760       }
2761     }
2762     aa.v[aa.c] = 0;
2763     if (!sss) {
2764       if (aa.c<uu) aa.v[++aa.c] = 0;
2765       else arg_add(&aa, 0);
2766       sss = aa.v+aa.c-1;
2767     }
2768     *sss = xmprintf("_=%s", ss);
2769 
2770     // Don't leave open filehandles to scripts in children
2771     if (!TT.isexec)
2772       for (ii = 0; ii<TT.recursion; ii++)
2773         if (TT.recfile[ii]>0) close(TT.recfile[ii]);
2774 
2775     // Run builtin, exec command, or call shell script without #!
2776     toy_exec_which(tl, argv);
2777     execve(ss, argv, environ);
2778     // shell script without #!
2779     if (errno == ENOEXEC) {
2780       for (argc = 0; argv[argc]; argc++);
2781       argv2 = xmalloc((argc+3)*sizeof(char *));
2782       memcpy(argv2+3, argv+1, argc*sizeof(char *));
2783       argv2[0] = "sh";
2784       argv2[1] = "--";
2785       argv2[2] = ss;
2786       xexec(argv2);
2787       free(argv2);
2788     }
2789     environ = oldenv;
2790     free(*sss);
2791     free(aa.v);
2792   }
2793 
2794   perror_msg("%s", *argv);
2795   if (!TT.isexec) _exit(127);
2796   llist_traverse(sl, free);
2797 }
2798 
2799 // Execute a single command at TT.ff->pl
run_command(void)2800 static struct sh_process *run_command(void)
2801 {
2802   char *s, *ss, *sss;
2803   struct sh_arg *arg = TT.ff->pl->arg;
2804   int envlen, skiplen, funk = TT.funcslen, ii, jj = 0, prefix = 0;
2805   struct sh_process *pp;
2806 
2807   // Count leading variable assignments
2808   for (envlen = skiplen = 0; envlen<arg->c; envlen++)
2809     if ((ss = varend(arg->v[envlen]))==arg->v[envlen] || ss[*ss=='+']!='=')
2810       break;
2811 
2812   // Skip [[ ]] and (( )) contents for now
2813   if ((s = arg->v[envlen])) {
2814     if (!smemcmp(s, "((", 2)) skiplen = 1;
2815     else if (!strcmp(s, "[[")) while (strcmp(arg->v[envlen+skiplen++], "]]"));
2816   }
2817   pp = expand_redir(arg, envlen+skiplen, 0);
2818 
2819 // TODO: if error stops redir, expansion assignments, prefix assignments,
2820 // what sequence do they occur in?
2821   if (skiplen) {
2822     // Trailing redirects can't expand to any contents
2823     if (pp->arg.c) {
2824       syntax_err(*pp->arg.v);
2825       pp->exit = 1;
2826     }
2827     if (!pp->exit) {
2828       for (ii = 0; ii<skiplen; ii++)
2829 // TODO: [[ ~ ] expands but ((~)) doesn't, what else?
2830         if (expand_arg(&pp->arg, arg->v[envlen+ii], NO_PATH|NO_SPLIT, &pp->delete))
2831           break;
2832       if (ii != skiplen) pp->exit = toys.exitval = 1;
2833     }
2834     if (pp->exit) return pp;
2835   }
2836 
2837   // Are we calling a shell function?  TODO binary search
2838   if (pp->arg.c)
2839     if (!strchr(s, '/')) for (funk = 0; funk<TT.funcslen; funk++)
2840        if (!strcmp(s, TT.functions[funk]->name)) break;
2841 
2842   // Create new function context to hold local vars?
2843   if (funk != TT.funcslen || (envlen && pp->arg.c) || TT.ff->blk->pipe) {
2844     call_function();
2845 // TODO function needs to run asynchronously in pipeline
2846     if (funk != TT.funcslen) {
2847       TT.ff->delete = pp->delete;
2848       pp->delete = 0;
2849     }
2850     addvar(0, TT.ff); // function context (not source) so end_fcall deletes
2851     prefix = 1;  // create local variables for function prefix assignment
2852   }
2853 
2854   // perform any assignments
2855   if (envlen) for (; jj<envlen && !pp->exit; jj++) {
2856     struct sh_vars *vv;
2857 
2858     if ((sss = expand_one_arg(ss = arg->v[jj], SEMI_IFS))) {
2859       if (!prefix && sss==ss) sss = xstrdup(sss);
2860       if ((vv = setvar_long(sss, sss!=ss, prefix ? TT.ff : TT.ff->prev))) {
2861         if (prefix) vv->flags |= VAR_EXPORT;
2862         continue;
2863       }
2864     }
2865 
2866     pp->exit = 1;
2867     break;
2868   }
2869 
2870   // Do the thing
2871   if (pp->exit || envlen==arg->c) s = 0; // leave $_ alone
2872   else if (!pp->arg.c) s = "";           // nothing to do but blank $_
2873 
2874 // TODO: call functions() FUNCTION
2875 // TODO what about "echo | x=1 | export fruit", must subshell? Test this.
2876 //   Several NOFORK can just NOP in a pipeline? Except ${a?b} still errors
2877 
2878   // ((math))
2879   else if (!smemcmp(s = *pp->arg.v, "((", 2)) {
2880     char *ss = s+2;
2881     long long ll;
2882 
2883     funk = TT.funcslen;
2884     ii = strlen(s)-2;
2885     if (!recalculate(&ll, &ss, 0) || ss!=s+ii)
2886       perror_msg("bad math: %.*s @ %ld", ii-2, s+2, (long)(ss-s)-2);
2887     else toys.exitval = !ll;
2888     pp->exit = toys.exitval;
2889     s = 0; // Really!
2890 
2891   // call shell function
2892   } else if (funk != TT.funcslen) {
2893     s = 0; // $_ set on return, not here
2894     (TT.ff->func = TT.functions[funk])->refcount++;
2895     TT.ff->pl = TT.ff->func->pipeline;
2896     TT.ff->arg = pp->arg;
2897 // TODO: unredirect(pp->urd) called below but haven't traversed function yet
2898   } else {
2899     struct toy_list *tl = toy_find(*pp->arg.v);
2900 
2901     jj = tl ? tl->flags : 0;
2902     TT.pp = pp;
2903     s = pp->arg.v[pp->arg.c-1];
2904     sss = pp->arg.v[pp->arg.c];
2905 //dprintf(2, "%d run command %p %s\n", getpid(), TT.ff, *pp->arg.v); debug_show_fds();
2906 // TODO: figure out when can exec instead of forking, ala sh -c blah
2907 
2908     // Is this command a builtin that should run in this process?
2909     if ((jj&TOYFLAG_NOFORK) || ((jj&TOYFLAG_MAYFORK) && !prefix)) {
2910       sigjmp_buf rebound, *prebound = toys.rebound;
2911       char temp[jj = offsetof(struct toy_context, rebound)];
2912 
2913       // This fakes lots of what toybox_main() does.
2914       memcpy(&temp, &toys, jj);
2915       memset(&toys, 0, jj);
2916 
2917       // The compiler complains "declaration does not declare anything" if we
2918       // name the union in TT, only works WITHOUT name. So we can't
2919       // sizeof(union) instead offsetof() first thing after union to get size.
2920       memset(&TT, 0, offsetof(struct sh_data, SECONDS));
2921       if (!sigsetjmp(rebound, 1)) {
2922         toys.rebound = &rebound;
2923 //dprintf(2, "%d builtin", getpid()); for (int xx = 0; xx<=pp->arg.c; xx++) dprintf(2, "{%s}", pp->arg.v[xx]); dprintf(2, "\n");
2924         toy_singleinit(tl, pp->arg.v);
2925         tl->toy_main();
2926         xexit();
2927       }
2928       toys.rebound = prebound;
2929       pp->exit = toys.exitval;
2930       clearerr(stdout);
2931       if (toys.optargs != toys.argv+1) free(toys.optargs);
2932       if (toys.old_umask) umask(toys.old_umask);
2933       memcpy(&toys, &temp, jj);
2934     } else if (-1==(pp->pid = xpopen_setup(pp->arg.v, 0, sh_exec)))
2935         perror_msg("%s: vfork", *pp->arg.v);
2936   }
2937 
2938   // cleanup process
2939   unredirect(pp->urd);
2940   pp->urd = 0;
2941   if (prefix && funk == TT.funcslen) end_fcall(0);
2942   if (s) setvarval("_", s);
2943 
2944   return pp;
2945 }
2946 
free_process(struct sh_process * pp)2947 static int free_process(struct sh_process *pp)
2948 {
2949   int rc;
2950 
2951   if (!pp) return 127;
2952   rc = pp->exit;
2953   llist_traverse(pp->delete, llist_free_arg);
2954   free(pp);
2955 
2956   return rc;
2957 }
2958 
2959 // if then fi for while until select done done case esac break continue return
2960 
2961 // Free one pipeline segment.
free_pipeline(void * pipeline)2962 static void free_pipeline(void *pipeline)
2963 {
2964   struct sh_pipeline *pl = pipeline;
2965   int i, j, k;
2966 
2967   if (!pl) return;
2968 
2969   // free either function or arguments and HERE doc contents
2970   if (pl->type == 'F') {
2971     free_function((void *)*pl->arg->v);
2972     *pl->arg->v = 0;
2973   }
2974   for (j=0; j<=pl->count; j++) {
2975     if (!pl->arg[j].v) continue;
2976     k = pl->arg[j].c-!!pl->count;
2977     for (i = 0; i<=k; i++) free(pl->arg[j].v[i]);
2978     free(pl->arg[j].v);
2979   }
2980   free(pl);
2981 }
2982 
2983 // Append a new pipeline to function, returning pipeline and pipeline's arg
add_pl(struct sh_pipeline ** ppl,struct sh_arg ** arg)2984 static struct sh_pipeline *add_pl(struct sh_pipeline **ppl, struct sh_arg **arg)
2985 {
2986   struct sh_pipeline *pl = xzalloc(sizeof(struct sh_pipeline));
2987 
2988   if (arg) *arg = pl->arg;
2989   pl->lineno = TT.LINENO;
2990   dlist_add_nomalloc((void *)ppl, (void *)pl);
2991 
2992   return pl->end = pl;
2993 }
2994 
2995 // Add a line of shell script to a shell function. Returns 0 if finished,
2996 // 1 to request another line of input (> prompt), -1 for syntax err
parse_line(char * line,struct sh_pipeline ** ppl,struct double_list ** expect)2997 static int parse_line(char *line, struct sh_pipeline **ppl,
2998    struct double_list **expect)
2999 {
3000   char *start = line, *delete = 0, *end, *s, *ex, done = 0,
3001     *tails[] = {"fi", "done", "esac", "}", "]]", ")", 0};
3002   struct sh_pipeline *pl = *ppl ? (*ppl)->prev : 0, *pl2, *pl3;
3003   struct sh_arg *arg = 0;
3004   long i;
3005 
3006   // Resume appending to last statement?
3007   if (pl) {
3008     arg = pl->arg;
3009 
3010     // Extend/resume quoted block
3011     if (arg->c<0) {
3012       arg->c = (-arg->c)-1;
3013       if (start) {
3014         delete = start = xmprintf("%s%s", arg->v[arg->c], start);
3015         free(arg->v[arg->c]);
3016       } else start = arg->v[arg->c];
3017       arg->v[arg->c] = 0;
3018 
3019     // is a HERE document in progress?
3020     } else if (pl->count != pl->here) {
3021 here_loop:
3022       // Back up to oldest unfinished pipeline segment.
3023       while (pl != *ppl && pl->prev->count != pl->prev->here) pl = pl->prev;
3024       arg = pl->arg+1+pl->here;
3025 
3026       // Match unquoted EOF.
3027       if (!line) {
3028         error_msg("%u: <<%s EOF", TT.LINENO, arg->v[arg->c]);
3029         goto here_end;
3030       }
3031       for (s = line, end = arg->v[arg->c]; *end; s++, end++) {
3032         end += strspn(end, "\\\"'\n");
3033         if (!*s || *s != *end) break;
3034       }
3035 
3036       // Add this line, else EOF hit so end HERE document
3037       if ((*s && *s!='\n') || *end) {
3038         end = arg->v[arg->c];
3039         arg_add(arg, xstrdup(line));
3040         arg->v[arg->c] = end;
3041       } else {
3042 here_end:
3043         // End segment and advance/consume bridge segments
3044         arg->v[arg->c] = 0;
3045         if (pl->count == ++pl->here)
3046           while (pl->next != *ppl && (pl = pl->next)->here == -1)
3047             pl->here = pl->count;
3048       }
3049       if (pl->here != pl->count) {
3050         if (!line) goto here_loop;
3051         else return 1;
3052       }
3053       start = 0;
3054 
3055     // Nope, new segment if not self-managing type
3056     } else if (pl->type < 128) pl = 0;
3057   }
3058 
3059   // Parse words, assemble argv[] pipelines, check flow control and HERE docs
3060   if (start) for (;;) {
3061     ex = *expect ? (*expect)->prev->data : 0;
3062 
3063     // Look for << HERE redirections in completed pipeline segment
3064     if (pl && pl->count == -1) {
3065       // find arguments of the form [{n}]<<[-] with another one after it
3066       for (arg = pl->arg, pl->count = i = 0; i<arg->c; i++) {
3067         s = skip_redir_prefix(arg->v[i]);
3068         if (strncmp(s, "<<", 2) || s[2]=='<') continue;
3069         if (i+1 == arg->c) goto flush;
3070 
3071         // Add another arg[] to the pipeline segment (removing/re-adding
3072         // to list because realloc can move pointer, and adjusing end pointers)
3073         dlist_lpop(ppl);
3074         pl2 = pl;
3075         pl = xrealloc(pl, sizeof(*pl)+(++pl->count+1)*sizeof(struct sh_arg));
3076         arg = pl->arg;
3077         dlist_add_nomalloc((void *)ppl, (void *)pl);
3078         for (pl3 = *ppl;;) {
3079           if (pl3->end == pl2) pl3->end = pl;
3080           if ((pl3 = pl3->next) == *ppl) break;
3081         }
3082 
3083         // queue up HERE EOF so input loop asks for more lines.
3084         memset(arg+pl->count, 0, sizeof(*arg));
3085         arg_add(arg+pl->count, arg->v[++i]);
3086         arg[pl->count].c--;
3087       }
3088       // Mark "bridge" segment when previous pl had HERE but this doesn't
3089       if (!pl->count && pl->prev->count != pl->prev->here) pl->here = -1;
3090       pl = 0;
3091     }
3092     if (done) break;
3093     s = 0;
3094 
3095     // skip leading whitespace/comment here to know where next word starts
3096     while (isspace(*start)) ++start;
3097     if (*start=='#') while (*start) ++start;
3098 
3099     // Parse next word and detect overflow (too many nested quotes).
3100     if ((end = parse_word(start, 0)) == (void *)1) goto flush;
3101 //dprintf(2, "%d %p(%d) %s word=%.*s\n", getpid(), pl, pl ? pl->type : -1, ex, (int)(end-start), end ? start : "");
3102 
3103     // End function declaration?
3104     if (pl && pl->type == 'f' && arg->c == 1 && (end-start!=1 || *start!='(')) {
3105       // end (possibly multiline) function segment, expect function body next
3106       dlist_add(expect, 0);
3107       pl = 0;
3108 
3109       continue;
3110     }
3111 
3112     // Is this a new pipeline segment?
3113     if (!pl) pl = add_pl(ppl, &arg);
3114 
3115     // Do we need to request another line to finish word (find ending quote)?
3116     if (!end) {
3117       // Save unparsed bit of this line, we'll need to re-parse it.
3118       if (*start=='\\' && (!start[1] || start[1]=='\n')) start++;
3119       arg_add(arg, xstrndup(start, strlen(start)));
3120       arg->c = -arg->c;
3121       free(delete);
3122 
3123       return 1;
3124     }
3125 
3126     // Ok, we have a word. What does it _mean_?
3127 
3128     // case/esac parsing is weird (unbalanced parentheses!), handle first
3129     i = ex && !strcmp(ex, "esac") &&
3130         ((pl->type && pl->type != 3) || (*start==';' && end-start>1));
3131     if (i) {
3132 
3133       // Premature EOL in type 1 (case x\nin) or 2 (at start or after ;;) is ok
3134       if (end == start) {
3135         if (pl->type==128 && arg->c==2) break;  // case x\nin
3136         if (pl->type==129 && (!arg->c || (arg->c==1 && **arg->v==';'))) break;
3137         s = "newline";
3138         goto flush;
3139       }
3140 
3141       // type 0 means just got ;; so start new type 2
3142       if (!pl->type || pl->type==3) {
3143         // catch "echo | ;;" errors
3144         if (arg->v && arg->v[arg->c] && strcmp(arg->v[arg->c], "&")) goto flush;
3145         if (!arg->c) {
3146           if (pl->prev->type == 2) {
3147             // Add a call to "true" between empty ) ;;
3148             arg_add(arg, xstrdup(":"));
3149             pl = add_pl(ppl, &arg);
3150           }
3151           pl->type = 129;
3152         } else {
3153           // check for here documents
3154           pl->count = -1;
3155           continue;
3156         }
3157       }
3158 
3159     // Did we hit end of line or ) outside a function declaration?
3160     // ) is only saved at start of a statement, ends current statement
3161     } else if (end == start || (arg->c && *start == ')' && pl->type!='f')) {
3162 //TODO: test ) within ]]
3163       // function () needs both parentheses or neither
3164       if (pl->type == 'f' && arg->c != 1 && arg->c != 3) {
3165         s = "function(";
3166         goto flush;
3167       }
3168 
3169       // "for" on its own line is an error.
3170       if (arg->c == 1 && !smemcmp(ex, "do\0A", 4)) {
3171         s = "newline";
3172         goto flush;
3173       }
3174 
3175       // Stop at EOL. Discard blank pipeline segment, else end segment
3176       if (end == start) done++;
3177       if (!pl->type && !arg->c) {
3178         free_pipeline(dlist_lpop(ppl));
3179         pl = *ppl ? (*ppl)->prev : 0;
3180       } else pl->count = -1;
3181 
3182       continue;
3183     }
3184 
3185     // Save word and check for flow control
3186     arg_add(arg, s = xstrndup(start, end-start));
3187     start = end;
3188 
3189     // Second half of case/esac parsing
3190     if (i) {
3191       // type 1 (128): case x [\n] in
3192       if (pl->type==128) {
3193         if (arg->c==2 && strchr("()|;&", *s)) goto flush;
3194         if (arg->c==3) {
3195           if (strcmp(s, "in")) goto flush;
3196           pl->type = 1;
3197           (pl = add_pl(ppl, &arg))->type = 129;
3198         }
3199 
3200         continue;
3201 
3202       // type 2 (129): [;;] [(] pattern [|pattern...] )
3203       } else {
3204 
3205         // can't start with line break or ";;" or "case ? in ;;" without ")"
3206         if (*s==';') {
3207           if (arg->c>1 || (arg->c==1 && pl->prev->type==1)) goto flush;
3208         } else pl->type = 2;
3209         i = arg->c - (**arg->v==';' && arg->v[0][1]);
3210         if (i==1 && !strcmp(s, "esac")) {
3211           // esac right after "in" or ";;" ends block, fall through
3212           if (arg->c>1) {
3213             arg->v[1] = 0;
3214             pl = add_pl(ppl, &arg);
3215             arg_add(arg, s);
3216           } else pl->type = 0;
3217         } else {
3218           if (arg->c>1) i -= *arg->v[1]=='(';
3219           if (i>0 && ((i&1)==!!strchr("|)", *s) || strchr(";(", *s)))
3220             goto flush;
3221           if (*s=='&' || !strcmp(s, "||")) goto flush;
3222           if (*s==')') pl = add_pl(ppl, &arg);
3223 
3224           continue;
3225         }
3226       }
3227     }
3228 
3229     // Are we starting a new [function] name [()] definition
3230     if (!pl->type || pl->type=='f') {
3231       if (!pl->type && arg->c==1 && !strcmp(s, "function")) {
3232         free(arg->v[--arg->c]);
3233         arg->v[arg->c] = 0;
3234         pl->type = 'f';
3235         continue;
3236       } else if (arg->c==2 && !strcmp(s, "(")) pl->type = 'f';
3237     }
3238 
3239     // one or both of [function] name[()]
3240     if (pl->type=='f') {
3241       if (arg->v[0][strcspn(*arg->v, "\"'`><;|&$")]) {
3242         s = *arg->v;
3243         goto flush;
3244       }
3245       if (arg->c == 2 && strcmp(s, "(")) goto flush;
3246       if (arg->c == 3) {
3247         if (strcmp(s, ")")) goto flush;
3248         dlist_add(expect, 0);
3249         pl = 0;
3250       }
3251 
3252       continue;
3253 
3254     // is it a line break token?
3255     } else if (strchr(";|&", *s) && strncmp(s, "&>", 2)) {
3256       arg->c--;
3257 
3258       // Connecting nonexistent statements is an error
3259       if (!arg->c || !smemcmp(ex, "do\0A", 4)) goto flush;
3260 
3261       // treat ; as newline so we don't have to check both elsewhere.
3262       if (!strcmp(s, ";")) {
3263         arg->v[arg->c] = 0;
3264         free(s);
3265         s = 0;
3266 // TODO can't have ; between "for i" and in or do. (Newline yes, ; no. Why?)
3267         if (!arg->c && !smemcmp(ex, "do\0C", 4)) continue;
3268 
3269       // ;; and friends only allowed in case statements
3270       } else if (*s == ';') goto flush;
3271       pl->count = -1;
3272 
3273       continue;
3274 
3275     // a for/select must have at least one additional argument on same line
3276     } else if (!smemcmp(ex, "do\0A", 4)) {
3277       // Sanity check and break the segment
3278       if (strncmp(s, "((", 2) && *varend(s)) goto flush;
3279       pl->count = -1;
3280       (*expect)->prev->data = "do\0C";
3281 
3282       continue;
3283 
3284     // flow control is the first word of a pipeline segment
3285     } else if (arg->c>1) {
3286       // Except that [[ ]] is a type 0 segment
3287       if (ex && *ex==']' && !strcmp(s, ex)) free(dlist_lpop(expect));
3288 
3289       continue;
3290     }
3291 
3292     // The "test" part of for/select loops can have (at most) one "in" line,
3293     // for {((;;))|name [in...]} do
3294     if (!smemcmp(ex, "do\0C", 4)) {
3295       if (strcmp(s, "do")) {
3296         // can only have one "in" line between for/do, but not with for(())
3297         if (pl->prev->type == 's') goto flush;
3298         if (!strncmp(pl->prev->arg->v[1], "((", 2)) goto flush;
3299         else if (strcmp(s, "in")) goto flush;
3300         pl->type = 's';
3301 
3302         continue;
3303       }
3304     }
3305 
3306     // start of a new block?
3307 
3308     // for/select/case require var name on same line, can't break segment yet
3309     if (!strcmp(s, "for") || !strcmp(s, "select") || !strcmp(s, "case")) {
3310 // TODO why !pl->type here
3311       if (!pl->type) pl->type = (*s == 'c') ? 128 : 1;
3312       dlist_add(expect, (*s == 'c') ? "esac" : "do\0A");
3313 
3314       continue;
3315     }
3316 
3317     end = 0;
3318     if (!strcmp(s, "if")) end = "then";
3319     else if (!strcmp(s, "while") || !strcmp(s, "until")) end = "do\0B";
3320     else if (!strcmp(s, "{")) end = "}";
3321     else if (!strcmp(s, "(")) end = ")";
3322     else if (!strcmp(s, "[[")) end = "]]";
3323 
3324     // Expecting NULL means any statement (don't care which).
3325     if (!ex && *expect) {
3326       if (pl->prev->type == 'f' && !end && smemcmp(s, "((", 2)) goto flush;
3327       free(dlist_lpop(expect));
3328     }
3329 
3330     // Did we start a new statement
3331     if (end) {
3332       if (*end!=']') pl->type = 1;
3333       else {
3334         // [[ ]] is a type 0 segment, not a flow control block
3335         dlist_add(expect, end);
3336         continue;
3337       }
3338 
3339       // Only innermost statement needed in { { { echo ;} ;} ;} and such
3340       if (*expect && !(*expect)->prev->data) free(dlist_lpop(expect));
3341 
3342     // if not looking for end of statement skip next few tests
3343     } else if (!ex);
3344 
3345     // If we got here we expect a specific word to end this block: is this it?
3346     else if (!strcmp(s, ex)) {
3347       // can't "if | then" or "while && do", only ; & or newline works
3348       if (strcmp(pl->prev->arg->v[pl->prev->arg->c] ? : "&", "&")) goto flush;
3349 
3350       // consume word, record block end in earlier !0 type (non-nested) blocks
3351       free(dlist_lpop(expect));
3352       if (3 == (pl->type = anystr(s, tails) ? 3 : 2)) {
3353         for (i = 0, pl2 = pl3 = pl; (pl2 = pl2->prev);) {
3354           if (pl2->type == 3) i++;
3355           else if (pl2->type) {
3356             if (!i) {
3357               if (pl2->type == 2) {
3358                 pl2->end = pl3;
3359                 pl3 = pl2;   // chain multiple gearshifts for case/esac
3360               } else pl2->end = pl;
3361             }
3362             if (pl2->type == 1 && --i<0) break;
3363           }
3364         }
3365       }
3366 
3367       // if it's a multipart block, what comes next?
3368       if (!strcmp(s, "do")) end = "done";
3369       else if (!strcmp(s, "then")) end = "fi\0A";
3370 
3371     // fi could have elif, which queues a then.
3372     } else if (!strcmp(ex, "fi")) {
3373       if (!strcmp(s, "elif")) {
3374         free(dlist_lpop(expect));
3375         end = "then";
3376       // catch duplicate else while we're here
3377       } else if (!strcmp(s, "else")) {
3378         if (ex[3] != 'A') {
3379           s = "2 else";
3380           goto flush;
3381         }
3382         free(dlist_lpop(expect));
3383         end = "fi\0B";
3384       }
3385     }
3386 
3387     // Queue up the next thing to expect, all preceded by a statement
3388     if (end) {
3389       if (!pl->type) pl->type = 2;
3390 
3391       dlist_add(expect, end);
3392       if (!anystr(end, tails)) dlist_add(expect, 0);
3393       pl->count = -1;
3394     }
3395 
3396     // syntax error check: these can't be the first word in an unexpected place
3397     if (!pl->type && anystr(s, (char *[]){"then", "do", "esac", "}", "]]", ")",
3398         "done", "fi", "elif", "else", 0})) goto flush;
3399   }
3400   free(delete);
3401 
3402   // Return now if line didn't tell us to DO anything.
3403   if (!*ppl) return 0;
3404   pl = (*ppl)->prev;
3405 
3406   // return if HERE document pending or more flow control needed to complete
3407   if (pl->count != pl->here) return 1;
3408   if (*expect) return 1;
3409   if (pl->arg->v[pl->arg->c] && strcmp(pl->arg->v[pl->arg->c], "&")) return 1;
3410 
3411   // Transplant completed function bodies into reference counted structures
3412   for (;;) {
3413     if (pl->type=='f') {
3414       struct sh_function *funky;
3415 
3416       // Create sh_function struct, attach to declaration's pipeline segment
3417       funky = xmalloc(sizeof(struct sh_function));
3418       funky->refcount = 1;
3419       funky->name = *pl->arg->v;
3420       *pl->arg->v = (void *)funky;
3421       pl->type = 'F'; // different cleanup
3422 
3423       // Transplant function body into new struct, re-circling both lists
3424       pl2 = pl->next;
3425       // Add NOP 'f' segment (TODO: remove need for this?)
3426       (funky->pipeline = add_pl(&pl2, 0))->type = 'f';
3427       // Find end of block
3428       for (i = 0, pl3 = pl2->next;;pl3 = pl3->next)
3429         if (pl3->type == 1) i++;
3430         else if (pl3->type == 3 && --i<0) break;
3431       // Chop removed segment out of old list.
3432       pl3->next->prev = pl;
3433       pl->next = pl3->next;
3434       // Terminate removed segment.
3435       pl2->prev = 0;
3436       pl3->next = 0;
3437     }
3438     if (pl == *ppl) break;
3439     pl = pl->prev;
3440   }
3441 
3442   // Don't need more input, can start executing.
3443 
3444   dlist_terminate(*ppl);
3445   return 0;
3446 
3447 flush:
3448   if (s) syntax_err(s);
3449   llist_traverse(*ppl, free_pipeline);
3450   *ppl = 0;
3451   llist_traverse(*expect, free);
3452   *expect = 0;
3453 
3454   return 0-!!s;
3455 }
3456 
3457 // Find + and - jobs. Returns index of plus, writes minus to *minus
find_plus_minus(int * minus)3458 int find_plus_minus(int *minus)
3459 {
3460   long long when, then;
3461   int i, plus;
3462 
3463   if (minus) *minus = 0;
3464   for (then = i = plus = 0; i<TT.jobs.c; i++) {
3465     if ((when = ((struct sh_process *)TT.jobs.v[i])->when) > then) {
3466       then = when;
3467       if (minus) *minus = plus;
3468       plus = i;
3469     }
3470   }
3471 
3472   return plus;
3473 }
3474 
is_plus_minus(int i,int plus,int minus)3475 char is_plus_minus(int i, int plus, int minus)
3476 {
3477   return (i == plus) ? '+' : (i == minus) ? '-' : ' ';
3478 }
3479 
3480 
3481 // We pass in dash to avoid looping over every job each time
show_job(struct sh_process * pp,char dash)3482 char *show_job(struct sh_process *pp, char dash)
3483 {
3484   char *s = "Run", *buf = 0;
3485   int i, j, len, len2;
3486 
3487 // TODO Terminated (Exited)
3488   if (pp->exit<0) s = "Stop";
3489   else if (pp->exit>126) s = "Kill";
3490   else if (pp->exit>0) s = "Done";
3491   for (i = len = len2 = 0;; i++) {
3492     len += snprintf(buf, len2, "[%d]%c  %-6s", pp->job, dash, s);
3493     for (j = 0; j<pp->raw->c; j++)
3494       len += snprintf(buf, len2, " %s"+!j, pp->raw->v[j]);
3495     if (!i) buf = xmalloc(len2 = len+1);
3496     else break;
3497   }
3498 
3499   return buf;
3500 }
3501 
3502 // Wait for pid to exit and remove from jobs table, returning process or 0.
wait_job(int pid,int nohang)3503 struct sh_process *wait_job(int pid, int nohang)
3504 {
3505   struct sh_process *pp = pp;
3506   int ii, status, minus, plus;
3507 
3508   if (TT.jobs.c<1) return 0;
3509   for (;;) {
3510     errno = 0;
3511     if (1>(pid = waitpid(pid, &status, nohang ? WNOHANG : 0))) {
3512       if (!nohang && errno==EINTR && !toys.signal) continue;
3513       return 0;
3514     }
3515     for (ii = 0; ii<TT.jobs.c; ii++) {
3516       pp = (void *)TT.jobs.v[ii];
3517       if (pp->pid == pid) break;
3518     }
3519     if (ii == TT.jobs.c) continue;
3520     if (pid<1) return 0;
3521     if (!WIFSTOPPED(status) && !WIFCONTINUED(status)) break;
3522   }
3523   plus = find_plus_minus(&minus);
3524   memmove(TT.jobs.v+ii, TT.jobs.v+ii+1, (TT.jobs.c--)-ii);
3525   pp->exit = WIFEXITED(status) ? WEXITSTATUS(status) : WTERMSIG(status)+128;
3526   pp->dash = is_plus_minus(ii, plus, minus);
3527 
3528   return pp;
3529 }
3530 
3531 // wait for every process in a pipeline to end
wait_pipeline(struct sh_process * pp)3532 static int wait_pipeline(struct sh_process *pp)
3533 {
3534   int rc = 0;
3535 
3536   for (dlist_terminate(pp); pp; pp = pp->next) {
3537     if (pp->pid) {
3538       // TODO job control: not xwait, handle EINTR ourselves and check signals
3539       pp->exit = xwaitpid(pp->pid);
3540       pp->pid = 0;
3541     }
3542     // TODO handle set -o pipefail here
3543     rc = (pp->flags&PFLAG_NOT) ? !pp->exit : pp->exit;
3544   }
3545 
3546   while ((pp = wait_job(-1, 1)) && (TT.options&FLAG_i)) {
3547     char *s = show_job(pp, pp->dash);
3548 
3549     dprintf(2, "%s\n", s);
3550     free(s);
3551   }
3552 
3553   return rc;
3554 }
3555 
3556 // Print prompt to stderr, parsing escapes
3557 // Truncated to 4k at the moment, waiting for somebody to complain.
do_prompt(char * prompt)3558 static void do_prompt(char *prompt)
3559 {
3560   char *s, *ss, c, cc, *pp = toybuf;
3561   int len, ll;
3562 
3563   if (!prompt) return;
3564   while ((len = sizeof(toybuf)-(pp-toybuf))>0 && *prompt) {
3565     c = *(prompt++);
3566 
3567     if (c=='!') {
3568       if (*prompt=='!') prompt++;
3569       else {
3570         pp += snprintf(pp, len, "%u", TT.LINENO);
3571         continue;
3572       }
3573     } else if (c=='\\') {
3574       cc = *(prompt++);
3575       if (!cc) {
3576         *pp++ = c;
3577         break;
3578       }
3579 
3580       // \nnn \dD{}hHjlstT@AuvVwW!#$
3581       // Ignore bash's "nonprintable" hack; query our cursor position instead.
3582       if (cc=='[' || cc==']') continue;
3583       else if (cc=='$') *pp++ = getuid() ? '$' : '#';
3584       else if (cc=='h' || cc=='H') {
3585         *pp = 0;
3586         gethostname(pp, len);
3587         pp[len-1] = 0;
3588         if (cc=='h' && (s = strchr(pp, '.'))) *s = 0;
3589         pp += strlen(pp);
3590       } else if (cc=='s') {
3591         s = getbasename(*toys.argv);
3592         while (*s && len--) *pp++ = *s++;
3593       } else if (cc=='w') {
3594         if ((s = getvar("PWD"))) {
3595           if ((ss = getvar("HOME")) && strstart(&s, ss)) {
3596             *pp++ = '~';
3597             if (--len && *s!='/') *pp++ = '/';
3598             len--;
3599           }
3600           if (len>0) {
3601             ll = strlen(s);
3602             pp = stpncpy(pp, s, ll>len ? len : ll);
3603           }
3604         }
3605       } else if (!(c = unescape(cc))) {
3606         *pp++ = '\\';
3607         if (--len) *pp++ = c;
3608       } else *pp++ = c;
3609     } else *pp++ = c;
3610   }
3611   len = pp-toybuf;
3612   if (len>=sizeof(toybuf)) len = sizeof(toybuf);
3613   writeall(2, toybuf, len);
3614 }
3615 
3616 // returns NULL for EOF, 1 for invalid, else null terminated string.
get_next_line(FILE * ff,int prompt)3617 static char *get_next_line(FILE *ff, int prompt)
3618 {
3619   char *new;
3620   int len, cc;
3621 
3622   if (!ff) {
3623     char ps[16];
3624 
3625     sprintf(ps, "PS%d", prompt);
3626     do_prompt(getvar(ps));
3627   }
3628 
3629 // TODO what should ctrl-C do? (also in "select")
3630 // TODO line editing/history, should set $COLUMNS $LINES and sigwinch update
3631 //  TODO: after first EINTR returns closed?
3632 // TODO: ctrl-z during script read having already read partial line,
3633 // SIGSTOP and SIGTSTP need SA_RESTART, but child proc should stop
3634 // TODO if (!isspace(*new)) add_to_history(line);
3635 // TODO: embedded nul bytes need signaling for the "tried to run binary" test.
3636 
3637   for (new = 0, len = 0;;) {
3638     errno = 0;
3639     if (!(cc = getc(ff ? : stdin))) {
3640       if (TT.LINENO) continue;
3641       free(new);
3642       return (char *)1;
3643     }
3644     if (cc<0) {
3645       if (errno == EINTR) continue;
3646       break;
3647     }
3648     if (!(len&63)) new = xrealloc(new, len+65);
3649     if ((new[len++] = cc) == '\n') break;
3650   }
3651   if (new) new[len] = 0;
3652 
3653   return new;
3654 }
3655 
3656 /*
3657  TODO: "echo | read i" is backgroundable with ctrl-Z despite read = builtin.
3658        probably have to inline run_command here to do that? Implicit ()
3659        also "X=42 | true; echo $X" doesn't get X.
3660        I.E. run_subshell() here sometimes? (But when?)
3661  TODO If we just started a new pipeline, implicit parentheses (subshell)
3662  TODO can't free sh_process delete until ready to dispose else no debug output
3663  TODO: a | b | c needs subshell for builtins?
3664         - anything that can produce output
3665         - echo declare dirs
3666       (a; b; c) like { } but subshell
3667       when to auto-exec? ps vs sh -c 'ps' vs sh -c '(ps)'
3668 */
3669 
3670 // run a parsed shell function. Handle flow control blocks and characters,
3671 // setup pipes and block redirection, break/continue, call builtins, functions,
3672 // vfork/exec external commands. Return when out of input.
run_lines(void)3673 static void run_lines(void)
3674 {
3675   char *ctl, *s, *ss, **vv;
3676   struct sh_process *pp, *pplist = 0; // processes piping into current level
3677   long i, j, k;
3678 
3679   // iterate through pipeline segments
3680   for (;;) {
3681     if (!TT.ff->pl) {
3682       if (!end_fcall(1)) break;
3683       goto advance;
3684     }
3685 
3686     ctl = TT.ff->pl->end->arg->v[TT.ff->pl->end->arg->c];
3687     s = *TT.ff->pl->arg->v;
3688     ss = TT.ff->pl->arg->v[1];
3689 //dprintf(2, "%d s=%s ss=%s ctl=%s type=%d pl=%p ff=%p\n", getpid(), (TT.ff->pl->type == 'F') ? ((struct sh_function *)s)->name : s, ss, ctl, TT.ff->pl->type, TT.ff->pl, TT.ff);
3690     if (!pplist) TT.hfd = 10;
3691 
3692     // Skip disabled blocks, handle pipes and backgrounding
3693     if (TT.ff->pl->type<2) {
3694       if (!TT.ff->blk->run) {
3695         TT.ff->pl = TT.ff->pl->end->next;
3696 
3697         continue;
3698       }
3699 
3700       if (TT.options&OPT_x) {
3701         unsigned lineno;
3702         char *ss, *ps4 = getvar("PS4");
3703 
3704         // duplicate first char of ps4 call depth times
3705         if (ps4 && *ps4) {
3706           j = getutf8(ps4, k = strlen(ps4), 0);
3707           ss = xmalloc(TT.srclvl*j+k+1);
3708           for (k = 0; k<TT.srclvl; k++) memcpy(ss+k*j, ps4, j);
3709           strcpy(ss+k*j, ps4+j);
3710           // show saved line number from function, not next to read
3711           lineno = TT.LINENO;
3712           TT.LINENO = TT.ff->pl->lineno;
3713           do_prompt(ss);
3714           TT.LINENO = lineno;
3715           free(ss);
3716 
3717           // TODO resolve variables
3718           ss = pl2str(TT.ff->pl, 1);
3719           dprintf(2, "%s\n", ss);
3720           free(ss);
3721         }
3722       }
3723 
3724       // pipe data into and out of this segment, I.E. leading/trailing |
3725       unredirect(TT.ff->blk->urd);
3726       TT.ff->blk->urd = 0;
3727       TT.ff->blk->pipe = 0;
3728 
3729       // Consume pipe from previous segment as stdin.
3730       if (TT.ff->blk->pout != -1) {
3731         TT.ff->blk->pipe++;
3732         if (save_redirect(&TT.ff->blk->urd, TT.ff->blk->pout, 0)) break;
3733         close(TT.ff->blk->pout);
3734         TT.ff->blk->pout = -1;
3735       }
3736 
3737       // Create output pipe and save next process's stdin in pout
3738       if (ctl && *ctl == '|' && ctl[1] != '|') {
3739         int pipes[2] = {-1, -1};
3740 
3741         TT.ff->blk->pipe++;
3742         if (pipe(pipes)) {
3743           perror_msg("pipe");
3744 
3745           break;
3746         }
3747         if (save_redirect(&TT.ff->blk->urd, pipes[1], 1)) {
3748           close(pipes[0]);
3749           close(pipes[1]);
3750 
3751           break;
3752         }
3753         if (pipes[1] != 1) close(pipes[1]);
3754         fcntl(TT.ff->blk->pout = *pipes, F_SETFD, FD_CLOEXEC);
3755         if (ctl[1] == '&') save_redirect(&TT.ff->blk->urd, 1, 2);
3756       }
3757     }
3758 
3759     // If executable segment parse and run next command saving resulting process
3760     if (!TT.ff->pl->type)
3761       dlist_add_nomalloc((void *)&pplist, (void *)run_command());
3762 
3763     // Start of flow control block?
3764     else if (TT.ff->pl->type == 1) {
3765 
3766 // TODO test cat | {thingy} is new PID: { is ( for |
3767 
3768       // perform/save trailing redirects
3769       pp = expand_redir(TT.ff->pl->end->arg, 1, TT.ff->blk->urd);
3770       TT.ff->blk->urd = pp->urd;
3771       pp->urd = 0;
3772       if (pp->arg.c) syntax_err(*pp->arg.v);
3773       llist_traverse(pp->delete, llist_free_arg);
3774       pp->delete = 0;
3775       if (pp->exit || pp->arg.c) {
3776         free(pp);
3777         toys.exitval = 1;
3778 
3779         break;
3780       }
3781       add_block();
3782 
3783 // TODO test background a block: { abc; } &
3784 
3785       // If we spawn a subshell, pass data off to child process
3786       if (TT.ff->blk->next->pipe || !strcmp(s, "(") || (ctl && !strcmp(ctl, "&"))) {
3787         if (!(pp->pid = run_subshell(0, -1))) {
3788 
3789           // zap forked child's cleanup context and advance to next statement
3790           pplist = 0;
3791           while (TT.ff->blk->next) TT.ff->blk = TT.ff->blk->next;
3792           TT.ff->blk->pout = -1;
3793           TT.ff->blk->urd = 0;
3794           TT.ff->pl = TT.ff->next->pl->next;
3795 
3796           continue;
3797         }
3798         TT.ff->pl = TT.ff->pl->end;
3799         pop_block();
3800         dlist_add_nomalloc((void *)&pplist, (void *)pp);
3801 
3802       // handle start of block in this process
3803       } else {
3804         free(pp);
3805 
3806         // What flow control statement is this?
3807 
3808         // {/} if/then/elif/else/fi, while until/do/done - no special handling
3809 
3810         // for/select/do/done: populate blk->farg with expanded args (if any)
3811         if (!strcmp(s, "for") || !strcmp(s, "select")) {
3812           if (TT.ff->blk->loop); // skip init, not first time through loop
3813 
3814           // in (;;)
3815           else if (!strncmp(TT.ff->blk->fvar = ss, "((", 2)) {
3816             char *in = ss+2, *out;
3817             long long ll;
3818 
3819             TT.ff->blk->loop = 1;
3820             for (i = 0; i<3; i++) {
3821               if (i==2) k = strlen(in)-2;
3822               else {
3823                 // perform expansion but immediately discard it to find ;
3824                 k = ';';
3825                 pp = xzalloc(sizeof(*pp));
3826                 if (expand_arg_nobrace(&pp->arg, ss+2, NO_PATH|NO_SPLIT,
3827                     &pp->delete, 0, &k)) break;
3828                 free_process(pp);
3829                 if (in[k] != ';') break;
3830               }
3831               (out = xmalloc(k+1))[k] = 0;
3832               memcpy(out, in, k);
3833               arg_add(&TT.ff->blk->farg, push_arg(&TT.ff->blk->fdelete, out));
3834               in += k+1;
3835             }
3836             if (i!=3) {
3837               syntax_err(ss);
3838               break;
3839             }
3840             in = out = *TT.ff->blk->farg.v;
3841             if (!recalculate(&ll, &in, 0) || *in) {
3842               perror_msg("bad math: %s @ %ld", in, (long)(in-out));
3843               break;
3844             }
3845 
3846           // in LIST
3847           } else if (TT.ff->pl->next->type == 's') {
3848             for (i = 1; i<TT.ff->pl->next->arg->c; i++)
3849               if (expand_arg(&TT.ff->blk->farg, TT.ff->pl->next->arg->v[i],
3850                              0, &TT.ff->blk->fdelete)) break;
3851             if (i != TT.ff->pl->next->arg->c) TT.ff->pl = pop_block();
3852 
3853           // in without LIST. (This expansion can't return error.)
3854           } else expand_arg(&TT.ff->blk->farg, "\"$@\"", 0,
3855                             &TT.ff->blk->fdelete);
3856 
3857           // TODO: ls -C style output
3858           if (*s == 's') for (i = 0; i<TT.ff->blk->farg.c; i++)
3859             dprintf(2, "%ld) %s\n", i+1, TT.ff->blk->farg.v[i]);
3860 
3861         // TODO: bash man page says it performs <(process substituion) here?!?
3862         } else if (!strcmp(s, "case")) {
3863           if (!(TT.ff->blk->fvar = expand_one_arg(ss, NO_NULL))) break;
3864           if (ss != TT.ff->blk->fvar)
3865             push_arg(&TT.ff->blk->fdelete, TT.ff->blk->fvar);
3866         }
3867 
3868 // TODO [[/]] ((/)) function/}
3869       }
3870 
3871     // gearshift from block start to block body (end of flow control test)
3872     } else if (TT.ff->pl->type == 2) {
3873       int match, err;
3874 
3875       TT.ff->blk->middle = TT.ff->pl;
3876 
3877       // ;; end, ;& continue through next block, ;;& test next block
3878       if (!strcmp(*TT.ff->blk->start->arg->v, "case")) {
3879         if (!strcmp(s, ";;")) {
3880           while (TT.ff->pl->type!=3) TT.ff->pl = TT.ff->pl->end;
3881           continue;
3882         } else if (strcmp(s, ";&")) {
3883           struct sh_arg arg = {0}, arg2 = {0};
3884 
3885           for (err = 0, vv = 0;;) {
3886             if (!vv) {
3887               vv = TT.ff->pl->arg->v + (**TT.ff->pl->arg->v == ';');
3888               if (!*vv) {
3889                 // TODO syntax err if not type==3, catch above
3890                 TT.ff->pl = TT.ff->pl->next;
3891                 break;
3892               } else vv += **vv == '(';
3893             }
3894             arg.c = arg2.c = 0;
3895             if ((err = expand_arg_nobrace(&arg, *vv++, NO_SPLIT,
3896               &TT.ff->blk->fdelete, &arg2, 0))) break;
3897             s = arg.c ? *arg.v : "";
3898             match = wildcard_match(TT.ff->blk->fvar, s, &arg2, 0);
3899             if (match>=0 && !s[match]) break;
3900             else if (**vv++ == ')') {
3901               vv = 0;
3902               if ((TT.ff->pl = TT.ff->pl->end)->type!=2) break;
3903             }
3904           }
3905           free(arg.v);
3906           free(arg2.v);
3907           if (err) break;
3908           if (TT.ff->pl->type==3) continue;
3909         }
3910 
3911       // Handle if/else/elif statement
3912       } else if (!strcmp(s, "then")) {
3913 do_then:
3914         TT.ff->blk->run = TT.ff->blk->run && !toys.exitval;
3915         toys.exitval = 0;
3916       } else if (!strcmp(s, "else") || !strcmp(s, "elif"))
3917         TT.ff->blk->run = !TT.ff->blk->run;
3918 
3919       // Loop
3920       else if (!strcmp(s, "do")) {
3921         struct sh_blockstack *blk = TT.ff->blk;
3922 
3923         ss = *blk->start->arg->v;
3924         if (!strcmp(ss, "while")) goto do_then;
3925         else if (!strcmp(ss, "until")) {
3926           blk->run = blk->run && toys.exitval;
3927           toys.exitval = 0;
3928         } else if (!strcmp(ss, "select")) {
3929           if (!(ss = get_next_line(0, 3)) || ss==(void *)1) {
3930             TT.ff->pl = pop_block();
3931             printf("\n");
3932           } else {
3933             match = atoi(ss);
3934             i = *s;
3935             free(ss);
3936             if (!i) {
3937               TT.ff->pl = blk->start;
3938               continue;
3939             } else setvarval(blk->fvar, (match<1 || match>blk->farg.c)
3940                                         ? "" : blk->farg.v[match-1]);
3941           }
3942         } else if (blk->loop >= blk->farg.c) TT.ff->pl = pop_block();
3943         else if (!strncmp(blk->fvar, "((", 2)) {
3944           char *aa, *bb;
3945           long long ll;
3946 
3947           for (i = 2; i; i--) {
3948             if (TT.ff->blk->loop == 1) {
3949               TT.ff->blk->loop++;
3950               i--;
3951             }
3952             aa = bb = TT.ff->blk->farg.v[i];
3953             if (!recalculate(&ll, &aa, 0) || *aa) {
3954               perror_msg("bad math: %s @ %ld", aa, (long)(aa-bb));
3955               break;
3956             }
3957             if (i==1 && !ll) TT.ff->pl = pop_block();
3958           }
3959         } else setvarval(blk->fvar, blk->farg.v[blk->loop++]);
3960       }
3961 
3962     // end of block
3963     } else if (TT.ff->pl->type == 3) {
3964       // If we end a block we're not in, exit subshell
3965       if (!TT.ff->blk->next) xexit();
3966 
3967       // repeating block?
3968       if (TT.ff->blk->run && !strcmp(s, "done")) {
3969         TT.ff->pl = (**TT.ff->blk->start->arg->v == 'w')
3970           ? TT.ff->blk->start->next : TT.ff->blk->middle;
3971         continue;
3972       }
3973 
3974       // cleans up after trailing redirections/pipe
3975       pop_block();
3976 
3977     // declare a shell function
3978     } else if (TT.ff->pl->type == 'F') {
3979       struct sh_function *funky = (void *)*TT.ff->pl->arg->v;
3980 
3981 // TODO binary search
3982       for (i = 0; i<TT.funcslen; i++)
3983         if (!strcmp(TT.functions[i]->name, funky->name)) break;
3984       if (i == TT.funcslen) {
3985         struct sh_arg arg = {(void *)TT.functions, TT.funcslen};
3986 
3987         arg_add(&arg, (void *)funky); // TODO possibly an expand@31 function?
3988         TT.functions = (void *)arg.v;
3989         TT.funcslen++;
3990       } else {
3991         free_function(TT.functions[i]);
3992         TT.functions[i] = funky;
3993       }
3994       TT.functions[i]->refcount++;
3995     }
3996 
3997     // Three cases: 1) background & 2) pipeline | 3) last process in pipeline ;
3998     // If we ran a process and didn't pipe output, background or wait for exit
3999     if (pplist && TT.ff->blk->pout == -1) {
4000       if (ctl && !strcmp(ctl, "&")) {
4001         if (!TT.jobs.c) TT.jobcnt = 0;
4002         pplist->job = ++TT.jobcnt;
4003         arg_add(&TT.jobs, (void *)pplist);
4004         if (TT.options&FLAG_i) dprintf(2, "[%u] %u\n", pplist->job,pplist->pid);
4005       } else {
4006         toys.exitval = wait_pipeline(pplist);
4007         llist_traverse(pplist, (void *)free_process);
4008       }
4009       pplist = 0;
4010     }
4011 advance:
4012     // for && and || skip pipeline segment(s) based on return code
4013     if (!TT.ff->pl->type || TT.ff->pl->type == 3) {
4014       for (;;) {
4015         ctl = TT.ff->pl->arg->v[TT.ff->pl->arg->c];
4016         if (!ctl || strcmp(ctl, toys.exitval ? "&&" : "||")) break;
4017         if ((TT.ff->pl = TT.ff->pl->next)->type) TT.ff->pl = TT.ff->pl->end;
4018       }
4019     }
4020     TT.ff->pl = TT.ff->pl->next;
4021   }
4022 
4023   // clean up any unfinished stuff
4024   if (pplist) {
4025     toys.exitval = wait_pipeline(pplist);
4026     llist_traverse(pplist, (void *)free_process);
4027   }
4028 
4029   // exit source context (and function calls on syntax err)
4030   while (end_fcall(0));
4031 }
4032 
4033 // set variable
initvar(char * name,char * val)4034 static struct sh_vars *initvar(char *name, char *val)
4035 {
4036   return addvar(xmprintf("%s=%s", name, val ? val : ""), TT.ff);
4037 }
4038 
initvardef(char * name,char * val,char * def)4039 static struct sh_vars *initvardef(char *name, char *val, char *def)
4040 {
4041   return initvar(name, (!val || !*val) ? def : val);
4042 }
4043 
4044 // export existing "name" or assign/export name=value string (making new copy)
set_varflags(char * str,unsigned set_flags,unsigned unset_flags)4045 static void set_varflags(char *str, unsigned set_flags, unsigned unset_flags)
4046 {
4047   struct sh_vars *shv = 0;
4048   struct sh_fcall *ff;
4049   char *s;
4050 
4051   // Make sure variable exists and is updated
4052   if (strchr(str, '=')) shv = setvar(xstrdup(str));
4053   else if (!(shv = findvar(str, &ff))) {
4054     if (!set_flags) return;
4055     shv = addvar(str = xmprintf("%s=", str), TT.ff->prev);
4056     shv->flags = VAR_WHITEOUT;
4057   } else if (shv->flags&VAR_WHITEOUT) shv->flags |= VAR_EXPORT;
4058   if (!shv || (shv->flags&VAR_EXPORT)) return;
4059 
4060   // Resolve magic for export (bash bug compatibility, really should be dynamic)
4061   if (shv->flags&VAR_MAGIC) {
4062     s = shv->str;
4063     shv->str = xmprintf("%.*s=%s", (int)(varend(str)-str), str, getvar(str));
4064     if (!(shv->flags&VAR_NOFREE)) free(s);
4065     else shv->flags ^= VAR_NOFREE;
4066   }
4067   shv->flags |= set_flags;
4068   shv->flags &= ~unset_flags;
4069 }
4070 
export(char * str)4071 static void export(char *str)
4072 {
4073   set_varflags(str, VAR_EXPORT, 0);
4074 }
4075 
fpathopen(char * name)4076 FILE *fpathopen(char *name)
4077 {
4078   int fd = open(name, O_RDONLY|O_CLOEXEC), ii;
4079   struct string_list *sl = 0;
4080   char *pp = getvar("PATH") ? : _PATH_DEFPATH;
4081 
4082   if (fd==-1) {
4083     for (sl = find_in_path(pp, name); sl; free(llist_pop(&sl)))
4084       if (-1==(fd = open(sl->str, O_RDONLY|O_CLOEXEC))) break;
4085     if (sl) llist_traverse(sl, free);
4086   }
4087   if (fd != -1) {
4088     dup2(fd, ii = next_hfd());
4089     fcntl(ii, F_SETFD, FD_CLOEXEC);
4090     close(fd);
4091     fd = ii;
4092   }
4093 
4094   return fd==-1 ? 0 : fdopen(fd, "r");
4095 }
4096 
4097 // Read script input and execute lines, with or without prompts
4098 // If !ff input is interactive (prompt, editing, etc)
do_source(char * name,FILE * ff)4099 int do_source(char *name, FILE *ff)
4100 {
4101   struct sh_pipeline *pl = 0;
4102   struct double_list *expect = 0;
4103   unsigned lineno = TT.LINENO, more = 0, wc;
4104   int cc, ii;
4105   char *new;
4106 
4107   TT.recfile[TT.recursion++] = ff ? fileno(ff) : 0;
4108   if (TT.recursion++>ARRAY_LEN(TT.recfile)) {
4109     error_msg("recursive occlusion");
4110 
4111     goto end;
4112   }
4113 
4114   if (name) TT.ff->omnom = name;
4115 
4116 // TODO fix/catch O_NONBLOCK on input?
4117 // TODO when DO we reset lineno? (!LINENO means \0 returns 1)
4118 // when do we NOT reset lineno? Inherit but preserve perhaps? newline in $()?
4119   if (!name) TT.LINENO = 0;
4120 
4121   do {
4122     if ((void *)1 == (new = get_next_line(ff, more+1))) goto is_binary;
4123 //dprintf(2, "%d getline from %p %s\n", getpid(), ff, new); debug_show_fds();
4124     // did we exec an ELF file or something?
4125     if (!TT.LINENO++ && name && new) {
4126       // A shell script's first line has no high bytes that aren't valid utf-8.
4127       for (ii = 0; new[ii]>6 && 0<(cc = utf8towc(&wc, new+ii, 4)); ii += cc);
4128       if (new[ii]) {
4129 is_binary:
4130         if (name) error_msg("'%s' is binary", name); // TODO syntax_err() exit?
4131         if (new != (void *)1) free(new);
4132         new = 0;
4133       }
4134     }
4135 
4136     // TODO: source <(echo 'echo hello\') vs source <(echo -n 'echo hello\')
4137     // prints "hello" vs "hello\"
4138 
4139     // returns 0 if line consumed, command if it needs more data
4140     more = parse_line(new, &pl, &expect);
4141     free(new);
4142     if (more==1) {
4143       if (!new) syntax_err("unexpected end of file");
4144       else continue;
4145     } else if (!more && pl) {
4146       TT.ff->pl = pl;
4147       run_lines();
4148     } else more = 0;
4149 
4150     llist_traverse(pl, free_pipeline);
4151     pl = 0;
4152     llist_traverse(expect, free);
4153     expect = 0;
4154   } while (new);
4155 
4156   if (ff) fclose(ff);
4157 
4158   if (!name) TT.LINENO = lineno;
4159 
4160 end:
4161   TT.recursion--;
4162 
4163   return more;
4164 }
4165 
4166 // On nommu we had to exec(), so parent environment is passed via a pipe.
nommu_reentry(void)4167 static void nommu_reentry(void)
4168 {
4169   struct stat st;
4170   int ii, pid, ppid, len;
4171   unsigned long ll;
4172   char *s = 0;
4173   FILE *fp;
4174 
4175   // Sanity check
4176   if (!fstat(254, &st) && S_ISFIFO(st.st_mode)) {
4177     for (ii = len = 0; (s = environ[ii]); ii++) {
4178       if (*s!='@') continue;
4179       sscanf(s, "@%u,%u%n", &pid, &ppid, &len);
4180       break;
4181     }
4182   }
4183   if (!s || s[len] || pid!=getpid() || ppid!=getppid()) error_exit(0);
4184 
4185 // TODO signal setup before this so fscanf can't EINTR.
4186 // TODO marshall TT.jobcnt TT.funcslen: child needs jobs and function list
4187   // Marshall magics: $SECONDS $- $LINENO $$ $!
4188   if (5!=fscanf(fp = fdopen(254, "r"), "%lld %u %u %u %u%*[^\n]", &TT.SECONDS,
4189       &TT.options, &TT.LINENO, &TT.pid, &TT.bangpid)) error_exit(0);
4190 
4191   // Read named variables: type, len, var=value\0
4192   for (;;) {
4193     len = ll = 0;
4194     (void)fscanf(fp, "%u %lu%*[^\n]", &len, &ll);
4195     fgetc(fp); // Discard the newline fscanf didn't eat.
4196     if (!len) break;
4197     (s = xmalloc(len+1))[len] = 0;
4198     for (ii = 0; ii<len; ii += pid)
4199       if (1>(pid = fread(s+ii, 1, len-ii, fp))) error_exit(0);
4200     set_varflags(s, ll, 0);
4201   }
4202 
4203   // Perform subshell command(s)
4204   do_source(0, fp);
4205   xexit();
4206 }
4207 
4208 // init locals, sanitize environment, handle nommu subshell handoff
subshell_setup(void)4209 static void subshell_setup(void)
4210 {
4211   int ii, from, uid = getuid();
4212   struct passwd *pw = getpwuid(uid);
4213   char *s, *ss, *magic[] = {"SECONDS", "RANDOM", "LINENO", "GROUPS", "BASHPID",
4214     "EPOCHREALTIME", "EPOCHSECONDS"},
4215     *readonly[] = {xmprintf("EUID=%d", geteuid()), xmprintf("UID=%d", uid),
4216                    xmprintf("PPID=%d", getppid())};
4217   struct sh_vars *shv;
4218   struct utsname uu;
4219 
4220   // Initialize magic and read only local variables
4221   for (ii = 0; ii<ARRAY_LEN(magic) && (s = magic[ii]); ii++)
4222     initvar(s, "")->flags = VAR_MAGIC+VAR_INT*('G'!=*s)+VAR_READONLY*('B'==*s);
4223   for (ii = 0; ii<ARRAY_LEN(readonly); ii++)
4224     addvar(readonly[ii], TT.ff)->flags = VAR_READONLY|VAR_INT;
4225 
4226   // Add local variables that can be overwritten
4227   initvar("PATH", _PATH_DEFPATH);
4228   if (!pw) pw = (void *)toybuf; // first use, so still zeroed
4229   sprintf(toybuf+1024, "%u", uid);
4230   initvardef("HOME", pw->pw_dir, "/");
4231   initvardef("SHELL", pw->pw_shell, "/bin/sh");
4232   initvardef("USER", pw->pw_name, toybuf+1024);
4233   initvardef("LOGNAME", pw->pw_name, toybuf+1024);
4234   gethostname(toybuf, sizeof(toybuf)-1);
4235   initvar("HOSTNAME", toybuf);
4236   uname(&uu);
4237   initvar("HOSTTYPE", uu.machine);
4238   sprintf(toybuf, "%s-unknown-linux", uu.machine);
4239   initvar("MACHTYPE", toybuf);
4240   initvar("OSTYPE", uu.sysname);
4241   // sprintf(toybuf, "%s-toybox", TOYBOX_VERSION);
4242   // initvar("BASH_VERSION", toybuf); TODO
4243   initvar("OPTERR", "1"); // TODO: test if already exported?
4244   if (readlink0("/proc/self/exe", s = toybuf, sizeof(toybuf))||(s=getenv("_")))
4245     initvar("BASH", s);
4246   initvar("PS2", "> ");
4247   initvar("PS3", "#? ");
4248   initvar("PS4", "+ ");
4249 
4250   // Ensure environ copied and toys.envc set, and clean out illegal entries
4251   for (from = 0; (s = environ[from]); from++) {
4252     if (*varend(s) != '=') continue;
4253     if (!(shv = findvar(s, 0))) addvar(s, TT.ff)->flags = VAR_EXPORT|VAR_NOFREE;
4254     else if (shv->flags&VAR_READONLY) continue;
4255     else {
4256       if (!(shv->flags&VAR_NOFREE)) {
4257         free(shv->str);
4258         shv->flags ^= VAR_NOFREE;
4259       }
4260       shv->flags |= VAR_EXPORT;
4261       shv->str = s;
4262     }
4263     cache_ifs(s, TT.ff); // TODO: replace with set(get("IFS")) after loop
4264   }
4265 
4266   // set/update PWD
4267   do_source(0, fmemopen("cd .", 4, "r"));
4268 
4269   // set _ to path to this shell
4270   s = toys.argv[0];
4271   ss = 0;
4272   if (!strchr(s, '/')) {
4273     if ((ss = getcwd(0, 0))) {
4274       s = xmprintf("%s/%s", ss, s);
4275       free(ss);
4276       ss = s;
4277     } else if (*toybuf) s = toybuf; // from /proc/self/exe
4278   }
4279   setvarval("_", s)->flags |= VAR_EXPORT;
4280   free(ss);
4281 
4282   // TODO: this is in pipe, not environment
4283   if (!(ss = getvar("SHLVL"))) export("SHLVL=1"); // Bash 5.0
4284   else {
4285     char buf[16];
4286 
4287     sprintf(buf, "%u", atoi(ss+6)+1);
4288     setvarval("SHLVL", buf)->flags |= VAR_EXPORT;
4289   }
4290 }
4291 
sh_main(void)4292 void sh_main(void)
4293 {
4294   char *cc = 0;
4295   FILE *ff;
4296 
4297 //dprintf(2, "%d main", getpid()); for (unsigned uu = 0; toys.argv[uu]; uu++) dprintf(2, " %s", toys.argv[uu]); dprintf(2, "\n");
4298 
4299   signal(SIGPIPE, SIG_IGN);
4300   TT.options = OPT_B;
4301   TT.pid = getpid();
4302   srandom(TT.SECONDS = millitime());
4303 
4304   // TODO euid stuff?
4305   // TODO login shell?
4306   // TODO read profile, read rc
4307 
4308   // if (!FLAG(noprofile)) { }
4309 
4310   // If not reentering, figure out if this is an interactive shell.
4311   if (toys.stacktop) {
4312     cc = TT.sh.c;
4313     if (!FLAG(c)) {
4314       if (toys.optc==1) toys.optflags |= FLAG_s;
4315       if (FLAG(s) && isatty(0)) toys.optflags |= FLAG_i;
4316     }
4317     if (toys.optc>1) {
4318       toys.optargs++;
4319       toys.optc--;
4320     }
4321     TT.options |= toys.optflags&0xff;
4322   }
4323 
4324   // Create initial function context
4325   call_function();
4326   TT.ff->arg.v = toys.optargs;
4327   TT.ff->arg.c = toys.optc;
4328   TT.ff->ifs = " \t\n";
4329 
4330   // Set up environment variables.
4331   // Note: can call run_command() which blanks argument sections of TT and this,
4332   // so parse everything we need from shell command line before here.
4333   if (CFG_TOYBOX_FORK || toys.stacktop) subshell_setup(); // returns
4334   else nommu_reentry(); // does not return
4335 
4336   if (TT.options&FLAG_i) {
4337     if (!getvar("PS1")) setvarval("PS1", getpid() ? "\\$ " : "# ");
4338     // TODO Set up signal handlers and grab control of this tty.
4339     // ^C SIGINT ^\ SIGQUIT ^Z SIGTSTP SIGTTIN SIGTTOU SIGCHLD
4340     // setsid(), setpgid(), tcsetpgrp()...
4341     xsignal(SIGINT, SIG_IGN);
4342   }
4343 
4344   if (cc) ff = fmemopen(cc, strlen(cc), "r");
4345   else if (TT.options&FLAG_s) ff = (TT.options&FLAG_i) ? 0 : stdin;
4346   else if (!(ff = fpathopen(*toys.optargs))) perror_exit_raw(*toys.optargs);
4347 
4348   // Read and execute lines from file
4349   if (do_source(cc ? : *toys.optargs, ff))
4350     error_exit("%u:unfinished line"+3*!TT.LINENO, TT.LINENO);
4351 }
4352 
4353 // TODO: ./blah.sh one two three: put one two three in scratch.arg
4354 
4355 /********************* shell builtin functions *************************/
4356 
4357 // Note: "break &" in bash breaks in the child, this breaks in the parent.
break_main(void)4358 void break_main(void)
4359 {
4360   int i = *toys.optargs ? atolx_range(*toys.optargs, 1, INT_MAX) : 1;
4361 
4362   // Peel off encosing do blocks
4363   while (i && TT.ff->blk->next)
4364     if (TT.ff->blk->middle && !strcmp(*TT.ff->blk->middle->arg->v, "do")
4365         && !--i && *toys.which->name=='c') TT.ff->pl = TT.ff->blk->start;
4366     else TT.ff->pl = pop_block();
4367 }
4368 
4369 #define FOR_cd
4370 #include "generated/flags.h"
cd_main(void)4371 void cd_main(void)
4372 {
4373   char *from, *to = 0, *dd = *toys.optargs ? : (getvar("HOME") ? : "/"),
4374        *pwd = FLAG(P) ? 0 : getvar("PWD"), *zap = 0;
4375   struct stat st1, st2;
4376 
4377   // TODO: CDPATH? Really?
4378 
4379   // For cd - use $OLDPWD as destination directory
4380   if (!strcmp(dd, "-") && (!(dd = getvar("OLDPWD")) || !*dd))
4381     return perror_msg("No $OLDPWD");
4382 
4383   if (*dd == '/') pwd = 0;
4384 
4385   // Did $PWD move out from under us?
4386   if (pwd && !stat(".", &st1))
4387     if (stat(pwd, &st2) || st1.st_dev!=st2.st_dev || st1.st_ino!=st2.st_ino)
4388       pwd = 0;
4389 
4390   // Handle logical relative path
4391   if (pwd) {
4392     zap = xmprintf("%s/%s", pwd, dd);
4393 
4394     // cancel out . and .. in the string
4395     for (from = to = zap; *from;) {
4396       if (*from=='/' && from[1]=='/') from++;
4397       else if (*from!='/' || from[1]!='.') *to++ = *from++;
4398       else if (!from[2] || from[2]=='/') from += 2;
4399       else if (from[2]=='.' && (!from[3] || from[3]=='/')) {
4400         from += 3;
4401         while (to>zap && *--to != '/');
4402       } else *to++ = *from++;
4403     }
4404     if (to == zap) to++;
4405     if (to-zap>1 && to[-1]=='/') to--;
4406     *to = 0;
4407   }
4408 
4409   // If logical chdir doesn't work, fall back to physical
4410   if (!zap || chdir(zap)) {
4411     free(zap);
4412     if (chdir(dd)) return perror_msg("%s", dd);
4413     if (!(dd = getcwd(0, 0))) dd = xstrdup("(nowhere)");
4414   } else dd = zap;
4415 
4416   if ((pwd = getvar("PWD"))) setvarval("OLDPWD", pwd);
4417   setvarval("PWD", dd);
4418   free(dd);
4419 
4420   if (!(TT.options&OPT_cd)) {
4421     export("OLDPWD");
4422     export("PWD");
4423     TT.options |= OPT_cd;
4424   }
4425 }
4426 
continue_main(void)4427 void continue_main(void)
4428 {
4429   break_main();
4430 }
4431 
exit_main(void)4432 void exit_main(void)
4433 {
4434   toys.exitval = *toys.optargs ? atoi(*toys.optargs) : 0;
4435   toys.rebound = 0;
4436   // TODO trap EXIT, sigatexit
4437   xexit();
4438 }
4439 
4440 // lib/args.c can't +prefix & "+o history" needs space so parse cmdline here
set_main(void)4441 void set_main(void)
4442 {
4443   char *cc, *ostr[] = {"braceexpand", "noclobber", "xtrace"};
4444   int ii, jj, kk, oo = 0, dd = 0;
4445 
4446   // display visible variables
4447   if (!*toys.optargs) {
4448     struct sh_vars **vv = visible_vars();
4449 
4450 // TODO escape properly
4451     for (ii = 0; vv[ii]; ii++)
4452       if (!(vv[ii]->flags&VAR_WHITEOUT)) printf("%s\n", vv[ii]->str);
4453     free(vv);
4454 
4455     return;
4456   }
4457 
4458   // Handle options
4459   for (ii = 0;; ii++) {
4460     if ((cc = toys.optargs[ii]) && !(dd = stridx("-+", *cc)+1) && oo--) {
4461       for (jj = 0; jj<ARRAY_LEN(ostr); jj++) if (!strcmp(cc, ostr[jj])) break;
4462       if (jj != ARRAY_LEN(ostr)) {
4463         if (dd==1) TT.options |= OPT_B<<kk;
4464         else TT.options &= ~(OPT_B<<kk);
4465 
4466         continue;
4467       }
4468       error_exit("bad -o %s", cc);
4469     }
4470     if (oo>0) for (jj = 0; jj<ARRAY_LEN(ostr); jj++)
4471       printf("%s\t%s\n", ostr[jj], TT.options&(OPT_B<<jj) ? "on" : "off");
4472     oo = 0;
4473     if (!cc || !dd) break;
4474     for (jj = 1; cc[jj]; jj++) {
4475       if (cc[jj] == 'o') oo++;
4476       else if (-1 != (kk = stridx("BCxu", cc[jj]))) {
4477         if (*cc == '-') TT.options |= OPT_B<<kk;
4478         else TT.options &= ~(OPT_B<<kk);
4479       } else error_exit("bad -%c", toys.optargs[ii][1]);
4480     }
4481   }
4482 
4483   // handle positional parameters
4484   if (cc) {
4485     struct arg_list *al, **head;
4486     struct sh_arg *arg = &TT.ff->arg;
4487 
4488     // don't free memory that's already scheduled for deletion
4489     for (al = *(head = &TT.ff->delete); al; al = *(head = &al->next))
4490       if (al->arg == (void *)arg->v) break;
4491 
4492     // free last set's memory (if any) so it doesn't accumulate in loop
4493     if (al) for (jj = arg->c+1; jj; jj--) {
4494       *head = al->next;
4495       free(al->arg);
4496       free(al);
4497     }
4498 
4499     while (toys.optargs[ii])
4500       arg_add(arg, push_arg(&TT.ff->delete, strdup(toys.optargs[ii++])));
4501     push_arg(&TT.ff->delete, arg->v);
4502   }
4503 }
4504 
4505 // TODO need test: unset clears var first and stops, function only if no var.
4506 #define FOR_unset
4507 #include "generated/flags.h"
4508 
unset_main(void)4509 void unset_main(void)
4510 {
4511   char **arg, *s;
4512   int ii;
4513 
4514   for (arg = toys.optargs; *arg; arg++) {
4515     s = varend(*arg);
4516     if (s == *arg || *s) {
4517       error_msg("bad '%s'", *arg);
4518       continue;
4519     }
4520 
4521     // TODO -n and name reference support
4522     // unset variable
4523     if (!FLAG(f) && unsetvar(*arg)) continue;
4524     // unset function TODO binary search
4525     for (ii = 0; ii<TT.funcslen; ii++)
4526       if (!strcmp(*arg, TT.functions[ii]->name)) break;
4527     if (ii != TT.funcslen) {
4528       free_function(TT.functions[ii]);
4529       memmove(TT.functions+ii, TT.functions+ii+1, TT.funcslen+1-ii);
4530     }
4531   }
4532 }
4533 
4534 #define FOR_export
4535 #include "generated/flags.h"
4536 
export_main(void)4537 void export_main(void)
4538 {
4539   char **arg, *eq;
4540 
4541   // list existing variables?
4542   if (!toys.optc) {
4543     struct sh_vars **vv = visible_vars();
4544     unsigned uu;
4545 
4546     for (uu = 0; vv[uu]; uu++) {
4547       if ((vv[uu]->flags&(VAR_WHITEOUT|VAR_EXPORT))==VAR_EXPORT) {
4548         xputs(eq = declarep(vv[uu]));
4549         free(eq);
4550       }
4551     }
4552     free(vv);
4553 
4554     return;
4555   }
4556 
4557   // set/move variables
4558   for (arg = toys.optargs; *arg; arg++) {
4559     eq = varend(*arg);
4560     if (eq == *arg || (*eq && eq[*eq=='+'] != '=')) {
4561       error_msg("bad %s", *arg);
4562       continue;
4563     }
4564 
4565     if (FLAG(n)) set_varflags(*arg, 0, VAR_EXPORT);
4566     else export(*arg);
4567   }
4568 }
4569 
4570 #define FOR_declare
4571 #include "generated/flags.h"
4572 
declare_main(void)4573 void declare_main(void)
4574 {
4575   unsigned uu, fl = toys.optflags&(FLAG(p)-1);
4576   char *ss, **arg;
4577 // TODO: need a show_vars() to collate all the visible_vars() loop output
4578 // TODO: -g support including -gp
4579 // TODO: dump everything key=value and functions too
4580   if (!toys.optc) {
4581     struct sh_vars **vv = visible_vars();
4582 
4583     for (uu = 0; vv[uu]; uu++) {
4584       if ((vv[uu]->flags&VAR_WHITEOUT) || (fl && !(vv[uu]->flags&fl))) continue;
4585       xputs(ss = declarep(vv[uu]));
4586       free(ss);
4587     }
4588     free(vv);
4589   } else if (FLAG(p)) for (arg = toys.optargs; *arg; arg++) {
4590     struct sh_vars *vv = *varend(ss = *arg) ? 0 : findvar(ss, 0);
4591 
4592     if (!vv) perror_msg("%s: not found", ss);
4593     else {
4594       xputs(ss = declarep(vv));
4595       free(ss);
4596     }
4597   } else for (arg = toys.optargs; *arg; arg++) {
4598     ss = varend(*arg);
4599     if (ss == *arg || (*ss && ss[*ss=='+'] != '=')) {
4600       error_msg("bad %s", *arg);
4601       continue;
4602     }
4603     set_varflags(*arg, toys.optflags<<1, 0); // TODO +x unset
4604   }
4605 }
4606 
eval_main(void)4607 void eval_main(void)
4608 {
4609   char *s;
4610 
4611   // borrow the $* expand infrastructure
4612   call_function();
4613   TT.ff->arg.v = toys.argv;
4614   TT.ff->arg.c = toys.optc+1;
4615   s = expand_one_arg("\"$*\"", SEMI_IFS);
4616   TT.ff->arg.v = TT.ff->next->arg.v;
4617   TT.ff->arg.c = TT.ff->next->arg.c;
4618   do_source(0, fmemopen(s, strlen(s), "r"));
4619   free(dlist_pop(&TT.ff));
4620   free(s);
4621 }
4622 
4623 #define FOR_exec
4624 #include "generated/flags.h"
4625 
exec_main(void)4626 void exec_main(void)
4627 {
4628   char *ee[1] = {0}, **old = environ;
4629 
4630   // discard redirects and return if nothing to exec
4631   free(TT.pp->urd);
4632   TT.pp->urd = 0;
4633   if (!toys.optc) return;
4634 
4635   // exec, handling -acl
4636   TT.isexec = *toys.optargs;
4637   if (FLAG(c)) environ = ee;
4638   if (TT.exec.a || FLAG(l))
4639     *toys.optargs = xmprintf("%s%s", FLAG(l) ? "-" : "", TT.exec.a?:TT.isexec);
4640   sh_exec(toys.optargs);
4641 
4642   // report error (usually ENOENT) and return
4643   if (*toys.optargs != TT.isexec) free(*toys.optargs);
4644   TT.isexec = 0;
4645   toys.exitval = 127;
4646   environ = old;
4647 }
4648 
4649 // Return T.jobs index or -1 from identifier
4650 // Note, we don't return "ambiguous job spec", we return the first hit or -1.
4651 // TODO %% %+ %- %?ab
find_job(char * s)4652 int find_job(char *s)
4653 {
4654   char *ss;
4655   long ll = strtol(s, &ss, 10);
4656   int i, j;
4657 
4658   if (!TT.jobs.c) return -1;
4659   if (!*s || (!s[1] && strchr("%+-", *s))) {
4660     int minus, plus = find_plus_minus(&minus);
4661 
4662     return (*s == '-') ? minus : plus;
4663   }
4664 
4665   // Is this a %1 numeric jobspec?
4666   if (s != ss && !*ss)
4667     for (i = 0; i<TT.jobs.c; i++)
4668       if (((struct sh_process *)TT.jobs.v[i])->job == ll) return i;
4669 
4670   // Match start of command or %?abc
4671   for (i = 0; i<TT.jobs.c; i++) {
4672     struct sh_process *pp = (void *)TT.jobs.v[i];
4673 
4674     if (strstart(&s, *pp->arg.v)) return i;
4675     if (*s != '?' || !s[1]) continue;
4676     for (j = 0; j<pp->arg.c; j++) if (strstr(pp->arg.v[j], s+1)) return i;
4677   }
4678 
4679   return -1;
4680 }
4681 
jobs_main(void)4682 void jobs_main(void)
4683 {
4684   int i, j, minus, plus = find_plus_minus(&minus);
4685   char *s;
4686 
4687 // TODO -lnprs
4688 
4689   for (i = 0;;i++) {
4690     if (toys.optc) {
4691       if (!(s = toys.optargs[i])) break;
4692       if ((j = find_job(s+('%' == *s))) == -1) {
4693         perror_msg("%s: no such job", s);
4694 
4695         continue;
4696       }
4697     } else if ((j = i) >= TT.jobs.c) break;
4698 
4699     s = show_job((void *)TT.jobs.v[i], is_plus_minus(i, plus, minus));
4700     printf("%s\n", s);
4701     free(s);
4702   }
4703 }
4704 
4705 #define FOR_local
4706 #include "generated/flags.h"
4707 
local_main(void)4708 void local_main(void)
4709 {
4710   struct sh_fcall *ff, *ff2;
4711   struct sh_vars *var;
4712   char **arg, *eq;
4713 
4714   // find local variable context
4715   for (ff = TT.ff;; ff = ff->next) {
4716     if (ff == TT.ff->prev) return error_msg("not in function");
4717     if (ff->vars) break;
4718   }
4719 
4720   // list existing vars (todo:
4721   if (!toys.optc) {
4722     for (var = ff->vars; var; var++) xputs(var->str); // TODO escape
4723     return;
4724   }
4725 
4726   // set/move variables
4727   for (arg = toys.optargs; *arg; arg++) {
4728     if ((eq = varend(*arg)) == *arg || (*eq && *eq != '=')) {
4729       error_msg("bad %s", *arg);
4730       continue;
4731     }
4732 
4733     if ((var = findvar(*arg, &ff2)) && ff == ff2 && !*eq) continue;
4734     if (var && (var->flags&VAR_READONLY)) {
4735       error_msg("%.*s: readonly variable", (int)(varend(*arg)-*arg), *arg);
4736       continue;
4737     }
4738 
4739     // Add local inheriting global status and setting whiteout if blank.
4740     if (!var || ff!=ff2) {
4741       int flags = var ? var->flags&VAR_EXPORT : 0;
4742 
4743       var = addvar(xmprintf("%s%s", *arg, *eq ? "" : "="), ff);
4744       var->flags = flags|(VAR_WHITEOUT*!*eq);
4745     }
4746 
4747     // TODO accept declare options to set more flags
4748     // TODO, integer, uppercase take effect. Setvar?
4749   }
4750 }
4751 
return_main(void)4752 void return_main(void)
4753 {
4754   struct sh_fcall *ff;
4755   char *ss;
4756 
4757   if (*toys.optargs) {
4758     toys.exitval = estrtol(*toys.optargs, &ss, 0);
4759     if (errno || *ss) error_msg("NaN");
4760   }
4761 
4762   // Do we have a non-transparent function context in the call stack?
4763   for (ff = TT.ff; !ff->func; ff = ff->next)
4764     if (ff == TT.ff->prev) return error_msg("not function or source");
4765 
4766   // Pop all blocks to start of function
4767   for (ff = TT.ff;; ff = ff->next) {
4768     while (TT.ff->blk->next) TT.ff->pl = pop_block();
4769     if (ff->func) break;
4770   }
4771 }
4772 
shift_main(void)4773 void shift_main(void)
4774 {
4775   long long by = 1;
4776 
4777   if (toys.optc) by = atolx(*toys.optargs);
4778   by += TT.ff->shift;
4779   if (by<0 || by>=TT.ff->arg.c) toys.exitval++;
4780   else TT.ff->shift = by;
4781 }
4782 
source_main(void)4783 void source_main(void)
4784 {
4785   char *name = *toys.optargs;
4786   FILE *ff = fpathopen(name);
4787 
4788   if (!ff) return perror_msg_raw(name);
4789   // $0 is shell name, not source file name while running this
4790 // TODO add tests: sh -c "source input four five" one two three
4791   *toys.optargs = *toys.argv;
4792   ++TT.srclvl;
4793   call_function();
4794   TT.ff->func = (void *)1;
4795   TT.ff->arg.v = toys.optargs;
4796   TT.ff->arg.c = toys.optc;
4797   TT.ff->oldlineno = TT.LINENO;
4798   TT.LINENO = 0;
4799   do_source(name, ff);
4800   TT.LINENO = TT.ff->oldlineno;
4801   // TODO: this doesn't do proper cleanup but isn't normal fcall either
4802   free(dlist_pop(&TT.ff));
4803   --TT.srclvl;
4804 }
4805 
4806 #define FOR_wait
4807 #include "generated/flags.h"
4808 
wait_main(void)4809 void wait_main(void)
4810 {
4811   struct sh_process *pp;
4812   int ii, jj;
4813   long long ll;
4814   char *s;
4815 
4816   // TODO does -o pipefail affect return code here
4817   if (FLAG(n)) toys.exitval = free_process(wait_job(-1, 0));
4818   else if (!toys.optc) while (TT.jobs.c) {
4819     if (!(pp = wait_job(-1, 0))) break;
4820   } else for (ii = 0; ii<toys.optc; ii++) {
4821     ll = estrtol(toys.optargs[ii], &s, 10);
4822     if (errno || *s) {
4823       if (-1 == (jj = find_job(toys.optargs[ii]))) {
4824         error_msg("%s: bad pid/job", toys.optargs[ii]);
4825         continue;
4826       }
4827       ll = ((struct sh_process *)TT.jobs.v[jj])->pid;
4828     }
4829     if (!(pp = wait_job(ll, 0))) {
4830       if (toys.signal) toys.exitval = 128+toys.signal;
4831       break;
4832     }
4833     toys.exitval = free_process(pp);
4834   }
4835 }
4836