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