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