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