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