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