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