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