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