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