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