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