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