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