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