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