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