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