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