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