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