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