remove unused include
[asterisk/asterisk.git] / asterisk.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2006, Digium, Inc.
5  *
6  * Mark Spencer <markster@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18
19
20 /* Doxygenified Copyright Header */
21 /*!
22  * \mainpage Asterisk -- An Open Source Telephony Toolkit
23  *
24  * \par Developer Documentation for Asterisk
25  * This is the main developer documentation for Asterisk. It is 
26  * generated by running "make progdocs".
27  * \par Additional documentation
28  * \arg \ref DevDoc 
29  * \arg \ref ConfigFiles
30  *
31  * \section copyright Copyright and author
32  *
33  * Copyright (C) 1999 - 2006, Digium, Inc.
34  * Asterisk is a trade mark registered by Digium, Inc.
35  *
36  * \author Mark Spencer <markster@digium.com>
37  * Also see \ref AstCREDITS
38  *
39  * \section license License
40  * See http://www.asterisk.org for more information about
41  * the Asterisk project. Please do not directly contact
42  * any of the maintainers of this project for assistance;
43  * the project provides a web site, mailing lists and IRC
44  * channels for your use.
45  *
46  * This program is free software, distributed under the terms of
47  * the GNU General Public License Version 2. See the LICENSE file
48  * at the top of the source tree.
49  *
50  * \verbinclude LICENSE
51  *
52  */
53
54 /*! \file
55   \brief Top level source file for Asterisk  - the Open Source PBX. Implementation
56   of PBX core functions and CLI interface.
57   
58  */
59
60 #include <unistd.h>
61 #include <stdlib.h>
62 #include <sys/time.h>
63 #include <fcntl.h>
64 #include <stdio.h>
65 #include <signal.h>
66 #include <sched.h>
67 #include <sys/socket.h>
68 #include <sys/un.h>
69 #include <sys/wait.h>
70 #include <string.h>
71 #include <errno.h>
72 #include <ctype.h>
73 #include <sys/resource.h>
74 #include <grp.h>
75 #include <pwd.h>
76 #include <sys/stat.h>
77 #ifdef linux
78 #include <sys/prctl.h>
79 #endif
80 #include <regex.h>
81
82 #ifdef linux
83 #include <sys/prctl.h>
84 #endif
85
86 #if  defined(__FreeBSD__) || defined( __NetBSD__ ) || defined(SOLARIS)
87 #include <netdb.h>
88 #if defined(SOLARIS)
89 extern int daemon(int, int);  /* defined in libresolv of all places */
90 #endif
91 #endif
92
93 #include "asterisk.h"
94
95 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
96
97 #include "asterisk/logger.h"
98 #include "asterisk/options.h"
99 #include "asterisk/cli.h"
100 #include "asterisk/channel.h"
101 #include "asterisk/ulaw.h"
102 #include "asterisk/alaw.h"
103 #include "asterisk/callerid.h"
104 #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 #include "asterisk/compat.h"
126
127 #include "asterisk/doxyref.h"           /* Doxygen documentation */
128
129 #include "defaults.h"
130
131 #ifndef AF_LOCAL
132 #define AF_LOCAL AF_UNIX
133 #define PF_LOCAL PF_UNIX
134 #endif
135
136 #define AST_MAX_CONNECTS 128
137 #define NUM_MSGS 64
138
139 /*! \brief Welcome message when starting a CLI interface */
140 #define WELCOME_MESSAGE \
141         ast_verbose("Asterisk " ASTERISK_VERSION ", Copyright (C) 1999 - 2006 Digium, Inc. and others.\n"); \
142         ast_verbose("Created by Mark Spencer <markster@digium.com>\n"); \
143         ast_verbose("Asterisk comes with ABSOLUTELY NO WARRANTY; type 'show warranty' for details.\n"); \
144         ast_verbose("This is free software, with components licensed under the GNU General Public\n"); \
145         ast_verbose("License version 2 and other licenses; you are welcome to redistribute it under\n"); \
146         ast_verbose("certain conditions. Type 'show license' for details.\n"); \
147         ast_verbose("=========================================================================\n")
148
149 /*! \defgroup main_options 
150  \brief Main configuration options from \ref Config_ast "asterisk.conf" or 
151   the operating system command line when starting Asterisk 
152   Some of them can be changed in the CLI 
153  */
154 /*! @{ */
155
156 extern int ast_language_is_prefix;      /* XXX move to some header */
157
158 struct ast_flags ast_options = { AST_DEFAULT_OPTIONS };
159
160 int option_verbose = 0;                         /*!< Verbosity level */
161 int option_debug = 0;                           /*!< Debug level */
162
163 double option_maxload = 0.0;                    /*!< Max load avg on system */
164 int option_maxcalls = 0;                        /*!< Max number of active calls */
165
166 /*! @} */
167
168 char record_cache_dir[AST_CACHE_DIR_LEN] = AST_TMP_DIR;
169 char debug_filename[AST_FILENAME_MAX] = "";
170
171 static int ast_socket = -1;             /*!< UNIX Socket for allowing remote control */
172 static int ast_consock = -1;            /*!< UNIX Socket for controlling another asterisk */
173 pid_t ast_mainpid;
174 struct console {
175         int fd;                         /*!< File descriptor */
176         int p[2];                       /*!< Pipe */
177         pthread_t t;                    /*!< Thread of handler */
178         int mute;                       /*!< Is the console muted for logs */
179 };
180
181 struct ast_atexit {
182         void (*func)(void);
183         AST_LIST_ENTRY(ast_atexit) list;
184 };
185
186 static AST_LIST_HEAD_STATIC(atexits, ast_atexit);
187
188 time_t ast_startuptime;
189 time_t ast_lastreloadtime;
190
191 static History *el_hist = NULL;
192 static EditLine *el = NULL;
193 static char *remotehostname;
194
195 struct console consoles[AST_MAX_CONNECTS];
196
197 char defaultlanguage[MAX_LANGUAGE] = DEFAULT_LANGUAGE;
198
199 static int ast_el_add_history(char *);
200 static int ast_el_read_history(char *);
201 static int ast_el_write_history(char *);
202
203 char ast_config_AST_CONFIG_DIR[AST_CONFIG_MAX_PATH];
204 char ast_config_AST_CONFIG_FILE[AST_CONFIG_MAX_PATH];
205 char ast_config_AST_MODULE_DIR[AST_CONFIG_MAX_PATH];
206 char ast_config_AST_SPOOL_DIR[AST_CONFIG_MAX_PATH];
207 char ast_config_AST_MONITOR_DIR[AST_CONFIG_MAX_PATH];
208 char ast_config_AST_VAR_DIR[AST_CONFIG_MAX_PATH];
209 char ast_config_AST_DATA_DIR[AST_CONFIG_MAX_PATH];
210 char ast_config_AST_LOG_DIR[AST_CONFIG_MAX_PATH];
211 char ast_config_AST_AGI_DIR[AST_CONFIG_MAX_PATH];
212 char ast_config_AST_DB[AST_CONFIG_MAX_PATH];
213 char ast_config_AST_KEY_DIR[AST_CONFIG_MAX_PATH];
214 char ast_config_AST_PID[AST_CONFIG_MAX_PATH];
215 char ast_config_AST_SOCKET[AST_CONFIG_MAX_PATH];
216 char ast_config_AST_RUN_DIR[AST_CONFIG_MAX_PATH];
217 char ast_config_AST_RUN_USER[AST_CONFIG_MAX_PATH];
218 char ast_config_AST_RUN_GROUP[AST_CONFIG_MAX_PATH];
219 char ast_config_AST_CTL_PERMISSIONS[AST_CONFIG_MAX_PATH];
220 char ast_config_AST_CTL_OWNER[AST_CONFIG_MAX_PATH] = "\0";
221 char ast_config_AST_CTL_GROUP[AST_CONFIG_MAX_PATH] = "\0";
222 char ast_config_AST_CTL[AST_CONFIG_MAX_PATH] = "asterisk.ctl";
223 char ast_config_AST_SYSTEM_NAME[20] = "";
224
225 extern const char *ast_build_hostname;
226 extern const char *ast_build_kernel;
227 extern const char *ast_build_machine;
228 extern const char *ast_build_os;
229 extern const char *ast_build_date;
230 extern const char *ast_build_user;
231
232 static char *_argv[256];
233 static int shuttingdown = 0;
234 static int restartnow = 0;
235 static pthread_t consolethread = AST_PTHREADT_NULL;
236
237 static char randompool[256];
238
239 #if !defined(LOW_MEMORY)
240 struct file_version {
241         AST_LIST_ENTRY(file_version) list;
242         const char *file;
243         char *version;
244 };
245
246 static AST_LIST_HEAD_STATIC(file_versions, file_version);
247
248 void ast_register_file_version(const char *file, const char *version)
249 {
250         struct file_version *new;
251         char *work;
252         size_t version_length;
253
254         work = ast_strdupa(version);
255         work = ast_strip(ast_strip_quoted(work, "$", "$"));
256         version_length = strlen(work) + 1;
257         
258         if (!(new = ast_calloc(1, sizeof(*new) + version_length)))
259                 return;
260
261         new->file = file;
262         new->version = (char *) new + sizeof(*new);
263         memcpy(new->version, work, version_length);
264         AST_LIST_LOCK(&file_versions);
265         AST_LIST_INSERT_HEAD(&file_versions, new, list);
266         AST_LIST_UNLOCK(&file_versions);
267 }
268
269 void ast_unregister_file_version(const char *file)
270 {
271         struct file_version *find;
272
273         AST_LIST_LOCK(&file_versions);
274         AST_LIST_TRAVERSE_SAFE_BEGIN(&file_versions, find, list) {
275                 if (!strcasecmp(find->file, file)) {
276                         AST_LIST_REMOVE_CURRENT(&file_versions, list);
277                         break;
278                 }
279         }
280         AST_LIST_TRAVERSE_SAFE_END;
281         AST_LIST_UNLOCK(&file_versions);
282         if (find)
283                 free(find);
284 }
285
286 struct thread_list_t {
287         AST_LIST_ENTRY(thread_list_t) list;
288         char *name;
289         pthread_t id;
290 };
291
292 static AST_LIST_HEAD_STATIC(thread_list, thread_list_t);
293
294 static char show_threads_help[] =
295 "Usage: show threads\n"
296 "       List threads currently active in the system.\n";
297
298 void ast_register_thread(char *name)
299
300         struct thread_list_t *new = ast_calloc(1, sizeof(*new));
301
302         if (!new)
303                 return;
304         new->id = pthread_self();
305         new->name = name; /* this was a copy already */
306         AST_LIST_LOCK(&thread_list);
307         AST_LIST_INSERT_HEAD(&thread_list, new, list);
308         AST_LIST_UNLOCK(&thread_list);
309 }
310
311 void ast_unregister_thread(void *id)
312 {
313         struct thread_list_t *x;
314
315         AST_LIST_LOCK(&thread_list);
316         AST_LIST_TRAVERSE_SAFE_BEGIN(&thread_list, x, list) {
317                 if ((void *)x->id == id) {
318                         AST_LIST_REMOVE_CURRENT(&thread_list, list);
319                         break;
320                 }
321         }
322         AST_LIST_TRAVERSE_SAFE_END;
323         AST_LIST_UNLOCK(&thread_list);
324         if (x) {
325                 free(x->name);
326                 free(x);
327         }
328 }
329
330 static int handle_show_threads(int fd, int argc, char *argv[])
331 {
332         int count = 0;
333         struct thread_list_t *cur;
334
335         AST_LIST_LOCK(&thread_list);
336         AST_LIST_TRAVERSE(&thread_list, cur, list) {
337                 ast_cli(fd, "%p %s\n", (void *)cur->id, cur->name);
338                 count++;
339         }
340         AST_LIST_UNLOCK(&thread_list);
341         ast_cli(fd, "%d threads listed.\n", count);
342         return 0;
343 }
344
345 struct profile_entry {
346         const char *name;
347         uint64_t        scale;  /* if non-zero, values are scaled by this */
348         int64_t mark;
349         int64_t value;
350         int64_t events;
351 };
352
353 struct profile_data {
354         int entries;
355         int max_size;
356         struct profile_entry e[0];
357 };
358
359 static struct profile_data *prof_data;
360
361 /*
362  * allocates a counter with a given name and scale.
363  * Returns the identifier of the counter.
364  */
365 int ast_add_profile(const char *name, uint64_t scale)
366 {
367         int l = sizeof(struct profile_data);
368         int n = 10;     /* default entries */
369
370         if (prof_data == NULL) {
371                 prof_data = ast_calloc(1, l + n*sizeof(struct profile_entry));
372                 if (prof_data == NULL)
373                         return -1;
374                 prof_data->entries = 0;
375                 prof_data->max_size = n;
376         }
377         if (prof_data->entries >= prof_data->max_size) {
378                 void *p;
379                 n = prof_data->max_size + 20;
380                 p = ast_realloc(prof_data, l + n*sizeof(struct profile_entry));
381                 if (p == NULL)
382                         return -1;
383                 prof_data = p;
384                 prof_data->max_size = n;
385         }
386         n = prof_data->entries++;
387         prof_data->e[n].name = ast_strdup(name);
388         prof_data->e[n].value = 0;
389         prof_data->e[n].events = 0;
390         prof_data->e[n].mark = 0;
391         prof_data->e[n].scale = scale;
392         return n;
393 }
394
395 int64_t ast_profile(int i, int64_t delta)
396 {
397         if (!prof_data || i < 0 || i > prof_data->entries)      /* invalid index */
398                 return 0;
399         if (prof_data->e[i].scale > 1)
400                 delta /= prof_data->e[i].scale;
401         prof_data->e[i].value += delta;
402         prof_data->e[i].events++;
403         return prof_data->e[i].value;
404 }
405
406 #if defined ( __i386__) && (defined(__FreeBSD__) || defined(linux))
407 #if defined(__FreeBSD__)
408 #include <machine/cpufunc.h>
409 #elif defined(linux)
410 static __inline u_int64_t
411 rdtsc(void)
412
413         uint64_t rv;
414
415         __asm __volatile(".byte 0x0f, 0x31" : "=A" (rv));
416         return (rv);
417 }
418 #endif
419 #else   /* supply a dummy function on other platforms */
420 static __inline u_int64_t
421 rdtsc(void)
422 {
423         return 0;
424 }
425 #endif
426
427 int64_t ast_mark(int i, int startstop)
428 {
429         if (!prof_data || i < 0 || i > prof_data->entries) /* invalid index */
430                 return 0;
431         if (startstop == 1)
432                 prof_data->e[i].mark = rdtsc();
433         else {
434                 prof_data->e[i].mark = (rdtsc() - prof_data->e[i].mark);
435                 if (prof_data->e[i].scale > 1)
436                         prof_data->e[i].mark /= prof_data->e[i].scale;
437                 prof_data->e[i].value += prof_data->e[i].mark;
438                 prof_data->e[i].events++;
439         }
440         return prof_data->e[i].mark;
441 }
442
443 static int handle_show_profile(int fd, int argc, char *argv[])
444 {
445         int i, min, max;
446         char *search = NULL;
447
448         if (prof_data == NULL)
449                 return 0;
450
451         min = 0;
452         max = prof_data->entries;
453         if  (argc >= 3) { /* specific entries */
454                 if (isdigit(argv[2][0])) {
455                         min = atoi(argv[2]);
456                         if (argc == 4 && strcmp(argv[3], "-"))
457                                 max = atoi(argv[3]);
458                 } else
459                         search = argv[2];
460         }
461         if (max > prof_data->entries)
462                 max = prof_data->entries;
463         if (!strcmp(argv[0], "clear")) {
464                 for (i= min; i < max; i++) {
465                         if (!search || strstr(prof_data->e[i].name, search)) {
466                                 prof_data->e[i].value = 0;
467                                 prof_data->e[i].events = 0;
468                         }
469                 }
470                 return 0;
471         }
472         ast_cli(fd, "profile values (%d, allocated %d)\n-------------------\n",
473                 prof_data->entries, prof_data->max_size);
474         for (i = min; i < max; i++) {
475                 struct profile_entry *e = &prof_data->e[i];
476                 if (!search || strstr(prof_data->e[i].name, search))
477                     ast_cli(fd, "%6d: [%8ld] %10ld %12lld %12lld %s\n",
478                         i,
479                         (long)e->scale,
480                         (long)e->events, (long long)e->value,
481                         (long long)(e->events ? e->value / e->events : e->value),
482                         e->name);
483         }
484         return 0;
485 }
486
487 static char show_version_files_help[] = 
488 "Usage: show version files [like <pattern>]\n"
489 "       Shows the revision numbers of the files used to build this copy of Asterisk.\n"
490 "       Optional regular expression pattern is used to filter the file list.\n";
491
492 /*! CLI command to list module versions */
493 static int handle_show_version_files(int fd, int argc, char *argv[])
494 {
495 #define FORMAT "%-25.25s %-40.40s\n"
496         struct file_version *iterator;
497         regex_t regexbuf;
498         int havepattern = 0;
499         int havename = 0;
500         int count_files = 0;
501
502         switch (argc) {
503         case 5:
504                 if (!strcasecmp(argv[3], "like")) {
505                         if (regcomp(&regexbuf, argv[4], REG_EXTENDED | REG_NOSUB))
506                                 return RESULT_SHOWUSAGE;
507                         havepattern = 1;
508                 } else
509                         return RESULT_SHOWUSAGE;
510                 break;
511         case 4:
512                 havename = 1;
513                 break;
514         case 3:
515                 break;
516         default:
517                 return RESULT_SHOWUSAGE;
518         }
519
520         ast_cli(fd, FORMAT, "File", "Revision");
521         ast_cli(fd, FORMAT, "----", "--------");
522         AST_LIST_LOCK(&file_versions);
523         AST_LIST_TRAVERSE(&file_versions, iterator, list) {
524                 if (havename && strcasecmp(iterator->file, argv[3]))
525                         continue;
526
527                 if (havepattern && regexec(&regexbuf, iterator->file, 0, NULL, 0))
528                         continue;
529
530                 ast_cli(fd, FORMAT, iterator->file, iterator->version);
531                 count_files++;
532                 if (havename)
533                         break;
534         }
535         AST_LIST_UNLOCK(&file_versions);
536         if (!havename) {
537                 ast_cli(fd, "%d files listed.\n", count_files);
538         }
539
540         if (havepattern)
541                 regfree(&regexbuf);
542
543         return RESULT_SUCCESS;
544 #undef FORMAT
545 }
546
547 static char *complete_show_version_files(const char *line, const char *word, int pos, int state)
548 {
549         struct file_version *find;
550         int which = 0;
551         char *ret = NULL;
552         int matchlen = strlen(word);
553
554         if (pos != 3)
555                 return NULL;
556
557         AST_LIST_LOCK(&file_versions);
558         AST_LIST_TRAVERSE(&file_versions, find, list) {
559                 if (!strncasecmp(word, find->file, matchlen) && ++which > state) {
560                         ret = ast_strdup(find->file);
561                         break;
562                 }
563         }
564         AST_LIST_UNLOCK(&file_versions);
565
566         return ret;
567 }
568 #endif /* ! LOW_MEMORY */
569
570 int ast_register_atexit(void (*func)(void))
571 {
572         int res = -1;
573         struct ast_atexit *ae;
574         ast_unregister_atexit(func);    
575         AST_LIST_LOCK(&atexits);
576         if ((ae = ast_calloc(1, sizeof(*ae)))) {
577                 AST_LIST_INSERT_HEAD(&atexits, ae, list);
578                 ae->func = func;
579                 res = 0;
580         }
581         AST_LIST_UNLOCK(&atexits);
582         return res;
583 }
584
585 void ast_unregister_atexit(void (*func)(void))
586 {
587         struct ast_atexit *ae;
588         AST_LIST_LOCK(&atexits);
589         AST_LIST_TRAVERSE_SAFE_BEGIN(&atexits, ae, list) {
590                 if (ae->func == func) {
591                         AST_LIST_REMOVE_CURRENT(&atexits, list);
592                         break;
593                 }
594         }
595         AST_LIST_TRAVERSE_SAFE_END
596         AST_LIST_UNLOCK(&atexits);
597 }
598
599 static int fdprint(int fd, const char *s)
600 {
601         return write(fd, s, strlen(s) + 1);
602 }
603
604 /*! NULL handler so we can collect the child exit status */
605 static void null_sig_handler(int signal)
606 {
607
608 }
609
610 AST_MUTEX_DEFINE_STATIC(safe_system_lock);
611 /*! Keep track of how many threads are currently trying to wait*() on
612  *  a child process */
613 static unsigned int safe_system_level = 0;
614 static void *safe_system_prev_handler;
615
616 void ast_replace_sigchld(void)
617 {
618         unsigned int level;
619
620         ast_mutex_lock(&safe_system_lock);
621         level = safe_system_level++;
622
623         /* only replace the handler if it has not already been done */
624         if (level == 0)
625                 safe_system_prev_handler = signal(SIGCHLD, null_sig_handler);
626
627         ast_mutex_unlock(&safe_system_lock);
628 }
629
630 void ast_unreplace_sigchld(void)
631 {
632         unsigned int level;
633
634         ast_mutex_lock(&safe_system_lock);
635         level = --safe_system_level;
636
637         /* only restore the handler if we are the last one */
638         if (level == 0)
639                 signal(SIGCHLD, safe_system_prev_handler);
640
641         ast_mutex_unlock(&safe_system_lock);
642 }
643
644 int ast_safe_system(const char *s)
645 {
646         pid_t pid;
647         int x;
648         int res;
649         struct rusage rusage;
650         int status;
651
652         ast_replace_sigchld();
653
654         pid = fork();
655
656         if (pid == 0) {
657                 if (ast_opt_high_priority)
658                         ast_set_priority(0);
659                 /* Close file descriptors and launch system command */
660                 for (x = STDERR_FILENO + 1; x < 4096; x++)
661                         close(x);
662                 execl("/bin/sh", "/bin/sh", "-c", s, NULL);
663                 exit(1);
664         } else if (pid > 0) {
665                 for(;;) {
666                         res = wait4(pid, &status, 0, &rusage);
667                         if (res > -1) {
668                                 res = WIFEXITED(status) ? WEXITSTATUS(status) : -1;
669                                 break;
670                         } else if (errno != EINTR) 
671                                 break;
672                 }
673         } else {
674                 ast_log(LOG_WARNING, "Fork failed: %s\n", strerror(errno));
675                 res = -1;
676         }
677
678         ast_unreplace_sigchld();
679
680         return res;
681 }
682
683 /*!
684  * mute or unmute a console from logging
685  */
686 void ast_console_toggle_mute(int fd) {
687         int x;
688         for (x = 0;x < AST_MAX_CONNECTS; x++) {
689                 if (fd == consoles[x].fd) {
690                         if (consoles[x].mute) {
691                                 consoles[x].mute = 0;
692                                 ast_cli(fd, "Console is not muted anymore.\n");
693                         } else {
694                                 consoles[x].mute = 1;
695                                 ast_cli(fd, "Console is muted.\n");
696                         }
697                         return;
698                 }
699         }
700         ast_cli(fd, "Couldn't find remote console.\n");
701 }
702
703 /*!
704  * log the string to all attached console clients
705  */
706 static void ast_network_puts_mutable(const char *string)
707 {
708         int x;
709         for (x = 0;x < AST_MAX_CONNECTS; x++) {
710                 if (consoles[x].mute)
711                         continue;
712                 if (consoles[x].fd > -1) 
713                         fdprint(consoles[x].p[1], string);
714         }
715 }
716
717 /*!
718  * log the string to the console, and all attached
719  * console clients
720  */
721 void ast_console_puts_mutable(const char *string)
722 {
723         fputs(string, stdout);
724         fflush(stdout);
725         ast_network_puts_mutable(string);
726 }
727
728 /*!
729  * write the string to all attached console clients
730  */
731 static void ast_network_puts(const char *string)
732 {
733         int x;
734         for (x=0; x < AST_MAX_CONNECTS; x++) {
735                 if (consoles[x].fd > -1) 
736                         fdprint(consoles[x].p[1], string);
737         }
738 }
739
740 /*!
741  * write the string to the console, and all attached
742  * console clients
743  */
744 void ast_console_puts(const char *string)
745 {
746         fputs(string, stdout);
747         fflush(stdout);
748         ast_network_puts(string);
749 }
750
751 static void network_verboser(const char *s, int pos, int replace, int complete)
752         /* ARGUSED */
753 {
754         if (replace) {
755                 char *t;
756                 if ((t = alloca(strlen(s) + 2))) {
757                         sprintf(t, "\r%s", s);
758                         if (complete)
759                                 ast_network_puts_mutable(t);
760                 } else {
761                         ast_log(LOG_ERROR, "Out of memory\n");
762                         ast_network_puts_mutable(s);
763                 }
764         } else {
765                 if (complete)
766                         ast_network_puts_mutable(s);
767         }
768 }
769
770 static pthread_t lthread;
771
772 static void *netconsole(void *vconsole)
773 {
774         struct console *con = vconsole;
775         char hostname[MAXHOSTNAMELEN] = "";
776         char tmp[512];
777         int res;
778         struct pollfd fds[2];
779         
780         if (gethostname(hostname, sizeof(hostname)-1))
781                 ast_copy_string(hostname, "<Unknown>", sizeof(hostname));
782         snprintf(tmp, sizeof(tmp), "%s/%ld/%s\n", hostname, (long)ast_mainpid, ASTERISK_VERSION);
783         fdprint(con->fd, tmp);
784         for(;;) {
785                 fds[0].fd = con->fd;
786                 fds[0].events = POLLIN;
787                 fds[0].revents = 0;
788                 fds[1].fd = con->p[0];
789                 fds[1].events = POLLIN;
790                 fds[1].revents = 0;
791
792                 res = poll(fds, 2, -1);
793                 if (res < 0) {
794                         if (errno != EINTR)
795                                 ast_log(LOG_WARNING, "poll returned < 0: %s\n", strerror(errno));
796                         continue;
797                 }
798                 if (fds[0].revents) {
799                         res = read(con->fd, tmp, sizeof(tmp));
800                         if (res < 1) {
801                                 break;
802                         }
803                         tmp[res] = 0;
804                         ast_cli_command(con->fd, tmp);
805                 }
806                 if (fds[1].revents) {
807                         res = read(con->p[0], tmp, sizeof(tmp));
808                         if (res < 1) {
809                                 ast_log(LOG_ERROR, "read returned %d\n", res);
810                                 break;
811                         }
812                         res = write(con->fd, tmp, res);
813                         if (res < 1)
814                                 break;
815                 }
816         }
817         if (option_verbose > 2) 
818                 ast_verbose(VERBOSE_PREFIX_3 "Remote UNIX connection disconnected\n");
819         close(con->fd);
820         close(con->p[0]);
821         close(con->p[1]);
822         con->fd = -1;
823         
824         return NULL;
825 }
826
827 static void *listener(void *unused)
828 {
829         struct sockaddr_un sunaddr;
830         int s;
831         socklen_t len;
832         int x;
833         int flags;
834         struct pollfd fds[1];
835         pthread_attr_t attr;
836         pthread_attr_init(&attr);
837         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
838         for (;;) {
839                 if (ast_socket < 0)
840                         return NULL;
841                 fds[0].fd = ast_socket;
842                 fds[0].events = POLLIN;
843                 s = poll(fds, 1, -1);
844                 if (s < 0) {
845                         if (errno != EINTR)
846                                 ast_log(LOG_WARNING, "poll returned error: %s\n", strerror(errno));
847                         continue;
848                 }
849                 len = sizeof(sunaddr);
850                 s = accept(ast_socket, (struct sockaddr *)&sunaddr, &len);
851                 if (s < 0) {
852                         if (errno != EINTR)
853                                 ast_log(LOG_WARNING, "Accept returned %d: %s\n", s, strerror(errno));
854                 } else {
855                         for (x = 0; x < AST_MAX_CONNECTS; x++) {
856                                 if (consoles[x].fd < 0) {
857                                         if (socketpair(AF_LOCAL, SOCK_STREAM, 0, consoles[x].p)) {
858                                                 ast_log(LOG_ERROR, "Unable to create pipe: %s\n", strerror(errno));
859                                                 consoles[x].fd = -1;
860                                                 fdprint(s, "Server failed to create pipe\n");
861                                                 close(s);
862                                                 break;
863                                         }
864                                         flags = fcntl(consoles[x].p[1], F_GETFL);
865                                         fcntl(consoles[x].p[1], F_SETFL, flags | O_NONBLOCK);
866                                         consoles[x].fd = s;
867                                         consoles[x].mute = ast_opt_mute;
868                                         if (ast_pthread_create(&consoles[x].t, &attr, netconsole, &consoles[x])) {
869                                                 ast_log(LOG_ERROR, "Unable to spawn thread to handle connection: %s\n", strerror(errno));
870                                                 close(consoles[x].p[0]);
871                                                 close(consoles[x].p[1]);
872                                                 consoles[x].fd = -1;
873                                                 fdprint(s, "Server failed to spawn thread\n");
874                                                 close(s);
875                                         }
876                                         break;
877                                 }
878                         }
879                         if (x >= AST_MAX_CONNECTS) {
880                                 fdprint(s, "No more connections allowed\n");
881                                 ast_log(LOG_WARNING, "No more connections allowed\n");
882                                 close(s);
883                         } else if (consoles[x].fd > -1) {
884                                 if (option_verbose > 2) 
885                                         ast_verbose(VERBOSE_PREFIX_3 "Remote UNIX connection\n");
886                         }
887                 }
888         }
889         return NULL;
890 }
891
892 static int ast_makesocket(void)
893 {
894         struct sockaddr_un sunaddr;
895         int res;
896         int x;
897         uid_t uid = -1;
898         gid_t gid = -1;
899
900         for (x = 0; x < AST_MAX_CONNECTS; x++)  
901                 consoles[x].fd = -1;
902         unlink(ast_config_AST_SOCKET);
903         ast_socket = socket(PF_LOCAL, SOCK_STREAM, 0);
904         if (ast_socket < 0) {
905                 ast_log(LOG_WARNING, "Unable to create control socket: %s\n", strerror(errno));
906                 return -1;
907         }               
908         memset(&sunaddr, 0, sizeof(sunaddr));
909         sunaddr.sun_family = AF_LOCAL;
910         ast_copy_string(sunaddr.sun_path, ast_config_AST_SOCKET, sizeof(sunaddr.sun_path));
911         res = bind(ast_socket, (struct sockaddr *)&sunaddr, sizeof(sunaddr));
912         if (res) {
913                 ast_log(LOG_WARNING, "Unable to bind socket to %s: %s\n", ast_config_AST_SOCKET, strerror(errno));
914                 close(ast_socket);
915                 ast_socket = -1;
916                 return -1;
917         }
918         res = listen(ast_socket, 2);
919         if (res < 0) {
920                 ast_log(LOG_WARNING, "Unable to listen on socket %s: %s\n", ast_config_AST_SOCKET, strerror(errno));
921                 close(ast_socket);
922                 ast_socket = -1;
923                 return -1;
924         }
925         ast_register_verbose(network_verboser);
926         ast_pthread_create(&lthread, NULL, listener, NULL);
927
928         if (!ast_strlen_zero(ast_config_AST_CTL_OWNER)) {
929                 struct passwd *pw;
930                 if ((pw = getpwnam(ast_config_AST_CTL_OWNER)) == NULL) {
931                         ast_log(LOG_WARNING, "Unable to find uid of user %s\n", ast_config_AST_CTL_OWNER);
932                 } else {
933                         uid = pw->pw_uid;
934                 }
935         }
936                 
937         if (!ast_strlen_zero(ast_config_AST_CTL_GROUP)) {
938                 struct group *grp;
939                 if ((grp = getgrnam(ast_config_AST_CTL_GROUP)) == NULL) {
940                         ast_log(LOG_WARNING, "Unable to find gid of group %s\n", ast_config_AST_CTL_GROUP);
941                 } else {
942                         gid = grp->gr_gid;
943                 }
944         }
945
946         if (chown(ast_config_AST_SOCKET, uid, gid) < 0)
947                 ast_log(LOG_WARNING, "Unable to change ownership of %s: %s\n", ast_config_AST_SOCKET, strerror(errno));
948
949         if (!ast_strlen_zero(ast_config_AST_CTL_PERMISSIONS)) {
950                 int p1;
951                 mode_t p;
952                 sscanf(ast_config_AST_CTL_PERMISSIONS, "%o", &p1);
953                 p = p1;
954                 if ((chmod(ast_config_AST_SOCKET, p)) < 0)
955                         ast_log(LOG_WARNING, "Unable to change file permissions of %s: %s\n", ast_config_AST_SOCKET, strerror(errno));
956         }
957
958         return 0;
959 }
960
961 static int ast_tryconnect(void)
962 {
963         struct sockaddr_un sunaddr;
964         int res;
965         ast_consock = socket(PF_LOCAL, SOCK_STREAM, 0);
966         if (ast_consock < 0) {
967                 ast_log(LOG_WARNING, "Unable to create socket: %s\n", strerror(errno));
968                 return 0;
969         }
970         memset(&sunaddr, 0, sizeof(sunaddr));
971         sunaddr.sun_family = AF_LOCAL;
972         ast_copy_string(sunaddr.sun_path, (char *)ast_config_AST_SOCKET, sizeof(sunaddr.sun_path));
973         res = connect(ast_consock, (struct sockaddr *)&sunaddr, sizeof(sunaddr));
974         if (res) {
975                 close(ast_consock);
976                 ast_consock = -1;
977                 return 0;
978         } else
979                 return 1;
980 }
981
982 /*! Urgent handler
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 /*! 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 /*! 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                 close(ast_socket);
1157                 ast_socket = -1;
1158                 unlink(ast_config_AST_SOCKET);
1159                 pthread_cancel(lthread);
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 #ifdef __Darwin__
2093                 struct pollfd fds[0];
2094                 fds[0].fd = ast_consock;
2095                 fds[0].events = POLLIN;
2096                 fds[0].revents = 0;
2097                 while (poll(fds, 1, 100) > 0) {
2098                         ast_el_read_char(el, &tempchar);
2099                 }
2100 #else
2101                 while (!ast_el_read_char(el, &tempchar));
2102 #endif
2103                 return;
2104         }
2105         for (;;) {
2106                 ebuf = (char *)el_gets(el, &num);
2107
2108                 if (!ast_strlen_zero(ebuf)) {
2109                         if (ebuf[strlen(ebuf)-1] == '\n')
2110                                 ebuf[strlen(ebuf)-1] = '\0';
2111                         if (!remoteconsolehandler(ebuf)) {
2112                                 res = write(ast_consock, ebuf, strlen(ebuf) + 1);
2113                                 if (res < 1) {
2114                                         ast_log(LOG_WARNING, "Unable to write: %s\n", strerror(errno));
2115                                         break;
2116                                 }
2117                         }
2118                 }
2119         }
2120         printf("\nDisconnected from Asterisk server\n");
2121 }
2122
2123 static int show_version(void)
2124 {
2125         printf("Asterisk " ASTERISK_VERSION "\n");
2126         return 0;
2127 }
2128
2129 static int show_cli_help(void) {
2130         printf("Asterisk " ASTERISK_VERSION ", Copyright (C) 1999 - 2006, Digium, Inc. and others.\n");
2131         printf("Usage: asterisk [OPTIONS]\n");
2132         printf("Valid Options:\n");
2133         printf("   -V              Display version number and exit\n");
2134         printf("   -C <configfile> Use an alternate configuration file\n");
2135         printf("   -G <group>      Run as a group other than the caller\n");
2136         printf("   -U <user>       Run as a user other than the caller\n");
2137         printf("   -c              Provide console CLI\n");
2138         printf("   -d              Enable extra debugging\n");
2139         printf("   -f              Do not fork\n");
2140         printf("   -g              Dump core in case of a crash\n");
2141         printf("   -h              This help screen\n");
2142         printf("   -i              Initialize crypto keys at startup\n");
2143         printf("   -I              Enable internal timing if Zaptel timer is available\n");
2144         printf("   -L <load>       Limit the maximum load average before rejecting new calls\n");
2145         printf("   -M <value>      Limit the maximum number of calls to the specified value\n");
2146         printf("   -m              Mute the console from debugging and verbose output\n");
2147         printf("   -n              Disable console colorization\n");
2148         printf("   -p              Run as pseudo-realtime thread\n");
2149         printf("   -q              Quiet mode (suppress output)\n");
2150         printf("   -r              Connect to Asterisk on this machine\n");
2151         printf("   -R              Connect to Asterisk, and attempt to reconnect if disconnected\n");
2152         printf("   -t              Record soundfiles in /var/tmp and move them where they belong after they are done.\n");
2153         printf("   -T              Display the time in [Mmm dd hh:mm:ss] format for each line of output to the CLI.\n");
2154         printf("   -v              Increase verbosity (multiple v's = more verbose)\n");
2155         printf("   -x <cmd>        Execute command <cmd> (only valid with -r)\n");
2156         printf("\n");
2157         return 0;
2158 }
2159
2160 static void ast_readconfig(void) 
2161 {
2162         struct ast_config *cfg;
2163         struct ast_variable *v;
2164         char *config = AST_CONFIG_FILE;
2165
2166         if (ast_opt_override_config) {
2167                 cfg = ast_config_load(ast_config_AST_CONFIG_FILE);
2168                 if (!cfg)
2169                         ast_log(LOG_WARNING, "Unable to open specified master config file '%s', using built-in defaults\n", ast_config_AST_CONFIG_FILE);
2170         } else {
2171                 cfg = ast_config_load(config);
2172         }
2173
2174         /* init with buildtime config */
2175         ast_copy_string(ast_config_AST_CONFIG_DIR, AST_CONFIG_DIR, sizeof(ast_config_AST_CONFIG_DIR));
2176         ast_copy_string(ast_config_AST_SPOOL_DIR, AST_SPOOL_DIR, sizeof(ast_config_AST_SPOOL_DIR));
2177         ast_copy_string(ast_config_AST_MODULE_DIR, AST_MODULE_DIR, sizeof(ast_config_AST_MODULE_DIR));
2178         snprintf(ast_config_AST_MONITOR_DIR, sizeof(ast_config_AST_MONITOR_DIR) - 1, "%s/monitor", ast_config_AST_SPOOL_DIR);
2179         ast_copy_string(ast_config_AST_VAR_DIR, AST_VAR_DIR, sizeof(ast_config_AST_VAR_DIR));
2180         ast_copy_string(ast_config_AST_DATA_DIR, AST_DATA_DIR, sizeof(ast_config_AST_DATA_DIR));
2181         ast_copy_string(ast_config_AST_LOG_DIR, AST_LOG_DIR, sizeof(ast_config_AST_LOG_DIR));
2182         ast_copy_string(ast_config_AST_AGI_DIR, AST_AGI_DIR, sizeof(ast_config_AST_AGI_DIR));
2183         ast_copy_string(ast_config_AST_DB, AST_DB, sizeof(ast_config_AST_DB));
2184         ast_copy_string(ast_config_AST_KEY_DIR, AST_KEY_DIR, sizeof(ast_config_AST_KEY_DIR));
2185         ast_copy_string(ast_config_AST_PID, AST_PID, sizeof(ast_config_AST_PID));
2186         ast_copy_string(ast_config_AST_SOCKET, AST_SOCKET, sizeof(ast_config_AST_SOCKET));
2187         ast_copy_string(ast_config_AST_RUN_DIR, AST_RUN_DIR, sizeof(ast_config_AST_RUN_DIR));
2188
2189         /* no asterisk.conf? no problem, use buildtime config! */
2190         if (!cfg) {
2191                 return;
2192         }
2193         v = ast_variable_browse(cfg, "files");
2194         while (v) {
2195                 if (!strcasecmp(v->name, "astctlpermissions")) {
2196                         ast_copy_string(ast_config_AST_CTL_PERMISSIONS, v->value, sizeof(ast_config_AST_CTL_PERMISSIONS));
2197                 } else if (!strcasecmp(v->name, "astctlowner")) {
2198                         ast_copy_string(ast_config_AST_CTL_OWNER, v->value, sizeof(ast_config_AST_CTL_OWNER));
2199                 } else if (!strcasecmp(v->name, "astctlgroup")) {
2200                         ast_copy_string(ast_config_AST_CTL_GROUP, v->value, sizeof(ast_config_AST_CTL_GROUP));
2201                 } else if (!strcasecmp(v->name, "astctl")) {
2202                         ast_copy_string(ast_config_AST_CTL, v->value, sizeof(ast_config_AST_CTL));
2203                 }
2204                 v = v->next;
2205         }
2206         v = ast_variable_browse(cfg, "directories");
2207         while(v) {
2208                 if (!strcasecmp(v->name, "astetcdir")) {
2209                         ast_copy_string(ast_config_AST_CONFIG_DIR, v->value, sizeof(ast_config_AST_CONFIG_DIR));
2210                 } else if (!strcasecmp(v->name, "astspooldir")) {
2211                         ast_copy_string(ast_config_AST_SPOOL_DIR, v->value, sizeof(ast_config_AST_SPOOL_DIR));
2212                         snprintf(ast_config_AST_MONITOR_DIR, sizeof(ast_config_AST_MONITOR_DIR) - 1, "%s/monitor", v->value);
2213                 } else if (!strcasecmp(v->name, "astvarlibdir")) {
2214                         ast_copy_string(ast_config_AST_VAR_DIR, v->value, sizeof(ast_config_AST_VAR_DIR));
2215                         snprintf(ast_config_AST_DB, sizeof(ast_config_AST_DB), "%s/astdb", v->value);
2216                 } else if (!strcasecmp(v->name, "astdatadir")) {
2217                         ast_copy_string(ast_config_AST_DATA_DIR, v->value, sizeof(ast_config_AST_DATA_DIR));
2218                         snprintf(ast_config_AST_KEY_DIR, sizeof(ast_config_AST_KEY_DIR), "%s/keys", v->value);
2219                 } else if (!strcasecmp(v->name, "astlogdir")) {
2220                         ast_copy_string(ast_config_AST_LOG_DIR, v->value, sizeof(ast_config_AST_LOG_DIR));
2221                 } else if (!strcasecmp(v->name, "astagidir")) {
2222                         ast_copy_string(ast_config_AST_AGI_DIR, v->value, sizeof(ast_config_AST_AGI_DIR));
2223                 } else if (!strcasecmp(v->name, "astrundir")) {
2224                         snprintf(ast_config_AST_PID, sizeof(ast_config_AST_PID), "%s/%s", v->value, "asterisk.pid");
2225                         snprintf(ast_config_AST_SOCKET, sizeof(ast_config_AST_SOCKET), "%s/%s", v->value, ast_config_AST_CTL);
2226                         ast_copy_string(ast_config_AST_RUN_DIR, v->value, sizeof(ast_config_AST_RUN_DIR));
2227                 } else if (!strcasecmp(v->name, "astmoddir")) {
2228                         ast_copy_string(ast_config_AST_MODULE_DIR, v->value, sizeof(ast_config_AST_MODULE_DIR));
2229                 } else if (!strcasecmp(v->name, "languageprefix")) {
2230                         ast_language_is_prefix = ast_true(v->value);
2231                 }
2232                 v = v->next;
2233         }
2234         v = ast_variable_browse(cfg, "options");
2235         while(v) {
2236                 /* verbose level (-v at startup) */
2237                 if (!strcasecmp(v->name, "verbose")) {
2238                         option_verbose = atoi(v->value);
2239                 /* whether or not to force timestamping. (-T at startup) */
2240                 } else if (!strcasecmp(v->name, "timestamp")) {
2241                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_TIMESTAMP);
2242                 /* whether or not to support #exec in config files */
2243                 } else if (!strcasecmp(v->name, "execincludes")) {
2244                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_EXEC_INCLUDES);
2245                 /* debug level (-d at startup) */
2246                 } else if (!strcasecmp(v->name, "debug")) {
2247                         option_debug = 0;
2248                         if (sscanf(v->value, "%d", &option_debug) != 1) {
2249                                 option_debug = ast_true(v->value);
2250                         }
2251                 /* Disable forking (-f at startup) */
2252                 } else if (!strcasecmp(v->name, "nofork")) {
2253                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_NO_FORK);
2254                 /* Always fork, even if verbose or debug are enabled (-F at startup) */
2255                 } else if (!strcasecmp(v->name, "alwaysfork")) {
2256                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_ALWAYS_FORK);
2257                 /* Run quietly (-q at startup ) */
2258                 } else if (!strcasecmp(v->name, "quiet")) {
2259                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_QUIET);
2260                 /* Run as console (-c at startup, implies nofork) */
2261                 } else if (!strcasecmp(v->name, "console")) {
2262                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_CONSOLE);
2263                 /* Run with high priority if the O/S permits (-p at startup) */
2264                 } else if (!strcasecmp(v->name, "highpriority")) {
2265                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_HIGH_PRIORITY);
2266                 /* Initialize RSA auth keys (IAX2) (-i at startup) */
2267                 } else if (!strcasecmp(v->name, "initcrypto")) {
2268                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_INIT_KEYS);
2269                 /* Disable ANSI colors for console (-c at startup) */
2270                 } else if (!strcasecmp(v->name, "nocolor")) {
2271                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_NO_COLOR);
2272                 /* Disable some usage warnings for picky people :p */
2273                 } else if (!strcasecmp(v->name, "dontwarn")) {
2274                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_DONT_WARN);
2275                 /* Dump core in case of crash (-g) */
2276                 } else if (!strcasecmp(v->name, "dumpcore")) {
2277                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_DUMP_CORE);
2278                 /* Cache recorded sound files to another directory during recording */
2279                 } else if (!strcasecmp(v->name, "cache_record_files")) {
2280                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_CACHE_RECORD_FILES);
2281                 /* Specify cache directory */
2282                 }  else if (!strcasecmp(v->name, "record_cache_dir")) {
2283                         ast_copy_string(record_cache_dir, v->value, AST_CACHE_DIR_LEN);
2284                 /* Build transcode paths via SLINEAR, instead of directly */
2285                 } else if (!strcasecmp(v->name, "transcode_via_sln")) {
2286                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_TRANSCODE_VIA_SLIN);
2287                 /* Transmit SLINEAR silence while a channel is being recorded */
2288                 } else if (!strcasecmp(v->name, "transmit_silence_during_record")) {
2289                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_TRANSMIT_SILENCE);
2290                 /* Enable internal timing */
2291                 } else if (!strcasecmp(v->name, "internal_timing")) {
2292                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_INTERNAL_TIMING);
2293                 } else if (!strcasecmp(v->name, "maxcalls")) {
2294                         if ((sscanf(v->value, "%d", &option_maxcalls) != 1) || (option_maxcalls < 0)) {
2295                                 option_maxcalls = 0;
2296                         }
2297                 } else if (!strcasecmp(v->name, "maxload")) {
2298                         double test[1];
2299
2300                         if (getloadavg(test, 1) == -1) {
2301                                 ast_log(LOG_ERROR, "Cannot obtain load average on this system. 'maxload' option disabled.\n");
2302                                 option_maxload = 0.0;
2303                         } else if ((sscanf(v->value, "%lf", &option_maxload) != 1) || (option_maxload < 0.0)) {
2304                                 option_maxload = 0.0;
2305                         }
2306                 /* What user to run as */
2307                 } else if (!strcasecmp(v->name, "runuser")) {
2308                         ast_copy_string(ast_config_AST_RUN_USER, v->value, sizeof(ast_config_AST_RUN_USER));
2309                 /* What group to run as */
2310                 } else if (!strcasecmp(v->name, "rungroup")) {
2311                         ast_copy_string(ast_config_AST_RUN_GROUP, v->value, sizeof(ast_config_AST_RUN_GROUP));
2312                 } else if (!strcasecmp(v->name, "systemname")) {
2313                         ast_copy_string(ast_config_AST_SYSTEM_NAME, v->value, sizeof(ast_config_AST_SYSTEM_NAME));
2314                 }
2315                 v = v->next;
2316         }
2317         ast_config_destroy(cfg);
2318 }
2319
2320 int main(int argc, char *argv[])
2321 {
2322         int c;
2323         char filename[80] = "";
2324         char hostname[MAXHOSTNAMELEN] = "";
2325         char tmp[80];
2326         char * xarg = NULL;
2327         int x;
2328         FILE *f;
2329         sigset_t sigs;
2330         int num;
2331         int is_child_of_nonroot = 0;
2332         char *buf;
2333         char *runuser = NULL, *rungroup = NULL;
2334
2335         /* Remember original args for restart */
2336         if (argc > sizeof(_argv) / sizeof(_argv[0]) - 1) {
2337                 fprintf(stderr, "Truncating argument size to %d\n", (int)(sizeof(_argv) / sizeof(_argv[0])) - 1);
2338                 argc = sizeof(_argv) / sizeof(_argv[0]) - 1;
2339         }
2340         for (x=0; x<argc; x++)
2341                 _argv[x] = argv[x];
2342         _argv[x] = NULL;
2343
2344         /* if the progname is rasterisk consider it a remote console */
2345         if (argv[0] && (strstr(argv[0], "rasterisk")) != NULL) {
2346                 ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK | AST_OPT_FLAG_REMOTE);
2347         }
2348         if (gethostname(hostname, sizeof(hostname)-1))
2349                 ast_copy_string(hostname, "<Unknown>", sizeof(hostname));
2350         ast_mainpid = getpid();
2351         ast_ulaw_init();
2352         ast_alaw_init();
2353         callerid_init();
2354         ast_builtins_init();
2355         ast_utils_init();
2356         tdd_init();
2357         /* When Asterisk restarts after it has dropped the root privileges,
2358          * it can't issue setuid(), setgid(), setgroups() or set_priority() 
2359          */
2360         if (getenv("ASTERISK_ALREADY_NONROOT"))
2361                 is_child_of_nonroot=1;
2362         if (getenv("HOME")) 
2363                 snprintf(filename, sizeof(filename), "%s/.asterisk_history", getenv("HOME"));
2364         /* Check for options */
2365         while ((c = getopt(argc, argv, "mtThfdvVqprRgciInx:U:G:C:L:M:")) != -1) {
2366                 switch (c) {
2367                 case 'F':
2368                         ast_set_flag(&ast_options, AST_OPT_FLAG_ALWAYS_FORK);
2369                         break;
2370                 case 'd':
2371                         option_debug++;
2372                         ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK);
2373                         break;
2374                 case 'c':
2375                         ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK | AST_OPT_FLAG_CONSOLE);
2376                         break;
2377                 case 'f':
2378                         ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK);
2379                         break;
2380                 case 'n':
2381                         ast_set_flag(&ast_options, AST_OPT_FLAG_NO_COLOR);
2382                         break;
2383                 case 'r':
2384                         ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK | AST_OPT_FLAG_REMOTE);
2385                         break;
2386                 case 'R':
2387                         ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK | AST_OPT_FLAG_REMOTE | AST_OPT_FLAG_RECONNECT);
2388                         break;
2389                 case 'p':
2390                         ast_set_flag(&ast_options, AST_OPT_FLAG_HIGH_PRIORITY);
2391                         break;
2392                 case 'v':
2393                         option_verbose++;
2394                         ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK);
2395                         break;
2396                 case 'm':
2397                         ast_set_flag(&ast_options, AST_OPT_FLAG_MUTE);
2398                         break;
2399                 case 'M':
2400                         if ((sscanf(optarg, "%d", &option_maxcalls) != 1) || (option_maxcalls < 0))
2401                                 option_maxcalls = 0;
2402                         break;
2403                 case 'L':
2404                         if ((sscanf(optarg, "%lf", &option_maxload) != 1) || (option_maxload < 0.0))
2405                                 option_maxload = 0.0;
2406                         break;
2407                 case 'q':
2408                         ast_set_flag(&ast_options, AST_OPT_FLAG_QUIET);
2409                         break;
2410                 case 't':
2411                         ast_set_flag(&ast_options, AST_OPT_FLAG_CACHE_RECORD_FILES);
2412                         break;
2413                 case 'T':
2414                         ast_set_flag(&ast_options, AST_OPT_FLAG_TIMESTAMP);
2415                         break;
2416                 case 'x':
2417                         ast_set_flag(&ast_options, AST_OPT_FLAG_EXEC);
2418                         xarg = optarg;
2419                         break;
2420                 case 'C':
2421                         ast_copy_string(ast_config_AST_CONFIG_FILE, optarg, sizeof(ast_config_AST_CONFIG_FILE));
2422                         ast_set_flag(&ast_options, AST_OPT_FLAG_OVERRIDE_CONFIG);
2423                         break;
2424                 case 'I':
2425                         ast_set_flag(&ast_options, AST_OPT_FLAG_INTERNAL_TIMING);
2426                         break;
2427                 case 'i':
2428                         ast_set_flag(&ast_options, AST_OPT_FLAG_INIT_KEYS);
2429                         break;
2430                 case 'g':
2431                         ast_set_flag(&ast_options, AST_OPT_FLAG_DUMP_CORE);
2432                         break;
2433                 case 'h':
2434                         show_cli_help();
2435                         exit(0);
2436                 case 'V':
2437                         show_version();
2438                         exit(0);
2439                 case 'U':
2440                         runuser = optarg;
2441                         break;
2442                 case 'G':
2443                         rungroup = optarg;
2444                         break;
2445                 case '?':
2446                         exit(1);
2447                 }
2448         }
2449
2450         if (ast_opt_always_fork && (ast_opt_remote || ast_opt_console)) {
2451                 ast_log(LOG_WARNING, "'alwaysfork' is not compatible with console or remote console mode; ignored\n");
2452                 ast_clear_flag(&ast_options, AST_OPT_FLAG_ALWAYS_FORK);
2453         }
2454
2455         /* For remote connections, change the name of the remote connection.
2456          * We do this for the benefit of init scripts (which need to know if/when
2457          * the main asterisk process has died yet). */
2458         if (ast_opt_remote) {
2459                 strcpy(argv[0], "rasterisk");
2460                 for (x = 1; x < argc; x++) {
2461                         argv[x] = argv[0] + 10;
2462                 }
2463         }
2464
2465         if (ast_opt_console && !option_verbose) 
2466                 ast_verbose("[ Reading Master Configuration ]");
2467         ast_readconfig();
2468
2469         if (ast_opt_dump_core) {
2470                 struct rlimit l;
2471                 memset(&l, 0, sizeof(l));
2472                 l.rlim_cur = RLIM_INFINITY;
2473                 l.rlim_max = RLIM_INFINITY;
2474                 if (setrlimit(RLIMIT_CORE, &l)) {
2475                         ast_log(LOG_WARNING, "Unable to disable core size resource limit: %s\n", strerror(errno));
2476                 }
2477         }
2478
2479         if ((!rungroup) && !ast_strlen_zero(ast_config_AST_RUN_GROUP))
2480                 rungroup = ast_config_AST_RUN_GROUP;
2481         if ((!runuser) && !ast_strlen_zero(ast_config_AST_RUN_USER))
2482                 runuser = ast_config_AST_RUN_USER;
2483
2484 #ifndef __CYGWIN__
2485
2486         if (!is_child_of_nonroot) 
2487                 ast_set_priority(ast_opt_high_priority);
2488
2489         if (!is_child_of_nonroot && rungroup) {
2490                 struct group *gr;
2491                 gr = getgrnam(rungroup);
2492                 if (!gr) {
2493                         ast_log(LOG_WARNING, "No such group '%s'!\n", rungroup);
2494                         exit(1);
2495                 }
2496                 if (setgid(gr->gr_gid)) {
2497                         ast_log(LOG_WARNING, "Unable to setgid to %d (%s)\n", (int)gr->gr_gid, rungroup);
2498                         exit(1);
2499                 }
2500                 if (setgroups(0, NULL)) {
2501                         ast_log(LOG_WARNING, "Unable to drop unneeded groups\n");
2502                         exit(1);
2503                 }
2504                 if (option_verbose)
2505                         ast_verbose("Running as group '%s'\n", rungroup);
2506         }
2507
2508         if (!is_child_of_nonroot && runuser) {
2509                 struct passwd *pw;
2510                 pw = getpwnam(runuser);
2511                 if (!pw) {
2512                         ast_log(LOG_WARNING, "No such user '%s'!\n", runuser);
2513                         exit(1);
2514                 }
2515                 if (!rungroup) {
2516                         if (setgid(pw->pw_gid)) {
2517                                 ast_log(LOG_WARNING, "Unable to setgid to %d!\n", (int)pw->pw_gid);
2518                                 exit(1);
2519                         }
2520                         if (initgroups(pw->pw_name, pw->pw_gid)) {
2521                                 ast_log(LOG_WARNING, "Unable to init groups for '%s'\n", runuser);
2522                                 exit(1);
2523                         }
2524                 }
2525                 if (setuid(pw->pw_uid)) {
2526                         ast_log(LOG_WARNING, "Unable to setuid to %d (%s)\n", (int)pw->pw_uid, runuser);
2527                         exit(1);
2528                 }
2529                 setenv("ASTERISK_ALREADY_NONROOT", "yes", 1);
2530                 if (option_verbose)
2531                         ast_verbose("Running as user '%s'\n", runuser);
2532         }
2533
2534 #endif /* __CYGWIN__ */
2535
2536 #ifdef linux
2537         if (geteuid() && ast_opt_dump_core) {
2538                 if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) < 0) {
2539                         ast_log(LOG_WARNING, "Unable to set the process for core dumps after changing to a non-root user. %s\n", strerror(errno));
2540                 }       
2541         }
2542 #endif
2543
2544         term_init();
2545         printf(term_end());
2546         fflush(stdout);
2547
2548         if (ast_opt_console && !option_verbose) 
2549                 ast_verbose("[ Initializing Custom Configuration Options ]");
2550         /* custom config setup */
2551         register_config_cli();
2552         read_config_maps();
2553         
2554         if (ast_opt_console) {
2555                 if (el_hist == NULL || el == NULL)
2556                         ast_el_initialize();
2557
2558                 if (!ast_strlen_zero(filename))
2559                         ast_el_read_history(filename);
2560         }
2561
2562         if (ast_tryconnect()) {
2563                 /* One is already running */
2564                 if (ast_opt_remote) {
2565                         if (ast_opt_exec) {
2566                                 ast_remotecontrol(xarg);
2567                                 quit_handler(0, 0, 0, 0);
2568                                 exit(0);
2569                         }
2570                         printf(term_quit());
2571                         ast_register_verbose(console_verboser);
2572                         WELCOME_MESSAGE;
2573                         ast_remotecontrol(NULL);
2574                         quit_handler(0, 0, 0, 0);
2575                         exit(0);
2576                 } else {
2577                         ast_log(LOG_ERROR, "Asterisk already running on %s.  Use 'asterisk -r' to connect.\n", ast_config_AST_SOCKET);
2578                         printf(term_quit());
2579                         exit(1);
2580                 }
2581         } else if (ast_opt_remote || ast_opt_exec) {
2582                 ast_log(LOG_ERROR, "Unable to connect to remote asterisk (does %s exist?)\n", ast_config_AST_SOCKET);
2583                 printf(term_quit());
2584                 exit(1);
2585         }
2586         /* Blindly write pid file since we couldn't connect */
2587         unlink(ast_config_AST_PID);
2588         f = fopen(ast_config_AST_PID, "w");
2589         if (f) {
2590                 fprintf(f, "%ld\n", (long)getpid());
2591                 fclose(f);
2592         } else
2593                 ast_log(LOG_WARNING, "Unable to open pid file '%s': %s\n", ast_config_AST_PID, strerror(errno));
2594
2595         if (ast_opt_always_fork || !ast_opt_no_fork) {
2596                 daemon(0, 0);
2597                 ast_mainpid = getpid();
2598                 /* Blindly re-write pid file since we are forking */
2599                 unlink(ast_config_AST_PID);
2600                 f = fopen(ast_config_AST_PID, "w");
2601                 if (f) {
2602                         fprintf(f, "%ld\n", (long)ast_mainpid);
2603                         fclose(f);
2604                 } else
2605                         ast_log(LOG_WARNING, "Unable to open pid file '%s': %s\n", ast_config_AST_PID, strerror(errno));
2606         }
2607
2608         /* Test recursive mutex locking. */
2609         if (test_for_thread_safety())
2610                 ast_verbose("Warning! Asterisk is not thread safe.\n");
2611
2612         ast_makesocket();
2613         sigemptyset(&sigs);
2614         sigaddset(&sigs, SIGHUP);
2615         sigaddset(&sigs, SIGTERM);
2616         sigaddset(&sigs, SIGINT);
2617         sigaddset(&sigs, SIGPIPE);
2618         sigaddset(&sigs, SIGWINCH);
2619         pthread_sigmask(SIG_BLOCK, &sigs, NULL);
2620         if (ast_opt_console || option_verbose || ast_opt_remote)
2621                 ast_register_verbose(console_verboser);
2622         /* Print a welcome message if desired */
2623         if (option_verbose || ast_opt_console) {
2624                 WELCOME_MESSAGE;
2625         }
2626         if (ast_opt_console && !option_verbose) 
2627                 ast_verbose("[ Booting...");
2628
2629         signal(SIGURG, urg_handler);
2630         signal(SIGINT, __quit_handler);
2631         signal(SIGTERM, __quit_handler);
2632         signal(SIGHUP, hup_handler);
2633         signal(SIGCHLD, child_handler);
2634         signal(SIGPIPE, SIG_IGN);
2635
2636         /* ensure that the random number generators are seeded with a different value every time
2637            Asterisk is started
2638         */
2639         srand((unsigned int) getpid() + (unsigned int) time(NULL));
2640         initstate((unsigned int) getpid() * 65536 + (unsigned int) time(NULL), randompool, sizeof(randompool));
2641
2642         if (init_logger()) {
2643                 printf(term_quit());
2644                 exit(1);
2645         }
2646         if (dnsmgr_init()) {
2647                 printf(term_quit());
2648                 exit(1);
2649         }
2650         /* load 'preload' modules, required for access to Realtime-mapped configuration files */
2651         if (load_modules(1)) {
2652                 printf(term_quit());
2653                 exit(1);
2654         }
2655         ast_http_init();
2656         ast_channels_init();
2657         if (init_manager()) {
2658                 printf(term_quit());
2659                 exit(1);
2660         }
2661         if (ast_cdr_engine_init()) {
2662                 printf(term_quit());
2663                 exit(1);
2664         }
2665         if (ast_device_state_engine_init()) {
2666                 printf(term_quit());
2667                 exit(1);
2668         }
2669         ast_rtp_init();
2670         ast_udptl_init();
2671         if (ast_image_init()) {
2672                 printf(term_quit());
2673                 exit(1);
2674         }
2675         if (ast_file_init()) {
2676                 printf(term_quit());
2677                 exit(1);
2678         }
2679         if (load_pbx()) {
2680                 printf(term_quit());
2681                 exit(1);
2682         }
2683         if (load_modules(0)) {
2684                 printf(term_quit());
2685                 exit(1);
2686         }
2687         if (init_framer()) {
2688                 printf(term_quit());
2689                 exit(1);
2690         }
2691         if (astdb_init()) {
2692                 printf(term_quit());
2693                 exit(1);
2694         }
2695         if (ast_enum_init()) {
2696                 printf(term_quit());
2697                 exit(1);
2698         }
2699
2700         dnsmgr_start_refresh();
2701
2702 #if 0
2703         /* This should no longer be necessary */
2704         /* sync cust config and reload some internals in case a custom config handler binded to them */
2705         read_ast_cust_config();
2706         reload_logger(0);
2707         reload_manager();
2708         ast_enum_reload();
2709         ast_rtp_reload();
2710 #endif
2711
2712         /* We might have the option of showing a console, but for now just
2713            do nothing... */
2714         if (ast_opt_console && !option_verbose)
2715                 ast_verbose(" ]\n");
2716         if (option_verbose || ast_opt_console)
2717                 ast_verbose(term_color(tmp, "Asterisk Ready.\n", COLOR_BRWHITE, COLOR_BLACK, sizeof(tmp)));
2718         if (ast_opt_no_fork)
2719                 consolethread = pthread_self();
2720         ast_set_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED);
2721         pthread_sigmask(SIG_UNBLOCK, &sigs, NULL);
2722 #ifdef __AST_DEBUG_MALLOC
2723         __ast_mm_init();
2724 #endif  
2725         time(&ast_startuptime);
2726         ast_cli_register_multiple(core_cli, sizeof(core_cli) / sizeof(core_cli[0]));
2727         if (ast_opt_console) {
2728                 /* Console stuff now... */
2729                 /* Register our quit function */
2730                 char title[256];
2731                 set_icon("Asterisk");
2732                 snprintf(title, sizeof(title), "Asterisk Console on '%s' (pid %ld)", hostname, (long)ast_mainpid);
2733                 set_title(title);
2734
2735                 for (;;) {
2736                         buf = (char *)el_gets(el, &num);
2737                         if (buf) {
2738                                 if (buf[strlen(buf)-1] == '\n')
2739                                         buf[strlen(buf)-1] = '\0';
2740
2741                                 consolehandler((char *)buf);
2742                         } else {
2743                                 if (write(STDOUT_FILENO, "\nUse EXIT or QUIT to exit the asterisk console\n",
2744                                                 strlen("\nUse EXIT or QUIT to exit the asterisk console\n")) < 0) {
2745                                         /* Whoa, stdout disappeared from under us... Make /dev/null's */
2746                                         int fd;
2747                                         fd = open("/dev/null", O_RDWR);
2748                                         if (fd > -1) {
2749                                                 dup2(fd, STDOUT_FILENO);
2750                                                 dup2(fd, STDIN_FILENO);
2751                                         } else
2752                                                 ast_log(LOG_WARNING, "Failed to open /dev/null to recover from dead console. Bad things will happen!\n");
2753                                         break;
2754                                 }
2755                         }
2756                 }
2757
2758         }
2759         /* Do nothing */
2760         for(;;)  {      /* apparently needed for the MACos */
2761                 struct pollfd p = { -1 /* no descriptor */, 0, 0 };
2762                 poll(&p, 0, -1);
2763         }
2764         return 0;
2765 }