Add some more hold music
[asterisk/asterisk.git] / asterisk.c
1 /*
2  * Asterisk -- A telephony toolkit for Linux.
3  *
4  * Top level source file for asterisk
5  * 
6  * Copyright (C) 1999, Mark Spencer
7  *
8  * Mark Spencer <markster@linux-support.net>
9  *
10  * This program is free software, distributed under the terms of
11  * the GNU General Public License
12  */
13
14 #include <unistd.h>
15 #include <stdlib.h>
16 #include <sys/poll.h>
17 #include <asterisk/logger.h>
18 #include <asterisk/options.h>
19 #include <asterisk/cli.h>
20 #include <asterisk/channel.h>
21 #include <asterisk/ulaw.h>
22 #include <asterisk/alaw.h>
23 #include <asterisk/callerid.h>
24 #include <asterisk/module.h>
25 #include <asterisk/image.h>
26 #include <asterisk/tdd.h>
27 #include <asterisk/term.h>
28 #include <asterisk/manager.h>
29 #include <asterisk/pbx.h>
30 #include <asterisk/enum.h>
31 #include <asterisk/rtp.h>
32 #include <asterisk/app.h>
33 #include <asterisk/lock.h>
34 #include <asterisk/utils.h>
35 #include <asterisk/file.h>
36 #include <sys/resource.h>
37 #include <fcntl.h>
38 #include <stdio.h>
39 #include <signal.h>
40 #include <sched.h>
41 #include <asterisk/io.h>
42 #include <asterisk/lock.h>
43 #include <sys/socket.h>
44 #include <sys/un.h>
45 #include <sys/wait.h>
46 #include <string.h>
47 #include <errno.h>
48 #include <ctype.h>
49 #include "editline/histedit.h"
50 #include "asterisk.h"
51 #include <asterisk/config.h>
52 #include <asterisk/config_pvt.h>
53 #include <sys/resource.h>
54 #include <grp.h>
55 #include <pwd.h>
56
57 #if  defined(__FreeBSD__)
58 #include <netdb.h>
59 #endif
60
61 #define AST_MAX_CONNECTS 128
62 #define NUM_MSGS 64
63
64 #define WELCOME_MESSAGE ast_verbose( "Asterisk " ASTERISK_VERSION ", Copyright (C) 1999-2004 Digium.\n"); \
65                 ast_verbose( "Written by Mark Spencer <markster@digium.com>\n"); \
66                 ast_verbose( "=========================================================================\n")
67
68 int option_verbose=0;
69 int option_debug=0;
70 int option_nofork=0;
71 int option_quiet=0;
72 int option_console=0;
73 int option_highpriority=0;
74 int option_remote=0;
75 int option_exec=0;
76 int option_initcrypto=0;
77 int option_nocolor;
78 int option_dumpcore = 0;
79 int option_overrideconfig = 0;
80 int option_reconnect = 0;
81 int fully_booted = 0;
82
83 static int ast_socket = -1;             /* UNIX Socket for allowing remote control */
84 static int ast_consock = -1;            /* UNIX Socket for controlling another asterisk */
85 int ast_mainpid;
86 struct console {
87         int fd;                                 /* File descriptor */
88         int p[2];                               /* Pipe */
89         pthread_t t;                    /* Thread of handler */
90 };
91
92 static struct ast_atexit {
93         void (*func)(void);
94         struct ast_atexit *next;
95 } *atexits = NULL;
96 AST_MUTEX_DEFINE_STATIC(atexitslock);
97
98 time_t ast_startuptime;
99 time_t ast_lastreloadtime;
100
101 static History *el_hist = NULL;
102 static EditLine *el = NULL;
103 static char *remotehostname;
104
105 struct console consoles[AST_MAX_CONNECTS];
106
107 char defaultlanguage[MAX_LANGUAGE] = DEFAULT_LANGUAGE;
108
109 static int ast_el_add_history(char *);
110 static int ast_el_read_history(char *);
111 static int ast_el_write_history(char *);
112
113 char ast_config_AST_CONFIG_DIR[AST_CONFIG_MAX_PATH];
114 char ast_config_AST_CONFIG_FILE[AST_CONFIG_MAX_PATH];
115 char ast_config_AST_MODULE_DIR[AST_CONFIG_MAX_PATH];
116 char ast_config_AST_SPOOL_DIR[AST_CONFIG_MAX_PATH];
117 char ast_config_AST_VAR_DIR[AST_CONFIG_MAX_PATH];
118 char ast_config_AST_LOG_DIR[AST_CONFIG_MAX_PATH];
119 char ast_config_AST_AGI_DIR[AST_CONFIG_MAX_PATH];
120 char ast_config_AST_DB[AST_CONFIG_MAX_PATH];
121 char ast_config_AST_KEY_DIR[AST_CONFIG_MAX_PATH];
122 char ast_config_AST_PID[AST_CONFIG_MAX_PATH];
123 char ast_config_AST_SOCKET[AST_CONFIG_MAX_PATH];
124 char ast_config_AST_RUN_DIR[AST_CONFIG_MAX_PATH];
125
126 static char *_argv[256];
127 static int shuttingdown = 0;
128 static int restartnow = 0;
129 static pthread_t consolethread = AST_PTHREADT_NULL;
130
131 int ast_register_atexit(void (*func)(void))
132 {
133         int res = -1;
134         struct ast_atexit *ae;
135         ast_unregister_atexit(func);
136         ae = malloc(sizeof(struct ast_atexit));
137         ast_mutex_lock(&atexitslock);
138         if (ae) {
139                 memset(ae, 0, sizeof(struct ast_atexit));
140                 ae->next = atexits;
141                 ae->func = func;
142                 atexits = ae;
143                 res = 0;
144         }
145         ast_mutex_unlock(&atexitslock);
146         return res;
147 }
148
149 void ast_unregister_atexit(void (*func)(void))
150 {
151         struct ast_atexit *ae, *prev = NULL;
152         ast_mutex_lock(&atexitslock);
153         ae = atexits;
154         while(ae) {
155                 if (ae->func == func) {
156                         if (prev)
157                                 prev->next = ae->next;
158                         else
159                                 atexits = ae->next;
160                         break;
161                 }
162                 prev = ae;
163                 ae = ae->next;
164         }
165         ast_mutex_unlock(&atexitslock);
166 }
167
168 static int fdprint(int fd, const char *s)
169 {
170         return write(fd, s, strlen(s) + 1);
171 }
172
173 int ast_safe_system(const char *s)
174 {
175         /* XXX This function needs some optimization work XXX */
176         pid_t pid;
177         int x;
178         int res;
179         struct rusage rusage;
180         int status;
181         pid = fork();
182         if (pid == 0) {
183                 /* Close file descriptors and launch system command */
184                 for (x=STDERR_FILENO + 1; x<4096;x++) {
185                         close(x);
186                 }
187                 res = execl("/bin/sh", "/bin/sh", "-c", s, NULL);
188                 exit(1);
189         } else if (pid > 0) {
190                 for(;;) {
191                         res = wait4(pid, &status, 0, &rusage);
192                         if (res > -1) {
193                                 if (WIFEXITED(status))
194                                         res = WEXITSTATUS(status);
195                                 else
196                                         res = -1;
197                                 break;
198                         } else {
199                                 if (errno != EINTR) 
200                                         break;
201                         }
202                 }
203         } else {
204                 ast_log(LOG_WARNING, "Fork failed: %s\n", strerror(errno));
205                 res = -1;
206         }
207         return res;
208 }
209
210 /*
211  * write the string to all attached console clients
212  */
213 static void ast_network_puts(const char *string)
214 {
215         int x;
216         for (x=0;x<AST_MAX_CONNECTS; x++) {
217                 if (consoles[x].fd > -1) 
218                         fdprint(consoles[x].p[1], string);
219         }
220 }
221
222 /*
223  * write the string to the console, and all attached
224  * console clients
225  */
226 void ast_console_puts(const char *string)
227 {
228         fputs(string, stdout);
229         fflush(stdout);
230         ast_network_puts(string);
231 }
232
233 static void network_verboser(const char *s, int pos, int replace, int complete)
234         /* ARGUSED */
235 {
236         ast_network_puts(s);
237 }
238
239 static pthread_t lthread;
240
241 static void *netconsole(void *vconsole)
242 {
243         struct console *con = vconsole;
244         char hostname[256];
245         char tmp[512];
246         int res;
247         struct pollfd fds[2];
248         
249         if (gethostname(hostname, sizeof(hostname)))
250                 strncpy(hostname, "<Unknown>", sizeof(hostname)-1);
251         snprintf(tmp, sizeof(tmp), "%s/%d/%s\n", hostname, ast_mainpid, ASTERISK_VERSION);
252         fdprint(con->fd, tmp);
253         for(;;) {
254                 fds[0].fd = con->fd;
255                 fds[0].events = POLLIN;
256                 fds[1].fd = con->p[0];
257                 fds[1].events = POLLIN;
258
259                 res = poll(fds, 2, -1);
260                 if (res < 0) {
261                         if (errno != EINTR)
262                                 ast_log(LOG_WARNING, "poll returned < 0: %s\n", strerror(errno));
263                         continue;
264                 }
265                 if (fds[0].revents) {
266                         res = read(con->fd, tmp, sizeof(tmp));
267                         if (res < 1) {
268                                 break;
269                         }
270                         tmp[res] = 0;
271                         ast_cli_command(con->fd, tmp);
272                 }
273                 if (fds[1].revents) {
274                         res = read(con->p[0], tmp, sizeof(tmp));
275                         if (res < 1) {
276                                 ast_log(LOG_ERROR, "read returned %d\n", res);
277                                 break;
278                         }
279                         res = write(con->fd, tmp, res);
280                         if (res < 1)
281                                 break;
282                 }
283         }
284         if (option_verbose > 2) 
285                 ast_verbose(VERBOSE_PREFIX_3 "Remote UNIX connection disconnected\n");
286         close(con->fd);
287         close(con->p[0]);
288         close(con->p[1]);
289         con->fd = -1;
290         
291         return NULL;
292 }
293
294 static void *listener(void *unused)
295 {
296         struct sockaddr_un sun;
297         int s;
298         int len;
299         int x;
300         int flags;
301         struct pollfd fds[1];
302         pthread_attr_t attr;
303         pthread_attr_init(&attr);
304         pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
305         for(;;) {
306                 if (ast_socket < 0)
307                         return NULL;
308                 fds[0].fd = ast_socket;
309                 fds[0].events= POLLIN;
310                 s = poll(fds, 1, -1);
311                 if (s < 0) {
312                         if (errno != EINTR)
313                                 ast_log(LOG_WARNING, "poll returned error: %s\n", strerror(errno));
314                         continue;
315                 }
316                 len = sizeof(sun);
317                 s = accept(ast_socket, (struct sockaddr *)&sun, &len);
318                 if (s < 0) {
319                         if (errno != EINTR)
320                                 ast_log(LOG_WARNING, "Accept returned %d: %s\n", s, strerror(errno));
321                 } else {
322                         for (x=0;x<AST_MAX_CONNECTS;x++) {
323                                 if (consoles[x].fd < 0) {
324                                         if (socketpair(AF_LOCAL, SOCK_STREAM, 0, consoles[x].p)) {
325                                                 ast_log(LOG_ERROR, "Unable to create pipe: %s\n", strerror(errno));
326                                                 consoles[x].fd = -1;
327                                                 fdprint(s, "Server failed to create pipe\n");
328                                                 close(s);
329                                                 break;
330                                         }
331                                         flags = fcntl(consoles[x].p[1], F_GETFL);
332                                         fcntl(consoles[x].p[1], F_SETFL, flags | O_NONBLOCK);
333                                         consoles[x].fd = s;
334                                         if (pthread_create(&consoles[x].t, &attr, netconsole, &consoles[x])) {
335                                                 ast_log(LOG_ERROR, "Unable to spawn thread to handle connection: %s\n", strerror(errno));
336                                                 consoles[x].fd = -1;
337                                                 fdprint(s, "Server failed to spawn thread\n");
338                                                 close(s);
339                                         }
340                                         break;
341                                 }
342                         }
343                         if (x >= AST_MAX_CONNECTS) {
344                                 fdprint(s, "No more connections allowed\n");
345                                 ast_log(LOG_WARNING, "No more connections allowed\n");
346                                 close(s);
347                         } else if (consoles[x].fd > -1) {
348                                 if (option_verbose > 2) 
349                                         ast_verbose(VERBOSE_PREFIX_3 "Remote UNIX connection\n");
350                         }
351                 }
352         }
353         return NULL;
354 }
355
356 static int ast_makesocket(void)
357 {
358         struct sockaddr_un sun;
359         int res;
360         int x;
361         for (x=0;x<AST_MAX_CONNECTS;x++)        
362                 consoles[x].fd = -1;
363         unlink((char *)ast_config_AST_SOCKET);
364         ast_socket = socket(PF_LOCAL, SOCK_STREAM, 0);
365         if (ast_socket < 0) {
366                 ast_log(LOG_WARNING, "Unable to create control socket: %s\n", strerror(errno));
367                 return -1;
368         }               
369         memset(&sun, 0, sizeof(sun));
370         sun.sun_family = AF_LOCAL;
371         strncpy(sun.sun_path, (char *)ast_config_AST_SOCKET, sizeof(sun.sun_path)-1);
372         res = bind(ast_socket, (struct sockaddr *)&sun, sizeof(sun));
373         if (res) {
374                 ast_log(LOG_WARNING, "Unable to bind socket to %s: %s\n", (char *)ast_config_AST_SOCKET, strerror(errno));
375                 close(ast_socket);
376                 ast_socket = -1;
377                 return -1;
378         }
379         res = listen(ast_socket, 2);
380         if (res < 0) {
381                 ast_log(LOG_WARNING, "Unable to listen on socket %s: %s\n", (char *)ast_config_AST_SOCKET, strerror(errno));
382                 close(ast_socket);
383                 ast_socket = -1;
384                 return -1;
385         }
386         ast_register_verbose(network_verboser);
387         pthread_create(&lthread, NULL, listener, NULL);
388         return 0;
389 }
390
391 static int ast_tryconnect(void)
392 {
393         struct sockaddr_un sun;
394         int res;
395         ast_consock = socket(PF_LOCAL, SOCK_STREAM, 0);
396         if (ast_consock < 0) {
397                 ast_log(LOG_WARNING, "Unable to create socket: %s\n", strerror(errno));
398                 return 0;
399         }
400         memset(&sun, 0, sizeof(sun));
401         sun.sun_family = AF_LOCAL;
402         strncpy(sun.sun_path, (char *)ast_config_AST_SOCKET, sizeof(sun.sun_path)-1);
403         res = connect(ast_consock, (struct sockaddr *)&sun, sizeof(sun));
404         if (res) {
405                 close(ast_consock);
406                 ast_consock = -1;
407                 return 0;
408         } else
409                 return 1;
410 }
411
412 static void urg_handler(int num)
413 {
414         /* Called by soft_hangup to interrupt the poll, read, or other
415            system call.  We don't actually need to do anything though.  */
416         /* Cannot EVER ast_log from within a signal handler */
417         if (option_debug) 
418                 printf("Urgent handler\n");
419         signal(num, urg_handler);
420         return;
421 }
422
423 static void hup_handler(int num)
424 {
425         if (option_verbose > 1) 
426                 printf("Received HUP signal -- Reloading configs\n");
427         if (restartnow)
428                 execvp(_argv[0], _argv);
429         /* XXX This could deadlock XXX */
430         ast_module_reload();
431 }
432
433 static void child_handler(int sig)
434 {
435         /* Must not ever ast_log or ast_verbose within signal handler */
436         int n, status;
437
438         /*
439          * Reap all dead children -- not just one
440          */
441         for (n = 0; wait4(-1, &status, WNOHANG, NULL) > 0; n++)
442                 ;
443         if (n == 0 && option_debug)     
444                 printf("Huh?  Child handler, but nobody there?\n");
445 }
446
447 static void set_title(char *text)
448 {
449         /* Set an X-term or screen title */
450         if (getenv("TERM") && strstr(getenv("TERM"), "xterm"))
451                 fprintf(stdout, "\033]2;%s\007", text);
452 }
453
454 static void set_icon(char *text)
455 {
456         if (getenv("TERM") && strstr(getenv("TERM"), "xterm"))
457                 fprintf(stdout, "\033]1;%s\007", text);
458 }
459
460 static int set_priority(int pri)
461 {
462         struct sched_param sched;
463         memset(&sched, 0, sizeof(sched));
464         /* We set ourselves to a high priority, that we might pre-empt everything
465            else.  If your PBX has heavy activity on it, this is a good thing.  */
466 #ifdef __linux__
467         if (pri) {  
468                 sched.sched_priority = 10;
469                 if (sched_setscheduler(0, SCHED_RR, &sched)) {
470                         ast_log(LOG_WARNING, "Unable to set high priority\n");
471                         return -1;
472                 } else
473                         if (option_verbose)
474                                 ast_verbose("Set to realtime thread\n");
475         } else {
476                 sched.sched_priority = 0;
477                 if (sched_setscheduler(0, SCHED_OTHER, &sched)) {
478                         ast_log(LOG_WARNING, "Unable to set normal priority\n");
479                         return -1;
480                 }
481         }
482 #else
483         if (pri) {
484                 if (setpriority(PRIO_PROCESS, 0, -10) == -1) {
485                         ast_log(LOG_WARNING, "Unable to set high priority\n");
486                         return -1;
487                 } else
488                         if (option_verbose)
489                                 ast_verbose("Set to high priority\n");
490         } else {
491                 if (setpriority(PRIO_PROCESS, 0, 0) == -1) {
492                         ast_log(LOG_WARNING, "Unable to set normal priority\n");
493                         return -1;
494                 }
495         }
496 #endif
497         return 0;
498 }
499
500 static void ast_run_atexits(void)
501 {
502         struct ast_atexit *ae;
503         ast_mutex_lock(&atexitslock);
504         ae = atexits;
505         while(ae) {
506                 if (ae->func) 
507                         ae->func();
508                 ae = ae->next;
509         }
510         ast_mutex_unlock(&atexitslock);
511 }
512
513 static void quit_handler(int num, int nice, int safeshutdown, int restart)
514 {
515         char filename[80] = "";
516         time_t s,e;
517         int x;
518         if (safeshutdown) {
519                 shuttingdown = 1;
520                 if (!nice) {
521                         /* Begin shutdown routine, hanging up active channels */
522                         ast_begin_shutdown(1);
523                         if (option_verbose && option_console)
524                                 ast_verbose("Beginning asterisk %s....\n", restart ? "restart" : "shutdown");
525                         time(&s);
526                         for(;;) {
527                                 time(&e);
528                                 /* Wait up to 15 seconds for all channels to go away */
529                                 if ((e - s) > 15)
530                                         break;
531                                 if (!ast_active_channels())
532                                         break;
533                                 if (!shuttingdown)
534                                         break;
535                                 /* Sleep 1/10 of a second */
536                                 usleep(100000);
537                         }
538                 } else {
539                         if (nice < 2)
540                                 ast_begin_shutdown(0);
541                         if (option_verbose && option_console)
542                                 ast_verbose("Waiting for inactivity to perform %s...\n", restart ? "restart" : "halt");
543                         for(;;) {
544                                 if (!ast_active_channels())
545                                         break;
546                                 if (!shuttingdown)
547                                         break;
548                                 sleep(1);
549                         }
550                 }
551
552                 if (!shuttingdown) {
553                         if (option_verbose && option_console)
554                                 ast_verbose("Asterisk %s cancelled.\n", restart ? "restart" : "shutdown");
555                         return;
556                 }
557         }
558         if (option_console || option_remote) {
559                 if (getenv("HOME")) 
560                         snprintf(filename, sizeof(filename), "%s/.asterisk_history", getenv("HOME"));
561                 if (!ast_strlen_zero(filename))
562                         ast_el_write_history(filename);
563                 if (el != NULL)
564                         el_end(el);
565                 if (el_hist != NULL)
566                         history_end(el_hist);
567         }
568         if (option_verbose)
569                 ast_verbose("Executing last minute cleanups\n");
570         ast_run_atexits();
571         /* Called on exit */
572         if (option_verbose && option_console)
573                 ast_verbose("Asterisk %s ending (%d).\n", ast_active_channels() ? "uncleanly" : "cleanly", num);
574         else if (option_debug)
575                 ast_log(LOG_DEBUG, "Asterisk ending (%d).\n", num);
576         manager_event(EVENT_FLAG_SYSTEM, "Shutdown", "Shutdown: %s\r\nRestart: %s\r\n", ast_active_channels() ? "Uncleanly" : "Cleanly", restart ? "True" : "False");
577         if (ast_socket > -1) {
578                 close(ast_socket);
579                 ast_socket = -1;
580         }
581         if (ast_consock > -1)
582                 close(ast_consock);
583         if (ast_socket > -1)
584                 unlink((char *)ast_config_AST_SOCKET);
585         if (!option_remote) unlink((char *)ast_config_AST_PID);
586         printf(term_quit());
587         if (restart) {
588                 if (option_verbose || option_console)
589                         ast_verbose("Preparing for Asterisk restart...\n");
590                 /* Mark all FD's for closing on exec */
591                 for (x=3;x<32768;x++) {
592                         fcntl(x, F_SETFD, FD_CLOEXEC);
593                 }
594                 if (option_verbose || option_console)
595                         ast_verbose("Restarting Asterisk NOW...\n");
596                 restartnow = 1;
597
598                 /* close logger */
599                 close_logger();
600
601                 /* If there is a consolethread running send it a SIGHUP 
602                    so it can execvp, otherwise we can do it ourselves */
603                 if (consolethread != AST_PTHREADT_NULL) {
604                         pthread_kill(consolethread, SIGHUP);
605                         /* Give the signal handler some time to complete */
606                         sleep(2);
607                 } else
608                         execvp(_argv[0], _argv);
609         
610         } else {
611                 /* close logger */
612                 close_logger();
613         }
614         exit(0);
615 }
616
617 static void __quit_handler(int num)
618 {
619         quit_handler(num, 0, 1, 0);
620 }
621
622 static const char *fix_header(char *outbuf, int maxout, const char *s, char *cmp)
623 {
624         const char *c;
625         if (!strncmp(s, cmp, strlen(cmp))) {
626                 c = s + strlen(cmp);
627                 term_color(outbuf, cmp, COLOR_GRAY, 0, maxout);
628                 return c;
629         }
630         return NULL;
631 }
632
633 static void console_verboser(const char *s, int pos, int replace, int complete)
634 {
635         char tmp[80];
636         const char *c=NULL;
637         /* Return to the beginning of the line */
638         if (!pos) {
639                 fprintf(stdout, "\r");
640                 if ((c = fix_header(tmp, sizeof(tmp), s, VERBOSE_PREFIX_4)) ||
641                         (c = fix_header(tmp, sizeof(tmp), s, VERBOSE_PREFIX_3)) ||
642                         (c = fix_header(tmp, sizeof(tmp), s, VERBOSE_PREFIX_2)) ||
643                         (c = fix_header(tmp, sizeof(tmp), s, VERBOSE_PREFIX_1)))
644                         fputs(tmp, stdout);
645         }
646         if (c)
647                 fputs(c + pos,stdout);
648         else
649                 fputs(s + pos,stdout);
650         fflush(stdout);
651         if (complete)
652         /* Wake up a poll()ing console */
653                 if (option_console && consolethread != AST_PTHREADT_NULL)
654                         pthread_kill(consolethread, SIGURG);
655 }
656
657 static int ast_all_zeros(char *s)
658 {
659         while(*s) {
660                 if (*s > 32)
661                         return 0;
662                 s++;  
663         }
664         return 1;
665 }
666
667 static void consolehandler(char *s)
668 {
669         printf(term_end());
670         fflush(stdout);
671         /* Called when readline data is available */
672         if (s && !ast_all_zeros(s))
673                 ast_el_add_history(s);
674         /* Give the console access to the shell */
675         if (s) {
676                 /* The real handler for bang */
677                 if (s[0] == '!') {
678                         if (s[1])
679                                 ast_safe_system(s+1);
680                         else
681                                 ast_safe_system(getenv("SHELL") ? getenv("SHELL") : "/bin/sh");
682                 } else 
683                 ast_cli_command(STDOUT_FILENO, s);
684         } else
685                 fprintf(stdout, "\nUse \"quit\" to exit\n");
686 }
687
688 static int remoteconsolehandler(char *s)
689 {
690         int ret = 0;
691         /* Called when readline data is available */
692         if (s && !ast_strlen_zero(s))
693                 ast_el_add_history(s);
694         /* Give the console access to the shell */
695         if (s) {
696                 /* The real handler for bang */
697                 if (s[0] == '!') {
698                         if (s[1])
699                                 ast_safe_system(s+1);
700                         else
701                                 ast_safe_system(getenv("SHELL") ? getenv("SHELL") : "/bin/sh");
702                         ret = 1;
703                 }
704                 if ((strncasecmp(s, "quit", 4) == 0 || strncasecmp(s, "exit", 4) == 0) &&
705                     (s[4] == '\0' || isspace(s[4]))) {
706                         quit_handler(0, 0, 0, 0);
707                         ret = 1;
708                 }
709         } else
710                 fprintf(stdout, "\nUse \"quit\" to exit\n");
711
712         return ret;
713 }
714
715 static char quit_help[] = 
716 "Usage: quit\n"
717 "       Exits Asterisk.\n";
718
719 static char abort_halt_help[] = 
720 "Usage: abort shutdown\n"
721 "       Causes Asterisk to abort an executing shutdown or restart, and resume normal\n"
722 "       call operations.\n";
723
724 static char shutdown_now_help[] = 
725 "Usage: stop now\n"
726 "       Shuts down a running Asterisk immediately, hanging up all active calls .\n";
727
728 static char shutdown_gracefully_help[] = 
729 "Usage: stop gracefully\n"
730 "       Causes Asterisk to not accept new calls, and exit when all\n"
731 "       active calls have terminated normally.\n";
732
733 static char shutdown_when_convenient_help[] = 
734 "Usage: stop when convenient\n"
735 "       Causes Asterisk to perform a shutdown when all active calls have ended.\n";
736
737 static char restart_now_help[] = 
738 "Usage: restart now\n"
739 "       Causes Asterisk to hangup all calls and exec() itself performing a cold.\n"
740 "       restart.\n";
741
742 static char restart_gracefully_help[] = 
743 "Usage: restart gracefully\n"
744 "       Causes Asterisk to stop accepting new calls and exec() itself performing a cold.\n"
745 "       restart when all active calls have ended.\n";
746
747 static char restart_when_convenient_help[] = 
748 "Usage: restart when convenient\n"
749 "       Causes Asterisk to perform a cold restart when all active calls have ended.\n";
750
751 static char bang_help[] =
752 "Usage: !<command>\n"
753 "       Executes a given shell command\n";
754
755 #if 0
756 static int handle_quit(int fd, int argc, char *argv[])
757 {
758         if (argc != 1)
759                 return RESULT_SHOWUSAGE;
760         quit_handler(0, 0, 1, 0);
761         return RESULT_SUCCESS;
762 }
763 #endif
764
765 static int no_more_quit(int fd, int argc, char *argv[])
766 {
767         if (argc != 1)
768                 return RESULT_SHOWUSAGE;
769         ast_cli(fd, "The QUIT and EXIT commands may no longer be used to shutdown the PBX.\n"
770                     "Please use STOP NOW instead, if you wish to shutdown the PBX.\n");
771         return RESULT_SUCCESS;
772 }
773
774 static int handle_shutdown_now(int fd, int argc, char *argv[])
775 {
776         if (argc != 2)
777                 return RESULT_SHOWUSAGE;
778         quit_handler(0, 0 /* Not nice */, 1 /* safely */, 0 /* not restart */);
779         return RESULT_SUCCESS;
780 }
781
782 static int handle_shutdown_gracefully(int fd, int argc, char *argv[])
783 {
784         if (argc != 2)
785                 return RESULT_SHOWUSAGE;
786         quit_handler(0, 1 /* nicely */, 1 /* safely */, 0 /* no restart */);
787         return RESULT_SUCCESS;
788 }
789
790 static int handle_shutdown_when_convenient(int fd, int argc, char *argv[])
791 {
792         if (argc != 3)
793                 return RESULT_SHOWUSAGE;
794         quit_handler(0, 2 /* really nicely */, 1 /* safely */, 0 /* don't restart */);
795         return RESULT_SUCCESS;
796 }
797
798 static int handle_restart_now(int fd, int argc, char *argv[])
799 {
800         if (argc != 2)
801                 return RESULT_SHOWUSAGE;
802         quit_handler(0, 0 /* not nicely */, 1 /* safely */, 1 /* restart */);
803         return RESULT_SUCCESS;
804 }
805
806 static int handle_restart_gracefully(int fd, int argc, char *argv[])
807 {
808         if (argc != 2)
809                 return RESULT_SHOWUSAGE;
810         quit_handler(0, 1 /* nicely */, 1 /* safely */, 1 /* restart */);
811         return RESULT_SUCCESS;
812 }
813
814 static int handle_restart_when_convenient(int fd, int argc, char *argv[])
815 {
816         if (argc != 3)
817                 return RESULT_SHOWUSAGE;
818         quit_handler(0, 2 /* really nicely */, 1 /* safely */, 1 /* restart */);
819         return RESULT_SUCCESS;
820 }
821
822 static int handle_abort_halt(int fd, int argc, char *argv[])
823 {
824         if (argc != 2)
825                 return RESULT_SHOWUSAGE;
826         ast_cancel_shutdown();
827         shuttingdown = 0;
828         return RESULT_SUCCESS;
829 }
830
831 static int handle_bang(int fd, int argc, char *argv[])
832 {
833         return RESULT_SUCCESS;
834 }
835
836 #define ASTERISK_PROMPT "*CLI> "
837
838 #define ASTERISK_PROMPT2 "%s*CLI> "
839
840 static struct ast_cli_entry aborthalt = { { "abort", "halt", NULL }, handle_abort_halt, "Cancel a running halt", abort_halt_help };
841
842 static struct ast_cli_entry quit =      { { "quit", NULL }, no_more_quit, "Exit Asterisk", quit_help };
843 static struct ast_cli_entry astexit =   { { "exit", NULL }, no_more_quit, "Exit Asterisk", quit_help };
844
845 static struct ast_cli_entry astshutdownnow =    { { "stop", "now", NULL }, handle_shutdown_now, "Shut down Asterisk immediately", shutdown_now_help };
846 static struct ast_cli_entry astshutdowngracefully =     { { "stop", "gracefully", NULL }, handle_shutdown_gracefully, "Gracefully shut down Asterisk", shutdown_gracefully_help };
847 static struct ast_cli_entry astshutdownwhenconvenient =         { { "stop", "when","convenient", NULL }, handle_shutdown_when_convenient, "Shut down Asterisk at empty call volume", shutdown_when_convenient_help };
848 static struct ast_cli_entry astrestartnow =     { { "restart", "now", NULL }, handle_restart_now, "Restart Asterisk immediately", restart_now_help };
849 static struct ast_cli_entry astrestartgracefully =      { { "restart", "gracefully", NULL }, handle_restart_gracefully, "Restart Asterisk gracefully", restart_gracefully_help };
850 static struct ast_cli_entry astrestartwhenconvenient=   { { "restart", "when", "convenient", NULL }, handle_restart_when_convenient, "Restart Asterisk at empty call volume", restart_when_convenient_help };
851 static struct ast_cli_entry astbang = { { "!", NULL }, handle_bang, "Execute a shell command", bang_help };
852
853 static int ast_el_read_char(EditLine *el, char *cp)
854 {
855         int num_read=0;
856         int lastpos=0;
857         struct pollfd fds[2];
858         int res;
859         int max;
860         char buf[512];
861
862         for (;;) {
863                 max = 1;
864                 fds[0].fd = ast_consock;
865                 fds[0].events = POLLIN;
866                 if (!option_exec) {
867                         fds[1].fd = STDIN_FILENO;
868                         fds[1].events = POLLIN;
869                         max++;
870                 }
871                 res = poll(fds, max, -1);
872                 if (res < 0) {
873                         if (errno == EINTR)
874                                 continue;
875                         ast_log(LOG_ERROR, "poll failed: %s\n", strerror(errno));
876                         break;
877                 }
878
879                 if (!option_exec && fds[1].revents) {
880                         num_read = read(STDIN_FILENO, cp, 1);
881                         if (num_read < 1) {
882                                 break;
883                         } else 
884                                 return (num_read);
885                 }
886                 if (fds[0].revents) {
887                         res = read(ast_consock, buf, sizeof(buf) - 1);
888                         /* if the remote side disappears exit */
889                         if (res < 1) {
890                                 fprintf(stderr, "\nDisconnected from Asterisk server\n");
891                                 if (!option_reconnect) {
892                                         quit_handler(0, 0, 0, 0);
893                                 } else {
894                                         int tries;
895                                         int reconnects_per_second = 20;
896                                         fprintf(stderr, "Attempting to reconnect for 30 seconds\n");
897                                         for (tries=0;tries<30 * reconnects_per_second;tries++) {
898                                                 if (ast_tryconnect()) {
899                                                         fprintf(stderr, "Reconnect succeeded after %.3f seconds\n", 1.0 / reconnects_per_second * tries);
900                                                         printf(term_quit());
901                                                         WELCOME_MESSAGE;
902                                                         break;
903                                                 } else {
904                                                         usleep(1000000 / reconnects_per_second);
905                                                 }
906                                         }
907                                         if (tries >= 30) {
908                                                 fprintf(stderr, "Failed to reconnect for 30 seconds.  Quitting.\n");
909                                                 quit_handler(0, 0, 0, 0);
910                                         }
911                                 }
912                         }
913
914                         buf[res] = '\0';
915
916                         if (!option_exec && !lastpos)
917                                 write(STDOUT_FILENO, "\r", 1);
918                         write(STDOUT_FILENO, buf, res);
919                         if ((buf[res-1] == '\n') || (buf[res-2] == '\n')) {
920                                 *cp = CC_REFRESH;
921                                 return(1);
922                         } else {
923                                 lastpos = 1;
924                         }
925                 }
926         }
927
928         *cp = '\0';
929         return (0);
930 }
931
932 static char *cli_prompt(EditLine *el)
933 {
934         static char prompt[200];
935         char *pfmt;
936         int color_used=0;
937         char term_code[20];
938
939         if ((pfmt = getenv("ASTERISK_PROMPT"))) {
940                 char *t = pfmt, *p = prompt;
941                 memset(prompt, 0, sizeof(prompt));
942                 while (*t != '\0' && *p < sizeof(prompt)) {
943                         if (*t == '%') {
944                                 char hostname[256];
945                                 int i;
946                                 struct timeval tv;
947                                 struct tm tm;
948 #ifdef linux
949                                 FILE *LOADAVG;
950 #endif
951                                 int fgcolor = COLOR_WHITE, bgcolor = COLOR_BLACK;
952
953                                 t++;
954                                 switch (*t) {
955                                         case 'C': /* color */
956                                                 t++;
957                                                 if (sscanf(t, "%d;%d%n", &fgcolor, &bgcolor, &i) == 2) {
958                                                         strncat(p, term_color_code(term_code, fgcolor, bgcolor, sizeof(term_code)),sizeof(prompt) - strlen(prompt) - 1);
959                                                         t += i - 1;
960                                                 } else if (sscanf(t, "%d%n", &fgcolor, &i) == 1) {
961                                                         strncat(p, term_color_code(term_code, fgcolor, 0, sizeof(term_code)),sizeof(prompt) - strlen(prompt) - 1);
962                                                         t += i - 1;
963                                                 }
964
965                                                 /* If the color has been reset correctly, then there's no need to reset it later */
966                                                 if ((fgcolor == COLOR_WHITE) && (bgcolor == COLOR_BLACK)) {
967                                                         color_used = 0;
968                                                 } else {
969                                                         color_used = 1;
970                                                 }
971                                                 break;
972                                         case 'd': /* date */
973                                                 memset(&tm, 0, sizeof(struct tm));
974                                                 gettimeofday(&tv, NULL);
975                                                 if (localtime_r(&(tv.tv_sec), &tm)) {
976                                                         strftime(p, sizeof(prompt) - strlen(prompt), "%Y-%m-%d", &tm);
977                                                 }
978                                                 break;
979                                         case 'h': /* hostname */
980                                                 if (!gethostname(hostname, sizeof(hostname) - 1)) {
981                                                         strncat(p, hostname, sizeof(prompt) - strlen(prompt) - 1);
982                                                 } else {
983                                                         strncat(p, "localhost", sizeof(prompt) - strlen(prompt) - 1);
984                                                 }
985                                                 break;
986                                         case 'H': /* short hostname */
987                                                 if (!gethostname(hostname, sizeof(hostname) - 1)) {
988                                                         for (i=0;i<sizeof(hostname);i++) {
989                                                                 if (hostname[i] == '.') {
990                                                                         hostname[i] = '\0';
991                                                                         break;
992                                                                 }
993                                                         }
994                                                         strncat(p, hostname, sizeof(prompt) - strlen(prompt) - 1);
995                                                 } else {
996                                                         strncat(p, "localhost", sizeof(prompt) - strlen(prompt) - 1);
997                                                 }
998                                                 break;
999 #ifdef linux
1000                                         case 'l': /* load avg */
1001                                                 t++;
1002                                                 if ((LOADAVG = fopen("/proc/loadavg", "r"))) {
1003                                                         float avg1, avg2, avg3;
1004                                                         int actproc, totproc, npid, which;
1005                                                         fscanf(LOADAVG, "%f %f %f %d/%d %d",
1006                                                                 &avg1, &avg2, &avg3, &actproc, &totproc, &npid);
1007                                                         if (sscanf(t, "%d", &which) == 1) {
1008                                                                 switch (which) {
1009                                                                         case 1:
1010                                                                                 snprintf(p, sizeof(prompt) - strlen(prompt), "%.2f", avg1);
1011                                                                                 break;
1012                                                                         case 2:
1013                                                                                 snprintf(p, sizeof(prompt) - strlen(prompt), "%.2f", avg2);
1014                                                                                 break;
1015                                                                         case 3:
1016                                                                                 snprintf(p, sizeof(prompt) - strlen(prompt), "%.2f", avg3);
1017                                                                                 break;
1018                                                                         case 4:
1019                                                                                 snprintf(p, sizeof(prompt) - strlen(prompt), "%d/%d", actproc, totproc);
1020                                                                                 break;
1021                                                                         case 5:
1022                                                                                 snprintf(p, sizeof(prompt) - strlen(prompt), "%d", npid);
1023                                                                                 break;
1024                                                                 }
1025                                                         }
1026                                                 }
1027                                                 break;
1028 #endif
1029                                         case 't': /* time */
1030                                                 memset(&tm, 0, sizeof(struct tm));
1031                                                 gettimeofday(&tv, NULL);
1032                                                 if (localtime_r(&(tv.tv_sec), &tm)) {
1033                                                         strftime(p, sizeof(prompt) - strlen(prompt), "%H:%M:%S", &tm);
1034                                                 }
1035                                                 break;
1036                                         case '#': /* process console or remote? */
1037                                                 if (! option_remote) {
1038                                                         strncat(p, "#", sizeof(prompt) - strlen(prompt) - 1);
1039                                                 } else {
1040                                                         strncat(p, ">", sizeof(prompt) - strlen(prompt) - 1);
1041                                                 }
1042                                                 break;
1043                                         case '%': /* literal % */
1044                                                 strncat(p, "%", sizeof(prompt) - strlen(prompt) - 1);
1045                                                 break;
1046                                         case '\0': /* % is last character - prevent bug */
1047                                                 t--;
1048                                                 break;
1049                                 }
1050                                 while (*p != '\0') {
1051                                         p++;
1052                                 }
1053                                 t++;
1054                         } else {
1055                                 *p = *t;
1056                                 p++;
1057                                 t++;
1058                         }
1059                 }
1060                 if (color_used) {
1061                         /* Force colors back to normal at end */
1062                         term_color_code(term_code, COLOR_WHITE, COLOR_BLACK, sizeof(term_code));
1063                         if (strlen(term_code) > sizeof(prompt) - strlen(prompt)) {
1064                                 strncat(prompt + sizeof(prompt) - strlen(term_code) - 1, term_code, strlen(term_code));
1065                         } else {
1066                                 strncat(p, term_code, sizeof(term_code));
1067                         }
1068                 }
1069         } else if (remotehostname)
1070                 snprintf(prompt, sizeof(prompt), ASTERISK_PROMPT2, remotehostname);
1071         else
1072                 snprintf(prompt, sizeof(prompt), ASTERISK_PROMPT);
1073
1074         return(prompt); 
1075 }
1076
1077 static char **ast_el_strtoarr(char *buf)
1078 {
1079         char **match_list = NULL, *retstr;
1080         size_t match_list_len;
1081         int matches = 0;
1082
1083         match_list_len = 1;
1084         while ( (retstr = strsep(&buf, " ")) != NULL) {
1085
1086                 if (!strcmp(retstr, AST_CLI_COMPLETE_EOF))
1087                         break;
1088                 if (matches + 1 >= match_list_len) {
1089                         match_list_len <<= 1;
1090                         match_list = realloc(match_list, match_list_len * sizeof(char *));
1091                 }
1092
1093                 match_list[matches++] = strdup(retstr);
1094         }
1095
1096         if (!match_list)
1097                 return (char **) NULL;
1098
1099         if (matches>= match_list_len)
1100                 match_list = realloc(match_list, (match_list_len + 1) * sizeof(char *));
1101
1102         match_list[matches] = (char *) NULL;
1103
1104         return match_list;
1105 }
1106
1107 static int ast_el_sort_compare(const void *i1, const void *i2)
1108 {
1109         char *s1, *s2;
1110
1111         s1 = ((char **)i1)[0];
1112         s2 = ((char **)i2)[0];
1113
1114         return strcasecmp(s1, s2);
1115 }
1116
1117 static int ast_cli_display_match_list(char **matches, int len, int max)
1118 {
1119         int i, idx, limit, count;
1120         int screenwidth = 0;
1121         int numoutput = 0, numoutputline = 0;
1122
1123         screenwidth = ast_get_termcols(STDOUT_FILENO);
1124
1125         /* find out how many entries can be put on one line, with two spaces between strings */
1126         limit = screenwidth / (max + 2);
1127         if (limit == 0)
1128                 limit = 1;
1129
1130         /* how many lines of output */
1131         count = len / limit;
1132         if (count * limit < len)
1133                 count++;
1134
1135         idx = 1;
1136
1137         qsort(&matches[0], (size_t)(len + 1), sizeof(char *), ast_el_sort_compare);
1138
1139         for (; count > 0; count--) {
1140                 numoutputline = 0;
1141                 for (i=0; i < limit && matches[idx]; i++, idx++) {
1142
1143                         /* Don't print dupes */
1144                         if ( (matches[idx+1] != NULL && strcmp(matches[idx], matches[idx+1]) == 0 ) ) {
1145                                 i--;
1146                                 free(matches[idx]);
1147                                 matches[idx] = NULL;
1148                                 continue;
1149                         }
1150
1151                         numoutput++;  numoutputline++;
1152                         fprintf(stdout, "%-*s  ", max, matches[idx]);
1153                         free(matches[idx]);
1154                         matches[idx] = NULL;
1155                 }
1156                 if (numoutputline > 0)
1157                         fprintf(stdout, "\n");
1158         }
1159
1160         return numoutput;
1161 }
1162
1163
1164 static char *cli_complete(EditLine *el, int ch)
1165 {
1166         int len=0;
1167         char *ptr;
1168         int nummatches = 0;
1169         char **matches;
1170         int retval = CC_ERROR;
1171         char buf[2048];
1172         int res;
1173
1174         LineInfo *lf = (LineInfo *)el_line(el);
1175
1176         *(char *)lf->cursor = '\0';
1177         ptr = (char *)lf->cursor;
1178         if (ptr) {
1179                 while (ptr > lf->buffer) {
1180                         if (isspace(*ptr)) {
1181                                 ptr++;
1182                                 break;
1183                         }
1184                         ptr--;
1185                 }
1186         }
1187
1188         len = lf->cursor - ptr;
1189
1190         if (option_remote) {
1191                 snprintf(buf, sizeof(buf),"_COMMAND NUMMATCHES \"%s\" \"%s\"", lf->buffer, ptr); 
1192                 fdprint(ast_consock, buf);
1193                 res = read(ast_consock, buf, sizeof(buf));
1194                 buf[res] = '\0';
1195                 nummatches = atoi(buf);
1196
1197                 if (nummatches > 0) {
1198                         char *mbuf;
1199                         int mlen = 0, maxmbuf = 2048;
1200                         /* Start with a 2048 byte buffer */
1201                         mbuf = malloc(maxmbuf);
1202                         if (!mbuf)
1203                                 return (char *)(CC_ERROR);
1204                         snprintf(buf, sizeof(buf),"_COMMAND MATCHESARRAY \"%s\" \"%s\"", lf->buffer, ptr); 
1205                         fdprint(ast_consock, buf);
1206                         res = 0;
1207                         mbuf[0] = '\0';
1208                         while (!strstr(mbuf, AST_CLI_COMPLETE_EOF) && res != -1) {
1209                                 if (mlen + 1024 > maxmbuf) {
1210                                         /* Every step increment buffer 1024 bytes */
1211                                         maxmbuf += 1024;
1212                                         mbuf = realloc(mbuf, maxmbuf);
1213                                         if (!mbuf)
1214                                                 return (char *)(CC_ERROR);
1215                                 }
1216                                 /* Only read 1024 bytes at a time */
1217                                 res = read(ast_consock, mbuf + mlen, 1024);
1218                                 if (res > 0)
1219                                         mlen += res;
1220                         }
1221                         mbuf[mlen] = '\0';
1222
1223                         matches = ast_el_strtoarr(mbuf);
1224                         free(mbuf);
1225                 } else
1226                         matches = (char **) NULL;
1227
1228
1229         }  else {
1230
1231                 nummatches = ast_cli_generatornummatches((char *)lf->buffer,ptr);
1232                 matches = ast_cli_completion_matches((char *)lf->buffer,ptr);
1233         }
1234
1235         if (matches) {
1236                 int i;
1237                 int matches_num, maxlen, match_len;
1238
1239                 if (matches[0][0] != '\0') {
1240                         el_deletestr(el, (int) len);
1241                         el_insertstr(el, matches[0]);
1242                         retval = CC_REFRESH;
1243                 }
1244
1245                 if (nummatches == 1) {
1246                         /* Found an exact match */
1247                         el_insertstr(el, " ");
1248                         retval = CC_REFRESH;
1249                 } else {
1250                         /* Must be more than one match */
1251                         for (i=1, maxlen=0; matches[i]; i++) {
1252                                 match_len = strlen(matches[i]);
1253                                 if (match_len > maxlen)
1254                                         maxlen = match_len;
1255                         }
1256                         matches_num = i - 1;
1257                         if (matches_num >1) {
1258                                 fprintf(stdout, "\n");
1259                                 ast_cli_display_match_list(matches, nummatches, maxlen);
1260                                 retval = CC_REDISPLAY;
1261                         } else { 
1262                                 el_insertstr(el," ");
1263                                 retval = CC_REFRESH;
1264                         }
1265                 }
1266         free(matches);
1267         }
1268
1269         return (char *)(long)retval;
1270 }
1271
1272 static int ast_el_initialize(void)
1273 {
1274         HistEvent ev;
1275         char *editor = getenv("AST_EDITOR");
1276
1277         if (el != NULL)
1278                 el_end(el);
1279         if (el_hist != NULL)
1280                 history_end(el_hist);
1281
1282         el = el_init("asterisk", stdin, stdout, stderr);
1283         el_set(el, EL_PROMPT, cli_prompt);
1284
1285         el_set(el, EL_EDITMODE, 1);             
1286         el_set(el, EL_EDITOR, editor ? editor : "emacs");               
1287         el_hist = history_init();
1288         if (!el || !el_hist)
1289                 return -1;
1290
1291         /* setup history with 100 entries */
1292         history(el_hist, &ev, H_SETSIZE, 100);
1293
1294         el_set(el, EL_HIST, history, el_hist);
1295
1296         el_set(el, EL_ADDFN, "ed-complete", "Complete argument", cli_complete);
1297         /* Bind <tab> to command completion */
1298         el_set(el, EL_BIND, "^I", "ed-complete", NULL);
1299         /* Bind ? to command completion */
1300         el_set(el, EL_BIND, "?", "ed-complete", NULL);
1301         /* Bind ^D to redisplay */
1302         el_set(el, EL_BIND, "^D", "ed-redisplay", NULL);
1303
1304         return 0;
1305 }
1306
1307 static int ast_el_add_history(char *buf)
1308 {
1309         HistEvent ev;
1310
1311         if (el_hist == NULL || el == NULL)
1312                 ast_el_initialize();
1313         if (strlen(buf) > 256)
1314                 return 0;
1315         return (history(el_hist, &ev, H_ENTER, buf));
1316 }
1317
1318 static int ast_el_write_history(char *filename)
1319 {
1320         HistEvent ev;
1321
1322         if (el_hist == NULL || el == NULL)
1323                 ast_el_initialize();
1324
1325         return (history(el_hist, &ev, H_SAVE, filename));
1326 }
1327
1328 static int ast_el_read_history(char *filename)
1329 {
1330         char buf[256];
1331         FILE *f;
1332         int ret = -1;
1333
1334         if (el_hist == NULL || el == NULL)
1335                 ast_el_initialize();
1336
1337         if ((f = fopen(filename, "r")) == NULL)
1338                 return ret;
1339
1340         while (!feof(f)) {
1341                 fgets(buf, sizeof(buf), f);
1342                 if (!strcmp(buf, "_HiStOrY_V2_\n"))
1343                         continue;
1344                 if ((ret = ast_el_add_history(buf)) == -1)
1345                         break;
1346         }
1347         fclose(f);
1348
1349         return ret;
1350 }
1351
1352 static void ast_remotecontrol(char * data)
1353 {
1354         char buf[80];
1355         int res;
1356         char filename[80] = "";
1357         char *hostname;
1358         char *cpid;
1359         char *version;
1360         int pid;
1361         char tmp[80];
1362         char *stringp=NULL;
1363
1364         char *ebuf;
1365         int num = 0;
1366
1367         read(ast_consock, buf, sizeof(buf));
1368         if (data)
1369                 write(ast_consock, data, strlen(data) + 1);
1370         stringp=buf;
1371         hostname = strsep(&stringp, "/");
1372         cpid = strsep(&stringp, "/");
1373         version = strsep(&stringp, "\n");
1374         if (!version)
1375                 version = "<Version Unknown>";
1376         stringp=hostname;
1377         strsep(&stringp, ".");
1378         if (cpid)
1379                 pid = atoi(cpid);
1380         else
1381                 pid = -1;
1382         snprintf(tmp, sizeof(tmp), "set verbose atleast %d", option_verbose);
1383         fdprint(ast_consock, tmp);
1384         ast_verbose("Connected to Asterisk %s currently running on %s (pid = %d)\n", version, hostname, pid);
1385         remotehostname = hostname;
1386         if (getenv("HOME")) 
1387                 snprintf(filename, sizeof(filename), "%s/.asterisk_history", getenv("HOME"));
1388         if (el_hist == NULL || el == NULL)
1389                 ast_el_initialize();
1390
1391         el_set(el, EL_GETCFN, ast_el_read_char);
1392
1393         if (!ast_strlen_zero(filename))
1394                 ast_el_read_history(filename);
1395
1396         ast_cli_register(&quit);
1397         ast_cli_register(&astexit);
1398 #if 0
1399         ast_cli_register(&astshutdown);
1400 #endif  
1401         if (option_exec && data) {  /* hack to print output then exit if asterisk -rx is used */
1402                 char tempchar;
1403                 ast_el_read_char(el, &tempchar);
1404                 return;
1405         }
1406         for(;;) {
1407                 ebuf = (char *)el_gets(el, &num);
1408
1409                 if (ebuf && !ast_strlen_zero(ebuf)) {
1410                         if (ebuf[strlen(ebuf)-1] == '\n')
1411                                 ebuf[strlen(ebuf)-1] = '\0';
1412                         if (!remoteconsolehandler(ebuf)) {
1413                                 res = write(ast_consock, ebuf, strlen(ebuf) + 1);
1414                                 if (res < 1) {
1415                                         ast_log(LOG_WARNING, "Unable to write: %s\n", strerror(errno));
1416                                         break;
1417                                 }
1418                         }
1419                 }
1420         }
1421         printf("\nDisconnected from Asterisk server\n");
1422 }
1423
1424 static int show_version(void)
1425 {
1426         printf("Asterisk " ASTERISK_VERSION "\n");
1427         return 0;
1428 }
1429
1430 static int show_cli_help(void) {
1431         printf("Asterisk " ASTERISK_VERSION ", Copyright (C) 2000-2004, Digium.\n");
1432         printf("Usage: asterisk [OPTIONS]\n");
1433         printf("Valid Options:\n");
1434         printf("   -V              Display version number and exit\n");
1435         printf("   -C <configfile> Use an alternate configuration file\n");
1436         printf("   -G <group>      Run as a group other than the caller\n");
1437         printf("   -U <user>       Run as a user other than the caller\n");
1438         printf("   -c              Provide console CLI\n");
1439         printf("   -d              Enable extra debugging\n");
1440         printf("   -f              Do not fork\n");
1441         printf("   -g              Dump core in case of a crash\n");
1442         printf("   -h              This help screen\n");
1443         printf("   -i              Initializie crypto keys at startup\n");
1444         printf("   -n              Disable console colorization\n");
1445         printf("   -p              Run as pseudo-realtime thread\n");
1446         printf("   -q              Quiet mode (supress output)\n");
1447         printf("   -r              Connect to Asterisk on this machine\n");
1448         printf("   -R              Connect to Asterisk, and attempt to reconnect if disconnected\n");
1449         printf("   -v              Increase verbosity (multiple v's = more verbose)\n");
1450         printf("   -x <cmd>        Execute command <cmd> (only valid with -r)\n");
1451         printf("\n");
1452         return 0;
1453 }
1454
1455 static void ast_readconfig(void) {
1456         struct ast_config *cfg;
1457         struct ast_variable *v;
1458         char *config = ASTCONFPATH;
1459
1460         if (option_overrideconfig == 1) {
1461             cfg = ast_load((char *)ast_config_AST_CONFIG_FILE);
1462         } else {
1463             cfg = ast_load(config);
1464         }
1465
1466         /* init with buildtime config */
1467         strncpy((char *)ast_config_AST_CONFIG_DIR,AST_CONFIG_DIR,sizeof(ast_config_AST_CONFIG_DIR)-1);
1468         strncpy((char *)ast_config_AST_SPOOL_DIR,AST_SPOOL_DIR,sizeof(ast_config_AST_SPOOL_DIR)-1);
1469         strncpy((char *)ast_config_AST_MODULE_DIR,AST_MODULE_DIR,sizeof(ast_config_AST_VAR_DIR)-1);
1470         strncpy((char *)ast_config_AST_VAR_DIR,AST_VAR_DIR,sizeof(ast_config_AST_VAR_DIR)-1);
1471         strncpy((char *)ast_config_AST_LOG_DIR,AST_LOG_DIR,sizeof(ast_config_AST_LOG_DIR)-1);
1472         strncpy((char *)ast_config_AST_AGI_DIR,AST_AGI_DIR,sizeof(ast_config_AST_AGI_DIR)-1);
1473         strncpy((char *)ast_config_AST_DB,AST_DB,sizeof(ast_config_AST_DB)-1);
1474         strncpy((char *)ast_config_AST_KEY_DIR,AST_KEY_DIR,sizeof(ast_config_AST_KEY_DIR)-1);
1475         strncpy((char *)ast_config_AST_PID,AST_PID,sizeof(ast_config_AST_PID)-1);
1476         strncpy((char *)ast_config_AST_SOCKET,AST_SOCKET,sizeof(ast_config_AST_SOCKET)-1);
1477         strncpy((char *)ast_config_AST_RUN_DIR,AST_RUN_DIR,sizeof(ast_config_AST_RUN_DIR)-1);
1478         
1479         /* no asterisk.conf? no problem, use buildtime config! */
1480         if (!cfg) {
1481             return;
1482         }
1483         v = ast_variable_browse(cfg, "directories");
1484         while(v) {
1485                 if (!strcasecmp(v->name, "astetcdir")) {
1486                     strncpy((char *)ast_config_AST_CONFIG_DIR,v->value,sizeof(ast_config_AST_CONFIG_DIR)-1);
1487                 } else if (!strcasecmp(v->name, "astspooldir")) {
1488                     strncpy((char *)ast_config_AST_SPOOL_DIR,v->value,sizeof(ast_config_AST_SPOOL_DIR)-1);
1489                 } else if (!strcasecmp(v->name, "astvarlibdir")) {
1490                     strncpy((char *)ast_config_AST_VAR_DIR,v->value,sizeof(ast_config_AST_VAR_DIR)-1);
1491                     snprintf((char *)ast_config_AST_DB,sizeof(ast_config_AST_DB),"%s/%s",v->value,"astdb");    
1492                 } else if (!strcasecmp(v->name, "astlogdir")) {
1493                     strncpy((char *)ast_config_AST_LOG_DIR,v->value,sizeof(ast_config_AST_LOG_DIR)-1);
1494                 } else if (!strcasecmp(v->name, "astagidir")) {
1495                     strncpy((char *)ast_config_AST_AGI_DIR,v->value,sizeof(ast_config_AST_AGI_DIR)-1);
1496                 } else if (!strcasecmp(v->name, "astrundir")) {
1497                     snprintf((char *)ast_config_AST_PID,sizeof(ast_config_AST_PID),"%s/%s",v->value,"asterisk.pid");    
1498                     snprintf((char *)ast_config_AST_SOCKET,sizeof(ast_config_AST_SOCKET),"%s/%s",v->value,"asterisk.ctl");    
1499                     strncpy((char *)ast_config_AST_RUN_DIR,v->value,sizeof(ast_config_AST_RUN_DIR)-1);
1500                 } else if (!strcasecmp(v->name, "astmoddir")) {
1501                     strncpy((char *)ast_config_AST_MODULE_DIR,v->value,sizeof(ast_config_AST_MODULE_DIR)-1);
1502                 }
1503                 v = v->next;
1504         }
1505         ast_destroy(cfg);
1506 }
1507
1508 int main(int argc, char *argv[])
1509 {
1510         int c;
1511         char filename[80] = "";
1512         char hostname[256];
1513         char tmp[80];
1514         char * xarg = NULL;
1515         int x;
1516         FILE *f;
1517         sigset_t sigs;
1518         int num;
1519         char *buf;
1520         char *runuser=NULL, *rungroup=NULL;
1521
1522         /* Remember original args for restart */
1523         if (argc > sizeof(_argv) / sizeof(_argv[0]) - 1) {
1524                 fprintf(stderr, "Truncating argument size to %d\n", (int)(sizeof(_argv) / sizeof(_argv[0])) - 1);
1525                 argc = sizeof(_argv) / sizeof(_argv[0]) - 1;
1526         }
1527         for (x=0;x<argc;x++)
1528                 _argv[x] = argv[x];
1529         _argv[x] = NULL;
1530
1531         /* if the progname is rasterisk consider it a remote console */
1532         if ( argv[0] && (strstr(argv[0], "rasterisk")) != NULL)  {
1533                 option_remote++;
1534                 option_nofork++;
1535         }
1536         if (gethostname(hostname, sizeof(hostname)))
1537                 strncpy(hostname, "<Unknown>", sizeof(hostname)-1);
1538         ast_mainpid = getpid();
1539         ast_ulaw_init();
1540         ast_alaw_init();
1541         callerid_init();
1542         ast_utils_init();
1543         tdd_init();
1544         if (getenv("HOME")) 
1545                 snprintf(filename, sizeof(filename), "%s/.asterisk_history", getenv("HOME"));
1546         /* Check if we're root */
1547         /*
1548         if (geteuid()) {
1549                 ast_log(LOG_ERROR, "Must be run as root\n");
1550                 exit(1);
1551         }
1552         */
1553         /* Check for options */
1554         while((c=getopt(argc, argv, "hfdvVqprRgcinx:U:G:C:")) != -1) {
1555                 switch(c) {
1556                 case 'd':
1557                         option_debug++;
1558                         option_nofork++;
1559                         break;
1560                 case 'c':
1561                         option_console++;
1562                         option_nofork++;
1563                         break;
1564                 case 'f':
1565                         option_nofork++;
1566                         break;
1567                 case 'n':
1568                         option_nocolor++;
1569                         break;
1570                 case 'r':
1571                         option_remote++;
1572                         option_nofork++;
1573                         break;
1574                 case 'R':
1575                         option_remote++;
1576                         option_nofork++;
1577                         option_reconnect++;
1578                         break;
1579                 case 'p':
1580                         option_highpriority++;
1581                         break;
1582                 case 'v':
1583                         option_verbose++;
1584                         option_nofork++;
1585                         break;
1586                 case 'q':
1587                         option_quiet++;
1588                         break;
1589                 case 'x':
1590                         option_exec++;
1591                         xarg = optarg;
1592                         break;
1593                 case 'C':
1594                         strncpy((char *)ast_config_AST_CONFIG_FILE,optarg,sizeof(ast_config_AST_CONFIG_FILE) - 1);
1595                         option_overrideconfig++;
1596                         break;
1597                 case 'i':
1598                         option_initcrypto++;
1599                         break;
1600                 case'g':
1601                         option_dumpcore++;
1602                         break;
1603                 case 'h':
1604                         show_cli_help();
1605                         exit(0);
1606                 case 'V':
1607                         show_version();
1608                         exit(0);
1609                 case 'U':
1610                         runuser = optarg;
1611                         break;
1612                 case 'G':
1613                         rungroup = optarg;
1614                         break;
1615                 case '?':
1616                         exit(1);
1617                 }
1618         }
1619
1620         if (option_dumpcore) {
1621                 struct rlimit l;
1622                 memset(&l, 0, sizeof(l));
1623                 l.rlim_cur = RLIM_INFINITY;
1624                 l.rlim_max = RLIM_INFINITY;
1625                 if (setrlimit(RLIMIT_CORE, &l)) {
1626                         ast_log(LOG_WARNING, "Unable to disable core size resource limit: %s\n", strerror(errno));
1627                 }
1628         }
1629
1630         if (rungroup) {
1631                 struct group *gr;
1632                 gr = getgrnam(rungroup);
1633                 if (!gr) {
1634                         ast_log(LOG_WARNING, "No such group '%s'!\n", rungroup);
1635                         exit(1);
1636                 }
1637                 if (setgid(gr->gr_gid)) {
1638                         ast_log(LOG_WARNING, "Unable to setgid to %d (%s)\n", gr->gr_gid, rungroup);
1639                         exit(1);
1640                 }
1641                 if (option_verbose)
1642                         ast_verbose("Running as group '%s'\n", rungroup);
1643         }
1644
1645         if (set_priority(option_highpriority)) {
1646                 exit(1);
1647         }
1648         if (runuser) {
1649                 struct passwd *pw;
1650                 pw = getpwnam(runuser);
1651                 if (!pw) {
1652                         ast_log(LOG_WARNING, "No such user '%s'!\n", runuser);
1653                         exit(1);
1654                 }
1655                 if (setuid(pw->pw_uid)) {
1656                         ast_log(LOG_WARNING, "Unable to setuid to %d (%s)\n", pw->pw_uid, runuser);
1657                         exit(1);
1658                 }
1659                 if (option_verbose)
1660                         ast_verbose("Running as user '%s'\n", runuser);
1661         }
1662
1663         term_init();
1664         printf(term_end());
1665         fflush(stdout);
1666
1667         /* Test recursive mutex locking. */
1668         if (test_for_thread_safety())
1669                 ast_verbose("Warning! Asterisk is not thread safe.\n");
1670
1671         if (option_console && !option_verbose) 
1672                 ast_verbose("[ Reading Master Configuration ]");
1673         ast_readconfig();
1674
1675         if (option_console && !option_verbose) 
1676                 ast_verbose("[ Initializing Custom Configuration Options]");
1677         /* custom config setup */
1678         register_config_cli();
1679         read_ast_cust_config();
1680         
1681
1682         if (option_console) {
1683                 if (el_hist == NULL || el == NULL)
1684                         ast_el_initialize();
1685
1686                 if (!ast_strlen_zero(filename))
1687                         ast_el_read_history(filename);
1688         }
1689
1690         if (ast_tryconnect()) {
1691                 /* One is already running */
1692                 if (option_remote) {
1693                         if (option_exec) {
1694                                 ast_remotecontrol(xarg);
1695                                 quit_handler(0, 0, 0, 0);
1696                                 exit(0);
1697                         }
1698                         printf(term_quit());
1699                         ast_register_verbose(console_verboser);
1700                         WELCOME_MESSAGE;
1701                         ast_remotecontrol(NULL);
1702                         quit_handler(0, 0, 0, 0);
1703                         exit(0);
1704                 } else {
1705                         ast_log(LOG_ERROR, "Asterisk already running on %s.  Use 'asterisk -r' to connect.\n", (char *)ast_config_AST_SOCKET);
1706                         printf(term_quit());
1707                         exit(1);
1708                 }
1709         } else if (option_remote || option_exec) {
1710                 ast_log(LOG_ERROR, "Unable to connect to remote asterisk\n");
1711                 printf(term_quit());
1712                 exit(1);
1713         }
1714         /* Blindly write pid file since we couldn't connect */
1715         unlink((char *)ast_config_AST_PID);
1716         f = fopen((char *)ast_config_AST_PID, "w");
1717         if (f) {
1718                 fprintf(f, "%d\n", getpid());
1719                 fclose(f);
1720         } else
1721                 ast_log(LOG_WARNING, "Unable to open pid file '%s': %s\n", (char *)ast_config_AST_PID, strerror(errno));
1722
1723         if (!option_verbose && !option_debug && !option_nofork && !option_console) {
1724                 daemon(0,0);
1725                 /* Blindly re-write pid file since we are forking */
1726                 unlink((char *)ast_config_AST_PID);
1727                 f = fopen((char *)ast_config_AST_PID, "w");
1728                 if (f) {
1729                         fprintf(f, "%d\n", getpid());
1730                         fclose(f);
1731                 } else
1732                         ast_log(LOG_WARNING, "Unable to open pid file '%s': %s\n", (char *)ast_config_AST_PID, strerror(errno));
1733         }
1734
1735         ast_makesocket();
1736         sigemptyset(&sigs);
1737         sigaddset(&sigs, SIGHUP);
1738         sigaddset(&sigs, SIGTERM);
1739         sigaddset(&sigs, SIGINT);
1740         sigaddset(&sigs, SIGPIPE);
1741         sigaddset(&sigs, SIGWINCH);
1742         pthread_sigmask(SIG_BLOCK, &sigs, NULL);
1743         if (option_console || option_verbose || option_remote)
1744                 ast_register_verbose(console_verboser);
1745         /* Print a welcome message if desired */
1746         if (option_verbose || option_console) {
1747                 WELCOME_MESSAGE;
1748         }
1749         if (option_console && !option_verbose) 
1750                 ast_verbose("[ Booting...");
1751
1752         signal(SIGURG, urg_handler);
1753         signal(SIGINT, __quit_handler);
1754         signal(SIGTERM, __quit_handler);
1755         signal(SIGHUP, hup_handler);
1756         signal(SIGCHLD, child_handler);
1757         signal(SIGPIPE, SIG_IGN);
1758
1759         if (init_logger()) {
1760                 printf(term_quit());
1761                 exit(1);
1762         }
1763         if (init_manager()) {
1764                 printf(term_quit());
1765                 exit(1);
1766         }
1767         ast_rtp_init();
1768         if (ast_image_init()) {
1769                 printf(term_quit());
1770                 exit(1);
1771         }
1772         if (ast_file_init()) {
1773                 printf(term_quit());
1774                 exit(1);
1775         }
1776         if (load_pbx()) {
1777                 printf(term_quit());
1778                 exit(1);
1779         }
1780         if (load_modules()) {
1781                 printf(term_quit());
1782                 exit(1);
1783         }
1784         if (init_framer()) {
1785                 printf(term_quit());
1786                 exit(1);
1787         }
1788         if (astdb_init()) {
1789                 printf(term_quit());
1790                 exit(1);
1791         }
1792         if (ast_enum_init()) {
1793                 printf(term_quit());
1794                 exit(1);
1795         }
1796         /* reload logger in case a custom config handler binded to logger.conf*/
1797         reload_logger(0);
1798
1799         /* We might have the option of showing a console, but for now just
1800            do nothing... */
1801         if (option_console && !option_verbose)
1802                 ast_verbose(" ]\n");
1803         if (option_verbose || option_console)
1804                 ast_verbose(term_color(tmp, "Asterisk Ready.\n", COLOR_BRWHITE, COLOR_BLACK, sizeof(tmp)));
1805         if (option_nofork)
1806                 consolethread = pthread_self();
1807         fully_booted = 1;
1808         pthread_sigmask(SIG_UNBLOCK, &sigs, NULL);
1809 #ifdef __AST_DEBUG_MALLOC
1810         __ast_mm_init();
1811 #endif  
1812         time(&ast_startuptime);
1813         ast_cli_register(&astshutdownnow);
1814         ast_cli_register(&astshutdowngracefully);
1815         ast_cli_register(&astrestartnow);
1816         ast_cli_register(&astrestartgracefully);
1817         ast_cli_register(&astrestartwhenconvenient);
1818         ast_cli_register(&astshutdownwhenconvenient);
1819         ast_cli_register(&aborthalt);
1820         ast_cli_register(&astbang);
1821         if (option_console) {
1822                 /* Console stuff now... */
1823                 /* Register our quit function */
1824                 char title[256];
1825                 set_icon("Asterisk");
1826                 snprintf(title, sizeof(title), "Asterisk Console on '%s' (pid %d)", hostname, ast_mainpid);
1827                 set_title(title);
1828             ast_cli_register(&quit);
1829             ast_cli_register(&astexit);
1830
1831                 for (;;) {
1832                         buf = (char *)el_gets(el, &num);
1833                         if (buf) {
1834                                 if (buf[strlen(buf)-1] == '\n')
1835                                         buf[strlen(buf)-1] = '\0';
1836
1837                                 consolehandler((char *)buf);
1838                         } else {
1839                                 if (option_remote)
1840                                         ast_cli(STDOUT_FILENO, "\nUse EXIT or QUIT to exit the asterisk console\n");
1841                         }
1842                 }
1843
1844         } else {
1845                 /* Do nothing */
1846                 for(;;) 
1847                         poll(NULL,0, -1);
1848         }
1849         return 0;
1850 }