Snap for 7325096 from dcacb9b215f353b03bbb0606d0ee786533c73684 to sc-d1-release

Change-Id: Iced538f785520d85ab57e757c603471d360d5859
diff --git a/android/device/generated/newtoys.h b/android/device/generated/newtoys.h
index e97ac2f..04b4b8e 100644
--- a/android/device/generated/newtoys.h
+++ b/android/device/generated/newtoys.h
@@ -69,7 +69,7 @@
 USE_DOS2UNIX(NEWTOY(dos2unix, 0, TOYFLAG_BIN))
 USE_DU(NEWTOY(du, "d#<0=-1hmlcaHkKLsxb[-HL][-kKmh]", TOYFLAG_USR|TOYFLAG_BIN))
 USE_DUMPLEASES(NEWTOY(dumpleases, ">0arf:[!ar]", TOYFLAG_USR|TOYFLAG_BIN))
-USE_ECHO(NEWTOY(echo, "^?Een[-eE]", TOYFLAG_BIN|TOYFLAG_MAYFORK))
+USE_ECHO(NEWTOY(echo, "^?Een[-eE]", TOYFLAG_BIN|TOYFLAG_MAYFORK|TOYFLAG_LINEBUF))
 USE_EGREP(OLDTOY(egrep, grep, TOYFLAG_BIN|TOYFLAG_ARGFAIL(2)|TOYFLAG_LINEBUF))
 USE_EJECT(NEWTOY(eject, ">1stT[!tT]", TOYFLAG_USR|TOYFLAG_BIN))
 USE_ENV(NEWTOY(env, "^i0u*", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_ARGFAIL(125)))
@@ -315,5 +315,5 @@
 USE_XARGS(NEWTOY(xargs, "^E:P#<0=1optrn#<1(max-args)s#0[!0E]", TOYFLAG_USR|TOYFLAG_BIN))
 USE_XXD(NEWTOY(xxd, ">1c#l#o#g#<1=2iprs#[!rs]", TOYFLAG_USR|TOYFLAG_BIN))
 USE_XZCAT(NEWTOY(xzcat, NULL, TOYFLAG_USR|TOYFLAG_BIN))
-USE_YES(NEWTOY(yes, NULL, TOYFLAG_USR|TOYFLAG_BIN))
+USE_YES(NEWTOY(yes, NULL, TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_LINEBUF))
 USE_ZCAT(NEWTOY(zcat,     "cdfk123456789[-123456789]", TOYFLAG_USR|TOYFLAG_BIN))
diff --git a/android/linux/generated/newtoys.h b/android/linux/generated/newtoys.h
index e97ac2f..04b4b8e 100644
--- a/android/linux/generated/newtoys.h
+++ b/android/linux/generated/newtoys.h
@@ -69,7 +69,7 @@
 USE_DOS2UNIX(NEWTOY(dos2unix, 0, TOYFLAG_BIN))
 USE_DU(NEWTOY(du, "d#<0=-1hmlcaHkKLsxb[-HL][-kKmh]", TOYFLAG_USR|TOYFLAG_BIN))
 USE_DUMPLEASES(NEWTOY(dumpleases, ">0arf:[!ar]", TOYFLAG_USR|TOYFLAG_BIN))
-USE_ECHO(NEWTOY(echo, "^?Een[-eE]", TOYFLAG_BIN|TOYFLAG_MAYFORK))
+USE_ECHO(NEWTOY(echo, "^?Een[-eE]", TOYFLAG_BIN|TOYFLAG_MAYFORK|TOYFLAG_LINEBUF))
 USE_EGREP(OLDTOY(egrep, grep, TOYFLAG_BIN|TOYFLAG_ARGFAIL(2)|TOYFLAG_LINEBUF))
 USE_EJECT(NEWTOY(eject, ">1stT[!tT]", TOYFLAG_USR|TOYFLAG_BIN))
 USE_ENV(NEWTOY(env, "^i0u*", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_ARGFAIL(125)))
@@ -315,5 +315,5 @@
 USE_XARGS(NEWTOY(xargs, "^E:P#<0=1optrn#<1(max-args)s#0[!0E]", TOYFLAG_USR|TOYFLAG_BIN))
 USE_XXD(NEWTOY(xxd, ">1c#l#o#g#<1=2iprs#[!rs]", TOYFLAG_USR|TOYFLAG_BIN))
 USE_XZCAT(NEWTOY(xzcat, NULL, TOYFLAG_USR|TOYFLAG_BIN))
