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