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