Skip to content
Snippets Groups Projects
Commit 57386dcb authored by Corey Farrell's avatar Corey Farrell
Browse files

Allow command-line options to override asterisk.conf.

Previous versions of Asterisk processed command-line options before
processing asterisk.conf.  This meant that if an option was set in
asterisk.conf, it could not be overridden with the equivelent command
line option.  This change causes Asterisk to process the command-line
twice.  First it processes options that are needed to load asterisk.conf,
then it processes the remaining options after the config is read.

This changes the function of -X slightly.  Previously using -X without
disabling execincludes in asterisk.conf caused #exec to be usable in any
config.  Now -X only enables #exec for the load of asterisk.conf, if it
is wanted in the rest of the system it must be enabled with execincludes
in asterisk.conf.  Updated 'asterisk -h' and 'man asterisk' to reflect
the limited function of -X.

ASTERISK-25042 #close
Reported by: Corey Farrell

Change-Id: I1450d45c15b4467274b871914d893ed4f6564cd7
parent cc853dcf
No related branches found
No related tags found
No related merge requests found
...@@ -104,6 +104,12 @@ Core ...@@ -104,6 +104,12 @@ Core
for DNS functionality. Modules that use this functionality will require that for DNS functionality. Modules that use this functionality will require that
a DNS resolver module is loaded and available. a DNS resolver module is loaded and available.
* Modified processing of command-line options to first parse only what
is necessary to read asterisk.conf. Once asterisk.conf is fully loaded,
the remaining options are processed. The -X option now applies to
asterisk.conf only. To enable #exec for other config files you must
set execincludes=yes in asterisk.conf. Any other option set on the
command-line will now override the equivalent setting from asterisk.conf.
Functions Functions
------------------ ------------------
......
...@@ -36,6 +36,13 @@ Core: ...@@ -36,6 +36,13 @@ Core:
The setting can be overridden in asterisk.conf by setting refdebug in The setting can be overridden in asterisk.conf by setting refdebug in
the options category. No recompile is required to enable/disable it. the options category. No recompile is required to enable/disable it.
- Modified processing of command-line options to first parse only what
is necessary to read asterisk.conf. Once asterisk.conf is fully loaded,
the remaining options are processed. The -X option now applies to
asterisk.conf only. To enable #exec for other config files you must
set execincludes=yes in asterisk.conf. Any other option set on the
command-line will now override the equivalent setting from asterisk.conf.
AMI: AMI:
- The 'ModuleCheck' Action's Version key will no longer show the module - The 'ModuleCheck' Action's Version key will no longer show the module
version. The value will always be blank. version. The value will always be blank.
......
...@@ -232,9 +232,8 @@ then terminating when the command execution completes. Implies ...@@ -232,9 +232,8 @@ then terminating when the command execution completes. Implies
supplied. supplied.
.TP .TP
\-X \-X
Enables executing of includes via \fB#exec\fR directive. Enables executing of includes via \fB#exec\fR directive inside
This can be useful if You want to do \fB#exec\fR inside \*(T<\fIasterisk.conf\fR\*(T>.
\*(T<\fIasterisk.conf\fR\*(T>
.SH EXAMPLES .SH EXAMPLES
\fBasterisk\fR - Begin Asterisk as a daemon \fBasterisk\fR - Begin Asterisk as a daemon
.PP .PP
......
...@@ -66,8 +66,6 @@ enum ast_option_flags { ...@@ -66,8 +66,6 @@ enum ast_option_flags {
AST_OPT_FLAG_CACHE_RECORD_FILES = (1 << 13), AST_OPT_FLAG_CACHE_RECORD_FILES = (1 << 13),
/*! Display timestamp in CLI verbose output */ /*! Display timestamp in CLI verbose output */
AST_OPT_FLAG_TIMESTAMP = (1 << 14), AST_OPT_FLAG_TIMESTAMP = (1 << 14),
/*! Override config */
AST_OPT_FLAG_OVERRIDE_CONFIG = (1 << 15),
/*! Reconnect */ /*! Reconnect */
AST_OPT_FLAG_RECONNECT = (1 << 16), AST_OPT_FLAG_RECONNECT = (1 << 16),
/*! Transmit Silence during Record() and DTMF Generation */ /*! Transmit Silence during Record() and DTMF Generation */
...@@ -119,7 +117,6 @@ enum ast_option_flags { ...@@ -119,7 +117,6 @@ enum ast_option_flags {
#define ast_opt_dump_core ast_test_flag(&ast_options, AST_OPT_FLAG_DUMP_CORE) #define ast_opt_dump_core ast_test_flag(&ast_options, AST_OPT_FLAG_DUMP_CORE)
#define ast_opt_cache_record_files ast_test_flag(&ast_options, AST_OPT_FLAG_CACHE_RECORD_FILES) #define ast_opt_cache_record_files ast_test_flag(&ast_options, AST_OPT_FLAG_CACHE_RECORD_FILES)
#define ast_opt_timestamp ast_test_flag(&ast_options, AST_OPT_FLAG_TIMESTAMP) #define ast_opt_timestamp ast_test_flag(&ast_options, AST_OPT_FLAG_TIMESTAMP)
#define ast_opt_override_config ast_test_flag(&ast_options, AST_OPT_FLAG_OVERRIDE_CONFIG)
#define ast_opt_reconnect ast_test_flag(&ast_options, AST_OPT_FLAG_RECONNECT) #define ast_opt_reconnect ast_test_flag(&ast_options, AST_OPT_FLAG_RECONNECT)
#define ast_opt_transmit_silence ast_test_flag(&ast_options, AST_OPT_FLAG_TRANSMIT_SILENCE) #define ast_opt_transmit_silence ast_test_flag(&ast_options, AST_OPT_FLAG_TRANSMIT_SILENCE)
#define ast_opt_dont_warn ast_test_flag(&ast_options, AST_OPT_FLAG_DONT_WARN) #define ast_opt_dont_warn ast_test_flag(&ast_options, AST_OPT_FLAG_DONT_WARN)
......
...@@ -3352,7 +3352,7 @@ static int show_cli_help(void) ...@@ -3352,7 +3352,7 @@ static int show_cli_help(void)
printf(" -G <group> Run as a group other than the caller\n"); printf(" -G <group> Run as a group other than the caller\n");
printf(" -U <user> Run as a user other than the caller\n"); printf(" -U <user> Run as a user other than the caller\n");
printf(" -c Provide console CLI\n"); printf(" -c Provide console CLI\n");
printf(" -d Enable extra debugging\n"); printf(" -d Increase debugging (multiple d's = more debugging)\n");
#if HAVE_WORKING_FORK #if HAVE_WORKING_FORK
printf(" -f Do not fork\n"); printf(" -f Do not fork\n");
printf(" -F Always fork\n"); printf(" -F Always fork\n");
...@@ -3375,7 +3375,7 @@ static int show_cli_help(void) ...@@ -3375,7 +3375,7 @@ static int show_cli_help(void)
printf(" of output to the CLI\n"); printf(" of output to the CLI\n");
printf(" -v Increase verbosity (multiple v's = more verbose)\n"); printf(" -v Increase verbosity (multiple v's = more verbose)\n");
printf(" -x <cmd> Execute command <cmd> (implies -r)\n"); printf(" -x <cmd> Execute command <cmd> (implies -r)\n");
printf(" -X Execute includes by default (allows #exec in asterisk.conf)\n"); printf(" -X Enable use of #exec in asterisk.conf\n");
printf(" -W Adjust terminal colors to compensate for a light background\n"); printf(" -W Adjust terminal colors to compensate for a light background\n");
printf("\n"); printf("\n");
return 0; return 0;
...@@ -3385,7 +3385,6 @@ static void ast_readconfig(void) ...@@ -3385,7 +3385,6 @@ static void ast_readconfig(void)
{ {
struct ast_config *cfg; struct ast_config *cfg;
struct ast_variable *v; struct ast_variable *v;
char *config = DEFAULT_CONFIG_FILE;
char hostname[MAXHOSTNAMELEN] = ""; char hostname[MAXHOSTNAMELEN] = "";
struct ast_flags config_flags = { CONFIG_FLAG_NOREALTIME }; struct ast_flags config_flags = { CONFIG_FLAG_NOREALTIME };
struct { struct {
...@@ -3394,19 +3393,12 @@ static void ast_readconfig(void) ...@@ -3394,19 +3393,12 @@ static void ast_readconfig(void)
} found = { 0, 0 }; } found = { 0, 0 };
/* Default to false for security */ /* Default to false for security */
int live_dangerously = 0; int live_dangerously = 0;
int option_debug_new = 0;
int option_verbose_new = 0;
/* Set default value */ /* Set default value */
option_dtmfminduration = AST_MIN_DTMF_DURATION; option_dtmfminduration = AST_MIN_DTMF_DURATION;
if (ast_opt_override_config) {
cfg = ast_config_load2(ast_config_AST_CONFIG_FILE, "" /* core, can't reload */, config_flags);
if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEUNCHANGED || cfg == CONFIG_STATUS_FILEINVALID) {
fprintf(stderr, "Unable to open specified master config file '%s', using built-in defaults\n", ast_config_AST_CONFIG_FILE);
}
} else {
cfg = ast_config_load2(config, "" /* core, can't reload */, config_flags);
}
/* init with buildtime config */ /* init with buildtime config */
ast_copy_string(cfg_paths.config_dir, DEFAULT_CONFIG_DIR, sizeof(cfg_paths.config_dir)); ast_copy_string(cfg_paths.config_dir, DEFAULT_CONFIG_DIR, sizeof(cfg_paths.config_dir));
ast_copy_string(cfg_paths.spool_dir, DEFAULT_SPOOL_DIR, sizeof(cfg_paths.spool_dir)); ast_copy_string(cfg_paths.spool_dir, DEFAULT_SPOOL_DIR, sizeof(cfg_paths.spool_dir));
...@@ -3432,8 +3424,15 @@ static void ast_readconfig(void) ...@@ -3432,8 +3424,15 @@ static void ast_readconfig(void)
ast_set_default_eid(&ast_eid_default); ast_set_default_eid(&ast_eid_default);
cfg = ast_config_load2(ast_config_AST_CONFIG_FILE, "" /* core, can't reload */, config_flags);
/* If AST_OPT_FLAG_EXEC_INCLUDES was previously enabled with -X turn it off now.
* Using #exec from other configs requires that it be enabled from asterisk.conf. */
ast_clear_flag(&ast_options, AST_OPT_FLAG_EXEC_INCLUDES);
/* no asterisk.conf? no problem, use buildtime config! */ /* no asterisk.conf? no problem, use buildtime config! */
if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEUNCHANGED || cfg == CONFIG_STATUS_FILEINVALID) { if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEUNCHANGED || cfg == CONFIG_STATUS_FILEINVALID) {
fprintf(stderr, "Unable to open specified master config file '%s', using built-in defaults\n", ast_config_AST_CONFIG_FILE);
return; return;
} }
...@@ -3487,7 +3486,7 @@ static void ast_readconfig(void) ...@@ -3487,7 +3486,7 @@ static void ast_readconfig(void)
for (v = ast_variable_browse(cfg, "options"); v; v = v->next) { for (v = ast_variable_browse(cfg, "options"); v; v = v->next) {
/* verbose level (-v at startup) */ /* verbose level (-v at startup) */
if (!strcasecmp(v->name, "verbose")) { if (!strcasecmp(v->name, "verbose")) {
option_verbose = atoi(v->value); option_verbose_new = atoi(v->value);
/* whether or not to force timestamping in CLI verbose output. (-T at startup) */ /* whether or not to force timestamping in CLI verbose output. (-T at startup) */
} else if (!strcasecmp(v->name, "timestamp")) { } else if (!strcasecmp(v->name, "timestamp")) {
ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_TIMESTAMP); ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_TIMESTAMP);
...@@ -3496,9 +3495,9 @@ static void ast_readconfig(void) ...@@ -3496,9 +3495,9 @@ static void ast_readconfig(void)
ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_EXEC_INCLUDES); ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_EXEC_INCLUDES);
/* debug level (-d at startup) */ /* debug level (-d at startup) */
} else if (!strcasecmp(v->name, "debug")) { } else if (!strcasecmp(v->name, "debug")) {
option_debug = 0; option_debug_new = 0;
if (sscanf(v->value, "%30d", &option_debug) != 1) { if (sscanf(v->value, "%30d", &option_debug_new) != 1) {
option_debug = ast_true(v->value) ? 1 : 0; option_debug_new = ast_true(v->value) ? 1 : 0;
} }
} else if (!strcasecmp(v->name, "refdebug")) { } else if (!strcasecmp(v->name, "refdebug")) {
ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_REF_DEBUG); ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_REF_DEBUG);
...@@ -3647,6 +3646,9 @@ static void ast_readconfig(void) ...@@ -3647,6 +3646,9 @@ static void ast_readconfig(void)
pbx_live_dangerously(live_dangerously); pbx_live_dangerously(live_dangerously);
} }
option_debug += option_debug_new;
option_verbose += option_verbose_new;
ast_config_destroy(cfg); ast_config_destroy(cfg);
} }
...@@ -3787,9 +3789,9 @@ int main(int argc, char *argv[]) ...@@ -3787,9 +3789,9 @@ int main(int argc, char *argv[])
int isroot = 1, rundir_exists = 0; int isroot = 1, rundir_exists = 0;
char *buf; char *buf;
const char *runuser = NULL, *rungroup = NULL; const char *runuser = NULL, *rungroup = NULL;
char *remotesock = NULL;
int moduleresult; /*!< Result from the module load subsystem */ int moduleresult; /*!< Result from the module load subsystem */
struct rlimit l; struct rlimit l;
static const char *getopt_settings = "BC:cde:FfG:ghIiL:M:mnpqRrs:TtU:VvWXx:";
/* Remember original args for restart */ /* Remember original args for restart */
if (argc > ARRAY_LEN(_argv) - 1) { if (argc > ARRAY_LEN(_argv) - 1) {
...@@ -3813,11 +3815,57 @@ int main(int argc, char *argv[]) ...@@ -3813,11 +3815,57 @@ int main(int argc, char *argv[])
if (getenv("HOME")) if (getenv("HOME"))
snprintf(filename, sizeof(filename), "%s/.asterisk_history", getenv("HOME")); snprintf(filename, sizeof(filename), "%s/.asterisk_history", getenv("HOME"));
/* Set config file to default before checking arguments for override. */
ast_copy_string(cfg_paths.config_file, DEFAULT_CONFIG_FILE, sizeof(cfg_paths.config_file));
/* Process command-line options that effect asterisk.conf load. */
while ((c = getopt(argc, argv, getopt_settings)) != -1) {
switch (c) {
case 'X':
ast_set_flag(&ast_options, AST_OPT_FLAG_EXEC_INCLUDES);
break;
case 'C':
ast_copy_string(cfg_paths.config_file, optarg, sizeof(cfg_paths.config_file));
break;
case 'd':
option_debug++;
break;
case 'h':
show_cli_help();
exit(0);
case 'R':
case 'r':
case 'x':
/* ast_opt_remote is checked during config load. This is only part of what
* these options do, see the second loop for the rest of the actions. */
ast_set_flag(&ast_options, AST_OPT_FLAG_REMOTE);
break;
case 'V':
show_version();
exit(0);
case 'v':
option_verbose++;
break;
case '?':
exit(1);
}
}
/* Initialize env so it is available if #exec is used in asterisk.conf. */
env_init();
ast_readconfig();
/* Update env to include any systemname that was set. */
env_init();
/*! \brief Check for options /*! \brief Check for options
* *
* \todo Document these options * \todo Document these options
*/ */
while ((c = getopt(argc, argv, "BC:cde:FfG:ghIiL:M:mnpqRrs:TtU:VvWXx:")) != -1) { optind = 0;
while ((c = getopt(argc, argv, getopt_settings)) != -1) {
/*!\note Please keep the ordering here to alphabetical, capital letters /*!\note Please keep the ordering here to alphabetical, capital letters
* first. This will make it easier in the future to select unused * first. This will make it easier in the future to select unused
* option flags for new features. */ * option flags for new features. */
...@@ -3827,18 +3875,16 @@ int main(int argc, char *argv[]) ...@@ -3827,18 +3875,16 @@ int main(int argc, char *argv[])
ast_clear_flag(&ast_options, AST_OPT_FLAG_LIGHT_BACKGROUND); ast_clear_flag(&ast_options, AST_OPT_FLAG_LIGHT_BACKGROUND);
break; break;
case 'X': case 'X':
ast_set_flag(&ast_options, AST_OPT_FLAG_EXEC_INCLUDES); /* The command-line -X option enables #exec for asterisk.conf only. */
break; break;
case 'C': case 'C':
ast_copy_string(cfg_paths.config_file, optarg, sizeof(cfg_paths.config_file)); /* already processed. */
ast_set_flag(&ast_options, AST_OPT_FLAG_OVERRIDE_CONFIG);
break; break;
case 'c': case 'c':
ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK | AST_OPT_FLAG_CONSOLE); ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK | AST_OPT_FLAG_CONSOLE);
break; break;
case 'd': case 'd':
option_debug++; /* already processed. */
ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK);
break; break;
#if defined(HAVE_SYSINFO) #if defined(HAVE_SYSINFO)
case 'e': case 'e':
...@@ -3862,8 +3908,8 @@ int main(int argc, char *argv[]) ...@@ -3862,8 +3908,8 @@ int main(int argc, char *argv[])
ast_set_flag(&ast_options, AST_OPT_FLAG_DUMP_CORE); ast_set_flag(&ast_options, AST_OPT_FLAG_DUMP_CORE);
break; break;
case 'h': case 'h':
show_cli_help(); /* already processed. */
exit(0); break;
case 'I': case 'I':
fprintf(stderr, fprintf(stderr,
"NOTICE: The -I option is no longer needed.\n" "NOTICE: The -I option is no longer needed.\n"
...@@ -3901,7 +3947,9 @@ int main(int argc, char *argv[]) ...@@ -3901,7 +3947,9 @@ int main(int argc, char *argv[])
ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK | AST_OPT_FLAG_REMOTE); ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK | AST_OPT_FLAG_REMOTE);
break; break;
case 's': case 's':
remotesock = ast_strdupa(optarg); if (ast_opt_remote) {
ast_copy_string((char *) cfg_paths.socket_path, optarg, sizeof(cfg_paths.socket_path));
}
break; break;
case 'T': case 'T':
ast_set_flag(&ast_options, AST_OPT_FLAG_TIMESTAMP); ast_set_flag(&ast_options, AST_OPT_FLAG_TIMESTAMP);
...@@ -3913,11 +3961,8 @@ int main(int argc, char *argv[]) ...@@ -3913,11 +3961,8 @@ int main(int argc, char *argv[])
runuser = ast_strdupa(optarg); runuser = ast_strdupa(optarg);
break; break;
case 'V': case 'V':
show_version();
exit(0);
case 'v': case 'v':
option_verbose++; /* already processed. */
ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK);
break; break;
case 'W': /* White background */ case 'W': /* White background */
ast_set_flag(&ast_options, AST_OPT_FLAG_LIGHT_BACKGROUND); ast_set_flag(&ast_options, AST_OPT_FLAG_LIGHT_BACKGROUND);
...@@ -3931,7 +3976,8 @@ int main(int argc, char *argv[]) ...@@ -3931,7 +3976,8 @@ int main(int argc, char *argv[])
xarg = ast_strdupa(optarg); xarg = ast_strdupa(optarg);
break; break;
case '?': case '?':
exit(1); /* already processed. */
break;
} }
} }
...@@ -3945,12 +3991,6 @@ int main(int argc, char *argv[]) ...@@ -3945,12 +3991,6 @@ int main(int argc, char *argv[])
} }
} }
ast_readconfig();
env_init();
if (ast_opt_remote && remotesock != NULL)
ast_copy_string((char *) cfg_paths.socket_path, remotesock, sizeof(cfg_paths.socket_path));
if (!ast_language_is_prefix && !ast_opt_remote) { if (!ast_language_is_prefix && !ast_opt_remote) {
fprintf(stderr, "The 'languageprefix' option in asterisk.conf is deprecated; in a future release it will be removed, and your sound files will need to be organized in the 'new style' language layout.\n"); fprintf(stderr, "The 'languageprefix' option in asterisk.conf is deprecated; in a future release it will be removed, and your sound files will need to be organized in the 'new style' language layout.\n");
} }
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment