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 */
/* 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;
}
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<n; ii++) {
+ free((*cfg_files)[ii]);
+ }
+ free(*cfg_files); /* safe even if n==0 */
+ }
+}
/* TBD -- Trust Links */
} TR_CFG;
-int tr_find_config_files (struct dirent ***cfg_files);
-TR_CFG_RC tr_parse_config (TR_INSTANCE *tr, int n, struct dirent **cfg_files);
+int tr_find_config_files (const char *config_dir, struct dirent ***cfg_files);
+void tr_free_config_file_list(int n, struct dirent ***cfg_files);
+TR_CFG_RC tr_parse_config (TR_INSTANCE *tr, const char *config_dir, int n, struct dirent **cfg_files);
TR_CFG_RC tr_apply_new_config (TR_INSTANCE *tr);
TR_CFG_RC tr_cfg_validate (TR_CFG *trc);
void tr_cfg_free(TR_CFG *cfg);
#include <stdio.h>
#include <stdlib.h>
#include <jansson.h>
+#include <argp.h>
#include <tr.h>
#include <tr_filter.h>
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))) {