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