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