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