0214159d66993691e828743447e53bbeb110a319
[asterisk/asterisk.git] / main / asterisk.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2016, Digium, Inc.
5  *
6  * Mark Spencer <markster@digium.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
20 /* Doxygenified Copyright Header */
21 /*!
22  * \mainpage Asterisk -- The Open Source Telephony Project
23  *
24  * \par Welcome
25  *
26  * This documentation created by the Doxygen project clearly explains the
27  * internals of the Asterisk software. This documentation contains basic
28  * examples, developer documentation, support information, and information
29  * for upgrading.
30  *
31  * \section community Community
32  * Asterisk is a big project and has a busy community. Look at the
33  * resources for questions and stick around to help answer questions.
34  * \li \ref asterisk_community_resources
35  *
36  * \par Developer Documentation for Asterisk
37  *
38  * This is the main developer documentation for Asterisk. It is
39  * generated by running "make progdocs" from the Asterisk source tree.
40  *
41  * In addition to the information available on the Asterisk source code,
42  * please see the appendices for information on coding guidelines,
43  * release management, commit policies, and more.
44  *
45  * \arg \ref AsteriskArchitecture
46  *
47  * \par Additional documentation
48  * \arg \ref Licensing
49  * \arg \ref DevDoc
50  * \arg \ref configuration_file
51  * \arg \ref channel_drivers
52  * \arg \ref applications
53  *
54  * \section copyright Copyright and Author
55  *
56  * Copyright (C) 1999 - 2016, Digium, Inc.
57  * Asterisk is a <a href="http://www.digium.com/en/company/view-policy.php?id=Trademark-Policy">registered trademark</a>
58  * of <a rel="nofollow" href="http://www.digium.com">Digium, Inc</a>.
59  *
60  * \author Mark Spencer <markster@digium.com>
61  *
62  * See http://www.asterisk.org for more information about
63  * the Asterisk project. Please do not directly contact
64  * any of the maintainers of this project for assistance;
65  * the project provides a web site, mailing lists, and IRC
66  * channels for your use.
67  *
68  */
69
70 /*!
71  * \page asterisk_community_resources Asterisk Community Resources
72  * \par Websites
73  * \li http://www.asterisk.org Asterisk Homepage
74  * \li http://wiki.asterisk.org Asterisk Wiki
75  *
76  * \par Mailing Lists
77  * \par
78  * All lists: http://lists.digium.com/mailman/listinfo
79  * \li aadk-commits     SVN commits to the AADK repository
80  * \li asterisk-addons-commits  SVN commits to the Asterisk addons project
81  * \li asterisk-announce        [no description available]
82  * \li asterisk-biz     Commercial and Business-Oriented Asterisk Discussion
83  * \li Asterisk-BSD     Asterisk on BSD discussion
84  * \li asterisk-bugs    [no description available]
85  * \li asterisk-commits SVN commits to the Asterisk project
86  * \li asterisk-dev     Asterisk Developers Mailing List
87  * \li asterisk-doc     Discussions regarding The Asterisk Documentation Project
88  * \li asterisk-embedded        Asterisk Embedded Development
89  * \li asterisk-gui     Asterisk GUI project discussion
90  * \li asterisk-gui-commits     SVN commits to the Asterisk-GUI project
91  * \li asterisk-ha-clustering   Asterisk High Availability and Clustering List - Non-Commercial Discussion
92  * \li Asterisk-i18n    Discussion of Asterisk internationalization
93  * \li asterisk-r2      [no description available]
94  * \li asterisk-scf-commits     Commits to the Asterisk SCF project code repositories
95  * \li asterisk-scf-committee   Asterisk SCF Steering Committee discussions
96  * \li asterisk-scf-dev Asterisk SCF Developers Mailing List
97  * \li asterisk-scf-wiki-changes        Changes to the Asterisk SCF space on wiki.asterisk.org
98  * \li asterisk-security        Asterisk Security Discussion
99  * \li asterisk-speech-rec      Use of speech recognition in Asterisk
100  * \li asterisk-ss7     [no description available]
101  * \li asterisk-users   Asterisk Users Mailing List - Non-Commercial Discussion
102  * \li asterisk-video   Development discussion of video media support in Asterisk
103  * \li asterisk-wiki-changes    Changes to the Asterisk space on wiki.asterisk.org
104  * \li asterisknow      AsteriskNOW Discussion
105  * \li dahdi-commits    SVN commits to the DAHDI project
106  * \li digium-announce  Digium Product Announcements
107  * \li Dundi    Distributed Universal Number Discovery
108  * \li libiax2-commits  SVN commits to the libiax2 project
109  * \li libpri-commits   SVN commits to the libpri project
110  * \li libss7-commits   SVN commits to the libss7 project
111  * \li svn-commits      SVN commits to the Digium repositories
112  * \li Test-results     Results from automated testing
113  * \li thirdparty-commits       SVN commits to the Digium third-party software repository
114  * \li zaptel-commits   SVN commits to the Zaptel project
115  *
116  * \par Forums
117  * \li Forums are located at http://forums.asterisk.org/
118  *
119  * \par IRC
120  * \par
121  * Use http://www.freenode.net IRC server to connect with Asterisk
122  * developers and users in realtime.
123  *
124  * \li \verbatim #asterisk \endverbatim Asterisk Users Room
125  * \li \verbatim #asterisk-dev \endverbatim Asterisk Developers Room
126  *
127  * \par More
128  * \par
129  * If you would like to add a resource to this list please create an issue
130  * on the issue tracker with a patch.
131  */
132
133 /*! \file
134  * \brief Top level source file for Asterisk - the Open Source PBX.
135  *      Implementation of PBX core functions and CLI interface.
136  */
137
138 /*! \li \ref asterisk.c uses the configuration file \ref asterisk.conf
139  * \addtogroup configuration_file
140  */
141
142 /*! \page asterisk.conf asterisk.conf
143  * \verbinclude asterisk.conf.sample
144  */
145
146 /*** MODULEINFO
147         <support_level>core</support_level>
148  ***/
149
150 #include "asterisk.h"
151
152 #include "asterisk/_private.h"
153
154 #undef sched_setscheduler
155 #undef setpriority
156 #include <sys/time.h>
157 #include <fcntl.h>
158 #include <signal.h>
159 #include <sched.h>
160 #include <sys/un.h>
161 #include <sys/wait.h>
162 #include <ctype.h>
163 #include <sys/resource.h>
164 #include <grp.h>
165 #include <pwd.h>
166 #include <sys/stat.h>
167 #if defined(HAVE_SYSINFO)
168 #include <sys/sysinfo.h>
169 #elif defined(HAVE_SYSCTL)
170 #include <sys/param.h>
171 #include <sys/sysctl.h>
172 #include <sys/vmmeter.h>
173 #if defined(__FreeBSD__)
174 #include <vm/vm_param.h>
175 #endif
176 #if defined(HAVE_SWAPCTL)
177 #include <sys/swap.h>
178 #endif
179 #endif
180 #include <regex.h>
181 #include <histedit.h>
182
183 #if defined(SOLARIS)
184 int daemon(int, int);  /* defined in libresolv of all places */
185 #include <sys/loadavg.h>
186 #endif
187
188 #ifdef linux
189 #include <sys/prctl.h>
190 #ifdef HAVE_CAP
191 #include <sys/capability.h>
192 #endif /* HAVE_CAP */
193 #endif /* linux */
194
195 /* we define here the variables so to better agree on the prototype */
196 #include "asterisk/paths.h"
197 #include "asterisk/network.h"
198 #include "asterisk/cli.h"
199 #include "asterisk/channel.h"
200 #include "asterisk/translate.h"
201 #include "asterisk/pickup.h"
202 #include "asterisk/features.h"
203 #include "asterisk/acl.h"
204 #include "asterisk/ulaw.h"
205 #include "asterisk/alaw.h"
206 #include "asterisk/callerid.h"
207 #include "asterisk/image.h"
208 #include "asterisk/tdd.h"
209 #include "asterisk/term.h"
210 #include "asterisk/manager.h"
211 #include "asterisk/cdr.h"
212 #include "asterisk/cel.h"
213 #include "asterisk/pbx.h"
214 #include "asterisk/enum.h"
215 #include "asterisk/http.h"
216 #include "asterisk/udptl.h"
217 #include "asterisk/app.h"
218 #include "asterisk/lock.h"
219 #include "asterisk/utils.h"
220 #include "asterisk/file.h"
221 #include "asterisk/io.h"
222 #include "editline/histedit.h"
223 #include "asterisk/config.h"
224 #include "asterisk/ast_version.h"
225 #include "asterisk/linkedlists.h"
226 #include "asterisk/devicestate.h"
227 #include "asterisk/presencestate.h"
228 #include "asterisk/module.h"
229 #include "asterisk/dsp.h"
230 #include "asterisk/buildinfo.h"
231 #include "asterisk/xmldoc.h"
232 #include "asterisk/poll-compat.h"
233 #include "asterisk/ccss.h"
234 #include "asterisk/test.h"
235 #include "asterisk/rtp_engine.h"
236 #include "asterisk/format.h"
237 #include "asterisk/aoc.h"
238 #include "asterisk/uuid.h"
239 #include "asterisk/sorcery.h"
240 #include "asterisk/bucket.h"
241 #include "asterisk/stasis.h"
242 #include "asterisk/json.h"
243 #include "asterisk/stasis_endpoints.h"
244 #include "asterisk/stasis_system.h"
245 #include "asterisk/security_events.h"
246 #include "asterisk/endpoints.h"
247 #include "asterisk/codec.h"
248 #include "asterisk/format_cache.h"
249 #include "asterisk/media_cache.h"
250 #include "asterisk/astdb.h"
251 #include "asterisk/options.h"
252
253 #include "../defaults.h"
254
255 /*** DOCUMENTATION
256         <managerEvent language="en_US" name="FullyBooted">
257                 <managerEventInstance class="EVENT_FLAG_SYSTEM">
258                         <synopsis>Raised when all Asterisk initialization procedures have finished.</synopsis>
259                         <syntax>
260                                 <parameter name="Status">
261                                         <para>Informational message</para>
262                                 </parameter>
263                                 <parameter name="Uptime">
264                                         <para>Seconds since start</para>
265                                 </parameter>
266                                 <parameter name="LastReload">
267                                         <para>Seconds since last reload</para>
268                                 </parameter>
269                         </syntax>
270                 </managerEventInstance>
271         </managerEvent>
272         <managerEvent language="en_US" name="Shutdown">
273                 <managerEventInstance class="EVENT_FLAG_SYSTEM">
274                         <synopsis>Raised when Asterisk is shutdown or restarted.</synopsis>
275                         <syntax>
276                                 <parameter name="Shutdown">
277                                         <para>Whether the shutdown is proceeding cleanly (all channels
278                                         were hungup successfully) or uncleanly (channels will be
279                                         terminated)</para>
280                                         <enumlist>
281                                                 <enum name="Uncleanly"/>
282                                                 <enum name="Cleanly"/>
283                                         </enumlist>
284                                 </parameter>
285                                 <parameter name="Restart">
286                                         <para>Whether or not a restart will occur.</para>
287                                         <enumlist>
288                                                 <enum name="True"/>
289                                                 <enum name="False"/>
290                                         </enumlist>
291                                 </parameter>
292                         </syntax>
293                 </managerEventInstance>
294         </managerEvent>
295  ***/
296
297 #ifndef AF_LOCAL
298 #define AF_LOCAL AF_UNIX
299 #define PF_LOCAL PF_UNIX
300 #endif
301
302 #define AST_MAX_CONNECTS 128
303 #define NUM_MSGS 64
304
305 /*! Default minimum DTMF digit length - 80ms */
306 #define AST_MIN_DTMF_DURATION 80
307
308
309 /*! \brief Welcome message when starting a CLI interface */
310 #define WELCOME_MESSAGE \
311     ast_verbose("Asterisk %s, Copyright (C) 1999 - 2016, Digium, Inc. and others.\n" \
312                 "Created by Mark Spencer <markster@digium.com>\n" \
313                 "Asterisk comes with ABSOLUTELY NO WARRANTY; type 'core show warranty' for details.\n" \
314                 "This is free software, with components licensed under the GNU General Public\n" \
315                 "License version 2 and other licenses; you are welcome to redistribute it under\n" \
316                 "certain conditions. Type 'core show license' for details.\n" \
317                 "=========================================================================\n", ast_get_version()) \
318
319 /*! \defgroup main_options Main Configuration Options
320  * \brief Main configuration options from asterisk.conf or OS command line on starting Asterisk.
321  * \arg \ref Config_ast "asterisk.conf"
322  * \note Some of them can be changed in the CLI
323  */
324 /*! @{ */
325
326 struct ast_flags ast_options = { AST_DEFAULT_OPTIONS };
327
328 /*! Maximum active system verbosity level. */
329 int ast_verb_sys_level;
330
331 int option_verbose;                             /*!< Verbosity level */
332 int option_debug;                               /*!< Debug level */
333 int ast_pjproject_max_log_level = -1;/* Default to -1 to know if we have read the level from pjproject yet. */
334 int ast_option_pjproject_log_level;
335 double ast_option_maxload;                      /*!< Max load avg on system */
336 int ast_option_maxcalls;                        /*!< Max number of active calls */
337 int ast_option_maxfiles;                        /*!< Max number of open file handles (files, sockets) */
338 unsigned int option_dtmfminduration;            /*!< Minimum duration of DTMF. */
339 #if defined(HAVE_SYSINFO)
340 long option_minmemfree;                         /*!< Minimum amount of free system memory - stop accepting calls if free memory falls below this watermark */
341 #endif
342 int ast_option_rtpusedynamic;
343 unsigned int ast_option_rtpptdynamic;
344
345 /*! @} */
346
347 struct ast_eid ast_eid_default;
348
349 /* XXX tmpdir is a subdir of the spool directory, and no way to remap it */
350 char record_cache_dir[AST_CACHE_DIR_LEN] = DEFAULT_TMP_DIR;
351
352 static int ast_socket = -1;             /*!< UNIX Socket for allowing remote control */
353 static int ast_socket_is_sd = 0; /*!< Is socket activation responsible for ast_socket? */
354 static int ast_consock = -1;            /*!< UNIX Socket for controlling another asterisk */
355 pid_t ast_mainpid;
356 struct console {
357         int fd;                         /*!< File descriptor */
358         int p[2];                       /*!< Pipe */
359         pthread_t t;                    /*!< Thread of handler */
360         int mute;                       /*!< Is the console muted for logs */
361         int uid;                        /*!< Remote user ID. */
362         int gid;                        /*!< Remote group ID. */
363         int levels[NUMLOGLEVELS];       /*!< Which log levels are enabled for the console */
364         /*! Verbosity level of this console. */
365         int option_verbose;
366 };
367
368 struct ast_atexit {
369         void (*func)(void);
370         int is_cleanup;
371         AST_LIST_ENTRY(ast_atexit) list;
372 };
373
374 static AST_LIST_HEAD_STATIC(atexits, ast_atexit);
375
376 struct timeval ast_startuptime;
377 struct timeval ast_lastreloadtime;
378
379 static History *el_hist;
380 static EditLine *el;
381 static char *remotehostname;
382
383 struct console consoles[AST_MAX_CONNECTS];
384
385 char ast_defaultlanguage[MAX_LANGUAGE] = DEFAULT_LANGUAGE;
386
387 static int ast_el_add_history(const char *);
388 static int ast_el_read_history(const char *);
389 static int ast_el_write_history(const char *);
390
391 static void ast_el_read_default_histfile(void);
392 static void ast_el_write_default_histfile(void);
393
394 static void asterisk_daemon(int isroot, const char *runuser, const char *rungroup);
395
396 #define DEFAULT_MONITOR_DIR DEFAULT_SPOOL_DIR "/monitor"
397 #define DEFAULT_RECORDING_DIR DEFAULT_SPOOL_DIR "/recording"
398
399 struct _cfg_paths {
400         char config_dir[PATH_MAX];
401         char module_dir[PATH_MAX];
402         char spool_dir[PATH_MAX];
403         char monitor_dir[PATH_MAX];
404         char recording_dir[PATH_MAX];
405         char var_dir[PATH_MAX];
406         char data_dir[PATH_MAX];
407         char log_dir[PATH_MAX];
408         char agi_dir[PATH_MAX];
409         char run_dir[PATH_MAX];
410         char key_dir[PATH_MAX];
411
412         char config_file[PATH_MAX];
413         char db_path[PATH_MAX];
414         char sbin_dir[PATH_MAX];
415         char pid_path[PATH_MAX];
416         char socket_path[PATH_MAX];
417         char run_user[PATH_MAX];
418         char run_group[PATH_MAX];
419         char system_name[128];
420 };
421
422 static struct _cfg_paths cfg_paths;
423
424 const char *ast_config_AST_CONFIG_DIR   = cfg_paths.config_dir;
425 const char *ast_config_AST_CONFIG_FILE  = cfg_paths.config_file;
426 const char *ast_config_AST_MODULE_DIR   = cfg_paths.module_dir;
427 const char *ast_config_AST_SPOOL_DIR    = cfg_paths.spool_dir;
428 const char *ast_config_AST_MONITOR_DIR  = cfg_paths.monitor_dir;
429 const char *ast_config_AST_RECORDING_DIR        = cfg_paths.recording_dir;
430 const char *ast_config_AST_VAR_DIR      = cfg_paths.var_dir;
431 const char *ast_config_AST_DATA_DIR     = cfg_paths.data_dir;
432 const char *ast_config_AST_LOG_DIR      = cfg_paths.log_dir;
433 const char *ast_config_AST_AGI_DIR      = cfg_paths.agi_dir;
434 const char *ast_config_AST_KEY_DIR      = cfg_paths.key_dir;
435 const char *ast_config_AST_RUN_DIR      = cfg_paths.run_dir;
436 const char *ast_config_AST_SBIN_DIR = cfg_paths.sbin_dir;
437
438 const char *ast_config_AST_DB           = cfg_paths.db_path;
439 const char *ast_config_AST_PID          = cfg_paths.pid_path;
440 const char *ast_config_AST_SOCKET       = cfg_paths.socket_path;
441 const char *ast_config_AST_RUN_USER     = cfg_paths.run_user;
442 const char *ast_config_AST_RUN_GROUP    = cfg_paths.run_group;
443 const char *ast_config_AST_SYSTEM_NAME  = cfg_paths.system_name;
444
445 static char ast_config_AST_CTL_PERMISSIONS[PATH_MAX];
446 static char ast_config_AST_CTL_OWNER[PATH_MAX] = "\0";
447 static char ast_config_AST_CTL_GROUP[PATH_MAX] = "\0";
448 static char ast_config_AST_CTL[PATH_MAX] = "asterisk.ctl";
449
450 extern unsigned int ast_FD_SETSIZE;
451
452 static char *_argv[256];
453
454 typedef enum {
455         /*! Normal operation */
456         NOT_SHUTTING_DOWN,
457         /*! Committed to shutting down.  Final phase */
458         SHUTTING_DOWN_FINAL,
459         /*! Committed to shutting down.  Initial phase */
460         SHUTTING_DOWN,
461         /*!
462          * Valid values for quit_handler() niceness below.
463          * These shutdown/restart levels can be cancelled.
464          *
465          * Remote console exit right now
466          */
467         SHUTDOWN_FAST,
468         /*! core stop/restart now */
469         SHUTDOWN_NORMAL,
470         /*! core stop/restart gracefully */
471         SHUTDOWN_NICE,
472         /*! core stop/restart when convenient */
473         SHUTDOWN_REALLY_NICE
474 } shutdown_nice_t;
475
476 static shutdown_nice_t shuttingdown = NOT_SHUTTING_DOWN;
477
478 /*! Prevent new channel allocation for shutdown. */
479 static int shutdown_pending;
480
481 static int restartnow;
482 static pthread_t consolethread = AST_PTHREADT_NULL;
483 static pthread_t mon_sig_flags;
484 static int canary_pid = 0;
485 static char canary_filename[128];
486 static int multi_thread_safe;
487
488 static char randompool[256];
489
490 static int sig_alert_pipe[2] = { -1, -1 };
491 static struct {
492          unsigned int need_reload:1;
493          unsigned int need_quit:1;
494          unsigned int need_quit_handler:1;
495 } sig_flags;
496
497 #if !defined(LOW_MEMORY)
498 struct thread_list_t {
499         AST_RWLIST_ENTRY(thread_list_t) list;
500         char *name;
501         pthread_t id;
502         int lwp;
503 };
504
505 static AST_RWLIST_HEAD_STATIC(thread_list, thread_list_t);
506
507 void ast_register_thread(char *name)
508 {
509         struct thread_list_t *new = ast_calloc(1, sizeof(*new));
510
511         if (!new)
512                 return;
513
514         ast_assert(multi_thread_safe);
515         new->id = pthread_self();
516         new->lwp = ast_get_tid();
517         new->name = name; /* steal the allocated memory for the thread name */
518         AST_RWLIST_WRLOCK(&thread_list);
519         AST_RWLIST_INSERT_HEAD(&thread_list, new, list);
520         AST_RWLIST_UNLOCK(&thread_list);
521 }
522
523 void ast_unregister_thread(void *id)
524 {
525         struct thread_list_t *x;
526
527         AST_RWLIST_WRLOCK(&thread_list);
528         AST_RWLIST_TRAVERSE_SAFE_BEGIN(&thread_list, x, list) {
529                 if ((void *) x->id == id) {
530                         AST_RWLIST_REMOVE_CURRENT(list);
531                         break;
532                 }
533         }
534         AST_RWLIST_TRAVERSE_SAFE_END;
535         AST_RWLIST_UNLOCK(&thread_list);
536         if (x) {
537                 ast_free(x->name);
538                 ast_free(x);
539         }
540 }
541
542 /*! \brief Give an overview of core settings */
543 static char *handle_show_settings(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
544 {
545         char buf[BUFSIZ];
546         struct ast_tm tm;
547         char eid_str[128];
548         struct rlimit limits;
549         char pbx_uuid[AST_UUID_STR_LEN];
550
551         switch (cmd) {
552         case CLI_INIT:
553                 e->command = "core show settings";
554                 e->usage = "Usage: core show settings\n"
555                            "       Show core misc settings";
556                 return NULL;
557         case CLI_GENERATE:
558                 return NULL;
559         }
560
561         ast_eid_to_str(eid_str, sizeof(eid_str), &ast_eid_default);
562         ast_pbx_uuid_get(pbx_uuid, sizeof(pbx_uuid));
563
564         ast_cli(a->fd, "\nPBX Core settings\n");
565         ast_cli(a->fd, "-----------------\n");
566         ast_cli(a->fd, "  Version:                     %s\n", ast_get_version());
567         ast_cli(a->fd, "  Build Options:               %s\n", S_OR(ast_get_build_opts(), "(none)"));
568         if (ast_option_maxcalls)
569                 ast_cli(a->fd, "  Maximum calls:               %d (Current %d)\n", ast_option_maxcalls, ast_active_channels());
570         else
571                 ast_cli(a->fd, "  Maximum calls:               Not set\n");
572
573         if (getrlimit(RLIMIT_NOFILE, &limits)) {
574                 ast_cli(a->fd, "  Maximum open file handles:   Error because of %s\n", strerror(errno));
575         } else if (limits.rlim_cur == RLIM_INFINITY) {
576                 ast_cli(a->fd, "  Maximum open file handles:   Unlimited\n");
577         } else if (limits.rlim_cur < ast_option_maxfiles) {
578                 ast_cli(a->fd, "  Maximum open file handles:   %d (is) %d (requested)\n", (int) limits.rlim_cur, ast_option_maxfiles);
579         } else {
580                 ast_cli(a->fd, "  Maximum open file handles:   %d\n", (int) limits.rlim_cur);
581         }
582
583         ast_cli(a->fd, "  Root console verbosity:      %d\n", option_verbose);
584         ast_cli(a->fd, "  Current console verbosity:   %d\n", ast_verb_console_get());
585         ast_cli(a->fd, "  Debug level:                 %d\n", option_debug);
586         ast_cli(a->fd, "  Maximum load average:        %lf\n", ast_option_maxload);
587 #if defined(HAVE_SYSINFO)
588         ast_cli(a->fd, "  Minimum free memory:         %ld MB\n", option_minmemfree);
589 #endif
590         if (ast_localtime(&ast_startuptime, &tm, NULL)) {
591                 ast_strftime(buf, sizeof(buf), "%H:%M:%S", &tm);
592                 ast_cli(a->fd, "  Startup time:                %s\n", buf);
593         }
594         if (ast_localtime(&ast_lastreloadtime, &tm, NULL)) {
595                 ast_strftime(buf, sizeof(buf), "%H:%M:%S", &tm);
596                 ast_cli(a->fd, "  Last reload time:            %s\n", buf);
597         }
598         ast_cli(a->fd, "  System:                      %s/%s built by %s on %s %s\n", ast_build_os, ast_build_kernel, ast_build_user, ast_build_machine, ast_build_date);
599         ast_cli(a->fd, "  System name:                 %s\n", ast_config_AST_SYSTEM_NAME);
600         ast_cli(a->fd, "  Entity ID:                   %s\n", eid_str);
601         ast_cli(a->fd, "  PBX UUID:                    %s\n", pbx_uuid);
602         ast_cli(a->fd, "  Default language:            %s\n", ast_defaultlanguage);
603         ast_cli(a->fd, "  Language prefix:             %s\n", ast_language_is_prefix ? "Enabled" : "Disabled");
604         ast_cli(a->fd, "  User name and group:         %s/%s\n", ast_config_AST_RUN_USER, ast_config_AST_RUN_GROUP);
605         ast_cli(a->fd, "  Executable includes:         %s\n", ast_test_flag(&ast_options, AST_OPT_FLAG_EXEC_INCLUDES) ? "Enabled" : "Disabled");
606         ast_cli(a->fd, "  Transcode via SLIN:          %s\n", ast_test_flag(&ast_options, AST_OPT_FLAG_TRANSCODE_VIA_SLIN) ? "Enabled" : "Disabled");
607         ast_cli(a->fd, "  Transmit silence during rec: %s\n", ast_test_flag(&ast_options, AST_OPT_FLAG_TRANSMIT_SILENCE) ? "Enabled" : "Disabled");
608         ast_cli(a->fd, "  Generic PLC:                 %s\n", ast_test_flag(&ast_options, AST_OPT_FLAG_GENERIC_PLC) ? "Enabled" : "Disabled");
609         ast_cli(a->fd, "  Min DTMF duration::          %u\n", option_dtmfminduration);
610 #if !defined(LOW_MEMORY)
611         ast_cli(a->fd, "  Cache media frames:          %s\n", ast_opt_cache_media_frames ? "Enabled" : "Disabled");
612 #endif
613         ast_cli(a->fd, "  RTP use dynamic payloads:    %u\n", ast_option_rtpusedynamic);
614
615         if (ast_option_rtpptdynamic == AST_RTP_PT_LAST_REASSIGN) {
616                 ast_cli(a->fd, "  RTP dynamic payload types:   %u,%u-%u\n",
617                         ast_option_rtpptdynamic,
618                         AST_RTP_PT_FIRST_DYNAMIC, AST_RTP_MAX_PT - 1);
619         } else if (ast_option_rtpptdynamic < AST_RTP_PT_LAST_REASSIGN) {
620                 ast_cli(a->fd, "  RTP dynamic payload types:   %u-%u,%u-%u\n",
621                         ast_option_rtpptdynamic, AST_RTP_PT_LAST_REASSIGN,
622                         AST_RTP_PT_FIRST_DYNAMIC, AST_RTP_MAX_PT - 1);
623         } else {
624                 ast_cli(a->fd, "  RTP dynamic payload types:   %u-%u\n",
625                         AST_RTP_PT_FIRST_DYNAMIC, AST_RTP_MAX_PT - 1);
626         }
627
628         ast_cli(a->fd, "\n* Subsystems\n");
629         ast_cli(a->fd, "  -------------\n");
630         ast_cli(a->fd, "  Manager (AMI):               %s\n", check_manager_enabled() ? "Enabled" : "Disabled");
631         ast_cli(a->fd, "  Web Manager (AMI/HTTP):      %s\n", check_webmanager_enabled() ? "Enabled" : "Disabled");
632         ast_cli(a->fd, "  Call data records:           %s\n", ast_cdr_is_enabled() ? "Enabled" : "Disabled");
633         ast_cli(a->fd, "  Realtime Architecture (ARA): %s\n", ast_realtime_enabled() ? "Enabled" : "Disabled");
634
635         /*! \todo we could check musiconhold, voicemail, smdi, adsi, queues  */
636
637         ast_cli(a->fd, "\n* Directories\n");
638         ast_cli(a->fd, "  -------------\n");
639         ast_cli(a->fd, "  Configuration file:          %s\n", ast_config_AST_CONFIG_FILE);
640         ast_cli(a->fd, "  Configuration directory:     %s\n", ast_config_AST_CONFIG_DIR);
641         ast_cli(a->fd, "  Module directory:            %s\n", ast_config_AST_MODULE_DIR);
642         ast_cli(a->fd, "  Spool directory:             %s\n", ast_config_AST_SPOOL_DIR);
643         ast_cli(a->fd, "  Log directory:               %s\n", ast_config_AST_LOG_DIR);
644         ast_cli(a->fd, "  Run/Sockets directory:       %s\n", ast_config_AST_RUN_DIR);
645         ast_cli(a->fd, "  PID file:                    %s\n", ast_config_AST_PID);
646         ast_cli(a->fd, "  VarLib directory:            %s\n", ast_config_AST_VAR_DIR);
647         ast_cli(a->fd, "  Data directory:              %s\n", ast_config_AST_DATA_DIR);
648         ast_cli(a->fd, "  ASTDB:                       %s\n", ast_config_AST_DB);
649         ast_cli(a->fd, "  IAX2 Keys directory:         %s\n", ast_config_AST_KEY_DIR);
650         ast_cli(a->fd, "  AGI Scripts directory:       %s\n", ast_config_AST_AGI_DIR);
651         ast_cli(a->fd, "\n\n");
652         return CLI_SUCCESS;
653 }
654
655 static char *handle_show_threads(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
656 {
657         int count = 0;
658         struct thread_list_t *cur;
659         switch (cmd) {
660         case CLI_INIT:
661                 e->command = "core show threads";
662                 e->usage =
663                         "Usage: core show threads\n"
664                         "       List threads currently active in the system.\n";
665                 return NULL;
666         case CLI_GENERATE:
667                 return NULL;
668         }
669
670         AST_RWLIST_RDLOCK(&thread_list);
671         AST_RWLIST_TRAVERSE(&thread_list, cur, list) {
672                 ast_cli(a->fd, "%p %d %s\n", (void *)cur->id, cur->lwp, cur->name);
673                 count++;
674         }
675         AST_RWLIST_UNLOCK(&thread_list);
676         ast_cli(a->fd, "%d threads listed.\n", count);
677         return CLI_SUCCESS;
678 }
679
680 #if defined (HAVE_SYSCTL) && defined(HAVE_SWAPCTL)
681 /*
682  * swapmode is rewritten by Tobias Weingartner <weingart@openbsd.org>
683  * to be based on the new swapctl(2) system call.
684  */
685 static int swapmode(int *used, int *total)
686 {
687         struct swapent *swdev;
688         int nswap, rnswap, i;
689
690         nswap = swapctl(SWAP_NSWAP, 0, 0);
691         if (nswap == 0)
692                 return 0;
693
694         swdev = ast_calloc(nswap, sizeof(*swdev));
695         if (swdev == NULL)
696                 return 0;
697
698         rnswap = swapctl(SWAP_STATS, swdev, nswap);
699         if (rnswap == -1) {
700                 ast_free(swdev);
701                 return 0;
702         }
703
704         /* if rnswap != nswap, then what? */
705
706         /* Total things up */
707         *total = *used = 0;
708         for (i = 0; i < nswap; i++) {
709                 if (swdev[i].se_flags & SWF_ENABLE) {
710                         *used += (swdev[i].se_inuse / (1024 / DEV_BSIZE));
711                         *total += (swdev[i].se_nblks / (1024 / DEV_BSIZE));
712                 }
713         }
714         ast_free(swdev);
715         return 1;
716 }
717 #endif
718
719 #if defined(HAVE_SYSINFO) || defined(HAVE_SYSCTL)
720 /*! \brief Give an overview of system statistics */
721 static char *handle_show_sysinfo(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
722 {
723         uint64_t physmem, freeram;
724 #if defined(HAVE_SYSINFO) || defined(HAVE_SWAPCTL)
725         int totalswap = 0;
726         uint64_t freeswap = 0;
727 #endif
728         int nprocs = 0;
729         long uptime = 0;
730 #if defined(HAVE_SYSINFO)
731         struct sysinfo sys_info;
732 #elif defined(HAVE_SYSCTL)
733         static int pageshift;
734         struct vmtotal vmtotal;
735         struct timeval  boottime;
736         time_t  now;
737         int mib[2], pagesize;
738 #if defined(HAVE_SWAPCTL)
739         int usedswap = 0;
740 #endif
741         size_t len;
742 #endif
743
744         switch (cmd) {
745         case CLI_INIT:
746                 e->command = "core show sysinfo";
747                 e->usage =
748                         "Usage: core show sysinfo\n"
749                         "       List current system information.\n";
750                 return NULL;
751         case CLI_GENERATE:
752                 return NULL;
753         }
754
755 #if defined(HAVE_SYSINFO)
756         sysinfo(&sys_info);
757         uptime = sys_info.uptime / 3600;
758         physmem = sys_info.totalram * sys_info.mem_unit;
759         freeram = (sys_info.freeram * sys_info.mem_unit) / 1024;
760         totalswap = (sys_info.totalswap * sys_info.mem_unit) / 1024;
761         freeswap = (sys_info.freeswap * sys_info.mem_unit) / 1024;
762         nprocs = sys_info.procs;
763 #elif defined(HAVE_SYSCTL)
764         /* calculate the uptime by looking at boottime */
765         time(&now);
766         mib[0] = CTL_KERN;
767         mib[1] = KERN_BOOTTIME;
768         len = sizeof(boottime);
769         if (sysctl(mib, 2, &boottime, &len, NULL, 0) != -1) {
770                 uptime = now - boottime.tv_sec;
771         }
772         uptime = uptime/3600;
773         /* grab total physical memory  */
774         mib[0] = CTL_HW;
775 #if defined(HW_PHYSMEM64)
776         mib[1] = HW_PHYSMEM64;
777 #else
778         mib[1] = HW_PHYSMEM;
779 #endif
780         len = sizeof(physmem);
781         sysctl(mib, 2, &physmem, &len, NULL, 0);
782
783         pagesize = getpagesize();
784         pageshift = 0;
785         while (pagesize > 1) {
786                 pageshift++;
787                 pagesize >>= 1;
788         }
789
790         /* we only need the amount of log(2)1024 for our conversion */
791         pageshift -= 10;
792
793         /* grab vm totals */
794         mib[0] = CTL_VM;
795         mib[1] = VM_METER;
796         len = sizeof(vmtotal);
797         sysctl(mib, 2, &vmtotal, &len, NULL, 0);
798         freeram = (vmtotal.t_free << pageshift);
799         /* generate swap usage and totals */
800 #if defined(HAVE_SWAPCTL)
801         swapmode(&usedswap, &totalswap);
802         freeswap = (totalswap - usedswap);
803 #endif
804         /* grab number of processes */
805 #if defined(__OpenBSD__)
806         mib[0] = CTL_KERN;
807         mib[1] = KERN_NPROCS;
808         len = sizeof(nprocs);
809         sysctl(mib, 2, &nprocs, &len, NULL, 0);
810 #endif
811 #endif
812
813         ast_cli(a->fd, "\nSystem Statistics\n");
814         ast_cli(a->fd, "-----------------\n");
815         ast_cli(a->fd, "  System Uptime:             %ld hours\n", uptime);
816         ast_cli(a->fd, "  Total RAM:                 %" PRIu64 " KiB\n", physmem / 1024);
817         ast_cli(a->fd, "  Free RAM:                  %" PRIu64 " KiB\n", freeram);
818 #if defined(HAVE_SYSINFO)
819         ast_cli(a->fd, "  Buffer RAM:                %" PRIu64 " KiB\n", ((uint64_t) sys_info.bufferram * sys_info.mem_unit) / 1024);
820 #endif
821 #if defined(HAVE_SYSINFO) || defined(HAVE_SWAPCTL)
822         ast_cli(a->fd, "  Total Swap Space:          %d KiB\n", totalswap);
823         ast_cli(a->fd, "  Free Swap Space:           %" PRIu64 " KiB\n\n", freeswap);
824 #endif
825         ast_cli(a->fd, "  Number of Processes:       %d \n\n", nprocs);
826         return CLI_SUCCESS;
827 }
828 #endif
829
830 struct profile_entry {
831         const char *name;
832         uint64_t        scale;  /* if non-zero, values are scaled by this */
833         int64_t mark;
834         int64_t value;
835         int64_t events;
836 };
837
838 struct profile_data {
839         int entries;
840         int max_size;
841         struct profile_entry e[0];
842 };
843
844 static struct profile_data *prof_data;
845 #endif /* ! LOW_MEMORY */
846
847 /*! \brief allocates a counter with a given name and scale.
848  * \return Returns the identifier of the counter.
849  */
850 int ast_add_profile(const char *name, uint64_t scale)
851 {
852 #if !defined(LOW_MEMORY)
853         int l = sizeof(struct profile_data);
854         int n = 10;     /* default entries */
855
856         if (prof_data == NULL) {
857                 prof_data = ast_calloc(1, l + n*sizeof(struct profile_entry));
858                 if (prof_data == NULL)
859                         return -1;
860                 prof_data->entries = 0;
861                 prof_data->max_size = n;
862         }
863         if (prof_data->entries >= prof_data->max_size) {
864                 void *p;
865                 n = prof_data->max_size + 20;
866                 p = ast_realloc(prof_data, l + n*sizeof(struct profile_entry));
867                 if (p == NULL)
868                         return -1;
869                 prof_data = p;
870                 prof_data->max_size = n;
871         }
872         n = prof_data->entries++;
873         prof_data->e[n].name = ast_strdup(name);
874         prof_data->e[n].value = 0;
875         prof_data->e[n].events = 0;
876         prof_data->e[n].mark = 0;
877         prof_data->e[n].scale = scale;
878         return n;
879 #else /* if defined(LOW_MEMORY) */
880         return 0;
881 #endif
882 }
883
884 int64_t ast_profile(int i, int64_t delta)
885 {
886 #if !defined(LOW_MEMORY)
887         if (!prof_data || i < 0 || i > prof_data->entries)      /* invalid index */
888                 return 0;
889         if (prof_data->e[i].scale > 1)
890                 delta /= prof_data->e[i].scale;
891         prof_data->e[i].value += delta;
892         prof_data->e[i].events++;
893         return prof_data->e[i].value;
894 #else /* if defined(LOW_MEMORY) */
895         return 0;
896 #endif
897 }
898
899 #if !defined(LOW_MEMORY)
900 /* The RDTSC instruction was introduced on the Pentium processor and is not
901  * implemented on certain clones, like the Cyrix 586. Hence, the previous
902  * expectation of __i386__ was in error. */
903 #if defined ( __i686__) && (defined(__FreeBSD__) || defined(linux))
904 #if defined(__FreeBSD__)
905 #include <machine/cpufunc.h>
906 #elif defined(linux)
907 static __inline uint64_t
908 rdtsc(void)
909 {
910         uint64_t rv;
911
912         __asm __volatile(".byte 0x0f, 0x31" : "=A" (rv));
913         return (rv);
914 }
915 #endif
916 #else   /* supply a dummy function on other platforms */
917 static __inline uint64_t
918 rdtsc(void)
919 {
920         return 0;
921 }
922 #endif
923 #endif /* ! LOW_MEMORY */
924
925 int64_t ast_mark(int i, int startstop)
926 {
927 #if !defined(LOW_MEMORY)
928         if (!prof_data || i < 0 || i > prof_data->entries) /* invalid index */
929                 return 0;
930         if (startstop == 1)
931                 prof_data->e[i].mark = rdtsc();
932         else {
933                 prof_data->e[i].mark = (rdtsc() - prof_data->e[i].mark);
934                 if (prof_data->e[i].scale > 1)
935                         prof_data->e[i].mark /= prof_data->e[i].scale;
936                 prof_data->e[i].value += prof_data->e[i].mark;
937                 prof_data->e[i].events++;
938         }
939         return prof_data->e[i].mark;
940 #else /* if defined(LOW_MEMORY) */
941         return 0;
942 #endif
943 }
944
945 #if !defined(LOW_MEMORY)
946 #define DEFINE_PROFILE_MIN_MAX_VALUES min = 0; \
947         max = prof_data->entries;\
948         if  (a->argc > 3) { /* specific entries */ \
949                 if (isdigit(a->argv[3][0])) { \
950                         min = atoi(a->argv[3]); \
951                         if (a->argc == 5 && strcmp(a->argv[4], "-")) \
952                                 max = atoi(a->argv[4]); \
953                 } else \
954                         search = a->argv[3]; \
955         } \
956         if (max > prof_data->entries) \
957                 max = prof_data->entries;
958
959 static char *handle_show_profile(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
960 {
961         int i, min, max;
962         const char *search = NULL;
963         switch (cmd) {
964         case CLI_INIT:
965                 e->command = "core show profile";
966                 e->usage = "Usage: core show profile\n"
967                            "       show profile information";
968                 return NULL;
969         case CLI_GENERATE:
970                 return NULL;
971         }
972
973         if (prof_data == NULL)
974                 return 0;
975
976         DEFINE_PROFILE_MIN_MAX_VALUES;
977         ast_cli(a->fd, "profile values (%d, allocated %d)\n-------------------\n",
978                 prof_data->entries, prof_data->max_size);
979         ast_cli(a->fd, "%6s   %8s  %10s %12s %12s  %s\n", "ID", "Scale", "Events",
980                         "Value", "Average", "Name");
981         for (i = min; i < max; i++) {
982                 struct profile_entry *entry = &prof_data->e[i];
983                 if (!search || strstr(entry->name, search))
984                     ast_cli(a->fd, "%6d: [%8ld] %10ld %12lld %12lld  %s\n",
985                         i,
986                         (long)entry->scale,
987                         (long)entry->events, (long long)entry->value,
988                         (long long)(entry->events ? entry->value / entry->events : entry->value),
989                         entry->name);
990         }
991         return CLI_SUCCESS;
992 }
993
994 static char *handle_clear_profile(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
995 {
996         int i, min, max;
997         const char *search = NULL;
998         switch (cmd) {
999         case CLI_INIT:
1000                 e->command = "core clear profile";
1001                 e->usage = "Usage: core clear profile\n"
1002                            "       clear profile information";
1003                 return NULL;
1004         case CLI_GENERATE:
1005                 return NULL;
1006         }
1007
1008         if (prof_data == NULL)
1009                 return 0;
1010
1011         DEFINE_PROFILE_MIN_MAX_VALUES;
1012         for (i= min; i < max; i++) {
1013                 if (!search || strstr(prof_data->e[i].name, search)) {
1014                         prof_data->e[i].value = 0;
1015                         prof_data->e[i].events = 0;
1016                 }
1017         }
1018         return CLI_SUCCESS;
1019 }
1020 #undef DEFINE_PROFILE_MIN_MAX_VALUES
1021
1022 #endif /* ! LOW_MEMORY */
1023
1024 int ast_pbx_uuid_get(char *pbx_uuid, int length)
1025 {
1026         return ast_db_get("pbx", "UUID", pbx_uuid, length);
1027 }
1028
1029 static void publish_fully_booted(void)
1030 {
1031         RAII_VAR(struct ast_json *, json_object, NULL, ast_json_unref);
1032         int uptime = 0;
1033         int lastreloaded = 0;
1034         struct timeval tmp;
1035         struct timeval curtime = ast_tvnow();
1036
1037         if (ast_startuptime.tv_sec) {
1038                 tmp = ast_tvsub(curtime, ast_startuptime);
1039                 uptime = (int) tmp.tv_sec;
1040         }
1041
1042         if (ast_lastreloadtime.tv_sec) {
1043                 tmp = ast_tvsub(curtime, ast_lastreloadtime);
1044                 lastreloaded = (int) tmp.tv_sec;
1045         }
1046
1047         json_object = ast_json_pack("{s: s, s: i, s: i}",
1048                         "Status", "Fully Booted",
1049                         "Uptime", uptime,
1050                         "LastReload", lastreloaded);
1051         ast_manager_publish_event("FullyBooted", EVENT_FLAG_SYSTEM, json_object);
1052 }
1053
1054 static void ast_run_atexits(int run_cleanups)
1055 {
1056         struct ast_atexit *ae;
1057
1058         AST_LIST_LOCK(&atexits);
1059         while ((ae = AST_LIST_REMOVE_HEAD(&atexits, list))) {
1060                 if (ae->func && (!ae->is_cleanup || run_cleanups)) {
1061                         ae->func();
1062                 }
1063                 ast_free(ae);
1064         }
1065         AST_LIST_UNLOCK(&atexits);
1066 }
1067
1068 static void __ast_unregister_atexit(void (*func)(void))
1069 {
1070         struct ast_atexit *ae;
1071
1072         AST_LIST_TRAVERSE_SAFE_BEGIN(&atexits, ae, list) {
1073                 if (ae->func == func) {
1074                         AST_LIST_REMOVE_CURRENT(list);
1075                         ast_free(ae);
1076                         break;
1077                 }
1078         }
1079         AST_LIST_TRAVERSE_SAFE_END;
1080 }
1081
1082 static int register_atexit(void (*func)(void), int is_cleanup)
1083 {
1084         struct ast_atexit *ae;
1085
1086         ae = ast_calloc(1, sizeof(*ae));
1087         if (!ae) {
1088                 return -1;
1089         }
1090         ae->func = func;
1091         ae->is_cleanup = is_cleanup;
1092
1093         AST_LIST_LOCK(&atexits);
1094         __ast_unregister_atexit(func);
1095         AST_LIST_INSERT_HEAD(&atexits, ae, list);
1096         AST_LIST_UNLOCK(&atexits);
1097
1098         return 0;
1099 }
1100
1101 int ast_register_atexit(void (*func)(void))
1102 {
1103         return register_atexit(func, 0);
1104 }
1105
1106 int ast_register_cleanup(void (*func)(void))
1107 {
1108         return register_atexit(func, 1);
1109 }
1110
1111 void ast_unregister_atexit(void (*func)(void))
1112 {
1113         AST_LIST_LOCK(&atexits);
1114         __ast_unregister_atexit(func);
1115         AST_LIST_UNLOCK(&atexits);
1116 }
1117
1118 /* Sending commands from consoles back to the daemon requires a terminating NULL */
1119 static int fdsend(int fd, const char *s)
1120 {
1121         return write(fd, s, strlen(s) + 1);
1122 }
1123
1124 /* Sending messages from the daemon back to the display requires _excluding_ the terminating NULL */
1125 static int fdprint(int fd, const char *s)
1126 {
1127         return write(fd, s, strlen(s));
1128 }
1129
1130 /*! \brief NULL handler so we can collect the child exit status */
1131 static void _null_sig_handler(int sig)
1132 {
1133 }
1134
1135 static struct sigaction null_sig_handler = {
1136         .sa_handler = _null_sig_handler,
1137         .sa_flags = SA_RESTART,
1138 };
1139
1140 static struct sigaction ignore_sig_handler = {
1141         .sa_handler = SIG_IGN,
1142 };
1143
1144 AST_MUTEX_DEFINE_STATIC(safe_system_lock);
1145 /*! \brief Keep track of how many threads are currently trying to wait*() on
1146  *  a child process
1147  */
1148 static unsigned int safe_system_level = 0;
1149 static struct sigaction safe_system_prev_handler;
1150
1151 void ast_replace_sigchld(void)
1152 {
1153         unsigned int level;
1154
1155         ast_mutex_lock(&safe_system_lock);
1156         level = safe_system_level++;
1157
1158         /* only replace the handler if it has not already been done */
1159         if (level == 0) {
1160                 sigaction(SIGCHLD, &null_sig_handler, &safe_system_prev_handler);
1161         }
1162
1163         ast_mutex_unlock(&safe_system_lock);
1164 }
1165
1166 void ast_unreplace_sigchld(void)
1167 {
1168         unsigned int level;
1169
1170         ast_mutex_lock(&safe_system_lock);
1171         level = --safe_system_level;
1172
1173         /* only restore the handler if we are the last one */
1174         if (level == 0) {
1175                 sigaction(SIGCHLD, &safe_system_prev_handler, NULL);
1176         }
1177
1178         ast_mutex_unlock(&safe_system_lock);
1179 }
1180
1181 /*! \brief fork and perform other preparations for spawning applications */
1182 static pid_t safe_exec_prep(int dualfork)
1183 {
1184         pid_t pid;
1185
1186 #if defined(HAVE_WORKING_FORK) || defined(HAVE_WORKING_VFORK)
1187         ast_replace_sigchld();
1188
1189 #ifdef HAVE_WORKING_FORK
1190         pid = fork();
1191 #else
1192         pid = vfork();
1193 #endif
1194
1195         if (pid == 0) {
1196 #ifdef HAVE_CAP
1197                 cap_t cap = cap_from_text("cap_net_admin-eip");
1198
1199                 if (cap_set_proc(cap)) {
1200                         /* Careful with order! Logging cannot happen after we close FDs */
1201                         ast_log(LOG_WARNING, "Unable to remove capabilities.\n");
1202                 }
1203                 cap_free(cap);
1204 #endif
1205 #ifdef HAVE_WORKING_FORK
1206                 if (ast_opt_high_priority) {
1207                         ast_set_priority(0);
1208                 }
1209                 /* Close file descriptors and launch system command */
1210                 ast_close_fds_above_n(STDERR_FILENO);
1211 #endif
1212                 if (dualfork) {
1213 #ifdef HAVE_WORKING_FORK
1214                         pid = fork();
1215 #else
1216                         pid = vfork();
1217 #endif
1218                         if (pid < 0) {
1219                                 /* Second fork failed. */
1220                                 /* No logger available. */
1221                                 _exit(1);
1222                         }
1223
1224                         if (pid > 0) {
1225                                 /* This is the first fork, exit so the reaper finishes right away. */
1226                                 _exit(0);
1227                         }
1228
1229                         /* This is the second fork.  The first fork will exit immediately so
1230                          * Asterisk doesn't have to wait for completion.
1231                          * ast_safe_system("cmd &") would run in the background, but the '&'
1232                          * cannot be added with ast_safe_execvp, so we have to double fork.
1233                          */
1234                 }
1235         }
1236
1237         if (pid < 0) {
1238                 ast_log(LOG_WARNING, "Fork failed: %s\n", strerror(errno));
1239         }
1240 #else
1241         ast_log(LOG_WARNING, "Fork failed: %s\n", strerror(ENOTSUP));
1242         pid = -1;
1243 #endif
1244
1245         return pid;
1246 }
1247
1248 /*! \brief wait for spawned application to complete and unreplace sigchld */
1249 static int safe_exec_wait(pid_t pid)
1250 {
1251         int res = -1;
1252
1253 #if defined(HAVE_WORKING_FORK) || defined(HAVE_WORKING_VFORK)
1254         if (pid > 0) {
1255                 for (;;) {
1256                         int status;
1257
1258                         res = waitpid(pid, &status, 0);
1259                         if (res > -1) {
1260                                 res = WIFEXITED(status) ? WEXITSTATUS(status) : -1;
1261                                 break;
1262                         }
1263                         if (errno != EINTR) {
1264                                 break;
1265                         }
1266                 }
1267         }
1268
1269         ast_unreplace_sigchld();
1270 #endif
1271
1272         return res;
1273 }
1274
1275 int ast_safe_execvp(int dualfork, const char *file, char *const argv[])
1276 {
1277         pid_t pid = safe_exec_prep(dualfork);
1278
1279         if (pid == 0) {
1280                 execvp(file, argv);
1281                 _exit(1);
1282                 /* noreturn from _exit */
1283         }
1284
1285         return safe_exec_wait(pid);
1286 }
1287
1288 int ast_safe_system(const char *s)
1289 {
1290         pid_t pid = safe_exec_prep(0);
1291
1292         if (pid == 0) {
1293                 execl("/bin/sh", "/bin/sh", "-c", s, (char *) NULL);
1294                 _exit(1);
1295                 /* noreturn from _exit */
1296         }
1297
1298         return safe_exec_wait(pid);
1299 }
1300
1301 /*!
1302  * \brief enable or disable a logging level to a specified console
1303  */
1304 void ast_console_toggle_loglevel(int fd, int level, int state)
1305 {
1306         int x;
1307
1308         if (level >= NUMLOGLEVELS) {
1309                 level = NUMLOGLEVELS - 1;
1310         }
1311
1312         for (x = 0;x < AST_MAX_CONNECTS; x++) {
1313                 if (fd == consoles[x].fd) {
1314                         /*
1315                          * Since the logging occurs when levels are false, set to
1316                          * flipped iinput because this function accepts 0 as off and 1 as on
1317                          */
1318                         consoles[x].levels[level] = state ? 0 : 1;
1319                         return;
1320                 }
1321         }
1322 }
1323
1324 /*!
1325  * \brief mute or unmute a console from logging
1326  */
1327 void ast_console_toggle_mute(int fd, int silent)
1328 {
1329         int x;
1330         for (x = 0;x < AST_MAX_CONNECTS; x++) {
1331                 if (fd == consoles[x].fd) {
1332                         if (consoles[x].mute) {
1333                                 consoles[x].mute = 0;
1334                                 if (!silent)
1335                                         ast_cli(fd, "Console is not muted anymore.\n");
1336                         } else {
1337                                 consoles[x].mute = 1;
1338                                 if (!silent)
1339                                         ast_cli(fd, "Console is muted.\n");
1340                         }
1341                         return;
1342                 }
1343         }
1344         ast_cli(fd, "Couldn't find remote console.\n");
1345 }
1346
1347 /*!
1348  * \brief log the string to all attached network console clients
1349  */
1350 static void ast_network_puts_mutable(const char *string, int level, int sublevel)
1351 {
1352         int x;
1353
1354         for (x = 0; x < AST_MAX_CONNECTS; ++x) {
1355                 if (consoles[x].fd < 0
1356                         || consoles[x].mute
1357                         || consoles[x].levels[level]
1358                         || (level == __LOG_VERBOSE && consoles[x].option_verbose < sublevel)) {
1359                         continue;
1360                 }
1361                 fdprint(consoles[x].p[1], string);
1362         }
1363 }
1364
1365 /*!
1366  * \brief log the string to the root console, and all attached
1367  * network console clients
1368  */
1369 void ast_console_puts_mutable(const char *string, int level)
1370 {
1371         ast_console_puts_mutable_full(string, level, 0);
1372 }
1373
1374 static int console_print(const char *s);
1375
1376 void ast_console_puts_mutable_full(const char *message, int level, int sublevel)
1377 {
1378         /* Send to the root console */
1379         console_print(message);
1380
1381         /* Wake up a poll()ing console */
1382         if (ast_opt_console && consolethread != AST_PTHREADT_NULL) {
1383                 pthread_kill(consolethread, SIGURG);
1384         }
1385
1386         /* Send to any network console clients */
1387         ast_network_puts_mutable(message, level, sublevel);
1388 }
1389
1390 /*!
1391  * \brief write the string to all attached console clients
1392  */
1393 static void ast_network_puts(const char *string)
1394 {
1395         int x;
1396
1397         for (x = 0; x < AST_MAX_CONNECTS; ++x) {
1398                 if (consoles[x].fd < 0) {
1399                         continue;
1400                 }
1401                 fdprint(consoles[x].p[1], string);
1402         }
1403 }
1404
1405 /*!
1406  * \brief write the string to the root console, and all attached
1407  * network console clients
1408  */
1409 void ast_console_puts(const char *string)
1410 {
1411         /* Send to the root console */
1412         fputs(string, stdout);
1413         fflush(stdout);
1414
1415         /* Send to any network console clients */
1416         ast_network_puts(string);
1417 }
1418
1419 static pthread_t lthread;
1420
1421 /*!
1422  * \brief read() function supporting the reception of user credentials.
1423  *
1424  * \param fd Socket file descriptor.
1425  * \param buffer Receive buffer.
1426  * \param size 'buffer' size.
1427  * \param con Console structure to set received credentials
1428  * \retval -1 on error
1429  * \retval the number of bytes received on success.
1430  */
1431 static int read_credentials(int fd, char *buffer, size_t size, struct console *con)
1432 {
1433 #if defined(SO_PEERCRED)
1434 #ifdef HAVE_STRUCT_SOCKPEERCRED_UID
1435 #define HAVE_STRUCT_UCRED_UID
1436         struct sockpeercred cred;
1437 #else
1438         struct ucred cred;
1439 #endif
1440         socklen_t len = sizeof(cred);
1441 #endif
1442 #if defined(HAVE_GETPEEREID)
1443         uid_t uid;
1444         gid_t gid;
1445 #else
1446         int uid, gid;
1447 #endif
1448         int result;
1449
1450         result = read(fd, buffer, size);
1451         if (result < 0) {
1452                 return result;
1453         }
1454
1455 #if defined(SO_PEERCRED) && (defined(HAVE_STRUCT_UCRED_UID) || defined(HAVE_STRUCT_UCRED_CR_UID))
1456         if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &cred, &len)) {
1457                 return result;
1458         }
1459 #if defined(HAVE_STRUCT_UCRED_UID)
1460         uid = cred.uid;
1461         gid = cred.gid;
1462 #else /* defined(HAVE_STRUCT_UCRED_CR_UID) */
1463         uid = cred.cr_uid;
1464         gid = cred.cr_gid;
1465 #endif /* defined(HAVE_STRUCT_UCRED_UID) */
1466
1467 #elif defined(HAVE_GETPEEREID)
1468         if (getpeereid(fd, &uid, &gid)) {
1469                 return result;
1470         }
1471 #else
1472         return result;
1473 #endif
1474         con->uid = uid;
1475         con->gid = gid;
1476
1477         return result;
1478 }
1479
1480 /* This is the thread running the remote console on the main process. */
1481 static void *netconsole(void *vconsole)
1482 {
1483         struct console *con = vconsole;
1484         char hostname[MAXHOSTNAMELEN] = "";
1485         char inbuf[512];
1486         char outbuf[512];
1487         const char * const end_buf = inbuf + sizeof(inbuf);
1488         char *start_read = inbuf;
1489         int res;
1490         struct pollfd fds[2];
1491
1492         if (gethostname(hostname, sizeof(hostname)-1))
1493                 ast_copy_string(hostname, "<Unknown>", sizeof(hostname));
1494         snprintf(outbuf, sizeof(outbuf), "%s/%ld/%s\n", hostname, (long)ast_mainpid, ast_get_version());
1495         fdprint(con->fd, outbuf);
1496         ast_verb_console_register(&con->option_verbose);
1497         for (;;) {
1498                 fds[0].fd = con->fd;
1499                 fds[0].events = POLLIN;
1500                 fds[0].revents = 0;
1501                 fds[1].fd = con->p[0];
1502                 fds[1].events = POLLIN;
1503                 fds[1].revents = 0;
1504
1505                 res = ast_poll(fds, 2, -1);
1506                 if (res < 0) {
1507                         if (errno != EINTR)
1508                                 ast_log(LOG_WARNING, "poll returned < 0: %s\n", strerror(errno));
1509                         continue;
1510                 }
1511                 if (fds[0].revents) {
1512                         int cmds_read, bytes_read;
1513                         if ((bytes_read = read_credentials(con->fd, start_read, end_buf - start_read, con)) < 1) {
1514                                 break;
1515                         }
1516                         /* XXX This will only work if it is the first command, and I'm not sure fixing it is worth the effort. */
1517                         if (strncmp(inbuf, "cli quit after ", 15) == 0) {
1518                                 ast_cli_command_multiple_full(con->uid, con->gid, con->fd, bytes_read - 15, inbuf + 15);
1519                                 break;
1520                         }
1521                         /* ast_cli_command_multiple_full will only process individual commands terminated by a
1522                          * NULL and not trailing partial commands. */
1523                         if (!(cmds_read = ast_cli_command_multiple_full(con->uid, con->gid, con->fd, bytes_read + start_read - inbuf, inbuf))) {
1524                                 /* No commands were read. We either have a short read on the first command
1525                                  * with space left, or a command that is too long */
1526                                 if (start_read + bytes_read < end_buf) {
1527                                         start_read += bytes_read;
1528                                 } else {
1529                                         ast_log(LOG_ERROR, "Command too long! Skipping\n");
1530                                         start_read = inbuf;
1531                                 }
1532                                 continue;
1533                         }
1534                         if (start_read[bytes_read - 1] == '\0') {
1535                                 /* The read ended on a command boundary, start reading again at the head of inbuf */
1536                                 start_read = inbuf;
1537                                 continue;
1538                         }
1539                         /* If we get this far, we have left over characters that have not been processed.
1540                          * Advance to the character after the last command read by ast_cli_command_multiple_full.
1541                          * We are guaranteed to have at least cmds_read NULLs */
1542                         while (cmds_read-- && (start_read = strchr(start_read, '\0'))) {
1543                                 start_read++;
1544                         }
1545                         memmove(inbuf, start_read, end_buf - start_read);
1546                         start_read = end_buf - start_read + inbuf;
1547                 }
1548                 if (fds[1].revents) {
1549                         res = read_credentials(con->p[0], outbuf, sizeof(outbuf), con);
1550                         if (res < 1) {
1551                                 ast_log(LOG_ERROR, "read returned %d\n", res);
1552                                 break;
1553                         }
1554                         res = write(con->fd, outbuf, res);
1555                         if (res < 1)
1556                                 break;
1557                 }
1558         }
1559         ast_verb_console_unregister();
1560         if (!ast_opt_hide_connect) {
1561                 ast_verb(3, "Remote UNIX connection disconnected\n");
1562         }
1563         close(con->fd);
1564         close(con->p[0]);
1565         close(con->p[1]);
1566         con->fd = -1;
1567
1568         return NULL;
1569 }
1570
1571 static void *listener(void *unused)
1572 {
1573         struct sockaddr_un sunaddr;
1574         int s;
1575         socklen_t len;
1576         int x;
1577         int poll_result;
1578         struct pollfd fds[1];
1579
1580         for (;;) {
1581                 if (ast_socket < 0) {
1582                         return NULL;
1583                 }
1584                 fds[0].fd = ast_socket;
1585                 fds[0].events = POLLIN;
1586                 poll_result = ast_poll(fds, 1, -1);
1587                 pthread_testcancel();
1588                 if (poll_result < 0) {
1589                         if (errno != EINTR) {
1590                                 ast_log(LOG_WARNING, "poll returned error: %s\n", strerror(errno));
1591                         }
1592                         continue;
1593                 }
1594                 len = sizeof(sunaddr);
1595                 s = accept(ast_socket, (struct sockaddr *)&sunaddr, &len);
1596                 if (s < 0) {
1597                         if (errno != EINTR)
1598                                 ast_log(LOG_WARNING, "Accept returned %d: %s\n", s, strerror(errno));
1599                 } else {
1600 #if defined(SO_PASSCRED)
1601                         int sckopt = 1;
1602                         /* turn on socket credentials passing. */
1603                         if (setsockopt(s, SOL_SOCKET, SO_PASSCRED, &sckopt, sizeof(sckopt)) < 0) {
1604                                 ast_log(LOG_WARNING, "Unable to turn on socket credentials passing\n");
1605                                 close(s);
1606                         } else
1607 #endif
1608                         {
1609                                 for (x = 0; x < AST_MAX_CONNECTS; x++) {
1610                                         if (consoles[x].fd >= 0) {
1611                                                 continue;
1612                                         }
1613                                         if (socketpair(AF_LOCAL, SOCK_STREAM, 0, consoles[x].p)) {
1614                                                 ast_log(LOG_ERROR, "Unable to create pipe: %s\n", strerror(errno));
1615                                                 fdprint(s, "Server failed to create pipe\n");
1616                                                 close(s);
1617                                                 break;
1618                                         }
1619                                         ast_fd_set_flags(consoles[x].p[1], O_NONBLOCK);
1620                                         consoles[x].mute = 1; /* Default is muted, we will un-mute if necessary */
1621                                         /* Default uid and gid to -2, so then in cli.c/cli_has_permissions() we will be able
1622                                            to know if the user didn't send the credentials. */
1623                                         consoles[x].uid = -2;
1624                                         consoles[x].gid = -2;
1625                                         /* Server default of remote console verbosity level is OFF. */
1626                                         consoles[x].option_verbose = 0;
1627                                         consoles[x].fd = s;
1628                                         if (ast_pthread_create_detached_background(&consoles[x].t, NULL, netconsole, &consoles[x])) {
1629                                                 consoles[x].fd = -1;
1630                                                 ast_log(LOG_ERROR, "Unable to spawn thread to handle connection: %s\n", strerror(errno));
1631                                                 close(consoles[x].p[0]);
1632                                                 close(consoles[x].p[1]);
1633                                                 fdprint(s, "Server failed to spawn thread\n");
1634                                                 close(s);
1635                                         }
1636                                         break;
1637                                 }
1638                                 if (x >= AST_MAX_CONNECTS) {
1639                                         fdprint(s, "No more connections allowed\n");
1640                                         ast_log(LOG_WARNING, "No more connections allowed\n");
1641                                         close(s);
1642                                 } else if ((consoles[x].fd > -1) && (!ast_opt_hide_connect)) {
1643                                         ast_verb(3, "Remote UNIX connection\n");
1644                                 }
1645                         }
1646                 }
1647         }
1648         return NULL;
1649 }
1650
1651 static int ast_makesocket(void)
1652 {
1653         struct sockaddr_un sunaddr;
1654         int res;
1655         int x;
1656         uid_t uid = -1;
1657         gid_t gid = -1;
1658
1659         for (x = 0; x < AST_MAX_CONNECTS; x++) {
1660                 consoles[x].fd = -1;
1661         }
1662
1663         if (ast_socket_is_sd) {
1664                 ast_socket = ast_sd_get_fd_un(SOCK_STREAM, ast_config_AST_SOCKET);
1665
1666                 goto start_lthread;
1667         }
1668
1669         unlink(ast_config_AST_SOCKET);
1670         ast_socket = socket(PF_LOCAL, SOCK_STREAM, 0);
1671         if (ast_socket < 0) {
1672                 ast_log(LOG_WARNING, "Unable to create control socket: %s\n", strerror(errno));
1673                 return -1;
1674         }
1675         memset(&sunaddr, 0, sizeof(sunaddr));
1676         sunaddr.sun_family = AF_LOCAL;
1677         ast_copy_string(sunaddr.sun_path, ast_config_AST_SOCKET, sizeof(sunaddr.sun_path));
1678         res = bind(ast_socket, (struct sockaddr *)&sunaddr, sizeof(sunaddr));
1679         if (res) {
1680                 ast_log(LOG_WARNING, "Unable to bind socket to %s: %s\n", ast_config_AST_SOCKET, strerror(errno));
1681                 close(ast_socket);
1682                 ast_socket = -1;
1683                 return -1;
1684         }
1685         res = listen(ast_socket, 2);
1686         if (res < 0) {
1687                 ast_log(LOG_WARNING, "Unable to listen on socket %s: %s\n", ast_config_AST_SOCKET, strerror(errno));
1688                 close(ast_socket);
1689                 ast_socket = -1;
1690                 return -1;
1691         }
1692
1693 start_lthread:
1694         if (ast_pthread_create_background(&lthread, NULL, listener, NULL)) {
1695                 ast_log(LOG_WARNING, "Unable to create listener thread.\n");
1696                 close(ast_socket);
1697                 return -1;
1698         }
1699
1700         if (ast_socket_is_sd) {
1701                 /* owner/group/permissions are set by systemd, we might not even have access
1702                  * to socket file so leave it alone */
1703                 return 0;
1704         }
1705
1706         if (!ast_strlen_zero(ast_config_AST_CTL_OWNER)) {
1707                 struct passwd *pw;
1708                 if ((pw = getpwnam(ast_config_AST_CTL_OWNER)) == NULL)
1709                         ast_log(LOG_WARNING, "Unable to find uid of user %s\n", ast_config_AST_CTL_OWNER);
1710                 else
1711                         uid = pw->pw_uid;
1712         }
1713
1714         if (!ast_strlen_zero(ast_config_AST_CTL_GROUP)) {
1715                 struct group *grp;
1716                 if ((grp = getgrnam(ast_config_AST_CTL_GROUP)) == NULL)
1717                         ast_log(LOG_WARNING, "Unable to find gid of group %s\n", ast_config_AST_CTL_GROUP);
1718                 else
1719                         gid = grp->gr_gid;
1720         }
1721
1722         if (chown(ast_config_AST_SOCKET, uid, gid) < 0)
1723                 ast_log(LOG_WARNING, "Unable to change ownership of %s: %s\n", ast_config_AST_SOCKET, strerror(errno));
1724
1725         if (!ast_strlen_zero(ast_config_AST_CTL_PERMISSIONS)) {
1726                 unsigned int p1;
1727                 mode_t p;
1728                 sscanf(ast_config_AST_CTL_PERMISSIONS, "%30o", &p1);
1729                 p = p1;
1730                 if ((chmod(ast_config_AST_SOCKET, p)) < 0)
1731                         ast_log(LOG_WARNING, "Unable to change file permissions of %s: %s\n", ast_config_AST_SOCKET, strerror(errno));
1732         }
1733
1734         return 0;
1735 }
1736
1737 static int ast_tryconnect(void)
1738 {
1739         struct sockaddr_un sunaddr;
1740         int res;
1741         ast_consock = socket(PF_LOCAL, SOCK_STREAM, 0);
1742         if (ast_consock < 0) {
1743                 fprintf(stderr, "Unable to create socket: %s\n", strerror(errno));
1744                 return 0;
1745         }
1746         memset(&sunaddr, 0, sizeof(sunaddr));
1747         sunaddr.sun_family = AF_LOCAL;
1748         ast_copy_string(sunaddr.sun_path, ast_config_AST_SOCKET, sizeof(sunaddr.sun_path));
1749         res = connect(ast_consock, (struct sockaddr *)&sunaddr, sizeof(sunaddr));
1750         if (res) {
1751                 close(ast_consock);
1752                 ast_consock = -1;
1753                 return 0;
1754         } else
1755                 return 1;
1756 }
1757
1758 /*! \brief Urgent handler
1759  *
1760  * Called by soft_hangup to interrupt the poll, read, or other
1761  * system call.  We don't actually need to do anything though.
1762  * Remember: Cannot EVER ast_log from within a signal handler
1763  */
1764 static void _urg_handler(int num)
1765 {
1766         return;
1767 }
1768
1769 static struct sigaction urg_handler = {
1770         .sa_handler = _urg_handler,
1771 };
1772
1773 static void _hup_handler(int num)
1774 {
1775         int save_errno = errno;
1776         printf("Received HUP signal -- Reloading configs\n");
1777         if (restartnow)
1778                 execvp(_argv[0], _argv);
1779         sig_flags.need_reload = 1;
1780         if (ast_alertpipe_write(sig_alert_pipe)) {
1781                 fprintf(stderr, "hup_handler: write() failed: %s\n", strerror(errno));
1782         }
1783         errno = save_errno;
1784 }
1785
1786 static struct sigaction hup_handler = {
1787         .sa_handler = _hup_handler,
1788         .sa_flags = SA_RESTART,
1789 };
1790
1791 static void _child_handler(int sig)
1792 {
1793         /* Must not ever ast_log or ast_verbose within signal handler */
1794         int n, status, save_errno = errno;
1795
1796         /*
1797          * Reap all dead children -- not just one
1798          */
1799         for (n = 0; waitpid(-1, &status, WNOHANG) > 0; n++)
1800                 ;
1801         if (n == 0 && option_debug)
1802                 printf("Huh?  Child handler, but nobody there?\n");
1803         errno = save_errno;
1804 }
1805
1806 static struct sigaction child_handler = {
1807         .sa_handler = _child_handler,
1808         .sa_flags = SA_RESTART,
1809 };
1810
1811 /*! \brief Set maximum open files */
1812 static void set_ulimit(int value)
1813 {
1814         struct rlimit l = {0, 0};
1815
1816         if (value <= 0) {
1817                 ast_log(LOG_WARNING, "Unable to change max files open to invalid value %i\n",value);
1818                 return;
1819         }
1820
1821         l.rlim_cur = value;
1822         l.rlim_max = value;
1823
1824         if (setrlimit(RLIMIT_NOFILE, &l)) {
1825                 ast_log(LOG_WARNING, "Unable to disable core size resource limit: %s\n",strerror(errno));
1826                 return;
1827         }
1828
1829         ast_log(LOG_NOTICE, "Setting max files open to %d\n",value);
1830
1831         return;
1832 }
1833
1834 /*! \brief Set an X-term or screen title */
1835 static void set_title(char *text)
1836 {
1837         if (getenv("TERM") && strstr(getenv("TERM"), "xterm"))
1838                 fprintf(stdout, "\033]2;%s\007", text);
1839 }
1840
1841 static void set_icon(char *text)
1842 {
1843         if (getenv("TERM") && strstr(getenv("TERM"), "xterm"))
1844                 fprintf(stdout, "\033]1;%s\007", text);
1845 }
1846
1847 /*! \brief Check whether we were set to high(er) priority. */
1848 static int has_priority(void)
1849 {
1850         /* Neither of these calls should fail with these arguments. */
1851 #ifdef __linux__
1852         /* For SCHED_OTHER, SCHED_BATCH and SCHED_IDLE, this will return
1853          * 0. For the realtime priorities SCHED_RR and SCHED_FIFO, it
1854          * will return something >= 1. */
1855         return sched_getscheduler(0);
1856 #else
1857         /* getpriority() can return a value in -20..19 (or even -INF..20)
1858          * where negative numbers are high priority. We don't bother
1859          * checking errno. If the query fails and it returns -1, we'll
1860          * assume that we're running at high prio; a safe assumption
1861          * that will enable the resource starvation monitor (canary)
1862          * just in case. */
1863         return (getpriority(PRIO_PROCESS, 0) < 0);
1864 #endif
1865 }
1866
1867 /*! \brief Set priority on all known threads. */
1868 static int set_priority_all(int pri)
1869 {
1870 #if !defined(__linux__)
1871         /* The non-linux version updates the entire process prio. */
1872         return ast_set_priority(pri);
1873 #elif defined(LOW_MEMORY)
1874         ast_log(LOG_WARNING, "Unable to enumerate all threads to update priority\n");
1875         return ast_set_priority(pri);
1876 #else
1877         struct thread_list_t *cur;
1878         struct sched_param sched;
1879         char const *policy_str;
1880         int policy;
1881
1882         memset(&sched, 0, sizeof(sched));
1883         if (pri) {
1884                 policy = SCHED_RR;
1885                 policy_str = "realtime";
1886                 sched.sched_priority = 10;
1887         } else {
1888                 policy = SCHED_OTHER;
1889                 policy_str = "regular";
1890                 sched.sched_priority = 0;
1891         }
1892         if (sched_setscheduler(getpid(), policy, &sched)) {
1893                 ast_log(LOG_WARNING, "Unable to set %s thread priority on main thread\n", policy_str);
1894                 return -1;
1895         }
1896         ast_verb(1, "Setting %s thread priority on all threads\n", policy_str);
1897         AST_RWLIST_RDLOCK(&thread_list);
1898         AST_RWLIST_TRAVERSE(&thread_list, cur, list) {
1899                 /* Don't care about the return value. It should work. */
1900                 sched_setscheduler(cur->lwp, policy, &sched);
1901         }
1902         AST_RWLIST_UNLOCK(&thread_list);
1903         return 0;
1904 #endif
1905 }
1906
1907 /*! \brief We set ourselves to a high priority, that we might pre-empt
1908  * everything else.  If your PBX has heavy activity on it, this is a
1909  * good thing.
1910  */
1911 int ast_set_priority(int pri)
1912 {
1913         struct sched_param sched;
1914         memset(&sched, 0, sizeof(sched));
1915 #ifdef __linux__
1916         if (pri) {
1917                 sched.sched_priority = 10;
1918                 if (sched_setscheduler(0, SCHED_RR, &sched)) {
1919                         ast_log(LOG_WARNING, "Unable to set high priority\n");
1920                         return -1;
1921                 } else
1922                         ast_verb(1, "Set to realtime thread\n");
1923         } else {
1924                 sched.sched_priority = 0;
1925                 /* According to the manpage, these parameters can never fail. */
1926                 sched_setscheduler(0, SCHED_OTHER, &sched);
1927         }
1928 #else
1929         if (pri) {
1930                 if (setpriority(PRIO_PROCESS, 0, -10) == -1) {
1931                         ast_log(LOG_WARNING, "Unable to set high priority\n");
1932                         return -1;
1933                 } else
1934                         ast_verb(1, "Set to high priority\n");
1935         } else {
1936                 /* According to the manpage, these parameters can never fail. */
1937                 setpriority(PRIO_PROCESS, 0, 0);
1938         }
1939 #endif
1940         return 0;
1941 }
1942
1943 int ast_shutdown_final(void)
1944 {
1945         return shuttingdown == SHUTTING_DOWN_FINAL;
1946 }
1947
1948 int ast_shutting_down(void)
1949 {
1950         return shutdown_pending;
1951 }
1952
1953 int ast_cancel_shutdown(void)
1954 {
1955         int shutdown_aborted = 0;
1956
1957         ast_mutex_lock(&safe_system_lock);
1958         if (shuttingdown >= SHUTDOWN_FAST) {
1959                 shuttingdown = NOT_SHUTTING_DOWN;
1960                 shutdown_pending = 0;
1961                 shutdown_aborted = 1;
1962         }
1963         ast_mutex_unlock(&safe_system_lock);
1964         return shutdown_aborted;
1965 }
1966
1967 /*!
1968  * \internal
1969  * \brief Initiate system shutdown -- prevents new channels from being allocated.
1970  */
1971 static void ast_begin_shutdown(void)
1972 {
1973         ast_mutex_lock(&safe_system_lock);
1974         if (shuttingdown != NOT_SHUTTING_DOWN) {
1975                 shutdown_pending = 1;
1976         }
1977         ast_mutex_unlock(&safe_system_lock);
1978 }
1979
1980 static int can_safely_quit(shutdown_nice_t niceness, int restart);
1981 static void really_quit(int num, shutdown_nice_t niceness, int restart);
1982
1983 static void quit_handler(int num, shutdown_nice_t niceness, int restart)
1984 {
1985         if (can_safely_quit(niceness, restart)) {
1986                 really_quit(num, niceness, restart);
1987                 /* No one gets here. */
1988         }
1989         /* It wasn't our time. */
1990 }
1991
1992 #define SHUTDOWN_TIMEOUT        15      /* Seconds */
1993
1994 /*!
1995  * \internal
1996  * \brief Wait for all channels to die, a timeout, or shutdown cancelled.
1997  * \since 13.3.0
1998  *
1999  * \param niceness Shutdown niceness in effect
2000  * \param seconds Number of seconds to wait or less than zero if indefinitely.
2001  *
2002  * \retval zero if waiting wasn't necessary.  We were idle.
2003  * \retval non-zero if we had to wait.
2004  */
2005 static int wait_for_channels_to_die(shutdown_nice_t niceness, int seconds)
2006 {
2007         time_t start;
2008         time_t now;
2009         int waited = 0;
2010
2011         time(&start);
2012         for (;;) {
2013                 if (!ast_undestroyed_channels() || shuttingdown != niceness) {
2014                         break;
2015                 }
2016                 if (seconds < 0) {
2017                         /* No timeout so just poll every second */
2018                         sleep(1);
2019                 } else {
2020                         time(&now);
2021
2022                         /* Wait up to the given seconds for all channels to go away */
2023                         if (seconds < (now - start)) {
2024                                 break;
2025                         }
2026
2027                         /* Sleep 1/10 of a second */
2028                         usleep(100000);
2029                 }
2030                 waited = 1;
2031         }
2032         return waited;
2033 }
2034
2035 static int can_safely_quit(shutdown_nice_t niceness, int restart)
2036 {
2037         int waited = 0;
2038
2039         /* Check if someone else isn't already doing this. */
2040         ast_mutex_lock(&safe_system_lock);
2041         if (shuttingdown != NOT_SHUTTING_DOWN && niceness >= shuttingdown) {
2042                 /* Already in progress and other request was less nice. */
2043                 ast_mutex_unlock(&safe_system_lock);
2044                 ast_verbose("Ignoring asterisk %s request, already in progress.\n", restart ? "restart" : "shutdown");
2045                 return 0;
2046         }
2047         shuttingdown = niceness;
2048         ast_mutex_unlock(&safe_system_lock);
2049
2050         /* Try to get as many CDRs as possible submitted to the backend engines
2051          * (if in batch mode). really_quit happens to call it again when running
2052          * the atexit handlers, otherwise this would be a bit early. */
2053         ast_cdr_engine_term();
2054
2055         /*
2056          * Shutdown the message queue for the technology agnostic message channel.
2057          * This has to occur before we pause shutdown pending ast_undestroyed_channels.
2058          *
2059          * XXX This is not reversed on shutdown cancel.
2060          */
2061         ast_msg_shutdown();
2062
2063         if (niceness == SHUTDOWN_NORMAL) {
2064                 /* Begin shutdown routine, hanging up active channels */
2065                 ast_begin_shutdown();
2066                 if (ast_opt_console) {
2067                         ast_verb(0, "Beginning asterisk %s....\n", restart ? "restart" : "shutdown");
2068                 }
2069                 ast_softhangup_all();
2070                 waited |= wait_for_channels_to_die(niceness, SHUTDOWN_TIMEOUT);
2071         } else if (niceness >= SHUTDOWN_NICE) {
2072                 if (niceness != SHUTDOWN_REALLY_NICE) {
2073                         ast_begin_shutdown();
2074                 }
2075                 if (ast_opt_console) {
2076                         ast_verb(0, "Waiting for inactivity to perform %s...\n", restart ? "restart" : "halt");
2077                 }
2078                 waited |= wait_for_channels_to_die(niceness, -1);
2079         }
2080
2081         /* Re-acquire lock and check if someone changed the niceness, in which
2082          * case someone else has taken over the shutdown.
2083          */
2084         ast_mutex_lock(&safe_system_lock);
2085         if (shuttingdown != niceness) {
2086                 if (shuttingdown == NOT_SHUTTING_DOWN && ast_opt_console) {
2087                         ast_verb(0, "Asterisk %s cancelled.\n", restart ? "restart" : "shutdown");
2088                 }
2089                 ast_mutex_unlock(&safe_system_lock);
2090                 return 0;
2091         }
2092
2093         if (niceness >= SHUTDOWN_REALLY_NICE) {
2094                 shuttingdown = SHUTTING_DOWN;
2095                 ast_mutex_unlock(&safe_system_lock);
2096
2097                 /* No more Mr. Nice guy.  We are committed to shutting down now. */
2098                 ast_begin_shutdown();
2099                 ast_softhangup_all();
2100                 waited |= wait_for_channels_to_die(SHUTTING_DOWN, SHUTDOWN_TIMEOUT);
2101
2102                 ast_mutex_lock(&safe_system_lock);
2103         }
2104         shuttingdown = SHUTTING_DOWN_FINAL;
2105         ast_mutex_unlock(&safe_system_lock);
2106
2107         if (niceness >= SHUTDOWN_NORMAL && waited) {
2108                 /*
2109                  * We were not idle.  Give things in progress a chance to
2110                  * recognize the final shutdown phase.
2111                  */
2112                 sleep(1);
2113         }
2114         return 1;
2115 }
2116
2117 /*! Called when exiting is certain. */
2118 static void really_quit(int num, shutdown_nice_t niceness, int restart)
2119 {
2120         int active_channels;
2121         struct ast_json *json_object = NULL;
2122         int run_cleanups = niceness >= SHUTDOWN_NICE;
2123
2124         if (run_cleanups && modules_shutdown()) {
2125                 ast_verb(0, "Some modules could not be unloaded, switching to fast shutdown\n");
2126                 run_cleanups = 0;
2127         }
2128
2129         if (!restart) {
2130                 ast_sd_notify("STOPPING=1");
2131         }
2132         if (ast_opt_console || (ast_opt_remote && !ast_opt_exec)) {
2133                 ast_el_write_default_histfile();
2134                 if (consolethread == AST_PTHREADT_NULL || consolethread == pthread_self()) {
2135                         /* Only end if we are the consolethread, otherwise there's a race with that thread. */
2136                         if (el != NULL) {
2137                                 el_end(el);
2138                         }
2139                         if (el_hist != NULL) {
2140                                 history_end(el_hist);
2141                         }
2142                 } else if (mon_sig_flags == pthread_self()) {
2143                         if (consolethread != AST_PTHREADT_NULL) {
2144                                 pthread_kill(consolethread, SIGURG);
2145                         }
2146                 }
2147         }
2148         active_channels = ast_active_channels();
2149         /* Don't publish messages if we're a remote console - we won't have all of the Stasis
2150          * topics or message types
2151          */
2152         if (!ast_opt_remote) {
2153                 json_object = ast_json_pack("{s: s, s: s}",
2154                                 "Shutdown", active_channels ? "Uncleanly" : "Cleanly",
2155                                 "Restart", restart ? "True" : "False");
2156                 ast_manager_publish_event("Shutdown", EVENT_FLAG_SYSTEM, json_object);
2157                 ast_json_unref(json_object);
2158                 json_object = NULL;
2159         }
2160         ast_verb(0, "Asterisk %s ending (%d).\n",
2161                 active_channels ? "uncleanly" : "cleanly", num);
2162
2163         ast_verb(0, "Executing last minute cleanups\n");
2164         ast_run_atexits(run_cleanups);
2165
2166         ast_debug(1, "Asterisk ending (%d).\n", num);
2167         if (ast_socket > -1) {
2168                 pthread_cancel(lthread);
2169                 close(ast_socket);
2170                 ast_socket = -1;
2171                 if (!ast_socket_is_sd) {
2172                         unlink(ast_config_AST_SOCKET);
2173                 }
2174                 pthread_kill(lthread, SIGURG);
2175                 pthread_join(lthread, NULL);
2176         }
2177         if (ast_consock > -1)
2178                 close(ast_consock);
2179         if (!ast_opt_remote)
2180                 unlink(ast_config_AST_PID);
2181         ast_alertpipe_close(sig_alert_pipe);
2182         printf("%s", term_quit());
2183         if (restart) {
2184                 int i;
2185                 ast_verb(0, "Preparing for Asterisk restart...\n");
2186                 /* Mark all FD's for closing on exec */
2187                 for (i = 3; i < 32768; i++) {
2188                         fcntl(i, F_SETFD, FD_CLOEXEC);
2189                 }
2190                 ast_verb(0, "Asterisk is now restarting...\n");
2191                 restartnow = 1;
2192
2193                 /* close logger */
2194                 close_logger();
2195                 clean_time_zones();
2196
2197                 /* If there is a consolethread running send it a SIGHUP
2198                    so it can execvp, otherwise we can do it ourselves */
2199                 if ((consolethread != AST_PTHREADT_NULL) && (consolethread != pthread_self())) {
2200                         pthread_kill(consolethread, SIGHUP);
2201                         /* Give the signal handler some time to complete */
2202                         sleep(2);
2203                 } else
2204                         execvp(_argv[0], _argv);
2205
2206         } else {
2207                 /* close logger */
2208                 close_logger();
2209                 clean_time_zones();
2210         }
2211
2212         exit(0);
2213 }
2214
2215 static void __quit_handler(int num)
2216 {
2217         sig_flags.need_quit = 1;
2218         if (ast_alertpipe_write(sig_alert_pipe)) {
2219                 fprintf(stderr, "quit_handler: write() failed: %s\n", strerror(errno));
2220         }
2221         /* There is no need to restore the signal handler here, since the app
2222          * is going to exit */
2223 }
2224
2225 static void __remote_quit_handler(int num)
2226 {
2227         sig_flags.need_quit = 1;
2228 }
2229
2230 static void set_header(char *outbuf, int maxout, char level)
2231 {
2232         const char *cmp;
2233         char date[40];
2234
2235         switch (level) {
2236         case 0: cmp = NULL;
2237                 break;
2238         case 1: cmp = VERBOSE_PREFIX_1;
2239                 break;
2240         case 2: cmp = VERBOSE_PREFIX_2;
2241                 break;
2242         case 3: cmp = VERBOSE_PREFIX_3;
2243                 break;
2244         default: cmp = VERBOSE_PREFIX_4;
2245                 break;
2246         }
2247
2248         if (ast_opt_timestamp) {
2249                 struct ast_tm tm;
2250                 struct timeval now = ast_tvnow();
2251                 ast_localtime(&now, &tm, NULL);
2252                 ast_strftime(date, sizeof(date), ast_logger_get_dateformat(), &tm);
2253         }
2254
2255         snprintf(outbuf, maxout, "%s%s%s%s%s%s",
2256                 ast_opt_timestamp ? "[" : "",
2257                 ast_opt_timestamp ? date : "",
2258                 ast_opt_timestamp ? "] " : "",
2259                 cmp ? ast_term_color(COLOR_GRAY, 0) : "",
2260                 cmp ? cmp : "",
2261                 cmp ? ast_term_reset() : "");
2262 }
2263
2264 struct console_state_data {
2265         char verbose_line_level;
2266 };
2267
2268 static int console_state_init(void *ptr)
2269 {
2270         struct console_state_data *state = ptr;
2271         state->verbose_line_level = 0;
2272         return 0;
2273 }
2274
2275 AST_THREADSTORAGE_CUSTOM(console_state, console_state_init, ast_free_ptr);
2276
2277 static int console_print(const char *s)
2278 {
2279         struct console_state_data *state =
2280                 ast_threadstorage_get(&console_state, sizeof(*state));
2281
2282         char prefix[80];
2283         const char *c;
2284         int num, res = 0;
2285         unsigned int newline;
2286
2287         do {
2288                 if (VERBOSE_HASMAGIC(s)) {
2289
2290                         /* always use the given line's level, otherwise
2291                            we'll use the last line's level */
2292                         state->verbose_line_level = VERBOSE_MAGIC2LEVEL(s);
2293
2294                         /* move past magic */
2295                         s++;
2296
2297                         set_header(prefix, sizeof(prefix), state->verbose_line_level);
2298                 } else {
2299                         *prefix = '\0';
2300                 }
2301                 c = s;
2302
2303                 /* for a given line separate on verbose magic, newline, and eol */
2304                 if ((s = strchr(c, '\n'))) {
2305                         ++s;
2306                         newline = 1;
2307                 } else {
2308                         s = strchr(c, '\0');
2309                         newline = 0;
2310                 }
2311
2312                 /* check if we should write this line after calculating begin/end
2313                    so we process the case of a higher level line embedded within
2314                    two lower level lines */
2315                 if (state->verbose_line_level > option_verbose) {
2316                         continue;
2317                 }
2318
2319                 if (!ast_strlen_zero(prefix)) {
2320                         fputs(prefix, stdout);
2321                 }
2322
2323                 num = s - c;
2324                 if (fwrite(c, sizeof(char), num, stdout) < num) {
2325                         break;
2326                 }
2327
2328                 if (!res) {
2329                         /* if at least some info has been written
2330                            we'll want to return true */
2331                         res = 1;
2332                 }
2333         } while (*s);
2334
2335         if (newline) {
2336                 /* if ending on a newline then reset last level to zero
2337                     since what follows may be not be logging output */
2338                 state->verbose_line_level = 0;
2339         }
2340
2341         if (res) {
2342                 fflush(stdout);
2343         }
2344
2345         return res;
2346 }
2347
2348 static int ast_all_zeros(const char *s)
2349 {
2350         while (*s) {
2351                 if (*s > 32)
2352                         return 0;
2353                 s++;
2354         }
2355         return 1;
2356 }
2357
2358 /* This is the main console CLI command handler.  Run by the main() thread. */
2359 static void consolehandler(const char *s)
2360 {
2361         printf("%s", term_end());
2362         fflush(stdout);
2363
2364         /* Called when readline data is available */
2365         if (!ast_all_zeros(s))
2366                 ast_el_add_history(s);
2367         /* The real handler for bang */
2368         if (s[0] == '!') {
2369                 if (s[1])
2370                         ast_safe_system(s+1);
2371                 else
2372                         ast_safe_system(getenv("SHELL") ? getenv("SHELL") : "/bin/sh");
2373         } else
2374                 ast_cli_command(STDOUT_FILENO, s);
2375 }
2376
2377 static int remoteconsolehandler(const char *s)
2378 {
2379         int ret = 0;
2380
2381         /* Called when readline data is available */
2382         if (!ast_all_zeros(s))
2383                 ast_el_add_history(s);
2384
2385         while (isspace(*s)) {
2386                 s++;
2387         }
2388
2389         /* The real handler for bang */
2390         if (s[0] == '!') {
2391                 if (s[1])
2392                         ast_safe_system(s+1);
2393                 else
2394                         ast_safe_system(getenv("SHELL") ? getenv("SHELL") : "/bin/sh");
2395                 ret = 1;
2396         } else if ((strncasecmp(s, "quit", 4) == 0 || strncasecmp(s, "exit", 4) == 0) &&
2397             (s[4] == '\0' || isspace(s[4]))) {
2398                 quit_handler(0, SHUTDOWN_FAST, 0);
2399                 ret = 1;
2400         }
2401
2402         return ret;
2403 }
2404
2405 static char *handle_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2406 {
2407         switch (cmd) {
2408         case CLI_INIT:
2409                 e->command = "core show version";
2410                 e->usage =
2411                         "Usage: core show version\n"
2412                         "       Shows Asterisk version information.\n";
2413                 return NULL;
2414         case CLI_GENERATE:
2415                 return NULL;
2416         }
2417
2418         if (a->argc != 3)
2419                 return CLI_SHOWUSAGE;
2420         ast_cli(a->fd, "Asterisk %s built by %s @ %s on a %s running %s on %s\n",
2421                 ast_get_version(), ast_build_user, ast_build_hostname,
2422                 ast_build_machine, ast_build_os, ast_build_date);
2423         return CLI_SUCCESS;
2424 }
2425
2426 static char *handle_stop_now(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2427 {
2428         switch (cmd) {
2429         case CLI_INIT:
2430                 e->command = "core stop now";
2431                 e->usage =
2432                         "Usage: core stop now\n"
2433                         "       Shuts down a running Asterisk immediately, hanging up all active calls .\n";
2434                 ast_cli_allow_at_shutdown(e);
2435                 return NULL;
2436         case CLI_GENERATE:
2437                 return NULL;
2438         }
2439
2440         if (a->argc != e->args)
2441                 return CLI_SHOWUSAGE;
2442         quit_handler(0, SHUTDOWN_NORMAL, 0 /* not restart */);
2443         return CLI_SUCCESS;
2444 }
2445
2446 static char *handle_stop_gracefully(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2447 {
2448         switch (cmd) {
2449         case CLI_INIT:
2450                 e->command = "core stop gracefully";
2451                 e->usage =
2452                         "Usage: core stop gracefully\n"
2453                         "       Causes Asterisk to not accept new calls, and exit when all\n"
2454                         "       active calls have terminated normally.\n";
2455                 ast_cli_allow_at_shutdown(e);
2456                 return NULL;
2457         case CLI_GENERATE:
2458                 return NULL;
2459         }
2460
2461         if (a->argc != e->args)
2462                 return CLI_SHOWUSAGE;
2463         quit_handler(0, SHUTDOWN_NICE, 0 /* no restart */);
2464         return CLI_SUCCESS;
2465 }
2466
2467 static char *handle_stop_when_convenient(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2468 {
2469         switch (cmd) {
2470         case CLI_INIT:
2471                 e->command = "core stop when convenient";
2472                 e->usage =
2473                         "Usage: core stop when convenient\n"
2474                         "       Causes Asterisk to perform a shutdown when all active calls have ended.\n";
2475                 ast_cli_allow_at_shutdown(e);
2476                 return NULL;
2477         case CLI_GENERATE:
2478                 return NULL;
2479         }
2480
2481         if (a->argc != e->args)
2482                 return CLI_SHOWUSAGE;
2483         ast_cli(a->fd, "Waiting for inactivity to perform halt\n");
2484         quit_handler(0, SHUTDOWN_REALLY_NICE, 0 /* don't restart */);
2485         return CLI_SUCCESS;
2486 }
2487
2488 static char *handle_restart_now(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2489 {
2490         switch (cmd) {
2491         case CLI_INIT:
2492                 e->command = "core restart now";
2493                 e->usage =
2494                         "Usage: core restart now\n"
2495                         "       Causes Asterisk to hangup all calls and exec() itself performing a cold\n"
2496                         "       restart.\n";
2497                 ast_cli_allow_at_shutdown(e);
2498                 return NULL;
2499         case CLI_GENERATE:
2500                 return NULL;
2501         }
2502
2503         if (a->argc != e->args)
2504                 return CLI_SHOWUSAGE;
2505         quit_handler(0, SHUTDOWN_NORMAL, 1 /* restart */);
2506         return CLI_SUCCESS;
2507 }
2508
2509 static char *handle_restart_gracefully(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2510 {
2511         switch (cmd) {
2512         case CLI_INIT:
2513                 e->command = "core restart gracefully";
2514                 e->usage =
2515                         "Usage: core restart gracefully\n"
2516                         "       Causes Asterisk to stop accepting new calls and exec() itself performing a cold\n"
2517                         "       restart when all active calls have ended.\n";
2518                 ast_cli_allow_at_shutdown(e);
2519                 return NULL;
2520         case CLI_GENERATE:
2521                 return NULL;
2522         }
2523
2524         if (a->argc != e->args)
2525                 return CLI_SHOWUSAGE;
2526         quit_handler(0, SHUTDOWN_NICE, 1 /* restart */);
2527         return CLI_SUCCESS;
2528 }
2529
2530 static char *handle_restart_when_convenient(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2531 {
2532         switch (cmd) {
2533         case CLI_INIT:
2534                 e->command = "core restart when convenient";
2535                 e->usage =
2536                         "Usage: core restart when convenient\n"
2537                         "       Causes Asterisk to perform a cold restart when all active calls have ended.\n";
2538                 ast_cli_allow_at_shutdown(e);
2539                 return NULL;
2540         case CLI_GENERATE:
2541                 return NULL;
2542         }
2543
2544         if (a->argc != e->args)
2545                 return CLI_SHOWUSAGE;
2546         ast_cli(a->fd, "Waiting for inactivity to perform restart\n");
2547         quit_handler(0, SHUTDOWN_REALLY_NICE, 1 /* restart */);
2548         return CLI_SUCCESS;
2549 }
2550
2551 static char *handle_abort_shutdown(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2552 {
2553         switch (cmd) {
2554         case CLI_INIT:
2555                 e->command = "core abort shutdown";
2556                 e->usage =
2557                         "Usage: core abort shutdown\n"
2558                         "       Causes Asterisk to abort an executing shutdown or restart, and resume normal\n"
2559                         "       call operations.\n";
2560                 ast_cli_allow_at_shutdown(e);
2561                 return NULL;
2562         case CLI_GENERATE:
2563                 return NULL;
2564         }
2565
2566         if (a->argc != e->args)
2567                 return CLI_SHOWUSAGE;
2568
2569         ast_cancel_shutdown();
2570
2571         return CLI_SUCCESS;
2572 }
2573
2574 static char *handle_bang(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2575 {
2576         switch (cmd) {
2577         case CLI_INIT:
2578                 e->command = "!";
2579                 e->usage =
2580                         "Usage: !<command>\n"
2581                         "       Executes a given shell command\n";
2582                 return NULL;
2583         case CLI_GENERATE:
2584                 return NULL;
2585         }
2586
2587         return CLI_SUCCESS;
2588 }
2589 static const char warranty_lines[] = {
2590         "\n"
2591         "                           NO WARRANTY\n"
2592         "\n"
2593         "BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY\n"
2594         "FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN\n"
2595         "OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES\n"
2596         "PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED\n"
2597         "OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\n"
2598         "MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS\n"
2599         "TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE\n"
2600         "PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,\n"
2601         "REPAIR OR CORRECTION.\n"
2602         "\n"
2603         "IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\n"
2604         "WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR\n"
2605         "REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,\n"
2606         "INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING\n"
2607         "OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED\n"
2608         "TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY\n"
2609         "YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER\n"
2610         "PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE\n"
2611         "POSSIBILITY OF SUCH DAMAGES.\n"
2612 };
2613
2614 static char *show_warranty(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2615 {
2616         switch (cmd) {
2617         case CLI_INIT:
2618                 e->command = "core show warranty";
2619                 e->usage =
2620                         "Usage: core show warranty\n"
2621                         "       Shows the warranty (if any) for this copy of Asterisk.\n";
2622                 return NULL;
2623         case CLI_GENERATE:
2624                 return NULL;
2625         }
2626
2627         ast_cli(a->fd, "%s", warranty_lines);
2628
2629         return CLI_SUCCESS;
2630 }
2631
2632 static const char license_lines[] = {
2633         "\n"
2634         "This program is free software; you can redistribute it and/or modify\n"
2635         "it under the terms of the GNU General Public License version 2 as\n"
2636         "published by the Free Software Foundation.\n"
2637         "\n"
2638         "This program also contains components licensed under other licenses.\n"
2639         "They include:\n"
2640         "\n"
2641         "This program is distributed in the hope that it will be useful,\n"
2642         "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
2643         "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
2644         "GNU General Public License for more details.\n"
2645         "\n"
2646         "You should have received a copy of the GNU General Public License\n"
2647         "along with this program; if not, write to the Free Software\n"
2648         "Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n"
2649 };
2650
2651 static char *show_license(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2652 {
2653         switch (cmd) {
2654         case CLI_INIT:
2655                 e->command = "core show license";
2656                 e->usage =
2657                         "Usage: core show license\n"
2658                         "       Shows the license(s) for this copy of Asterisk.\n";
2659                 return NULL;
2660         case CLI_GENERATE:
2661                 return NULL;
2662         }
2663
2664         ast_cli(a->fd, "%s", license_lines);
2665
2666         return CLI_SUCCESS;
2667 }
2668
2669 #define ASTERISK_PROMPT "*CLI> "
2670
2671 /*!
2672  * \brief Shutdown Asterisk CLI commands.
2673  *
2674  * \note These CLI commands cannot be unregistered at shutdown
2675  * because one of them is likely the reason for the shutdown.
2676  * The CLI generates a warning if a command is in-use when it is
2677  * unregistered.
2678  */
2679 static struct ast_cli_entry cli_asterisk_shutdown[] = {
2680         AST_CLI_DEFINE(handle_stop_now, "Shut down Asterisk immediately"),
2681         AST_CLI_DEFINE(handle_stop_gracefully, "Gracefully shut down Asterisk"),
2682         AST_CLI_DEFINE(handle_stop_when_convenient, "Shut down Asterisk at empty call volume"),
2683         AST_CLI_DEFINE(handle_restart_now, "Restart Asterisk immediately"),
2684         AST_CLI_DEFINE(handle_restart_gracefully, "Restart Asterisk gracefully"),
2685         AST_CLI_DEFINE(handle_restart_when_convenient, "Restart Asterisk at empty call volume"),
2686 };
2687
2688 static struct ast_cli_entry cli_asterisk[] = {
2689         AST_CLI_DEFINE(handle_abort_shutdown, "Cancel a running shutdown"),
2690         AST_CLI_DEFINE(show_warranty, "Show the warranty (if any) for this copy of Asterisk"),
2691         AST_CLI_DEFINE(show_license, "Show the license(s) for this copy of Asterisk"),
2692         AST_CLI_DEFINE(handle_version, "Display version info"),
2693         AST_CLI_DEFINE(handle_bang, "Execute a shell command"),
2694 #if !defined(LOW_MEMORY)
2695         AST_CLI_DEFINE(handle_show_threads, "Show running threads"),
2696 #if defined(HAVE_SYSINFO) || defined(HAVE_SYSCTL)
2697         AST_CLI_DEFINE(handle_show_sysinfo, "Show System Information"),
2698 #endif
2699         AST_CLI_DEFINE(handle_show_profile, "Display profiling info"),
2700         AST_CLI_DEFINE(handle_show_settings, "Show some core settings"),
2701         AST_CLI_DEFINE(handle_clear_profile, "Clear profiling info"),
2702 #endif /* ! LOW_MEMORY */
2703 };
2704
2705 static void send_rasterisk_connect_commands(void)
2706 {
2707         char buf[80];
2708
2709         /*
2710          * Tell the server asterisk instance about the verbose level
2711          * initially desired.
2712          */
2713         if (option_verbose) {
2714                 snprintf(buf, sizeof(buf), "core set verbose atleast %d silent", option_verbose);
2715                 fdsend(ast_consock, buf);
2716         }
2717
2718         if (option_debug) {
2719                 snprintf(buf, sizeof(buf), "core set debug atleast %d", option_debug);
2720                 fdsend(ast_consock, buf);
2721         }
2722
2723         /* Leave verbose filtering to the server. */
2724         option_verbose = INT_MAX;
2725
2726         if (!ast_opt_mute) {
2727                 fdsend(ast_consock, "logger mute silent");
2728         } else {
2729                 printf("log and verbose output currently muted ('logger mute' to unmute)\n");
2730         }
2731 }
2732
2733 #ifdef HAVE_LIBEDIT_IS_UNICODE
2734 static int ast_el_read_char(EditLine *editline, wchar_t *cp)
2735 #else
2736 static int ast_el_read_char(EditLine *editline, char *cp)
2737 #endif
2738 {
2739         int num_read = 0;
2740         int lastpos = 0;
2741         struct pollfd fds[2];
2742         int res;
2743         int max;
2744 #define EL_BUF_SIZE 512
2745         char buf[EL_BUF_SIZE];
2746
2747         for (;;) {
2748                 max = 1;
2749                 fds[0].fd = ast_consock;
2750                 fds[0].events = POLLIN;
2751                 if (!ast_opt_exec) {
2752                         fds[1].fd = STDIN_FILENO;
2753                         fds[1].events = POLLIN;
2754                         max++;
2755                 }
2756                 res = ast_poll(fds, max, -1);
2757                 if (res < 0) {
2758                         if (sig_flags.need_quit || sig_flags.need_quit_handler)
2759                                 break;
2760                         if (errno == EINTR)
2761                                 continue;
2762                         fprintf(stderr, "poll failed: %s\n", strerror(errno));
2763                         break;
2764                 }
2765
2766                 if (!ast_opt_exec && fds[1].revents) {
2767                         char c = '\0';
2768                         num_read = read(STDIN_FILENO, &c, 1);
2769                         if (num_read < 1) {
2770                                 break;
2771                         } else {
2772 #ifdef  HAVE_LIBEDIT_IS_UNICODE
2773                                 *cp = btowc(c);
2774 #else
2775                                 *cp = c;
2776 #endif
2777                                 return (num_read);
2778                         }
2779                 }
2780                 if (fds[0].revents) {
2781                         res = read(ast_consock, buf, sizeof(buf) - 1);
2782                         /* if the remote side disappears exit */
2783                         if (res < 1) {
2784                                 fprintf(stderr, "\nDisconnected from Asterisk server\n");
2785                                 if (!ast_opt_reconnect) {
2786                                         quit_handler(0, SHUTDOWN_FAST, 0);
2787                                 } else {
2788                                         int tries;
2789                                         int reconnects_per_second = 20;
2790                                         fprintf(stderr, "Attempting to reconnect for 30 seconds\n");
2791                                         for (tries = 0; tries < 30 * reconnects_per_second; tries++) {
2792                                                 if (ast_tryconnect()) {
2793                                                         fprintf(stderr, "Reconnect succeeded after %.3f seconds\n", 1.0 / reconnects_per_second * tries);
2794                                                         printf("%s", term_quit());
2795                                                         WELCOME_MESSAGE;
2796                                                         send_rasterisk_connect_commands();
2797                                                         break;
2798                                                 } else
2799                                                         usleep(1000000 / reconnects_per_second);
2800                                         }
2801                                         if (tries >= 30 * reconnects_per_second) {
2802                                                 fprintf(stderr, "Failed to reconnect for 30 seconds.  Quitting.\n");
2803                                                 quit_handler(0, SHUTDOWN_FAST, 0);
2804                                         }
2805                                 }
2806                                 continue;
2807                         }
2808
2809                         buf[res] = '\0';
2810
2811                         /* Write over the CLI prompt */
2812                         if (!ast_opt_exec && !lastpos) {
2813                                 if (write(STDOUT_FILENO, "\r\e[0K", 5) < 0) {
2814                                 }
2815                         }
2816
2817                         console_print(buf);
2818
2819                         if ((res < EL_BUF_SIZE - 1) && ((buf[res-1] == '\n') || (res >= 2 && buf[res-2] == '\n'))) {
2820 #ifdef  HAVE_LIBEDIT_IS_UNICODE
2821                                 *cp = btowc(CC_REFRESH);
2822 #else
2823                                 *cp = CC_REFRESH;
2824 #endif
2825                                 return(1);
2826                         } else {
2827                                 lastpos = 1;
2828                         }
2829                 }
2830         }
2831
2832 #ifdef  HAVE_LIBEDIT_IS_UNICODE
2833         *cp = btowc('\0');
2834 #else
2835         *cp = '\0';
2836 #endif
2837
2838         return (0);
2839 }
2840
2841 static struct ast_str *prompt = NULL;
2842
2843 static char *cli_prompt(EditLine *editline)
2844 {
2845         char tmp[100];
2846         char *pfmt;
2847         int color_used = 0;
2848         static int cli_prompt_changes = 0;
2849         struct passwd *pw;
2850         struct group *gr;
2851
2852         if (prompt == NULL) {
2853                 prompt = ast_str_create(100);
2854         } else if (!cli_prompt_changes) {
2855                 return ast_str_buffer(prompt);
2856         } else {
2857                 ast_str_reset(prompt);
2858         }
2859
2860         if ((pfmt = getenv("ASTERISK_PROMPT"))) {
2861                 char *t = pfmt;
2862                 struct timeval ts = ast_tvnow();
2863                 while (*t != '\0') {
2864                         if (*t == '%') {
2865                                 char hostname[MAXHOSTNAMELEN] = "";
2866                                 int i, which;
2867                                 struct ast_tm tm = { 0, };
2868                                 int fgcolor = COLOR_WHITE, bgcolor = COLOR_BLACK;
2869
2870                                 t++;
2871                                 switch (*t) {
2872                                 case 'C': /* color */
2873                                         t++;
2874                                         if (sscanf(t, "%30d;%30d%n", &fgcolor, &bgcolor, &i) == 2) {
2875                                                 ast_term_color_code(&prompt, fgcolor, bgcolor);
2876                                                 t += i - 1;
2877                                         } else if (sscanf(t, "%30d%n", &fgcolor, &i) == 1) {
2878                                                 ast_term_color_code(&prompt, fgcolor, 0);
2879                                                 t += i - 1;
2880                                         }
2881
2882                                         /* If the color has been reset correctly, then there's no need to reset it later */
2883                                         color_used = ((fgcolor == COLOR_WHITE) && (bgcolor == COLOR_BLACK)) ? 0 : 1;
2884                                         break;
2885                                 case 'd': /* date */
2886                                         if (ast_localtime(&ts, &tm, NULL)) {
2887                                                 ast_strftime(tmp, sizeof(tmp), "%Y-%m-%d", &tm);
2888                                                 ast_str_append(&prompt, 0, "%s", tmp);
2889                                                 cli_prompt_changes++;
2890                                         }
2891                                         break;
2892                                 case 'g': /* group */
2893                                         if ((gr = getgrgid(getgid()))) {
2894                                                 ast_str_append(&prompt, 0, "%s", gr->gr_name);
2895                                         }
2896                                         break;
2897                                 case 'h': /* hostname */
2898                                         if (!gethostname(hostname, sizeof(hostname) - 1)) {
2899                                                 ast_str_append(&prompt, 0, "%s", hostname);
2900                                         } else {
2901                                                 ast_str_append(&prompt, 0, "%s", "localhost");
2902                                         }
2903                                         break;
2904                                 case 'H': /* short hostname */
2905                                         if (!gethostname(hostname, sizeof(hostname) - 1)) {
2906                                                 char *dotptr;
2907                                                 if ((dotptr = strchr(hostname, '.'))) {
2908                                                         *dotptr = '\0';
2909                                                 }
2910                                                 ast_str_append(&prompt, 0, "%s", hostname);
2911                                         } else {
2912                                                 ast_str_append(&prompt, 0, "%s", "localhost");
2913                                         }
2914                                         break;
2915 #ifdef HAVE_GETLOADAVG
2916                                 case 'l': /* load avg */
2917                                         t++;
2918                                         if (sscanf(t, "%30d", &which) == 1 && which > 0 && which <= 3) {
2919                                                 double list[3];
2920                                                 getloadavg(list, 3);
2921                                                 ast_str_append(&prompt, 0, "%.2f", list[which - 1]);
2922                                                 cli_prompt_changes++;
2923                                         }
2924                                         break;
2925 #endif
2926                                 case 's': /* Asterisk system name (from asterisk.conf) */
2927                                         ast_str_append(&prompt, 0, "%s", ast_config_AST_SYSTEM_NAME);
2928                                         break;
2929                                 case 't': /* time */
2930                                         if (ast_localtime(&ts, &tm, NULL)) {
2931                                                 ast_strftime(tmp, sizeof(tmp), "%H:%M:%S", &tm);
2932                                                 ast_str_append(&prompt, 0, "%s", tmp);
2933                                                 cli_prompt_changes++;
2934                                         }
2935                                         break;
2936                                 case 'u': /* username */
2937                                         if ((pw = getpwuid(getuid()))) {
2938                                                 ast_str_append(&prompt, 0, "%s", pw->pw_name);
2939                                         }
2940                                         break;
2941                                 case '#': /* process console or remote? */
2942                                         ast_str_append(&prompt, 0, "%c", ast_opt_remote ? '>' : '#');
2943                                         break;
2944                                 case '%': /* literal % */
2945                                         ast_str_append(&prompt, 0, "%c", '%');
2946                                         break;
2947                                 case '\0': /* % is last character - prevent bug */
2948                                         t--;
2949                                         break;
2950                                 }
2951                         } else {
2952                                 ast_str_append(&prompt, 0, "%c", *t);
2953                         }
2954                         t++;
2955                 }
2956                 if (color_used) {
2957                         /* Force colors back to normal at end */
2958                         ast_term_color_code(&prompt, 0, 0);
2959                 }
2960         } else {
2961                 ast_str_set(&prompt, 0, "%s%s",
2962                         remotehostname ? remotehostname : "",
2963                         ASTERISK_PROMPT);
2964         }
2965
2966         return ast_str_buffer(prompt);
2967 }
2968
2969 static struct ast_vector_string *ast_el_strtoarr(char *buf)
2970 {
2971         char *retstr;
2972         struct ast_vector_string *vec = ast_calloc(1, sizeof(*vec));
2973
2974         if (!vec) {
2975                 return NULL;
2976         }
2977
2978         while ((retstr = strsep(&buf, " "))) {
2979                 if (!strcmp(retstr, AST_CLI_COMPLETE_EOF)) {
2980                         break;
2981                 }
2982
2983                 retstr = ast_strdup(retstr);
2984                 if (!retstr || AST_VECTOR_APPEND(vec, retstr)) {
2985                         ast_free(retstr);
2986                         goto vector_cleanup;
2987                 }
2988         }
2989
2990         if (!AST_VECTOR_SIZE(vec)) {
2991                 goto vector_cleanup;
2992         }
2993
2994         return vec;
2995
2996 vector_cleanup:
2997         AST_VECTOR_CALLBACK_VOID(vec, ast_free);
2998         AST_VECTOR_PTR_FREE(vec);
2999
3000         return NULL;
3001 }
3002
3003 static void ast_cli_display_match_list(struct ast_vector_string *matches, int max)
3004 {
3005         int idx = 1;
3006         /* find out how many entries can be put on one line, with two spaces between strings */
3007         int limit = ast_get_termcols(STDOUT_FILENO) / (max + 2);
3008
3009         if (limit == 0) {
3010                 limit = 1;
3011         }
3012
3013         for (;;) {
3014                 int numoutputline;
3015
3016                 for (numoutputline = 0; numoutputline < limit && idx < AST_VECTOR_SIZE(matches); idx++) {
3017                         numoutputline++;
3018                         fprintf(stdout, "%-*s  ", max, AST_VECTOR_GET(matches, idx));
3019                 }
3020
3021                 if (!numoutputline) {
3022                         break;
3023                 }
3024
3025                 fprintf(stdout, "\n");
3026         }
3027 }
3028
3029
3030 static char *cli_complete(EditLine *editline, int ch)
3031 {
3032         int len = 0;
3033         char *ptr;
3034         struct ast_vector_string *matches;
3035         int retval = CC_ERROR;
3036         char savechr;
3037         int res;
3038
3039         LineInfo *lf = (LineInfo *)el_line(editline);
3040
3041         savechr = *(char *)lf->cursor;
3042         *(char *)lf->cursor = '\0';
3043         ptr = (char *)lf->cursor;
3044         if (ptr) {
3045                 while (ptr > lf->buffer) {
3046                         if (isspace(*ptr)) {
3047                                 ptr++;
3048                                 break;
3049                         }
3050                         ptr--;
3051                 }
3052         }
3053
3054         len = lf->cursor - ptr;
3055
3056         if (ast_opt_remote) {
3057 #define CMD_MATCHESARRAY "_COMMAND MATCHESARRAY \"%s\" \"%s\""
3058                 char *mbuf;
3059                 char *new_mbuf;
3060                 int mlen = 0;
3061                 int maxmbuf = ast_asprintf(&mbuf, CMD_MATCHESARRAY, lf->buffer, ptr);
3062
3063                 if (maxmbuf == -1) {
3064                         *((char *) lf->cursor) = savechr;
3065
3066                         return (char *)(CC_ERROR);
3067                 }
3068
3069                 fdsend(ast_consock, mbuf);
3070                 res = 0;
3071                 mlen = 0;
3072                 mbuf[0] = '\0';
3073
3074                 while (!strstr(mbuf, AST_CLI_COMPLETE_EOF) && res != -1) {
3075                         if (mlen + 1024 > maxmbuf) {
3076                                 /* Expand buffer to the next 1024 byte increment plus a NULL terminator. */
3077                                 maxmbuf = mlen + 1024;
3078                                 new_mbuf = ast_realloc(mbuf, maxmbuf + 1);
3079                                 if (!new_mbuf) {
3080                                         ast_free(mbuf);
3081                                         *((char *) lf->cursor) = savechr;
3082
3083                                         return (char *)(CC_ERROR);
3084                                 }
3085                                 mbuf = new_mbuf;
3086                         }
3087                         /* Only read 1024 bytes at a time */
3088                         res = read(ast_consock, mbuf + mlen, 1024);
3089                         if (res > 0) {
3090                                 mlen += res;
3091                                 mbuf[mlen] = '\0';
3092                         }
3093                 }
3094                 mbuf[mlen] = '\0';
3095
3096                 matches = ast_el_strtoarr(mbuf);
3097                 ast_free(mbuf);
3098         } else {
3099                 matches = ast_cli_completion_vector((char *)lf->buffer, ptr);
3100         }
3101
3102         if (matches) {
3103                 int i;
3104                 int maxlen, match_len;
3105                 const char *best_match = AST_VECTOR_GET(matches, 0);
3106
3107                 if (!ast_strlen_zero(best_match)) {
3108                         el_deletestr(editline, (int) len);
3109                         el_insertstr(editline, best_match);
3110                         retval = CC_REFRESH;
3111                 }
3112
3113                 if (AST_VECTOR_SIZE(matches) == 2) {
3114                         /* Found an exact match */
3115                         el_insertstr(editline, " ");
3116                         retval = CC_REFRESH;
3117                 } else {
3118                         /* Must be more than one match */
3119                         for (i = 1, maxlen = 0; i < AST_VECTOR_SIZE(matches); i++) {
3120                                 match_len = strlen(AST_VECTOR_GET(matches, i));
3121                                 if (match_len > maxlen) {
3122                                         maxlen = match_len;
3123                                 }
3124                         }
3125
3126                         fprintf(stdout, "\n");
3127                         ast_cli_display_match_list(matches, maxlen);
3128                         retval = CC_REDISPLAY;
3129                 }
3130                 AST_VECTOR_CALLBACK_VOID(matches, ast_free);
3131                 AST_VECTOR_PTR_FREE(matches);
3132         }
3133
3134         *((char *) lf->cursor) = savechr;
3135
3136         return (char *)(long)retval;
3137 }
3138
3139 static int ast_el_initialize(void)
3140 {
3141         HistEvent ev;
3142         char *editor, *editrc = getenv("EDITRC");
3143
3144         if (!(editor = getenv("AST_EDITMODE"))) {
3145                 if (!(editor = getenv("AST_EDITOR"))) {
3146                         editor = "emacs";
3147                 }
3148         }
3149
3150         if (el != NULL)
3151                 el_end(el);
3152         if (el_hist != NULL)
3153                 history_end(el_hist);
3154
3155         el = el_init("asterisk", stdin, stdout, stderr);
3156         el_set(el, EL_PROMPT, cli_prompt);
3157
3158         el_set(el, EL_EDITMODE, 1);
3159         el_set(el, EL_EDITOR, editor);
3160         el_hist = history_init();
3161         if (!el || !el_hist)
3162                 return -1;
3163
3164         /* setup history with 100 entries */
3165         history(el_hist, &ev, H_SETSIZE, 100);
3166
3167         el_set(el, EL_HIST, history, el_hist);
3168
3169         el_set(el, EL_ADDFN, "ed-complete", "Complete argument", cli_complete);
3170         /* Bind <tab> to command completion */
3171         el_set(el, EL_BIND, "^I", "ed-complete", NULL);
3172         /* Bind ? to command completion */
3173         el_set(el, EL_BIND, "?", "ed-complete", NULL);
3174         /* Bind ^D to redisplay */
3175         el_set(el, EL_BIND, "^D", "ed-redisplay", NULL);
3176         /* Bind Delete to delete char left */
3177         el_set(el, EL_BIND, "\\e[3~", "ed-delete-next-char", NULL);
3178         /* Bind Home and End to move to line start and end */
3179         el_set(el, EL_BIND, "\\e[1~", "ed-move-to-beg", NULL);
3180         el_set(el, EL_BIND, "\\e[4~", "ed-move-to-end", NULL);
3181         /* Bind C-left and C-right to move by word (not all terminals) */
3182         el_set(el, EL_BIND, "\\eOC", "vi-next-word", NULL);
3183         el_set(el, EL_BIND, "\\eOD", "vi-prev-word", NULL);
3184
3185         if (editrc) {
3186                 el_source(el, editrc);
3187         }
3188
3189         return 0;
3190 }
3191
3192 #define MAX_HISTORY_COMMAND_LENGTH 256
3193
3194 static int ast_el_add_history(const char *buf)
3195 {
3196         HistEvent ev;
3197         char *stripped_buf;
3198
3199         if (el_hist == NULL || el == NULL) {
3200                 ast_el_initialize();
3201         }
3202         if (strlen(buf) > (MAX_HISTORY_COMMAND_LENGTH - 1)) {
3203                 return 0;
3204         }
3205
3206         stripped_buf = ast_strip(ast_strdupa(buf));
3207
3208         /* HISTCONTROL=ignoredups */
3209         if (!history(el_hist, &ev, H_FIRST) && strcmp(ev.str, stripped_buf) == 0) {
3210                 return 0;
3211         }
3212
3213         return history(el_hist, &ev, H_ENTER, stripped_buf);
3214 }
3215
3216 static int ast_el_write_history(const char *filename)
3217 {
3218         HistEvent ev;
3219
3220         if (el_hist == NULL || el == NULL)
3221                 ast_el_initialize();
3222
3223         return (history(el_hist, &ev, H_SAVE, filename));
3224 }
3225
3226 static int ast_el_read_history(const char *filename)
3227 {
3228         HistEvent ev;
3229
3230         if (el_hist == NULL || el == NULL) {
3231                 ast_el_initialize();
3232         }
3233
3234         return history(el_hist, &ev, H_LOAD, filename);
3235 }
3236
3237 static void ast_el_read_default_histfile(void)
3238 {
3239         char histfile[80] = "";
3240         const char *home = getenv("HOME");
3241
3242         if (!ast_strlen_zero(home)) {
3243                 snprintf(histfile, sizeof(histfile), "%s/.asterisk_history", home);
3244                 ast_el_read_history(histfile);
3245         }
3246 }
3247
3248 static void ast_el_write_default_histfile(void)
3249 {
3250         char histfile[80] = "";
3251         const char *home = getenv("HOME");
3252
3253         if (!ast_strlen_zero(home)) {
3254                 snprintf(histfile, sizeof(histfile), "%s/.asterisk_history", home);
3255                 ast_el_write_history(histfile);
3256         }
3257 }
3258
3259 static void ast_remotecontrol(char *data)
3260 {
3261         char buf[256] = "";
3262         int res;
3263         char *hostname;
3264         char *cpid;
3265         char *version;
3266         int pid;
3267         char *stringp = NULL;
3268
3269         char *ebuf;
3270         int num = 0;
3271
3272         ast_term_init();
3273         printf("%s", term_end());
3274         fflush(stdout);
3275
3276         memset(&sig_flags, 0, sizeof(sig_flags));
3277         signal(SIGINT, __remote_quit_handler);
3278         signal(SIGTERM, __remote_quit_handler);
3279         signal(SIGHUP, __remote_quit_handler);
3280
3281         if (read(ast_consock, buf, sizeof(buf) - 1) < 0) {
3282                 ast_log(LOG_ERROR, "read() failed: %s\n", strerror(errno));
3283                 return;
3284         }
3285         if (data) {
3286                 char prefix[] = "cli quit after ";
3287                 char *tmp = ast_alloca(strlen(data) + strlen(prefix) + 1);
3288                 sprintf(tmp, "%s%s", prefix, data);
3289                 if (write(ast_consock, tmp, strlen(tmp) + 1) < 0) {
3290                         ast_log(LOG_ERROR, "write() failed: %s\n", strerror(errno));
3291                         if (sig_flags.need_quit || sig_flags.need_quit_handler) {
3292                                 return;
3293                         }
3294                 }
3295         }
3296         stringp = buf;
3297         hostname = strsep(&stringp, "/");
3298         cpid = strsep(&stringp, "/");
3299         version = strsep(&stringp, "\n");
3300         if (!version)
3301                 version = "<Version Unknown>";
3302         stringp = hostname;
3303         strsep(&stringp, ".");
3304         if (cpid)
3305                 pid = atoi(cpid);
3306         else
3307                 pid = -1;
3308         if (!data) {
3309                 send_rasterisk_connect_commands();
3310         }
3311
3312         if (ast_opt_exec && data) {  /* hack to print output then exit if asterisk -rx is used */
3313                 int linefull = 1, prev_linefull = 1, prev_line_verbose = 0;
3314                 struct pollfd fds;
3315                 fds.fd = ast_consock;
3316                 fds.events = POLLIN;
3317                 fds.revents = 0;
3318
3319                 while (ast_poll(&fds, 1, 60000) > 0) {
3320                         char buffer[512] = "", *curline = buffer, *nextline;
3321                         int not_written = 1;
3322
3323                         if (sig_flags.need_quit || sig_flags.need_quit_handler) {
3324                                 break;
3325                         }
3326
3327                         if (read(ast_consock, buffer, sizeof(buffer) - 1) <= 0) {
3328                                 break;
3329                         }
3330
3331                         do {
3332                                 prev_linefull = linefull;
3333                                 if ((nextline = strchr(curline, '\n'))) {
3334                                         linefull = 1;
3335                                         nextline++;
3336                                 } else {
3337                                         linefull = 0;
3338                                         nextline = strchr(curline, '\0');
3339                                 }
3340
3341                                 /* Skip verbose lines */
3342                                 /* Prev line full? | Line is verbose | Last line verbose? | Print
3343                                  * TRUE            | TRUE*           | TRUE               | FALSE
3344                                  * TRUE            | TRUE*           | FALSE              | FALSE
3345                                  * TRUE            | FALSE*          | TRUE               | TRUE
3346                                  * TRUE            | FALSE*          | FALSE              | TRUE
3347                                  * FALSE           | TRUE            | TRUE*              | FALSE
3348                                  * FALSE           | TRUE            | FALSE*             | TRUE
3349                                  * FALSE           | FALSE           | TRUE*              | FALSE
3350                                  * FALSE           | FALSE           | FALSE*             | TRUE
3351                                  */
3352                                 if ((!prev_linefull && !prev_line_verbose) || (prev_linefull && *curline > 0)) {
3353                                         prev_line_verbose = 0;
3354                                         not_written = 0;
3355                                         if (write(STDOUT_FILENO, curline, nextline - curline) < 0) {
3356                                                 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
3357                                         }
3358                                 } else {
3359                                         prev_line_verbose = 1;
3360                                 }
3361                                 curline = nextline;
3362                         } while (!ast_strlen_zero(curline));
3363
3364                         /* No non-verbose output in 60 seconds. */
3365                         if (not_written) {
3366                                 break;
3367                         }
3368                 }
3369                 return;
3370         }
3371
3372         ast_verbose("Connected to Asterisk %s currently running on %s (pid = %d)\n", version, hostname, pid);
3373         remotehostname = hostname;
3374         if (el_hist == NULL || el == NULL)
3375                 ast_el_initialize();
3376         ast_el_read_default_histfile();
3377
3378         el_set(el, EL_GETCFN, ast_el_read_char);
3379
3380         for (;;) {
3381                 ebuf = (char *)el_gets(el, &num);
3382
3383                 if (sig_flags.need_quit || sig_flags.need_quit_handler) {
3384                         break;
3385                 }
3386
3387                 if (!ebuf && write(1, "", 1) < 0)
3388                         break;
3389
3390                 if (!ast_strlen_zero(ebuf)) {
3391                         if (ebuf[strlen(ebuf)-1] == '\n')
3392                                 ebuf[strlen(ebuf)-1] = '\0';
3393                         if (!remoteconsolehandler(ebuf)) {
3394                                 res = write(ast_consock, ebuf, strlen(ebuf) + 1);
3395                                 if (res < 1) {
3396                                         ast_log(LOG_WARNING, "Unable to write: %s\n", strerror(errno));
3397                                         break;
3398                                 }
3399                         }
3400                 }
3401         }
3402         printf("\nDisconnected from Asterisk server\n");
3403 }
3404
3405 static int show_version(void)
3406 {
3407         printf("Asterisk %s\n", ast_get_version());
3408         return 0;
3409 }
3410
3411 static int show_cli_help(void)
3412 {
3413         printf("Asterisk %s, Copyright (C) 1999 - 2016, Digium, Inc. and others.\n", ast_get_version());
3414         printf("Usage: asterisk [OPTIONS]\n");
3415         printf("Valid Options:\n");
3416         printf("   -V              Display version number and exit\n");
3417         printf("   -C <configfile> Use an alternate configuration file\n");
3418         printf("   -G <group>      Run as a group other than the caller\n");
3419         printf("   -U <user>       Run as a user other than the caller\n");
3420         printf("   -c              Provide console CLI\n");
3421         printf("   -d              Increase debugging (multiple d's = more debugging)\n");
3422 #if HAVE_WORKING_FORK
3423         printf("   -f              Do not fork\n");
3424         printf("   -F              Always fork\n");
3425 #endif
3426         printf("   -g              Dump core in case of a crash\n");
3427         printf("   -h              This help screen\n");
3428         printf("   -i              Initialize crypto keys at startup\n");
3429         printf("   -L <load>       Limit the maximum load average before rejecting new calls\n");
3430         printf("   -M <value>      Limit the maximum number of calls to the specified value\n");
3431         printf("   -m              Mute debugging and console output on the console\n");
3432         printf("   -n              Disable console colorization\n");
3433         printf("   -p              Run as pseudo-realtime thread\n");
3434         printf("   -q              Quiet mode (suppress output)\n");
3435         printf("   -r              Connect to Asterisk on this machine\n");
3436         printf("   -R              Same as -r, except attempt to reconnect if disconnected\n");
3437         printf("   -s <socket>     Connect to Asterisk via socket <socket> (only valid with -r)\n");
3438         printf("   -t              Record soundfiles in /var/tmp and move them where they\n");
3439         printf("                   belong after they are done\n");
3440         printf("   -T              Display the time in [Mmm dd hh:mm:ss] format for each line\n");
3441         printf("                   of output to the CLI\n");
3442         printf("   -v              Increase verbosity (multiple v's = more verbose)\n");
3443         printf("   -x <cmd>        Execute command <cmd> (implies -r)\n");
3444         printf("   -X              Enable use of #exec in asterisk.conf\n");
3445         printf("   -W              Adjust terminal colors to compensate for a light background\n");
3446         printf("\n");
3447         return 0;
3448 }
3449
3450 static void ast_readconfig(void)
3451 {
3452         struct ast_config *cfg;
3453         struct ast_variable *v;
3454         char hostname[MAXHOSTNAMELEN] = "";
3455         struct ast_flags config_flags = { CONFIG_FLAG_NOREALTIME };
3456         struct {
3457                 unsigned int dbdir:1;
3458                 unsigned int keydir:1;
3459         } found = { 0, 0 };
3460         /* Default to false for security */
3461         int live_dangerously = 0;
3462         int option_debug_new = 0;
3463         int option_verbose_new = 0;
3464
3465         /* Set default value */
3466         option_dtmfminduration = AST_MIN_DTMF_DURATION;
3467         ast_option_rtpusedynamic = 1;
3468         ast_option_rtpptdynamic = 35;
3469
3470         /* init with buildtime config */
3471         ast_copy_string(cfg_paths.config_dir, DEFAULT_CONFIG_DIR, sizeof(cfg_paths.config_dir));
3472         ast_copy_string(cfg_paths.spool_dir, DEFAULT_SPOOL_DIR, sizeof(cfg_paths.spool_dir));
3473         ast_copy_string(cfg_paths.module_dir, DEFAULT_MODULE_DIR, sizeof(cfg_paths.module_dir));
3474         ast_copy_string(cfg_paths.monitor_dir, DEFAULT_MONITOR_DIR, sizeof(cfg_paths.monitor_dir));
3475         ast_copy_string(cfg_paths.recording_dir, DEFAULT_RECORDING_DIR, sizeof(cfg_paths.recording_dir));
3476         ast_copy_string(cfg_paths.var_dir, DEFAULT_VAR_DIR, sizeof(cfg_paths.var_dir));
3477         ast_copy_string(cfg_paths.data_dir, DEFAULT_DATA_DIR, sizeof(cfg_paths.data_dir));
3478         ast_copy_string(cfg_paths.log_dir, DEFAULT_LOG_DIR, sizeof(cfg_paths.log_dir));
3479         ast_copy_string(cfg_paths.agi_dir, DEFAULT_AGI_DIR, sizeof(cfg_paths.agi_dir));
3480         ast_copy_string(cfg_paths.db_path, DEFAULT_DB, sizeof(cfg_paths.db_path));
3481         ast_copy_string(cfg_paths.sbin_dir, DEFAULT_SBIN_DIR, sizeof(cfg_paths.sbin_dir));
3482         ast_copy_string(cfg_paths.key_dir, DEFAULT_KEY_DIR, sizeof(cfg_paths.key_dir));
3483         ast_copy_string(cfg_paths.pid_path, DEFAULT_PID, sizeof(cfg_paths.pid_path));
3484         ast_copy_string(cfg_paths.socket_path, DEFAULT_SOCKET, sizeof(cfg_paths.socket_path));
3485         ast_copy_string(cfg_paths.run_dir, DEFAULT_RUN_DIR, sizeof(cfg_paths.run_dir));
3486
3487 #ifdef REF_DEBUG
3488         /* The REF_DEBUG compiler flag is now only used to enable refdebug by default.
3489          * Support for debugging reference counts is always compiled in. */
3490         ast_set2_flag(&ast_options, 1, AST_OPT_FLAG_REF_DEBUG);
3491 #endif
3492
3493         ast_set_default_eid(&ast_eid_default);
3494
3495         cfg = ast_config_load2(ast_config_AST_CONFIG_FILE, "" /* core, can't reload */, config_flags);
3496
3497         /* If AST_OPT_FLAG_EXEC_INCLUDES was previously enabled with -X turn it off now.
3498          * Using #exec from other configs requires that it be enabled from asterisk.conf. */
3499         ast_clear_flag(&ast_options, AST_OPT_FLAG_EXEC_INCLUDES);
3500
3501         /* no asterisk.conf? no problem, use buildtime config! */
3502         if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEUNCHANGED || cfg == CONFIG_STATUS_FILEINVALID) {
3503                 fprintf(stderr, "Unable to open specified master config file '%s', using built-in defaults\n", ast_config_AST_CONFIG_FILE);
3504                 return;
3505         }
3506
3507         for (v = ast_variable_browse(cfg, "files"); v; v = v->next) {
3508                 if (!strcasecmp(v->name, "astctlpermissions"))
3509                         ast_copy_string(ast_config_AST_CTL_PERMISSIONS, v->value, sizeof(ast_config_AST_CTL_PERMISSIONS));
3510                 else if (!strcasecmp(v->name, "astctlowner"))
3511                         ast_copy_string(ast_config_AST_CTL_OWNER, v->value, sizeof(ast_config_AST_CTL_OWNER));
3512                 else if (!strcasecmp(v->name, "astctlgroup"))
3513                         ast_copy_string(ast_config_AST_CTL_GROUP, v->value, sizeof(ast_config_AST_CTL_GROUP));
3514                 else if (!strcasecmp(v->name, "astctl"))
3515                         ast_copy_string(ast_config_AST_CTL, v->value, sizeof(ast_config_AST_CTL));
3516         }
3517
3518         for (v = ast_variable_browse(cfg, "directories"); v; v = v->next) {
3519                 if (!strcasecmp(v->name, "astetcdir")) {
3520                         ast_copy_string(cfg_paths.config_dir, v->value, sizeof(cfg_paths.config_dir));
3521                 } else if (!strcasecmp(v->name, "astspooldir")) {
3522                         ast_copy_string(cfg_paths.spool_dir, v->value, sizeof(cfg_paths.spool_dir));
3523                         snprintf(cfg_paths.monitor_dir, sizeof(cfg_paths.monitor_dir), "%s/monitor", v->value);
3524                         snprintf(cfg_paths.recording_dir, sizeof(cfg_paths.recording_dir), "%s/recording", v->value);
3525                 } else if (!strcasecmp(v->name, "astvarlibdir")) {
3526                         ast_copy_string(cfg_paths.var_dir, v->value, sizeof(cfg_paths.var_dir));
3527                         if (!found.dbdir)
3528                                 snprintf(cfg_paths.db_path, sizeof(cfg_paths.db_path), "%s/astdb", v->value);
3529                 } else if (!strcasecmp(v->name, "astdbdir")) {
3530                         snprintf(cfg_paths.db_path, sizeof(cfg_paths.db_path), "%s/astdb", v->value);
3531                         found.dbdir = 1;
3532                 } else if (!strcasecmp(v->name, "astdatadir")) {
3533                         ast_copy_string(cfg_paths.data_dir, v->value, sizeof(cfg_paths.data_dir));
3534                         if (!found.keydir)
3535                                 snprintf(cfg_paths.key_dir, sizeof(cfg_paths.key_dir), "%s/keys", v->value);
3536                 } else if (!strcasecmp(v->name, "astkeydir")) {
3537                         snprintf(cfg_paths.key_dir, sizeof(cfg_paths.key_dir), "%s/keys", v->value);
3538                         found.keydir = 1;
3539                 } else if (!strcasecmp(v->name, "astlogdir")) {
3540                         ast_copy_string(cfg_paths.log_dir, v->value, sizeof(cfg_paths.log_dir));
3541                 } else if (!strcasecmp(v->name, "astagidir")) {
3542                         ast_copy_string(cfg_paths.agi_dir, v->value, sizeof(cfg_paths.agi_dir));
3543                 } else if (!strcasecmp(v->name, "astrundir")) {
3544                         snprintf(cfg_paths.pid_path, sizeof(cfg_paths.pid_path), "%s/%s", v->value, "asterisk.pid");
3545                         ast_copy_string(cfg_paths.run_dir, v->value, sizeof(cfg_paths.run_dir));
3546                 } else if (!strcasecmp(v->name, "astmoddir")) {
3547                         ast_copy_string(cfg_paths.module_dir, v->value, sizeof(cfg_paths.module_dir));
3548                 } else if (!strcasecmp(v->name, "astsbindir")) {
3549                         ast_copy_string(cfg_paths.sbin_dir, v->value, sizeof(cfg_paths.sbin_dir));
3550                 }
3551         }
3552
3553         /* Combine astrundir and astctl settings. */
3554         snprintf(cfg_paths.socket_path, sizeof(cfg_paths.socket_path), "%s/%s",
3555                 ast_config_AST_RUN_DIR, ast_config_AST_CTL);
3556
3557         for (v = ast_variable_browse(cfg, "options"); v; v = v->next) {
3558                 /* verbose level (-v at startup) */
3559                 if (!strcasecmp(v->name, "verbose")) {
3560                         option_verbose_new = atoi(v->value);
3561                 /* whether or not to force timestamping in CLI verbose output. (-T at startup) */
3562                 } else if (!strcasecmp(v->name, "timestamp")) {
3563                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_TIMESTAMP);
3564                 /* whether or not to support #exec in config files */
3565                 } else if (!strcasecmp(v->name, "execincludes")) {
3566                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_EXEC_INCLUDES);
3567                 /* debug level (-d at startup) */
3568                 } else if (!strcasecmp(v->name, "debug")) {
3569                         option_debug_new = 0;
3570                         if (sscanf(v->value, "%30d", &option_debug_new) != 1) {
3571                                 option_debug_new = ast_true(v->value) ? 1 : 0;
3572                         }
3573                 } else if (!strcasecmp(v->name, "refdebug")) {
3574                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_REF_DEBUG);
3575 #if HAVE_WORKING_FORK
3576                 /* Disable forking (-f at startup) */
3577                 } else if (!strcasecmp(v->name, "nofork")) {
3578                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_NO_FORK);
3579                 /* Always fork, even if verbose or debug are enabled (-F at startup) */
3580                 } else if (!strcasecmp(v->name, "alwaysfork")) {
3581                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_ALWAYS_FORK);
3582 #endif
3583                 /* Run quietly (-q at startup ) */
3584                 } else if (!strcasecmp(v->name, "quiet")) {
3585                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_QUIET);
3586                 /* Run as console (-c at startup, implies nofork) */
3587                 } else if (!strcasecmp(v->name, "console")) {
3588                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_NO_FORK | AST_OPT_FLAG_CONSOLE);
3589                 /* Run with high priority if the O/S permits (-p at startup) */
3590                 } else if (!strcasecmp(v->name, "highpriority")) {
3591                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_HIGH_PRIORITY);
3592                 /* Initialize RSA auth keys (IAX2) (-i at startup) */
3593                 } else if (!strcasecmp(v->name, "initcrypto")) {
3594                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_INIT_KEYS);
3595                 /* Disable ANSI colors for console (-c at startup) */
3596                 } else if (!strcasecmp(v->name, "nocolor")) {
3597                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_NO_COLOR);
3598                 /* Disable some usage warnings for picky people :p */
3599                 } else if (!strcasecmp(v->name, "dontwarn")) {
3600                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_DONT_WARN);
3601                 /* Dump core in case of crash (-g) */
3602                 } else if (!strcasecmp(v->name, "dumpcore")) {
3603                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_DUMP_CORE);
3604                 /* Cache recorded sound files to another directory during recording */
3605                 } else if (!strcasecmp(v->name, "cache_record_files")) {
3606                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_CACHE_RECORD_FILES);
3607 #if !defined(LOW_MEMORY)
3608                 /* Cache media frames for performance */
3609                 } else if (!strcasecmp(v->name, "cache_media_frames")) {
3610                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_CACHE_MEDIA_FRAMES);
3611 #endif
3612                 /* Specify cache directory */
3613                 }  else if (!strcasecmp(v->name, "record_cache_dir")) {
3614                         ast_copy_string(record_cache_dir, v->value, AST_CACHE_DIR_LEN);
3615                 /* Build transcode paths via SLINEAR, instead of directly */
3616                 } else if (!strcasecmp(v->name, "transcode_via_sln")) {
3617                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_TRANSCODE_VIA_SLIN);
3618                 /* Transmit SLINEAR silence while a channel is being recorded or DTMF is being generated on a channel */
3619                 } else if (!strcasecmp(v->name, "transmit_silence_during_record") || !strcasecmp(v->name, "transmit_silence")) {
3620                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_TRANSMIT_SILENCE);
3621                 /* Enable internal timing */
3622                 } else if (!strcasecmp(v->name, "internal_timing")) {
3623                         if (!ast_opt_remote) {
3624                                 fprintf(stderr,
3625                                         "NOTICE: The internal_timing option is no longer needed.\n"
3626                                         "  It will always be enabled if you have a timing module loaded.\n");
3627                         }
3628                 } else if (!strcasecmp(v->name, "mindtmfduration")) {
3629                         if (sscanf(v->value, "%30u", &option_dtmfminduration) != 1) {
3630                                 option_dtmfminduration = AST_MIN_DTMF_DURATION;
3631                         }
3632                 } else if (!strcasecmp(v->name, "rtp_use_dynamic")) {
3633                         ast_option_rtpusedynamic = ast_true(v->value);
3634                 /* http://www.iana.org/assignments/rtp-parameters
3635                  * RTP dynamic payload types start at 96 normally; extend down to 0 */
3636                 } else if (!strcasecmp(v->name, "rtp_pt_dynamic")) {
3637                         ast_parse_arg(v->value, PARSE_UINT32|PARSE_IN_RANGE,
3638                                       &ast_option_rtpptdynamic, 0, AST_RTP_PT_FIRST_DYNAMIC);
3639                 } else if (!strcasecmp(v->name, "maxcalls")) {
3640                         if ((sscanf(v->value, "%30d", &ast_option_maxcalls) != 1) || (ast_option_maxcalls < 0)) {
3641                                 ast_option_maxcalls = 0;
3642                         }
3643                 } else if (!strcasecmp(v->name, "maxload")) {
3644                         double test[1];
3645
3646                         if (getloadavg(test, 1) == -1) {
3647                                 ast_log(LOG_ERROR, "Cannot obtain load average on this system. 'maxload' option disabled.\n");
3648                                 ast_option_maxload = 0.0;
3649                         } else if ((sscanf(v->value, "%30lf", &ast_option_maxload) != 1) || (ast_option_maxload < 0.0)) {
3650                                 ast_option_maxload = 0.0;
3651                         }
3652                 /* Set the maximum amount of open files */
3653                 } else if (!strcasecmp(v->name, "maxfiles")) {
3654                         ast_option_maxfiles = atoi(v->value);
3655                         if (!ast_opt_remote) {
3656                                 set_ulimit(ast_option_maxfiles);
3657                         }
3658                 /* What user to run as */
3659                 } else if (!strcasecmp(v->name, "runuser")) {
3660                         ast_copy_string(cfg_paths.run_user, v->value, sizeof(cfg_paths.run_user));
3661                 /* What group to run as */
3662                 } else if (!strcasecmp(v->name, "rungroup")) {
3663                         ast_copy_string(cfg_paths.run_group, v->value, sizeof(cfg_paths.run_group));
3664                 } else if (!strcasecmp(v->name, "systemname")) {
3665                         ast_copy_string(cfg_paths.system_name, v->value, sizeof(cfg_paths.system_name));
3666                 } else if (!strcasecmp(v->name, "autosystemname")) {
3667                         if (ast_true(v->value)) {
3668                                 if (!gethostname(hostname, sizeof(hostname) - 1))
3669                                         ast_copy_string(cfg_paths.system_name, hostname, sizeof(cfg_paths.system_name));
3670                                 else {
3671                                         if (ast_strlen_zero(ast_config_AST_SYSTEM_NAME)){
3672                                                 ast_copy_string(cfg_paths.system_name, "localhost", sizeof(cfg_paths.system_name));
3673                                         }
3674                                         ast_log(LOG_ERROR, "Cannot obtain hostname for this system.  Using '%s' instead.\n", ast_config_AST_SYSTEM_NAME);
3675                                 }
3676                         }
3677                 } else if (!strcasecmp(v->name, "languageprefix")) {
3678                         ast_language_is_prefix = ast_true(v->value);
3679                 } else if (!strcasecmp(v->name, "defaultlanguage")) {
3680                         ast_copy_string(ast_defaultlanguage, v->value, MAX_LANGUAGE);
3681                 } else if (!strcasecmp(v->name, "lockmode")) {
3682                         if (!strcasecmp(v->value, "lockfile")) {