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