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