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