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