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