Commit ad1297dc authored by Alessandro Rubini's avatar Alessandro Rubini

config: fold back config-file parsing into command line parsing

This undoes part of the strangeness we had in configuration files. Now
"-f" is recognized on the command line, and more than one file can be
specified. Only if no file is found, the default one is used
(wr-switch looks in /wrc/etc/ppsi.conf first).
Signed-off-by: Alessandro Rubini's avatarAlessandro Rubini <rubini@gnudd.com>
parent 4455858c
...@@ -61,8 +61,14 @@ int main(int argc, char **argv) ...@@ -61,8 +61,14 @@ int main(int argc, char **argv)
if (adjtimex(&t) >= 0) if (adjtimex(&t) >= 0)
timePropertiesDS.currentUtcOffset = t.tai; timePropertiesDS.currentUtcOffset = t.tai;
pp_config_file(ppg, &argc, argv, NULL, "link 0\niface eth0\n" if (pp_parse_cmdline(ppg, argc, argv) != 0)
"proto udp\n" /* mandatory trailing \n */); return -1;
/* If no item has been parsed, provide a default file or string */
if (ppg->cfg_items == 0)
pp_config_file(ppg, 0, PP_DEFAULT_CONFIGFILE);
if (ppg->cfg_items == 0)
pp_config_string(ppg, strdup("link 0; iface eth0; proto udp"));
for (i = 0; i < ppg->nlinks; i++) { for (i = 0; i < ppg->nlinks; i++) {
...@@ -95,9 +101,6 @@ int main(int argc, char **argv) ...@@ -95,9 +101,6 @@ int main(int argc, char **argv)
exit(__LINE__); exit(__LINE__);
} }
if (pp_parse_cmdline(ppg, argc, argv) != 0)
return -1;
pp_open_globals(ppg); pp_open_globals(ppg);
unix_main_loop(ppg); unix_main_loop(ppg);
......
...@@ -90,9 +90,25 @@ int main(int argc, char **argv) ...@@ -90,9 +90,25 @@ int main(int argc, char **argv)
timePropertiesDS.currentUtcOffset = *p; timePropertiesDS.currentUtcOffset = *p;
} }
pp_config_file(ppg, &argc, argv, "/wr/etc/ppsi.conf", if (pp_parse_cmdline(ppg, argc, argv) != 0)
"link 0\niface wr0\n" /* mandatory trailing \n */); return -1;
/* If no item has been parsed, provide a default file or string */
if (ppg->cfg_items == 0)
pp_config_file(ppg, 0, "/wr/etc/ppsi.conf");
if (ppg->cfg_items == 0)
pp_config_file(ppg, 0, PP_DEFAULT_CONFIGFILE);
if (ppg->cfg_items == 0) {
/* Default configuration for WR switch is all ports */
char s[128];
int i;
for (i = 0; i < 18; i++) {
sprintf(s, "port wr%i; iface wr%i; proto raw;"
"extension whiterabbit; role auto", i, i);
pp_config_string(ppg, s);
}
}
for (i = 0; i < ppg->nlinks; i++) { for (i = 0; i < ppg->nlinks; i++) {
ppi = &ppg->pp_instances[i]; ppi = &ppg->pp_instances[i];
...@@ -126,9 +142,6 @@ int main(int argc, char **argv) ...@@ -126,9 +142,6 @@ int main(int argc, char **argv)
} }
if (pp_parse_cmdline(ppg, argc, argv) != 0)
return -1;
pp_open_globals(ppg); pp_open_globals(ppg);
wrs_main_loop(ppg); wrs_main_loop(ppg);
......
...@@ -207,6 +207,7 @@ struct pp_globals { ...@@ -207,6 +207,7 @@ struct pp_globals {
int nlinks; int nlinks;
int max_links; int max_links;
int cfg_items; /* Remember how many we parsed */
void *arch_data; /* if arch needs it */ void *arch_data; /* if arch needs it */
/* FIXME Here include all is common to many interfaces */ /* FIXME Here include all is common to many interfaces */
......
...@@ -255,8 +255,35 @@ extern int pp_close_globals(struct pp_globals *ppg); ...@@ -255,8 +255,35 @@ extern int pp_close_globals(struct pp_globals *ppg);
extern int pp_parse_cmdline(struct pp_globals *ppg, int argc, char **argv); extern int pp_parse_cmdline(struct pp_globals *ppg, int argc, char **argv);
extern int pp_config_file(struct pp_globals *ppg, int *argcp, char **argv, /*
char *default_name, char *default_conf); * Configuration: we are structure-based, and a typedef simplifies things
*/
typedef int (*cfg_handler)(int lineno, int iarg, char *sarg);
struct pp_argname {
char *name;
int value;
};
enum pp_argtype {
ARG_NONE,
ARG_INT,
ARG_STR,
ARG_NAMES,
};
struct pp_argline {
cfg_handler f;
char *keyword; /* Each line starts with a keyword */
enum pp_argtype t;
struct pp_argname *args;
};
/* Both the architecture and the extension can provide config arguments */
extern struct pp_argline pp_arch_arglines[];
extern struct pp_argline pp_ext_arglines[];
/* Note: config_string modifies the string it receives */
extern int pp_config_string(struct pp_globals *ppg, char *s);
extern int pp_config_file(struct pp_globals *ppg, int force, char *fname);
#define PPSI_PROTO_RAW 0 #define PPSI_PROTO_RAW 0
#define PPSI_PROTO_UDP 1 #define PPSI_PROTO_UDP 1
......
...@@ -72,3 +72,11 @@ int ppsi_main(int argc, char **argv) ...@@ -72,3 +72,11 @@ int ppsi_main(int argc, char **argv)
bare_main_loop(ppi); bare_main_loop(ppi);
return 0; return 0;
} }
/* We can't parse a config file (no system calls, /me is lazy) */
int pp_config_file(struct pp_globals *ppg, int force, char *fname)
{
pp_printf("No support for config file: can't read \"%s\"\n",
fname);
return -1;
}
...@@ -23,6 +23,7 @@ static struct cmd_line_opt cmd_line_list[] = { ...@@ -23,6 +23,7 @@ static struct cmd_line_opt cmd_line_list[] = {
//{"-d", "display stats"}, //{"-d", "display stats"},
//{"-D", "display stats in .csv format"}, //{"-D", "display stats in .csv format"},
//{"-R", "record data about sync packets in a file"}, //{"-R", "record data about sync packets in a file"},
{"-f FILE", "read configuration file"},
{"-V", "run in verbose mode"}, {"-V", "run in verbose mode"},
{"-d STRING", "diagnostic level (see diag-macros.h)"}, {"-d STRING", "diagnostic level (see diag-macros.h)"},
CMD_LINE_SEPARATOR, CMD_LINE_SEPARATOR,
...@@ -114,6 +115,9 @@ int pp_parse_cmdline(struct pp_globals *ppg, int argc, char **argv) ...@@ -114,6 +115,9 @@ int pp_parse_cmdline(struct pp_globals *ppg, int argc, char **argv)
a = argv[++i]; a = argv[++i];
pp_global_flags = pp_diag_parse(a); pp_global_flags = pp_diag_parse(a);
break; break;
case 'f':
pp_config_file(ppg, 1, argv[++i]);
break;
case 'x': case 'x':
GOPTS(ppg)->no_rst_clk = 1; GOPTS(ppg)->no_rst_clk = 1;
break; break;
......
...@@ -172,13 +172,14 @@ static char *first_word(char *line, char **rest) ...@@ -172,13 +172,14 @@ static char *first_word(char *line, char **rest)
return ret; return ret;
} }
static int pp_parse_line(char *line, int lineno) static int pp_config_line(struct pp_globals *ppg, char *line, int lineno)
{ {
struct argline *l; struct argline *l;
struct argname *n; struct argname *n;
char *word; char *word;
int i; int i;
current_ppg = ppg;
pp_diag(NULL, config, 2, "parsing line %i: \"%s\"\n", lineno, line); pp_diag(NULL, config, 2, "parsing line %i: \"%s\"\n", lineno, line);
word = first_word(line, &line); word = first_word(line, &line);
/* now line points to the next word, with no leading blanks */ /* now line points to the next word, with no leading blanks */
...@@ -237,31 +238,32 @@ static int pp_parse_line(char *line, int lineno) ...@@ -237,31 +238,32 @@ static int pp_parse_line(char *line, int lineno)
return 0; return 0;
} }
/* Parse a whole string by splitting line (shoud I fgets instead?) */ /* Parse a whole string by splitting lines at '\n' or ';' */
static int pp_parse_conf(struct pp_globals *ppg, char *conf, int len) static int pp_parse_conf(struct pp_globals *ppg, char *conf, int len)
{ {
current_ppg = ppg;
int errcount = 0; int errcount = 0;
char *line, *rest, term; char *line, *rest, term;
int lineno = 0; int lineno = 1;
line = conf; line = conf;
do { do {
lineno++; for (rest = line;
for (rest = line; *rest && *rest != '\n'; rest++) *rest && *rest != '\n' && *rest != ';'; rest++)
; ;
term = *rest; term = *rest;
*rest = '\0'; *rest = '\0';
if (*line) if (*line)
errcount += pp_parse_line(line, lineno) < 0; errcount += pp_config_line(ppg, line, lineno) < 0;
line = rest + 1; line = rest + 1;
if (term == '\n')
lineno++;
} while (term); /* if terminator was already 0, we are done */ } while (term); /* if terminator was already 0, we are done */
pp_config_line(ppg, "", 0); /* done: clear current_ppi */
return errcount ? -1 : 0; return errcount ? -1 : 0;
} }
/* Open about a file, warn if not found */ /* Open a file, warn if not found */
static int pp_open_conf_file(char **argv, char *name) static int pp_open_conf_file(char *name)
{ {
int fd; int fd;
...@@ -269,76 +271,59 @@ static int pp_open_conf_file(char **argv, char *name) ...@@ -269,76 +271,59 @@ static int pp_open_conf_file(char **argv, char *name)
return -1; return -1;
fd = open(name, O_RDONLY); fd = open(name, O_RDONLY);
if (fd >= 0) { if (fd >= 0) {
pp_printf("%s: Using config file %s\n", argv[0], name); pp_printf("Using config file %s\n", name);
return fd; return fd;
} }
pp_printf("%s: Warning: %s: %s\n", argv[0], name, pp_printf("Warning: %s: %s\n", name, strerror(errno));
strerror(errno));
return -1; return -1;
} }
/* /*
* This is the public entry point, that is passed both a default name * This is one of the public entry points, opening a file
* and a default value for the configuration file. This only builds
* in hosted environment.
* *
* The function allows "-f <config>" to appear on the command line, * "force" means that the called wants to open *this file.
* and modifies the command line accordingly (hackish, I admit) * In this case we count it even if it fails, so the default
* config file is not used
*/ */
int pp_config_file(struct pp_globals *ppg, int *argcp, char **argv, int pp_config_file(struct pp_globals *ppg, int force, char *fname)
char *default_name, char *default_conf)
{ {
char *name = NULL;
int conf_fd, i, conf_len = 0; int conf_fd, i, conf_len = 0;
int r = 0, next_r;
struct stat conf_fs; struct stat conf_fs;
char *conf_buf; char *conf_buf;
current_ppg = ppg; conf_fd = pp_open_conf_file(fname);
if (conf_fd < 0) {
/* First, look for fname on the command line (which is parsed later) */ if (force)
for (i = 1; i < *argcp - 1; i++) { ppg->cfg_items++;
if (strcmp(argv[i], "-f")) return -1;
continue;
/* found: remove it from argv */
name = argv[i + 1];
for (;i < *argcp - 2; i++)
argv[i] = argv[i + 2];
*argcp -= 2;
} }
conf_fd = pp_open_conf_file(argv, name); ppg->cfg_items++;
/* Then try the caller-provided name */
if (conf_fd < 0)
conf_fd = pp_open_conf_file(argv, default_name);
/* Finally, the project-wide name */
if (conf_fd < 0)
conf_fd = pp_open_conf_file(argv, PP_DEFAULT_CONFIGFILE);
/* If nothing, use provided string */
if (conf_fd < 0) { /* Read it, if any */
conf_buf = strdup(default_conf);
conf_len = strlen(conf_buf) - 1;
} else {
int r = 0, next_r;
fstat(conf_fd, &conf_fs);
conf_buf = calloc(1, conf_fs.st_size + 2);
do {
next_r = conf_fs.st_size - conf_len;
r = read(conf_fd, &conf_buf[conf_len], next_r);
if (r <= 0)
break;
conf_len = strlen(conf_buf);
} while (conf_len < conf_fs.st_size);
close(conf_fd); /* read the whole file, it is split up later on */
}
/* We need this trailing \0 for the parser */ fstat(conf_fd, &conf_fs);
conf_buf[conf_len + 1] = '\0'; conf_buf = calloc(1, conf_fs.st_size + 2);
do {
next_r = conf_fs.st_size - conf_len;
r = read(conf_fd, &conf_buf[conf_len], next_r);
if (r <= 0)
break;
conf_len = strlen(conf_buf);
} while (conf_len < conf_fs.st_size);
close(conf_fd);
i = pp_parse_conf(ppg, conf_buf, conf_len); i = pp_parse_conf(ppg, conf_buf, conf_len);
free(conf_buf); free(conf_buf);
return i; return i;
} }
/*
* This is the other public entry points, opening a file
*/
int pp_config_string(struct pp_globals *ppg, char *s)
{
return pp_parse_conf(ppg, s, strlen(s));
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment