udhcpc: convert to getopt32
diff --git a/networking/udhcp/dhcpc.c b/networking/udhcp/dhcpc.c
index 4ccd8ec..f69b687 100644
--- a/networking/udhcp/dhcpc.c
+++ b/networking/udhcp/dhcpc.c
@@ -33,25 +33,8 @@
 #define LISTEN_RAW 2
 static int listen_mode;
 
-struct client_config_t client_config = {
-	/* Default options. */
-	.abort_if_no_lease = 0,
-	.foreground = 0,
-	.quit_after_lease = 0,
-	.release_on_quit = 0,
-	.background_if_no_lease = 0,
-	.interface = "eth0",
-	.pidfile = NULL,
-	.script = DEFAULT_SCRIPT,
-	.clientid = NULL,
-	.vendorclass = NULL,
-	.hostname = NULL,
-	.fqdn = NULL,
-	.ifindex = 0,
-	.retries = 3,
-	.timeout = 3,
-	.arp = "\0\0\0\0\0\0",		/* appease gcc-3.0 */
-};
+struct client_config_t client_config;
+
 
 /* just a little helper */
 static void change_mode(int new_mode)
@@ -126,139 +109,137 @@
 }
 
 
+static uint8_t* alloc_dhcp_option(int code, const char *str, int extra)
+{
+	uint8_t *storage;
+	int len = strlen(str);
+	if (len > 255) len = 255;
+	storage = xzalloc(len + extra + OPT_DATA);
+	storage[OPT_CODE] = code;
+	storage[OPT_LEN] = len + extra;
+	memcpy(storage + extra + OPT_DATA, str, len);
+	return storage;
+}
+
+
 int udhcpc_main(int argc, char *argv[])
 {
 	uint8_t *temp, *message;
+	char *str_c, *str_V, *str_h, *str_F, *str_r, *str_T, *str_t;
 	unsigned long t1 = 0, t2 = 0, xid = 0;
 	unsigned long start = 0, lease = 0;
-	fd_set rfds;
-	int retval;
-	struct timeval tv;
-	int c, len;
-	struct dhcpMessage packet;
-	struct in_addr temp_addr;
 	long now;
+	unsigned opt;
 	int max_fd;
 	int sig;
+	int retval;
+	int len;
 	int no_clientid = 0;
+	fd_set rfds;
+	struct timeval tv;
+	struct dhcpMessage packet;
+	struct in_addr temp_addr;
 
+	enum {
+		OPT_c = 1 << 0,
+		OPT_C = 1 << 1,
+		OPT_V = 1 << 2,
+		OPT_f = 1 << 3,
+		OPT_b = 1 << 4,
+		OPT_H = 1 << 5,
+		OPT_h = 1 << 6,
+		OPT_F = 1 << 7,
+		OPT_i = 1 << 8,
+		OPT_n = 1 << 9,
+		OPT_p = 1 << 10,
+		OPT_q = 1 << 11,
+		OPT_R = 1 << 12,
+		OPT_r = 1 << 13,
+		OPT_s = 1 << 14,
+		OPT_T = 1 << 15,
+		OPT_t = 1 << 16,
+		OPT_v = 1 << 17,
+	};
 	static const struct option arg_options[] = {
-		{"clientid",	required_argument,	0, 'c'},
-		{"clientid-none", no_argument,		0, 'C'},
-		{"vendorclass",	required_argument,	0, 'V'},
-		{"foreground",	no_argument,		0, 'f'},
-		{"background",	no_argument,		0, 'b'},
-		{"hostname",	required_argument,	0, 'H'},
-		{"hostname",	required_argument,	0, 'h'},
-		{"fqdn",	required_argument,	0, 'F'},
-		{"interface",	required_argument,	0, 'i'},
-		{"now",		no_argument,		0, 'n'},
-		{"pidfile",	required_argument,	0, 'p'},
-		{"quit",	no_argument,		0, 'q'},
-		{"release",	no_argument,		0, 'R'},
-		{"request",	required_argument,	0, 'r'},
-		{"script",	required_argument,	0, 's'},
-		{"timeout",	required_argument,	0, 'T'},
-		{"version",	no_argument,		0, 'v'},
-		{"retries",	required_argument,	0, 't'},
-		{0, 0, 0, 0}
+		{ "clientid",   required_argument,      0, 'c' },
+		{ "clientid-none", no_argument,         0, 'C' },
+		{ "vendorclass", required_argument,     0, 'V' },
+		{ "foreground", no_argument,            0, 'f' },
+		{ "background", no_argument,            0, 'b' },
+		{ "hostname",   required_argument,      0, 'H' },
+		{ "hostname",   required_argument,      0, 'h' },
+		{ "fqdn",       required_argument,      0, 'F' },
+		{ "interface",  required_argument,      0, 'i' },
+		{ "now",        no_argument,            0, 'n' },
+		{ "pidfile",    required_argument,      0, 'p' },
+		{ "quit",       no_argument,            0, 'q' },
+		{ "release",    no_argument,            0, 'R' },
+		{ "request",    required_argument,      0, 'r' },
+		{ "script",     required_argument,      0, 's' },
+		{ "timeout",    required_argument,      0, 'T' },
+		{ "version",    no_argument,            0, 'v' },
+		{ "retries",    required_argument,      0, 't' },
+		{ 0, 0, 0, 0 }
 	};
 
-	/* get options */
-	while (1) {
-		int option_index = 0;
-		c = getopt_long(argc, argv, "c:CV:fbH:h:F:i:np:qRr:s:T:t:v", arg_options, &option_index);
-		if (c == -1) break;
+	/* Default options. */
+	client_config.interface = "eth0";
+	client_config.script = DEFAULT_SCRIPT;
+	client_config.retries = 3;
+	client_config.timeout = 3;
 
-		switch (c) {
-		case 'c':
-			if (no_clientid) bb_show_usage();
-			len = strlen(optarg) > 255 ? 255 : strlen(optarg);
-			free(client_config.clientid);
-			client_config.clientid = xmalloc(len + 2);
-			client_config.clientid[OPT_CODE] = DHCP_CLIENT_ID;
-			client_config.clientid[OPT_LEN] = len;
-			client_config.clientid[OPT_DATA] = '\0';
-			strncpy((char*)client_config.clientid + OPT_DATA, optarg, len);
-			break;
-		case 'C':
-			if (client_config.clientid) bb_show_usage();
-			no_clientid = 1;
-			break;
-		case 'V':
-			len = strlen(optarg) > 255 ? 255 : strlen(optarg);
-			free(client_config.vendorclass);
-			client_config.vendorclass = xmalloc(len + 2);
-			client_config.vendorclass[OPT_CODE] = DHCP_VENDOR;
-			client_config.vendorclass[OPT_LEN] = len;
-			strncpy((char*)client_config.vendorclass + OPT_DATA, optarg, len);
-			break;
-		case 'f':
-			client_config.foreground = 1;
-			break;
-		case 'b':
-			client_config.background_if_no_lease = 1;
-			break;
-		case 'h':
-		case 'H':
-			len = strlen(optarg) > 255 ? 255 : strlen(optarg);
-			free(client_config.hostname);
-			client_config.hostname = xmalloc(len + 2);
-			client_config.hostname[OPT_CODE] = DHCP_HOST_NAME;
-			client_config.hostname[OPT_LEN] = len;
-			strncpy((char*)client_config.hostname + 2, optarg, len);
-			break;
-		case 'F':
-			len = strlen(optarg) > 255 ? 255 : strlen(optarg);
-			free(client_config.fqdn);
-			client_config.fqdn = xmalloc(len + 5);
-			client_config.fqdn[OPT_CODE] = DHCP_FQDN;
-			client_config.fqdn[OPT_LEN] = len + 3;
-			/* Flags: 0000NEOS
-			S: 1 => Client requests Server to update A RR in DNS as well as PTR
-			O: 1 => Server indicates to client that DNS has been updated regardless
-			E: 1 => Name data is DNS format, i.e. <4>host<6>domain<4>com<0> not "host.domain.com"
-			N: 1 => Client requests Server to not update DNS
-			*/
-			client_config.fqdn[OPT_LEN + 1] = 0x1;
-			client_config.fqdn[OPT_LEN + 2] = 0;
-			client_config.fqdn[OPT_LEN + 3] = 0;
-			strncpy((char*)client_config.fqdn + 5, optarg, len);
-			break;
-		case 'i':
-			client_config.interface =  optarg;
-			break;
-		case 'n':
-			client_config.abort_if_no_lease = 1;
-			break;
-		case 'p':
-			client_config.pidfile = optarg;
-			break;
-		case 'q':
-			client_config.quit_after_lease = 1;
-			break;
-		case 'R':
-			client_config.release_on_quit = 1;
-			break;
-		case 'r':
-			requested_ip = inet_addr(optarg);
-			break;
-		case 's':
-			client_config.script = optarg;
-			break;
-		case 'T':
-			client_config.timeout = xatoi_u(optarg);
-			break;
-		case 't':
-			client_config.retries = xatoi_u(optarg);
-			break;
-		case 'v':
-			printf("version %s\n\n", BB_VER);
-			return 0;
-			break;
-		default:
-			bb_show_usage();
-		}
+	/* Parse command line */
+	opt_complementary = "?:c--C:C--c" // mutually exclusive
+	                    ":hH:Hh"; // -h and -H are the same
+	applet_long_options = arg_options;
+	opt = getopt32(argc, argv, "c:CV:fbH:h:F:i:np:qRr:s:T:t:v",
+		&str_c, &str_V, &str_h, &str_h, &str_F,
+		&client_config.interface, &client_config.pidfile, &str_r,
+		&client_config.script, &str_T, &str_t
+		);
+
+	if (opt & OPT_c)
+		client_config.clientid = alloc_dhcp_option(DHCP_CLIENT_ID, str_c, 0);
+	if (opt & OPT_C)
+		no_clientid = 1;
+	if (opt & OPT_V)
+		client_config.vendorclass = alloc_dhcp_option(DHCP_VENDOR, str_V, 0);
+	if (opt & OPT_f)
+		client_config.foreground = 1;
+	if (opt & OPT_b)
+		client_config.background_if_no_lease = 1;
+	if (opt & OPT_h)
+		client_config.hostname = alloc_dhcp_option(DHCP_HOST_NAME, str_h, 0);
+	if (opt & OPT_F) {
+		client_config.fqdn = alloc_dhcp_option(DHCP_FQDN, str_F, 3);
+		/* Flags: 0000NEOS
+		S: 1 => Client requests Server to update A RR in DNS as well as PTR
+		O: 1 => Server indicates to client that DNS has been updated regardless
+		E: 1 => Name data is DNS format, i.e. <4>host<6>domain<4>com<0> not "host.domain.com"
+		N: 1 => Client requests Server to not update DNS
+		*/
+		client_config.fqdn[OPT_DATA + 0] = 0x1;
+		/* client_config.fqdn[OPT_DATA + 1] = 0; - redundant */
+		/* client_config.fqdn[OPT_DATA + 2] = 0; - redundant */
+	}
+	// if (opt & OPT_i) client_config.interface = ...
+	if (opt & OPT_n)
+		client_config.abort_if_no_lease = 1;
+	// if (opt & OPT_p) client_config.pidfile = ...
+	if (opt & OPT_q)
+		client_config.quit_after_lease = 1;
+	if (opt & OPT_R)
+		client_config.release_on_quit = 1;
+	if (opt & OPT_r)
+		requested_ip = inet_addr(str_r);
+	// if (opt & OPT_s) client_config.script = ...
+	if (opt & OPT_T)
+		client_config.timeout = xatoi_u(str_T);
+	if (opt & OPT_t)
+		client_config.retries = xatoi_u(str_t);
+	if (opt & OPT_v) {
+		printf("version %s\n\n", BB_VER);
+		return 0;
 	}
 
 	/* Start the log, sanitize fd's, and write a pid file */
@@ -270,22 +251,13 @@
 
 	/* if not set, and not suppressed, setup the default client ID */
 	if (!client_config.clientid && !no_clientid) {
-		client_config.clientid = xmalloc(6 + 3);
-		client_config.clientid[OPT_CODE] = DHCP_CLIENT_ID;
-		client_config.clientid[OPT_LEN] = 7;
+		client_config.clientid = alloc_dhcp_option(DHCP_CLIENT_ID, "", 7);
 		client_config.clientid[OPT_DATA] = 1;
-		memcpy(client_config.clientid + 3, client_config.arp, 6);
+		memcpy(client_config.clientid + OPT_DATA+1, client_config.arp, 6);
 	}
 
-	if (!client_config.vendorclass) {
-		client_config.vendorclass = xmalloc(sizeof("udhcp "BB_VER) + 2);
-		client_config.vendorclass[OPT_CODE] = DHCP_VENDOR;
-		client_config.vendorclass[OPT_LEN] = sizeof("udhcp "BB_VER) - 1;
-		client_config.vendorclass[OPT_DATA] = 1;
-		memcpy(&client_config.vendorclass[OPT_DATA],
-			"udhcp "BB_VER, sizeof("udhcp "BB_VER) - 1);
-	}
-
+	if (!client_config.vendorclass)
+		client_config.vendorclass = alloc_dhcp_option(DHCP_VENDOR, "udhcp "BB_VER, 0);
 
 	/* setup the signal pipe */
 	udhcp_sp_setup();
@@ -295,7 +267,6 @@
 	change_mode(LISTEN_RAW);
 
 	for (;;) {
-
 		tv.tv_sec = timeout - uptime();
 		tv.tv_usec = 0;
 
diff --git a/networking/udhcp/dhcpc.h b/networking/udhcp/dhcpc.h
index d5c8a4b..fd17917 100644
--- a/networking/udhcp/dhcpc.h
+++ b/networking/udhcp/dhcpc.h
@@ -13,22 +13,24 @@
 #define RELEASED	7
 
 struct client_config_t {
-	char foreground;		/* Do not fork */
-	char quit_after_lease;		/* Quit after obtaining lease */
-	char release_on_quit;		/* perform release on quit */
-	char abort_if_no_lease;		/* Abort if no lease */
-	char background_if_no_lease;	/* Fork to background if no lease */
-	char *interface;		/* The name of the interface to use */
-	char *pidfile;			/* Optionally store the process ID */
-	char *script;			/* User script to run at dhcp events */
-	uint8_t *clientid;		/* Optional client id to use */
-	uint8_t *vendorclass;		/* Optional vendor class-id to use */
-	uint8_t *hostname;		/* Optional hostname to use */
-	uint8_t *fqdn;			/* Optional fully qualified domain name to use */
-	int ifindex;			/* Index number of the interface to use */
-	int retries;			/* Max number of request packets */
-	int timeout;			/* Number of seconds to try to get a lease */
-	uint8_t arp[6];			/* Our arp address */
+	/* TODO: combine flag fields into single "unsigned opt" */
+	/* (can be set directly to the result of getopt32) */
+	char foreground;                /* Do not fork */
+	char quit_after_lease;          /* Quit after obtaining lease */
+	char release_on_quit;           /* perform release on quit */
+	char abort_if_no_lease;         /* Abort if no lease */
+	char background_if_no_lease;    /* Fork to background if no lease */
+	char *interface;                /* The name of the interface to use */
+	char *pidfile;                  /* Optionally store the process ID */
+	char *script;                   /* User script to run at dhcp events */
+	uint8_t *clientid;              /* Optional client id to use */
+	uint8_t *vendorclass;           /* Optional vendor class-id to use */
+	uint8_t *hostname;              /* Optional hostname to use */
+	uint8_t *fqdn;                  /* Optional fully qualified domain name to use */
+	int ifindex;                    /* Index number of the interface to use */
+	int retries;                    /* Max number of request packets */
+	int timeout;                    /* Number of seconds to try to get a lease */
+	uint8_t arp[6];                 /* Our arp address */
 };
 
 extern struct client_config_t client_config;
diff --git a/networking/udhcp/dhcpd.c b/networking/udhcp/dhcpd.c
index 0935a94..7438036 100644
--- a/networking/udhcp/dhcpd.c
+++ b/networking/udhcp/dhcpd.c
@@ -68,11 +68,13 @@
 	timeout_end = time(0) + server_config.auto_time;
 	while (1) { /* loop until universe collapses */
 
-		if (server_socket < 0)
-			if ((server_socket = listen_socket(INADDR_ANY, SERVER_PORT, server_config.interface)) < 0) {
+		if (server_socket < 0) {
+			server_socket = listen_socket(INADDR_ANY, SERVER_PORT, server_config.interface);
+			if (server_socket < 0) {
 				bb_perror_msg("FATAL: cannot create server socket");
 				return 2;
 			}
+		}
 
 		max_sock = udhcp_sp_fd_set(&rfds, server_socket);
 		if (server_config.auto_time) {