-USE_YES(NEWTOY(yes, NULL, TOYFLAG_USR|TOYFLAG_BIN))
+USE_YES(NEWTOY(yes, NULL, TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_LINEBUF))
 USE_ZCAT(NEWTOY(zcat,     "cdfk123456789[-123456789]", TOYFLAG_USR|TOYFLAG_BIN))
diff --git a/android/mac/generated/newtoys.h b/android/mac/generated/newtoys.h
index e97ac2f..04b4b8e 100644
--- a/android/mac/generated/newtoys.h
+++ b/android/mac/generated/newtoys.h
@@ -69,7 +69,7 @@
 USE_DOS2UNIX(NEWTOY(dos2unix, 0, TOYFLAG_BIN))
 USE_DU(NEWTOY(du, "d#<0=-1hmlcaHkKLsxb[-HL][-kKmh]", TOYFLAG_USR|TOYFLAG_BIN))
 USE_DUMPLEASES(NEWTOY(dumpleases, ">0arf:[!ar]", TOYFLAG_USR|TOYFLAG_BIN))
-USE_ECHO(NEWTOY(echo, "^?Een[-eE]", TOYFLAG_BIN|TOYFLAG_MAYFORK))
+USE_ECHO(NEWTOY(echo, "^?Een[-eE]", TOYFLAG_BIN|TOYFLAG_MAYFORK|TOYFLAG_LINEBUF))
 USE_EGREP(OLDTOY(egrep, grep, TOYFLAG_BIN|TOYFLAG_ARGFAIL(2)|TOYFLAG_LINEBUF))
 USE_EJECT(NEWTOY(eject, ">1stT[!tT]", TOYFLAG_USR|TOYFLAG_BIN))
 USE_ENV(NEWTOY(env, "^i0u*", TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_ARGFAIL(125)))
@@ -315,5 +315,5 @@
 USE_XARGS(NEWTOY(xargs, "^E:P#<0=1optrn#<1(max-args)s#0[!0E]", TOYFLAG_USR|TOYFLAG_BIN))
 USE_XXD(NEWTOY(xxd, ">1c#l#o#g#<1=2iprs#[!rs]", TOYFLAG_USR|TOYFLAG_BIN))
 USE_XZCAT(NEWTOY(xzcat, NULL, TOYFLAG_USR|TOYFLAG_BIN))
-USE_YES(NEWTOY(yes, NULL, TOYFLAG_USR|TOYFLAG_BIN))
+USE_YES(NEWTOY(yes, NULL, TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_LINEBUF))
 USE_ZCAT(NEWTOY(zcat,     "cdfk123456789[-123456789]", TOYFLAG_USR|TOYFLAG_BIN))
diff --git a/main.c b/main.c
index deea989..d5abe6e 100644
--- a/main.c
+++ b/main.c
@@ -95,7 +95,7 @@
     for (toys.optc = 0; toys.optargs[toys.optc]; toys.optc++);
   }
 
