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