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