Avoid cppcheck warnings; removing unused vars and a bit of cleanup.
[asterisk/asterisk.git] / main / asterisk.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2012, Digium, Inc.
5  *
6  * Mark Spencer <markster@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18
19
20 /* Doxygenified Copyright Header */
21 /*!
22  * \mainpage Asterisk -- The Open Source Telephony Project
23  *
24  * \par 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         for (x = 0;x < AST_MAX_CONNECTS; x++) {
1108                 if (fd == consoles[x].fd) {
1109                         /*
1110                          * Since the logging occurs when levels are false, set to
1111                          * flipped iinput because this function accepts 0 as off and 1 as on
1112                          */
1113                         consoles[x].levels[level] = state ? 0 : 1;
1114                         return;
1115                 }
1116         }
1117 }
1118
1119 /*!
1120  * \brief mute or unmute a console from logging
1121  */
1122 void ast_console_toggle_mute(int fd, int silent)
1123 {
1124         int x;
1125         for (x = 0;x < AST_MAX_CONNECTS; x++) {
1126                 if (fd == consoles[x].fd) {
1127                         if (consoles[x].mute) {
1128                                 consoles[x].mute = 0;
1129                                 if (!silent)
1130                                         ast_cli(fd, "Console is not muted anymore.\n");
1131                         } else {
1132                                 consoles[x].mute = 1;
1133                                 if (!silent)
1134                                         ast_cli(fd, "Console is muted.\n");
1135                         }
1136                         return;
1137                 }
1138         }
1139         ast_cli(fd, "Couldn't find remote console.\n");
1140 }
1141
1142 /*!
1143  * \brief log the string to all attached console clients
1144  */
1145 static void ast_network_puts_mutable(const char *string, int level)
1146 {
1147         int x;
1148         for (x = 0;x < AST_MAX_CONNECTS; x++) {
1149                 if (consoles[x].mute)
1150                         continue;
1151                 if (consoles[x].fd > -1) {
1152                         if (!consoles[x].levels[level])
1153                                 fdprint(consoles[x].p[1], string);
1154                 }
1155         }
1156 }
1157
1158 /*!
1159  * \brief log the string to the console, and all attached
1160  * console clients
1161  */
1162 void ast_console_puts_mutable(const char *string, int level)
1163 {
1164         fputs(string, stdout);
1165         fflush(stdout);
1166         ast_network_puts_mutable(string, level);
1167 }
1168
1169 /*!
1170  * \brief write the string to all attached console clients
1171  */
1172 static void ast_network_puts(const char *string)
1173 {
1174         int x;
1175         for (x = 0; x < AST_MAX_CONNECTS; x++) {
1176                 if (consoles[x].fd > -1)
1177                         fdprint(consoles[x].p[1], string);
1178         }
1179 }
1180
1181 /*!
1182  * write the string to the console, and all attached
1183  * console clients
1184  */
1185 void ast_console_puts(const char *string)
1186 {
1187         fputs(string, stdout);
1188         fflush(stdout);
1189         ast_network_puts(string);
1190 }
1191
1192 static void network_verboser(const char *s)
1193 {
1194         ast_network_puts_mutable(s, __LOG_VERBOSE);
1195 }
1196
1197 static pthread_t lthread;
1198
1199 /*!
1200  * \brief read() function supporting the reception of user credentials.
1201  *
1202  * \param fd Socket file descriptor.
1203  * \param buffer Receive buffer.
1204  * \param size 'buffer' size.
1205  * \param con Console structure to set received credentials
1206  * \retval -1 on error
1207  * \retval the number of bytes received on success.
1208  */
1209 static int read_credentials(int fd, char *buffer, size_t size, struct console *con)
1210 {
1211 #if defined(SO_PEERCRED)
1212 #ifdef HAVE_STRUCT_SOCKPEERCRED_UID
1213 #define HAVE_STRUCT_UCRED_UID
1214         struct sockpeercred cred;
1215 #else
1216         struct ucred cred;
1217 #endif
1218         socklen_t len = sizeof(cred);
1219 #endif
1220 #if defined(HAVE_GETPEEREID)
1221         uid_t uid;
1222         gid_t gid;
1223 #else
1224         int uid, gid;
1225 #endif
1226         int result;
1227
1228         result = read(fd, buffer, size);
1229         if (result < 0) {
1230                 return result;
1231         }
1232
1233 #if defined(SO_PEERCRED) && (defined(HAVE_STRUCT_UCRED_UID) || defined(HAVE_STRUCT_UCRED_CR_UID))
1234         if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &cred, &len)) {
1235                 return result;
1236         }
1237 #if defined(HAVE_STRUCT_UCRED_UID)
1238         uid = cred.uid;
1239         gid = cred.gid;
1240 #else /* defined(HAVE_STRUCT_UCRED_CR_UID) */
1241         uid = cred.cr_uid;
1242         gid = cred.cr_gid;
1243 #endif /* defined(HAVE_STRUCT_UCRED_UID) */
1244
1245 #elif defined(HAVE_GETPEEREID)
1246         if (getpeereid(fd, &uid, &gid)) {
1247                 return result;
1248         }
1249 #else
1250         return result;
1251 #endif
1252         con->uid = uid;
1253         con->gid = gid;
1254
1255         return result;
1256 }
1257
1258 static void *netconsole(void *vconsole)
1259 {
1260         struct console *con = vconsole;
1261         char hostname[MAXHOSTNAMELEN] = "";
1262         char tmp[512];
1263         int res;
1264         struct pollfd fds[2];
1265
1266         if (gethostname(hostname, sizeof(hostname)-1))
1267                 ast_copy_string(hostname, "<Unknown>", sizeof(hostname));
1268         snprintf(tmp, sizeof(tmp), "%s/%ld/%s\n", hostname, (long)ast_mainpid, ast_get_version());
1269         fdprint(con->fd, tmp);
1270         for (;;) {
1271                 fds[0].fd = con->fd;
1272                 fds[0].events = POLLIN;
1273                 fds[0].revents = 0;
1274                 fds[1].fd = con->p[0];
1275                 fds[1].events = POLLIN;
1276                 fds[1].revents = 0;
1277
1278                 res = ast_poll(fds, 2, -1);
1279                 if (res < 0) {
1280                         if (errno != EINTR)
1281                                 ast_log(LOG_WARNING, "poll returned < 0: %s\n", strerror(errno));
1282                         continue;
1283                 }
1284                 if (fds[0].revents) {
1285                         res = read_credentials(con->fd, tmp, sizeof(tmp) - 1, con);
1286                         if (res < 1) {
1287                                 break;
1288                         }
1289                         tmp[res] = 0;
1290                         if (strncmp(tmp, "cli quit after ", 15) == 0) {
1291                                 ast_cli_command_multiple_full(con->uid, con->gid, con->fd, res - 15, tmp + 15);
1292                                 break;
1293                         }
1294                         ast_cli_command_multiple_full(con->uid, con->gid, con->fd, res, tmp);
1295                 }
1296                 if (fds[1].revents) {
1297                         res = read_credentials(con->p[0], tmp, sizeof(tmp), con);
1298                         if (res < 1) {
1299                                 ast_log(LOG_ERROR, "read returned %d\n", res);
1300                                 break;
1301                         }
1302                         res = write(con->fd, tmp, res);
1303                         if (res < 1)
1304                                 break;
1305                 }
1306         }
1307         if (!ast_opt_hide_connect) {
1308                 ast_verb(3, "Remote UNIX connection disconnected\n");
1309         }
1310         close(con->fd);
1311         close(con->p[0]);
1312         close(con->p[1]);
1313         con->fd = -1;
1314
1315         return NULL;
1316 }
1317
1318 static void *listener(void *unused)
1319 {
1320         struct sockaddr_un sunaddr;
1321         int s;
1322         socklen_t len;
1323         int x;
1324         int flags;
1325         struct pollfd fds[1];
1326         for (;;) {
1327                 if (ast_socket < 0)
1328                         return NULL;
1329                 fds[0].fd = ast_socket;
1330                 fds[0].events = POLLIN;
1331                 s = ast_poll(fds, 1, -1);
1332                 pthread_testcancel();
1333                 if (s < 0) {
1334                         if (errno != EINTR)
1335                                 ast_log(LOG_WARNING, "poll returned error: %s\n", strerror(errno));
1336                         continue;
1337                 }
1338                 len = sizeof(sunaddr);
1339                 s = accept(ast_socket, (struct sockaddr *)&sunaddr, &len);
1340                 if (s < 0) {
1341                         if (errno != EINTR)
1342                                 ast_log(LOG_WARNING, "Accept returned %d: %s\n", s, strerror(errno));
1343                 } else {
1344 #if !defined(SO_PASSCRED)
1345                         {
1346 #else
1347                         int sckopt = 1;
1348                         /* turn on socket credentials passing. */
1349                         if (setsockopt(s, SOL_SOCKET, SO_PASSCRED, &sckopt, sizeof(sckopt)) < 0) {
1350                                 ast_log(LOG_WARNING, "Unable to turn on socket credentials passing\n");
1351                         } else {
1352 #endif
1353                                 for (x = 0; x < AST_MAX_CONNECTS; x++) {
1354                                         if (consoles[x].fd >= 0) {
1355                                                 continue;
1356                                         }
1357                                         if (socketpair(AF_LOCAL, SOCK_STREAM, 0, consoles[x].p)) {
1358                                                 ast_log(LOG_ERROR, "Unable to create pipe: %s\n", strerror(errno));
1359                                                 consoles[x].fd = -1;
1360                                                 fdprint(s, "Server failed to create pipe\n");
1361                                                 close(s);
1362                                                 break;
1363                                         }
1364                                         flags = fcntl(consoles[x].p[1], F_GETFL);
1365                                         fcntl(consoles[x].p[1], F_SETFL, flags | O_NONBLOCK);
1366                                         consoles[x].fd = s;
1367                                         consoles[x].mute = 1; /* Default is muted, we will un-mute if necessary */
1368                                         /* Default uid and gid to -2, so then in cli.c/cli_has_permissions() we will be able
1369                                            to know if the user didn't send the credentials. */
1370                                         consoles[x].uid = -2;
1371                                         consoles[x].gid = -2;
1372                                         if (ast_pthread_create_detached_background(&consoles[x].t, NULL, netconsole, &consoles[x])) {
1373                                                 ast_log(LOG_ERROR, "Unable to spawn thread to handle connection: %s\n", strerror(errno));
1374                                                 close(consoles[x].p[0]);
1375                                                 close(consoles[x].p[1]);
1376                                                 consoles[x].fd = -1;
1377                                                 fdprint(s, "Server failed to spawn thread\n");
1378                                                 close(s);
1379                                         }
1380                                         break;
1381                                 }
1382                                 if (x >= AST_MAX_CONNECTS) {
1383                                         fdprint(s, "No more connections allowed\n");
1384                                         ast_log(LOG_WARNING, "No more connections allowed\n");
1385                                         close(s);
1386                                 } else if ((consoles[x].fd > -1) && (!ast_opt_hide_connect)) {
1387                                         ast_verb(3, "Remote UNIX connection\n");
1388                                 }
1389                         }
1390                 }
1391         }
1392         return NULL;
1393 }
1394
1395 static int ast_makesocket(void)
1396 {
1397         struct sockaddr_un sunaddr;
1398         int res;
1399         int x;
1400         uid_t uid = -1;
1401         gid_t gid = -1;
1402
1403         for (x = 0; x < AST_MAX_CONNECTS; x++)
1404                 consoles[x].fd = -1;
1405         unlink(ast_config_AST_SOCKET);
1406         ast_socket = socket(PF_LOCAL, SOCK_STREAM, 0);
1407         if (ast_socket < 0) {
1408                 ast_log(LOG_WARNING, "Unable to create control socket: %s\n", strerror(errno));
1409                 return -1;
1410         }
1411         memset(&sunaddr, 0, sizeof(sunaddr));
1412         sunaddr.sun_family = AF_LOCAL;
1413         ast_copy_string(sunaddr.sun_path, ast_config_AST_SOCKET, sizeof(sunaddr.sun_path));
1414         res = bind(ast_socket, (struct sockaddr *)&sunaddr, sizeof(sunaddr));
1415         if (res) {
1416                 ast_log(LOG_WARNING, "Unable to bind socket to %s: %s\n", ast_config_AST_SOCKET, strerror(errno));
1417                 close(ast_socket);
1418                 ast_socket = -1;
1419                 return -1;
1420         }
1421         res = listen(ast_socket, 2);
1422         if (res < 0) {
1423                 ast_log(LOG_WARNING, "Unable to listen on socket %s: %s\n", ast_config_AST_SOCKET, strerror(errno));
1424                 close(ast_socket);
1425                 ast_socket = -1;
1426                 return -1;
1427         }
1428         if (ast_register_verbose(network_verboser)) {
1429                 ast_log(LOG_WARNING, "Unable to register network verboser?\n");
1430         }
1431
1432         ast_pthread_create_background(&lthread, NULL, listener, NULL);
1433
1434         if (!ast_strlen_zero(ast_config_AST_CTL_OWNER)) {
1435                 struct passwd *pw;
1436                 if ((pw = getpwnam(ast_config_AST_CTL_OWNER)) == NULL)
1437                         ast_log(LOG_WARNING, "Unable to find uid of user %s\n", ast_config_AST_CTL_OWNER);
1438                 else
1439                         uid = pw->pw_uid;
1440         }
1441
1442         if (!ast_strlen_zero(ast_config_AST_CTL_GROUP)) {
1443                 struct group *grp;
1444                 if ((grp = getgrnam(ast_config_AST_CTL_GROUP)) == NULL)
1445                         ast_log(LOG_WARNING, "Unable to find gid of group %s\n", ast_config_AST_CTL_GROUP);
1446                 else
1447                         gid = grp->gr_gid;
1448         }
1449
1450         if (chown(ast_config_AST_SOCKET, uid, gid) < 0)
1451                 ast_log(LOG_WARNING, "Unable to change ownership of %s: %s\n", ast_config_AST_SOCKET, strerror(errno));
1452
1453         if (!ast_strlen_zero(ast_config_AST_CTL_PERMISSIONS)) {
1454                 int p1;
1455                 mode_t p;
1456                 sscanf(ast_config_AST_CTL_PERMISSIONS, "%30o", &p1);
1457                 p = p1;
1458                 if ((chmod(ast_config_AST_SOCKET, p)) < 0)
1459                         ast_log(LOG_WARNING, "Unable to change file permissions of %s: %s\n", ast_config_AST_SOCKET, strerror(errno));
1460         }
1461
1462         return 0;
1463 }
1464
1465 static int ast_tryconnect(void)
1466 {
1467         struct sockaddr_un sunaddr;
1468         int res;
1469         ast_consock = socket(PF_LOCAL, SOCK_STREAM, 0);
1470         if (ast_consock < 0) {
1471                 ast_log(LOG_WARNING, "Unable to create socket: %s\n", strerror(errno));
1472                 return 0;
1473         }
1474         memset(&sunaddr, 0, sizeof(sunaddr));
1475         sunaddr.sun_family = AF_LOCAL;
1476         ast_copy_string(sunaddr.sun_path, ast_config_AST_SOCKET, sizeof(sunaddr.sun_path));
1477         res = connect(ast_consock, (struct sockaddr *)&sunaddr, sizeof(sunaddr));
1478         if (res) {
1479                 close(ast_consock);
1480                 ast_consock = -1;
1481                 return 0;
1482         } else
1483                 return 1;
1484 }
1485
1486 /*! \brief Urgent handler
1487
1488  Called by soft_hangup to interrupt the poll, read, or other
1489  system call.  We don't actually need to do anything though.
1490  Remember: Cannot EVER ast_log from within a signal handler
1491  */
1492 static void _urg_handler(int num)
1493 {
1494         return;
1495 }
1496
1497 static struct sigaction urg_handler = {
1498         .sa_handler = _urg_handler,
1499         .sa_flags = SA_RESTART,
1500 };
1501
1502 static void _hup_handler(int num)
1503 {
1504         int a = 0, save_errno = errno;
1505         printf("Received HUP signal -- Reloading configs\n");
1506         if (restartnow)
1507                 execvp(_argv[0], _argv);
1508         sig_flags.need_reload = 1;
1509         if (sig_alert_pipe[1] != -1) {
1510                 if (write(sig_alert_pipe[1], &a, sizeof(a)) < 0) {
1511                         fprintf(stderr, "hup_handler: write() failed: %s\n", strerror(errno));
1512                 }
1513         }
1514         errno = save_errno;
1515 }
1516
1517 static struct sigaction hup_handler = {
1518         .sa_handler = _hup_handler,
1519         .sa_flags = SA_RESTART,
1520 };
1521
1522 static void _child_handler(int sig)
1523 {
1524         /* Must not ever ast_log or ast_verbose within signal handler */
1525         int n, status, save_errno = errno;
1526
1527         /*
1528          * Reap all dead children -- not just one
1529          */
1530         for (n = 0; wait4(-1, &status, WNOHANG, NULL) > 0; n++)
1531                 ;
1532         if (n == 0 && option_debug)
1533                 printf("Huh?  Child handler, but nobody there?\n");
1534         errno = save_errno;
1535 }
1536
1537 static struct sigaction child_handler = {
1538         .sa_handler = _child_handler,
1539         .sa_flags = SA_RESTART,
1540 };
1541
1542 /*! \brief Set maximum open files */
1543 static void set_ulimit(int value)
1544 {
1545         struct rlimit l = {0, 0};
1546
1547         if (value <= 0) {
1548                 ast_log(LOG_WARNING, "Unable to change max files open to invalid value %i\n",value);
1549                 return;
1550         }
1551
1552         l.rlim_cur = value;
1553         l.rlim_max = value;
1554
1555         if (setrlimit(RLIMIT_NOFILE, &l)) {
1556                 ast_log(LOG_WARNING, "Unable to disable core size resource limit: %s\n",strerror(errno));
1557                 return;
1558         }
1559
1560         ast_log(LOG_NOTICE, "Setting max files open to %d\n",value);
1561
1562         return;
1563 }
1564
1565 /*! \brief Set an X-term or screen title */
1566 static void set_title(char *text)
1567 {
1568         if (getenv("TERM") && strstr(getenv("TERM"), "xterm"))
1569                 fprintf(stdout, "\033]2;%s\007", text);
1570 }
1571
1572 static void set_icon(char *text)
1573 {
1574         if (getenv("TERM") && strstr(getenv("TERM"), "xterm"))
1575                 fprintf(stdout, "\033]1;%s\007", text);
1576 }
1577
1578 /*! \brief We set ourselves to a high priority, that we might pre-empt everything
1579    else.  If your PBX has heavy activity on it, this is a good thing.  */
1580 int ast_set_priority(int pri)
1581 {
1582         struct sched_param sched;
1583         memset(&sched, 0, sizeof(sched));
1584 #ifdef __linux__
1585         if (pri) {
1586                 sched.sched_priority = 10;
1587                 if (sched_setscheduler(0, SCHED_RR, &sched)) {
1588                         ast_log(LOG_WARNING, "Unable to set high priority\n");
1589                         return -1;
1590                 } else
1591                         ast_verb(1, "Set to realtime thread\n");
1592         } else {
1593                 sched.sched_priority = 0;
1594                 /* According to the manpage, these parameters can never fail. */
1595                 sched_setscheduler(0, SCHED_OTHER, &sched);
1596         }
1597 #else
1598         if (pri) {
1599                 if (setpriority(PRIO_PROCESS, 0, -10) == -1) {
1600                         ast_log(LOG_WARNING, "Unable to set high priority\n");
1601                         return -1;
1602                 } else
1603                         ast_verb(1, "Set to high priority\n");
1604         } else {
1605                 /* According to the manpage, these parameters can never fail. */
1606                 setpriority(PRIO_PROCESS, 0, 0);
1607         }
1608 #endif
1609         return 0;
1610 }
1611
1612 static void ast_run_atexits(void)
1613 {
1614         struct ast_atexit *ae;
1615         AST_RWLIST_RDLOCK(&atexits);
1616         AST_RWLIST_TRAVERSE(&atexits, ae, list) {
1617                 if (ae->func)
1618                         ae->func();
1619         }
1620         AST_RWLIST_UNLOCK(&atexits);
1621 }
1622
1623 static int can_safely_quit(shutdown_nice_t niceness, int restart);
1624 static void really_quit(int num, shutdown_nice_t niceness, int restart);
1625
1626 static void quit_handler(int num, shutdown_nice_t niceness, int restart)
1627 {
1628         if (can_safely_quit(niceness, restart)) {
1629                 really_quit(num, niceness, restart);
1630                 /* No one gets here. */
1631         }
1632         /* It wasn't our time. */
1633 }
1634
1635 static int can_safely_quit(shutdown_nice_t niceness, int restart)
1636 {
1637         /* Check if someone else isn't already doing this. */
1638         ast_mutex_lock(&safe_system_lock);
1639         if (shuttingdown != NOT_SHUTTING_DOWN && niceness >= shuttingdown) {
1640                 /* Already in progress and other request was less nice. */
1641                 ast_mutex_unlock(&safe_system_lock);
1642                 ast_verbose("Ignoring asterisk %s request, already in progress.\n", restart ? "restart" : "shutdown");
1643                 return 0;
1644         }
1645         shuttingdown = niceness;
1646         ast_mutex_unlock(&safe_system_lock);
1647
1648         /* Try to get as many CDRs as possible submitted to the backend engines
1649          * (if in batch mode). really_quit happens to call it again when running
1650          * the atexit handlers, otherwise this would be a bit early. */
1651         ast_cdr_engine_term();
1652
1653         if (niceness == SHUTDOWN_NORMAL) {
1654                 time_t s, e;
1655                 /* Begin shutdown routine, hanging up active channels */
1656                 ast_begin_shutdown(1);
1657                 if (option_verbose && ast_opt_console) {
1658                         ast_verbose("Beginning asterisk %s....\n", restart ? "restart" : "shutdown");
1659                 }
1660                 time(&s);
1661                 for (;;) {
1662                         time(&e);
1663                         /* Wait up to 15 seconds for all channels to go away */
1664                         if ((e - s) > 15 || !ast_active_channels() || shuttingdown != niceness) {
1665                                 break;
1666                         }
1667                         /* Sleep 1/10 of a second */
1668                         usleep(100000);
1669                 }
1670         } else if (niceness >= SHUTDOWN_NICE) {
1671                 if (niceness != SHUTDOWN_REALLY_NICE) {
1672                         ast_begin_shutdown(0);
1673                 }
1674                 if (option_verbose && ast_opt_console) {
1675                         ast_verb(0, "Waiting for inactivity to perform %s...\n", restart ? "restart" : "halt");
1676                 }
1677                 for (;;) {
1678                         if (!ast_active_channels() || shuttingdown != niceness) {
1679                                 break;
1680                         }
1681                         sleep(1);
1682                 }
1683         }
1684
1685         /* Re-acquire lock and check if someone changed the niceness, in which
1686          * case someone else has taken over the shutdown. */
1687         ast_mutex_lock(&safe_system_lock);
1688         if (shuttingdown != niceness) {
1689                 if (shuttingdown == NOT_SHUTTING_DOWN && option_verbose && ast_opt_console) {
1690                         ast_verb(0, "Asterisk %s cancelled.\n", restart ? "restart" : "shutdown");
1691                 }
1692                 ast_mutex_unlock(&safe_system_lock);
1693                 return 0;
1694         }
1695         shuttingdown = SHUTTING_DOWN;
1696         ast_mutex_unlock(&safe_system_lock);
1697
1698         return 1;
1699 }
1700
1701 static void really_quit(int num, shutdown_nice_t niceness, int restart)
1702 {
1703         if (niceness >= SHUTDOWN_NICE) {
1704                 ast_module_shutdown();
1705         }
1706
1707         if (ast_opt_console || (ast_opt_remote && !ast_opt_exec)) {
1708                 char filename[80] = "";
1709                 if (getenv("HOME")) {
1710                         snprintf(filename, sizeof(filename), "%s/.asterisk_history", getenv("HOME"));
1711                 }
1712                 if (!ast_strlen_zero(filename)) {
1713                         ast_el_write_history(filename);
1714                 }
1715                 if (consolethread == AST_PTHREADT_NULL || consolethread == pthread_self()) {
1716                         /* Only end if we are the consolethread, otherwise there's a race with that thread. */
1717                         if (el != NULL) {
1718                                 el_end(el);
1719                         }
1720                         if (el_hist != NULL) {
1721                                 history_end(el_hist);
1722                         }
1723                 } else if (mon_sig_flags == pthread_self()) {
1724                         if (consolethread != AST_PTHREADT_NULL) {
1725                                 pthread_kill(consolethread, SIGURG);
1726                         }
1727                 }
1728         }
1729         ast_verb(0, "Executing last minute cleanups\n");
1730         ast_run_atexits();
1731         /* Called on exit */
1732         ast_verb(0, "Asterisk %s ending (%d).\n", ast_active_channels() ? "uncleanly" : "cleanly", num);
1733         ast_debug(1, "Asterisk ending (%d).\n", num);
1734         manager_event(EVENT_FLAG_SYSTEM, "Shutdown", "Shutdown: %s\r\nRestart: %s\r\n", ast_active_channels() ? "Uncleanly" : "Cleanly", restart ? "True" : "False");
1735         if (ast_socket > -1) {
1736                 pthread_cancel(lthread);
1737                 close(ast_socket);
1738                 ast_socket = -1;
1739                 unlink(ast_config_AST_SOCKET);
1740         }
1741         if (ast_consock > -1)
1742                 close(ast_consock);
1743         if (!ast_opt_remote)
1744                 unlink(ast_config_AST_PID);
1745         printf("%s", term_quit());
1746         if (restart) {
1747                 int i;
1748                 ast_verb(0, "Preparing for Asterisk restart...\n");
1749                 /* Mark all FD's for closing on exec */
1750                 for (i = 3; i < 32768; i++) {
1751                         fcntl(i, F_SETFD, FD_CLOEXEC);
1752                 }
1753                 ast_verb(0, "Asterisk is now restarting...\n");
1754                 restartnow = 1;
1755
1756                 /* close logger */
1757                 close_logger();
1758
1759                 /* If there is a consolethread running send it a SIGHUP
1760                    so it can execvp, otherwise we can do it ourselves */
1761                 if ((consolethread != AST_PTHREADT_NULL) && (consolethread != pthread_self())) {
1762                         pthread_kill(consolethread, SIGHUP);
1763                         /* Give the signal handler some time to complete */
1764                         sleep(2);
1765                 } else
1766                         execvp(_argv[0], _argv);
1767
1768         } else {
1769                 /* close logger */
1770                 close_logger();
1771         }
1772
1773         exit(0);
1774 }
1775
1776 static void __quit_handler(int num)
1777 {
1778         int a = 0;
1779         sig_flags.need_quit = 1;
1780         if (sig_alert_pipe[1] != -1) {
1781                 if (write(sig_alert_pipe[1], &a, sizeof(a)) < 0) {
1782                         fprintf(stderr, "quit_handler: write() failed: %s\n", strerror(errno));
1783                 }
1784         }
1785         /* There is no need to restore the signal handler here, since the app
1786          * is going to exit */
1787 }
1788
1789 static void __remote_quit_handler(int num)
1790 {
1791         sig_flags.need_quit = 1;
1792 }
1793
1794 static const char *fix_header(char *outbuf, int maxout, const char *s, char *cmp)
1795 {
1796         const char *c;
1797
1798         if (!strncmp(s, cmp, strlen(cmp))) {
1799                 c = s + strlen(cmp);
1800                 term_color(outbuf, cmp, COLOR_GRAY, 0, maxout);
1801                 return c;
1802         }
1803         return NULL;
1804 }
1805
1806 /* These gymnastics are due to platforms which designate char as unsigned by
1807  * default. Level is the negative character -- offset by 1, because \0 is the
1808  * EOS delimiter. */
1809 #define VERBOSE_MAGIC2LEVEL(x) (((char) -*(signed char *) (x)) - 1)
1810 #define VERBOSE_HASMAGIC(x)     (*(signed char *) (x) < 0)
1811
1812 static void console_verboser(const char *s)
1813 {
1814         char tmp[80];
1815         const char *c = NULL;
1816         char level = 0;
1817
1818         if (VERBOSE_HASMAGIC(s)) {
1819                 level = VERBOSE_MAGIC2LEVEL(s);
1820                 s++;
1821                 if (level > option_verbose) {
1822                         return;
1823                 }
1824         }
1825
1826         if ((c = fix_header(tmp, sizeof(tmp), s, VERBOSE_PREFIX_4)) ||
1827             (c = fix_header(tmp, sizeof(tmp), s, VERBOSE_PREFIX_3)) ||
1828             (c = fix_header(tmp, sizeof(tmp), s, VERBOSE_PREFIX_2)) ||
1829             (c = fix_header(tmp, sizeof(tmp), s, VERBOSE_PREFIX_1))) {
1830                 fputs(tmp, stdout);
1831                 fputs(c, stdout);
1832         } else {
1833                 fputs(s, stdout);
1834         }
1835
1836         fflush(stdout);
1837
1838         /* Wake up a poll()ing console */
1839         if (ast_opt_console && consolethread != AST_PTHREADT_NULL) {
1840                 pthread_kill(consolethread, SIGURG);
1841         }
1842 }
1843
1844 static int ast_all_zeros(char *s)
1845 {
1846         while (*s) {
1847                 if (*s > 32)
1848                         return 0;
1849                 s++;
1850         }
1851         return 1;
1852 }
1853
1854 static void consolehandler(char *s)
1855 {
1856         printf("%s", term_end());
1857         fflush(stdout);
1858
1859         /* Called when readline data is available */
1860         if (!ast_all_zeros(s))
1861                 ast_el_add_history(s);
1862         /* The real handler for bang */
1863         if (s[0] == '!') {
1864                 if (s[1])
1865                         ast_safe_system(s+1);
1866                 else
1867                         ast_safe_system(getenv("SHELL") ? getenv("SHELL") : "/bin/sh");
1868         } else
1869                 ast_cli_command(STDOUT_FILENO, s);
1870 }
1871
1872 static int remoteconsolehandler(char *s)
1873 {
1874         int ret = 0;
1875
1876         /* Called when readline data is available */
1877         if (!ast_all_zeros(s))
1878                 ast_el_add_history(s);
1879         /* The real handler for bang */
1880         if (s[0] == '!') {
1881                 if (s[1])
1882                         ast_safe_system(s+1);
1883                 else
1884                         ast_safe_system(getenv("SHELL") ? getenv("SHELL") : "/bin/sh");
1885                 ret = 1;
1886         } else if (strncasecmp(s, "core set verbose ", 17) == 0) {
1887                 int old_verbose = option_verbose;
1888                 if (strncasecmp(s + 17, "atleast ", 8) == 0) {
1889                         int tmp;
1890                         if (sscanf(s + 25, "%d", &tmp) != 1) {
1891                                 fprintf(stderr, "Usage: core set verbose [atleast] <level>\n");
1892                         } else {
1893                                 if (tmp > option_verbose) {
1894                                         option_verbose = tmp;
1895                                 }
1896                                 if (old_verbose != option_verbose) {
1897                                         fprintf(stdout, "Set remote console verbosity from %d to %d\n", old_verbose, option_verbose);
1898                                 } else {
1899                                         fprintf(stdout, "Verbosity level unchanged.\n");
1900                                 }
1901                         }
1902                 } else {
1903                         if (sscanf(s + 17, "%d", &option_verbose) != 1) {
1904                                 fprintf(stderr, "Usage: core set verbose [atleast] <level>\n");
1905                         } else {
1906                                 if (old_verbose != option_verbose) {
1907                                         fprintf(stdout, "Set remote console verbosity to %d\n", option_verbose);
1908                                 } else {
1909                                         fprintf(stdout, "Verbosity level unchanged.\n");
1910                                 }
1911                         }
1912                 }
1913                 ret = 1;
1914         } else if ((strncasecmp(s, "quit", 4) == 0 || strncasecmp(s, "exit", 4) == 0) &&
1915             (s[4] == '\0' || isspace(s[4]))) {
1916                 quit_handler(0, SHUTDOWN_FAST, 0);
1917                 ret = 1;
1918         }
1919
1920         return ret;
1921 }
1922
1923 static char *handle_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1924 {
1925         switch (cmd) {
1926         case CLI_INIT:
1927                 e->command = "core show version";
1928                 e->usage =
1929                         "Usage: core show version\n"
1930                         "       Shows Asterisk version information.\n";
1931                 return NULL;
1932         case CLI_GENERATE:
1933                 return NULL;
1934         }
1935
1936         if (a->argc != 3)
1937                 return CLI_SHOWUSAGE;
1938         ast_cli(a->fd, "Asterisk %s built by %s @ %s on a %s running %s on %s\n",
1939                 ast_get_version(), ast_build_user, ast_build_hostname,
1940                 ast_build_machine, ast_build_os, ast_build_date);
1941         return CLI_SUCCESS;
1942 }
1943
1944 #if 0
1945 static int handle_quit(int fd, int argc, char *argv[])
1946 {
1947         if (argc != 1)
1948                 return RESULT_SHOWUSAGE;
1949         quit_handler(0, SHUTDOWN_NORMAL, 0);
1950         return RESULT_SUCCESS;
1951 }
1952 #endif
1953
1954 static char *handle_stop_now(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1955 {
1956         switch (cmd) {
1957         case CLI_INIT:
1958                 e->command = "core stop now";
1959                 e->usage =
1960                         "Usage: core stop now\n"
1961                         "       Shuts down a running Asterisk immediately, hanging up all active calls .\n";
1962                 return NULL;
1963         case CLI_GENERATE:
1964                 return NULL;
1965         }
1966
1967         if (a->argc != e->args)
1968                 return CLI_SHOWUSAGE;
1969         quit_handler(0, SHUTDOWN_NORMAL, 0 /* not restart */);
1970         return CLI_SUCCESS;
1971 }
1972
1973 static char *handle_stop_gracefully(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1974 {
1975         switch (cmd) {
1976         case CLI_INIT:
1977                 e->command = "core stop gracefully";
1978                 e->usage =
1979                         "Usage: core stop gracefully\n"
1980                         "       Causes Asterisk to not accept new calls, and exit when all\n"
1981                         "       active calls have terminated normally.\n";
1982                 return NULL;
1983         case CLI_GENERATE:
1984                 return NULL;
1985         }
1986
1987         if (a->argc != e->args)
1988                 return CLI_SHOWUSAGE;
1989         quit_handler(0, SHUTDOWN_NICE, 0 /* no restart */);
1990         return CLI_SUCCESS;
1991 }
1992
1993 static char *handle_stop_when_convenient(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1994 {
1995         switch (cmd) {
1996         case CLI_INIT:
1997                 e->command = "core stop when convenient";
1998                 e->usage =
1999                         "Usage: core stop when convenient\n"
2000                         "       Causes Asterisk to perform a shutdown when all active calls have ended.\n";
2001                 return NULL;
2002         case CLI_GENERATE:
2003                 return NULL;
2004         }
2005
2006         if (a->argc != e->args)
2007                 return CLI_SHOWUSAGE;
2008         ast_cli(a->fd, "Waiting for inactivity to perform halt\n");
2009         quit_handler(0, SHUTDOWN_REALLY_NICE, 0 /* don't restart */);
2010         return CLI_SUCCESS;
2011 }
2012
2013 static char *handle_restart_now(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2014 {
2015         switch (cmd) {
2016         case CLI_INIT:
2017                 e->command = "core restart now";
2018                 e->usage =
2019                         "Usage: core restart now\n"
2020                         "       Causes Asterisk to hangup all calls and exec() itself performing a cold\n"
2021                         "       restart.\n";
2022                 return NULL;
2023         case CLI_GENERATE:
2024                 return NULL;
2025         }
2026
2027         if (a->argc != e->args)
2028                 return CLI_SHOWUSAGE;
2029         quit_handler(0, SHUTDOWN_NORMAL, 1 /* restart */);
2030         return CLI_SUCCESS;
2031 }
2032
2033 static char *handle_restart_gracefully(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2034 {
2035         switch (cmd) {
2036         case CLI_INIT:
2037                 e->command = "core restart gracefully";
2038                 e->usage =
2039                         "Usage: core restart gracefully\n"
2040                         "       Causes Asterisk to stop accepting new calls and exec() itself performing a cold\n"
2041                         "       restart when all active calls have ended.\n";
2042                 return NULL;
2043         case CLI_GENERATE:
2044                 return NULL;
2045         }
2046
2047         if (a->argc != e->args)
2048                 return CLI_SHOWUSAGE;
2049         quit_handler(0, SHUTDOWN_NICE, 1 /* restart */);
2050         return CLI_SUCCESS;
2051 }
2052
2053 static char *handle_restart_when_convenient(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2054 {
2055         switch (cmd) {
2056         case CLI_INIT:
2057                 e->command = "core restart when convenient";
2058                 e->usage =
2059                         "Usage: core restart when convenient\n"
2060                         "       Causes Asterisk to perform a cold restart when all active calls have ended.\n";
2061                 return NULL;
2062         case CLI_GENERATE:
2063                 return NULL;
2064         }
2065
2066         if (a->argc != e->args)
2067                 return CLI_SHOWUSAGE;
2068         ast_cli(a->fd, "Waiting for inactivity to perform restart\n");
2069         quit_handler(0, SHUTDOWN_REALLY_NICE, 1 /* restart */);
2070         return CLI_SUCCESS;
2071 }
2072
2073 static char *handle_abort_shutdown(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2074 {
2075         int aborting_shutdown = 0;
2076
2077         switch (cmd) {
2078         case CLI_INIT:
2079                 e->command = "core abort shutdown";
2080                 e->usage =
2081                         "Usage: core abort shutdown\n"
2082                         "       Causes Asterisk to abort an executing shutdown or restart, and resume normal\n"
2083                         "       call operations.\n";
2084                 return NULL;
2085         case CLI_GENERATE:
2086                 return NULL;
2087         }
2088
2089         if (a->argc != e->args)
2090                 return CLI_SHOWUSAGE;
2091
2092         ast_mutex_lock(&safe_system_lock);
2093         if (shuttingdown >= SHUTDOWN_FAST) {
2094                 aborting_shutdown = 1;
2095                 shuttingdown = NOT_SHUTTING_DOWN;
2096         }
2097         ast_mutex_unlock(&safe_system_lock);
2098
2099         if (aborting_shutdown) {
2100                 ast_cancel_shutdown();
2101         }
2102         return CLI_SUCCESS;
2103 }
2104
2105 static char *handle_bang(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2106 {
2107         switch (cmd) {
2108         case CLI_INIT:
2109                 e->command = "!";
2110                 e->usage =
2111                         "Usage: !<command>\n"
2112                         "       Executes a given shell command\n";
2113                 return NULL;
2114         case CLI_GENERATE:
2115                 return NULL;
2116         }
2117
2118         return CLI_SUCCESS;
2119 }
2120 static const char warranty_lines[] = {
2121         "\n"
2122         "                           NO WARRANTY\n"
2123         "\n"
2124         "BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY\n"
2125         "FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN\n"
2126         "OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES\n"
2127         "PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED\n"
2128         "OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\n"
2129         "MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS\n"
2130         "TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE\n"
2131         "PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,\n"
2132         "REPAIR OR CORRECTION.\n"
2133         "\n"
2134         "IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\n"
2135         "WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR\n"
2136         "REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,\n"
2137         "INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING\n"
2138         "OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED\n"
2139         "TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY\n"
2140         "YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER\n"
2141         "PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE\n"
2142         "POSSIBILITY OF SUCH DAMAGES.\n"
2143 };
2144
2145 static char *show_warranty(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2146 {
2147         switch (cmd) {
2148         case CLI_INIT:
2149                 e->command = "core show warranty";
2150                 e->usage =
2151                         "Usage: core show warranty\n"
2152                         "       Shows the warranty (if any) for this copy of Asterisk.\n";
2153                 return NULL;
2154         case CLI_GENERATE:
2155                 return NULL;
2156         }
2157
2158         ast_cli(a->fd, "%s", warranty_lines);
2159
2160         return CLI_SUCCESS;
2161 }
2162
2163 static const char license_lines[] = {
2164         "\n"
2165         "This program is free software; you can redistribute it and/or modify\n"
2166         "it under the terms of the GNU General Public License version 2 as\n"
2167         "published by the Free Software Foundation.\n"
2168         "\n"
2169         "This program also contains components licensed under other licenses.\n"
2170         "They include:\n"
2171         "\n"
2172         "This program is distributed in the hope that it will be useful,\n"
2173         "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
2174         "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
2175         "GNU General Public License for more details.\n"
2176         "\n"
2177         "You should have received a copy of the GNU General Public License\n"
2178         "along with this program; if not, write to the Free Software\n"
2179         "Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n"
2180 };
2181
2182 static char *show_license(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2183 {
2184         switch (cmd) {
2185         case CLI_INIT:
2186                 e->command = "core show license";
2187                 e->usage =
2188                         "Usage: core show license\n"
2189                         "       Shows the license(s) for this copy of Asterisk.\n";
2190                 return NULL;
2191         case CLI_GENERATE:
2192                 return NULL;
2193         }
2194
2195         ast_cli(a->fd, "%s", license_lines);
2196
2197         return CLI_SUCCESS;
2198 }
2199
2200 #define ASTERISK_PROMPT "*CLI> "
2201
2202 #define ASTERISK_PROMPT2 "%s*CLI> "
2203
2204 static struct ast_cli_entry cli_asterisk[] = {
2205         AST_CLI_DEFINE(handle_abort_shutdown, "Cancel a running shutdown"),
2206         AST_CLI_DEFINE(handle_stop_now, "Shut down Asterisk immediately"),
2207         AST_CLI_DEFINE(handle_stop_gracefully, "Gracefully shut down Asterisk"),
2208         AST_CLI_DEFINE(handle_stop_when_convenient, "Shut down Asterisk at empty call volume"),
2209         AST_CLI_DEFINE(handle_restart_now, "Restart Asterisk immediately"),
2210         AST_CLI_DEFINE(handle_restart_gracefully, "Restart Asterisk gracefully"),
2211         AST_CLI_DEFINE(handle_restart_when_convenient, "Restart Asterisk at empty call volume"),
2212         AST_CLI_DEFINE(show_warranty, "Show the warranty (if any) for this copy of Asterisk"),
2213         AST_CLI_DEFINE(show_license, "Show the license(s) for this copy of Asterisk"),
2214         AST_CLI_DEFINE(handle_version, "Display version info"),
2215         AST_CLI_DEFINE(handle_bang, "Execute a shell command"),
2216 #if !defined(LOW_MEMORY)
2217         AST_CLI_DEFINE(handle_show_version_files, "List versions of files used to build Asterisk"),
2218         AST_CLI_DEFINE(handle_show_threads, "Show running threads"),
2219 #if defined(HAVE_SYSINFO) || defined(HAVE_SYSCTL)
2220         AST_CLI_DEFINE(handle_show_sysinfo, "Show System Information"),
2221 #endif
2222         AST_CLI_DEFINE(handle_show_profile, "Display profiling info"),
2223         AST_CLI_DEFINE(handle_show_settings, "Show some core settings"),
2224         AST_CLI_DEFINE(handle_clear_profile, "Clear profiling info"),
2225 #endif /* ! LOW_MEMORY */
2226 };
2227
2228 struct el_read_char_state_struct {
2229         unsigned int line_full:1;
2230         unsigned int prev_line_full:1;
2231         char prev_line_verbosity;
2232 };
2233
2234 static int el_read_char_state_init(void *ptr)
2235 {
2236         struct el_read_char_state_struct *state = ptr;
2237         state->line_full = 1;
2238         state->prev_line_full = 1;
2239         state->prev_line_verbosity = 0;
2240         return 0;
2241 }
2242
2243 AST_THREADSTORAGE_CUSTOM(el_read_char_state, el_read_char_state_init, ast_free_ptr);
2244
2245 static int ast_el_read_char(EditLine *editline, char *cp)
2246 {
2247         int num_read = 0;
2248         int lastpos = 0;
2249         struct pollfd fds[2];
2250         int res;
2251         int max;
2252 #define EL_BUF_SIZE 512
2253         char buf[EL_BUF_SIZE];
2254         struct el_read_char_state_struct *state = ast_threadstorage_get(&el_read_char_state, sizeof(*state));
2255
2256         for (;;) {
2257                 max = 1;
2258                 fds[0].fd = ast_consock;
2259                 fds[0].events = POLLIN;
2260                 if (!ast_opt_exec) {
2261                         fds[1].fd = STDIN_FILENO;
2262                         fds[1].events = POLLIN;
2263                         max++;
2264                 }
2265                 res = ast_poll(fds, max, -1);
2266                 if (res < 0) {
2267                         if (sig_flags.need_quit || sig_flags.need_quit_handler)
2268                                 break;
2269                         if (errno == EINTR)
2270                                 continue;
2271                         ast_log(LOG_ERROR, "poll failed: %s\n", strerror(errno));
2272                         break;
2273                 }
2274
2275                 if (!ast_opt_exec && fds[1].revents) {
2276                         num_read = read(STDIN_FILENO, cp, 1);
2277                         if (num_read < 1) {
2278                                 break;
2279                         } else {
2280                                 return (num_read);
2281                         }
2282                 }
2283                 if (fds[0].revents) {
2284                         char level = 0;
2285                         char *curline = buf, *nextline;
2286                         res = read(ast_consock, buf, sizeof(buf) - 1);
2287                         /* if the remote side disappears exit */
2288                         if (res < 1) {
2289                                 fprintf(stderr, "\nDisconnected from Asterisk server\n");
2290                                 if (!ast_opt_reconnect) {
2291                                         quit_handler(0, SHUTDOWN_FAST, 0);
2292                                 } else {
2293                                         int tries;
2294                                         int reconnects_per_second = 20;
2295                                         fprintf(stderr, "Attempting to reconnect for 30 seconds\n");
2296                                         for (tries = 0; tries < 30 * reconnects_per_second; tries++) {
2297                                                 if (ast_tryconnect()) {
2298                                                         fprintf(stderr, "Reconnect succeeded after %.3f seconds\n", 1.0 / reconnects_per_second * tries);
2299                                                         printf("%s", term_quit());
2300                                                         WELCOME_MESSAGE;
2301                                                         if (!ast_opt_mute)
2302                                                                 fdsend(ast_consock, "logger mute silent");
2303                                                         else
2304                                                                 printf("log and verbose output currently muted ('logger mute' to unmute)\n");
2305                                                         break;
2306                                                 } else
2307                                                         usleep(1000000 / reconnects_per_second);
2308                                         }
2309                                         if (tries >= 30 * reconnects_per_second) {
2310                                                 fprintf(stderr, "Failed to reconnect for 30 seconds.  Quitting.\n");
2311                                                 quit_handler(0, SHUTDOWN_FAST, 0);
2312                                         }
2313                                 }
2314                         }
2315
2316                         buf[res] = '\0';
2317
2318                         /* Write over the CLI prompt */
2319                         if (!ast_opt_exec && !lastpos) {
2320                                 if (write(STDOUT_FILENO, "\r\e[0K", 5) < 0) {
2321                                 }
2322                         }
2323
2324                         do {
2325                                 state->prev_line_full = state->line_full;
2326                                 if ((nextline = strchr(curline, '\n'))) {
2327                                         state->line_full = 1;
2328                                         nextline++;
2329                                 } else {
2330                                         state->line_full = 0;
2331                                         nextline = strchr(curline, '\0');
2332                                 }
2333
2334                                 if (state->prev_line_full && VERBOSE_HASMAGIC(curline)) {
2335                                         level = VERBOSE_MAGIC2LEVEL(curline);
2336                                         curline++;
2337                                 } else if (state->prev_line_full && !VERBOSE_HASMAGIC(curline)) {
2338                                         /* Non-verbose output */
2339                                         level = 0;
2340                                 } else {
2341                                         level = state->prev_line_verbosity;
2342                                 }
2343                                 if ((!state->prev_line_full && state->prev_line_verbosity <= option_verbose) || (state->prev_line_full && level <= option_verbose)) {
2344                                         if (write(STDOUT_FILENO, curline, nextline - curline) < 0) {
2345                                         }
2346                                 }
2347
2348                                 state->prev_line_verbosity = level;
2349                                 curline = nextline;
2350                         } while (!ast_strlen_zero(curline));
2351
2352                         if ((res < EL_BUF_SIZE - 1) && ((buf[res-1] == '\n') || (buf[res-2] == '\n'))) {
2353                                 *cp = CC_REFRESH;
2354                                 return(1);
2355                         } else
2356                                 lastpos = 1;
2357                 }
2358         }
2359
2360         *cp = '\0';
2361         return (0);
2362 }
2363
2364 static struct ast_str *prompt = NULL;
2365
2366 static char *cli_prompt(EditLine *editline)
2367 {
2368         char tmp[100];
2369         char *pfmt;
2370         int color_used = 0;
2371         static int cli_prompt_changes = 0;
2372         char term_code[20];
2373         struct passwd *pw;
2374         struct group *gr;
2375
2376         if (prompt == NULL) {
2377                 prompt = ast_str_create(100);
2378         } else if (!cli_prompt_changes) {
2379                 return ast_str_buffer(prompt);
2380         } else {
2381                 ast_str_reset(prompt);
2382         }
2383
2384         if ((pfmt = getenv("ASTERISK_PROMPT"))) {
2385                 char *t = pfmt;
2386                 struct timeval ts = ast_tvnow();
2387                 while (*t != '\0') {
2388                         if (*t == '%') {
2389                                 char hostname[MAXHOSTNAMELEN] = "";
2390                                 int i, which;
2391                                 struct ast_tm tm = { 0, };
2392                                 int fgcolor = COLOR_WHITE, bgcolor = COLOR_BLACK;
2393
2394                                 t++;
2395                                 switch (*t) {
2396                                 case 'C': /* color */
2397                                         t++;
2398                                         if (sscanf(t, "%30d;%30d%n", &fgcolor, &bgcolor, &i) == 2) {
2399                                                 ast_str_append(&prompt, 0, "%s", term_color_code(term_code, fgcolor, bgcolor, sizeof(term_code)));
2400                                                 t += i - 1;
2401                                         } else if (sscanf(t, "%30d%n", &fgcolor, &i) == 1) {
2402                                                 ast_str_append(&prompt, 0, "%s", term_color_code(term_code, fgcolor, 0, sizeof(term_code)));
2403                                                 t += i - 1;
2404                                         }
2405
2406                                         /* If the color has been reset correctly, then there's no need to reset it later */
2407                                         color_used = ((fgcolor == COLOR_WHITE) && (bgcolor == COLOR_BLACK)) ? 0 : 1;
2408                                         break;
2409                                 case 'd': /* date */
2410                                         if (ast_localtime(&ts, &tm, NULL)) {
2411                                                 ast_strftime(tmp, sizeof(tmp), "%Y-%m-%d", &tm);
2412                                                 ast_str_append(&prompt, 0, "%s", tmp);
2413                                                 cli_prompt_changes++;
2414                                         }
2415                                         break;
2416                                 case 'g': /* group */
2417                                         if ((gr = getgrgid(getgid()))) {
2418                                                 ast_str_append(&prompt, 0, "%s", gr->gr_name);
2419                                         }
2420                                         break;
2421                                 case 'h': /* hostname */
2422                                         if (!gethostname(hostname, sizeof(hostname) - 1)) {
2423                                                 ast_str_append(&prompt, 0, "%s", hostname);
2424                                         } else {
2425                                                 ast_str_append(&prompt, 0, "%s", "localhost");
2426                                         }
2427                                         break;
2428                                 case 'H': /* short hostname */
2429                                         if (!gethostname(hostname, sizeof(hostname) - 1)) {
2430                                                 char *dotptr;
2431                                                 if ((dotptr = strchr(hostname, '.'))) {
2432                                                         *dotptr = '\0';
2433                                                 }
2434                                                 ast_str_append(&prompt, 0, "%s", hostname);
2435                                         } else {
2436                                                 ast_str_append(&prompt, 0, "%s", "localhost");
2437                                         }
2438                                         break;
2439 #ifdef HAVE_GETLOADAVG
2440                                 case 'l': /* load avg */
2441                                         t++;
2442                                         if (sscanf(t, "%30d", &which) == 1 && which > 0 && which <= 3) {
2443                                                 double list[3];
2444                                                 getloadavg(list, 3);
2445                                                 ast_str_append(&prompt, 0, "%.2f", list[which - 1]);
2446                                                 cli_prompt_changes++;
2447                                         }
2448                                         break;
2449 #endif
2450                                 case 's': /* Asterisk system name (from asterisk.conf) */
2451                                         ast_str_append(&prompt, 0, "%s", ast_config_AST_SYSTEM_NAME);
2452                                         break;
2453                                 case 't': /* time */
2454                                         if (ast_localtime(&ts, &tm, NULL)) {
2455                                                 ast_strftime(tmp, sizeof(tmp), "%H:%M:%S", &tm);
2456                                                 ast_str_append(&prompt, 0, "%s", tmp);
2457                                                 cli_prompt_changes++;
2458                                         }
2459                                         break;
2460                                 case 'u': /* username */
2461                                         if ((pw = getpwuid(getuid()))) {
2462                                                 ast_str_append(&prompt, 0, "%s", pw->pw_name);
2463                                         }
2464                                         break;
2465                                 case '#': /* process console or remote? */
2466                                         ast_str_append(&prompt, 0, "%c", ast_opt_remote ? '>' : '#');
2467                                         break;
2468                                 case '%': /* literal % */
2469                                         ast_str_append(&prompt, 0, "%c", '%');
2470                                         break;
2471                                 case '\0': /* % is last character - prevent bug */
2472                                         t--;
2473                                         break;
2474                                 }
2475                         } else {
2476                                 ast_str_append(&prompt, 0, "%c", *t);
2477                         }
2478                         t++;
2479                 }
2480                 if (color_used) {
2481                         /* Force colors back to normal at end */
2482                         ast_str_append(&prompt, 0, "%s", term_color_code(term_code, 0, 0, sizeof(term_code)));
2483                 }
2484         } else if (remotehostname) {
2485                 ast_str_set(&prompt, 0, ASTERISK_PROMPT2, remotehostname);
2486         } else {
2487                 ast_str_set(&prompt, 0, "%s", ASTERISK_PROMPT);
2488         }
2489
2490         return ast_str_buffer(prompt);
2491 }
2492
2493 static char **ast_el_strtoarr(char *buf)
2494 {
2495         char **match_list = NULL, **match_list_tmp, *retstr;
2496         size_t match_list_len;
2497         int matches = 0;
2498
2499         match_list_len = 1;
2500         while ( (retstr = strsep(&buf, " ")) != NULL) {
2501
2502                 if (!strcmp(retstr, AST_CLI_COMPLETE_EOF))
2503                         break;
2504                 if (matches + 1 >= match_list_len) {
2505                         match_list_len <<= 1;
2506                         if ((match_list_tmp = ast_realloc(match_list, match_list_len * sizeof(char *)))) {
2507                                 match_list = match_list_tmp;
2508                         } else {
2509                                 if (match_list)
2510                                         ast_free(match_list);
2511                                 return (char **) NULL;
2512                         }
2513                 }
2514
2515                 match_list[matches++] = ast_strdup(retstr);
2516         }
2517
2518         if (!match_list)
2519                 return (char **) NULL;
2520
2521         if (matches >= match_list_len) {
2522                 if ((match_list_tmp = ast_realloc(match_list, (match_list_len + 1) * sizeof(char *)))) {
2523                         match_list = match_list_tmp;
2524                 } else {
2525                         if (match_list)
2526                                 ast_free(match_list);
2527                         return (char **) NULL;
2528                 }
2529         }
2530
2531         match_list[matches] = (char *) NULL;
2532
2533         return match_list;
2534 }
2535
2536 static int ast_el_sort_compare(const void *i1, const void *i2)
2537 {
2538         char *s1, *s2;
2539
2540         s1 = ((char **)i1)[0];
2541         s2 = ((char **)i2)[0];
2542
2543         return strcasecmp(s1, s2);
2544 }
2545
2546 static int ast_cli_display_match_list(char **matches, int len, int max)
2547 {
2548         int i, idx, limit, count;
2549         int screenwidth = 0;
2550         int numoutput = 0, numoutputline = 0;
2551
2552         screenwidth = ast_get_termcols(STDOUT_FILENO);
2553
2554         /* find out how many entries can be put on one line, with two spaces between strings */
2555         limit = screenwidth / (max + 2);
2556         if (limit == 0)
2557                 limit = 1;
2558
2559         /* how many lines of output */
2560         count = len / limit;
2561         if (count * limit < len)
2562                 count++;
2563
2564         idx = 1;
2565
2566         qsort(&matches[0], (size_t)(len), sizeof(char *), ast_el_sort_compare);
2567
2568         for (; count > 0; count--) {
2569                 numoutputline = 0;
2570                 for (i = 0; i < limit && matches[idx]; i++, idx++) {
2571
2572                         /* Don't print dupes */
2573                         if ( (matches[idx+1] != NULL && strcmp(matches[idx], matches[idx+1]) == 0 ) ) {
2574                                 i--;
2575                                 ast_free(matches[idx]);
2576                                 matches[idx] = NULL;
2577                                 continue;
2578                         }
2579
2580                         numoutput++;
2581                         numoutputline++;
2582                         fprintf(stdout, "%-*s  ", max, matches[idx]);
2583                         ast_free(matches[idx]);
2584                         matches[idx] = NULL;
2585                 }
2586                 if (numoutputline > 0)
2587                         fprintf(stdout, "\n");
2588         }
2589
2590         return numoutput;
2591 }
2592
2593
2594 static char *cli_complete(EditLine *editline, int ch)
2595 {
2596         int len = 0;
2597         char *ptr;
2598         int nummatches = 0;
2599         char **matches;
2600         int retval = CC_ERROR;
2601         char buf[2048], savechr;
2602         int res;
2603
2604         LineInfo *lf = (LineInfo *)el_line(editline);
2605
2606         savechr = *(char *)lf->cursor;
2607         *(char *)lf->cursor = '\0';
2608         ptr = (char *)lf->cursor;
2609         if (ptr) {
2610                 while (ptr > lf->buffer) {
2611                         if (isspace(*ptr)) {
2612                                 ptr++;
2613                                 break;
2614                         }
2615                         ptr--;
2616                 }
2617         }
2618
2619         len = lf->cursor - ptr;
2620
2621         if (ast_opt_remote) {
2622                 snprintf(buf, sizeof(buf), "_COMMAND NUMMATCHES \"%s\" \"%s\"", lf->buffer, ptr);
2623                 fdsend(ast_consock, buf);
2624                 res = read(ast_consock, buf, sizeof(buf) - 1);
2625                 buf[res] = '\0';
2626                 nummatches = atoi(buf);
2627
2628                 if (nummatches > 0) {
2629                         char *mbuf;
2630                         int mlen = 0, maxmbuf = 2048;
2631                         /* Start with a 2048 byte buffer */
2632                         if (!(mbuf = ast_malloc(maxmbuf))) {
2633                                 lf->cursor[0] = savechr;
2634                                 return (char *)(CC_ERROR);
2635                         }
2636                         snprintf(buf, sizeof(buf), "_COMMAND MATCHESARRAY \"%s\" \"%s\"", lf->buffer, ptr);
2637                         fdsend(ast_consock, buf);
2638                         res = 0;
2639                         mbuf[0] = '\0';
2640                         while (!strstr(mbuf, AST_CLI_COMPLETE_EOF) && res != -1) {
2641                                 if (mlen + 1024 > maxmbuf) {
2642                                         /* Every step increment buffer 1024 bytes */
2643                                         maxmbuf += 1024;
2644                                         if (!(mbuf = ast_realloc(mbuf, maxmbuf))) {
2645                                                 lf->cursor[0] = savechr;
2646                                                 return (char *)(CC_ERROR);
2647                                         }
2648                                 }
2649                                 /* Only read 1024 bytes at a time */
2650                                 res = read(ast_consock, mbuf + mlen, 1024);
2651                                 if (res > 0)
2652                                         mlen += res;
2653                         }
2654                         mbuf[mlen] = '\0';
2655
2656                         matches = ast_el_strtoarr(mbuf);
2657                         ast_free(mbuf);
2658                 } else
2659                         matches = (char **) NULL;
2660         } else {
2661                 char **p, *oldbuf=NULL;
2662                 nummatches = 0;
2663                 matches = ast_cli_completion_matches((char *)lf->buffer,ptr);
2664                 for (p = matches; p && *p; p++) {
2665                         if (!oldbuf || strcmp(*p,oldbuf))
2666                                 nummatches++;
2667                         oldbuf = *p;
2668                 }
2669         }
2670
2671         if (matches) {
2672                 int i;
2673                 int matches_num, maxlen, match_len;
2674
2675                 if (matches[0][0] != '\0') {
2676                         el_deletestr(editline, (int) len);
2677                         el_insertstr(editline, matches[0]);
2678                         retval = CC_REFRESH;
2679                 }
2680
2681                 if (nummatches == 1) {
2682                         /* Found an exact match */
2683                         el_insertstr(editline, " ");
2684                         retval = CC_REFRESH;
2685                 } else {
2686                         /* Must be more than one match */
2687                         for (i = 1, maxlen = 0; matches[i]; i++) {
2688                                 match_len = strlen(matches[i]);
2689                                 if (match_len > maxlen)
2690                                         maxlen = match_len;
2691                         }
2692                         matches_num = i - 1;
2693                         if (matches_num >1) {
2694                                 fprintf(stdout, "\n");
2695                                 ast_cli_display_match_list(matches, nummatches, maxlen);
2696                                 retval = CC_REDISPLAY;
2697                         } else {
2698                                 el_insertstr(editline," ");
2699                                 retval = CC_REFRESH;
2700                         }
2701                 }
2702                 for (i = 0; matches[i]; i++)
2703                         ast_free(matches[i]);
2704                 ast_free(matches);
2705         }
2706
2707         lf->cursor[0] = savechr;
2708
2709         return (char *)(long)retval;
2710 }
2711
2712 static int ast_el_initialize(void)
2713 {
2714         HistEvent ev;
2715         char *editor, *editrc = getenv("EDITRC");
2716
2717         if (!(editor = getenv("AST_EDITMODE"))) {
2718                 if (!(editor = getenv("AST_EDITOR"))) {
2719                         editor = "emacs";
2720                 }
2721         }
2722
2723         if (el != NULL)
2724                 el_end(el);
2725         if (el_hist != NULL)
2726                 history_end(el_hist);
2727
2728         el = el_init("asterisk", stdin, stdout, stderr);
2729         el_set(el, EL_PROMPT, cli_prompt);
2730
2731         el_set(el, EL_EDITMODE, 1);
2732         el_set(el, EL_EDITOR, editor);
2733         el_hist = history_init();
2734         if (!el || !el_hist)
2735                 return -1;
2736
2737         /* setup history with 100 entries */
2738         history(el_hist, &ev, H_SETSIZE, 100);
2739
2740         el_set(el, EL_HIST, history, el_hist);
2741
2742         el_set(el, EL_ADDFN, "ed-complete", "Complete argument", cli_complete);
2743         /* Bind <tab> to command completion */
2744         el_set(el, EL_BIND, "^I", "ed-complete", NULL);
2745         /* Bind ? to command completion */
2746         el_set(el, EL_BIND, "?", "ed-complete", NULL);
2747         /* Bind ^D to redisplay */
2748         el_set(el, EL_BIND, "^D", "ed-redisplay", NULL);
2749         /* Bind Delete to delete char left */
2750         el_set(el, EL_BIND, "\\e[3~", "ed-delete-next-char", NULL);
2751         /* Bind Home and End to move to line start and end */
2752         el_set(el, EL_BIND, "\\e[1~", "ed-move-to-beg", NULL);
2753         el_set(el, EL_BIND, "\\e[4~", "ed-move-to-end", NULL);
2754         /* Bind C-left and C-right to move by word (not all terminals) */
2755         el_set(el, EL_BIND, "\\eOC", "vi-next-word", NULL);
2756         el_set(el, EL_BIND, "\\eOD", "vi-prev-word", NULL);
2757
2758         if (editrc) {
2759                 el_source(el, editrc);
2760         }
2761
2762         return 0;
2763 }
2764
2765 #define MAX_HISTORY_COMMAND_LENGTH 256
2766
2767 static int ast_el_add_history(char *buf)
2768 {
2769         HistEvent ev;
2770
2771         if (el_hist == NULL || el == NULL)
2772                 ast_el_initialize();
2773         if (strlen(buf) > (MAX_HISTORY_COMMAND_LENGTH - 1))
2774                 return 0;
2775         return (history(el_hist, &ev, H_ENTER, ast_strip(ast_strdupa(buf))));
2776 }
2777
2778 static int ast_el_write_history(char *filename)
2779 {
2780         HistEvent ev;
2781
2782         if (el_hist == NULL || el == NULL)
2783                 ast_el_initialize();
2784
2785         return (history(el_hist, &ev, H_SAVE, filename));
2786 }
2787
2788 static int ast_el_read_history(char *filename)
2789 {
2790         char buf[MAX_HISTORY_COMMAND_LENGTH];
2791         FILE *f;
2792         int ret = -1;
2793
2794         if (el_hist == NULL || el == NULL)
2795                 ast_el_initialize();
2796
2797         if ((f = fopen(filename, "r")) == NULL)
2798                 return ret;
2799
2800         while (!feof(f)) {
2801                 if (!fgets(buf, sizeof(buf), f))
2802                         break;
2803                 if (!strcmp(buf, "_HiStOrY_V2_\n"))
2804                         continue;
2805                 if (ast_all_zeros(buf))
2806                         continue;
2807                 if ((ret = ast_el_add_history(buf)) == -1)
2808                         break;
2809         }
2810         fclose(f);
2811
2812         return ret;
2813 }
2814
2815 static void ast_remotecontrol(char *data)
2816 {
2817         char buf[80];
2818         int res;
2819         char filename[80] = "";
2820         char *hostname;
2821         char *cpid;
2822         char *version;
2823         int pid;
2824         char *stringp = NULL;
2825
2826         char *ebuf;
2827         int num = 0;
2828
2829         memset(&sig_flags, 0, sizeof(sig_flags));
2830         signal(SIGINT, __remote_quit_handler);
2831         signal(SIGTERM, __remote_quit_handler);
2832         signal(SIGHUP, __remote_quit_handler);
2833
2834         if (read(ast_consock, buf, sizeof(buf)) < 0) {
2835                 ast_log(LOG_ERROR, "read() failed: %s\n", strerror(errno));
2836                 return;
2837         }
2838         if (data) {
2839                 char prefix[] = "cli quit after ";
2840                 char *tmp = alloca(strlen(data) + strlen(prefix) + 1);
2841                 sprintf(tmp, "%s%s", prefix, data);
2842                 if (write(ast_consock, tmp, strlen(tmp) + 1) < 0) {
2843                         ast_log(LOG_ERROR, "write() failed: %s\n", strerror(errno));
2844                         if (sig_flags.need_quit || sig_flags.need_quit_handler) {
2845                                 return;
2846                         }
2847                 }
2848         }
2849         stringp = buf;
2850         hostname = strsep(&stringp, "/");
2851         cpid = strsep(&stringp, "/");
2852         version = strsep(&stringp, "\n");
2853         if (!version)
2854                 version = "<Version Unknown>";
2855         stringp = hostname;
2856         strsep(&stringp, ".");
2857         if (cpid)
2858                 pid = atoi(cpid);
2859         else
2860                 pid = -1;
2861         if (!data) {
2862                 if (!ast_opt_mute) {
2863                         fdsend(ast_consock, "logger mute silent");
2864                 } else {
2865                         printf("log and verbose output currently muted ('logger mute' to unmute)\n");
2866                 }
2867         }
2868
2869         if (ast_opt_exec && data) {  /* hack to print output then exit if asterisk -rx is used */
2870                 int linefull = 1, prev_linefull = 1, prev_line_verbose = 0;
2871                 struct pollfd fds;
2872                 fds.fd = ast_consock;
2873                 fds.events = POLLIN;
2874                 fds.revents = 0;
2875
2876                 while (ast_poll(&fds, 1, 60000) > 0) {
2877                         char buffer[512] = "", *curline = buffer, *nextline;
2878                         int not_written = 1;
2879
2880                         if (sig_flags.need_quit || sig_flags.need_quit_handler) {
2881                                 break;
2882                         }
2883
2884                         if (read(ast_consock, buffer, sizeof(buffer) - 1) <= 0) {
2885                                 break;
2886                         }
2887
2888                         do {
2889                                 prev_linefull = linefull;
2890                                 if ((nextline = strchr(curline, '\n'))) {
2891                                         linefull = 1;
2892                                         nextline++;
2893                                 } else {
2894                                         linefull = 0;
2895                                         nextline = strchr(curline, '\0');
2896                                 }
2897
2898                                 /* Skip verbose lines */
2899                                 /* Prev line full? | Line is verbose | Last line verbose? | Print
2900                                  * TRUE            | TRUE*           | TRUE               | FALSE
2901                                  * TRUE            | TRUE*           | FALSE              | FALSE
2902                                  * TRUE            | FALSE*          | TRUE               | TRUE
2903                                  * TRUE            | FALSE*          | FALSE              | TRUE
2904                                  * FALSE           | TRUE            | TRUE*              | FALSE
2905                                  * FALSE           | TRUE            | FALSE*             | TRUE
2906                                  * FALSE           | FALSE           | TRUE*              | FALSE
2907                                  * FALSE           | FALSE           | FALSE*             | TRUE
2908                                  */
2909                                 if ((!prev_linefull && !prev_line_verbose) || (prev_linefull && *curline > 0)) {
2910                                         prev_line_verbose = 0;
2911                                         not_written = 0;
2912                                         if (write(STDOUT_FILENO, curline, nextline - curline) < 0) {
2913                                                 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
2914                                         }
2915                                 } else {
2916                                         prev_line_verbose = 1;
2917                                 }
2918                                 curline = nextline;
2919                         } while (!ast_strlen_zero(curline));
2920
2921                         /* No non-verbose output in 60 seconds. */
2922                         if (not_written) {
2923                                 break;
2924                         }
2925                 }
2926                 return;
2927         }
2928
2929         ast_verbose("Connected to Asterisk %s currently running on %s (pid = %d)\n", version, hostname, pid);
2930         remotehostname = hostname;
2931         if (getenv("HOME"))
2932                 snprintf(filename, sizeof(filename), "%s/.asterisk_history", getenv("HOME"));
2933         if (el_hist == NULL || el == NULL)
2934                 ast_el_initialize();
2935
2936         el_set(el, EL_GETCFN, ast_el_read_char);
2937
2938         if (!ast_strlen_zero(filename))
2939                 ast_el_read_history(filename);
2940
2941         for (;;) {
2942                 ebuf = (char *)el_gets(el, &num);
2943
2944                 if (sig_flags.need_quit || sig_flags.need_quit_handler) {
2945                         break;
2946                 }
2947
2948                 if (!ebuf && write(1, "", 1) < 0)
2949                         break;
2950
2951                 if (!ast_strlen_zero(ebuf)) {
2952                         if (ebuf[strlen(ebuf)-1] == '\n')
2953                                 ebuf[strlen(ebuf)-1] = '\0';
2954                         if (!remoteconsolehandler(ebuf)) {
2955                                 res = write(ast_consock, ebuf, strlen(ebuf) + 1);
2956                                 if (res < 1) {
2957                                         ast_log(LOG_WARNING, "Unable to write: %s\n", strerror(errno));
2958                                         break;
2959                                 }
2960                         }
2961                 }
2962         }
2963         printf("\nDisconnected from Asterisk server\n");
2964 }
2965
2966 static int show_version(void)
2967 {
2968         printf("Asterisk %s\n", ast_get_version());
2969         return 0;
2970 }
2971
2972 static int show_cli_help(void)
2973 {
2974         printf("Asterisk %s, Copyright (C) 1999 - 2012, Digium, Inc. and others.\n", ast_get_version());
2975         printf("Usage: asterisk [OPTIONS]\n");
2976         printf("Valid Options:\n");
2977         printf("   -V              Display version number and exit\n");
2978         printf("   -C <configfile> Use an alternate configuration file\n");
2979         printf("   -G <group>      Run as a group other than the caller\n");
2980         printf("   -U <user>       Run as a user other than the caller\n");
2981         printf("   -c              Provide console CLI\n");
2982         printf("   -d              Enable extra debugging\n");
2983 #if HAVE_WORKING_FORK
2984         printf("   -f              Do not fork\n");
2985         printf("   -F              Always fork\n");
2986 #endif
2987         printf("   -g              Dump core in case of a crash\n");
2988         printf("   -h              This help screen\n");
2989         printf("   -i              Initialize crypto keys at startup\n");
2990         printf("   -I              Enable internal timing if DAHDI timer is available\n");
2991         printf("   -L <load>       Limit the maximum load average before rejecting new calls\n");
2992         printf("   -M <value>      Limit the maximum number of calls to the specified value\n");
2993         printf("   -m              Mute debugging and console output on the console\n");
2994         printf("   -n              Disable console colorization\n");
2995         printf("   -p              Run as pseudo-realtime thread\n");
2996         printf("   -q              Quiet mode (suppress output)\n");
2997         printf("   -r              Connect to Asterisk on this machine\n");
2998         printf("   -R              Same as -r, except attempt to reconnect if disconnected\n");
2999         printf("   -s <socket>     Connect to Asterisk via socket <socket> (only valid with -r)\n");
3000         printf("   -t              Record soundfiles in /var/tmp and move them where they\n");
3001         printf("                   belong after they are done\n");
3002         printf("   -T              Display the time in [Mmm dd hh:mm:ss] format for each line\n");
3003         printf("                   of output to the CLI\n");
3004         printf("   -v              Increase verbosity (multiple v's = more verbose)\n");
3005         printf("   -x <cmd>        Execute command <cmd> (implies -r)\n");
3006         printf("   -X              Execute includes by default (allows #exec in asterisk.conf)\n");
3007         printf("   -W              Adjust terminal colors to compensate for a light background\n");
3008         printf("\n");
3009         return 0;
3010 }
3011
3012 static void ast_readconfig(void)
3013 {
3014         struct ast_config *cfg;
3015         struct ast_variable *v;
3016         char *config = DEFAULT_CONFIG_FILE;
3017         char hostname[MAXHOSTNAMELEN] = "";
3018         struct ast_flags config_flags = { CONFIG_FLAG_NOREALTIME };
3019         struct {
3020                 unsigned int dbdir:1;
3021                 unsigned int keydir:1;
3022         } found = { 0, 0 };
3023
3024         if (ast_opt_override_config) {
3025                 cfg = ast_config_load2(ast_config_AST_CONFIG_FILE, "" /* core, can't reload */, config_flags);
3026                 if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEUNCHANGED || cfg == CONFIG_STATUS_FILEINVALID)
3027                         ast_log(LOG_WARNING, "Unable to open specified master config file '%s', using built-in defaults\n", ast_config_AST_CONFIG_FILE);
3028         } else
3029                 cfg = ast_config_load2(config, "" /* core, can't reload */, config_flags);
3030
3031         /* init with buildtime config */
3032         ast_copy_string(cfg_paths.config_dir, DEFAULT_CONFIG_DIR, sizeof(cfg_paths.config_dir));
3033         ast_copy_string(cfg_paths.spool_dir, DEFAULT_SPOOL_DIR, sizeof(cfg_paths.spool_dir));
3034         ast_copy_string(cfg_paths.module_dir, DEFAULT_MODULE_DIR, sizeof(cfg_paths.module_dir));
3035         snprintf(cfg_paths.monitor_dir, sizeof(cfg_paths.monitor_dir), "%s/monitor", cfg_paths.spool_dir);
3036         ast_copy_string(cfg_paths.var_dir, DEFAULT_VAR_DIR, sizeof(cfg_paths.var_dir));
3037         ast_copy_string(cfg_paths.data_dir, DEFAULT_DATA_DIR, sizeof(cfg_paths.data_dir));
3038         ast_copy_string(cfg_paths.log_dir, DEFAULT_LOG_DIR, sizeof(cfg_paths.log_dir));
3039         ast_copy_string(cfg_paths.agi_dir, DEFAULT_AGI_DIR, sizeof(cfg_paths.agi_dir));
3040         ast_copy_string(cfg_paths.db_path, DEFAULT_DB, sizeof(cfg_paths.db_path));
3041         ast_copy_string(cfg_paths.sbin_dir, DEFAULT_SBIN_DIR, sizeof(cfg_paths.sbin_dir));
3042         ast_copy_string(cfg_paths.key_dir, DEFAULT_KEY_DIR, sizeof(cfg_paths.key_dir));
3043         ast_copy_string(cfg_paths.pid_path, DEFAULT_PID, sizeof(cfg_paths.pid_path));
3044         ast_copy_string(cfg_paths.socket_path, DEFAULT_SOCKET, sizeof(cfg_paths.socket_path));
3045         ast_copy_string(cfg_paths.run_dir, DEFAULT_RUN_DIR, sizeof(cfg_paths.run_dir));
3046
3047         ast_set_default_eid(&ast_eid_default);
3048
3049         /* no asterisk.conf? no problem, use buildtime config! */
3050         if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEUNCHANGED || cfg == CONFIG_STATUS_FILEINVALID) {
3051                 return;
3052         }
3053
3054         for (v = ast_variable_browse(cfg, "files"); v; v = v->next) {
3055                 if (!strcasecmp(v->name, "astctlpermissions"))
3056                         ast_copy_string(ast_config_AST_CTL_PERMISSIONS, v->value, sizeof(ast_config_AST_CTL_PERMISSIONS));
3057                 else if (!strcasecmp(v->name, "astctlowner"))
3058                         ast_copy_string(ast_config_AST_CTL_OWNER, v->value, sizeof(ast_config_AST_CTL_OWNER));
3059                 else if (!strcasecmp(v->name, "astctlgroup"))
3060                         ast_copy_string(ast_config_AST_CTL_GROUP, v->value, sizeof(ast_config_AST_CTL_GROUP));
3061                 else if (!strcasecmp(v->name, "astctl"))
3062                         ast_copy_string(ast_config_AST_CTL, v->value, sizeof(ast_config_AST_CTL));
3063         }
3064
3065         for (v = ast_variable_browse(cfg, "directories"); v; v = v->next) {
3066                 if (!strcasecmp(v->name, "astetcdir")) {
3067                         ast_copy_string(cfg_paths.config_dir, v->value, sizeof(cfg_paths.config_dir));
3068                 } else if (!strcasecmp(v->name, "astspooldir")) {
3069                         ast_copy_string(cfg_paths.spool_dir, v->value, sizeof(cfg_paths.spool_dir));
3070                         snprintf(cfg_paths.monitor_dir, sizeof(cfg_paths.monitor_dir), "%s/monitor", v->value);
3071                 } else if (!strcasecmp(v->name, "astvarlibdir")) {
3072                         ast_copy_string(cfg_paths.var_dir, v->value, sizeof(cfg_paths.var_dir));
3073                         if (!found.dbdir)
3074                                 snprintf(cfg_paths.db_path, sizeof(cfg_paths.db_path), "%s/astdb", v->value);
3075                 } else if (!strcasecmp(v->name, "astdbdir")) {
3076                         snprintf(cfg_paths.db_path, sizeof(cfg_paths.db_path), "%s/astdb", v->value);
3077                         found.dbdir = 1;
3078                 } else if (!strcasecmp(v->name, "astdatadir")) {
3079                         ast_copy_string(cfg_paths.data_dir, v->value, sizeof(cfg_paths.data_dir));
3080                         if (!found.keydir)
3081                                 snprintf(cfg_paths.key_dir, sizeof(cfg_paths.key_dir), "%s/keys", v->value);
3082                 } else if (!strcasecmp(v->name, "astkeydir")) {
3083                         snprintf(cfg_paths.key_dir, sizeof(cfg_paths.key_dir), "%s/keys", v->value);
3084                         found.keydir = 1;
3085                 } else if (!strcasecmp(v->name, "astlogdir")) {
3086                         ast_copy_string(cfg_paths.log_dir, v->value, sizeof(cfg_paths.log_dir));
3087                 } else if (!strcasecmp(v->name, "astagidir")) {
3088                         ast_copy_string(cfg_paths.agi_dir, v->value, sizeof(cfg_paths.agi_dir));
3089                 } else if (!strcasecmp(v->name, "astrundir")) {
3090                         snprintf(cfg_paths.pid_path, sizeof(cfg_paths.pid_path), "%s/%s", v->value, "asterisk.pid");
3091                         snprintf(cfg_paths.socket_path, sizeof(cfg_paths.socket_path), "%s/%s", v->value, ast_config_AST_CTL);
3092                         ast_copy_string(cfg_paths.run_dir, v->value, sizeof(cfg_paths.run_dir));
3093                 } else if (!strcasecmp(v->name, "astmoddir")) {
3094                         ast_copy_string(cfg_paths.module_dir, v->value, sizeof(cfg_paths.module_dir));
3095                 } else if (!strcasecmp(v->name, "astsbindir")) {
3096                         ast_copy_string(cfg_paths.sbin_dir, v->value, sizeof(cfg_paths.sbin_dir));
3097                 }
3098         }
3099
3100         for (v = ast_variable_browse(cfg, "options"); v; v = v->next) {
3101                 /* verbose level (-v at startup) */
3102                 if (!strcasecmp(v->name, "verbose")) {
3103                         option_verbose = atoi(v->value);
3104                 /* whether or not to force timestamping in CLI verbose output. (-T at startup) */
3105                 } else if (!strcasecmp(v->name, "timestamp")) {
3106                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_TIMESTAMP);
3107                 /* whether or not to support #exec in config files */
3108                 } else if (!strcasecmp(v->name, "execincludes")) {
3109                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_EXEC_INCLUDES);
3110                 /* debug level (-d at startup) */
3111                 } else if (!strcasecmp(v->name, "debug")) {
3112                         option_debug = 0;
3113                         if (sscanf(v->value, "%30d", &option_debug) != 1) {
3114                                 option_debug = ast_true(v->value);
3115                         }
3116 #if HAVE_WORKING_FORK
3117                 /* Disable forking (-f at startup) */
3118                 } else if (!strcasecmp(v->name, "nofork")) {
3119                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_NO_FORK);
3120                 /* Always fork, even if verbose or debug are enabled (-F at startup) */
3121                 } else if (!strcasecmp(v->name, "alwaysfork")) {
3122                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_ALWAYS_FORK);
3123 #endif
3124                 /* Run quietly (-q at startup ) */
3125                 } else if (!strcasecmp(v->name, "quiet")) {
3126                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_QUIET);
3127                 /* Run as console (-c at startup, implies nofork) */
3128                 } else if (!strcasecmp(v->name, "console")) {
3129                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_NO_FORK | AST_OPT_FLAG_CONSOLE);
3130                 /* Run with high priority if the O/S permits (-p at startup) */
3131                 } else if (!strcasecmp(v->name, "highpriority")) {
3132                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_HIGH_PRIORITY);
3133                 /* Initialize RSA auth keys (IAX2) (-i at startup) */
3134                 } else if (!strcasecmp(v->name, "initcrypto")) {
3135                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_INIT_KEYS);
3136                 /* Disable ANSI colors for console (-c at startup) */
3137                 } else if (!strcasecmp(v->name, "nocolor")) {
3138                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_NO_COLOR);
3139                 /* Disable some usage warnings for picky people :p */
3140                 } else if (!strcasecmp(v->name, "dontwarn")) {
3141                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_DONT_WARN);
3142                 /* Dump core in case of crash (-g) */
3143                 } else if (!strcasecmp(v->name, "dumpcore")) {
3144                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_DUMP_CORE);
3145                 /* Cache recorded sound files to another directory during recording */
3146                 } else if (!strcasecmp(v->name, "cache_record_files")) {
3147                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_CACHE_RECORD_FILES);
3148                 /* Specify cache directory */
3149                 }  else if (!strcasecmp(v->name, "record_cache_dir")) {
3150                         ast_copy_string(record_cache_dir, v->value, AST_CACHE_DIR_LEN);
3151                 /* Build transcode paths via SLINEAR, instead of directly */
3152                 } else if (!strcasecmp(v->name, "transcode_via_sln")) {
3153                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_TRANSCODE_VIA_SLIN);
3154                 /* Transmit SLINEAR silence while a channel is being recorded or DTMF is being generated on a channel */
3155                 } else if (!strcasecmp(v->name, "transmit_silence_during_record") || !strcasecmp(v->name, "transmit_silence")) {
3156                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_TRANSMIT_SILENCE);
3157                 /* Enable internal timing */
3158                 } else if (!strcasecmp(v->name, "internal_timing")) {
3159                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_INTERNAL_TIMING);
3160                 } else if (!strcasecmp(v->name, "maxcalls")) {
3161                         if ((sscanf(v->value, "%30d", &option_maxcalls) != 1) || (option_maxcalls < 0)) {
3162                                 option_maxcalls = 0;
3163                         }
3164                 } else if (!strcasecmp(v->name, "maxload")) {
3165                         double test[1];
3166
3167                         if (getloadavg(test, 1) == -1) {
3168                                 ast_log(LOG_ERROR, "Cannot obtain load average on this system. 'maxload' option disabled.\n");
3169                                 option_maxload = 0.0;
3170                         } else if ((sscanf(v->value, "%30lf", &option_maxload) != 1) || (option_maxload < 0.0)) {
3171                                 option_maxload = 0.0;
3172                         }
3173                 /* Set the maximum amount of open files */
3174                 } else if (!strcasecmp(v->name, "maxfiles")) {
3175                         option_maxfiles = atoi(v->value);
3176                         set_ulimit(option_maxfiles);
3177                 /* What user to run as */
3178                 } else if (!strcasecmp(v->name, "runuser")) {
3179                         ast_copy_string(cfg_paths.run_user, v->value, sizeof(cfg_paths.run_user));
3180                 /* What group to run as */
3181                 } else if (!strcasecmp(v->name, "rungroup")) {
3182                         ast_copy_string(cfg_paths.run_group, v->value, sizeof(cfg_paths.run_group));
3183                 } else if (!strcasecmp(v->name, "systemname")) {
3184                         ast_copy_string(cfg_paths.system_name, v->value, sizeof(cfg_paths.system_name));
3185                 } else if (!strcasecmp(v->name, "autosystemname")) {
3186                         if (ast_true(v->value)) {
3187                                 if (!gethostname(hostname, sizeof(hostname) - 1))
3188                                         ast_copy_string(cfg_paths.system_name, hostname, sizeof(cfg_paths.system_name));
3189                                 else {
3190                                         if (ast_strlen_zero(ast_config_AST_SYSTEM_NAME)){
3191                                                 ast_copy_string(cfg_paths.system_name, "localhost", sizeof(cfg_paths.system_name));
3192                                         }
3193                                         ast_log(LOG_ERROR, "Cannot obtain hostname for this system.  Using '%s' instead.\n", ast_config_AST_SYSTEM_NAME);
3194                                 }
3195                         }
3196                 } else if (!strcasecmp(v->name, "languageprefix")) {
3197                         ast_language_is_prefix = ast_true(v->value);
3198                 } else if (!strcasecmp(v->name, "defaultlanguage")) {
3199                         ast_copy_string(defaultlanguage, v->value, MAX_LANGUAGE);
3200                 } else if (!strcasecmp(v->name, "lockmode")) {
3201                         if (!strcasecmp(v->value, "lockfile")) {
3202                                 ast_set_lock_type(AST_LOCK_TYPE_LOCKFILE);
3203                         } else if (!strcasecmp(v->value, "flock")) {
3204                                 ast_set_lock_type(AST_LOCK_TYPE_FLOCK);
3205                         } else {
3206                                 ast_log(LOG_WARNING, "'%s' is not a valid setting for the lockmode option, "
3207                                         "defaulting to 'lockfile'\n", v->value);
3208                                 ast_set_lock_type(AST_LOCK_TYPE_LOCKFILE);
3209                         }
3210 #if defined(HAVE_SYSINFO)
3211                 } else if (!strcasecmp(v->name, "minmemfree")) {
3212                         /* specify the minimum amount of free memory to retain.  Asterisk should stop accepting new calls
3213                          * if the amount of free memory falls below this watermark */
3214                         if ((sscanf(v->value, "%30ld", &option_minmemfree) != 1) || (option_minmemfree < 0)) {
3215                                 option_minmemfree = 0;
3216                         }
3217 #endif
3218                 } else if (!strcasecmp(v->name, "entityid")) {
3219                         struct ast_eid tmp_eid;
3220                         if (!ast_str_to_eid(&tmp_eid, v->value)) {
3221                                 ast_verbose("Successfully set global EID to '%s'\n", v->value);
3222                                 ast_eid_default = tmp_eid;
3223                         } else
3224                                 ast_verbose("Invalid Entity ID '%s' provided\n", v->value);
3225                 } else if (!strcasecmp(v->name, "lightbackground")) {
3226                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_LIGHT_BACKGROUND);
3227                 } else if (!strcasecmp(v->name, "forceblackbackground")) {
3228                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_FORCE_BLACK_BACKGROUND);
3229                 } else if (!strcasecmp(v->name, "hideconnect")) {
3230                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_HIDE_CONSOLE_CONNECT);
3231                 } else if (!strcasecmp(v->name, "lockconfdir")) {
3232                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_LOCK_CONFIG_DIR);
3233                 } else if (!strcasecmp(v->name, "stdexten")) {
3234                         /* Choose how to invoke the extensions.conf stdexten */
3235                         if (!strcasecmp(v->value, "gosub")) {
3236                                 ast_clear_flag(&ast_options, AST_OPT_FLAG_STDEXTEN_MACRO);
3237                         } else if (!strcasecmp(v->value, "macro")) {
3238                                 ast_set_flag(&ast_options, AST_OPT_FLAG_STDEXTEN_MACRO);
3239                         } else {
3240                                 ast_log(LOG_WARNING,
3241                                         "'%s' is not a valid setting for the stdexten option, defaulting to 'gosub'\n",
3242                                         v->value);
3243                                 ast_clear_flag(&ast_options, AST_OPT_FLAG_STDEXTEN_MACRO);
3244                         }
3245                 }
3246         }
3247         for (v = ast_variable_browse(cfg, "compat"); v; v = v->next) {
3248                 float version;
3249                 if (sscanf(v->value, "%30f", &version) != 1) {
3250                         ast_log(LOG_WARNING, "Compatibility version for option '%s' is not a number: '%s'\n", v->name, v->value);
3251                         continue;
3252                 }
3253                 if (!strcasecmp(v->name, "app_set")) {
3254                         ast_set2_flag(&ast_compat, version < 1.5 ? 1 : 0, AST_COMPAT_APP_SET);
3255                 } else if (!strcasecmp(v->name, "res_agi")) {
3256                         ast_set2_flag(&ast_compat, version < 1.5 ? 1 : 0, AST_COMPAT_DELIM_RES_AGI);
3257                 } else if (!strcasecmp(v->name, "pbx_realtime")) {
3258                         ast_set2_flag(&ast_compat, version < 1.5 ? 1 : 0, AST_COMPAT_DELIM_PBX_REALTIME);
3259                 }
3260         }
3261         ast_config_destroy(cfg);
3262 }
3263
3264 static void *monitor_sig_flags(void *unused)
3265 {
3266         for (;;) {
3267                 struct pollfd p = { sig_alert_pipe[0], POLLIN, 0 };
3268                 int a;
3269                 ast_poll(&p, 1, -1);
3270                 if (sig_flags.need_reload) {
3271                         sig_flags.need_reload = 0;
3272                         ast_module_reload(NULL);
3273                 }
3274                 if (sig_flags.need_quit) {
3275                         sig_flags.need_quit = 0;
3276                         if ((consolethread != AST_PTHREADT_NULL) && (consolethread != pthread_self())) {
3277                                 sig_flags.need_quit_handler = 1;
3278                                 pthread_kill(consolethread, SIGURG);
3279                         } else {
3280                                 quit_handler(0, SHUTDOWN_NORMAL, 0);
3281                         }
3282                 }
3283                 if (read(sig_alert_pipe[0], &a, sizeof(a)) != sizeof(a)) {
3284                 }
3285         }
3286
3287         return NULL;
3288 }
3289
3290 static void *canary_thread(void *unused)
3291 {
3292         struct stat canary_stat;
3293         struct timeval now;
3294
3295         /* Give the canary time to sing */
3296         sleep(120);
3297
3298         for (;;) {
3299                 stat(canary_filename, &canary_stat);
3300                 now = ast_tvnow();
3301                 if (now.tv_sec > canary_stat.st_mtime + 60) {
3302                         ast_log(LOG_WARNING,
3303                                 "The canary is no more.  He has ceased to be!  "
3304                                 "He's expired and gone to meet his maker!  "
3305                                 "He's a stiff!  Bereft of life, he rests in peace.  "
3306                                 "His metabolic processes are now history!  He's off the twig!  "
3307                                 "He's kicked the bucket.  He's shuffled off his mortal coil, "
3308                                 "run down the curtain, and joined the bleeding choir invisible!!  "
3309                                 "THIS is an EX-CANARY.  (Reducing priority)\n");
3310                         ast_set_priority(0);
3311                         pthread_exit(NULL);
3312                 }
3313
3314                 /* Check the canary once a minute */
3315                 sleep(60);
3316         }
3317 }
3318
3319 /* Used by libc's atexit(3) function */
3320 static void canary_exit(void)
3321 {
3322         if (canary_pid > 0)
3323                 kill(canary_pid, SIGKILL);
3324 }
3325
3326 static void run_startup_commands(void)
3327 {
3328         int fd;
3329         struct ast_config *cfg;
3330         struct ast_flags cfg_flags = { 0 };
3331         struct ast_variable *v;
3332
3333         if (!(cfg = ast_config_load2("cli.conf", "" /* core, can't reload */, cfg_flags)))
3334                 return;
3335         if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEUNCHANGED || cfg == CONFIG_STATUS_FILEINVALID) {
3336                 return;
3337         }
3338
3339         fd = open("/dev/null", O_RDWR);
3340         if (fd < 0) {
3341                 ast_config_destroy(cfg);
3342                 return;
3343         }
3344
3345         for (v = ast_variable_browse(cfg, "startup_commands"); v; v = v->next) {
3346                 if (ast_true(v->value))
3347                         ast_cli_command(fd, v->name);
3348         }
3349
3350         close(fd);
3351         ast_config_destroy(cfg);
3352 }
3353
3354 static void env_init(void)
3355 {
3356         setenv("AST_SYSTEMNAME", ast_config_AST_SYSTEM_NAME, 1);
3357         setenv("AST_BUILD_HOST", ast_build_hostname, 1);
3358         setenv("AST_BUILD_DATE", ast_build_date, 1);
3359         setenv("AST_BUILD_KERNEL", ast_build_kernel, 1);
3360         setenv("AST_BUILD_MACHINE", ast_build_machine, 1);
3361         setenv("AST_BUILD_OS", ast_build_os, 1);
3362         setenv("AST_BUILD_USER", ast_build_user, 1);
3363         setenv("AST_VERSION", ast_get_version(), 1);
3364 }
3365
3366 int main(int argc, char *argv[])
3367 {
3368         int c;
3369         char filename[80] = "";
3370         char hostname[MAXHOSTNAMELEN] = "";
3371         char tmp[80];
3372         char * xarg = NULL;
3373         int x;
3374         FILE *f;
3375         sigset_t sigs;
3376         int num;
3377         int isroot = 1, rundir_exists = 0;
3378         char *buf;
3379         const char *runuser = NULL, *rungroup = NULL;
3380         char *remotesock = NULL;
3381         int moduleresult;         /*!< Result from the module load subsystem */
3382         struct rlimit l;
3383
3384         /* Remember original args for restart */
3385         if (argc > ARRAY_LEN(_argv) - 1) {
3386                 fprintf(stderr, "Truncating argument size to %d\n", (int)ARRAY_LEN(_argv) - 1);
3387                 argc = ARRAY_LEN(_argv) - 1;
3388         }
3389         for (x = 0; x < argc; x++)
3390                 _argv[x] = argv[x];
3391         _argv[x] = NULL;
3392
3393         if (geteuid() != 0)
3394                 isroot = 0;
3395
3396         /* if the progname is rasterisk consider it a remote console */
3397         if (argv[0] && (strstr(argv[0], "rasterisk")) != NULL) {
3398                 ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK | AST_OPT_FLAG_REMOTE);
3399         }
3400         if (gethostname(hostname, sizeof(hostname)-1))
3401                 ast_copy_string(hostname, "<Unknown>", sizeof(hostname));
3402         ast_mainpid = getpid();
3403         ast_ulaw_init();
3404         ast_alaw_init();
3405         callerid_init();
3406         ast_builtins_init();
3407         ast_utils_init();
3408         tdd_init();
3409         ast_tps_init();
3410         ast_fd_init();
3411         ast_pbx_init();
3412
3413         if (getenv("HOME"))
3414                 snprintf(filename, sizeof(filename), "%s/.asterisk_history", getenv("HOME"));
3415         /* Check for options */
3416         while ((c = getopt(argc, argv, "BC:cde:FfG:ghIiL:M:mnpqRrs:TtU:VvWXx:")) != -1) {
3417                 /*!\note Please keep the ordering here to alphabetical, capital letters
3418                  * first.  This will make it easier in the future to select unused
3419                  * option flags for new features. */
3420                 switch (c) {
3421                 case 'B': /* Force black background */
3422                         ast_set_flag(&ast_options, AST_OPT_FLAG_FORCE_BLACK_BACKGROUND);
3423                         ast_clear_flag(&ast_options, AST_OPT_FLAG_LIGHT_BACKGROUND);
3424                         break;
3425                 case 'X':
3426                         ast_set_flag(&ast_options, AST_OPT_FLAG_EXEC_INCLUDES);
3427                         break;
3428                 case 'C':
3429                         ast_copy_string(cfg_paths.config_file, optarg, sizeof(cfg_paths.config_file));
3430                         ast_set_flag(&ast_options, AST_OPT_FLAG_OVERRIDE_CONFIG);
3431                         break;
3432                 case 'c':
3433                         ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK | AST_OPT_FLAG_CONSOLE);
3434                         break;
3435                 case 'd':
3436                         option_debug++;
3437                         ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK);
3438                         break;
3439 #if defined(HAVE_SYSINFO)
3440                 case 'e':
3441                         if ((sscanf(&optarg[1], "%30ld", &option_minmemfree) != 1) || (option_minmemfree < 0)) {
3442                                 option_minmemfree = 0;
3443                         }
3444                         break;
3445 #endif
3446 #if HAVE_WORKING_FORK
3447                 case 'F':
3448                         ast_set_flag(&ast_options, AST_OPT_FLAG_ALWAYS_FORK);
3449                         break;
3450                 case 'f':
3451                         ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK);
3452                         break;
3453 #endif
3454                 case 'G':
3455                         rungroup = ast_strdupa(optarg);
3456                         break;
3457                 case 'g':
3458                         ast_set_flag(&ast_options, AST_OPT_FLAG_DUMP_CORE);
3459                         break;
3460                 case 'h':
3461                         show_cli_help();
3462                         exit(0);
3463                 case 'I':
3464                         ast_set_flag(&ast_options, AST_OPT_FLAG_INTERNAL_TIMING);
3465                         break;
3466                 case 'i':
3467                         ast_set_flag(&ast_options, AST_OPT_FLAG_INIT_KEYS);
3468                         break;
3469                 case 'L':
3470                         if ((sscanf(optarg, "%30lf", &option_maxload) != 1) || (option_maxload < 0.0)) {
3471                                 option_maxload = 0.0;
3472                         }
3473                         break;
3474                 case 'M':
3475                         if ((sscanf(optarg, "%30d", &option_maxcalls) != 1) || (option_maxcalls < 0)) {
3476                                 option_maxcalls = 0;
3477                         }
3478                         break;
3479                 case 'm':
3480                         ast_set_flag(&ast_options, AST_OPT_FLAG_MUTE);
3481                         break;
3482                 case 'n':
3483                         ast_set_flag(&ast_options, AST_OPT_FLAG_NO_COLOR);
3484                         break;
3485                 case 'p':
3486                         ast_set_flag(&ast_options, AST_OPT_FLAG_HIGH_PRIORITY);
3487                         break;
3488                 case 'q':
3489                         ast_set_flag(&ast_options, AST_OPT_FLAG_QUIET);
3490                         break;
3491                 case 'R':
3492                         ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK | AST_OPT_FLAG_REMOTE | AST_OPT_FLAG_RECONNECT);
3493                         break;
3494                 case 'r':
3495                         ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK | AST_OPT_FLAG_REMOTE);
3496                         break;
3497                 case 's':
3498                         remotesock = ast_strdupa(optarg);
3499                         break;
3500                 case 'T':
3501                         ast_set_flag(&ast_options, AST_OPT_FLAG_TIMESTAMP);
3502                         break;
3503                 case 't':
3504                         ast_set_flag(&ast_options, AST_OPT_FLAG_CACHE_RECORD_FILES);
3505                         break;
3506                 case 'U':
3507                         runuser = ast_strdupa(optarg);
3508                         break;
3509                 case 'V':
3510                         show_version();
3511                         exit(0);
3512                 case 'v':
3513                         option_verbose++;
3514                         ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK);
3515                         break;
3516                 case 'W': /* White background */
3517                         ast_set_flag(&ast_options, AST_OPT_FLAG_LIGHT_BACKGROUND);
3518                         ast_clear_flag(&ast_options, AST_OPT_FLAG_FORCE_BLACK_BACKGROUND);
3519                         break;
3520                 case 'x':
3521                         /* -r is implied by -x so set the flags -r sets as well. */
3522                         ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK | AST_OPT_FLAG_REMOTE);
3523
3524                         ast_set_flag(&ast_options, AST_OPT_FLAG_EXEC | AST_OPT_FLAG_NO_COLOR);
3525                         xarg = ast_strdupa(optarg);
3526                         break;
3527                 case '?':
3528                         exit(1);
3529                 }
3530         }
3531
3532         if (ast_opt_console || option_verbose || (ast_opt_remote && !ast_opt_exec)) {
3533                 if (ast_register_verbose(console_verboser)) {
3534                         ast_log(LOG_WARNING, "Unable to register console verboser?\n");
3535                 }
3536                 WELCOME_MESSAGE;
3537         }
3538
3539         if (ast_opt_console && !option_verbose)
3540                 ast_verbose("[ Booting...\n");
3541
3542         /* For remote connections, change the name of the remote connection.
3543          * We do this for the benefit of init scripts (which need to know if/when
3544          * the main asterisk process has died yet). */
3545         if (ast_opt_remote) {
3546                 strcpy(argv[0], "rasterisk");
3547                 for (x = 1; x < argc; x++) {
3548                         argv[x] = argv[0] + 10;
3549                 }
3550         }
3551
3552         if (ast_opt_console && !option_verbose) {
3553                 ast_verbose("[ Reading Master Configuration ]\n");
3554         }
3555
3556         ast_readconfig();
3557         env_init();
3558
3559         if (ast_opt_remote && remotesock != NULL)
3560                 ast_copy_string((char *) cfg_paths.socket_path, remotesock, sizeof(cfg_paths.socket_path));
3561
3562         if (!ast_language_is_prefix && !ast_opt_remote)
3563                 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");
3564
3565         if (ast_opt_always_fork && (ast_opt_remote || ast_opt_console)) {
3566                 ast_log(LOG_WARNING, "'alwaysfork' is not compatible with console or remote console mode; ignored\n");
3567                 ast_clear_flag(&ast_options, AST_OPT_FLAG_ALWAYS_FORK);
3568         }
3569
3570         if (ast_opt_dump_core) {
3571                 memset(&l, 0, sizeof(l));
3572                 l.rlim_cur = RLIM_INFINITY;
3573                 l.rlim_max = RLIM_INFINITY;