misc: move command line option parsing to separate function

Earlier main() had lots of temporary variables related to command line
parsing.  By moving these to separate function runtime can forget these
variables when moving on.  If nothing else this makes running gdb nicer when
debugging crashes, but as said stack memory should also be spared for better
purpose.

Signed-off-by: Sami Kerola <kerolasa@iki.fi>
This commit is contained in:
Sami Kerola 2017-11-13 21:12:50 +00:00
parent 3369278fc0
commit 74b697321f
No known key found for this signature in database
GPG key ID: A9553245FDE9B739

View file

@ -95,6 +95,7 @@ static void skip_arg_parse(struct conf_t *state, char *optarg)
OPT_ARG_MINSIZE,
OPT_ARG_SUPRESSED
};
char *const tokens[] = {
[OPT_ARG_OK] = "ok",
[OPT_ARG_WARNING] = "warning",
@ -106,7 +107,7 @@ static void skip_arg_parse(struct conf_t *state, char *optarg)
char *value;
while (*optarg != '\0') {
switch(getsubopt(&optarg, tokens, &value)) {
switch (getsubopt(&optarg, tokens, &value)) {
case OPT_ARG_OK:
state->skip_ok = 1;
break;
@ -128,33 +129,9 @@ static void skip_arg_parse(struct conf_t *state, char *optarg)
}
}
/*! \brief Start of execution. Parse options, and call other other
* functions one after another. At the moment adding threading support
* would be difficult, but there does not seem to be valid reason to
* consider that. Overall the analysis already quick enough even without
* making it parallel.
*
* \return Return value indicates success or fail or analysis, unless
* either --warning or --critical options are in use, which makes the
* return value in some cases to match with Nagios expectations about
* alarming. */
int main(int argc, char **argv)
/*! \brief Command options parser. */
static char parse_command_line_opts(struct conf_t *state, int argc, char **argv)
{
struct conf_t state = {
.warning = ALARM_WARN,
.critical = ALARM_CRIT,
.warn_count = 0x100000000, /* == 2^32 that is the entire IPv4 space */
.crit_count = 0x100000000, /* basically turns off the count criteria */
.header_limit = 8,
.color_mode = color_auto,
.ranges_size = 64,
.ip_version = IPvUNKNOWN,
0
};
int option_index = 0;
char output_format = '\0';
int alarming = 0;
enum {
OPT_SNET_ALARMS = CHAR_MAX + 1,
OPT_WARN,
@ -167,7 +144,6 @@ int main(int argc, char **argv)
OPT_SET_IPV,
OPT_MUSTACH
};
int ret_val;
static struct option const long_options[] = {
{"config", required_argument, NULL, 'c'},
@ -193,27 +169,23 @@ int main(int argc, char **argv)
{"ip-version", required_argument, NULL, OPT_SET_IPV},
{NULL, 0, NULL, 0}
};
char output_format = '\0';
int alarming = 0;
atexit(close_stdout);
set_program_name(argv[0]);
prepare_memory(&state);
set_ipv_functions(&state, IPvUNKNOWN);
/* Parse command line options */
while (1) {
int c;
c = getopt_long(argc, argv, "c:l:f:o:s:rL:pAvh", long_options, &option_index);
c = getopt_long(argc, argv, "c:l:f:o:s:rL:pAvh", long_options, NULL);
if (c == EOF)
break;
switch (c) {
case 'c':
/* config file */
state.dhcpdconf_file = optarg;
state->dhcpdconf_file = optarg;
break;
case 'l':
/* lease file */
state.dhcpdlease_file = optarg;
state->dhcpdlease_file = optarg;
break;
case 'f':
/* Output format */
@ -222,16 +194,16 @@ int main(int argc, char **argv)
case 's':
{
/* Output sorting option */
struct output_sort *p = state.sorts;
struct output_sort *p = state->sorts;
size_t len;
while (p && p->next)
p = p->next;
for (len = 0; len < strlen(optarg); len++) {
if (state.sorts == NULL) {
state.sorts =
if (state->sorts == NULL) {
state->sorts =
xcalloc(1, sizeof(struct output_sort));
p = state.sorts;
p = state->sorts;
} else {
p->next = xcalloc(1, sizeof(struct output_sort));
p = p->next;
@ -242,62 +214,62 @@ int main(int argc, char **argv)
break;
case 'r':
/* What ever sort in reverse order */
state.reverse_order = 1;
state->reverse_order = 1;
break;
case 'o':
/* Output file */
state.output_file = optarg;
state->output_file = optarg;
break;
case 'L':
/* Specification what will be printed */
state.header_limit = return_limit(optarg[0]);
state.number_limit = return_limit(optarg[1]);
state->header_limit = return_limit(optarg[0]);
state->number_limit = return_limit(optarg[1]);
break;
case OPT_MUSTACH:
#ifdef BUILD_MUSTACH
state.mustach_template = optarg;
state->mustach_template = optarg;
output_format = 'm';
#else
error(EXIT_FAILURE, 0, "compiled without mustach support");
#endif
break;
case OPT_COLOR:
state.color_mode = parse_color_mode(optarg);
if (state.color_mode == color_unknown)
state->color_mode = parse_color_mode(optarg);
if (state->color_mode == color_unknown)
error(EXIT_FAILURE, errno, "unknown color mode: %s", quote(optarg));
break;
case OPT_SKIP:
skip_arg_parse(&state, optarg);
skip_arg_parse(state, optarg);
break;
case OPT_SNET_ALARMS:
state.snet_alarms = 1;
state->snet_alarms = 1;
break;
case OPT_WARN:
alarming = 1;
state.warning = strtod_or_err(optarg, "illegal argument");
state->warning = strtod_or_err(optarg, "illegal argument");
break;
case OPT_CRIT:
alarming = 1;
state.critical = strtod_or_err(optarg, "illegal argument");
state->critical = strtod_or_err(optarg, "illegal argument");
break;
case OPT_WARN_COUNT:
alarming = 1;
state.warn_count = strtod_or_err(optarg, "illegal argument");
state->warn_count = strtod_or_err(optarg, "illegal argument");
break;
case OPT_CRIT_COUNT:
alarming = 1;
state.crit_count = strtod_or_err(optarg, "illegal argument");
state->crit_count = strtod_or_err(optarg, "illegal argument");
break;
case OPT_MINSIZE:
state.minsize = strtod_or_err(optarg, "illegal argument");
state->minsize = strtod_or_err(optarg, "illegal argument");
break;
case OPT_SET_IPV:
switch (optarg[0]) {
case '4':
set_ipv_functions(&state, IPv4);
set_ipv_functions(state, IPv4);
break;
case '6':
set_ipv_functions(&state, IPv6);
set_ipv_functions(state, IPv6);
break;
default:
error(EXIT_FAILURE, 0, "unknown --ip-version argument: %s", optarg);
@ -305,11 +277,11 @@ int main(int argc, char **argv)
break;
case 'p':
/* Print additional performance data in alarming mode */
state.perfdata = 1;
state->perfdata = 1;
break;
case 'A':
/* Treat single networks as shared with network CIDR as name */
state.all_as_shared = 1;
state->all_as_shared = 1;
break;
case 'v':
/* Print version */
@ -323,17 +295,17 @@ int main(int argc, char **argv)
}
/* Use default dhcpd.conf when user did not define anything. */
if (state.dhcpdconf_file == NULL)
state.dhcpdconf_file = DHCPDCONF_FILE;
if (state->dhcpdconf_file == NULL)
state->dhcpdconf_file = DHCPDCONF_FILE;
/* Use default dhcpd.leases when user did not define anything. */
if (state.dhcpdlease_file == NULL)
state.dhcpdlease_file = DHCPDLEASE_FILE;
if (state->dhcpdlease_file == NULL)
state->dhcpdlease_file = DHCPDLEASE_FILE;
/* Use default limits when user did not define anything. */
if (state.header_limit == 8) {
if (state->header_limit == 8) {
char const *default_limit = OUTPUT_LIMIT;
state.header_limit = return_limit(default_limit[0]);
state.number_limit = return_limit(default_limit[1]);
state->header_limit = return_limit(default_limit[0]);
state->number_limit = return_limit(default_limit[1]);
}
/* Output format is not defined, if alarm thresholds are then it's alarming, else use the
* default. */
@ -346,6 +318,37 @@ int main(int argc, char **argv)
output_format = default_format[0];
}
}
return output_format;
}
/*!\brief Start of execution. This will mostly call other functions one
* after another.
*
* \return Return value indicates success or fail or analysis, unless
* either --warning or --critical options are in use, which makes the
* return value in some cases to match with Nagios expectations about
* alarming. */
int main(int argc, char **argv)
{
struct conf_t state = {
.warning = ALARM_WARN,
.critical = ALARM_CRIT,
.warn_count = 0x100000000, /* == 2^32 that is the entire IPv4 space */
.crit_count = 0x100000000, /* basically turns off the count criteria */
.header_limit = 8,
.color_mode = color_auto,
.ranges_size = 64,
.ip_version = IPvUNKNOWN,
0
};
char output_format;
int ret_val;
atexit(close_stdout);
set_program_name(argv[0]);
prepare_memory(&state);
set_ipv_functions(&state, IPvUNKNOWN);
output_format = parse_command_line_opts(&state, argc, argv);
/* Do the job */
parse_config(&state, 1, state.dhcpdconf_file, state.shared_net_root);