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