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