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