zcip: make it work on NOMMU (+ improve NOMMU support machinery)

fsck: fix bad English in a comment
This commit is contained in:
Denis Vlasenko 2007-03-26 17:25:33 +00:00
parent 4e1361a481
commit afa7023b46
6 changed files with 102 additions and 90 deletions

View File

@ -5,7 +5,7 @@
# #
# Automatically generated make config: don't edit # Automatically generated make config: don't edit
# Busybox version: 1.6.0.svn # 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 CONFIG_HAVE_DOT_CONFIG=y
@ -266,7 +266,7 @@ CONFIG_RESET=y
CONFIG_RESIZE=y CONFIG_RESIZE=y
CONFIG_FEATURE_RESIZE_PRINT=y CONFIG_FEATURE_RESIZE_PRINT=y
CONFIG_SETCONSOLE=y CONFIG_SETCONSOLE=y
# CONFIG_FEATURE_SETCONSOLE_LONG_OPTIONS is not set CONFIG_FEATURE_SETCONSOLE_LONG_OPTIONS=y
CONFIG_SETKEYCODES=y CONFIG_SETKEYCODES=y
CONFIG_SETLOGCONS=y CONFIG_SETLOGCONS=y
@ -605,7 +605,7 @@ CONFIG_WGET=y
CONFIG_FEATURE_WGET_STATUSBAR=y CONFIG_FEATURE_WGET_STATUSBAR=y
CONFIG_FEATURE_WGET_AUTHENTICATION=y CONFIG_FEATURE_WGET_AUTHENTICATION=y
CONFIG_FEATURE_WGET_LONG_OPTIONS=y CONFIG_FEATURE_WGET_LONG_OPTIONS=y
# CONFIG_ZCIP is not set CONFIG_ZCIP=y
# #
# Process Utilities # Process Utilities

View File

