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