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