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