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