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