stasis: No need to keep a stasis type ref in a stasis msg or cache object.
[asterisk/asterisk.git] / main / options.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2018, CFWare, LLC
5  *
6  * Corey Farrell <git@cfware.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18
19 /*! \file
20  *
21  * \brief Symbols related to asterisk.conf options and paths.
22  *
23  * \author Corey Farrell <git@cfware.com>
24  */
25
26 /*** MODULEINFO
27         <support_level>core</support_level>
28  ***/
29
30 #include "asterisk.h"
31 #include "asterisk/_private.h"
32 #include "asterisk/app.h"
33 #include "asterisk/config.h"
34 #include "asterisk/logger.h"
35 #include "asterisk/options.h"
36 #include "asterisk/paths.h"
37 #include "asterisk/pbx.h"
38 #include "asterisk/rtp_engine.h"
39 #include "asterisk/strings.h"
40 #include "asterisk/utils.h"
41
42 #include "../defaults.h"
43
44 #include <sys/time.h>
45 #include <sys/resource.h>
46
47
48 /*! Default minimum DTMF digit length - 80ms */
49 #define AST_MIN_DTMF_DURATION 80
50
51 #define DEFAULT_MONITOR_DIR DEFAULT_SPOOL_DIR "/monitor"
52 #define DEFAULT_RECORDING_DIR DEFAULT_SPOOL_DIR "/recording"
53
54 /*! \defgroup main_options Main Configuration Options
55  * \brief Main configuration options from asterisk.conf or OS command line on starting Asterisk.
56  * \arg \ref Config_ast "asterisk.conf"
57  * \note Some of them can be changed in the CLI
58  */
59 /*! @{ */
60
61 struct ast_flags ast_options = { AST_DEFAULT_OPTIONS };
62
63 /*! Maximum active system verbosity level. */
64 int ast_verb_sys_level;
65
66 /*! Verbosity level */
67 int option_verbose;
68 /*! Debug level */
69 int option_debug;
70 /*! Default to -1 to know if we have read the level from pjproject yet. */
71 int ast_pjproject_max_log_level = -1;
72 int ast_option_pjproject_log_level;
73 int ast_option_pjproject_cache_pools;
74 /*! Max load avg on system */
75 double ast_option_maxload;
76 /*! Max number of active calls */
77 int ast_option_maxcalls;
78 /*! Max number of open file handles (files, sockets) */
79 int ast_option_maxfiles;
80 /*! Minimum duration of DTMF. */
81 unsigned int option_dtmfminduration = AST_MIN_DTMF_DURATION;
82 #if defined(HAVE_SYSINFO)
83 /*! Minimum amount of free system memory - stop accepting calls if free memory falls below this watermark */
84 long option_minmemfree;
85 #endif
86 int ast_option_rtpusedynamic = 1;
87 unsigned int ast_option_rtpptdynamic = 35;
88
89 /*! @} */
90
91 struct ast_eid ast_eid_default;
92
93 /* XXX tmpdir is a subdir of the spool directory, and no way to remap it */
94 char record_cache_dir[AST_CACHE_DIR_LEN] = DEFAULT_TMP_DIR;
95
96 char ast_defaultlanguage[MAX_LANGUAGE] = DEFAULT_LANGUAGE;
97
98 struct _cfg_paths {
99         char config_dir[PATH_MAX];
100         char module_dir[PATH_MAX];
101         char spool_dir[PATH_MAX];
102         char monitor_dir[PATH_MAX];
103         char recording_dir[PATH_MAX];
104         char var_dir[PATH_MAX];
105         char data_dir[PATH_MAX];
106         char log_dir[PATH_MAX];
107         char agi_dir[PATH_MAX];
108         char run_dir[PATH_MAX];
109         char key_dir[PATH_MAX];
110
111         char config_file[PATH_MAX];
112         char db_path[PATH_MAX];
113         char sbin_dir[PATH_MAX];
114         char pid_path[PATH_MAX];
115         char socket_path[PATH_MAX];
116         char run_user[PATH_MAX];
117         char run_group[PATH_MAX];
118         char system_name[128];
119         char ctl_perms[PATH_MAX];
120         char ctl_owner[PATH_MAX];
121         char ctl_group[PATH_MAX];
122         char ctl_file[PATH_MAX];
123 };
124
125 static struct _cfg_paths cfg_paths = {
126         .config_dir = DEFAULT_CONFIG_DIR,
127         .module_dir = DEFAULT_MODULE_DIR,
128         .spool_dir = DEFAULT_SPOOL_DIR,
129         .monitor_dir = DEFAULT_MONITOR_DIR,
130         .recording_dir = DEFAULT_RECORDING_DIR,
131         .var_dir = DEFAULT_VAR_DIR,
132         .data_dir = DEFAULT_DATA_DIR,
133         .log_dir = DEFAULT_LOG_DIR,
134         .agi_dir = DEFAULT_AGI_DIR,
135         .run_dir = DEFAULT_RUN_DIR,
136         .key_dir = DEFAULT_KEY_DIR,
137
138         .config_file = DEFAULT_CONFIG_FILE,
139         .db_path = DEFAULT_DB,
140         .sbin_dir = DEFAULT_SBIN_DIR,
141         .pid_path = DEFAULT_PID,
142         .socket_path = DEFAULT_SOCKET,
143         .ctl_file = "asterisk.ctl",
144 };
145
146 const char *ast_config_AST_CONFIG_DIR   = cfg_paths.config_dir;
147 const char *ast_config_AST_CONFIG_FILE  = cfg_paths.config_file;
148 const char *ast_config_AST_MODULE_DIR   = cfg_paths.module_dir;
149 const char *ast_config_AST_SPOOL_DIR    = cfg_paths.spool_dir;
150 const char *ast_config_AST_MONITOR_DIR  = cfg_paths.monitor_dir;
151 const char *ast_config_AST_RECORDING_DIR        = cfg_paths.recording_dir;
152 const char *ast_config_AST_VAR_DIR      = cfg_paths.var_dir;
153 const char *ast_config_AST_DATA_DIR     = cfg_paths.data_dir;
154 const char *ast_config_AST_LOG_DIR      = cfg_paths.log_dir;
155 const char *ast_config_AST_AGI_DIR      = cfg_paths.agi_dir;
156 const char *ast_config_AST_KEY_DIR      = cfg_paths.key_dir;
157 const char *ast_config_AST_RUN_DIR      = cfg_paths.run_dir;
158 const char *ast_config_AST_SBIN_DIR = cfg_paths.sbin_dir;
159
160 const char *ast_config_AST_DB           = cfg_paths.db_path;
161 const char *ast_config_AST_PID          = cfg_paths.pid_path;
162 const char *ast_config_AST_SOCKET       = cfg_paths.socket_path;
163 const char *ast_config_AST_RUN_USER     = cfg_paths.run_user;
164 const char *ast_config_AST_RUN_GROUP    = cfg_paths.run_group;
165 const char *ast_config_AST_SYSTEM_NAME  = cfg_paths.system_name;
166
167 const char *ast_config_AST_CTL_PERMISSIONS = cfg_paths.ctl_perms;
168 const char *ast_config_AST_CTL_OWNER = cfg_paths.ctl_owner;
169 const char *ast_config_AST_CTL_GROUP = cfg_paths.ctl_group;
170 const char *ast_config_AST_CTL = cfg_paths.ctl_file;
171
172 /*! \brief Set maximum open files */
173 static void set_ulimit(int value)
174 {
175         struct rlimit l = {0, 0};
176
177         if (value <= 0) {
178                 ast_log(LOG_WARNING, "Unable to change max files open to invalid value %i\n",value);
179                 return;
180         }
181
182         l.rlim_cur = value;
183         l.rlim_max = value;
184
185         if (setrlimit(RLIMIT_NOFILE, &l)) {
186                 ast_log(LOG_WARNING, "Unable to disable core size resource limit: %s\n",strerror(errno));
187                 return;
188         }
189
190         ast_log(LOG_NOTICE, "Setting max files open to %d\n",value);
191
192         return;
193 }
194
195 void set_asterisk_conf_path(const char *path)
196 {
197         ast_copy_string(cfg_paths.config_file, path, sizeof(cfg_paths.config_file));
198 }
199
200 void set_socket_path(const char *path)
201 {
202         ast_copy_string(cfg_paths.socket_path, path, sizeof(cfg_paths.socket_path));
203 }
204
205 void load_asterisk_conf(void)
206 {
207         struct ast_config *cfg;
208         struct ast_variable *v;
209         char hostname[MAXHOSTNAMELEN] = "";
210         struct ast_flags config_flags = { CONFIG_FLAG_NOREALTIME };
211         struct {
212                 unsigned int dbdir:1;
213                 unsigned int keydir:1;
214         } found = { 0, 0 };
215         /* Default to false for security */
216         int live_dangerously = 0;
217         int option_debug_new = 0;
218         int option_verbose_new = 0;
219
220         /* init with buildtime config */
221 #ifdef REF_DEBUG
222         /* The REF_DEBUG compiler flag is now only used to enable refdebug by default.
223          * Support for debugging reference counts is always compiled in. */
224         ast_set2_flag(&ast_options, 1, AST_OPT_FLAG_REF_DEBUG);
225 #endif
226
227         ast_set_default_eid(&ast_eid_default);
228
229         cfg = ast_config_load2(ast_config_AST_CONFIG_FILE, "" /* core, can't reload */, config_flags);
230
231         /* If AST_OPT_FLAG_EXEC_INCLUDES was previously enabled with -X turn it off now.
232          * Using #exec from other configs requires that it be enabled from asterisk.conf. */
233         ast_clear_flag(&ast_options, AST_OPT_FLAG_EXEC_INCLUDES);
234
235         /* no asterisk.conf? no problem, use buildtime config! */
236         if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEUNCHANGED || cfg == CONFIG_STATUS_FILEINVALID) {
237                 fprintf(stderr, "Unable to open specified master config file '%s', using built-in defaults\n", ast_config_AST_CONFIG_FILE);
238                 return;
239         }
240
241         for (v = ast_variable_browse(cfg, "files"); v; v = v->next) {
242                 if (!strcasecmp(v->name, "astctlpermissions")) {
243                         ast_copy_string(cfg_paths.ctl_perms, v->value, sizeof(cfg_paths.ctl_perms));
244                 } else if (!strcasecmp(v->name, "astctlowner")) {
245                         ast_copy_string(cfg_paths.ctl_owner, v->value, sizeof(cfg_paths.ctl_owner));
246                 } else if (!strcasecmp(v->name, "astctlgroup")) {
247                         ast_copy_string(cfg_paths.ctl_group, v->value, sizeof(cfg_paths.ctl_group));
248                 } else if (!strcasecmp(v->name, "astctl")) {
249                         ast_copy_string(cfg_paths.ctl_file, v->value, sizeof(cfg_paths.ctl_file));
250                 }
251         }
252
253         for (v = ast_variable_browse(cfg, "directories"); v; v = v->next) {
254                 if (!strcasecmp(v->name, "astetcdir")) {
255                         ast_copy_string(cfg_paths.config_dir, v->value, sizeof(cfg_paths.config_dir));
256                 } else if (!strcasecmp(v->name, "astspooldir")) {
257                         ast_copy_string(cfg_paths.spool_dir, v->value, sizeof(cfg_paths.spool_dir));
258                         snprintf(cfg_paths.monitor_dir, sizeof(cfg_paths.monitor_dir), "%s/monitor", v->value);
259                         snprintf(cfg_paths.recording_dir, sizeof(cfg_paths.recording_dir), "%s/recording", v->value);
260                 } else if (!strcasecmp(v->name, "astvarlibdir")) {
261                         ast_copy_string(cfg_paths.var_dir, v->value, sizeof(cfg_paths.var_dir));
262                         if (!found.dbdir) {
263                                 snprintf(cfg_paths.db_path, sizeof(cfg_paths.db_path), "%s/astdb", v->value);
264                         }
265                 } else if (!strcasecmp(v->name, "astdbdir")) {
266                         snprintf(cfg_paths.db_path, sizeof(cfg_paths.db_path), "%s/astdb", v->value);
267                         found.dbdir = 1;
268                 } else if (!strcasecmp(v->name, "astdatadir")) {
269                         ast_copy_string(cfg_paths.data_dir, v->value, sizeof(cfg_paths.data_dir));
270                         if (!found.keydir) {
271                                 snprintf(cfg_paths.key_dir, sizeof(cfg_paths.key_dir), "%s/keys", v->value);
272                         }
273                 } else if (!strcasecmp(v->name, "astkeydir")) {
274                         snprintf(cfg_paths.key_dir, sizeof(cfg_paths.key_dir), "%s/keys", v->value);
275                         found.keydir = 1;
276                 } else if (!strcasecmp(v->name, "astlogdir")) {
277                         ast_copy_string(cfg_paths.log_dir, v->value, sizeof(cfg_paths.log_dir));
278                 } else if (!strcasecmp(v->name, "astagidir")) {
279                         ast_copy_string(cfg_paths.agi_dir, v->value, sizeof(cfg_paths.agi_dir));
280                 } else if (!strcasecmp(v->name, "astrundir")) {
281                         snprintf(cfg_paths.pid_path, sizeof(cfg_paths.pid_path), "%s/%s", v->value, "asterisk.pid");
282                         ast_copy_string(cfg_paths.run_dir, v->value, sizeof(cfg_paths.run_dir));
283                 } else if (!strcasecmp(v->name, "astmoddir")) {
284                         ast_copy_string(cfg_paths.module_dir, v->value, sizeof(cfg_paths.module_dir));
285                 } else if (!strcasecmp(v->name, "astsbindir")) {
286                         ast_copy_string(cfg_paths.sbin_dir, v->value, sizeof(cfg_paths.sbin_dir));
287                 }
288         }
289
290         /* Combine astrundir and astctl settings. */
291         snprintf(cfg_paths.socket_path, sizeof(cfg_paths.socket_path), "%s/%s",
292                 ast_config_AST_RUN_DIR, ast_config_AST_CTL);
293
294         for (v = ast_variable_browse(cfg, "options"); v; v = v->next) {
295                 /* verbose level (-v at startup) */
296                 if (!strcasecmp(v->name, "verbose")) {
297                         option_verbose_new = atoi(v->value);
298                 /* whether or not to force timestamping in CLI verbose output. (-T at startup) */
299                 } else if (!strcasecmp(v->name, "timestamp")) {
300                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_TIMESTAMP);
301                 /* whether or not to support #exec in config files */
302                 } else if (!strcasecmp(v->name, "execincludes")) {
303                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_EXEC_INCLUDES);
304                 /* debug level (-d at startup) */
305                 } else if (!strcasecmp(v->name, "debug")) {
306                         option_debug_new = 0;
307                         if (sscanf(v->value, "%30d", &option_debug_new) != 1) {
308                                 option_debug_new = ast_true(v->value) ? 1 : 0;
309                         }
310                 } else if (!strcasecmp(v->name, "refdebug")) {
311                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_REF_DEBUG);
312 #if HAVE_WORKING_FORK
313                 /* Disable forking (-f at startup) */
314                 } else if (!strcasecmp(v->name, "nofork")) {
315                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_NO_FORK);
316                 /* Always fork, even if verbose or debug are enabled (-F at startup) */
317                 } else if (!strcasecmp(v->name, "alwaysfork")) {
318                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_ALWAYS_FORK);
319 #endif
320                 /* Run quietly (-q at startup ) */
321                 } else if (!strcasecmp(v->name, "quiet")) {
322                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_QUIET);
323                 /* Run as console (-c at startup, implies nofork) */
324                 } else if (!strcasecmp(v->name, "console")) {
325                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_NO_FORK | AST_OPT_FLAG_CONSOLE);
326                 /* Run with high priority if the O/S permits (-p at startup) */
327                 } else if (!strcasecmp(v->name, "highpriority")) {
328                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_HIGH_PRIORITY);
329                 /* Initialize RSA auth keys (IAX2) (-i at startup) */
330                 } else if (!strcasecmp(v->name, "initcrypto")) {
331                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_INIT_KEYS);
332                 /* Disable ANSI colors for console (-c at startup) */
333                 } else if (!strcasecmp(v->name, "nocolor")) {
334                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_NO_COLOR);
335                 /* Disable some usage warnings for picky people :p */
336                 } else if (!strcasecmp(v->name, "dontwarn")) {
337                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_DONT_WARN);
338                 /* Dump core in case of crash (-g) */
339                 } else if (!strcasecmp(v->name, "dumpcore")) {
340                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_DUMP_CORE);
341                 /* Cache recorded sound files to another directory during recording */
342                 } else if (!strcasecmp(v->name, "cache_record_files")) {
343                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_CACHE_RECORD_FILES);
344 #if !defined(LOW_MEMORY)
345                 /* Cache media frames for performance */
346                 } else if (!strcasecmp(v->name, "cache_media_frames")) {
347                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_CACHE_MEDIA_FRAMES);
348 #endif
349                 /* Specify cache directory */
350                 } else if (!strcasecmp(v->name, "record_cache_dir")) {
351                         ast_copy_string(record_cache_dir, v->value, AST_CACHE_DIR_LEN);
352                 /* Build transcode paths via SLINEAR, instead of directly */
353                 } else if (!strcasecmp(v->name, "transcode_via_sln")) {
354                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_TRANSCODE_VIA_SLIN);
355                 /* Transmit SLINEAR silence while a channel is being recorded or DTMF is being generated on a channel */
356                 } else if (!strcasecmp(v->name, "transmit_silence_during_record") || !strcasecmp(v->name, "transmit_silence")) {
357                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_TRANSMIT_SILENCE);
358                 /* Enable internal timing */
359                 } else if (!strcasecmp(v->name, "internal_timing")) {
360                         if (!ast_opt_remote) {
361                                 fprintf(stderr,
362                                         "NOTICE: The internal_timing option is no longer needed.\n"
363                                         "  It will always be enabled if you have a timing module loaded.\n");
364                         }
365                 } else if (!strcasecmp(v->name, "mindtmfduration")) {
366                         if (sscanf(v->value, "%30u", &option_dtmfminduration) != 1) {
367                                 option_dtmfminduration = AST_MIN_DTMF_DURATION;
368                         }
369                 } else if (!strcasecmp(v->name, "rtp_use_dynamic")) {
370                         ast_option_rtpusedynamic = ast_true(v->value);
371                 /* http://www.iana.org/assignments/rtp-parameters
372                  * RTP dynamic payload types start at 96 normally; extend down to 0 */
373                 } else if (!strcasecmp(v->name, "rtp_pt_dynamic")) {
374                         ast_parse_arg(v->value, PARSE_UINT32|PARSE_IN_RANGE,
375                                       &ast_option_rtpptdynamic, 0, AST_RTP_PT_FIRST_DYNAMIC);
376                 } else if (!strcasecmp(v->name, "maxcalls")) {
377                         if ((sscanf(v->value, "%30d", &ast_option_maxcalls) != 1) || (ast_option_maxcalls < 0)) {
378                                 ast_option_maxcalls = 0;
379                         }
380                 } else if (!strcasecmp(v->name, "maxload")) {
381                         double test[1];
382
383                         if (getloadavg(test, 1) == -1) {
384                                 ast_log(LOG_ERROR, "Cannot obtain load average on this system. 'maxload' option disabled.\n");
385                                 ast_option_maxload = 0.0;
386                         } else if ((sscanf(v->value, "%30lf", &ast_option_maxload) != 1) || (ast_option_maxload < 0.0)) {
387                                 ast_option_maxload = 0.0;
388                         }
389                 /* Set the maximum amount of open files */
390                 } else if (!strcasecmp(v->name, "maxfiles")) {
391                         ast_option_maxfiles = atoi(v->value);
392                         if (!ast_opt_remote) {
393                                 set_ulimit(ast_option_maxfiles);
394                         }
395                 /* What user to run as */
396                 } else if (!strcasecmp(v->name, "runuser")) {
397                         ast_copy_string(cfg_paths.run_user, v->value, sizeof(cfg_paths.run_user));
398                 /* What group to run as */
399                 } else if (!strcasecmp(v->name, "rungroup")) {
400                         ast_copy_string(cfg_paths.run_group, v->value, sizeof(cfg_paths.run_group));
401                 } else if (!strcasecmp(v->name, "systemname")) {
402                         ast_copy_string(cfg_paths.system_name, v->value, sizeof(cfg_paths.system_name));
403                 } else if (!strcasecmp(v->name, "autosystemname")) {
404                         if (ast_true(v->value)) {
405                                 if (!gethostname(hostname, sizeof(hostname) - 1)) {
406                                         ast_copy_string(cfg_paths.system_name, hostname, sizeof(cfg_paths.system_name));
407                                 } else {
408                                         if (ast_strlen_zero(ast_config_AST_SYSTEM_NAME)){
409                                                 ast_copy_string(cfg_paths.system_name, "localhost", sizeof(cfg_paths.system_name));
410                                         }
411                                         ast_log(LOG_ERROR, "Cannot obtain hostname for this system.  Using '%s' instead.\n", ast_config_AST_SYSTEM_NAME);
412                                 }
413                         }
414                 } else if (!strcasecmp(v->name, "languageprefix")) {
415                         ast_language_is_prefix = ast_true(v->value);
416                 } else if (!strcasecmp(v->name, "defaultlanguage")) {
417                         ast_copy_string(ast_defaultlanguage, v->value, MAX_LANGUAGE);
418                 } else if (!strcasecmp(v->name, "lockmode")) {
419                         if (!strcasecmp(v->value, "lockfile")) {
420                                 ast_set_lock_type(AST_LOCK_TYPE_LOCKFILE);
421                         } else if (!strcasecmp(v->value, "flock")) {
422                                 ast_set_lock_type(AST_LOCK_TYPE_FLOCK);
423                         } else {
424                                 ast_log(LOG_WARNING, "'%s' is not a valid setting for the lockmode option, "
425                                         "defaulting to 'lockfile'\n", v->value);
426                                 ast_set_lock_type(AST_LOCK_TYPE_LOCKFILE);
427                         }
428 #if defined(HAVE_SYSINFO)
429                 } else if (!strcasecmp(v->name, "minmemfree")) {
430                         /* specify the minimum amount of free memory to retain.  Asterisk should stop accepting new calls
431                          * if the amount of free memory falls below this watermark */
432                         if ((sscanf(v->value, "%30ld", &option_minmemfree) != 1) || (option_minmemfree < 0)) {
433                                 option_minmemfree = 0;
434                         }
435 #endif
436                 } else if (!strcasecmp(v->name, "entityid")) {
437                         struct ast_eid tmp_eid;
438                         if (!ast_str_to_eid(&tmp_eid, v->value)) {
439                                 ast_eid_default = tmp_eid;
440                         } else {
441                                 ast_log(LOG_WARNING, "Invalid Entity ID '%s' provided\n", v->value);
442                         }
443                 } else if (!strcasecmp(v->name, "lightbackground")) {
444                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_LIGHT_BACKGROUND);
445                 } else if (!strcasecmp(v->name, "forceblackbackground")) {
446                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_FORCE_BLACK_BACKGROUND);
447                 } else if (!strcasecmp(v->name, "hideconnect")) {
448                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_HIDE_CONSOLE_CONNECT);
449                 } else if (!strcasecmp(v->name, "lockconfdir")) {
450                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_LOCK_CONFIG_DIR);
451                 } else if (!strcasecmp(v->name, "stdexten")) {
452                         /* Choose how to invoke the extensions.conf stdexten */
453                         if (!strcasecmp(v->value, "gosub")) {
454                                 ast_clear_flag(&ast_options, AST_OPT_FLAG_STDEXTEN_MACRO);
455                         } else if (!strcasecmp(v->value, "macro")) {
456                                 ast_set_flag(&ast_options, AST_OPT_FLAG_STDEXTEN_MACRO);
457                         } else {
458                                 ast_log(LOG_WARNING,
459                                         "'%s' is not a valid setting for the stdexten option, defaulting to 'gosub'\n",
460                                         v->value);
461                                 ast_clear_flag(&ast_options, AST_OPT_FLAG_STDEXTEN_MACRO);
462                         }
463                 } else if (!strcasecmp(v->name, "live_dangerously")) {
464                         live_dangerously = ast_true(v->value);
465                 }
466         }
467         if (!ast_opt_remote) {
468                 pbx_live_dangerously(live_dangerously);
469         }
470
471         option_debug += option_debug_new;
472         option_verbose += option_verbose_new;
473
474         ast_config_destroy(cfg);
475 }