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