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