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