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