-  if (!(which->flags & TOYFLAG_NOFORK)) {
+  if (!(CFG_TOYBOX && which == toy_list) && !(which->flags & TOYFLAG_NOFORK)) {
     toys.old_umask = umask(0);
     if (!(which->flags & TOYFLAG_UMASK)) umask(toys.old_umask);
 
diff --git a/toys/other/yes.c b/toys/other/yes.c
index 773a5a8..8edba0a 100644
--- a/toys/other/yes.c
+++ b/toys/other/yes.c
@@ -2,7 +2,7 @@
  *
  * Copyright 2007 Rob Landley <rob@landley.net>
 
-USE_YES(NEWTOY(yes, NULL, TOYFLAG_USR|TOYFLAG_BIN))
+USE_YES(NEWTOY(yes, NULL, TOYFLAG_USR|TOYFLAG_BIN|TOYFLAG_LINEBUF))
 
 config YES
   bool "yes"
diff --git a/toys/pending/sh.c b/toys/pending/sh.c
index fd72037..3ae66f6 100644
--- a/toys/pending/sh.c
+++ b/toys/pending/sh.c
@@ -2327,6 +2327,10 @@
   // Create new function context to hold local vars?
   if (funk != TT.funcslen || (envlen && pp->arg.c) || TT.ff->blk->pipe) {
     call_function();
+    if (funk != TT.funcslen) {
+      TT.ff->delete = pp->delete;
+      pp->delete = 0;
+    }
     addvar(0, TT.ff); // function context (not source) so end_function deletes
     locals = 1;
   }
@@ -2366,6 +2370,7 @@
   else if (funk != TT.funcslen) {
     (TT.ff->func = TT.functions[funk])->refcount++;
     TT.ff->pl = TT.ff->func->pipeline;
+    TT.ff->next->pl = TT.ff->next->pl->next;
     TT.ff->arg = pp->arg;
   } else {
     struct toy_list *tl = toy_find(*pp->arg.v);
@@ -2450,7 +2455,7 @@
 {
   struct sh_pipeline *pl = xzalloc(sizeof(struct sh_pipeline));
 
-  *arg = pl->arg;
+  if (arg) *arg = pl->arg;
   pl->lineno = TT.LINENO;
   dlist_add_nomalloc((void *)ppl, (void *)pl);
 
@@ -2532,50 +2537,50 @@
         arg[pl->count].c = 0;
         if (s[2] == '<') pl->here++; // <<< doesn't load more data
       }
+
+      // Did we just end a function?
+      if (ex == (void *)1) {
+        struct sh_function *funky;
+
+        // function must be followed by a compound statement for some reason
+        if ((*ppl)->prev->type != 3) {
+          s = *(*ppl)->prev->arg->v;
+          goto flush;
+        }
+
+        // Back up to saved function() statement and create sh_function
+        free(dlist_lpop(expect));
+        pl = (void *)(*expect)->data;
+        funky = xmalloc(sizeof(struct sh_function));
+        funky->refcount = 1;
+        funky->name = *pl->arg->v;
+        *pl->arg->v = (void *)funky;
+
+        // Chop out pipeline segments added since saved function
+        funky->pipeline = pl->next;
+        pl->next->prev = (*ppl)->prev;
+        (*ppl)->prev->next = pl->next;
+        pl->next = *ppl;
+        (*ppl)->prev = pl;
+        dlist_terminate(funky->pipeline = add_pl(&funky->pipeline, 0));
+
+        // Immature function has matured (meaning cleanup is different)
+        pl->type = 'F';
+        free(dlist_lpop(expect));
+        ex = *expect ? (*expect)->prev->data : 0;
+      }
       pl = 0;
     }
     if (done) break;
     s = 0;
 
-    // Did we just end a function?
-    if (ex == (void *)1) {
-      struct sh_function *funky;
-
-      // function must be followed by a compound statement for some reason
-      if ((*ppl)->prev->type != 3) {
-        s = *(*ppl)->prev->arg->v;
-        goto flush;
-      }
-
-      // Back up to saved function() statement and create sh_function
-      free(dlist_lpop(expect));
-      pl = (void *)(*expect)->data;
-      funky = xmalloc(sizeof(struct sh_function));
-      funky->refcount = 1;
-      funky->name = *pl->arg->v;
-      *pl->arg->v = (void *)funky;
-
-      // Chop out pipeline segments added since saved function
-      funky->pipeline = pl->next;
-      pl->next->prev = (*ppl)->prev;
-      (*ppl)->prev->next = pl->next;
-      pl->next = *ppl;
-      (*ppl)->prev = pl;
-
-      // Immature function has matured (meaning cleanup is different)
-      pl->type = 'F';
-      pl = 0;
-      free(dlist_lpop(expect));
-      ex = *expect ? (*expect)->prev->data : 0;
-    }
-
     // skip leading whitespace/comment here to know where next word starts
     while (isspace(*start)) ++start;
     if (*start=='#') while (*start && *start != '\n') ++start;
 
     // Parse next word and detect overflow (too many nested quotes).
     if ((end = parse_word(start, 0, 0)) == (void *)1) goto flush;
-//dprintf(2, "%d %p %s word=%.*s\n", getpid(), pl, ex, (int)(end-start), end ? start : "");
+//dprintf(2, "%d %p %s word=%.*s\n", getpid(), pl, (ex != (void *)1) ? ex : "function", (int)(end-start), end ? start : "");
 
     if (pl && pl->type == 'f' && arg->c == 1 && (end-start!=1 || *start!='(')) {
 funky:
@@ -2604,7 +2609,7 @@
     // Ok, we have a word. What does it _mean_?
 
     // case/esac parsing is weird (unbalanced parentheses!), handle first
-    i = ex && !strcmp(ex, "esac") &&
+    i = (unsigned long)ex>1 && !strcmp(ex, "esac") &&
         ((pl->type && pl->type != 3) || (*start==';' && end-start>1));
     if (i) {
 
@@ -2644,7 +2649,7 @@
       }
 
       // "for" on its own line is an error.
-      if (arg->c == 1 && ex && !memcmp(ex, "do\0A", 4)) {
+      if (arg->c == 1 && (unsigned long)ex>1 && !memcmp(ex, "do\0A", 4)) {
         s = "newline";
         goto flush;
       }
@@ -2735,7 +2740,7 @@
         free(s);
         s = 0;
 // TODO can't have ; between "for i" and in or do. (Newline yes, ; no. Why?)
-        if (!arg->c && ex && !memcmp(ex, "do\0C", 4)) continue;
+        if (!arg->c && (unsigned long)ex>1 && !memcmp(ex, "do\0C", 4)) continue;
 
       // ;; and friends only allowed in case statements
       } else if (*s == ';') goto flush;
@@ -2747,7 +2752,7 @@
       continue;
 
     // a for/select must have at least one additional argument on same line
-    } else if (ex && !memcmp(ex, "do\0A", 4)) {
+    } else if ((unsigned long)ex>1 && !memcmp(ex, "do\0A", 4)) {
 
       // Sanity check and break the segment
       if (strncmp(s, "((", 2) && *varend(s)) goto flush;
@@ -2760,7 +2765,7 @@
     } else if (arg->c>1) continue;
 
     // Do we expect something that _must_ come next? (no multiple statements)
-    if (ex) {
+    if ((unsigned long)ex>1) {
       // The "test" part of for/select loops can have (at most) one "in" line,
       // for {((;;))|name [in...]} do
       if (!memcmp(ex, "do\0C", 4)) {
@@ -2805,7 +2810,7 @@
       if (*expect && !(*expect)->prev->data) free(dlist_lpop(expect));
 
     // if can't end a statement here skip next few tests
-    } else if (!ex);
+    } else if ((unsigned long)ex<2);
 
     // If we got here we expect a specific word to end this block: is this it?
     else if (!strcmp(s, ex)) {
@@ -2887,7 +2892,12 @@
   if (s) syntax_err(s);
   llist_traverse(*ppl, free_pipeline);
   *ppl = 0;
-  llist_traverse(*expect, free);
+  while (*expect) {
+    struct double_list *del = dlist_pop(expect);
+
+    if (del->data != (void *)1) free(del->data);
+    free(del);
+  }
   *expect = 0;
 
   return 0-!!s;
@@ -3046,7 +3056,7 @@
     ctl = TT.ff->pl->end->arg->v[TT.ff->pl->end->arg->c];
     s = *TT.ff->pl->arg->v;
     ss = TT.ff->pl->arg->v[1];
-//dprintf(2, "%d s=%s ss=%s ctl=%s type=%d\n", getpid(), s, ss, ctl, TT.ff->pl->type);
+//dprintf(2, "%d s=%s ss=%s ctl=%s type=%d\n", getpid(), (TT.ff->pl->type == 'F') ? ((struct sh_function *)s)->name : s, ss, ctl, TT.ff->pl->type);
     if (!pplist) TT.hfd = 10;
 
     // Skip disabled blocks, handle pipes and backgrounding
diff --git a/toys/pending/telnetd.c b/toys/pending/telnetd.c
index 032104f..235bd17 100644
--- a/toys/pending/telnetd.c
+++ b/toys/pending/telnetd.c
@@ -162,7 +162,7 @@
   if (TT.fork_pid < 0) perror_exit("fork");
 
   if (getpeername(sockfd, (void *)&sa, &sl)) perror_exit("getpeername");
-  if (getnameinfo((void *)&sa, sl, toybuf, sizeof(toybuf), NULL, 0, 0))
+  if (getnameinfo((void *)&sa, sl, toybuf, sizeof(toybuf), NULL, 0, NI_NUMERICHOST))
     perror_exit("getnameinfo");
 
   write_issue(tty_name);
diff --git a/toys/posix/echo.c b/toys/posix/echo.c
index b546e94..9b7b922 100644
--- a/toys/posix/echo.c
+++ b/toys/posix/echo.c
@@ -9,7 +9,7 @@
  * We also honor -- to _stop_ option parsing (bash doesn't, we go with
  * consistency over compatibility here).
 
-USE_ECHO(NEWTOY(echo, "^?Een[-eE]", TOYFLAG_BIN|TOYFLAG_MAYFORK))
+USE_ECHO(NEWTOY(echo, "^?Een[-eE]", TOYFLAG_BIN|TOYFLAG_MAYFORK|TOYFLAG_LINEBUF))
 
 config ECHO
   bool "echo"