diff --git a/config.c b/config.c index 9f22a60c..ca5c984d 100644 --- a/config.c +++ b/config.c @@ -26,10 +26,25 @@ static void parse_event_notifications_list(t_configuration_options *options, const char *arg); static void tablespace_list_append(t_configuration_options *options, const char *arg); +static void exit_with_errors(ErrorList *config_errors); +const static char *_progname = '\0'; static char config_file_path[MAXPGPATH]; static bool config_file_provided = false; + +void +set_progname(const char *argv0) +{ + _progname = get_progname(argv0); +} + +const char * +progname(void) +{ + return _progname; +} + /* * load_config() * @@ -45,6 +60,7 @@ bool load_config(const char *config_file, t_configuration_options *options, char *argv0) { struct stat config; + /* Sanity checks */ /* @@ -101,7 +117,13 @@ load_config(const char *config_file, t_configuration_options *options, char *arg return parse_config(options); } - +/* + * Parse configuration file; if any errors are encountered, + * list them and exit. + * + * Ensure any default values set here are synced with repmgr.conf.sample + * and any other documentation. + */ bool parse_config(t_configuration_options *options) { @@ -115,6 +137,9 @@ parse_config(t_configuration_options *options) PQconninfoOption *conninfo_options; char *conninfo_errmsg = NULL; + /* Collate configuration file errors here for friendlier reporting */ + static ErrorList config_errors = { NULL, NULL }; + fp = fopen(config_file_path, "r"); /* @@ -177,7 +202,6 @@ parse_config(t_configuration_options *options) options->tablespace_mapping.tail = NULL; - /* Read next line */ while ((s = fgets(buff, sizeof buff, fp)) != NULL) { @@ -198,9 +222,9 @@ parse_config(t_configuration_options *options) if (strcmp(name, "cluster") == 0) strncpy(options->cluster_name, value, MAXLEN); else if (strcmp(name, "node") == 0) - options->node = repmgr_atoi(value, "node", NULL); + options->node = repmgr_atoi(value, "node", &config_errors); else if (strcmp(name, "upstream_node") == 0) - options->upstream_node = repmgr_atoi(value, "upstream_node", NULL); + options->upstream_node = repmgr_atoi(value, "upstream_node", &config_errors); else if (strcmp(name, "conninfo") == 0) strncpy(options->conninfo, value, MAXLEN); else if (strcmp(name, "rsync_options") == 0) @@ -232,7 +256,7 @@ parse_config(t_configuration_options *options) } } else if (strcmp(name, "priority") == 0) - options->priority = repmgr_atoi(value, "priority", NULL); + options->priority = repmgr_atoi(value, "priority", &config_errors); else if (strcmp(name, "node_name") == 0) strncpy(options->node_name, value, MAXLEN); else if (strcmp(name, "promote_command") == 0) @@ -240,16 +264,16 @@ parse_config(t_configuration_options *options) else if (strcmp(name, "follow_command") == 0) strncpy(options->follow_command, value, MAXLEN); else if (strcmp(name, "master_response_timeout") == 0) - options->master_response_timeout = repmgr_atoi(value, "master_response_timeout", NULL); + options->master_response_timeout = repmgr_atoi(value, "master_response_timeout", &config_errors); /* 'primary_response_timeout' as synonym for 'master_response_timeout' - * we'll switch terminology in a future release (3.1?) */ else if (strcmp(name, "primary_response_timeout") == 0) - options->master_response_timeout = repmgr_atoi(value, "primary_response_timeout", NULL); + options->master_response_timeout = repmgr_atoi(value, "primary_response_timeout", &config_errors); else if (strcmp(name, "reconnect_attempts") == 0) - options->reconnect_attempts = repmgr_atoi(value, "reconnect_attempts", NULL); + options->reconnect_attempts = repmgr_atoi(value, "reconnect_attempts", &config_errors); else if (strcmp(name, "reconnect_interval") == 0) - options->reconnect_interval = repmgr_atoi(value, "reconnect_interval", NULL); + options->reconnect_interval = repmgr_atoi(value, "reconnect_interval", &config_errors); else if (strcmp(name, "pg_bindir") == 0) strncpy(options->pg_bindir, value, MAXLEN); else if (strcmp(name, "pg_ctl_options") == 0) @@ -259,12 +283,12 @@ parse_config(t_configuration_options *options) else if (strcmp(name, "logfile") == 0) strncpy(options->logfile, value, MAXLEN); else if (strcmp(name, "monitor_interval_secs") == 0) - options->monitor_interval_secs = repmgr_atoi(value, "monitor_interval_secs", NULL); + options->monitor_interval_secs = repmgr_atoi(value, "monitor_interval_secs", &config_errors); else if (strcmp(name, "retry_promote_interval_secs") == 0) - options->retry_promote_interval_secs = repmgr_atoi(value, "retry_promote_interval_secs", NULL); + options->retry_promote_interval_secs = repmgr_atoi(value, "retry_promote_interval_secs", &config_errors); else if (strcmp(name, "use_replication_slots") == 0) /* XXX we should have a dedicated boolean argument format */ - options->use_replication_slots = repmgr_atoi(value, "use_replication_slots", NULL); + options->use_replication_slots = repmgr_atoi(value, "use_replication_slots", &config_errors); else if (strcmp(name, "event_notification_command") == 0) strncpy(options->event_notification_command, value, MAXLEN); else if (strcmp(name, "event_notifications") == 0) @@ -284,8 +308,13 @@ parse_config(t_configuration_options *options) * as currently e.g. an empty `node` value will be converted to '0'. */ if (known_parameter == true && !strlen(value)) { - log_err(_("no value provided for parameter '%s'\n"), name); - exit(ERR_BAD_CONFIG); + char error_message_buf[MAXLEN] = ""; + snprintf(error_message_buf, + MAXLEN, + _("no value provided for parameter \"%s\""), + name); + + error_list_append(&config_errors, error_message_buf); } } @@ -296,66 +325,51 @@ parse_config(t_configuration_options *options) /* The following checks are for the presence of the parameter */ if (*options->cluster_name == '\0') { - log_err(_("required parameter 'cluster' was not found\n")); - exit(ERR_BAD_CONFIG); + error_list_append(&config_errors, _("\"cluster\": parameter was not found\n")); } if (options->node == -1) { - log_err(_("required parameter 'node' was not found\n")); - exit(ERR_BAD_CONFIG); - } - - if (options->node <= 0) - { - log_err(_("'node' must be an integer greater than zero\n")); - exit(ERR_BAD_CONFIG); + error_list_append(&config_errors, _("\"node\": parameter was not found\n")); } if (*options->node_name == '\0') { - log_err(_("required parameter 'node_name' was not found\n")); - exit(ERR_BAD_CONFIG); + error_list_append(&config_errors, _("\"node_name\": parameter was not found\n")); } if (*options->conninfo == '\0') { - log_err(_("required parameter 'conninfo' was not found\n")); - exit(ERR_BAD_CONFIG); + error_list_append(&config_errors, _("\"conninfo\": parameter was not found\n")); } - - /* Sanity check the provided conninfo string - * - * NOTE: this verifies the string format and checks for valid options - * but does not sanity check values - */ - conninfo_options = PQconninfoParse(options->conninfo, &conninfo_errmsg); - if (conninfo_options == NULL) + else { - log_err(_("Parameter 'conninfo' is invalid: %s"), conninfo_errmsg); - exit(ERR_BAD_CONFIG); - } - PQconninfoFree(conninfo_options); - /* The following checks are for valid parameter values */ - if (options->master_response_timeout <= 0) + /* Sanity check the provided conninfo string + * + * NOTE: this verifies the string format and checks for valid options + * but does not sanity check values + */ + conninfo_options = PQconninfoParse(options->conninfo, &conninfo_errmsg); + if (conninfo_options == NULL) + { + char error_message_buf[MAXLEN] = ""; + snprintf(error_message_buf, + MAXLEN, + _("\"conninfo\": %s"), + conninfo_errmsg); + + error_list_append(&config_errors, error_message_buf); + } + + PQconninfoFree(conninfo_options); + } + + // exit_with_errors here + if (config_errors.head != NULL) { - log_err(_("'master_response_timeout' must be greater than zero\n")); - exit(ERR_BAD_CONFIG); + exit_with_errors(&config_errors); } - - if (options->reconnect_attempts < 0) - { - log_err(_("'reconnect_attempts' must be zero or greater\n")); - exit(ERR_BAD_CONFIG); - } - - if (options->reconnect_interval < 0) - { - log_err(_("'reconnect_interval' must be zero or greater\n")); - exit(ERR_BAD_CONFIG); - } - return true; } @@ -675,13 +689,42 @@ reload_config(t_configuration_options *orig_options) } +void +error_list_append(ErrorList *error_list, char *error_message) +{ + ErrorListCell *cell; + + cell = (ErrorListCell *) pg_malloc0(sizeof(ErrorListCell)); + + if (cell == NULL) + { + log_err(_("unable to allocate memory; terminating.\n")); + exit(ERR_BAD_CONFIG); + } + + cell->error_message = pg_malloc0(MAXLEN); + strncpy(cell->error_message, error_message, MAXLEN); + + if (error_list->tail) + { + error_list->tail->next = cell; + } + else + { + error_list->head = cell; + } + + error_list->tail = cell; +} + + /* * Convert provided string to an integer using strtol; * on error, if a callback is provided, pass the error message to that, * otherwise exit */ int -repmgr_atoi(const char *value, const char *config_item, void (*error_callback)(char *error_message)) +repmgr_atoi(const char *value, const char *config_item, ErrorList *error_list) { char *endptr; long longval = 0; @@ -695,7 +738,7 @@ repmgr_atoi(const char *value, const char *config_item, void (*error_callback)(c { snprintf(error_message_buf, MAXLEN, - _("No value provided for \"%s\""), + _("no value provided for \"%s\""), config_item); } else @@ -707,7 +750,7 @@ repmgr_atoi(const char *value, const char *config_item, void (*error_callback)(c { snprintf(error_message_buf, MAXLEN, - _("Invalid value provided for \"%s\": %s"), + _("\"%s\": invalid value (provided: \"%s\")"), config_item, value); } } @@ -717,20 +760,20 @@ repmgr_atoi(const char *value, const char *config_item, void (*error_callback)(c { snprintf(error_message_buf, MAXLEN, - _("\"%s\" cannot be a negative value (provided: %s)"), + _("\"%s\" must be zero or greater (provided: %s)"), config_item, value); } /* Error message buffer is set */ if (error_message_buf[0] != '\0') { - if (error_callback == NULL) + if (error_list == NULL) { log_err("%s\n", error_message_buf); exit(ERR_BAD_CONFIG); } - error_callback(error_message_buf); + error_list_append(error_list, error_message_buf); } return (int32) longval; @@ -868,3 +911,21 @@ parse_event_notifications_list(t_configuration_options *options, const char *arg } } } + + + +static void +exit_with_errors(ErrorList *config_errors) +{ + ErrorListCell *cell; + + log_err(_("%s: following errors were found in the configuration file.\n"), progname()); + + for (cell = config_errors->head; cell; cell = cell->next) + { + log_err("%s\n", cell->error_message); + } + + exit(ERR_BAD_CONFIG); +} + diff --git a/config.h b/config.h index 276c42fc..3c6d324c 100644 --- a/config.h +++ b/config.h @@ -82,14 +82,29 @@ typedef struct #define T_CONFIGURATION_OPTIONS_INITIALIZER { "", -1, NO_UPSTREAM_NODE, "", MANUAL_FAILOVER, -1, "", "", "", "", "", "", "", -1, -1, -1, "", "", "", "", 0, 0, 0, "", { NULL, NULL }, {NULL, NULL} } +typedef struct ErrorListCell +{ + struct ErrorListCell *next; + char *error_message; +} ErrorListCell; + +typedef struct ErrorList +{ + ErrorListCell *head; + ErrorListCell *tail; +} ErrorList; + +void set_progname(const char *argv0); +const char * progname(void); bool load_config(const char *config_file, t_configuration_options *options, char *argv0); bool reload_config(t_configuration_options *orig_options); bool parse_config(t_configuration_options *options); void parse_line(char *buff, char *name, char *value); char *trim(char *s); +void error_list_append(ErrorList *error_list, char *error_message); int repmgr_atoi(const char *s, const char *config_item, - void (*error_callback)(char *error_message)); + ErrorList *error_list); #endif diff --git a/repmgr.c b/repmgr.c index 0711a290..d0828ce8 100644 --- a/repmgr.c +++ b/repmgr.c @@ -101,12 +101,11 @@ static void do_cluster_show(void); static void do_cluster_cleanup(void); static void do_check_upstream_config(void); -static void error_list_append(char *error_message); static void exit_with_errors(void); -static void help(const char *progname); +static void help(void); /* Global variables */ -static const char *progname; +//static const char *progname; static const char *keywords[6]; static const char *values[6]; static bool config_file_required = true; @@ -127,7 +126,8 @@ static char *repmgr_slot_name_ptr = NULL; static char path_buf[MAXLEN] = ""; /* Collate command line errors here for friendlier reporting */ -static ErrorList cli_errors = { NULL, NULL }; +ErrorList cli_errors = { NULL, NULL }; + int main(int argc, char **argv) @@ -168,7 +168,8 @@ main(int argc, char **argv) bool config_file_parsed = false; char *ptr = NULL; - progname = get_progname(argv[0]); + set_progname(argv[0]); + /* Prevent getopt_long() from printing an error message */ opterr = 0; @@ -179,16 +180,16 @@ main(int argc, char **argv) /* * NOTE: some integer parameters (e.g. -p/--port) are stored internally * as strings. We use repmgr_atoi() to check these but discard the - * returned integer; the callback passed to repmgr_atoi() will append the - * error message to the list. + * returned integer; repmgr_atoi() will append the error message to the + * provided list. */ switch (c) { case '?': - help(progname); + help(); exit(SUCCESS); case 'V': - printf("%s %s (PostgreSQL %s)\n", progname, REPMGR_VERSION, PG_VERSION); + printf("%s %s (PostgreSQL %s)\n", progname(), REPMGR_VERSION, PG_VERSION); exit(SUCCESS); case 'd': strncpy(runtime_options.dbname, optarg, MAXLEN); @@ -197,7 +198,7 @@ main(int argc, char **argv) strncpy(runtime_options.host, optarg, MAXLEN); break; case 'p': - repmgr_atoi(optarg, "-p/--port", error_list_append); + repmgr_atoi(optarg, "-p/--port", &cli_errors); strncpy(runtime_options.masterport, optarg, MAXLEN); @@ -213,7 +214,7 @@ main(int argc, char **argv) break; case 'l': /* -l/--local-port is deprecated */ - repmgr_atoi(optarg, "-l/--local-port", error_list_append); + repmgr_atoi(optarg, "-l/--local-port", &cli_errors); strncpy(runtime_options.localport, optarg, MAXLEN); @@ -225,14 +226,14 @@ main(int argc, char **argv) strncpy(runtime_options.remote_user, optarg, MAXLEN); break; case 'w': - repmgr_atoi(optarg, "-w/--wal-keep-segments", error_list_append); + repmgr_atoi(optarg, "-w/--wal-keep-segments", &cli_errors); strncpy(runtime_options.wal_keep_segments, optarg, MAXLEN); wal_keep_segments_used = true; break; case 'k': - runtime_options.keep_history = repmgr_atoi(optarg, "-k/--keep-history", error_list_append); + runtime_options.keep_history = repmgr_atoi(optarg, "-k/--keep-history", &cli_errors); break; case 'F': runtime_options.force = true; @@ -266,7 +267,7 @@ main(int argc, char **argv) if (targ < 1) { - error_list_append(_("Invalid value provided for '-r/--recovery-min-apply-delay'")); + error_list_append(&cli_errors, _("Invalid value provided for '-r/--recovery-min-apply-delay'")); break; } if (ptr && *ptr) @@ -275,7 +276,7 @@ main(int argc, char **argv) strcmp(ptr, "min") != 0 && strcmp(ptr, "h") != 0 && strcmp(ptr, "d") != 0) { - error_list_append(_("Value provided for '-r/--recovery-min-apply-delay' must be one of ms/s/min/h/d")); + error_list_append(&cli_errors, _("Value provided for '-r/--recovery-min-apply-delay' must be one of ms/s/min/h/d")); break; } } @@ -291,7 +292,7 @@ main(int argc, char **argv) initPQExpBuffer(&unknown_option); appendPQExpBuffer(&unknown_option, _("Unknown option '%s'"), argv[optind - 1]); - error_list_append(unknown_option.data); + error_list_append(&cli_errors, unknown_option.data); } } } @@ -333,7 +334,7 @@ main(int argc, char **argv) PQExpBufferData unknown_mode; initPQExpBuffer(&unknown_mode); appendPQExpBuffer(&unknown_mode, _("Unknown server mode '%s'"), server_mode); - error_list_append(unknown_mode.data); + error_list_append(&cli_errors, unknown_mode.data); } } @@ -376,14 +377,14 @@ main(int argc, char **argv) if (action == NO_ACTION) { if (server_cmd == NULL) { - error_list_append("No server command provided"); + error_list_append(&cli_errors, "No server command provided"); } else { PQExpBufferData unknown_action; initPQExpBuffer(&unknown_action); appendPQExpBuffer(&unknown_action, _("Unknown server command '%s'"), server_cmd); - error_list_append(unknown_action.data); + error_list_append(&cli_errors, unknown_action.data); } } @@ -394,7 +395,7 @@ main(int argc, char **argv) { if (runtime_options.host[0]) { - error_list_append(_("Conflicting parameters: you can't use -h while providing a node separately.")); + error_list_append(&cli_errors, _("Conflicting parameters: you can't use -h while providing a node separately.")); } else { @@ -408,7 +409,7 @@ main(int argc, char **argv) PQExpBufferData too_many_args; initPQExpBuffer(&too_many_args); appendPQExpBuffer(&too_many_args, _("too many command-line arguments (first extra is \"%s\")"), argv[optind]); - error_list_append(too_many_args.data); + error_list_append(&cli_errors, too_many_args.data); } check_parameters_for_action(action); @@ -483,7 +484,7 @@ main(int argc, char **argv) keywords[3] = "dbname"; values[3] = runtime_options.dbname; keywords[4] = "application_name"; - values[4] = (char *) progname; + values[4] = (char *) progname(); keywords[5] = NULL; values[5] = NULL; @@ -494,7 +495,7 @@ main(int argc, char **argv) * logging level might be specified at, but it often requires detailed * logging to troubleshoot problems. */ - logger_init(&options, progname, options.loglevel, options.logfacility); + logger_init(&options, progname(), options.loglevel, options.logfacility); if (runtime_options.verbose) logger_min_verbose(LOG_INFO); @@ -2197,7 +2198,7 @@ do_witness_create(void) exit(ERR_BAD_CONFIG); } - xsnprintf(buf, sizeof(buf), "\n#Configuration added by %s\n", progname); + xsnprintf(buf, sizeof(buf), "\n#Configuration added by %s\n", progname()); fputs(buf, pg_conf); @@ -2488,15 +2489,15 @@ do_witness_create(void) static void -help(const char *progname) +help(void) { - printf(_("%s: replication management tool for PostgreSQL\n"), progname); + printf(_("%s: replication management tool for PostgreSQL\n"), progname()); printf(_("\n")); printf(_("Usage:\n")); - printf(_(" %s [OPTIONS] master {register}\n"), progname); + printf(_(" %s [OPTIONS] master {register}\n"), progname()); printf(_(" %s [OPTIONS] standby {register|unregister|clone|promote|follow}\n"), - progname); - printf(_(" %s [OPTIONS] cluster {show|cleanup}\n"), progname); + progname()); + printf(_(" %s [OPTIONS] cluster {show|cleanup}\n"), progname()); printf(_("\n")); printf(_("General options:\n")); printf(_(" -?, --help show this help, then exit\n")); @@ -2538,7 +2539,7 @@ help(const char *progname) printf(_(" -S, --superuser=USERNAME (witness server) superuser username for witness database\n" \ " (default: postgres)\n")); printf(_("\n")); - printf(_("%s performs the following node management tasks:\n"), progname); + printf(_("%s performs the following node management tasks:\n"), progname()); printf(_("\n")); printf(_("COMMANDS:\n")); printf(_(" master register - registers the master in a cluster\n")); @@ -2855,11 +2856,11 @@ check_parameters_for_action(const int action) if (runtime_options.host[0] || runtime_options.masterport[0] || runtime_options.username[0] || runtime_options.dbname[0]) { - error_list_append(_("master connection parameters not required when executing MASTER REGISTER")); + error_list_append(&cli_errors, _("master connection parameters not required when executing MASTER REGISTER")); } if (runtime_options.dest_dir[0]) { - error_list_append(_("destination directory not required when executing MASTER REGISTER")); + error_list_append(&cli_errors, _("destination directory not required when executing MASTER REGISTER")); } break; case STANDBY_REGISTER: @@ -2872,11 +2873,11 @@ check_parameters_for_action(const int action) if (runtime_options.host[0] || runtime_options.masterport[0] || runtime_options.username[0] || runtime_options.dbname[0]) { - error_list_append(_("master connection parameters not required when executing STANDBY REGISTER")); + error_list_append(&cli_errors, _("master connection parameters not required when executing STANDBY REGISTER")); } if (runtime_options.dest_dir[0]) { - error_list_append(_("destination directory not required when executing STANDBY REGISTER")); + error_list_append(&cli_errors, _("destination directory not required when executing STANDBY REGISTER")); } break; case STANDBY_UNREGISTER: @@ -2889,11 +2890,11 @@ check_parameters_for_action(const int action) if (runtime_options.host[0] || runtime_options.masterport[0] || runtime_options.username[0] || runtime_options.dbname[0]) { - error_list_append(_("master connection parameters not required when executing STANDBY UNREGISTER")); + error_list_append(&cli_errors, _("master connection parameters not required when executing STANDBY UNREGISTER")); } if (runtime_options.dest_dir[0]) { - error_list_append(_("destination directory not required when executing STANDBY UNREGISTER")); + error_list_append(&cli_errors, _("destination directory not required when executing STANDBY UNREGISTER")); } break; case STANDBY_PROMOTE: @@ -2907,11 +2908,11 @@ check_parameters_for_action(const int action) if (runtime_options.host[0] || runtime_options.masterport[0] || runtime_options.username[0] || runtime_options.dbname[0]) { - error_list_append(_("master connection parameters not required when executing STANDBY PROMOTE")); + error_list_append(&cli_errors, _("master connection parameters not required when executing STANDBY PROMOTE")); } if (runtime_options.dest_dir[0]) { - error_list_append(_("destination directory not required when executing STANDBY PROMOTE")); + error_list_append(&cli_errors, _("destination directory not required when executing STANDBY PROMOTE")); } break; case STANDBY_FOLLOW: @@ -2925,11 +2926,11 @@ check_parameters_for_action(const int action) if (runtime_options.host[0] || runtime_options.masterport[0] || runtime_options.username[0] || runtime_options.dbname[0]) { - error_list_append(_("master connection parameters not required when executing STANDBY FOLLOW")); + error_list_append(&cli_errors, _("master connection parameters not required when executing STANDBY FOLLOW")); } if (runtime_options.dest_dir[0]) { - error_list_append(_("destination directory not required when executing STANDBY FOLLOW")); + error_list_append(&cli_errors, _("destination directory not required when executing STANDBY FOLLOW")); } break; case STANDBY_CLONE: @@ -2942,17 +2943,17 @@ check_parameters_for_action(const int action) if (strcmp(runtime_options.host, "") == 0) { - error_list_append(_("master hostname (-h/--host) required when executing STANDBY CLONE")); + error_list_append(&cli_errors, _("master hostname (-h/--host) required when executing STANDBY CLONE")); } if (strcmp(runtime_options.dbname, "") == 0) { - error_list_append(_("master database name (-d/--dbname) required when executing STANDBY CLONE")); + error_list_append(&cli_errors, _("master database name (-d/--dbname) required when executing STANDBY CLONE")); } if (strcmp(runtime_options.username, "") == 0) { - error_list_append(_("master database username (-U/--username) required when executing STANDBY CLONE")); + error_list_append(&cli_errors, _("master database username (-U/--username) required when executing STANDBY CLONE")); } config_file_required = false; @@ -2972,22 +2973,22 @@ check_parameters_for_action(const int action) { if (runtime_options.rsync_only) { - error_list_append(_("--rsync-only can only be used when executing STANDBY CLONE")); + error_list_append(&cli_errors, _("--rsync-only can only be used when executing STANDBY CLONE")); } if (runtime_options.fast_checkpoint) { - error_list_append(_("--fast-checkpoint can only be used when executing STANDBY CLONE")); + error_list_append(&cli_errors, _("--fast-checkpoint can only be used when executing STANDBY CLONE")); } if (runtime_options.ignore_external_config_files) { - error_list_append(_("--ignore-external-config-files can only be used when executing STANDBY CLONE")); + error_list_append(&cli_errors, _("--ignore-external-config-files can only be used when executing STANDBY CLONE")); } if (*runtime_options.recovery_min_apply_delay) { - error_list_append(_("--recovery-min-apply-delay can only be used when executing STANDBY CLONE")); + error_list_append(&cli_errors, _("--recovery-min-apply-delay can only be used when executing STANDBY CLONE")); } } @@ -3333,7 +3334,7 @@ check_server_version(PGconn *conn, char *server_type, bool exit_on_error, char * { if (server_version_num > 0) log_err(_("%s requires %s to be PostgreSQL %s or later\n"), - progname, + progname(), server_type, MIN_SUPPORTED_VERSION ); @@ -3709,48 +3710,20 @@ make_pg_path(char *file) } -static void -error_list_append(char *error_message) -{ - ErrorListCell *cell; - - cell = (ErrorListCell *) pg_malloc0(sizeof(ErrorListCell)); - - if (cell == NULL) - { - log_err(_("unable to allocate memory; terminating.\n")); - exit(ERR_BAD_CONFIG); - } - - cell->error_message = pg_malloc0(MAXLEN); - strncpy(cell->error_message, error_message, MAXLEN); - - if (cli_errors.tail) - { - cli_errors.tail->next = cell; - } - else - { - cli_errors.head = cell; - } - - cli_errors.tail = cell; -} - - static void exit_with_errors(void) { ErrorListCell *cell; - fprintf(stderr, _("%s: Replication manager \n"), progname); + fprintf(stderr, _("%s: following command line errors were encountered.\n"), progname()); for (cell = cli_errors.head; cell; cell = cell->next) { - fprintf(stderr, "[ERROR] %s\n", cell->error_message); + fprintf(stderr, "%s\n", cell->error_message); } - fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname); + fprintf(stderr, _("Try \"%s --help\" for more information.\n"), progname()); exit(ERR_BAD_CONFIG); } + diff --git a/repmgr.h b/repmgr.h index 5fa9e976..0ed86b42 100644 --- a/repmgr.h +++ b/repmgr.h @@ -95,16 +95,5 @@ typedef struct extern char repmgr_schema[MAXLEN]; -typedef struct ErrorListCell -{ - struct ErrorListCell *next; - char *error_message; -} ErrorListCell; - -typedef struct ErrorList -{ - ErrorListCell *head; - ErrorListCell *tail; -} ErrorList; #endif diff --git a/repmgrd.c b/repmgrd.c index 00a7083f..f4cf46c0 100644 --- a/repmgrd.c +++ b/repmgrd.c @@ -68,8 +68,6 @@ t_configuration_options master_options; PGconn *master_conn = NULL; -const char *progname; - char *config_file = DEFAULT_CONFIG_FILE; bool verbose = false; bool monitoring_history = false; @@ -81,7 +79,7 @@ char *pid_file = NULL; t_configuration_options config = T_CONFIGURATION_OPTIONS_INITIALIZER; -static void help(const char *progname); +static void help(void); static void usage(void); static void check_cluster_configuration(PGconn *conn); static void check_node_configuration(void); @@ -158,7 +156,8 @@ main(int argc, char **argv) FILE *fd; int server_version_num = 0; - progname = get_progname(argv[0]); + + set_progname(argv[0]); while ((c = getopt_long(argc, argv, "?Vf:v:mdp:", long_options, &optindex)) != -1) { @@ -180,10 +179,10 @@ main(int argc, char **argv) pid_file = optarg; break; case '?': - help(progname); + help(); exit(SUCCESS); case 'V': - printf("%s %s (PostgreSQL %s)\n", progname, REPMGR_VERSION, PG_VERSION); + printf("%s %s (PostgreSQL %s)\n", progname(), REPMGR_VERSION, PG_VERSION); exit(SUCCESS); default: usage(); @@ -230,7 +229,7 @@ main(int argc, char **argv) strerror(errno)); } - logger_init(&local_options, progname, local_options.loglevel, + logger_init(&local_options, progname(), local_options.loglevel, local_options.logfacility); if (verbose) logger_min_verbose(LOG_INFO); @@ -264,7 +263,7 @@ main(int argc, char **argv) if (server_version_num > 0) { log_err(_("%s requires PostgreSQL %s or later\n"), - progname, + progname(), MIN_SUPPORTED_VERSION) ; } else @@ -2073,18 +2072,18 @@ lsn_to_xlogrecptr(char *lsn, bool *format_ok) void usage(void) { - log_err(_("%s: Replicator manager daemon \n"), progname); - log_err(_("Try \"%s --help\" for more information.\n"), progname); + log_err(_("%s: Replicator manager daemon \n"), progname()); + log_err(_("Try \"%s --help\" for more information.\n"), progname()); } void -help(const char *progname) +help(void) { - printf(_("%s: replication management daemon for PostgreSQL\n"), progname); + printf(_("%s: replication management daemon for PostgreSQL\n"), progname()); printf(_("\n")); printf(_("Usage:\n")); - printf(_(" %s [OPTIONS]\n"), progname); + printf(_(" %s [OPTIONS]\n"), progname()); printf(_("\n")); printf(_("Options:\n")); printf(_(" -?, --help show this help, then exit\n")); @@ -2095,7 +2094,7 @@ help(const char *progname) printf(_(" -d, --daemonize detach process from foreground\n")); printf(_(" -p, --pid-file=PATH write a PID file\n")); printf(_("\n")); - printf(_("%s monitors a cluster of servers and optionally performs failover.\n"), progname); + printf(_("%s monitors a cluster of servers and optionally performs failover.\n"), progname()); } @@ -2133,7 +2132,7 @@ terminate(int retval) unlink(pid_file); } - log_info(_("%s terminating...\n"), progname); + log_info(_("%s terminating...\n"), progname()); exit(retval); }