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