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