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