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