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