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