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