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