ptp4l: Accept any configuration option as a command line argument.

This patch provides a way to use the entire table of configuration options
as "long" command line switches.

Signed-off-by: Richard Cochran <richardcochran@gmail.com>
master
Richard Cochran 2016-12-06 19:40:36 +01:00
parent 891d56e429
commit 4e8dbd8492
3 changed files with 82 additions and 4 deletions

View File

@ -329,6 +329,7 @@ static enum parser_result parse_section_line(char *s, enum config_section *secti
} }
static enum parser_result parse_item(struct config *cfg, static enum parser_result parse_item(struct config *cfg,
int commandline,
const char *section, const char *section,
const char *option, const char *option,
const char *value) const char *value)
@ -387,7 +388,7 @@ static enum parser_result parse_item(struct config *cfg,
return NOT_PARSED; return NOT_PARSED;
} }
} }
} else if (cgi->flags & CFG_ITEM_LOCKED) { } else if (!commandline && cgi->flags & CFG_ITEM_LOCKED) {
/* This global option was set on the command line. */ /* This global option was set on the command line. */
return PARSED_OK; return PARSED_OK;
} else { } else {
@ -415,6 +416,10 @@ static enum parser_result parse_item(struct config *cfg,
dst->flags |= CFG_ITEM_DYNSTR; dst->flags |= CFG_ITEM_DYNSTR;
break; break;
} }
if (commandline) {
dst->flags &= CFG_ITEM_LOCKED;
}
return PARSED_OK; return PARSED_OK;
} }
@ -490,6 +495,25 @@ static void check_deprecated_options(const char **option)
} }
} }
static struct option *config_alloc_longopts(struct config *cfg)
{
struct config_item *ci;
struct option *opts;
int i;
opts = calloc(1, (1 + N_CONFIG_ITEMS) * sizeof(*opts));
if (!opts) {
return NULL;
}
for (i = 0; i < N_CONFIG_ITEMS; i++) {
ci = &config_tab[i];
opts[i].name = ci->label;
opts[i].has_arg = required_argument;
}
return opts;
}
int config_read(char *name, struct config *cfg) int config_read(char *name, struct config *cfg)
{ {
enum config_section current_section = UNKNOWN_SECTION; enum config_section current_section = UNKNOWN_SECTION;
@ -554,7 +578,7 @@ int config_read(char *name, struct config *cfg)
check_deprecated_options(&option); check_deprecated_options(&option);
parser_res = parse_item(cfg, current_section == GLOBAL_SECTION ? parser_res = parse_item(cfg, 0, current_section == GLOBAL_SECTION ?
NULL : current_port->name, option, value); NULL : current_port->name, option, value);
switch (parser_res) { switch (parser_res) {
@ -627,8 +651,15 @@ struct config *config_create(void)
} }
STAILQ_INIT(&cfg->interfaces); STAILQ_INIT(&cfg->interfaces);
cfg->opts = config_alloc_longopts(cfg);
if (!cfg->opts) {
free(cfg);
return NULL;
}
cfg->htab = hash_create(); cfg->htab = hash_create();
if (!cfg->htab) { if (!cfg->htab) {
free(cfg->opts);
free(cfg); free(cfg);
return NULL; return NULL;
} }
@ -657,6 +688,7 @@ struct config *config_create(void)
return cfg; return cfg;
fail: fail:
hash_destroy(cfg->htab, NULL); hash_destroy(cfg->htab, NULL);
free(cfg->opts);
free(cfg); free(cfg);
return NULL; return NULL;
} }
@ -670,6 +702,7 @@ void config_destroy(struct config *cfg)
free(iface); free(iface);
} }
hash_destroy(cfg->htab, config_item_free); hash_destroy(cfg->htab, config_item_free);
free(cfg->opts);
free(cfg); free(cfg);
} }
@ -720,6 +753,33 @@ char *config_get_string(struct config *cfg, const char *section,
return ci->val.s; return ci->val.s;
} }
int config_parse_option(struct config *cfg, const char *opt, const char *val)
{
enum parser_result result;
result = parse_item(cfg, 1, NULL, opt, val);
switch (result) {
case PARSED_OK:
return 0;
case NOT_PARSED:
fprintf(stderr, "unknown option %s\n", opt);
break;
case BAD_VALUE:
fprintf(stderr, "%s is a bad value for option %s\n", val, opt);
break;
case MALFORMED:
fprintf(stderr, "%s is a malformed value for option %s\n",
val, opt);
break;
case OUT_OF_RANGE:
fprintf(stderr, "%s is an out of range value for option %s\n",
val, opt);
break;
}
return -1;
}
int config_set_double(struct config *cfg, const char *option, double val) int config_set_double(struct config *cfg, const char *option, double val)
{ {
struct config_item *ci = config_find_item(cfg, NULL, option); struct config_item *ci = config_find_item(cfg, NULL, option);

View File

@ -20,6 +20,7 @@
#ifndef HAVE_CONFIG_H #ifndef HAVE_CONFIG_H
#define HAVE_CONFIG_H #define HAVE_CONFIG_H
#include <getopt.h>
#include <sys/queue.h> #include <sys/queue.h>
#include "ds.h" #include "ds.h"
@ -43,6 +44,9 @@ struct config {
STAILQ_HEAD(interfaces_head, interface) interfaces; STAILQ_HEAD(interfaces_head, interface) interfaces;
int n_interfaces; int n_interfaces;
/* for parsing command line options */
struct option *opts;
/* hash of all non-legacy items */ /* hash of all non-legacy items */
struct hash *htab; struct hash *htab;
}; };
@ -64,6 +68,13 @@ int config_get_int(struct config *cfg, const char *section,
char *config_get_string(struct config *cfg, const char *section, char *config_get_string(struct config *cfg, const char *section,
const char *option); const char *option);
static inline struct option *config_long_options(struct config *cfg)
{
return cfg->opts;
}
int config_parse_option(struct config *cfg, const char *opt, const char *val);
int config_set_double(struct config *cfg, const char *option, double val); int config_set_double(struct config *cfg, const char *option, double val);
int config_set_section_int(struct config *cfg, const char *section, int config_set_section_int(struct config *cfg, const char *section,

11
ptp4l.c
View File

@ -73,8 +73,9 @@ static void usage(char *progname)
int main(int argc, char *argv[]) int main(int argc, char *argv[])
{ {
char *config = NULL, *req_phc = NULL, *progname; char *config = NULL, *req_phc = NULL, *progname;
int c, err = -1, print_level; int c, err = -1, index, print_level;
struct clock *clock = NULL; struct clock *clock = NULL;
struct option *opts;
struct config *cfg; struct config *cfg;
if (handle_term_signals()) if (handle_term_signals())
@ -84,12 +85,18 @@ int main(int argc, char *argv[])
if (!cfg) { if (!cfg) {
return -1; return -1;
} }
opts = config_long_options(cfg);
/* Process the command line arguments. */ /* Process the command line arguments. */
progname = strrchr(argv[0], '/'); progname = strrchr(argv[0], '/');
progname = progname ? 1+progname : argv[0]; progname = progname ? 1+progname : argv[0];
while (EOF != (c = getopt(argc, argv, "AEP246HSLf:i:p:sl:mqvh"))) { while (EOF != (c = getopt_long(argc, argv, "AEP246HSLf:i:p:sl:mqvh",
opts, &index))) {
switch (c) { switch (c) {
case 0:
if (config_parse_option(cfg, opts[index].name, optarg))
goto out;
break;
case 'A': case 'A':
if (config_set_int(cfg, "delay_mechanism", DM_AUTO)) if (config_set_int(cfg, "delay_mechanism", DM_AUTO))
goto out; goto out;