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