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