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)
if (adjtimex(&t) >= 0)
timePropertiesDS.currentUtcOffset = t.tai;
pp_config_file(ppg, &argc, argv, NULL, "link 0\niface eth0\n"
"proto udp\n" /* mandatory trailing \n */);
if (pp_parse_cmdline(ppg, argc, argv) != 0)
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++) {
......@@ -95,9 +101,6 @@ int main(int argc, char **argv)
exit(__LINE__);
}
if (pp_parse_cmdline(ppg, argc, argv) != 0)
return -1;
pp_open_globals(ppg);
unix_main_loop(ppg);
......
......@@ -90,9 +90,25 @@ int main(int argc, char **argv)
timePropertiesDS.currentUtcOffset = *p;
}
pp_config_file(ppg, &argc, argv, "/wr/etc/ppsi.conf",
"link 0\niface wr0\n" /* mandatory trailing \n */);
if (pp_parse_cmdline(ppg, argc, argv) != 0)
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++) {
ppi = &ppg->pp_instances[i];
......@@ -126,9 +142,6 @@ int main(int argc, char **argv)
}
if (pp_parse_cmdline(ppg, argc, argv) != 0)
return -1;
pp_open_globals(ppg);
wrs_main_loop(ppg);
......
......@@ -207,6 +207,7 @@ struct pp_globals {
int nlinks;
int max_links;
int cfg_items; /* Remember how many we parsed */
void *arch_data; /* if arch needs it */
/* FIXME Here include all is common to many interfaces */
......
......@@ -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_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_UDP 1
......
......@@ -72,3 +72,11 @@ int ppsi_main(int argc, char **argv)
bare_main_loop(ppi);
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[] = {
//{"-d", "display stats"},
//{"-D", "display stats in .csv format"},
//{"-R", "record data about sync packets in a file"},
{"-f FILE", "read configuration file"},
{"-V", "run in verbose mode"},
{"-d STRING", "diagnostic level (see diag-macros.h)"},
CMD_LINE_SEPARATOR,
......@@ -114,6 +115,9 @@ int pp_parse_cmdline(struct pp_globals *ppg, int argc, char **argv)
a = argv[++i];
pp_global_flags = pp_diag_parse(a);
break;
case 'f':
pp_config_file(ppg, 1, argv[++i]);
break;
case 'x':
GOPTS(ppg)->no_rst_clk = 1;
break;
......
......@@ -172,13 +172,14 @@ static char *first_word(char *line, char **rest)
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 argname *n;
char *word;
int i;
current_ppg = ppg;
pp_diag(NULL, config, 2, "parsing line %i: \"%s\"\n", lineno, line);
word = first_word(line, &line);
/* now line points to the next word, with no leading blanks */
......@@ -237,31 +238,32 @@ static int pp_parse_line(char *line, int lineno)
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)
{
current_ppg = ppg;
int errcount = 0;
char *line, *rest, term;
int lineno = 0;
int lineno = 1;
line = conf;
do {
lineno++;
for (rest = line; *rest && *rest != '\n'; rest++)
for (rest = line;
*rest && *rest != '\n' && *rest != ';'; rest++)
;
term = *rest;
*rest = '\0';
if (*line)
errcount += pp_parse_line(line, lineno) < 0;
errcount += pp_config_line(ppg, line, lineno) < 0;
line = rest + 1;
if (term == '\n')
lineno++;
} while (term); /* if terminator was already 0, we are done */
pp_config_line(ppg, "", 0); /* done: clear current_ppi */
return errcount ? -1 : 0;
}
/* Open about a file, warn if not found */
static int pp_open_conf_file(char **argv, char *name)
/* Open a file, warn if not found */
static int pp_open_conf_file(char *name)
{
int fd;
......@@ -269,76 +271,59 @@ static int pp_open_conf_file(char **argv, char *name)
return -1;
fd = open(name, O_RDONLY);
if (fd >= 0) {
pp_printf("%s: Using config file %s\n", argv[0], name);
pp_printf("Using config file %s\n", name);
return fd;
}
pp_printf("%s: Warning: %s: %s\n", argv[0], name,
strerror(errno));
pp_printf("Warning: %s: %s\n", name, strerror(errno));
return -1;
}
/*
* This is the public entry point, that is passed both a default name
* and a default value for the configuration file. This only builds
* in hosted environment.
* This is one of the public entry points, opening a file
*
* The function allows "-f <config>" to appear on the command line,
* and modifies the command line accordingly (hackish, I admit)
* "force" means that the called wants to open *this file.
* 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,
char *default_name, char *default_conf)
int pp_config_file(struct pp_globals *ppg, int force, char *fname)
{
char *name = NULL;
int conf_fd, i, conf_len = 0;
int r = 0, next_r;
struct stat conf_fs;
char *conf_buf;
current_ppg = ppg;
/* First, look for fname on the command line (which is parsed later) */
for (i = 1; i < *argcp - 1; i++) {
if (strcmp(argv[i], "-f"))
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(fname);
if (conf_fd < 0) {
if (force)
ppg->cfg_items++;
return -1;
}
conf_fd = pp_open_conf_file(argv, name);
/* 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);
ppg->cfg_items++;
close(conf_fd);
}
/* read the whole file, it is split up later on */
/* We need this trailing \0 for the parser */
conf_buf[conf_len + 1] = '\0';
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);
i = pp_parse_conf(ppg, conf_buf, conf_len);
free(conf_buf);
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