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