@ -509,12 +509,7 @@ static struct fsck_instance *wait_one(int flags)
goto ret_inst; goto ret_inst;
} }
/* inst = prev = NULL; /* for gcc */
* gcc -Wall fails saving throw against stupidity
* (inst and prev are thought to be uninitialized variables)
*/
inst = prev = NULL;
do { do {
pid = waitpid(-1, &status, flags); pid = waitpid(-1, &status, flags);
kill_all_if_cancel_requested(); kill_all_if_cancel_requested();

View File

@ -263,6 +263,13 @@ char *xrealloc_getcwd_or_warn(char *cwd);
char *xmalloc_readlink_or_warn(const char *path); char *xmalloc_readlink_or_warn(const char *path);
char *xmalloc_realpath(const char *path); char *xmalloc_realpath(const char *path);
extern void xstat(const char *filename, struct stat *buf); 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 int wait4pid(int pid);
extern void xsetgid(gid_t gid); extern void xsetgid(gid_t gid);
extern void xsetuid(uid_t uid); extern void xsetuid(uid_t uid);

View File

@ -40,11 +40,14 @@ pid_t spawn(char **argv)
* (but don't run atexit() stuff, which would screw up parent.) * (but don't run atexit() stuff, which would screw up parent.)
*/ */
failed = errno; failed = errno;
_exit(0); _exit(111);
} }
/* parent */ /* parent */
/* Unfortunately, this is not reliable: vfork() /* Unfortunately, this is not reliable: according to standards
* can be equivalent to fork() 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) { if (failed) {
errno = failed; errno = failed;
return -1; return -1;

View File

@ -192,9 +192,16 @@ int wait4pid(int pid)
{ {
int status; int status;
if (pid == -1 || waitpid(pid, &status, 0) == -1) return -1; if (pid <= 0) {
if (WIFEXITED(status)) return WEXITSTATUS(status); errno = ECHILD;
if (WIFSIGNALED(status)) return WTERMSIG(status); 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; return 0;
} }

View File

@ -70,10 +70,6 @@ enum {
#define VDBG(fmt,args...) \ #define VDBG(fmt,args...) \
do { } while (0) 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 * Pick a random link local IP address on 169.254/16, except that
* the first and last 256 addresses are reserved. * the first and last 256 addresses are reserved.
@ -128,49 +124,30 @@ static void arp(int fd, struct sockaddr *saddr, int op,
} }
/** /**
* 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; int status;
const char *why;
if(1) { //always true: if (script != NULL) VDBG("%s run %s %s\n", intf, argv[0], argv[1]);
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);
}
pid = vfork(); if (ip) {
if (pid < 0) { // error char *addr = inet_ntoa(*ip);
why = "vfork"; setenv("ip", addr, 1);
goto bad; bb_info_msg("%s %s %s", argv[1], intf, addr);
} 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;
}
} }
return 0;
bad: status = wait4pid(spawn(argv));
status = -errno; if (status < 0) {
bb_perror_msg("%s %s, %s", arg, intf, why); 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 status;
} }
/** /**
* Return milliseconds of random delay, up to "secs" seconds. * Return milliseconds of random delay, up to "secs" seconds.
*/ */
@ -182,43 +159,58 @@ static unsigned ATTRIBUTE_ALWAYS_INLINE ms_rdelay(unsigned secs)
/** /**
* main program * 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 zcip_main(int argc, char *argv[]) int zcip_main(int argc, char *argv[])
{ {
int state = PROBE;
struct ether_addr eth_addr; struct ether_addr eth_addr;
const char *why; const char *why;
int fd; int fd;
// parse commandline: prog [options] ifname script
char *r_opt; 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); opts = getopt32(argc, argv, "fqr:v", &r_opt, &verbose);
if (!FOREGROUND) { if (!FOREGROUND) {
/* Do it early, before all bb_xx_msg calls */ /* Do it early, before all bb_xx_msg calls */
logmode = LOGMODE_SYSLOG;
openlog(applet_name, 0, LOG_DAEMON); openlog(applet_name, 0, LOG_DAEMON);
logmode |= LOGMODE_SYSLOG;
} }
if (opts & 4) { // -r n.n.n.n if (opts & 4) { // -r n.n.n.n
if (inet_aton(r_opt, &ip) == 0 if (inet_aton(r_opt, &ip) == 0
@ -227,16 +219,21 @@ int zcip_main(int argc, char *argv[])
bb_error_msg_and_die("invalid link address"); 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; argc -= optind;
argv += optind; argv += optind;
if (argc != 2)
bb_show_usage();
intf = argv[0]; intf = argv[0];
script = argv[1]; script_av[0] = argv[1];
setenv("interface", intf, 1); setenv("interface", intf, 1);
// initialize the interface (modprobe, ifup, etc) // 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; return EXIT_FAILURE;
// initialize saddr // initialize saddr
@ -271,8 +268,9 @@ int zcip_main(int argc, char *argv[])
// daemonize now; don't delay system startup // daemonize now; don't delay system startup
if (!FOREGROUND) { if (!FOREGROUND) {
//NOMMU #ifndef BB_NOMMU
bb_daemonize(DAEMON_CHDIR_ROOT); bb_daemonize(DAEMON_CHDIR_ROOT);
#endif
bb_info_msg("start, interface %s", intf); bb_info_msg("start, interface %s", intf);
} }
@ -375,7 +373,8 @@ int zcip_main(int argc, char *argv[])
state = MONITOR; state = MONITOR;
// link is ok to use earlier // link is ok to use earlier
// FIXME update filters // FIXME update filters
run(script, "config", intf, &ip); script_av[1] = (char*)"config";
run(script_av, intf, &ip);
ready = 1; ready = 1;
conflicts = 0; conflicts = 0;
timeout = -1; // Never timeout in the monitor state. timeout = -1; // Never timeout in the monitor state.
@ -429,8 +428,8 @@ int zcip_main(int argc, char *argv[])
// this shouldn't necessarily exit. // this shouldn't necessarily exit.
bb_error_msg("%s: poll error", intf); bb_error_msg("%s: poll error", intf);
if (ready) { if (ready) {
run(script, "deconfig", script_av[1] = (char*)"deconfig";
intf, &ip); run(script_av, intf, &ip);
} }
return EXIT_FAILURE; return EXIT_FAILURE;
} }
@ -516,7 +515,8 @@ int zcip_main(int argc, char *argv[])
state = PROBE; state = PROBE;
VDBG("defend conflict -- starting over\n"); VDBG("defend conflict -- starting over\n");
ready = 0; ready = 0;
run(script, "deconfig", intf, &ip); script_av[1] = (char*)"deconfig";
run(script_av, intf, &ip);
// restart the whole protocol // restart the whole protocol
pick(&ip); pick(&ip);
@ -542,7 +542,7 @@ int zcip_main(int argc, char *argv[])
goto bad; goto bad;
} // switch poll } // switch poll
} }
bad: bad:
bb_perror_msg("%s, %s", intf, why); bb_perror_msg("%s, %s", intf, why);
return EXIT_FAILURE; return EXIT_FAILURE;
} }