5d3e572105398516afa828c935a97af7bb550a44
[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
147 /*! \defgroup main_options Main Configuration Options
148  \brief Main configuration options from \ref Config_ast "asterisk.conf" or 
149   the operating system command line when starting Asterisk 
150   Some of them can be changed in the CLI 
151  */
152 /*! @{ */
153
154 extern int ast_language_is_prefix;      /* XXX move to some header */
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 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[2][0])) {
452                         min = atoi(argv[2]);
453                         if (argc == 4 && strcmp(argv[3], "-"))
454                                 max = atoi(argv[3]);
455                 } else
456                         search = argv[2];
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 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 an X-term or screen title */
1017 static void set_title(char *text)
1018 {
1019         if (getenv("TERM") && strstr(getenv("TERM"), "xterm"))
1020                 fprintf(stdout, "\033]2;%s\007", text);
1021 }
1022
1023 static void set_icon(char *text)
1024 {
1025         if (getenv("TERM") && strstr(getenv("TERM"), "xterm"))
1026                 fprintf(stdout, "\033]1;%s\007", text);
1027 }
1028
1029 /*! \brief We set ourselves to a high priority, that we might pre-empt everything
1030    else.  If your PBX has heavy activity on it, this is a good thing.  */
1031 int ast_set_priority(int pri)
1032 {
1033         struct sched_param sched;
1034         memset(&sched, 0, sizeof(sched));
1035 #ifdef __linux__
1036         if (pri) {  
1037                 sched.sched_priority = 10;
1038                 if (sched_setscheduler(0, SCHED_RR, &sched)) {
1039                         ast_log(LOG_WARNING, "Unable to set high priority\n");
1040                         return -1;
1041                 } else
1042                         if (option_verbose)
1043                                 ast_verbose("Set to realtime thread\n");
1044         } else {
1045                 sched.sched_priority = 0;
1046                 if (sched_setscheduler(0, SCHED_OTHER, &sched)) {
1047                         ast_log(LOG_WARNING, "Unable to set normal priority\n");
1048                         return -1;
1049                 }
1050         }
1051 #else
1052         if (pri) {
1053                 if (setpriority(PRIO_PROCESS, 0, -10) == -1) {
1054                         ast_log(LOG_WARNING, "Unable to set high priority\n");
1055                         return -1;
1056                 } else
1057                         if (option_verbose)
1058                                 ast_verbose("Set to high priority\n");
1059         } else {
1060                 if (setpriority(PRIO_PROCESS, 0, 0) == -1) {
1061                         ast_log(LOG_WARNING, "Unable to set normal priority\n");
1062                         return -1;
1063                 }
1064         }
1065 #endif
1066         return 0;
1067 }
1068
1069 static void ast_run_atexits(void)
1070 {
1071         struct ast_atexit *ae;
1072         AST_LIST_LOCK(&atexits);
1073         AST_LIST_TRAVERSE(&atexits, ae, list) {
1074                 if (ae->func) 
1075                         ae->func();
1076         }
1077         AST_LIST_UNLOCK(&atexits);
1078 }
1079
1080 static void quit_handler(int num, int nice, int safeshutdown, int restart)
1081 {
1082         char filename[80] = "";
1083         time_t s,e;
1084         int x;
1085         /* Try to get as many CDRs as possible submitted to the backend engines (if in batch mode) */
1086         ast_cdr_engine_term();
1087         if (safeshutdown) {
1088                 shuttingdown = 1;
1089                 if (!nice) {
1090                         /* Begin shutdown routine, hanging up active channels */
1091                         ast_begin_shutdown(1);
1092                         if (option_verbose && ast_opt_console)
1093                                 ast_verbose("Beginning asterisk %s....\n", restart ? "restart" : "shutdown");
1094                         time(&s);
1095                         for (;;) {
1096                                 time(&e);
1097                                 /* Wait up to 15 seconds for all channels to go away */
1098                                 if ((e - s) > 15)
1099                                         break;
1100                                 if (!ast_active_channels())
1101                                         break;
1102                                 if (!shuttingdown)
1103                                         break;
1104                                 /* Sleep 1/10 of a second */
1105                                 usleep(100000);
1106                         }
1107                 } else {
1108                         if (nice < 2)
1109                                 ast_begin_shutdown(0);
1110                         if (option_verbose && ast_opt_console)
1111                                 ast_verbose("Waiting for inactivity to perform %s...\n", restart ? "restart" : "halt");
1112                         for (;;) {
1113                                 if (!ast_active_channels())
1114                                         break;
1115                                 if (!shuttingdown)
1116                                         break;
1117                                 sleep(1);
1118                         }
1119                 }
1120
1121                 if (!shuttingdown) {
1122                         if (option_verbose && ast_opt_console)
1123                                 ast_verbose("Asterisk %s cancelled.\n", restart ? "restart" : "shutdown");
1124                         return;
1125                 }
1126         }
1127         if (ast_opt_console || ast_opt_remote) {
1128                 if (getenv("HOME")) 
1129                         snprintf(filename, sizeof(filename), "%s/.asterisk_history", getenv("HOME"));
1130                 if (!ast_strlen_zero(filename))
1131                         ast_el_write_history(filename);
1132                 if (el != NULL)
1133                         el_end(el);
1134                 if (el_hist != NULL)
1135                         history_end(el_hist);
1136         }
1137         if (option_verbose)
1138                 ast_verbose("Executing last minute cleanups\n");
1139         ast_run_atexits();
1140         /* Called on exit */
1141         if (option_verbose && ast_opt_console)
1142                 ast_verbose("Asterisk %s ending (%d).\n", ast_active_channels() ? "uncleanly" : "cleanly", num);
1143         if (option_debug)
1144                 ast_log(LOG_DEBUG, "Asterisk ending (%d).\n", num);
1145         manager_event(EVENT_FLAG_SYSTEM, "Shutdown", "Shutdown: %s\r\nRestart: %s\r\n", ast_active_channels() ? "Uncleanly" : "Cleanly", restart ? "True" : "False");
1146         if (ast_socket > -1) {
1147                 pthread_cancel(lthread);
1148                 close(ast_socket);
1149                 ast_socket = -1;
1150                 unlink(ast_config_AST_SOCKET);
1151         }
1152         if (ast_consock > -1)
1153                 close(ast_consock);
1154         if (!ast_opt_remote)
1155                 unlink(ast_config_AST_PID);
1156         printf(term_quit());
1157         if (restart) {
1158                 if (option_verbose || ast_opt_console)
1159                         ast_verbose("Preparing for Asterisk restart...\n");
1160                 /* Mark all FD's for closing on exec */
1161                 for (x=3; x < 32768; x++) {
1162                         fcntl(x, F_SETFD, FD_CLOEXEC);
1163                 }
1164                 if (option_verbose || ast_opt_console)
1165                         ast_verbose("Restarting Asterisk NOW...\n");
1166                 restartnow = 1;
1167
1168                 /* close logger */
1169                 close_logger();
1170
1171                 /* If there is a consolethread running send it a SIGHUP 
1172                    so it can execvp, otherwise we can do it ourselves */
1173                 if ((consolethread != AST_PTHREADT_NULL) && (consolethread != pthread_self())) {
1174                         pthread_kill(consolethread, SIGHUP);
1175                         /* Give the signal handler some time to complete */
1176                         sleep(2);
1177                 } else
1178                         execvp(_argv[0], _argv);
1179         
1180         } else {
1181                 /* close logger */
1182                 close_logger();
1183         }
1184         exit(0);
1185 }
1186
1187 static void __quit_handler(int num)
1188 {
1189         quit_handler(num, 0, 1, 0);
1190 }
1191
1192 static const char *fix_header(char *outbuf, int maxout, const char *s, char *cmp)
1193 {
1194         const char *c;
1195         if (!strncmp(s, cmp, strlen(cmp))) {
1196                 c = s + strlen(cmp);
1197                 term_color(outbuf, cmp, COLOR_GRAY, 0, maxout);
1198                 return c;
1199         }
1200         return NULL;
1201 }
1202
1203 static void console_verboser(const char *s)
1204 {
1205         char tmp[80];
1206         const char *c = NULL;
1207
1208         if ((c = fix_header(tmp, sizeof(tmp), s, VERBOSE_PREFIX_4)) ||
1209             (c = fix_header(tmp, sizeof(tmp), s, VERBOSE_PREFIX_3)) ||
1210             (c = fix_header(tmp, sizeof(tmp), s, VERBOSE_PREFIX_2)) ||
1211             (c = fix_header(tmp, sizeof(tmp), s, VERBOSE_PREFIX_1))) {
1212                 fputs(tmp, stdout);
1213                 fputs(c, stdout);
1214         } else
1215                 fputs(s, stdout);
1216
1217         fflush(stdout);
1218         
1219         /* Wake up a poll()ing console */
1220         if (ast_opt_console && consolethread != AST_PTHREADT_NULL)
1221                 pthread_kill(consolethread, SIGURG);
1222 }
1223
1224 static int ast_all_zeros(char *s)
1225 {
1226         while (*s) {
1227                 if (*s > 32)
1228                         return 0;
1229                 s++;  
1230         }
1231         return 1;
1232 }
1233
1234 static void consolehandler(char *s)
1235 {
1236         printf(term_end());
1237         fflush(stdout);
1238
1239         /* Called when readline data is available */
1240         if (!ast_all_zeros(s))
1241                 ast_el_add_history(s);
1242         /* The real handler for bang */
1243         if (s[0] == '!') {
1244                 if (s[1])
1245                         ast_safe_system(s+1);
1246                 else
1247                         ast_safe_system(getenv("SHELL") ? getenv("SHELL") : "/bin/sh");
1248         } else 
1249                 ast_cli_command(STDOUT_FILENO, s);
1250 }
1251
1252 static int remoteconsolehandler(char *s)
1253 {
1254         int ret = 0;
1255
1256         /* Called when readline data is available */
1257         if (!ast_all_zeros(s))
1258                 ast_el_add_history(s);
1259         /* The real handler for bang */
1260         if (s[0] == '!') {
1261                 if (s[1])
1262                         ast_safe_system(s+1);
1263                 else
1264                         ast_safe_system(getenv("SHELL") ? getenv("SHELL") : "/bin/sh");
1265                 ret = 1;
1266         }
1267         if ((strncasecmp(s, "quit", 4) == 0 || strncasecmp(s, "exit", 4) == 0) &&
1268             (s[4] == '\0' || isspace(s[4]))) {
1269                 quit_handler(0, 0, 0, 0);
1270                 ret = 1;
1271         }
1272
1273         return ret;
1274 }
1275
1276 static char abort_halt_help[] = 
1277 "Usage: abort shutdown\n"
1278 "       Causes Asterisk to abort an executing shutdown or restart, and resume normal\n"
1279 "       call operations.\n";
1280
1281 static char shutdown_now_help[] = 
1282 "Usage: stop now\n"
1283 "       Shuts down a running Asterisk immediately, hanging up all active calls .\n";
1284
1285 static char shutdown_gracefully_help[] = 
1286 "Usage: stop gracefully\n"
1287 "       Causes Asterisk to not accept new calls, and exit when all\n"
1288 "       active calls have terminated normally.\n";
1289
1290 static char shutdown_when_convenient_help[] = 
1291 "Usage: stop when convenient\n"
1292 "       Causes Asterisk to perform a shutdown when all active calls have ended.\n";
1293
1294 static char restart_now_help[] = 
1295 "Usage: restart now\n"
1296 "       Causes Asterisk to hangup all calls and exec() itself performing a cold\n"
1297 "       restart.\n";
1298
1299 static char restart_gracefully_help[] = 
1300 "Usage: restart gracefully\n"
1301 "       Causes Asterisk to stop accepting new calls and exec() itself performing a cold\n"
1302 "       restart when all active calls have ended.\n";
1303
1304 static char restart_when_convenient_help[] = 
1305 "Usage: restart when convenient\n"
1306 "       Causes Asterisk to perform a cold restart when all active calls have ended.\n";
1307
1308 static char bang_help[] =
1309 "Usage: !<command>\n"
1310 "       Executes a given shell command\n";
1311
1312 static char show_warranty_help[] =
1313 "Usage: core show warranty\n"
1314 "       Shows the warranty (if any) for this copy of Asterisk.\n";
1315
1316 static char show_license_help[] =
1317 "Usage: core show license\n"
1318 "       Shows the license(s) for this copy of Asterisk.\n";
1319
1320 static char version_help[] =
1321 "Usage: core show version\n"
1322 "       Shows Asterisk version information.\n";
1323
1324 static int handle_version(int fd, int argc, char *argv[])
1325 {
1326         if (argc != 2)
1327                 return RESULT_SHOWUSAGE;
1328         ast_cli(fd, "Asterisk %s built by %s @ %s on a %s running %s on %s\n",
1329                 ASTERISK_VERSION, ast_build_user, ast_build_hostname,
1330                 ast_build_machine, ast_build_os, ast_build_date);
1331         return RESULT_SUCCESS;
1332 }
1333
1334 #if 0
1335 static int handle_quit(int fd, int argc, char *argv[])
1336 {
1337         if (argc != 1)
1338                 return RESULT_SHOWUSAGE;
1339         quit_handler(0, 0, 1, 0);
1340         return RESULT_SUCCESS;
1341 }
1342 #endif
1343
1344 static int handle_shutdown_now(int fd, int argc, char *argv[])
1345 {
1346         if (argc != 2)
1347                 return RESULT_SHOWUSAGE;
1348         quit_handler(0, 0 /* Not nice */, 1 /* safely */, 0 /* not restart */);
1349         return RESULT_SUCCESS;
1350 }
1351
1352 static int handle_shutdown_gracefully(int fd, int argc, char *argv[])
1353 {
1354         if (argc != 2)
1355                 return RESULT_SHOWUSAGE;
1356         quit_handler(0, 1 /* nicely */, 1 /* safely */, 0 /* no restart */);
1357         return RESULT_SUCCESS;
1358 }
1359
1360 static int handle_shutdown_when_convenient(int fd, int argc, char *argv[])
1361 {
1362         if (argc != 3)
1363                 return RESULT_SHOWUSAGE;
1364         ast_cli(fd, "Waiting for inactivity to perform halt\n");
1365         quit_handler(0, 2 /* really nicely */, 1 /* safely */, 0 /* don't restart */);
1366         return RESULT_SUCCESS;
1367 }
1368
1369 static int handle_restart_now(int fd, int argc, char *argv[])
1370 {
1371         if (argc != 2)
1372                 return RESULT_SHOWUSAGE;
1373         quit_handler(0, 0 /* not nicely */, 1 /* safely */, 1 /* restart */);
1374         return RESULT_SUCCESS;
1375 }
1376
1377 static int handle_restart_gracefully(int fd, int argc, char *argv[])
1378 {
1379         if (argc != 2)
1380                 return RESULT_SHOWUSAGE;
1381         quit_handler(0, 1 /* nicely */, 1 /* safely */, 1 /* restart */);
1382         return RESULT_SUCCESS;
1383 }
1384
1385 static int handle_restart_when_convenient(int fd, int argc, char *argv[])
1386 {
1387         if (argc != 3)
1388                 return RESULT_SHOWUSAGE;
1389         ast_cli(fd, "Waiting for inactivity to perform restart\n");
1390         quit_handler(0, 2 /* really nicely */, 1 /* safely */, 1 /* restart */);
1391         return RESULT_SUCCESS;
1392 }
1393
1394 static int handle_abort_halt(int fd, int argc, char *argv[])
1395 {
1396         if (argc != 2)
1397                 return RESULT_SHOWUSAGE;
1398         ast_cancel_shutdown();
1399         shuttingdown = 0;
1400         return RESULT_SUCCESS;
1401 }
1402
1403 static int handle_bang(int fd, int argc, char *argv[])
1404 {
1405         return RESULT_SUCCESS;
1406 }
1407 static const char *warranty_lines[] = {
1408         "\n",
1409         "                           NO WARRANTY\n",
1410         "\n",
1411         "BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY\n",
1412         "FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN\n",
1413         "OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES\n",
1414         "PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED\n",
1415         "OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\n",
1416         "MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS\n",
1417         "TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE\n",
1418         "PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,\n",
1419         "REPAIR OR CORRECTION.\n",
1420         "\n",
1421         "IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\n",
1422         "WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR\n",
1423         "REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,\n",
1424         "INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING\n",
1425         "OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED\n",
1426         "TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY\n",
1427         "YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER\n",
1428         "PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE\n",
1429         "POSSIBILITY OF SUCH DAMAGES.\n",
1430 };
1431
1432 static int show_warranty(int fd, int argc, char *argv[])
1433 {
1434         int x;
1435
1436         for (x = 0; x < sizeof(warranty_lines) / sizeof(warranty_lines[0]); x++)
1437                 ast_cli(fd, (char *) warranty_lines[x]);
1438
1439         return RESULT_SUCCESS;
1440 }
1441
1442 static const char *license_lines[] = {
1443         "\n",
1444         "This program is free software; you can redistribute it and/or modify\n",
1445         "it under the terms of the GNU General Public License version 2 as\n",
1446         "published by the Free Software Foundation.\n",
1447         "\n",
1448         "This program also contains components licensed under other licenses.\n",
1449         "They include:\n",
1450         "\n",
1451         "This program is distributed in the hope that it will be useful,\n",
1452         "but WITHOUT ANY WARRANTY; without even the implied warranty of\n",
1453         "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n",
1454         "GNU General Public License for more details.\n",
1455         "\n",
1456         "You should have received a copy of the GNU General Public License\n",
1457         "along with this program; if not, write to the Free Software\n",
1458         "Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n",
1459 };
1460
1461 static int show_license(int fd, int argc, char *argv[])
1462 {
1463         int x;
1464
1465         for (x = 0; x < sizeof(license_lines) / sizeof(license_lines[0]); x++)
1466                 ast_cli(fd, (char *) license_lines[x]);
1467
1468         return RESULT_SUCCESS;
1469 }
1470
1471 #define ASTERISK_PROMPT "*CLI> "
1472
1473 #define ASTERISK_PROMPT2 "%s*CLI> "
1474
1475 static struct ast_cli_entry cli_asterisk[] = {
1476         { { "abort", "halt", NULL },
1477         handle_abort_halt, "Cancel a running halt",
1478         abort_halt_help },
1479
1480         { { "stop", "now", NULL },
1481         handle_shutdown_now, "Shut down Asterisk immediately",
1482         shutdown_now_help },
1483
1484         { { "stop", "gracefully", NULL },
1485         handle_shutdown_gracefully, "Gracefully shut down Asterisk",
1486         shutdown_gracefully_help },
1487
1488         { { "stop", "when", "convenient", NULL },
1489         handle_shutdown_when_convenient, "Shut down Asterisk at empty call volume",
1490         shutdown_when_convenient_help },
1491
1492         { { "restart", "now", NULL },
1493         handle_restart_now, "Restart Asterisk immediately", restart_now_help },
1494
1495         { { "restart", "gracefully", NULL },
1496         handle_restart_gracefully, "Restart Asterisk gracefully",
1497         restart_gracefully_help },
1498
1499         { { "restart", "when", "convenient", NULL },
1500         handle_restart_when_convenient, "Restart Asterisk at empty call volume",
1501         restart_when_convenient_help },
1502
1503         { { "core", "show", "warranty", NULL },
1504         show_warranty, "Show the warranty (if any) for this copy of Asterisk",
1505         show_warranty_help },
1506
1507         { { "core", "show", "license", NULL },
1508         show_license, "Show the license(s) for this copy of Asterisk",
1509         show_license_help },
1510
1511         { { "core", "show", "version", NULL },
1512         handle_version, "Display version info",
1513         version_help },
1514
1515         { { "!", NULL },
1516         handle_bang, "Execute a shell command",
1517         bang_help },
1518
1519 #if !defined(LOW_MEMORY)
1520         { { "core", "show", "file", "version", NULL },
1521         handle_show_version_files, "List versions of files used to build Asterisk",
1522         show_version_files_help, complete_show_version_files },
1523
1524         { { "core", "show", "threads", NULL },
1525         handle_show_threads, "Show running threads",
1526         show_threads_help },
1527
1528         { { "core", "show", "profile", NULL },
1529         handle_show_profile, "Display profiling info",
1530         NULL },
1531
1532         { { "core", "clear", "profile", NULL },
1533         handle_show_profile, "Clear profiling info",
1534         NULL },
1535 #endif /* ! LOW_MEMORY */
1536 };
1537
1538 static int ast_el_read_char(EditLine *el, char *cp)
1539 {
1540         int num_read = 0;
1541         int lastpos = 0;
1542         struct pollfd fds[2];
1543         int res;
1544         int max;
1545         char buf[512];
1546
1547         for (;;) {
1548                 max = 1;
1549                 fds[0].fd = ast_consock;
1550                 fds[0].events = POLLIN;
1551                 if (!ast_opt_exec) {
1552                         fds[1].fd = STDIN_FILENO;
1553                         fds[1].events = POLLIN;
1554                         max++;
1555                 }
1556                 res = poll(fds, max, -1);
1557                 if (res < 0) {
1558                         if (errno == EINTR)
1559                                 continue;
1560                         ast_log(LOG_ERROR, "poll failed: %s\n", strerror(errno));
1561                         break;
1562                 }
1563
1564                 if (!ast_opt_exec && fds[1].revents) {
1565                         num_read = read(STDIN_FILENO, cp, 1);
1566                         if (num_read < 1) {
1567                                 break;
1568                         } else 
1569                                 return (num_read);
1570                 }
1571                 if (fds[0].revents) {
1572                         res = read(ast_consock, buf, sizeof(buf) - 1);
1573                         /* if the remote side disappears exit */
1574                         if (res < 1) {
1575                                 fprintf(stderr, "\nDisconnected from Asterisk server\n");
1576                                 if (!ast_opt_reconnect) {
1577                                         quit_handler(0, 0, 0, 0);
1578                                 } else {
1579                                         int tries;
1580                                         int reconnects_per_second = 20;
1581                                         fprintf(stderr, "Attempting to reconnect for 30 seconds\n");
1582                                         for (tries=0; tries < 30 * reconnects_per_second; tries++) {
1583                                                 if (ast_tryconnect()) {
1584                                                         fprintf(stderr, "Reconnect succeeded after %.3f seconds\n", 1.0 / reconnects_per_second * tries);
1585                                                         printf(term_quit());
1586                                                         WELCOME_MESSAGE;
1587                                                         break;
1588                                                 } else
1589                                                         usleep(1000000 / reconnects_per_second);
1590                                         }
1591                                         if (tries >= 30 * reconnects_per_second) {
1592                                                 fprintf(stderr, "Failed to reconnect for 30 seconds.  Quitting.\n");
1593                                                 quit_handler(0, 0, 0, 0);
1594                                         }
1595                                 }
1596                         }
1597
1598                         buf[res] = '\0';
1599
1600                         if (!ast_opt_exec && !lastpos)
1601                                 write(STDOUT_FILENO, "\r", 1);
1602                         write(STDOUT_FILENO, buf, res);
1603                         if ((buf[res-1] == '\n') || (buf[res-2] == '\n')) {
1604                                 *cp = CC_REFRESH;
1605                                 return(1);
1606                         } else
1607                                 lastpos = 1;
1608                 }
1609         }
1610
1611         *cp = '\0';
1612         return (0);
1613 }
1614
1615 static char *cli_prompt(EditLine *el)
1616 {
1617         static char prompt[200];
1618         char *pfmt;
1619         int color_used = 0;
1620         char term_code[20];
1621
1622         if ((pfmt = getenv("ASTERISK_PROMPT"))) {
1623                 char *t = pfmt, *p = prompt;
1624                 memset(prompt, 0, sizeof(prompt));
1625                 while (*t != '\0' && *p < sizeof(prompt)) {
1626                         if (*t == '%') {
1627                                 char hostname[MAXHOSTNAMELEN]="";
1628                                 int i;
1629                                 time_t ts;
1630                                 struct tm tm;
1631 #ifdef linux
1632                                 FILE *LOADAVG;
1633 #endif
1634                                 int fgcolor = COLOR_WHITE, bgcolor = COLOR_BLACK;
1635
1636                                 t++;
1637                                 switch (*t) {
1638                                 case 'C': /* color */
1639                                         t++;
1640                                         if (sscanf(t, "%d;%d%n", &fgcolor, &bgcolor, &i) == 2) {
1641                                                 strncat(p, term_color_code(term_code, fgcolor, bgcolor, sizeof(term_code)),sizeof(prompt) - strlen(prompt) - 1);
1642                                                 t += i - 1;
1643                                         } else if (sscanf(t, "%d%n", &fgcolor, &i) == 1) {
1644                                                 strncat(p, term_color_code(term_code, fgcolor, 0, sizeof(term_code)),sizeof(prompt) - strlen(prompt) - 1);
1645                                                 t += i - 1;
1646                                         }
1647
1648                                         /* If the color has been reset correctly, then there's no need to reset it later */
1649                                         color_used = ((fgcolor == COLOR_WHITE) && (bgcolor == COLOR_BLACK)) ? 0 : 1;
1650                                         break;
1651                                 case 'd': /* date */
1652                                         memset(&tm, 0, sizeof(tm));
1653                                         time(&ts);
1654                                         if (localtime_r(&ts, &tm)) 
1655                                                 strftime(p, sizeof(prompt) - strlen(prompt), "%Y-%m-%d", &tm);
1656                                         break;
1657                                 case 'h': /* hostname */
1658                                         if (!gethostname(hostname, sizeof(hostname) - 1))
1659                                                 strncat(p, hostname, sizeof(prompt) - strlen(prompt) - 1);
1660                                         else
1661                                                 strncat(p, "localhost", sizeof(prompt) - strlen(prompt) - 1);
1662                                         break;
1663                                 case 'H': /* short hostname */
1664                                         if (!gethostname(hostname, sizeof(hostname) - 1)) {
1665                                                 for (i = 0; i < sizeof(hostname); i++) {
1666                                                         if (hostname[i] == '.') {
1667                                                                 hostname[i] = '\0';
1668                                                                 break;
1669                                                         }
1670                                                 }
1671                                                 strncat(p, hostname, sizeof(prompt) - strlen(prompt) - 1);
1672                                         } else
1673                                                 strncat(p, "localhost", sizeof(prompt) - strlen(prompt) - 1);
1674                                         break;
1675 #ifdef linux
1676                                 case 'l': /* load avg */
1677                                         t++;
1678                                         if ((LOADAVG = fopen("/proc/loadavg", "r"))) {
1679                                                 float avg1, avg2, avg3;
1680                                                 int actproc, totproc, npid, which;
1681                                                 fscanf(LOADAVG, "%f %f %f %d/%d %d",
1682                                                         &avg1, &avg2, &avg3, &actproc, &totproc, &npid);
1683                                                 if (sscanf(t, "%d", &which) == 1) {
1684                                                         switch (which) {
1685                                                         case 1:
1686                                                                 snprintf(p, sizeof(prompt) - strlen(prompt), "%.2f", avg1);
1687                                                                 break;
1688                                                         case 2:
1689                                                                 snprintf(p, sizeof(prompt) - strlen(prompt), "%.2f", avg2);
1690                                                                 break;
1691                                                         case 3:
1692                                                                 snprintf(p, sizeof(prompt) - strlen(prompt), "%.2f", avg3);
1693                                                                 break;
1694                                                         case 4:
1695                                                                 snprintf(p, sizeof(prompt) - strlen(prompt), "%d/%d", actproc, totproc);
1696                                                                 break;
1697                                                         case 5:
1698                                                                 snprintf(p, sizeof(prompt) - strlen(prompt), "%d", npid);
1699                                                                 break;
1700                                                         }
1701                                                 }
1702                                         }
1703                                         break;
1704 #endif
1705                                 case 's': /* Asterisk system name (from asterisk.conf) */
1706                                         strncat(p, ast_config_AST_SYSTEM_NAME, sizeof(prompt) - strlen(prompt) - 1);
1707                                         break;
1708                                 case 't': /* time */
1709                                         memset(&tm, 0, sizeof(tm));
1710                                         time(&ts);
1711                                         if (localtime_r(&ts, &tm))
1712                                                 strftime(p, sizeof(prompt) - strlen(prompt), "%H:%M:%S", &tm);
1713                                         break;
1714                                 case '#': /* process console or remote? */
1715                                         if (!ast_opt_remote) 
1716                                                 strncat(p, "#", sizeof(prompt) - strlen(prompt) - 1);
1717                                         else
1718                                                 strncat(p, ">", sizeof(prompt) - strlen(prompt) - 1);
1719                                         break;
1720                                 case '%': /* literal % */
1721                                         strncat(p, "%", sizeof(prompt) - strlen(prompt) - 1);
1722                                         break;
1723                                 case '\0': /* % is last character - prevent bug */
1724                                         t--;
1725                                         break;
1726                                 }
1727                                 while (*p != '\0')
1728                                         p++;
1729                                 t++;
1730                         } else {
1731                                 *p = *t;
1732                                 p++;
1733                                 t++;
1734                         }
1735                 }
1736                 if (color_used) {
1737                         /* Force colors back to normal at end */
1738                         term_color_code(term_code, COLOR_WHITE, COLOR_BLACK, sizeof(term_code));
1739                         if (strlen(term_code) > sizeof(prompt) - strlen(prompt))
1740                                 strncat(prompt + sizeof(prompt) - strlen(term_code) - 1, term_code, strlen(term_code));
1741                         else
1742                                 strncat(p, term_code, sizeof(term_code));
1743                 }
1744         } else if (remotehostname)
1745                 snprintf(prompt, sizeof(prompt), ASTERISK_PROMPT2, remotehostname);
1746         else
1747                 snprintf(prompt, sizeof(prompt), ASTERISK_PROMPT);
1748
1749         return(prompt); 
1750 }
1751
1752 static char **ast_el_strtoarr(char *buf)
1753 {
1754         char **match_list = NULL, *retstr;
1755         size_t match_list_len;
1756         int matches = 0;
1757
1758         match_list_len = 1;
1759         while ( (retstr = strsep(&buf, " ")) != NULL) {
1760
1761                 if (!strcmp(retstr, AST_CLI_COMPLETE_EOF))
1762                         break;
1763                 if (matches + 1 >= match_list_len) {
1764                         match_list_len <<= 1;
1765                         if (!(match_list = ast_realloc(match_list, match_list_len * sizeof(char *)))) {
1766                                 /* TODO: Handle memory allocation failure */
1767                         }
1768                 }
1769
1770                 match_list[matches++] = strdup(retstr);
1771         }
1772
1773         if (!match_list)
1774                 return (char **) NULL;
1775
1776         if (matches >= match_list_len) {
1777                 if (!(match_list = ast_realloc(match_list, (match_list_len + 1) * sizeof(char *)))) {
1778                         /* TODO: Handle memory allocation failure */
1779                 }
1780         }
1781
1782         match_list[matches] = (char *) NULL;
1783
1784         return match_list;
1785 }
1786
1787 static int ast_el_sort_compare(const void *i1, const void *i2)
1788 {
1789         char *s1, *s2;
1790
1791         s1 = ((char **)i1)[0];
1792         s2 = ((char **)i2)[0];
1793
1794         return strcasecmp(s1, s2);
1795 }
1796
1797 static int ast_cli_display_match_list(char **matches, int len, int max)
1798 {
1799         int i, idx, limit, count;
1800         int screenwidth = 0;
1801         int numoutput = 0, numoutputline = 0;
1802
1803         screenwidth = ast_get_termcols(STDOUT_FILENO);
1804
1805         /* find out how many entries can be put on one line, with two spaces between strings */
1806         limit = screenwidth / (max + 2);
1807         if (limit == 0)
1808                 limit = 1;
1809
1810         /* how many lines of output */
1811         count = len / limit;
1812         if (count * limit < len)
1813                 count++;
1814
1815         idx = 1;
1816
1817         qsort(&matches[0], (size_t)(len), sizeof(char *), ast_el_sort_compare);
1818
1819         for (; count > 0; count--) {
1820                 numoutputline = 0;
1821                 for (i=0; i < limit && matches[idx]; i++, idx++) {
1822
1823                         /* Don't print dupes */
1824                         if ( (matches[idx+1] != NULL && strcmp(matches[idx], matches[idx+1]) == 0 ) ) {
1825                                 i--;
1826                                 free(matches[idx]);
1827                                 matches[idx] = NULL;
1828                                 continue;
1829                         }
1830
1831                         numoutput++;
1832                         numoutputline++;
1833                         fprintf(stdout, "%-*s  ", max, matches[idx]);
1834                         free(matches[idx]);
1835                         matches[idx] = NULL;
1836                 }
1837                 if (numoutputline > 0)
1838                         fprintf(stdout, "\n");
1839         }
1840
1841         return numoutput;
1842 }
1843
1844
1845 static char *cli_complete(EditLine *el, int ch)
1846 {
1847         int len = 0;
1848         char *ptr;
1849         int nummatches = 0;
1850         char **matches;
1851         int retval = CC_ERROR;
1852         char buf[2048];
1853         int res;
1854
1855         LineInfo *lf = (LineInfo *)el_line(el);
1856
1857         *(char *)lf->cursor = '\0';
1858         ptr = (char *)lf->cursor;
1859         if (ptr) {
1860                 while (ptr > lf->buffer) {
1861                         if (isspace(*ptr)) {
1862                                 ptr++;
1863                                 break;
1864                         }
1865                         ptr--;
1866                 }
1867         }
1868
1869         len = lf->cursor - ptr;
1870
1871         if (ast_opt_remote) {
1872                 snprintf(buf, sizeof(buf),"_COMMAND NUMMATCHES \"%s\" \"%s\"", lf->buffer, ptr); 
1873                 fdprint(ast_consock, buf);
1874                 res = read(ast_consock, buf, sizeof(buf));
1875                 buf[res] = '\0';
1876                 nummatches = atoi(buf);
1877
1878                 if (nummatches > 0) {
1879                         char *mbuf;
1880                         int mlen = 0, maxmbuf = 2048;
1881                         /* Start with a 2048 byte buffer */                     
1882                         if (!(mbuf = ast_malloc(maxmbuf)))
1883                                 return (char *)(CC_ERROR);
1884                         snprintf(buf, sizeof(buf),"_COMMAND MATCHESARRAY \"%s\" \"%s\"", lf->buffer, ptr); 
1885                         fdprint(ast_consock, buf);
1886                         res = 0;
1887                         mbuf[0] = '\0';
1888                         while (!strstr(mbuf, AST_CLI_COMPLETE_EOF) && res != -1) {
1889                                 if (mlen + 1024 > maxmbuf) {
1890                                         /* Every step increment buffer 1024 bytes */
1891                                         maxmbuf += 1024;                                        
1892                                         if (!(mbuf = ast_realloc(mbuf, maxmbuf)))
1893                                                 return (char *)(CC_ERROR);
1894                                 }
1895                                 /* Only read 1024 bytes at a time */
1896                                 res = read(ast_consock, mbuf + mlen, 1024);
1897                                 if (res > 0)
1898                                         mlen += res;
1899                         }
1900                         mbuf[mlen] = '\0';
1901
1902                         matches = ast_el_strtoarr(mbuf);
1903                         free(mbuf);
1904                 } else
1905                         matches = (char **) NULL;
1906         } else {
1907                 char **p, *oldbuf=NULL;
1908                 nummatches = 0;
1909                 matches = ast_cli_completion_matches((char *)lf->buffer,ptr);
1910                 for (p = matches; p && *p; p++) {
1911                         if (!oldbuf || strcmp(*p,oldbuf))
1912                                 nummatches++;
1913                         oldbuf = *p;
1914                 }
1915         }
1916
1917         if (matches) {
1918                 int i;
1919                 int matches_num, maxlen, match_len;
1920
1921                 if (matches[0][0] != '\0') {
1922                         el_deletestr(el, (int) len);
1923                         el_insertstr(el, matches[0]);
1924                         retval = CC_REFRESH;
1925                 }
1926
1927                 if (nummatches == 1) {
1928                         /* Found an exact match */
1929                         el_insertstr(el, " ");
1930                         retval = CC_REFRESH;
1931                 } else {
1932                         /* Must be more than one match */
1933                         for (i=1, maxlen=0; matches[i]; i++) {
1934                                 match_len = strlen(matches[i]);
1935                                 if (match_len > maxlen)
1936                                         maxlen = match_len;
1937                         }
1938                         matches_num = i - 1;
1939                         if (matches_num >1) {
1940                                 fprintf(stdout, "\n");
1941                                 ast_cli_display_match_list(matches, nummatches, maxlen);
1942                                 retval = CC_REDISPLAY;
1943                         } else { 
1944                                 el_insertstr(el," ");
1945                                 retval = CC_REFRESH;
1946                         }
1947                 }
1948                 free(matches);
1949         }
1950
1951         return (char *)(long)retval;
1952 }
1953
1954 static int ast_el_initialize(void)
1955 {
1956         HistEvent ev;
1957         char *editor = getenv("AST_EDITOR");
1958
1959         if (el != NULL)
1960                 el_end(el);
1961         if (el_hist != NULL)
1962                 history_end(el_hist);
1963
1964         el = el_init("asterisk", stdin, stdout, stderr);
1965         el_set(el, EL_PROMPT, cli_prompt);
1966
1967         el_set(el, EL_EDITMODE, 1);             
1968         el_set(el, EL_EDITOR, editor ? editor : "emacs");               
1969         el_hist = history_init();
1970         if (!el || !el_hist)
1971                 return -1;
1972
1973         /* setup history with 100 entries */
1974         history(el_hist, &ev, H_SETSIZE, 100);
1975
1976         el_set(el, EL_HIST, history, el_hist);
1977
1978         el_set(el, EL_ADDFN, "ed-complete", "Complete argument", cli_complete);
1979         /* Bind <tab> to command completion */
1980         el_set(el, EL_BIND, "^I", "ed-complete", NULL);
1981         /* Bind ? to command completion */
1982         el_set(el, EL_BIND, "?", "ed-complete", NULL);
1983         /* Bind ^D to redisplay */
1984         el_set(el, EL_BIND, "^D", "ed-redisplay", NULL);
1985
1986         return 0;
1987 }
1988
1989 static int ast_el_add_history(char *buf)
1990 {
1991         HistEvent ev;
1992
1993         if (el_hist == NULL || el == NULL)
1994                 ast_el_initialize();
1995         if (strlen(buf) > 256)
1996                 return 0;
1997         return (history(el_hist, &ev, H_ENTER, buf));
1998 }
1999
2000 static int ast_el_write_history(char *filename)
2001 {
2002         HistEvent ev;
2003
2004         if (el_hist == NULL || el == NULL)
2005                 ast_el_initialize();
2006
2007         return (history(el_hist, &ev, H_SAVE, filename));
2008 }
2009
2010 static int ast_el_read_history(char *filename)
2011 {
2012         char buf[256];
2013         FILE *f;
2014         int ret = -1;
2015
2016         if (el_hist == NULL || el == NULL)
2017                 ast_el_initialize();
2018
2019         if ((f = fopen(filename, "r")) == NULL)
2020                 return ret;
2021
2022         while (!feof(f)) {
2023                 fgets(buf, sizeof(buf), f);
2024                 if (!strcmp(buf, "_HiStOrY_V2_\n"))
2025                         continue;
2026                 if (ast_all_zeros(buf))
2027                         continue;
2028                 if ((ret = ast_el_add_history(buf)) == -1)
2029                         break;
2030         }
2031         fclose(f);
2032
2033         return ret;
2034 }
2035
2036 static void ast_remotecontrol(char * data)
2037 {
2038         char buf[80];
2039         int res;
2040         char filename[80] = "";
2041         char *hostname;
2042         char *cpid;
2043         char *version;
2044         int pid;
2045         char tmp[80];
2046         char *stringp = NULL;
2047
2048         char *ebuf;
2049         int num = 0;
2050
2051         read(ast_consock, buf, sizeof(buf));
2052         if (data)
2053                 write(ast_consock, data, strlen(data) + 1);
2054         stringp = buf;
2055         hostname = strsep(&stringp, "/");
2056         cpid = strsep(&stringp, "/");
2057         version = strsep(&stringp, "\n");
2058         if (!version)
2059                 version = "<Version Unknown>";
2060         stringp = hostname;
2061         strsep(&stringp, ".");
2062         if (cpid)
2063                 pid = atoi(cpid);
2064         else
2065                 pid = -1;
2066         snprintf(tmp, sizeof(tmp), "core set verbose atleast %d", option_verbose);
2067         fdprint(ast_consock, tmp);
2068         snprintf(tmp, sizeof(tmp), "core set debug atleast %d", option_debug);
2069         fdprint(ast_consock, tmp);
2070         if (ast_opt_mute) {
2071                 snprintf(tmp, sizeof(tmp), "log and verbose output currently muted ('logger unmute' to unmute)");
2072                 fdprint(ast_consock, tmp);
2073         }
2074         ast_verbose("Connected to Asterisk %s currently running on %s (pid = %d)\n", version, hostname, pid);
2075         remotehostname = hostname;
2076         if (getenv("HOME")) 
2077                 snprintf(filename, sizeof(filename), "%s/.asterisk_history", getenv("HOME"));
2078         if (el_hist == NULL || el == NULL)
2079                 ast_el_initialize();
2080
2081         el_set(el, EL_GETCFN, ast_el_read_char);
2082
2083         if (!ast_strlen_zero(filename))
2084                 ast_el_read_history(filename);
2085
2086         if (ast_opt_exec && data) {  /* hack to print output then exit if asterisk -rx is used */
2087                 char tempchar;
2088                 struct pollfd fds;
2089                 fds.fd = ast_consock;
2090                 fds.events = POLLIN;
2091                 fds.revents = 0;
2092                 while (poll(&fds, 1, 100) > 0)
2093                         ast_el_read_char(el, &tempchar);
2094                 return;
2095         }
2096         for (;;) {
2097                 ebuf = (char *)el_gets(el, &num);
2098
2099                 if (!ast_strlen_zero(ebuf)) {
2100                         if (ebuf[strlen(ebuf)-1] == '\n')
2101                                 ebuf[strlen(ebuf)-1] = '\0';
2102                         if (!remoteconsolehandler(ebuf)) {
2103                                 res = write(ast_consock, ebuf, strlen(ebuf) + 1);
2104                                 if (res < 1) {
2105                                         ast_log(LOG_WARNING, "Unable to write: %s\n", strerror(errno));
2106                                         break;
2107                                 }
2108                         }
2109                 }
2110         }
2111         printf("\nDisconnected from Asterisk server\n");
2112 }
2113
2114 static int show_version(void)
2115 {
2116         printf("Asterisk " ASTERISK_VERSION "\n");
2117         return 0;
2118 }
2119
2120 static int show_cli_help(void) {
2121         printf("Asterisk " ASTERISK_VERSION ", Copyright (C) 1999 - 2006, Digium, Inc. and others.\n");
2122         printf("Usage: asterisk [OPTIONS]\n");
2123         printf("Valid Options:\n");
2124         printf("   -V              Display version number and exit\n");
2125         printf("   -C <configfile> Use an alternate configuration file\n");
2126         printf("   -G <group>      Run as a group other than the caller\n");
2127         printf("   -U <user>       Run as a user other than the caller\n");
2128         printf("   -c              Provide console CLI\n");
2129         printf("   -d              Enable extra debugging\n");
2130 #if HAVE_WORKING_FORK
2131         printf("   -f              Do not fork\n");
2132         printf("   -F              Always fork\n");
2133 #endif
2134         printf("   -g              Dump core in case of a crash\n");
2135         printf("   -h              This help screen\n");
2136         printf("   -i              Initialize crypto keys at startup\n");
2137         printf("   -I              Enable internal timing if Zaptel timer is available\n");
2138         printf("   -L <load>       Limit the maximum load average before rejecting new calls\n");
2139         printf("   -M <value>      Limit the maximum number of calls to the specified value\n");
2140         printf("   -m              Mute the console from debugging and verbose output\n");
2141         printf("   -n              Disable console colorization\n");
2142         printf("   -p              Run as pseudo-realtime thread\n");
2143         printf("   -q              Quiet mode (suppress output)\n");
2144         printf("   -r              Connect to Asterisk on this machine\n");
2145         printf("   -R              Connect to Asterisk, and attempt to reconnect if disconnected\n");
2146         printf("   -t              Record soundfiles in /var/tmp and move them where they belong after they are done.\n");
2147         printf("   -T              Display the time in [Mmm dd hh:mm:ss] format for each line of output to the CLI.\n");
2148         printf("   -v              Increase verbosity (multiple v's = more verbose)\n");
2149         printf("   -x <cmd>        Execute command <cmd> (only valid with -r)\n");
2150         printf("\n");
2151         return 0;
2152 }
2153
2154 static void ast_readconfig(void) 
2155 {
2156         struct ast_config *cfg;
2157         struct ast_variable *v;
2158         char *config = AST_CONFIG_FILE;
2159
2160         if (ast_opt_override_config) {
2161                 cfg = ast_config_load(ast_config_AST_CONFIG_FILE);
2162                 if (!cfg)
2163                         ast_log(LOG_WARNING, "Unable to open specified master config file '%s', using built-in defaults\n", ast_config_AST_CONFIG_FILE);
2164         } else 
2165                 cfg = ast_config_load(config);
2166
2167         /* init with buildtime config */
2168         ast_copy_string(ast_config_AST_CONFIG_DIR, AST_CONFIG_DIR, sizeof(ast_config_AST_CONFIG_DIR));
2169         ast_copy_string(ast_config_AST_SPOOL_DIR, AST_SPOOL_DIR, sizeof(ast_config_AST_SPOOL_DIR));
2170         ast_copy_string(ast_config_AST_MODULE_DIR, AST_MODULE_DIR, sizeof(ast_config_AST_MODULE_DIR));
2171         snprintf(ast_config_AST_MONITOR_DIR, sizeof(ast_config_AST_MONITOR_DIR) - 1, "%s/monitor", ast_config_AST_SPOOL_DIR);
2172         ast_copy_string(ast_config_AST_VAR_DIR, AST_VAR_DIR, sizeof(ast_config_AST_VAR_DIR));
2173         ast_copy_string(ast_config_AST_DATA_DIR, AST_DATA_DIR, sizeof(ast_config_AST_DATA_DIR));
2174         ast_copy_string(ast_config_AST_LOG_DIR, AST_LOG_DIR, sizeof(ast_config_AST_LOG_DIR));
2175         ast_copy_string(ast_config_AST_AGI_DIR, AST_AGI_DIR, sizeof(ast_config_AST_AGI_DIR));
2176         ast_copy_string(ast_config_AST_DB, AST_DB, sizeof(ast_config_AST_DB));
2177         ast_copy_string(ast_config_AST_KEY_DIR, AST_KEY_DIR, sizeof(ast_config_AST_KEY_DIR));
2178         ast_copy_string(ast_config_AST_PID, AST_PID, sizeof(ast_config_AST_PID));
2179         ast_copy_string(ast_config_AST_SOCKET, AST_SOCKET, sizeof(ast_config_AST_SOCKET));
2180         ast_copy_string(ast_config_AST_RUN_DIR, AST_RUN_DIR, sizeof(ast_config_AST_RUN_DIR));
2181
2182         /* no asterisk.conf? no problem, use buildtime config! */
2183         if (!cfg) {
2184                 return;
2185         }
2186
2187         for (v = ast_variable_browse(cfg, "files"); v; v = v->next) {
2188                 if (!strcasecmp(v->name, "astctlpermissions"))
2189                         ast_copy_string(ast_config_AST_CTL_PERMISSIONS, v->value, sizeof(ast_config_AST_CTL_PERMISSIONS));
2190                 else if (!strcasecmp(v->name, "astctlowner"))
2191                         ast_copy_string(ast_config_AST_CTL_OWNER, v->value, sizeof(ast_config_AST_CTL_OWNER));
2192                 else if (!strcasecmp(v->name, "astctlgroup"))
2193                         ast_copy_string(ast_config_AST_CTL_GROUP, v->value, sizeof(ast_config_AST_CTL_GROUP));
2194                 else if (!strcasecmp(v->name, "astctl"))
2195                         ast_copy_string(ast_config_AST_CTL, v->value, sizeof(ast_config_AST_CTL));
2196         }
2197
2198         for (v = ast_variable_browse(cfg, "directories"); v; v = v->next) {
2199                 if (!strcasecmp(v->name, "astetcdir")) {
2200                         ast_copy_string(ast_config_AST_CONFIG_DIR, v->value, sizeof(ast_config_AST_CONFIG_DIR));
2201                 } else if (!strcasecmp(v->name, "astspooldir")) {
2202                         ast_copy_string(ast_config_AST_SPOOL_DIR, v->value, sizeof(ast_config_AST_SPOOL_DIR));
2203                         snprintf(ast_config_AST_MONITOR_DIR, sizeof(ast_config_AST_MONITOR_DIR) - 1, "%s/monitor", v->value);
2204                 } else if (!strcasecmp(v->name, "astvarlibdir")) {
2205                         ast_copy_string(ast_config_AST_VAR_DIR, v->value, sizeof(ast_config_AST_VAR_DIR));
2206                         snprintf(ast_config_AST_DB, sizeof(ast_config_AST_DB), "%s/astdb", v->value);
2207                 } else if (!strcasecmp(v->name, "astdatadir")) {
2208                         ast_copy_string(ast_config_AST_DATA_DIR, v->value, sizeof(ast_config_AST_DATA_DIR));
2209                         snprintf(ast_config_AST_KEY_DIR, sizeof(ast_config_AST_KEY_DIR), "%s/keys", v->value);
2210                 } else if (!strcasecmp(v->name, "astlogdir")) {
2211                         ast_copy_string(ast_config_AST_LOG_DIR, v->value, sizeof(ast_config_AST_LOG_DIR));
2212                 } else if (!strcasecmp(v->name, "astagidir")) {
2213                         ast_copy_string(ast_config_AST_AGI_DIR, v->value, sizeof(ast_config_AST_AGI_DIR));
2214                 } else if (!strcasecmp(v->name, "astrundir")) {
2215                         snprintf(ast_config_AST_PID, sizeof(ast_config_AST_PID), "%s/%s", v->value, "asterisk.pid");
2216                         snprintf(ast_config_AST_SOCKET, sizeof(ast_config_AST_SOCKET), "%s/%s", v->value, ast_config_AST_CTL);
2217                         ast_copy_string(ast_config_AST_RUN_DIR, v->value, sizeof(ast_config_AST_RUN_DIR));
2218                 } else if (!strcasecmp(v->name, "astmoddir")) {
2219                         ast_copy_string(ast_config_AST_MODULE_DIR, v->value, sizeof(ast_config_AST_MODULE_DIR));
2220                 }
2221         }
2222
2223         for (v = ast_variable_browse(cfg, "options"); v; v = v->next) {
2224                 /* verbose level (-v at startup) */
2225                 if (!strcasecmp(v->name, "verbose")) {
2226                         option_verbose = atoi(v->value);
2227                 /* whether or not to force timestamping in CLI verbose output. (-T at startup) */
2228                 } else if (!strcasecmp(v->name, "timestamp")) {
2229                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_TIMESTAMP);
2230                 /* whether or not to support #exec in config files */
2231                 } else if (!strcasecmp(v->name, "execincludes")) {
2232                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_EXEC_INCLUDES);
2233                 /* debug level (-d at startup) */
2234                 } else if (!strcasecmp(v->name, "debug")) {
2235                         option_debug = 0;
2236                         if (sscanf(v->value, "%d", &option_debug) != 1) {
2237                                 option_debug = ast_true(v->value);
2238                         }
2239 #if HAVE_WORKING_FORK
2240                 /* Disable forking (-f at startup) */
2241                 } else if (!strcasecmp(v->name, "nofork")) {
2242                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_NO_FORK);
2243                 /* Always fork, even if verbose or debug are enabled (-F at startup) */
2244                 } else if (!strcasecmp(v->name, "alwaysfork")) {
2245                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_ALWAYS_FORK);
2246 #endif
2247                 /* Run quietly (-q at startup ) */
2248                 } else if (!strcasecmp(v->name, "quiet")) {
2249                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_QUIET);
2250                 /* Run as console (-c at startup, implies nofork) */
2251                 } else if (!strcasecmp(v->name, "console")) {
2252                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_CONSOLE);
2253                 /* Run with high priority if the O/S permits (-p at startup) */
2254                 } else if (!strcasecmp(v->name, "highpriority")) {
2255                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_HIGH_PRIORITY);
2256                 /* Initialize RSA auth keys (IAX2) (-i at startup) */
2257                 } else if (!strcasecmp(v->name, "initcrypto")) {
2258                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_INIT_KEYS);
2259                 /* Disable ANSI colors for console (-c at startup) */
2260                 } else if (!strcasecmp(v->name, "nocolor")) {
2261                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_NO_COLOR);
2262                 /* Disable some usage warnings for picky people :p */
2263                 } else if (!strcasecmp(v->name, "dontwarn")) {
2264                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_DONT_WARN);
2265                 /* Dump core in case of crash (-g) */
2266                 } else if (!strcasecmp(v->name, "dumpcore")) {
2267                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_DUMP_CORE);
2268                 /* Cache recorded sound files to another directory during recording */
2269                 } else if (!strcasecmp(v->name, "cache_record_files")) {
2270                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_CACHE_RECORD_FILES);
2271                 /* Specify cache directory */
2272                 }  else if (!strcasecmp(v->name, "record_cache_dir")) {
2273                         ast_copy_string(record_cache_dir, v->value, AST_CACHE_DIR_LEN);
2274                 /* Build transcode paths via SLINEAR, instead of directly */
2275                 } else if (!strcasecmp(v->name, "transcode_via_sln")) {
2276                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_TRANSCODE_VIA_SLIN);
2277                 /* Transmit SLINEAR silence while a channel is being recorded */
2278                 } else if (!strcasecmp(v->name, "transmit_silence_during_record")) {
2279                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_TRANSMIT_SILENCE);
2280                 /* Enable internal timing */
2281                 } else if (!strcasecmp(v->name, "internal_timing")) {
2282                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_INTERNAL_TIMING);
2283                 } else if (!strcasecmp(v->name, "maxcalls")) {
2284                         if ((sscanf(v->value, "%d", &option_maxcalls) != 1) || (option_maxcalls < 0)) {
2285                                 option_maxcalls = 0;
2286                         }
2287                 } else if (!strcasecmp(v->name, "maxload")) {
2288                         double test[1];
2289
2290                         if (getloadavg(test, 1) == -1) {
2291                                 ast_log(LOG_ERROR, "Cannot obtain load average on this system. 'maxload' option disabled.\n");
2292                                 option_maxload = 0.0;
2293                         } else if ((sscanf(v->value, "%lf", &option_maxload) != 1) || (option_maxload < 0.0)) {
2294                                 option_maxload = 0.0;
2295                         }
2296                 /* What user to run as */
2297                 } else if (!strcasecmp(v->name, "runuser")) {
2298                         ast_copy_string(ast_config_AST_RUN_USER, v->value, sizeof(ast_config_AST_RUN_USER));
2299                 /* What group to run as */
2300                 } else if (!strcasecmp(v->name, "rungroup")) {
2301                         ast_copy_string(ast_config_AST_RUN_GROUP, v->value, sizeof(ast_config_AST_RUN_GROUP));
2302                 } else if (!strcasecmp(v->name, "systemname")) {
2303                         ast_copy_string(ast_config_AST_SYSTEM_NAME, v->value, sizeof(ast_config_AST_SYSTEM_NAME));
2304                 } else if (!strcasecmp(v->name, "languageprefix")) {
2305                         ast_language_is_prefix = ast_true(v->value);
2306                 }
2307         }
2308         ast_config_destroy(cfg);
2309 }
2310
2311 int main(int argc, char *argv[])
2312 {
2313         int c;
2314         char filename[80] = "";
2315         char hostname[MAXHOSTNAMELEN] = "";
2316         char tmp[80];
2317         char * xarg = NULL;
2318         int x;
2319         FILE *f;
2320         sigset_t sigs;
2321         int num;
2322         int is_child_of_nonroot = 0;
2323         char *buf;
2324         char *runuser = NULL, *rungroup = NULL;
2325
2326         /* Remember original args for restart */
2327         if (argc > sizeof(_argv) / sizeof(_argv[0]) - 1) {
2328                 fprintf(stderr, "Truncating argument size to %d\n", (int)(sizeof(_argv) / sizeof(_argv[0])) - 1);
2329                 argc = sizeof(_argv) / sizeof(_argv[0]) - 1;
2330         }
2331         for (x=0; x<argc; x++)
2332                 _argv[x] = argv[x];
2333         _argv[x] = NULL;
2334
2335         /* if the progname is rasterisk consider it a remote console */
2336         if (argv[0] && (strstr(argv[0], "rasterisk")) != NULL) {
2337                 ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK | AST_OPT_FLAG_REMOTE);
2338         }
2339         if (gethostname(hostname, sizeof(hostname)-1))
2340                 ast_copy_string(hostname, "<Unknown>", sizeof(hostname));
2341         ast_mainpid = getpid();
2342         ast_ulaw_init();
2343         ast_alaw_init();
2344         callerid_init();
2345         ast_builtins_init();
2346         ast_utils_init();
2347         tdd_init();
2348         /* When Asterisk restarts after it has dropped the root privileges,
2349          * it can't issue setuid(), setgid(), setgroups() or set_priority() 
2350          */
2351         if (getenv("ASTERISK_ALREADY_NONROOT"))
2352                 is_child_of_nonroot=1;
2353         if (getenv("HOME")) 
2354                 snprintf(filename, sizeof(filename), "%s/.asterisk_history", getenv("HOME"));
2355         /* Check for options */
2356         while ((c = getopt(argc, argv, "mtThfdvVqprRgciInx:U:G:C:L:M:")) != -1) {
2357                 switch (c) {
2358 #if HAVE_WORKING_FORK
2359                 case 'F':
2360                         ast_set_flag(&ast_options, AST_OPT_FLAG_ALWAYS_FORK);
2361                         break;
2362                 case 'f':
2363                         ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK);
2364                         break;
2365 #endif
2366                 case 'd':
2367                         option_debug++;
2368                         ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK);
2369                         break;
2370                 case 'c':
2371                         ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK | AST_OPT_FLAG_CONSOLE);
2372                         break;
2373                 case 'n':
2374                         ast_set_flag(&ast_options, AST_OPT_FLAG_NO_COLOR);
2375                         break;
2376                 case 'r':
2377                         ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK | AST_OPT_FLAG_REMOTE);
2378                         break;
2379                 case 'R':
2380                         ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK | AST_OPT_FLAG_REMOTE | AST_OPT_FLAG_RECONNECT);
2381                         break;
2382                 case 'p':
2383                         ast_set_flag(&ast_options, AST_OPT_FLAG_HIGH_PRIORITY);
2384                         break;
2385                 case 'v':
2386                         option_verbose++;
2387                         ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK);
2388                         break;
2389                 case 'm':
2390                         ast_set_flag(&ast_options, AST_OPT_FLAG_MUTE);
2391                         break;
2392                 case 'M':
2393                         if ((sscanf(optarg, "%d", &option_maxcalls) != 1) || (option_maxcalls < 0))
2394                                 option_maxcalls = 0;
2395                         break;
2396                 case 'L':
2397                         if ((sscanf(optarg, "%lf", &option_maxload) != 1) || (option_maxload < 0.0))
2398                                 option_maxload = 0.0;
2399                         break;
2400                 case 'q':
2401                         ast_set_flag(&ast_options, AST_OPT_FLAG_QUIET);
2402                         break;
2403                 case 't':
2404                         ast_set_flag(&ast_options, AST_OPT_FLAG_CACHE_RECORD_FILES);
2405                         break;
2406                 case 'T':
2407                         ast_set_flag(&ast_options, AST_OPT_FLAG_TIMESTAMP);
2408                         break;
2409                 case 'x':
2410                         ast_set_flag(&ast_options, AST_OPT_FLAG_EXEC);
2411                         xarg = optarg;
2412                         break;
2413                 case 'C':
2414                         ast_copy_string(ast_config_AST_CONFIG_FILE, optarg, sizeof(ast_config_AST_CONFIG_FILE));
2415                         ast_set_flag(&ast_options, AST_OPT_FLAG_OVERRIDE_CONFIG);
2416                         break;
2417                 case 'I':
2418                         ast_set_flag(&ast_options, AST_OPT_FLAG_INTERNAL_TIMING);
2419                         break;
2420                 case 'i':
2421                         ast_set_flag(&ast_options, AST_OPT_FLAG_INIT_KEYS);
2422                         break;
2423                 case 'g':
2424                         ast_set_flag(&ast_options, AST_OPT_FLAG_DUMP_CORE);
2425                         break;
2426                 case 'h':
2427                         show_cli_help();
2428                         exit(0);
2429                 case 'V':
2430                         show_version();
2431                         exit(0);
2432                 case 'U':
2433                         runuser = optarg;
2434                         break;
2435                 case 'G':
2436                         rungroup = optarg;
2437                         break;
2438                 case '?':
2439                         exit(1);
2440                 }
2441         }
2442
2443         if (ast_opt_console || option_verbose || (ast_opt_remote && !ast_opt_exec)) {
2444                 ast_register_verbose(console_verboser);
2445                 WELCOME_MESSAGE;
2446         }
2447
2448         if (ast_opt_console && !option_verbose) 
2449                 ast_verbose("[ Booting...\n");
2450
2451         if (ast_opt_always_fork && (ast_opt_remote || ast_opt_console)) {
2452                 ast_log(LOG_WARNING, "'alwaysfork' is not compatible with console or remote console mode; ignored\n");
2453                 ast_clear_flag(&ast_options, AST_OPT_FLAG_ALWAYS_FORK);
2454         }
2455
2456         /* For remote connections, change the name of the remote connection.
2457          * We do this for the benefit of init scripts (which need to know if/when
2458          * the main asterisk process has died yet). */
2459         if (ast_opt_remote) {
2460                 strcpy(argv[0], "rasterisk");
2461                 for (x = 1; x < argc; x++) {
2462                         argv[x] = argv[0] + 10;
2463                 }
2464         }
2465
2466         if (ast_opt_console && !option_verbose) 
2467                 ast_verbose("[ Reading Master Configuration ]\n");
2468         ast_readconfig();
2469
2470         if (ast_opt_dump_core) {
2471                 struct rlimit l;
2472                 memset(&l, 0, sizeof(l));
2473                 l.rlim_cur = RLIM_INFINITY;
2474                 l.rlim_max = RLIM_INFINITY;
2475                 if (setrlimit(RLIMIT_CORE, &l)) {
2476                         ast_log(LOG_WARNING, "Unable to disable core size resource limit: %s\n", strerror(errno));
2477                 }
2478         }
2479
2480         if ((!rungroup) && !ast_strlen_zero(ast_config_AST_RUN_GROUP))
2481                 rungroup = ast_config_AST_RUN_GROUP;
2482         if ((!runuser) && !ast_strlen_zero(ast_config_AST_RUN_USER))
2483                 runuser = ast_config_AST_RUN_USER;
2484
2485 #ifndef __CYGWIN__
2486
2487         if (!is_child_of_nonroot) 
2488                 ast_set_priority(ast_opt_high_priority);
2489
2490         if (!is_child_of_nonroot && rungroup) {
2491                 struct group *gr;
2492                 gr = getgrnam(rungroup);
2493                 if (!gr) {
2494                         ast_log(LOG_WARNING, "No such group '%s'!\n", rungroup);
2495                         exit(1);
2496                 }
2497                 if (setgid(gr->gr_gid)) {
2498                         ast_log(LOG_WARNING, "Unable to setgid to %d (%s)\n", (int)gr->gr_gid, rungroup);
2499                         exit(1);
2500                 }
2501                 if (setgroups(0, NULL)) {
2502                         ast_log(LOG_WARNING, "Unable to drop unneeded groups\n");
2503                         exit(1);
2504                 }
2505                 if (option_verbose)
2506                         ast_verbose("Running as group '%s'\n", rungroup);
2507         }
2508
2509         if (!is_child_of_nonroot && runuser) {
2510 #ifdef HAVE_CAP
2511                 int has_cap = 1;
2512 #endif /* HAVE_CAP */
2513                 struct passwd *pw;
2514                 pw = getpwnam(runuser);
2515                 if (!pw) {
2516                         ast_log(LOG_WARNING, "No such user '%s'!\n", runuser);
2517                         exit(1);
2518                 }
2519 #ifdef HAVE_CAP
2520                 if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0)) {
2521                         ast_log(LOG_WARNING, "Unable to keep capabilities.\n");
2522                         has_cap = 0;
2523                 }
2524 #endif /* HAVE_CAP */
2525                 if (!rungroup) {
2526                         if (setgid(pw->pw_gid)) {
2527                                 ast_log(LOG_WARNING, "Unable to setgid to %d!\n", (int)pw->pw_gid);
2528                                 exit(1);
2529                         }
2530                         if (initgroups(pw->pw_name, pw->pw_gid)) {
2531                                 ast_log(LOG_WARNING, "Unable to init groups for '%s'\n", runuser);
2532                                 exit(1);
2533                         }
2534                 }
2535                 if (setuid(pw->pw_uid)) {
2536                         ast_log(LOG_WARNING, "Unable to setuid to %d (%s)\n", (int)pw->pw_uid, runuser);
2537                         exit(1);
2538                 }
2539                 setenv("ASTERISK_ALREADY_NONROOT", "yes", 1);
2540                 if (option_verbose)
2541                         ast_verbose("Running as user '%s'\n", runuser);
2542 #ifdef HAVE_CAP
2543                 if (has_cap) {
2544                         cap_t cap;
2545
2546                         cap = cap_from_text("cap_net_admin=ep");
2547
2548                         if (cap_set_proc(cap))
2549                                 ast_log(LOG_WARNING, "Unable to install capabilities.\n");
2550
2551                         if (cap_free(cap))
2552                                 ast_log(LOG_WARNING, "Unable to drop capabilities.\n");
2553                 }
2554 #endif /* HAVE_CAP */
2555         }
2556
2557 #endif /* __CYGWIN__ */
2558
2559 #ifdef linux
2560         if (geteuid() && ast_opt_dump_core) {
2561                 if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) < 0) {
2562                         ast_log(LOG_WARNING, "Unable to set the process for core dumps after changing to a non-root user. %s\n", strerror(errno));
2563                 }       
2564         }
2565 #endif
2566
2567         ast_term_init();
2568         printf(term_end());
2569         fflush(stdout);
2570
2571         if (ast_opt_console && !option_verbose) 
2572                 ast_verbose("[ Initializing Custom Configuration Options ]\n");
2573         /* custom config setup */
2574         register_config_cli();
2575         read_config_maps();
2576         
2577         if (ast_opt_console) {
2578                 if (el_hist == NULL || el == NULL)
2579                         ast_el_initialize();
2580
2581                 if (!ast_strlen_zero(filename))
2582                         ast_el_read_history(filename);
2583         }
2584
2585         if (ast_tryconnect()) {
2586                 /* One is already running */
2587                 if (ast_opt_remote) {
2588                         if (ast_opt_exec) {
2589                                 ast_remotecontrol(xarg);
2590                                 quit_handler(0, 0, 0, 0);
2591                                 exit(0);
2592                         }
2593                         printf(term_quit());
2594                         ast_remotecontrol(NULL);
2595                         quit_handler(0, 0, 0, 0);
2596                         exit(0);
2597                 } else {
2598                         ast_log(LOG_ERROR, "Asterisk already running on %s.  Use 'asterisk -r' to connect.\n", ast_config_AST_SOCKET);
2599                         printf(term_quit());
2600                         exit(1);
2601                 }
2602         } else if (ast_opt_remote || ast_opt_exec) {
2603                 ast_log(LOG_ERROR, "Unable to connect to remote asterisk (does %s exist?)\n", ast_config_AST_SOCKET);
2604                 printf(term_quit());
2605                 exit(1);
2606         }
2607         /* Blindly write pid file since we couldn't connect */
2608         unlink(ast_config_AST_PID);
2609         f = fopen(ast_config_AST_PID, "w");
2610         if (f) {
2611                 fprintf(f, "%ld\n", (long)getpid());
2612                 fclose(f);
2613         } else
2614                 ast_log(LOG_WARNING, "Unable to open pid file '%s': %s\n", ast_config_AST_PID, strerror(errno));
2615
2616 #if HAVE_WORKING_FORK
2617         if (ast_opt_always_fork || !ast_opt_no_fork) {
2618                 daemon(0, 0);
2619                 ast_mainpid = getpid();
2620                 /* Blindly re-write pid file since we are forking */
2621                 unlink(ast_config_AST_PID);
2622                 f = fopen(ast_config_AST_PID, "w");
2623                 if (f) {
2624                         fprintf(f, "%ld\n", (long)ast_mainpid);
2625                         fclose(f);
2626                 } else
2627                         ast_log(LOG_WARNING, "Unable to open pid file '%s': %s\n", ast_config_AST_PID, strerror(errno));
2628         }
2629 #endif
2630
2631         /* Test recursive mutex locking. */
2632         if (test_for_thread_safety())
2633                 ast_verbose("Warning! Asterisk is not thread safe.\n");
2634
2635         ast_makesocket();
2636         sigemptyset(&sigs);
2637         sigaddset(&sigs, SIGHUP);
2638         sigaddset(&sigs, SIGTERM);
2639         sigaddset(&sigs, SIGINT);
2640         sigaddset(&sigs, SIGPIPE);
2641         sigaddset(&sigs, SIGWINCH);
2642         pthread_sigmask(SIG_BLOCK, &sigs, NULL);
2643         signal(SIGURG, urg_handler);
2644         signal(SIGINT, __quit_handler);
2645         signal(SIGTERM, __quit_handler);
2646         signal(SIGHUP, hup_handler);
2647         signal(SIGCHLD, child_handler);
2648         signal(SIGPIPE, SIG_IGN);
2649
2650         /* ensure that the random number generators are seeded with a different value every time
2651            Asterisk is started
2652         */
2653         srand((unsigned int) getpid() + (unsigned int) time(NULL));
2654         initstate((unsigned int) getpid() * 65536 + (unsigned int) time(NULL), randompool, sizeof(randompool));
2655
2656         if (init_logger()) {            /* Start logging subsystem */
2657                 printf(term_quit());
2658                 exit(1);
2659         }
2660         if (load_modules(1)) {          /* Load modules */
2661                 printf(term_quit());
2662                 exit(1);
2663         }
2664
2665         if (dnsmgr_init()) {            /* Initialize the DNS manager */
2666                 printf(term_quit());
2667                 exit(1);
2668         }
2669
2670         ast_http_init();                /* Start the HTTP server, if needed */
2671
2672         ast_channels_init();
2673
2674         if (init_manager()) {
2675                 printf(term_quit());
2676                 exit(1);
2677         }
2678
2679         if (ast_cdr_engine_init()) {
2680                 printf(term_quit());
2681                 exit(1);
2682         }
2683
2684         if (ast_device_state_engine_init()) {
2685                 printf(term_quit());
2686                 exit(1);
2687         }
2688
2689         ast_rtp_init();
2690
2691         ast_udptl_init();
2692
2693         if (ast_image_init()) {
2694                 printf(term_quit());
2695                 exit(1);
2696         }
2697
2698         if (ast_file_init()) {
2699                 printf(term_quit());
2700                 exit(1);
2701         }
2702
2703         if (load_pbx()) {
2704                 printf(term_quit());
2705                 exit(1);
2706         }
2707
2708         if (init_framer()) {
2709                 printf(term_quit());
2710                 exit(1);
2711         }
2712
2713         if (astdb_init()) {
2714                 printf(term_quit());
2715                 exit(1);
2716         }
2717
2718         if (ast_enum_init()) {
2719                 printf(term_quit());
2720                 exit(1);
2721         }
2722
2723         if (load_modules(0)) {
2724                 printf(term_quit());
2725                 exit(1);
2726         }
2727
2728         dnsmgr_start_refresh();
2729
2730         /* We might have the option of showing a console, but for now just
2731            do nothing... */
2732         if (ast_opt_console && !option_verbose)
2733                 ast_verbose(" ]\n");
2734         if (option_verbose || ast_opt_console)
2735                 ast_verbose(term_color(tmp, "Asterisk Ready.\n", COLOR_BRWHITE, COLOR_BLACK, sizeof(tmp)));
2736         if (ast_opt_no_fork)
2737                 consolethread = pthread_self();
2738
2739         ast_set_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED);
2740         pthread_sigmask(SIG_UNBLOCK, &sigs, NULL);
2741
2742 #ifdef __AST_DEBUG_MALLOC
2743         __ast_mm_init();
2744 #endif  
2745
2746         time(&ast_startuptime);
2747         ast_cli_register_multiple(cli_asterisk, sizeof(cli_asterisk) / sizeof(struct ast_cli_entry));
2748
2749         if (ast_opt_console) {
2750                 /* Console stuff now... */
2751                 /* Register our quit function */
2752                 char title[256];
2753                 set_icon("Asterisk");
2754                 snprintf(title, sizeof(title), "Asterisk Console on '%s' (pid %ld)", hostname, (long)ast_mainpid);
2755                 set_title(title);
2756
2757                 for (;;) {
2758                         buf = (char *)el_gets(el, &num);
2759                         if (buf) {
2760                                 if (buf[strlen(buf)-1] == '\n')
2761                                         buf[strlen(buf)-1] = '\0';
2762
2763                                 consolehandler((char *)buf);
2764                         } else if (ast_opt_remote && (write(STDOUT_FILENO, "\nUse EXIT or QUIT to exit the asterisk console\n",
2765                                    strlen("\nUse EXIT or QUIT to exit the asterisk console\n")) < 0)) {
2766                                 /* Whoa, stdout disappeared from under us... Make /dev/null's */
2767                                 int fd;
2768                                 fd = open("/dev/null", O_RDWR);
2769                                 if (fd > -1) {
2770                                         dup2(fd, STDOUT_FILENO);
2771                                         dup2(fd, STDIN_FILENO);
2772                                 } else
2773                                         ast_log(LOG_WARNING, "Failed to open /dev/null to recover from dead console. Bad things will happen!\n");
2774                                 break;
2775                         }
2776                 }
2777
2778         }
2779         /* Do nothing */
2780         for (;;) {      /* apparently needed for Mac OS X */
2781                 struct pollfd p = { -1 /* no descriptor */, 0, 0 };
2782
2783                 poll(&p, 0, -1);
2784         }
2785
2786         return 0;
2787 }