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