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