zcip: make it work on NOMMU (+ improve NOMMU support machinery)
fsck: fix bad English in a comment
diff --git a/networking/zcip.c b/networking/zcip.c
index c0cf665..6035b91 100644
--- a/networking/zcip.c
+++ b/networking/zcip.c
@@ -70,10 +70,6 @@
 #define VDBG(fmt,args...) \
 	do { } while (0)
 
-static unsigned opts;
-#define FOREGROUND (opts & 1)
-#define QUIT (opts & 2)
-
 /**
  * Pick a random link local IP address on 169.254/16, except that
  * the first and last 256 addresses are reserved.
@@ -128,49 +124,30 @@
 }
 
 /**
- * Run a script.
+ * Run a script. argv[2] is already NULL.
  */
-static int run(const char *script, const char *arg, const char *intf, struct in_addr *ip)
+static int run(char *argv[3], const char *intf, struct in_addr *ip)
 {
-	int pid, status;
-	const char *why;
+	int status;
 
-	if(1) { //always true: if (script != NULL)
-		VDBG("%s run %s %s\n", intf, script, arg);
-		if (ip != NULL) {
-			char *addr = inet_ntoa(*ip);
-			setenv("ip", addr, 1);
-			bb_info_msg("%s %s %s", arg, intf, addr);
-		}
+	VDBG("%s run %s %s\n", intf, argv[0], argv[1]);
 
-		pid = vfork();
-		if (pid < 0) {			// error
-			why = "vfork";
-			goto bad;
-		} else if (pid == 0) {		// child
-			execl(script, script, arg, NULL);
-			bb_perror_msg("execl");
-			_exit(EXIT_FAILURE);
-		}
-
-		if (waitpid(pid, &status, 0) <= 0) {
-			why = "waitpid";
-			goto bad;
-		}
-		if (WEXITSTATUS(status) != 0) {
-			bb_error_msg("script %s failed, exit=%d",
-				script, WEXITSTATUS(status));
-			return -errno;
-		}
+	if (ip) {
+		char *addr = inet_ntoa(*ip);
+		setenv("ip", addr, 1);
+		bb_info_msg("%s %s %s", argv[1], intf, addr);
 	}
-	return 0;
-bad:
-	status = -errno;
-	bb_perror_msg("%s %s, %s", arg, intf, why);
+
+	status = wait4pid(spawn(argv));
+	if (status < 0) {
+		bb_perror_msg("%s %s", argv[1], intf);
+		return -errno;
+	}
+	if (status != 0)
+		bb_error_msg("script %s %s failed, exitcode=%d", argv[0], argv[1], status);
 	return status;
 }
 
-
 /**
  * Return milliseconds of random delay, up to "secs" seconds.
  */
@@ -182,43 +159,58 @@
 /**
  * main program
  */
-
-/* Used to be auto variables on main() stack, but
- * most of them were zero-inited. Moving them to bss
- * is more space-efficient.
- */
-static	const struct in_addr null_ip; // = { 0 };
-static	const struct ether_addr null_addr; // = { {0, 0, 0, 0, 0, 0} };
-
-static	struct sockaddr saddr; // memset(0);
-static	struct in_addr ip; // = { 0 };
-static	struct ifreq ifr; //memset(0);
-
-static	char *intf; // = NULL;
-static	char *script; // = NULL;
-static	suseconds_t timeout; // = 0;	// milliseconds
-static	unsigned conflicts; // = 0;
-static	unsigned nprobes; // = 0;
-static	unsigned nclaims; // = 0;
-static	int ready; // = 0;
-static	int verbose; // = 0;
-static	int state = PROBE;
-
 int zcip_main(int argc, char *argv[]);
 int zcip_main(int argc, char *argv[])
 {
+	int state = PROBE;
 	struct ether_addr eth_addr;
 	const char *why;
 	int fd;
-
-	// parse commandline: prog [options] ifname script
 	char *r_opt;
-	opt_complementary = "vv:vf"; // -v accumulates and implies -f
+	unsigned opts;
+
+	/* Ugly trick, but I want these zeroed in one go */
+	struct {
+		const struct in_addr null_ip;
+		const struct ether_addr null_addr;
+		struct sockaddr saddr;
+		struct in_addr ip;
+		struct ifreq ifr;
+		char *intf;
+		char *script_av[3];
+		suseconds_t timeout; // milliseconds
+		unsigned conflicts;
+		unsigned nprobes;
+		unsigned nclaims;
+		int ready;
+		int verbose;
+	} L;
+#define null_ip   (L.null_ip  )
+#define null_addr (L.null_addr)
+#define saddr     (L.saddr    )
+#define ip        (L.ip       )
+#define ifr       (L.ifr      )
+#define intf      (L.intf     )
+#define script_av (L.script_av)
+#define timeout   (L.timeout  )
+#define conflicts (L.conflicts)
+#define nprobes   (L.nprobes  )
+#define nclaims   (L.nclaims  )
+#define ready     (L.ready    )
+#define verbose   (L.verbose  )
+
+	memset(&L, 0, sizeof(L));
+
+#define FOREGROUND (opts & 1)
+#define QUIT       (opts & 2)
+	// parse commandline: prog [options] ifname script
+	// exactly 2 args; -v accumulates and implies -f
+	opt_complementary = "=2:vv:vf";
 	opts = getopt32(argc, argv, "fqr:v", &r_opt, &verbose);
 	if (!FOREGROUND) {
 		/* Do it early, before all bb_xx_msg calls */
-		logmode = LOGMODE_SYSLOG;
 		openlog(applet_name, 0, LOG_DAEMON);
+		logmode |= LOGMODE_SYSLOG;
 	}
 	if (opts & 4) { // -r n.n.n.n
 		if (inet_aton(r_opt, &ip) == 0
@@ -227,16 +219,21 @@
 			bb_error_msg_and_die("invalid link address");
 		}
 	}
+	// On NOMMU reexec early (or else we will rerun things twice)
+#ifdef BB_NOMMU
+	if (!FOREGROUND)
+		bb_daemonize_or_rexec(DAEMON_CHDIR_ROOT, argv);
+#endif
 	argc -= optind;
 	argv += optind;
-	if (argc != 2)
-		bb_show_usage();
+
 	intf = argv[0];
-	script = argv[1];
+	script_av[0] = argv[1];
 	setenv("interface", intf, 1);
 
 	// initialize the interface (modprobe, ifup, etc)
-	if (run(script, "init", intf, NULL) < 0)
+	script_av[1] = (char*)"init";
+	if (run(script_av, intf, NULL))
 		return EXIT_FAILURE;
 
 	// initialize saddr
@@ -271,8 +268,9 @@
 
 	// daemonize now; don't delay system startup
 	if (!FOREGROUND) {
-//NOMMU
+#ifndef BB_NOMMU
 		bb_daemonize(DAEMON_CHDIR_ROOT);
+#endif
 		bb_info_msg("start, interface %s", intf);
 	}
 
@@ -375,7 +373,8 @@
 					state = MONITOR;
 					// link is ok to use earlier
 					// FIXME update filters
-					run(script, "config", intf, &ip);
+					script_av[1] = (char*)"config";
+					run(script_av, intf, &ip);
 					ready = 1;
 					conflicts = 0;
 					timeout = -1; // Never timeout in the monitor state.
@@ -429,8 +428,8 @@
 					// this shouldn't necessarily exit.
 					bb_error_msg("%s: poll error", intf);
 					if (ready) {
-						run(script, "deconfig",
-								intf, &ip);
+						script_av[1] = (char*)"deconfig";
+						run(script_av, intf, &ip);
 					}
 					return EXIT_FAILURE;
 				}
@@ -516,7 +515,8 @@
 					state = PROBE;
 					VDBG("defend conflict -- starting over\n");
 					ready = 0;
-					run(script, "deconfig", intf, &ip);
+					script_av[1] = (char*)"deconfig";
+					run(script_av, intf, &ip);
 
 					// restart the whole protocol
 					pick(&ip);
@@ -542,7 +542,7 @@
 			goto bad;
 		} // switch poll
 	}
-bad:
+ bad:
 	bb_perror_msg("%s, %s", intf, why);
 	return EXIT_FAILURE;
 }