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