From: Jennifer Richards Date: Fri, 6 May 2016 02:16:38 +0000 (-0400) Subject: Process command-line args, add config dir option. X-Git-Tag: v1.5.2~10 X-Git-Url: http://www.project-moonshot.org/gitweb/?p=trust_router.git;a=commitdiff_plain;h=5637d2e50e55fe5f8ce1b9691747a670b3af83e9 Process command-line args, add config dir option. Add command-line processing with argp. Introduced an option to read configuration files from other than the working directory. Also, modified debug output in tr_parse_config to correctly indicate this function name instead of tr_read_config. --- diff --git a/common/tr_config.c b/common/tr_config.c index 5e48e3e..1da6dc4 100644 --- a/common/tr_config.c +++ b/common/tr_config.c @@ -866,11 +866,19 @@ TR_CFG_RC tr_cfg_validate (TR_CFG *trc) { return rc; } -TR_CFG_RC tr_parse_config (TR_INSTANCE *tr, int n, struct dirent **cfg_files) { +/* Join two paths and return a pointer to the result. This should be freed + * via talloc_free. Returns NULL on failure. */ +static char *join_paths(const char *p1, const char *p2) { + return talloc_asprintf(NULL, "%s/%s", p1, p2); /* returns NULL on a failure */ +} + +/* Reads configuration files in config_dir ("" or "./" will use the current directory) */ +TR_CFG_RC tr_parse_config (TR_INSTANCE *tr, const char *config_dir, int n, struct dirent **cfg_files) { json_t *jcfg; json_error_t rc; + char *file_with_path; - if ((!tr) || (!cfg_files)) + if ((!tr) || (!cfg_files) || (n<=0)) return TR_CFG_BAD_PARAMS; /* If there is a partial/abandoned config lying around, free it */ @@ -884,19 +892,26 @@ TR_CFG_RC tr_parse_config (TR_INSTANCE *tr, int n, struct dirent **cfg_files) { /* Parse configuration information from each config file */ while (n--) { - tr_debug("tr_read_config: Parsing %s.", cfg_files[n]->d_name); - if (NULL == (jcfg = json_load_file(cfg_files[n]->d_name, - JSON_DISABLE_EOF_CHECK, &rc))) { - tr_debug("tr_read_config: Error parsing config file %s.", - cfg_files[n]->d_name); + file_with_path=join_paths(config_dir, cfg_files[n]->d_name); /* must free result with talloc_free */ + if(file_with_path == NULL) { + tr_crit("tr_parse_config: error joining path."); + return TR_CFG_NOMEM; + } + tr_debug("tr_parse_config: Parsing %s.", cfg_files[n]->d_name); /* print the filename without the path */ + if (NULL == (jcfg = json_load_file(file_with_path, + JSON_DISABLE_EOF_CHECK, &rc))) { + tr_debug("tr_parse_config: Error parsing config file %s.", + cfg_files[n]->d_name); + talloc_free(file_with_path); return TR_CFG_NOPARSE; } - + talloc_free(file_with_path); /* done with filename */ + if ((TR_CFG_SUCCESS != tr_cfg_parse_internal(tr->new_cfg, jcfg)) || - (TR_CFG_SUCCESS != tr_cfg_parse_rp_clients(tr->new_cfg, jcfg)) || - (TR_CFG_SUCCESS != tr_cfg_parse_idp_realms(tr->new_cfg, jcfg)) || - (TR_CFG_SUCCESS != tr_cfg_parse_default_servers(tr->new_cfg, jcfg)) || - (TR_CFG_SUCCESS != tr_cfg_parse_comms(tr->new_cfg, jcfg))) { + (TR_CFG_SUCCESS != tr_cfg_parse_rp_clients(tr->new_cfg, jcfg)) || + (TR_CFG_SUCCESS != tr_cfg_parse_idp_realms(tr->new_cfg, jcfg)) || + (TR_CFG_SUCCESS != tr_cfg_parse_default_servers(tr->new_cfg, jcfg)) || + (TR_CFG_SUCCESS != tr_cfg_parse_comms(tr->new_cfg, jcfg))) { tr_cfg_free(tr->new_cfg); return TR_CFG_ERROR; } @@ -982,26 +997,42 @@ static int is_cfg_file(const struct dirent *dent) { return 0; } -int tr_find_config_files (struct dirent ***cfg_files) { +/* Find configuration files in a particular directory. Returns the + * number of entries found, 0 if none are found, or <0 for some + * errors. If n>=0, the cfg_files parameter will contain a newly + * allocated array of pointers to struct dirent entries, as returned + * by scandir(). These can be freed with tr_free_config_file_list(). + */ +int tr_find_config_files (const char *config_dir, struct dirent ***cfg_files) { int n = 0, i = 0; - n = scandir(".", cfg_files, &is_cfg_file, 0); + n = scandir(config_dir, cfg_files, &is_cfg_file, 0); if (n < 0) { perror("scandir"); - tr_debug("tr_find_config: scandir error."); - return 0; - } - - if (n == 0) { + tr_debug("tr_find_config: scandir error trying to scan %s.", config_dir); + } else if (n == 0) { tr_debug("tr_find_config: No config files found."); - return 0; + } else { + i = n; + while(i--) { + tr_debug("tr_find_config: Config file found (%s).", (*cfg_files)[i]->d_name); + } } - i = n; - while(i--) { - tr_debug("tr_find_config: Config file found (%s).", (*cfg_files)[i]->d_name); - } - return n; } + +/* Free memory allocated for configuration file list returned from tr_find_config_files(). + * This can be called regardless of the return value of tr_find_config_values(). */ +void tr_free_config_file_list(int n, struct dirent ***cfg_files) { + int ii; + + /* if n < 0, then scandir did not allocate anything because it failed */ + if(n>=0) { + for(ii=0; ii #include #include +#include #include #include @@ -254,35 +255,108 @@ static int tr_tids_gss_handler(gss_name_t client_name, TR_NAME *gss_name, return 0; } +/* Strip trailing / from a path name.*/ +static void remove_trailing_slash(char *s) { + size_t n; -int main (int argc, const char *argv[]) + n=strlen(s); + if(s[n-1]=='/') { + s[n-1]='\0'; + } +} + +/* command-line option setup */ + +/* argp global parameters */ +const char *argp_program_bug_address=PACKAGE_BUGREPORT; /* bug reporting address */ + +/* doc strings */ +static const char doc[]=PACKAGE_NAME " - Moonshot Trust Router"; +static const char arg_doc[]=""; /* string describing arguments, if any */ + +/* define the options here. Fields are: + * { long-name, short-name, variable name, options, help description } */ +static const struct argp_option cmdline_options[] = { + { "config-dir", 'c', "DIR", 0, "Specify configuration file location (default is current directory)"}, + { NULL } +}; + +/* structure for communicating with option parser */ +struct cmdline_args { + char *config_dir; +}; + +/* parser for individual options - fills in a struct cmdline_args */ +static error_t parse_option(int key, char *arg, struct argp_state *state) +{ + /* get a shorthand to the command line argument structure, part of state */ + struct cmdline_args *arguments=state->input; + + switch (key) { + case 'c': + if (arg == NULL) { + /* somehow we got called without an argument */ + return ARGP_ERR_UNKNOWN; + } + arguments->config_dir=arg; + break; + + default: + return ARGP_ERR_UNKNOWN; + } + + return 0; /* success */ +} + +/* assemble the argp parser */ +static struct argp argp = {cmdline_options, parse_option, arg_doc, doc}; + + +int main (int argc, char *argv[]) { TR_INSTANCE *tr = NULL; struct dirent **cfg_files = NULL; TR_CFG_RC rc = TR_CFG_SUCCESS; /* presume success */ - int err = 0, n = 0;; - - /* parse command-line arguments? -- TBD */ + int err = 0, n = 0; + struct cmdline_args opts; /* Use standalone logging */ tr_log_open(); + /* parse command-line arguments */ + /* set defaults */ + opts.config_dir="."; + + /* parse the command line*/ + argp_parse(&argp, argc, argv, 0, 0, &opts); + + /* process options */ + remove_trailing_slash(opts.config_dir); + /* create a Trust Router instance */ if (NULL == (tr = tr_create())) { tr_crit("Unable to create Trust Router instance, exiting."); return 1; } - /* find the configuration files */ - if (0 == (n = tr_find_config_files(&cfg_files))) { + /* find the configuration files -- n.b., tr_find_config_files() + * allocates memory to cfg_files which we must later free */ + tr_debug("Reading configuration files from %s/", opts.config_dir); + n = tr_find_config_files(opts.config_dir, &cfg_files); + if (n <= 0) { tr_crit("Can't locate configuration files, exiting."); + tr_free_config_file_list(n, &cfg_files); exit(1); } - if (TR_CFG_SUCCESS != tr_parse_config(tr, n, cfg_files)) { + if (TR_CFG_SUCCESS != tr_parse_config(tr, opts.config_dir, n, cfg_files)) { tr_crit("Error decoding configuration information, exiting."); + tr_free_config_file_list(n, &cfg_files); exit(1); } + + /* we are now done with the config filenames, free those */ + tr_free_config_file_list(n, &cfg_files); /* apply initial configuration */ if (TR_CFG_SUCCESS != (rc = tr_apply_new_config(tr))) {