zcip: make it work on NOMMU (+ improve NOMMU support machinery)
fsck: fix bad English in a comment
diff --git a/TODO_config_nommu b/TODO_config_nommu
index 74095aa..695ac11 100644
--- a/TODO_config_nommu
+++ b/TODO_config_nommu
@@ -5,7 +5,7 @@
#
# Automatically generated make config: don't edit
# Busybox version: 1.6.0.svn
-# Mon Mar 26 15:00:56 2007
+# Mon Mar 26 18:36:12 2007
#
CONFIG_HAVE_DOT_CONFIG=y
@@ -266,7 +266,7 @@
CONFIG_RESIZE=y
CONFIG_FEATURE_RESIZE_PRINT=y
CONFIG_SETCONSOLE=y
-# CONFIG_FEATURE_SETCONSOLE_LONG_OPTIONS is not set
+CONFIG_FEATURE_SETCONSOLE_LONG_OPTIONS=y
CONFIG_SETKEYCODES=y
CONFIG_SETLOGCONS=y
@@ -605,7 +605,7 @@
CONFIG_FEATURE_WGET_STATUSBAR=y
CONFIG_FEATURE_WGET_AUTHENTICATION=y
CONFIG_FEATURE_WGET_LONG_OPTIONS=y
-# CONFIG_ZCIP is not set
+CONFIG_ZCIP=y
#
# Process Utilities
diff --git a/e2fsprogs/fsck.c b/e2fsprogs/fsck.c
index 447b4d0..b70fd70 100644
--- a/e2fsprogs/fsck.c
+++ b/e2fsprogs/fsck.c
@@ -509,12 +509,7 @@
goto ret_inst;
}
- /*
- * gcc -Wall fails saving throw against stupidity
- * (inst and prev are thought to be uninitialized variables)
- */
- inst = prev = NULL;
-
+ inst = prev = NULL; /* for gcc */
do {
pid = waitpid(-1, &status, flags);
kill_all_if_cancel_requested();
diff --git a/include/libbb.h b/include/libbb.h
index 32e099b..67fd2af 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -263,6 +263,13 @@
char *xmalloc_readlink_or_warn(const char *path);
char *xmalloc_realpath(const char *path);
extern void xstat(const char *filename, struct stat *buf);
+/* Unlike waitpid, waits ONLY for one process,
+ * It's safe to pass negative 'pids' from failed [v]fork -
+ * wait4pid will return -1 and ECHILD in errno.
+ * IOW: rc = wait4pid(spawn(argv));
+ * if (rc < 0) bb_perror_msg("%s", argv[0]);
+ * if (rc > 0) bb_error_msg("exit code: %d", rc);
+ */
extern int wait4pid(int pid);
extern void xsetgid(gid_t gid);
extern void xsetuid(uid_t uid);
diff --git a/libbb/vfork_daemon_rexec.c b/libbb/vfork_daemon_rexec.c
index 89ae9a7..ec8b9b1 100644
--- a/libbb/vfork_daemon_rexec.c
+++ b/libbb/vfork_daemon_rexec.c
@@ -40,11 +40,14 @@
* (but don't run atexit() stuff, which would screw up parent.)
*/
failed = errno;
- _exit(0);
+ _exit(111);
}
/* parent */
- /* Unfortunately, this is not reliable: vfork()
- * can be equivalent to fork() according to standards */
+ /* Unfortunately, this is not reliable: according to standards
+ * vfork() can be equivalent to fork() and we won't see value
+ * of 'failed'.
+ * Interested party can wait on pid and learn exit code.
+ * If 111 - then it (most probably) failed to exec */
if (failed) {
errno = failed;
return -1;
diff --git a/libbb/xfuncs.c b/libbb/xfuncs.c
index 14bd62a..7f870ac 100644
--- a/libbb/xfuncs.c
+++ b/libbb/xfuncs.c
@@ -192,9 +192,16 @@
{
int status;
- if (pid == -1 || waitpid(pid, &status, 0) == -1) return -1;
- if (WIFEXITED(status)) return WEXITSTATUS(status);
- if (WIFSIGNALED(status)) return WTERMSIG(status);
+ if (pid <= 0) {
+ errno = ECHILD;
+ return -1;
+ }
+ if (waitpid(pid, &status, 0) == -1)
+ return -1;
+ if (WIFEXITED(status))
+ return WEXITSTATUS(status);
+ if (WIFSIGNALED(status))
+ return WTERMSIG(status) + 10000;
return 0;
}
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;
}