do parse defaultlanguage from asterisk.conf
[asterisk/asterisk.git] / main / asterisk.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2010, 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 -- The Open Source Telephony Project
23  *
24  * \par Developer Documentation for Asterisk
25  *
26  * This is the main developer documentation for Asterisk. It is 
27  * generated by running "make progdocs" from the Asterisk source tree.  
28  *
29  * In addition to the information available on the Asterisk source code, 
30  * please see the appendices for information on coding guidelines, 
31  * release management, commit policies, and more.
32  *
33  * \arg \ref AsteriskArchitecture
34  *
35  * \par Additional documentation
36  * \arg \ref Licensing
37  * \arg \ref DevDoc 
38  * \arg \ref ConfigFiles
39  *
40  * \section copyright Copyright and Author
41  *
42  * Copyright (C) 1999 - 2009, Digium, Inc.
43  * Asterisk is a <a href="http://www.digium.com/en/company/view-policy.php?id=Trademark-Policy">registered trademark</a>
44  * of <a href="http://www.digium.com">Digium, Inc</a>.
45  *
46  * \author Mark Spencer <markster@digium.com>
47  * Also see \ref AstCREDITS
48  *
49  * See http://www.asterisk.org for more information about
50  * the Asterisk project. Please do not directly contact
51  * any of the maintainers of this project for assistance;
52  * the project provides a web site, mailing lists, and IRC
53  * channels for your use.
54  */
55
56 /*! \file
57   \brief Top level source file for Asterisk  - the Open Source PBX. Implementation
58   of PBX core functions and CLI interface.
59   
60  */
61
62 #include "asterisk.h"
63
64 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
65
66 #include "asterisk/_private.h"
67
68 #undef sched_setscheduler
69 #undef setpriority
70 #include <sys/time.h>
71 #include <fcntl.h>
72 #include <signal.h>
73 #include <sched.h>
74 #include <sys/un.h>
75 #include <sys/wait.h>
76 #include <ctype.h>
77 #include <sys/resource.h>
78 #include <grp.h>
79 #include <pwd.h>
80 #include <sys/stat.h>
81 #if defined(HAVE_SYSINFO)
82 #include <sys/sysinfo.h>
83 #elif defined(HAVE_SYSCTL)
84 #include <sys/param.h>
85 #include <sys/sysctl.h>
86 #if !defined(__OpenBSD__)
87 #include <sys/vmmeter.h>
88 #if defined(__FreeBSD__)
89 #include <vm/vm_param.h>
90 #endif
91 #endif
92 #if defined(HAVE_SWAPCTL)
93 #include <sys/swap.h>
94 #endif
95 #endif
96 #include <regex.h>
97
98 #if defined(SOLARIS)
99 int daemon(int, int);  /* defined in libresolv of all places */
100 #include <sys/loadavg.h>
101 #endif
102
103 #ifdef linux
104 #include <sys/prctl.h>
105 #ifdef HAVE_CAP
106 #include <sys/capability.h>
107 #endif /* HAVE_CAP */
108 #endif /* linux */
109
110 #include "asterisk/paths.h"     /* we define here the variables so better agree on the prototype */
111 #include "asterisk/network.h"
112 #include "asterisk/cli.h"
113 #include "asterisk/channel.h"
114 #include "asterisk/translate.h"
115 #include "asterisk/features.h"
116 #include "asterisk/ulaw.h"
117 #include "asterisk/alaw.h"
118 #include "asterisk/callerid.h"
119 #include "asterisk/image.h"
120 #include "asterisk/tdd.h"
121 #include "asterisk/term.h"
122 #include "asterisk/manager.h"
123 #include "asterisk/cdr.h"
124 #include "asterisk/cel.h"
125 #include "asterisk/pbx.h"
126 #include "asterisk/enum.h"
127 #include "asterisk/http.h"
128 #include "asterisk/udptl.h"
129 #include "asterisk/app.h"
130 #include "asterisk/lock.h"
131 #include "asterisk/utils.h"
132 #include "asterisk/file.h"
133 #include "asterisk/io.h"
134 #include "editline/histedit.h"
135 #include "asterisk/config.h"
136 #include "asterisk/ast_version.h"
137 #include "asterisk/linkedlists.h"
138 #include "asterisk/devicestate.h"
139 #include "asterisk/module.h"
140 #include "asterisk/dsp.h"
141 #include "asterisk/buildinfo.h"
142 #include "asterisk/xmldoc.h"
143 #include "asterisk/poll-compat.h"
144 #include "asterisk/ccss.h"
145 #include "asterisk/test.h"
146 #include "asterisk/rtp_engine.h"
147 #include "asterisk/format.h"
148 #include "asterisk/aoc.h"
149
150 #include "../defaults.h"
151
152 #ifndef AF_LOCAL
153 #define AF_LOCAL AF_UNIX
154 #define PF_LOCAL PF_UNIX
155 #endif
156
157 #define AST_MAX_CONNECTS 128
158 #define NUM_MSGS 64
159
160 /*! \brief Welcome message when starting a CLI interface */
161 #define WELCOME_MESSAGE \
162     ast_verbose("Asterisk %s, Copyright (C) 1999 - 2011 Digium, Inc. and others.\n" \
163                 "Created by Mark Spencer <markster@digium.com>\n" \
164                 "Asterisk comes with ABSOLUTELY NO WARRANTY; type 'core show warranty' for details.\n" \
165                 "This is free software, with components licensed under the GNU General Public\n" \
166                 "License version 2 and other licenses; you are welcome to redistribute it under\n" \
167                 "certain conditions. Type 'core show license' for details.\n" \
168                 "=========================================================================\n", ast_get_version()) \
169
170 /*! \defgroup main_options Main Configuration Options
171  * \brief Main configuration options from asterisk.conf or OS command line on starting Asterisk.
172  * \arg \ref Config_ast "asterisk.conf"
173  * \note Some of them can be changed in the CLI 
174  */
175 /*! @{ */
176
177 struct ast_flags ast_options = { AST_DEFAULT_OPTIONS };
178 struct ast_flags ast_compat = { 0 };
179
180 int option_verbose;                             /*!< Verbosity level */
181 int option_debug;                               /*!< Debug level */
182 double option_maxload;                          /*!< Max load avg on system */
183 int option_maxcalls;                            /*!< Max number of active calls */
184 int option_maxfiles;                            /*!< Max number of open file handles (files, sockets) */
185 #if defined(HAVE_SYSINFO)
186 long option_minmemfree;                         /*!< Minimum amount of free system memory - stop accepting calls if free memory falls below this watermark */
187 #endif
188
189 /*! @} */
190
191 struct ast_eid ast_eid_default;
192
193 /* XXX tmpdir is a subdir of the spool directory, and no way to remap it */
194 char record_cache_dir[AST_CACHE_DIR_LEN] = DEFAULT_TMP_DIR;
195
196 static int ast_socket = -1;             /*!< UNIX Socket for allowing remote control */
197 static int ast_consock = -1;            /*!< UNIX Socket for controlling another asterisk */
198 pid_t ast_mainpid;
199 struct console {
200         int fd;                         /*!< File descriptor */
201         int p[2];                       /*!< Pipe */
202         pthread_t t;                    /*!< Thread of handler */
203         int mute;                       /*!< Is the console muted for logs */
204         int uid;                        /*!< Remote user ID. */
205         int gid;                        /*!< Remote group ID. */
206         int levels[NUMLOGLEVELS];       /*!< Which log levels are enabled for the console */
207 };
208
209 struct ast_atexit {
210         void (*func)(void);
211         AST_RWLIST_ENTRY(ast_atexit) list;
212 };
213
214 static AST_RWLIST_HEAD_STATIC(atexits, ast_atexit);
215
216 struct timeval ast_startuptime;
217 struct timeval ast_lastreloadtime;
218
219 static History *el_hist;
220 static EditLine *el;
221 static char *remotehostname;
222
223 struct console consoles[AST_MAX_CONNECTS];
224
225 char defaultlanguage[MAX_LANGUAGE] = DEFAULT_LANGUAGE;
226
227 static int ast_el_add_history(char *);
228 static int ast_el_read_history(char *);
229 static int ast_el_write_history(char *);
230
231 struct _cfg_paths {
232         char config_dir[PATH_MAX];
233         char module_dir[PATH_MAX];
234         char spool_dir[PATH_MAX];
235         char monitor_dir[PATH_MAX];
236         char var_dir[PATH_MAX];
237         char data_dir[PATH_MAX];
238         char log_dir[PATH_MAX];
239         char agi_dir[PATH_MAX];
240         char run_dir[PATH_MAX];
241         char key_dir[PATH_MAX];
242
243         char config_file[PATH_MAX];
244         char db_path[PATH_MAX];
245         char pid_path[PATH_MAX];
246         char socket_path[PATH_MAX];
247         char run_user[PATH_MAX];
248         char run_group[PATH_MAX];
249         char system_name[128];
250 };
251
252 static struct _cfg_paths cfg_paths;
253
254 const char *ast_config_AST_CONFIG_DIR   = cfg_paths.config_dir;
255 const char *ast_config_AST_CONFIG_FILE  = cfg_paths.config_file;
256 const char *ast_config_AST_MODULE_DIR   = cfg_paths.module_dir;
257 const char *ast_config_AST_SPOOL_DIR    = cfg_paths.spool_dir;
258 const char *ast_config_AST_MONITOR_DIR  = cfg_paths.monitor_dir;
259 const char *ast_config_AST_VAR_DIR      = cfg_paths.var_dir;
260 const char *ast_config_AST_DATA_DIR     = cfg_paths.data_dir;
261 const char *ast_config_AST_LOG_DIR      = cfg_paths.log_dir;
262 const char *ast_config_AST_AGI_DIR      = cfg_paths.agi_dir;
263 const char *ast_config_AST_KEY_DIR      = cfg_paths.key_dir;
264 const char *ast_config_AST_RUN_DIR      = cfg_paths.run_dir;
265
266 const char *ast_config_AST_DB           = cfg_paths.db_path;
267 const char *ast_config_AST_PID          = cfg_paths.pid_path;
268 const char *ast_config_AST_SOCKET       = cfg_paths.socket_path;
269 const char *ast_config_AST_RUN_USER     = cfg_paths.run_user;
270 const char *ast_config_AST_RUN_GROUP    = cfg_paths.run_group;
271 const char *ast_config_AST_SYSTEM_NAME  = cfg_paths.system_name;
272
273 static char ast_config_AST_CTL_PERMISSIONS[PATH_MAX];
274 static char ast_config_AST_CTL_OWNER[PATH_MAX] = "\0";
275 static char ast_config_AST_CTL_GROUP[PATH_MAX] = "\0";
276 static char ast_config_AST_CTL[PATH_MAX] = "asterisk.ctl";
277
278 extern unsigned int ast_FD_SETSIZE;
279
280 static char *_argv[256];
281 static int shuttingdown;
282 static int restartnow;
283 static pthread_t consolethread = AST_PTHREADT_NULL;
284 static pthread_t mon_sig_flags;
285 static int canary_pid = 0;
286 static char canary_filename[128];
287
288 static char randompool[256];
289
290 static int sig_alert_pipe[2] = { -1, -1 };
291 static struct {
292          unsigned int need_reload:1;
293          unsigned int need_quit:1;
294          unsigned int need_quit_handler:1;
295 } sig_flags;
296
297 #if !defined(LOW_MEMORY)
298 struct file_version {
299         AST_RWLIST_ENTRY(file_version) list;
300         const char *file;
301         char *version;
302 };
303
304 static AST_RWLIST_HEAD_STATIC(file_versions, file_version);
305
306 void ast_register_file_version(const char *file, const char *version)
307 {
308         struct file_version *new;
309         char *work;
310         size_t version_length;
311
312         work = ast_strdupa(version);
313         work = ast_strip(ast_strip_quoted(work, "$", "$"));
314         version_length = strlen(work) + 1;
315         
316         if (!(new = ast_calloc(1, sizeof(*new) + version_length)))
317                 return;
318
319         new->file = file;
320         new->version = (char *) new + sizeof(*new);
321         memcpy(new->version, work, version_length);
322         AST_RWLIST_WRLOCK(&file_versions);
323         AST_RWLIST_INSERT_HEAD(&file_versions, new, list);
324         AST_RWLIST_UNLOCK(&file_versions);
325 }
326
327 void ast_unregister_file_version(const char *file)
328 {
329         struct file_version *find;
330
331         AST_RWLIST_WRLOCK(&file_versions);
332         AST_RWLIST_TRAVERSE_SAFE_BEGIN(&file_versions, find, list) {
333                 if (!strcasecmp(find->file, file)) {
334                         AST_RWLIST_REMOVE_CURRENT(list);
335                         break;
336                 }
337         }
338         AST_RWLIST_TRAVERSE_SAFE_END;
339         AST_RWLIST_UNLOCK(&file_versions);
340
341         if (find)
342                 ast_free(find);
343 }
344
345 char *ast_complete_source_filename(const char *partial, int n)
346 {
347         struct file_version *find;
348         size_t len = strlen(partial);
349         int count = 0;
350         char *res = NULL;
351
352         AST_RWLIST_RDLOCK(&file_versions);
353         AST_RWLIST_TRAVERSE(&file_versions, find, list) {
354                 if (!strncasecmp(find->file, partial, len) && ++count > n) {
355                         res = ast_strdup(find->file);
356                         break;
357                 }
358         }
359         AST_RWLIST_UNLOCK(&file_versions);
360         return res;
361 }
362
363 /*! \brief Find version for given module name */
364 const char *ast_file_version_find(const char *file)
365 {
366         struct file_version *iterator;
367
368         AST_RWLIST_WRLOCK(&file_versions);
369         AST_RWLIST_TRAVERSE(&file_versions, iterator, list) {
370                 if (!strcasecmp(iterator->file, file))
371                         break;
372         }
373         AST_RWLIST_UNLOCK(&file_versions);
374         if (iterator)
375                 return iterator->version;
376         return NULL;
377 }      
378        
379
380
381 struct thread_list_t {
382         AST_RWLIST_ENTRY(thread_list_t) list;
383         char *name;
384         pthread_t id;
385         int lwp;
386 };
387
388 static AST_RWLIST_HEAD_STATIC(thread_list, thread_list_t);
389
390 void ast_register_thread(char *name)
391
392         struct thread_list_t *new = ast_calloc(1, sizeof(*new));
393
394         if (!new)
395                 return;
396         new->id = pthread_self();
397         new->lwp = ast_get_tid();
398         new->name = name; /* steal the allocated memory for the thread name */
399         AST_RWLIST_WRLOCK(&thread_list);
400         AST_RWLIST_INSERT_HEAD(&thread_list, new, list);
401         AST_RWLIST_UNLOCK(&thread_list);
402 }
403
404 void ast_unregister_thread(void *id)
405 {
406         struct thread_list_t *x;
407
408         AST_RWLIST_WRLOCK(&thread_list);
409         AST_RWLIST_TRAVERSE_SAFE_BEGIN(&thread_list, x, list) {
410                 if ((void *) x->id == id) {
411                         AST_RWLIST_REMOVE_CURRENT(list);
412                         break;
413                 }
414         }
415         AST_RWLIST_TRAVERSE_SAFE_END;
416         AST_RWLIST_UNLOCK(&thread_list);
417         if (x) {
418                 ast_free(x->name);
419                 ast_free(x);
420         }
421 }
422
423 /*! \brief Give an overview of core settings */
424 static char *handle_show_settings(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
425 {
426         char buf[BUFSIZ];
427         struct ast_tm tm;
428         char eid_str[128];
429
430         switch (cmd) {
431         case CLI_INIT:
432                 e->command = "core show settings";
433                 e->usage = "Usage: core show settings\n"
434                            "       Show core misc settings";
435                 return NULL;
436         case CLI_GENERATE:
437                 return NULL;
438         }
439
440         ast_eid_to_str(eid_str, sizeof(eid_str), &ast_eid_default);
441
442         ast_cli(a->fd, "\nPBX Core settings\n");
443         ast_cli(a->fd, "-----------------\n");
444         ast_cli(a->fd, "  Version:                     %s\n", ast_get_version());
445         ast_cli(a->fd, "  Build Options:               %s\n", S_OR(AST_BUILDOPTS, "(none)"));
446         if (option_maxcalls)
447                 ast_cli(a->fd, "  Maximum calls:               %d (Current %d)\n", option_maxcalls, ast_active_channels());
448         else
449                 ast_cli(a->fd, "  Maximum calls:               Not set\n");
450         if (option_maxfiles)
451                 ast_cli(a->fd, "  Maximum open file handles:   %d\n", option_maxfiles); 
452         else
453                 ast_cli(a->fd, "  Maximum open file handles:   Not set\n");
454         ast_cli(a->fd, "  Verbosity:                   %d\n", option_verbose);
455         ast_cli(a->fd, "  Debug level:                 %d\n", option_debug);
456         ast_cli(a->fd, "  Maximum load average:        %lf\n", option_maxload);
457 #if defined(HAVE_SYSINFO)
458         ast_cli(a->fd, "  Minimum free memory:         %ld MB\n", option_minmemfree);
459 #endif
460         if (ast_localtime(&ast_startuptime, &tm, NULL)) {
461                 ast_strftime(buf, sizeof(buf), "%H:%M:%S", &tm);
462                 ast_cli(a->fd, "  Startup time:                %s\n", buf);
463         }
464         if (ast_localtime(&ast_lastreloadtime, &tm, NULL)) {
465                 ast_strftime(buf, sizeof(buf), "%H:%M:%S", &tm);
466                 ast_cli(a->fd, "  Last reload time:            %s\n", buf);
467         }
468         ast_cli(a->fd, "  System:                      %s/%s built by %s on %s %s\n", ast_build_os, ast_build_kernel, ast_build_user, ast_build_machine, ast_build_date);
469         ast_cli(a->fd, "  System name:                 %s\n", ast_config_AST_SYSTEM_NAME);
470         ast_cli(a->fd, "  Entity ID:                   %s\n", eid_str);
471         ast_cli(a->fd, "  Default language:            %s\n", defaultlanguage);
472         ast_cli(a->fd, "  Language prefix:             %s\n", ast_language_is_prefix ? "Enabled" : "Disabled");
473         ast_cli(a->fd, "  User name and group:         %s/%s\n", ast_config_AST_RUN_USER, ast_config_AST_RUN_GROUP);
474         ast_cli(a->fd, "  Executable includes:         %s\n", ast_test_flag(&ast_options, AST_OPT_FLAG_EXEC_INCLUDES) ? "Enabled" : "Disabled");
475         ast_cli(a->fd, "  Transcode via SLIN:          %s\n", ast_test_flag(&ast_options, AST_OPT_FLAG_TRANSCODE_VIA_SLIN) ? "Enabled" : "Disabled");
476         ast_cli(a->fd, "  Internal timing:             %s\n", ast_test_flag(&ast_options, AST_OPT_FLAG_INTERNAL_TIMING) ? "Enabled" : "Disabled");
477         ast_cli(a->fd, "  Transmit silence during rec: %s\n", ast_test_flag(&ast_options, AST_OPT_FLAG_TRANSMIT_SILENCE) ? "Enabled" : "Disabled");
478         ast_cli(a->fd, "  Generic PLC:                 %s\n", ast_test_flag(&ast_options, AST_OPT_FLAG_GENERIC_PLC) ? "Enabled" : "Disabled");
479
480         ast_cli(a->fd, "\n* Subsystems\n");
481         ast_cli(a->fd, "  -------------\n");
482         ast_cli(a->fd, "  Manager (AMI):               %s\n", check_manager_enabled() ? "Enabled" : "Disabled");
483         ast_cli(a->fd, "  Web Manager (AMI/HTTP):      %s\n", check_webmanager_enabled() ? "Enabled" : "Disabled");
484         ast_cli(a->fd, "  Call data records:           %s\n", check_cdr_enabled() ? "Enabled" : "Disabled");
485         ast_cli(a->fd, "  Realtime Architecture (ARA): %s\n", ast_realtime_enabled() ? "Enabled" : "Disabled");
486
487         /*! \todo we could check musiconhold, voicemail, smdi, adsi, queues  */
488
489         ast_cli(a->fd, "\n* Directories\n");
490         ast_cli(a->fd, "  -------------\n");
491         ast_cli(a->fd, "  Configuration file:          %s\n", ast_config_AST_CONFIG_FILE);
492         ast_cli(a->fd, "  Configuration directory:     %s\n", ast_config_AST_CONFIG_DIR);
493         ast_cli(a->fd, "  Module directory:            %s\n", ast_config_AST_MODULE_DIR);
494         ast_cli(a->fd, "  Spool directory:             %s\n", ast_config_AST_SPOOL_DIR);
495         ast_cli(a->fd, "  Log directory:               %s\n", ast_config_AST_LOG_DIR);
496         ast_cli(a->fd, "  Run/Sockets directory:       %s\n", ast_config_AST_RUN_DIR);
497         ast_cli(a->fd, "  PID file:                    %s\n", ast_config_AST_PID);
498         ast_cli(a->fd, "  VarLib directory:            %s\n", ast_config_AST_VAR_DIR);
499         ast_cli(a->fd, "  Data directory:              %s\n", ast_config_AST_DATA_DIR);
500         ast_cli(a->fd, "  ASTDB:                       %s\n", ast_config_AST_DB);
501         ast_cli(a->fd, "  IAX2 Keys directory:         %s\n", ast_config_AST_KEY_DIR);
502         ast_cli(a->fd, "  AGI Scripts directory:       %s\n", ast_config_AST_AGI_DIR);
503         ast_cli(a->fd, "\n\n");
504         return CLI_SUCCESS;
505 }
506
507 static char *handle_show_threads(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
508 {
509         int count = 0;
510         struct thread_list_t *cur;
511         switch (cmd) {
512         case CLI_INIT:
513                 e->command = "core show threads";
514                 e->usage = 
515                         "Usage: core show threads\n"
516                         "       List threads currently active in the system.\n";
517                 return NULL;
518         case CLI_GENERATE:
519                 return NULL;
520         }
521
522         AST_RWLIST_RDLOCK(&thread_list);
523         AST_RWLIST_TRAVERSE(&thread_list, cur, list) {
524                 ast_cli(a->fd, "%p %d %s\n", (void *)cur->id, cur->lwp, cur->name);
525                 count++;
526         }
527         AST_RWLIST_UNLOCK(&thread_list);
528         ast_cli(a->fd, "%d threads listed.\n", count);
529         return CLI_SUCCESS;
530 }
531
532 #if defined (HAVE_SYSCTL) && defined(HAVE_SWAPCTL)
533 /*
534  * swapmode is rewritten by Tobias Weingartner <weingart@openbsd.org>
535  * to be based on the new swapctl(2) system call.
536  */
537 static int swapmode(int *used, int *total)
538 {
539         struct swapent *swdev;
540         int nswap, rnswap, i;
541
542         nswap = swapctl(SWAP_NSWAP, 0, 0);
543         if (nswap == 0)
544                 return 0;
545
546         swdev = ast_calloc(nswap, sizeof(*swdev));
547         if (swdev == NULL)
548                 return 0;
549
550         rnswap = swapctl(SWAP_STATS, swdev, nswap);
551         if (rnswap == -1) {
552                 ast_free(swdev);
553                 return 0;
554         }
555
556         /* if rnswap != nswap, then what? */
557
558         /* Total things up */
559         *total = *used = 0;
560         for (i = 0; i < nswap; i++) {
561                 if (swdev[i].se_flags & SWF_ENABLE) {
562                         *used += (swdev[i].se_inuse / (1024 / DEV_BSIZE));
563                         *total += (swdev[i].se_nblks / (1024 / DEV_BSIZE));
564                 }
565         }
566         ast_free(swdev);
567         return 1;
568 }
569 #elif defined(HAVE_SYSCTL) && !defined(HAVE_SYSINFO)
570 static int swapmode(int *used, int *total)
571 {
572         *used = *total = 0;
573         return 1;
574 }
575 #endif
576
577 #if defined(HAVE_SYSINFO) || defined(HAVE_SYSCTL)
578 /*! \brief Give an overview of system statistics */
579 static char *handle_show_sysinfo(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
580 {
581         uint64_t physmem, freeram;
582         uint64_t freeswap = 0;
583         int nprocs = 0;
584         long uptime = 0;
585         int totalswap = 0;
586 #if defined(HAVE_SYSINFO)
587         struct sysinfo sys_info;
588         sysinfo(&sys_info);
589         uptime = sys_info.uptime / 3600;
590         physmem = sys_info.totalram * sys_info.mem_unit;
591         freeram = (sys_info.freeram * sys_info.mem_unit) / 1024;
592         totalswap = (sys_info.totalswap * sys_info.mem_unit) / 1024;
593         freeswap = (sys_info.freeswap * sys_info.mem_unit) / 1024;
594         nprocs = sys_info.procs;
595 #elif defined(HAVE_SYSCTL)
596         static int pageshift;
597         struct vmtotal vmtotal;
598         struct timeval  boottime;
599         time_t  now;
600         int mib[2], pagesize, usedswap = 0;
601         size_t len;
602         /* calculate the uptime by looking at boottime */
603         time(&now);
604         mib[0] = CTL_KERN;
605         mib[1] = KERN_BOOTTIME;
606         len = sizeof(boottime);
607         if (sysctl(mib, 2, &boottime, &len, NULL, 0) != -1) {
608                 uptime = now - boottime.tv_sec;
609         }
610         uptime = uptime/3600;
611         /* grab total physical memory  */
612         mib[0] = CTL_HW;
613 #if defined(HW_PHYSMEM64)
614         mib[1] = HW_PHYSMEM64;
615 #else
616         mib[1] = HW_PHYSMEM;
617 #endif
618         len = sizeof(physmem);
619         sysctl(mib, 2, &physmem, &len, NULL, 0);
620
621         pagesize = getpagesize();
622         pageshift = 0;
623         while (pagesize > 1) {
624                 pageshift++;
625                 pagesize >>= 1;
626         }
627
628         /* we only need the amount of log(2)1024 for our conversion */
629         pageshift -= 10;
630
631         /* grab vm totals */
632         mib[0] = CTL_VM;
633         mib[1] = VM_METER;
634         len = sizeof(vmtotal);
635         sysctl(mib, 2, &vmtotal, &len, NULL, 0);
636         freeram = (vmtotal.t_free << pageshift);
637         /* generate swap usage and totals */
638         swapmode(&usedswap, &totalswap);
639         freeswap = (totalswap - usedswap);
640         /* grab number of processes */
641 #if defined(__OpenBSD__)
642         mib[0] = CTL_KERN;
643         mib[1] = KERN_NPROCS;
644         len = sizeof(nprocs);
645         sysctl(mib, 2, &nprocs, &len, NULL, 0);
646 #endif
647 #endif
648
649         switch (cmd) {
650         case CLI_INIT:
651                 e->command = "core show sysinfo";
652                 e->usage =
653                         "Usage: core show sysinfo\n"
654                         "       List current system information.\n";
655                 return NULL;
656         case CLI_GENERATE:
657                 return NULL;
658         }
659
660         ast_cli(a->fd, "\nSystem Statistics\n");
661         ast_cli(a->fd, "-----------------\n");
662         ast_cli(a->fd, "  System Uptime:             %lu hours\n", uptime);
663         ast_cli(a->fd, "  Total RAM:                 %" PRIu64 " KiB\n", physmem / 1024);
664         ast_cli(a->fd, "  Free RAM:                  %" PRIu64 " KiB\n", freeram);
665 #if defined(HAVE_SYSINFO)
666         ast_cli(a->fd, "  Buffer RAM:                %" PRIu64 " KiB\n", ((uint64_t) sys_info.bufferram * sys_info.mem_unit) / 1024);
667 #endif
668 #if defined (HAVE_SYSCTL) || defined(HAVE_SWAPCTL)
669         ast_cli(a->fd, "  Total Swap Space:          %u KiB\n", totalswap);
670         ast_cli(a->fd, "  Free Swap Space:           %" PRIu64 " KiB\n\n", freeswap);
671 #endif
672         ast_cli(a->fd, "  Number of Processes:       %d \n\n", nprocs);
673         return CLI_SUCCESS;
674 }
675 #endif
676
677 struct profile_entry {
678         const char *name;
679         uint64_t        scale;  /* if non-zero, values are scaled by this */
680         int64_t mark;
681         int64_t value;
682         int64_t events;
683 };
684
685 struct profile_data {
686         int entries;
687         int max_size;
688         struct profile_entry e[0];
689 };
690
691 static struct profile_data *prof_data;
692
693 /*! \brief allocates a counter with a given name and scale.
694  * \return Returns the identifier of the counter.
695  */
696 int ast_add_profile(const char *name, uint64_t scale)
697 {
698         int l = sizeof(struct profile_data);
699         int n = 10;     /* default entries */
700
701         if (prof_data == NULL) {
702                 prof_data = ast_calloc(1, l + n*sizeof(struct profile_entry));
703                 if (prof_data == NULL)
704                         return -1;
705                 prof_data->entries = 0;
706                 prof_data->max_size = n;
707         }
708         if (prof_data->entries >= prof_data->max_size) {
709                 void *p;
710                 n = prof_data->max_size + 20;
711                 p = ast_realloc(prof_data, l + n*sizeof(struct profile_entry));
712                 if (p == NULL)
713                         return -1;
714                 prof_data = p;
715                 prof_data->max_size = n;
716         }
717         n = prof_data->entries++;
718         prof_data->e[n].name = ast_strdup(name);
719         prof_data->e[n].value = 0;
720         prof_data->e[n].events = 0;
721         prof_data->e[n].mark = 0;
722         prof_data->e[n].scale = scale;
723         return n;
724 }
725
726 int64_t ast_profile(int i, int64_t delta)
727 {
728         if (!prof_data || i < 0 || i > prof_data->entries)      /* invalid index */
729                 return 0;
730         if (prof_data->e[i].scale > 1)
731                 delta /= prof_data->e[i].scale;
732         prof_data->e[i].value += delta;
733         prof_data->e[i].events++;
734         return prof_data->e[i].value;
735 }
736
737 /* The RDTSC instruction was introduced on the Pentium processor and is not
738  * implemented on certain clones, like the Cyrix 586. Hence, the previous
739  * expectation of __i386__ was in error. */
740 #if defined ( __i686__) && (defined(__FreeBSD__) || defined(linux))
741 #if defined(__FreeBSD__)
742 #include <machine/cpufunc.h>
743 #elif defined(linux)
744 static __inline uint64_t
745 rdtsc(void)
746
747         uint64_t rv;
748
749         __asm __volatile(".byte 0x0f, 0x31" : "=A" (rv));
750         return (rv);
751 }
752 #endif
753 #else   /* supply a dummy function on other platforms */
754 static __inline uint64_t
755 rdtsc(void)
756 {
757         return 0;
758 }
759 #endif
760
761 int64_t ast_mark(int i, int startstop)
762 {
763         if (!prof_data || i < 0 || i > prof_data->entries) /* invalid index */
764                 return 0;
765         if (startstop == 1)
766                 prof_data->e[i].mark = rdtsc();
767         else {
768                 prof_data->e[i].mark = (rdtsc() - prof_data->e[i].mark);
769                 if (prof_data->e[i].scale > 1)
770                         prof_data->e[i].mark /= prof_data->e[i].scale;
771                 prof_data->e[i].value += prof_data->e[i].mark;
772                 prof_data->e[i].events++;
773         }
774         return prof_data->e[i].mark;
775 }
776
777 #define DEFINE_PROFILE_MIN_MAX_VALUES min = 0; \
778         max = prof_data->entries;\
779         if  (a->argc > 3) { /* specific entries */ \
780                 if (isdigit(a->argv[3][0])) { \
781                         min = atoi(a->argv[3]); \
782                         if (a->argc == 5 && strcmp(a->argv[4], "-")) \
783                                 max = atoi(a->argv[4]); \
784                 } else \
785                         search = a->argv[3]; \
786         } \
787         if (max > prof_data->entries) \
788                 max = prof_data->entries;
789
790 static char *handle_show_profile(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
791 {
792         int i, min, max;
793         const char *search = NULL;
794         switch (cmd) {
795         case CLI_INIT:
796                 e->command = "core show profile";
797                 e->usage = "Usage: core show profile\n"
798                            "       show profile information";
799                 return NULL;
800         case CLI_GENERATE:
801                 return NULL;
802         }
803
804         if (prof_data == NULL)
805                 return 0;
806
807         DEFINE_PROFILE_MIN_MAX_VALUES;
808         ast_cli(a->fd, "profile values (%d, allocated %d)\n-------------------\n",
809                 prof_data->entries, prof_data->max_size);
810         ast_cli(a->fd, "%6s   %8s  %10s %12s %12s  %s\n", "ID", "Scale", "Events",
811                         "Value", "Average", "Name");
812         for (i = min; i < max; i++) {
813                 struct profile_entry *entry = &prof_data->e[i];
814                 if (!search || strstr(entry->name, search))
815                     ast_cli(a->fd, "%6d: [%8ld] %10ld %12lld %12lld  %s\n",
816                         i,
817                         (long)entry->scale,
818                         (long)entry->events, (long long)entry->value,
819                         (long long)(entry->events ? entry->value / entry->events : entry->value),
820                         entry->name);
821         }
822         return CLI_SUCCESS;
823 }
824
825 static char *handle_clear_profile(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
826 {
827         int i, min, max;
828         const char *search = NULL;
829         switch (cmd) {
830         case CLI_INIT:
831                 e->command = "core clear profile";
832                 e->usage = "Usage: core clear profile\n"
833                            "       clear profile information";
834                 return NULL;
835         case CLI_GENERATE:
836                 return NULL;
837         }
838
839         if (prof_data == NULL)
840                 return 0;
841
842         DEFINE_PROFILE_MIN_MAX_VALUES;
843         for (i= min; i < max; i++) {
844                 if (!search || strstr(prof_data->e[i].name, search)) {
845                         prof_data->e[i].value = 0;
846                         prof_data->e[i].events = 0;
847                 }
848         }
849         return CLI_SUCCESS;
850 }
851 #undef DEFINE_PROFILE_MIN_MAX_VALUES
852
853 /*! \brief CLI command to list module versions */
854 static char *handle_show_version_files(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
855 {
856 #define FORMAT "%-25.25s %-40.40s\n"
857         struct file_version *iterator;
858         regex_t regexbuf;
859         int havepattern = 0;
860         int havename = 0;
861         int count_files = 0;
862         char *ret = NULL;
863         int matchlen, which = 0;
864         struct file_version *find;
865
866         switch (cmd) {
867         case CLI_INIT:
868                 e->command = "core show file version [like]";
869                 e->usage = 
870                         "Usage: core show file version [like <pattern>]\n"
871                         "       Lists the revision numbers of the files used to build this copy of Asterisk.\n"
872                         "       Optional regular expression pattern is used to filter the file list.\n";
873                 return NULL;
874         case CLI_GENERATE:
875                 matchlen = strlen(a->word);
876                 if (a->pos != 3)
877                         return NULL;
878                 AST_RWLIST_RDLOCK(&file_versions);
879                 AST_RWLIST_TRAVERSE(&file_versions, find, list) {
880                         if (!strncasecmp(a->word, find->file, matchlen) && ++which > a->n) {
881                                 ret = ast_strdup(find->file);
882                                 break;
883                         }
884                 }
885                 AST_RWLIST_UNLOCK(&file_versions);
886                 return ret;
887         }
888
889
890         switch (a->argc) {
891         case 6:
892                 if (!strcasecmp(a->argv[4], "like")) {
893                         if (regcomp(&regexbuf, a->argv[5], REG_EXTENDED | REG_NOSUB))
894                                 return CLI_SHOWUSAGE;
895                         havepattern = 1;
896                 } else
897                         return CLI_SHOWUSAGE;
898                 break;
899         case 5:
900                 havename = 1;
901                 break;
902         case 4:
903                 break;
904         default:
905                 return CLI_SHOWUSAGE;
906         }
907
908         ast_cli(a->fd, FORMAT, "File", "Revision");
909         ast_cli(a->fd, FORMAT, "----", "--------");
910         AST_RWLIST_RDLOCK(&file_versions);
911         AST_RWLIST_TRAVERSE(&file_versions, iterator, list) {
912                 if (havename && strcasecmp(iterator->file, a->argv[4]))
913                         continue;
914
915                 if (havepattern && regexec(&regexbuf, iterator->file, 0, NULL, 0))
916                         continue;
917
918                 ast_cli(a->fd, FORMAT, iterator->file, iterator->version);
919                 count_files++;
920                 if (havename)
921                         break;
922         }
923         AST_RWLIST_UNLOCK(&file_versions);
924         if (!havename) {
925                 ast_cli(a->fd, "%d files listed.\n", count_files);
926         }
927
928         if (havepattern)
929                 regfree(&regexbuf);
930
931         return CLI_SUCCESS;
932 #undef FORMAT
933 }
934
935 #endif /* ! LOW_MEMORY */
936
937 int ast_register_atexit(void (*func)(void))
938 {
939         struct ast_atexit *ae;
940
941         if (!(ae = ast_calloc(1, sizeof(*ae))))
942                 return -1;
943
944         ae->func = func;
945
946         ast_unregister_atexit(func);    
947
948         AST_RWLIST_WRLOCK(&atexits);
949         AST_RWLIST_INSERT_HEAD(&atexits, ae, list);
950         AST_RWLIST_UNLOCK(&atexits);
951
952         return 0;
953 }
954
955 void ast_unregister_atexit(void (*func)(void))
956 {
957         struct ast_atexit *ae = NULL;
958
959         AST_RWLIST_WRLOCK(&atexits);
960         AST_RWLIST_TRAVERSE_SAFE_BEGIN(&atexits, ae, list) {
961                 if (ae->func == func) {
962                         AST_RWLIST_REMOVE_CURRENT(list);
963                         break;
964                 }
965         }
966         AST_RWLIST_TRAVERSE_SAFE_END;
967         AST_RWLIST_UNLOCK(&atexits);
968
969         free(ae);
970 }
971
972 /* Sending commands from consoles back to the daemon requires a terminating NULL */
973 static int fdsend(int fd, const char *s)
974 {
975         return write(fd, s, strlen(s) + 1);
976 }
977
978 /* Sending messages from the daemon back to the display requires _excluding_ the terminating NULL */
979 static int fdprint(int fd, const char *s)
980 {
981         return write(fd, s, strlen(s));
982 }
983
984 /*! \brief NULL handler so we can collect the child exit status */
985 static void _null_sig_handler(int sig)
986 {
987
988 }
989
990 static struct sigaction null_sig_handler = {
991         .sa_handler = _null_sig_handler,
992         .sa_flags = SA_RESTART,
993 };
994
995 static struct sigaction ignore_sig_handler = {
996         .sa_handler = SIG_IGN,
997 };
998
999 AST_MUTEX_DEFINE_STATIC(safe_system_lock);
1000 /*! \brief Keep track of how many threads are currently trying to wait*() on
1001  *  a child process */
1002 static unsigned int safe_system_level = 0;
1003 static struct sigaction safe_system_prev_handler;
1004
1005 void ast_replace_sigchld(void)
1006 {
1007         unsigned int level;
1008
1009         ast_mutex_lock(&safe_system_lock);
1010         level = safe_system_level++;
1011
1012         /* only replace the handler if it has not already been done */
1013         if (level == 0) {
1014                 sigaction(SIGCHLD, &null_sig_handler, &safe_system_prev_handler);
1015         }
1016
1017         ast_mutex_unlock(&safe_system_lock);
1018 }
1019
1020 void ast_unreplace_sigchld(void)
1021 {
1022         unsigned int level;
1023
1024         ast_mutex_lock(&safe_system_lock);
1025         level = --safe_system_level;
1026
1027         /* only restore the handler if we are the last one */
1028         if (level == 0) {
1029                 sigaction(SIGCHLD, &safe_system_prev_handler, NULL);
1030         }
1031
1032         ast_mutex_unlock(&safe_system_lock);
1033 }
1034
1035 int ast_safe_system(const char *s)
1036 {
1037         pid_t pid;
1038         int res;
1039         struct rusage rusage;
1040         int status;
1041
1042 #if defined(HAVE_WORKING_FORK) || defined(HAVE_WORKING_VFORK)
1043         ast_replace_sigchld();
1044
1045 #ifdef HAVE_WORKING_FORK
1046         pid = fork();
1047 #else
1048         pid = vfork();
1049 #endif  
1050
1051         if (pid == 0) {
1052 #ifdef HAVE_CAP
1053                 cap_t cap = cap_from_text("cap_net_admin-eip");
1054
1055                 if (cap_set_proc(cap)) {
1056                         /* Careful with order! Logging cannot happen after we close FDs */
1057                         ast_log(LOG_WARNING, "Unable to remove capabilities.\n");
1058                 }
1059                 cap_free(cap);
1060 #endif
1061 #ifdef HAVE_WORKING_FORK
1062                 if (ast_opt_high_priority)
1063                         ast_set_priority(0);
1064                 /* Close file descriptors and launch system command */
1065                 ast_close_fds_above_n(STDERR_FILENO);
1066 #endif
1067                 execl("/bin/sh", "/bin/sh", "-c", s, (char *) NULL);
1068                 _exit(1);
1069         } else if (pid > 0) {
1070                 for (;;) {
1071                         res = wait4(pid, &status, 0, &rusage);
1072                         if (res > -1) {
1073                                 res = WIFEXITED(status) ? WEXITSTATUS(status) : -1;
1074                                 break;
1075                         } else if (errno != EINTR) 
1076                                 break;
1077                 }
1078         } else {
1079                 ast_log(LOG_WARNING, "Fork failed: %s\n", strerror(errno));
1080                 res = -1;
1081         }
1082
1083         ast_unreplace_sigchld();
1084 #else /* !defined(HAVE_WORKING_FORK) && !defined(HAVE_WORKING_VFORK) */
1085         res = -1;
1086 #endif
1087
1088         return res;
1089 }
1090
1091 /*!
1092  * \brief enable or disable a logging level to a specified console
1093  */
1094 void ast_console_toggle_loglevel(int fd, int level, int state)
1095 {
1096         int x;
1097         for (x = 0;x < AST_MAX_CONNECTS; x++) {
1098                 if (fd == consoles[x].fd) {
1099                         /*
1100                          * Since the logging occurs when levels are false, set to
1101                          * flipped iinput because this function accepts 0 as off and 1 as on
1102                          */
1103                         consoles[x].levels[level] = state ? 0 : 1;
1104                         return;
1105                 }
1106         }
1107 }
1108
1109 /*!
1110  * \brief mute or unmute a console from logging
1111  */
1112 void ast_console_toggle_mute(int fd, int silent) {
1113         int x;
1114         for (x = 0;x < AST_MAX_CONNECTS; x++) {
1115                 if (fd == consoles[x].fd) {
1116                         if (consoles[x].mute) {
1117                                 consoles[x].mute = 0;
1118                                 if (!silent)
1119                                         ast_cli(fd, "Console is not muted anymore.\n");
1120                         } else {
1121                                 consoles[x].mute = 1;
1122                                 if (!silent)
1123                                         ast_cli(fd, "Console is muted.\n");
1124                         }
1125                         return;
1126                 }
1127         }
1128         ast_cli(fd, "Couldn't find remote console.\n");
1129 }
1130
1131 /*!
1132  * \brief log the string to all attached console clients
1133  */
1134 static void ast_network_puts_mutable(const char *string, int level)
1135 {
1136         int x;
1137         for (x = 0;x < AST_MAX_CONNECTS; x++) {
1138                 if (consoles[x].mute)
1139                         continue;
1140                 if (consoles[x].fd > -1) {
1141                         if (!consoles[x].levels[level]) 
1142                                 fdprint(consoles[x].p[1], string);
1143                 }
1144         }
1145 }
1146
1147 /*!
1148  * \brief log the string to the console, and all attached
1149  * console clients
1150  */
1151 void ast_console_puts_mutable(const char *string, int level)
1152 {
1153         fputs(string, stdout);
1154         fflush(stdout);
1155         ast_network_puts_mutable(string, level);
1156 }
1157
1158 /*!
1159  * \brief write the string to all attached console clients
1160  */
1161 static void ast_network_puts(const char *string)
1162 {
1163         int x;
1164         for (x = 0; x < AST_MAX_CONNECTS; x++) {
1165                 if (consoles[x].fd > -1) 
1166                         fdprint(consoles[x].p[1], string);
1167         }
1168 }
1169
1170 /*!
1171  * write the string to the console, and all attached
1172  * console clients
1173  */
1174 void ast_console_puts(const char *string)
1175 {
1176         fputs(string, stdout);
1177         fflush(stdout);
1178         ast_network_puts(string);
1179 }
1180
1181 static void network_verboser(const char *s)
1182 {
1183         ast_network_puts_mutable(s, __LOG_VERBOSE);
1184 }
1185
1186 static pthread_t lthread;
1187
1188 /*!
1189  * \brief read() function supporting the reception of user credentials.
1190  *
1191  * \param fd Socket file descriptor.
1192  * \param buffer Receive buffer.
1193  * \param size 'buffer' size.
1194  * \param con Console structure to set received credentials
1195  * \retval -1 on error
1196  * \retval the number of bytes received on success.
1197  */
1198 static int read_credentials(int fd, char *buffer, size_t size, struct console *con)
1199 {
1200 #if defined(SO_PEERCRED)
1201         struct ucred cred;
1202         socklen_t len = sizeof(cred);
1203 #endif
1204 #if defined(HAVE_GETPEEREID)
1205         uid_t uid;
1206         gid_t gid;
1207 #else
1208         int uid, gid;
1209 #endif
1210         int result;
1211
1212         result = read(fd, buffer, size);
1213         if (result < 0) {
1214                 return result;
1215         }
1216
1217 #if defined(SO_PEERCRED) && (defined(HAVE_STRUCT_UCRED_UID) || defined(HAVE_STRUCT_UCRED_CR_UID))
1218         if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &cred, &len)) {
1219                 return result;
1220         }
1221 #if defined(HAVE_STRUCT_UCRED_UID)
1222         uid = cred.uid;
1223         gid = cred.gid;
1224 #else /* defined(HAVE_STRUCT_UCRED_CR_UID) */
1225         uid = cred.cr_uid;
1226         gid = cred.cr_gid;
1227 #endif /* defined(HAVE_STRUCT_UCRED_UID) */
1228
1229 #elif defined(HAVE_GETPEEREID)
1230         if (getpeereid(fd, &uid, &gid)) {
1231                 return result;
1232         }
1233 #else
1234         return result;
1235 #endif
1236         con->uid = uid;
1237         con->gid = gid;
1238
1239         return result;
1240 }
1241
1242 static void *netconsole(void *vconsole)
1243 {
1244         struct console *con = vconsole;
1245         char hostname[MAXHOSTNAMELEN] = "";
1246         char tmp[512];
1247         int res;
1248         struct pollfd fds[2];
1249         
1250         if (gethostname(hostname, sizeof(hostname)-1))
1251                 ast_copy_string(hostname, "<Unknown>", sizeof(hostname));
1252         snprintf(tmp, sizeof(tmp), "%s/%ld/%s\n", hostname, (long)ast_mainpid, ast_get_version());
1253         fdprint(con->fd, tmp);
1254         for (;;) {
1255                 fds[0].fd = con->fd;
1256                 fds[0].events = POLLIN;
1257                 fds[0].revents = 0;
1258                 fds[1].fd = con->p[0];
1259                 fds[1].events = POLLIN;
1260                 fds[1].revents = 0;
1261
1262                 res = ast_poll(fds, 2, -1);
1263                 if (res < 0) {
1264                         if (errno != EINTR)
1265                                 ast_log(LOG_WARNING, "poll returned < 0: %s\n", strerror(errno));
1266                         continue;
1267                 }
1268                 if (fds[0].revents) {
1269                         res = read_credentials(con->fd, tmp, sizeof(tmp) - 1, con);
1270                         if (res < 1) {
1271                                 break;
1272                         }
1273                         tmp[res] = 0;
1274                         if (strncmp(tmp, "cli quit after ", 15) == 0) {
1275                                 ast_cli_command_multiple_full(con->uid, con->gid, con->fd, res - 15, tmp + 15);
1276                                 break;
1277                         }
1278                         ast_cli_command_multiple_full(con->uid, con->gid, con->fd, res, tmp);
1279                 }
1280                 if (fds[1].revents) {
1281                         res = read_credentials(con->p[0], tmp, sizeof(tmp), con);
1282                         if (res < 1) {
1283                                 ast_log(LOG_ERROR, "read returned %d\n", res);
1284                                 break;
1285                         }
1286                         res = write(con->fd, tmp, res);
1287                         if (res < 1)
1288                                 break;
1289                 }
1290         }
1291         if (!ast_opt_hide_connect) {
1292                 ast_verb(3, "Remote UNIX connection disconnected\n");
1293         }
1294         close(con->fd);
1295         close(con->p[0]);
1296         close(con->p[1]);
1297         con->fd = -1;
1298         
1299         return NULL;
1300 }
1301
1302 static void *listener(void *unused)
1303 {
1304         struct sockaddr_un sunaddr;
1305         int s;
1306         socklen_t len;
1307         int x;
1308         int flags;
1309         struct pollfd fds[1];
1310         for (;;) {
1311                 if (ast_socket < 0)
1312                         return NULL;
1313                 fds[0].fd = ast_socket;
1314                 fds[0].events = POLLIN;
1315                 s = ast_poll(fds, 1, -1);
1316                 pthread_testcancel();
1317                 if (s < 0) {
1318                         if (errno != EINTR)
1319                                 ast_log(LOG_WARNING, "poll returned error: %s\n", strerror(errno));
1320                         continue;
1321                 }
1322                 len = sizeof(sunaddr);
1323                 s = accept(ast_socket, (struct sockaddr *)&sunaddr, &len);
1324                 if (s < 0) {
1325                         if (errno != EINTR)
1326                                 ast_log(LOG_WARNING, "Accept returned %d: %s\n", s, strerror(errno));
1327                 } else {
1328 #if !defined(SO_PASSCRED)
1329                         {
1330 #else
1331                         int sckopt = 1;
1332                         /* turn on socket credentials passing. */
1333                         if (setsockopt(s, SOL_SOCKET, SO_PASSCRED, &sckopt, sizeof(sckopt)) < 0) {
1334                                 ast_log(LOG_WARNING, "Unable to turn on socket credentials passing\n");
1335                         } else {
1336 #endif
1337                                 for (x = 0; x < AST_MAX_CONNECTS; x++) {
1338                                         if (consoles[x].fd >= 0) {
1339                                                 continue;
1340                                         }
1341                                         if (socketpair(AF_LOCAL, SOCK_STREAM, 0, consoles[x].p)) {
1342                                                 ast_log(LOG_ERROR, "Unable to create pipe: %s\n", strerror(errno));
1343                                                 consoles[x].fd = -1;
1344                                                 fdprint(s, "Server failed to create pipe\n");
1345                                                 close(s);
1346                                                 break;
1347                                         }
1348                                         flags = fcntl(consoles[x].p[1], F_GETFL);
1349                                         fcntl(consoles[x].p[1], F_SETFL, flags | O_NONBLOCK);
1350                                         consoles[x].fd = s;
1351                                         consoles[x].mute = 1; /* Default is muted, we will un-mute if necessary */
1352                                         /* Default uid and gid to -2, so then in cli.c/cli_has_permissions() we will be able
1353                                            to know if the user didn't send the credentials. */
1354                                         consoles[x].uid = -2;
1355                                         consoles[x].gid = -2;
1356                                         if (ast_pthread_create_detached_background(&consoles[x].t, NULL, netconsole, &consoles[x])) {
1357                                                 ast_log(LOG_ERROR, "Unable to spawn thread to handle connection: %s\n", strerror(errno));
1358                                                 close(consoles[x].p[0]);
1359                                                 close(consoles[x].p[1]);
1360                                                 consoles[x].fd = -1;
1361                                                 fdprint(s, "Server failed to spawn thread\n");
1362                                                 close(s);
1363                                         }
1364                                         break;
1365                                 }
1366                                 if (x >= AST_MAX_CONNECTS) {
1367                                         fdprint(s, "No more connections allowed\n");
1368                                         ast_log(LOG_WARNING, "No more connections allowed\n");
1369                                         close(s);
1370                                 } else if ((consoles[x].fd > -1) && (!ast_opt_hide_connect)) {
1371                                         ast_verb(3, "Remote UNIX connection\n");
1372                                 }
1373                         }
1374                 }
1375         }
1376         return NULL;
1377 }
1378
1379 static int ast_makesocket(void)
1380 {
1381         struct sockaddr_un sunaddr;
1382         int res;
1383         int x;
1384         uid_t uid = -1;
1385         gid_t gid = -1;
1386
1387         for (x = 0; x < AST_MAX_CONNECTS; x++)  
1388                 consoles[x].fd = -1;
1389         unlink(ast_config_AST_SOCKET);
1390         ast_socket = socket(PF_LOCAL, SOCK_STREAM, 0);
1391         if (ast_socket < 0) {
1392                 ast_log(LOG_WARNING, "Unable to create control socket: %s\n", strerror(errno));
1393                 return -1;
1394         }               
1395         memset(&sunaddr, 0, sizeof(sunaddr));
1396         sunaddr.sun_family = AF_LOCAL;
1397         ast_copy_string(sunaddr.sun_path, ast_config_AST_SOCKET, sizeof(sunaddr.sun_path));
1398         res = bind(ast_socket, (struct sockaddr *)&sunaddr, sizeof(sunaddr));
1399         if (res) {
1400                 ast_log(LOG_WARNING, "Unable to bind socket to %s: %s\n", ast_config_AST_SOCKET, strerror(errno));
1401                 close(ast_socket);
1402                 ast_socket = -1;
1403                 return -1;
1404         }
1405         res = listen(ast_socket, 2);
1406         if (res < 0) {
1407                 ast_log(LOG_WARNING, "Unable to listen on socket %s: %s\n", ast_config_AST_SOCKET, strerror(errno));
1408                 close(ast_socket);
1409                 ast_socket = -1;
1410                 return -1;
1411         }
1412         if (ast_register_verbose(network_verboser)) {
1413                 ast_log(LOG_WARNING, "Unable to register network verboser?\n");
1414         }
1415
1416         ast_pthread_create_background(&lthread, NULL, listener, NULL);
1417
1418         if (!ast_strlen_zero(ast_config_AST_CTL_OWNER)) {
1419                 struct passwd *pw;
1420                 if ((pw = getpwnam(ast_config_AST_CTL_OWNER)) == NULL)
1421                         ast_log(LOG_WARNING, "Unable to find uid of user %s\n", ast_config_AST_CTL_OWNER);
1422                 else
1423                         uid = pw->pw_uid;
1424         }
1425                 
1426         if (!ast_strlen_zero(ast_config_AST_CTL_GROUP)) {
1427                 struct group *grp;
1428                 if ((grp = getgrnam(ast_config_AST_CTL_GROUP)) == NULL)
1429                         ast_log(LOG_WARNING, "Unable to find gid of group %s\n", ast_config_AST_CTL_GROUP);
1430                 else
1431                         gid = grp->gr_gid;
1432         }
1433
1434         if (chown(ast_config_AST_SOCKET, uid, gid) < 0)
1435                 ast_log(LOG_WARNING, "Unable to change ownership of %s: %s\n", ast_config_AST_SOCKET, strerror(errno));
1436
1437         if (!ast_strlen_zero(ast_config_AST_CTL_PERMISSIONS)) {
1438                 int p1;
1439                 mode_t p;
1440                 sscanf(ast_config_AST_CTL_PERMISSIONS, "%30o", &p1);
1441                 p = p1;
1442                 if ((chmod(ast_config_AST_SOCKET, p)) < 0)
1443                         ast_log(LOG_WARNING, "Unable to change file permissions of %s: %s\n", ast_config_AST_SOCKET, strerror(errno));
1444         }
1445
1446         return 0;
1447 }
1448
1449 static int ast_tryconnect(void)
1450 {
1451         struct sockaddr_un sunaddr;
1452         int res;
1453         ast_consock = socket(PF_LOCAL, SOCK_STREAM, 0);
1454         if (ast_consock < 0) {
1455                 ast_log(LOG_WARNING, "Unable to create socket: %s\n", strerror(errno));
1456                 return 0;
1457         }
1458         memset(&sunaddr, 0, sizeof(sunaddr));
1459         sunaddr.sun_family = AF_LOCAL;
1460         ast_copy_string(sunaddr.sun_path, ast_config_AST_SOCKET, sizeof(sunaddr.sun_path));
1461         res = connect(ast_consock, (struct sockaddr *)&sunaddr, sizeof(sunaddr));
1462         if (res) {
1463                 close(ast_consock);
1464                 ast_consock = -1;
1465                 return 0;
1466         } else
1467                 return 1;
1468 }
1469
1470 /*! \brief Urgent handler
1471
1472  Called by soft_hangup to interrupt the poll, read, or other
1473  system call.  We don't actually need to do anything though.  
1474  Remember: Cannot EVER ast_log from within a signal handler 
1475  */
1476 static void _urg_handler(int num)
1477 {
1478         return;
1479 }
1480
1481 static struct sigaction urg_handler = {
1482         .sa_handler = _urg_handler,
1483         .sa_flags = SA_RESTART,
1484 };
1485
1486 static void _hup_handler(int num)
1487 {
1488         int a = 0, save_errno = errno;
1489         if (option_verbose > 1) 
1490                 printf("Received HUP signal -- Reloading configs\n");
1491         if (restartnow)
1492                 execvp(_argv[0], _argv);
1493         sig_flags.need_reload = 1;
1494         if (sig_alert_pipe[1] != -1) {
1495                 if (write(sig_alert_pipe[1], &a, sizeof(a)) < 0) {
1496                         fprintf(stderr, "hup_handler: write() failed: %s\n", strerror(errno));
1497                 }
1498         }
1499         errno = save_errno;
1500 }
1501
1502 static struct sigaction hup_handler = {
1503         .sa_handler = _hup_handler,
1504         .sa_flags = SA_RESTART,
1505 };
1506
1507 static void _child_handler(int sig)
1508 {
1509         /* Must not ever ast_log or ast_verbose within signal handler */
1510         int n, status, save_errno = errno;
1511
1512         /*
1513          * Reap all dead children -- not just one
1514          */
1515         for (n = 0; wait4(-1, &status, WNOHANG, NULL) > 0; n++)
1516                 ;
1517         if (n == 0 && option_debug)     
1518                 printf("Huh?  Child handler, but nobody there?\n");
1519         errno = save_errno;
1520 }
1521
1522 static struct sigaction child_handler = {
1523         .sa_handler = _child_handler,
1524         .sa_flags = SA_RESTART,
1525 };
1526
1527 /*! \brief Set maximum open files */
1528 static void set_ulimit(int value)
1529 {
1530         struct rlimit l = {0, 0};
1531         
1532         if (value <= 0) {
1533                 ast_log(LOG_WARNING, "Unable to change max files open to invalid value %i\n",value);
1534                 return;
1535         }
1536         
1537         l.rlim_cur = value;
1538         l.rlim_max = value;
1539         
1540         if (setrlimit(RLIMIT_NOFILE, &l)) {
1541                 ast_log(LOG_WARNING, "Unable to disable core size resource limit: %s\n",strerror(errno));
1542                 return;
1543         }
1544         
1545         ast_log(LOG_NOTICE, "Setting max files open to %d\n",value);
1546         
1547         return;
1548 }
1549
1550 /*! \brief Set an X-term or screen title */
1551 static void set_title(char *text)
1552 {
1553         if (getenv("TERM") && strstr(getenv("TERM"), "xterm"))
1554                 fprintf(stdout, "\033]2;%s\007", text);
1555 }
1556
1557 static void set_icon(char *text)
1558 {
1559         if (getenv("TERM") && strstr(getenv("TERM"), "xterm"))
1560                 fprintf(stdout, "\033]1;%s\007", text);
1561 }
1562
1563 /*! \brief We set ourselves to a high priority, that we might pre-empt everything
1564    else.  If your PBX has heavy activity on it, this is a good thing.  */
1565 int ast_set_priority(int pri)
1566 {
1567         struct sched_param sched;
1568         memset(&sched, 0, sizeof(sched));
1569 #ifdef __linux__
1570         if (pri) {  
1571                 sched.sched_priority = 10;
1572                 if (sched_setscheduler(0, SCHED_RR, &sched)) {
1573                         ast_log(LOG_WARNING, "Unable to set high priority\n");
1574                         return -1;
1575                 } else
1576                         if (option_verbose)
1577                                 ast_verbose("Set to realtime thread\n");
1578         } else {
1579                 sched.sched_priority = 0;
1580                 /* According to the manpage, these parameters can never fail. */
1581                 sched_setscheduler(0, SCHED_OTHER, &sched);
1582         }
1583 #else
1584         if (pri) {
1585                 if (setpriority(PRIO_PROCESS, 0, -10) == -1) {
1586                         ast_log(LOG_WARNING, "Unable to set high priority\n");
1587                         return -1;
1588                 } else
1589                         if (option_verbose)
1590                                 ast_verbose("Set to high priority\n");
1591         } else {
1592                 /* According to the manpage, these parameters can never fail. */
1593                 setpriority(PRIO_PROCESS, 0, 0);
1594         }
1595 #endif
1596         return 0;
1597 }
1598
1599 static void ast_run_atexits(void)
1600 {
1601         struct ast_atexit *ae;
1602         AST_RWLIST_RDLOCK(&atexits);
1603         AST_RWLIST_TRAVERSE(&atexits, ae, list) {
1604                 if (ae->func) 
1605                         ae->func();
1606         }
1607         AST_RWLIST_UNLOCK(&atexits);
1608 }
1609
1610 static void quit_handler(int num, int niceness, int safeshutdown, int restart)
1611 {
1612         char filename[80] = "";
1613         time_t s,e;
1614         int x;
1615         /* Try to get as many CDRs as possible submitted to the backend engines (if in batch mode) */
1616         ast_cdr_engine_term();
1617         if (safeshutdown) {
1618                 shuttingdown = 1;
1619                 if (!niceness) {
1620                         /* Begin shutdown routine, hanging up active channels */
1621                         ast_begin_shutdown(1);
1622                         if (option_verbose && ast_opt_console)
1623                                 ast_verbose("Beginning asterisk %s....\n", restart ? "restart" : "shutdown");
1624                         time(&s);
1625                         for (;;) {
1626                                 time(&e);
1627                                 /* Wait up to 15 seconds for all channels to go away */
1628                                 if ((e - s) > 15)
1629                                         break;
1630                                 if (!ast_active_channels())
1631                                         break;
1632                                 if (!shuttingdown)
1633                                         break;
1634                                 /* Sleep 1/10 of a second */
1635                                 usleep(100000);
1636                         }
1637                 } else {
1638                         if (niceness < 2)
1639                                 ast_begin_shutdown(0);
1640                         if (option_verbose && ast_opt_console)
1641                                 ast_verbose("Waiting for inactivity to perform %s...\n", restart ? "restart" : "halt");
1642                         for (;;) {
1643                                 if (!ast_active_channels())
1644                                         break;
1645                                 if (!shuttingdown)
1646                                         break;
1647                                 sleep(1);
1648                         }
1649                 }
1650
1651                 if (!shuttingdown) {
1652                         if (option_verbose && ast_opt_console)
1653                                 ast_verbose("Asterisk %s cancelled.\n", restart ? "restart" : "shutdown");
1654                         return;
1655                 }
1656
1657                 if (niceness)
1658                         ast_module_shutdown();
1659         }
1660         if (ast_opt_console || (ast_opt_remote && !ast_opt_exec)) {
1661                 if (getenv("HOME")) {
1662                         snprintf(filename, sizeof(filename), "%s/.asterisk_history", getenv("HOME"));
1663                 }
1664                 if (!ast_strlen_zero(filename)) {
1665                         ast_el_write_history(filename);
1666                 }
1667                 if (consolethread == AST_PTHREADT_NULL || consolethread == pthread_self()) {
1668                         /* Only end if we are the consolethread, otherwise there's a race with that thread. */
1669                         if (el != NULL) {
1670                                 el_end(el);
1671                         }
1672                         if (el_hist != NULL) {
1673                                 history_end(el_hist);
1674                         }
1675                 } else if (mon_sig_flags == pthread_self()) {
1676                         if (consolethread != AST_PTHREADT_NULL) {
1677                                 pthread_kill(consolethread, SIGURG);
1678                         }
1679                 }
1680         }
1681         if (option_verbose)
1682                 ast_verbose("Executing last minute cleanups\n");
1683         ast_run_atexits();
1684         /* Called on exit */
1685         if (option_verbose && ast_opt_console)
1686                 ast_verbose("Asterisk %s ending (%d).\n", ast_active_channels() ? "uncleanly" : "cleanly", num);
1687         ast_debug(1, "Asterisk ending (%d).\n", num);
1688         manager_event(EVENT_FLAG_SYSTEM, "Shutdown", "Shutdown: %s\r\nRestart: %s\r\n", ast_active_channels() ? "Uncleanly" : "Cleanly", restart ? "True" : "False");
1689         if (ast_socket > -1) {
1690                 pthread_cancel(lthread);
1691                 close(ast_socket);
1692                 ast_socket = -1;
1693                 unlink(ast_config_AST_SOCKET);
1694         }
1695         if (ast_consock > -1)
1696                 close(ast_consock);
1697         if (!ast_opt_remote)
1698                 unlink(ast_config_AST_PID);
1699         printf("%s", term_quit());
1700         if (restart) {
1701                 if (option_verbose || ast_opt_console)
1702                         ast_verbose("Preparing for Asterisk restart...\n");
1703                 /* Mark all FD's for closing on exec */
1704                 for (x=3; x < 32768; x++) {
1705                         fcntl(x, F_SETFD, FD_CLOEXEC);
1706                 }
1707                 if (option_verbose || ast_opt_console)
1708                         ast_verbose("Asterisk is now restarting...\n");
1709                 restartnow = 1;
1710
1711                 /* close logger */
1712                 close_logger();
1713
1714                 /* If there is a consolethread running send it a SIGHUP 
1715                    so it can execvp, otherwise we can do it ourselves */
1716                 if ((consolethread != AST_PTHREADT_NULL) && (consolethread != pthread_self())) {
1717                         pthread_kill(consolethread, SIGHUP);
1718                         /* Give the signal handler some time to complete */
1719                         sleep(2);
1720                 } else
1721                         execvp(_argv[0], _argv);
1722         
1723         } else {
1724                 /* close logger */
1725                 close_logger();
1726         }
1727         exit(0);
1728 }
1729
1730 static void __quit_handler(int num)
1731 {
1732         int a = 0;
1733         sig_flags.need_quit = 1;
1734         if (sig_alert_pipe[1] != -1) {
1735                 if (write(sig_alert_pipe[1], &a, sizeof(a)) < 0) {
1736                         fprintf(stderr, "quit_handler: write() failed: %s\n", strerror(errno));
1737                 }
1738         }
1739         /* There is no need to restore the signal handler here, since the app
1740          * is going to exit */
1741 }
1742
1743 static void __remote_quit_handler(int num)
1744 {
1745         sig_flags.need_quit = 1;
1746 }
1747
1748 static const char *fix_header(char *outbuf, int maxout, const char *s, char *cmp)
1749 {
1750         const char *c;
1751
1752         /* Check for verboser preamble */
1753         if (*s == 127) {
1754                 s++;
1755         }
1756
1757         if (!strncmp(s, cmp, strlen(cmp))) {
1758                 c = s + strlen(cmp);
1759                 term_color(outbuf, cmp, COLOR_GRAY, 0, maxout);
1760                 return c;
1761         }
1762         return NULL;
1763 }
1764
1765 static void console_verboser(const char *s)
1766 {
1767         char tmp[80];
1768         const char *c = NULL;
1769
1770         if ((c = fix_header(tmp, sizeof(tmp), s, VERBOSE_PREFIX_4)) ||
1771             (c = fix_header(tmp, sizeof(tmp), s, VERBOSE_PREFIX_3)) ||
1772             (c = fix_header(tmp, sizeof(tmp), s, VERBOSE_PREFIX_2)) ||
1773             (c = fix_header(tmp, sizeof(tmp), s, VERBOSE_PREFIX_1))) {
1774                 fputs(tmp, stdout);
1775                 fputs(c, stdout);
1776         } else {
1777                 if (*s == 127) {
1778                         s++;
1779                 }
1780                 fputs(s, stdout);
1781         }
1782
1783         fflush(stdout);
1784         
1785         /* Wake up a poll()ing console */
1786         if (ast_opt_console && consolethread != AST_PTHREADT_NULL)
1787                 pthread_kill(consolethread, SIGURG);
1788 }
1789
1790 static int ast_all_zeros(char *s)
1791 {
1792         while (*s) {
1793                 if (*s > 32)
1794                         return 0;
1795                 s++;  
1796         }
1797         return 1;
1798 }
1799
1800 static void consolehandler(char *s)
1801 {
1802         printf("%s", term_end());
1803         fflush(stdout);
1804
1805         /* Called when readline data is available */
1806         if (!ast_all_zeros(s))
1807                 ast_el_add_history(s);
1808         /* The real handler for bang */
1809         if (s[0] == '!') {
1810                 if (s[1])
1811                         ast_safe_system(s+1);
1812                 else
1813                         ast_safe_system(getenv("SHELL") ? getenv("SHELL") : "/bin/sh");
1814         } else 
1815                 ast_cli_command(STDOUT_FILENO, s);
1816 }
1817
1818 static int remoteconsolehandler(char *s)
1819 {
1820         int ret = 0;
1821
1822         /* Called when readline data is available */
1823         if (!ast_all_zeros(s))
1824                 ast_el_add_history(s);
1825         /* The real handler for bang */
1826         if (s[0] == '!') {
1827                 if (s[1])
1828                         ast_safe_system(s+1);
1829                 else
1830                         ast_safe_system(getenv("SHELL") ? getenv("SHELL") : "/bin/sh");
1831                 ret = 1;
1832         }
1833         if ((strncasecmp(s, "quit", 4) == 0 || strncasecmp(s, "exit", 4) == 0) &&
1834             (s[4] == '\0' || isspace(s[4]))) {
1835                 quit_handler(0, 0, 0, 0);
1836                 ret = 1;
1837         }
1838
1839         return ret;
1840 }
1841
1842 static char *handle_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1843 {
1844         switch (cmd) {
1845         case CLI_INIT:
1846                 e->command = "core show version";
1847                 e->usage = 
1848                         "Usage: core show version\n"
1849                         "       Shows Asterisk version information.\n";
1850                 return NULL;
1851         case CLI_GENERATE:
1852                 return NULL;
1853         }
1854
1855         if (a->argc != 3)
1856                 return CLI_SHOWUSAGE;
1857         ast_cli(a->fd, "Asterisk %s built by %s @ %s on a %s running %s on %s\n",
1858                 ast_get_version(), ast_build_user, ast_build_hostname,
1859                 ast_build_machine, ast_build_os, ast_build_date);
1860         return CLI_SUCCESS;
1861 }
1862
1863 #if 0
1864 static int handle_quit(int fd, int argc, char *argv[])
1865 {
1866         if (argc != 1)
1867                 return RESULT_SHOWUSAGE;
1868         quit_handler(0, 0, 1, 0);
1869         return RESULT_SUCCESS;
1870 }
1871 #endif
1872
1873 static char *handle_stop_now(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1874 {
1875         switch (cmd) {
1876         case CLI_INIT:
1877                 e->command = "core stop now";
1878                 e->usage = 
1879                         "Usage: core stop now\n"
1880                         "       Shuts down a running Asterisk immediately, hanging up all active calls .\n";
1881                 return NULL;
1882         case CLI_GENERATE:
1883                 return NULL;
1884         }
1885
1886         if (a->argc != e->args)
1887                 return CLI_SHOWUSAGE;
1888         quit_handler(0, 0 /* Not nice */, 1 /* safely */, 0 /* not restart */);
1889         return CLI_SUCCESS;
1890 }
1891
1892 static char *handle_stop_gracefully(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1893 {
1894         switch (cmd) {
1895         case CLI_INIT:
1896                 e->command = "core stop gracefully";
1897                 e->usage = 
1898                         "Usage: core stop gracefully\n"
1899                         "       Causes Asterisk to not accept new calls, and exit when all\n"
1900                         "       active calls have terminated normally.\n";
1901                 return NULL;
1902         case CLI_GENERATE:
1903                 return NULL;
1904         }
1905
1906         if (a->argc != e->args)
1907                 return CLI_SHOWUSAGE;
1908         quit_handler(0, 1 /* nicely */, 1 /* safely */, 0 /* no restart */);
1909         return CLI_SUCCESS;
1910 }
1911
1912 static char *handle_stop_when_convenient(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1913 {
1914         switch (cmd) {
1915         case CLI_INIT:
1916                 e->command = "core stop when convenient";
1917                 e->usage = 
1918                         "Usage: core stop when convenient\n"
1919                         "       Causes Asterisk to perform a shutdown when all active calls have ended.\n";
1920                 return NULL;
1921         case CLI_GENERATE:
1922                 return NULL;
1923         }
1924
1925         if (a->argc != e->args)
1926                 return CLI_SHOWUSAGE;
1927         ast_cli(a->fd, "Waiting for inactivity to perform halt\n");
1928         quit_handler(0, 2 /* really nicely */, 1 /* safely */, 0 /* don't restart */);
1929         return CLI_SUCCESS;
1930 }
1931
1932 static char *handle_restart_now(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1933 {
1934         switch (cmd) {
1935         case CLI_INIT:
1936                 e->command = "core restart now";
1937                 e->usage = 
1938                         "Usage: core restart now\n"
1939                         "       Causes Asterisk to hangup all calls and exec() itself performing a cold\n"
1940                         "       restart.\n";
1941                 return NULL;
1942         case CLI_GENERATE:
1943                 return NULL;
1944         }
1945
1946         if (a->argc != e->args)
1947                 return CLI_SHOWUSAGE;
1948         quit_handler(0, 0 /* not nicely */, 1 /* safely */, 1 /* restart */);
1949         return CLI_SUCCESS;
1950 }
1951
1952 static char *handle_restart_gracefully(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1953 {
1954         switch (cmd) {
1955         case CLI_INIT:
1956                 e->command = "core restart gracefully";
1957                 e->usage = 
1958                         "Usage: core restart gracefully\n"
1959                         "       Causes Asterisk to stop accepting new calls and exec() itself performing a cold\n"
1960                         "       restart when all active calls have ended.\n";
1961                 return NULL;
1962         case CLI_GENERATE:
1963                 return NULL;
1964         }
1965
1966         if (a->argc != e->args)
1967                 return CLI_SHOWUSAGE;
1968         quit_handler(0, 1 /* nicely */, 1 /* safely */, 1 /* restart */);
1969         return CLI_SUCCESS;
1970 }
1971
1972 static char *handle_restart_when_convenient(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1973 {
1974         switch (cmd) {
1975         case CLI_INIT:
1976                 e->command = "core restart when convenient";
1977                 e->usage = 
1978                         "Usage: core restart when convenient\n"
1979                         "       Causes Asterisk to perform a cold restart when all active calls have ended.\n";
1980                 return NULL;
1981         case CLI_GENERATE:
1982                 return NULL;
1983         }
1984
1985         if (a->argc != e->args)
1986                 return CLI_SHOWUSAGE;
1987         ast_cli(a->fd, "Waiting for inactivity to perform restart\n");
1988         quit_handler(0, 2 /* really nicely */, 1 /* safely */, 1 /* restart */);
1989         return CLI_SUCCESS;
1990 }
1991
1992 static char *handle_abort_shutdown(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1993 {
1994         switch (cmd) {
1995         case CLI_INIT:
1996                 e->command = "core abort shutdown";
1997                 e->usage = 
1998                         "Usage: core abort shutdown\n"
1999                         "       Causes Asterisk to abort an executing shutdown or restart, and resume normal\n"
2000                         "       call operations.\n";
2001                 return NULL;
2002         case CLI_GENERATE:
2003                 return NULL;
2004         }
2005
2006         if (a->argc != e->args)
2007                 return CLI_SHOWUSAGE;
2008         ast_cancel_shutdown();
2009         shuttingdown = 0;
2010         return CLI_SUCCESS;
2011 }
2012
2013 static char *handle_bang(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2014 {
2015         switch (cmd) {
2016         case CLI_INIT:
2017                 e->command = "!";
2018                 e->usage = 
2019                         "Usage: !<command>\n"
2020                         "       Executes a given shell command\n";
2021                 return NULL;
2022         case CLI_GENERATE:
2023                 return NULL;
2024         }
2025
2026         return CLI_SUCCESS;
2027 }
2028 static const char warranty_lines[] = {
2029         "\n"
2030         "                           NO WARRANTY\n"
2031         "\n"
2032         "BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY\n"
2033         "FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN\n"
2034         "OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES\n"
2035         "PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED\n"
2036         "OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\n"
2037         "MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS\n"
2038         "TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE\n"
2039         "PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,\n"
2040         "REPAIR OR CORRECTION.\n"
2041         "\n"
2042         "IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\n"
2043         "WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR\n"
2044         "REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,\n"
2045         "INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING\n"
2046         "OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED\n"
2047         "TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY\n"
2048         "YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER\n"
2049         "PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE\n"
2050         "POSSIBILITY OF SUCH DAMAGES.\n"
2051 };
2052
2053 static char *show_warranty(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2054 {
2055         switch (cmd) {
2056         case CLI_INIT:
2057                 e->command = "core show warranty";
2058                 e->usage = 
2059                         "Usage: core show warranty\n"
2060                         "       Shows the warranty (if any) for this copy of Asterisk.\n";
2061                 return NULL;
2062         case CLI_GENERATE:
2063                 return NULL;
2064         }
2065
2066         ast_cli(a->fd, "%s", warranty_lines);
2067
2068         return CLI_SUCCESS;
2069 }
2070
2071 static const char license_lines[] = {
2072         "\n"
2073         "This program is free software; you can redistribute it and/or modify\n"
2074         "it under the terms of the GNU General Public License version 2 as\n"
2075         "published by the Free Software Foundation.\n"
2076         "\n"
2077         "This program also contains components licensed under other licenses.\n"
2078         "They include:\n"
2079         "\n"
2080         "This program is distributed in the hope that it will be useful,\n"
2081         "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
2082         "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
2083         "GNU General Public License for more details.\n"
2084         "\n"
2085         "You should have received a copy of the GNU General Public License\n"
2086         "along with this program; if not, write to the Free Software\n"
2087         "Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n"
2088 };
2089
2090 static char *show_license(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2091 {
2092         switch (cmd) {
2093         case CLI_INIT:
2094                 e->command = "core show license";
2095                 e->usage = 
2096                         "Usage: core show license\n"
2097                         "       Shows the license(s) for this copy of Asterisk.\n";
2098                 return NULL;
2099         case CLI_GENERATE:
2100                 return NULL;
2101         }
2102
2103         ast_cli(a->fd, "%s", license_lines);
2104
2105         return CLI_SUCCESS;
2106 }
2107
2108 #define ASTERISK_PROMPT "*CLI> "
2109
2110 #define ASTERISK_PROMPT2 "%s*CLI> "
2111
2112 static struct ast_cli_entry cli_asterisk[] = {
2113         AST_CLI_DEFINE(handle_abort_shutdown, "Cancel a running shutdown"),
2114         AST_CLI_DEFINE(handle_stop_now, "Shut down Asterisk immediately"),
2115         AST_CLI_DEFINE(handle_stop_gracefully, "Gracefully shut down Asterisk"),
2116         AST_CLI_DEFINE(handle_stop_when_convenient, "Shut down Asterisk at empty call volume"),
2117         AST_CLI_DEFINE(handle_restart_now, "Restart Asterisk immediately"), 
2118         AST_CLI_DEFINE(handle_restart_gracefully, "Restart Asterisk gracefully"),
2119         AST_CLI_DEFINE(handle_restart_when_convenient, "Restart Asterisk at empty call volume"),
2120         AST_CLI_DEFINE(show_warranty, "Show the warranty (if any) for this copy of Asterisk"),
2121         AST_CLI_DEFINE(show_license, "Show the license(s) for this copy of Asterisk"),
2122         AST_CLI_DEFINE(handle_version, "Display version info"),
2123         AST_CLI_DEFINE(handle_bang, "Execute a shell command"),
2124 #if !defined(LOW_MEMORY)
2125         AST_CLI_DEFINE(handle_show_version_files, "List versions of files used to build Asterisk"),
2126         AST_CLI_DEFINE(handle_show_threads, "Show running threads"),
2127 #if defined(HAVE_SYSINFO) || defined(HAVE_SYSCTL)
2128         AST_CLI_DEFINE(handle_show_sysinfo, "Show System Information"),
2129 #endif
2130         AST_CLI_DEFINE(handle_show_profile, "Display profiling info"),
2131         AST_CLI_DEFINE(handle_show_settings, "Show some core settings"),
2132         AST_CLI_DEFINE(handle_clear_profile, "Clear profiling info"),
2133 #endif /* ! LOW_MEMORY */
2134 };
2135
2136 static int ast_el_read_char(EditLine *editline, char *cp)
2137 {
2138         int num_read = 0;
2139         int lastpos = 0;
2140         struct pollfd fds[2];
2141         int res;
2142         int max;
2143 #define EL_BUF_SIZE 512
2144         char buf[EL_BUF_SIZE];
2145
2146         for (;;) {
2147                 max = 1;
2148                 fds[0].fd = ast_consock;
2149                 fds[0].events = POLLIN;
2150                 if (!ast_opt_exec) {
2151                         fds[1].fd = STDIN_FILENO;
2152                         fds[1].events = POLLIN;
2153                         max++;
2154                 }
2155                 res = ast_poll(fds, max, -1);
2156                 if (res < 0) {
2157                         if (sig_flags.need_quit || sig_flags.need_quit_handler)
2158                                 break;
2159                         if (errno == EINTR)
2160                                 continue;
2161                         ast_log(LOG_ERROR, "poll failed: %s\n", strerror(errno));
2162                         break;
2163                 }
2164
2165                 if (!ast_opt_exec && fds[1].revents) {
2166                         num_read = read(STDIN_FILENO, cp, 1);
2167                         if (num_read < 1) {
2168                                 break;
2169                         } else 
2170                                 return (num_read);
2171                 }
2172                 if (fds[0].revents) {
2173                         char *tmp;
2174                         res = read(ast_consock, buf, sizeof(buf) - 1);
2175                         /* if the remote side disappears exit */
2176                         if (res < 1) {
2177                                 fprintf(stderr, "\nDisconnected from Asterisk server\n");
2178                                 if (!ast_opt_reconnect) {
2179                                         quit_handler(0, 0, 0, 0);
2180                                 } else {
2181                                         int tries;
2182                                         int reconnects_per_second = 20;
2183                                         fprintf(stderr, "Attempting to reconnect for 30 seconds\n");
2184                                         for (tries = 0; tries < 30 * reconnects_per_second; tries++) {
2185                                                 if (ast_tryconnect()) {
2186                                                         fprintf(stderr, "Reconnect succeeded after %.3f seconds\n", 1.0 / reconnects_per_second * tries);
2187                                                         printf("%s", term_quit());
2188                                                         WELCOME_MESSAGE;
2189                                                         if (!ast_opt_mute)
2190                                                                 fdsend(ast_consock, "logger mute silent");
2191                                                         else 
2192                                                                 printf("log and verbose output currently muted ('logger mute' to unmute)\n");
2193                                                         break;
2194                                                 } else
2195                                                         usleep(1000000 / reconnects_per_second);
2196                                         }
2197                                         if (tries >= 30 * reconnects_per_second) {
2198                                                 fprintf(stderr, "Failed to reconnect for 30 seconds.  Quitting.\n");
2199                                                 quit_handler(0, 0, 0, 0);
2200                                         }
2201                                 }
2202                         }
2203
2204                         buf[res] = '\0';
2205
2206                         /* Strip preamble from asynchronous events, too */
2207                         for (tmp = buf; *tmp; tmp++) {
2208                                 if (*tmp == 127) {
2209                                         memmove(tmp, tmp + 1, strlen(tmp));
2210                                         tmp--;
2211                                         res--;
2212                                 }
2213                         }
2214
2215                         /* Write over the CLI prompt */
2216                         if (!ast_opt_exec && !lastpos) {
2217                                 if (write(STDOUT_FILENO, "\r\e[0K", 5) < 0) {
2218                                 }
2219                         }
2220                         if (write(STDOUT_FILENO, buf, res) < 0) {
2221                         }
2222                         if ((res < EL_BUF_SIZE - 1) && ((buf[res-1] == '\n') || (buf[res-2] == '\n'))) {
2223                                 *cp = CC_REFRESH;
2224                                 return(1);
2225                         } else
2226                                 lastpos = 1;
2227                 }
2228         }
2229
2230         *cp = '\0';
2231         return (0);
2232 }
2233
2234 static struct ast_str *prompt = NULL;
2235
2236 static char *cli_prompt(EditLine *editline)
2237 {
2238         char tmp[100];
2239         char *pfmt;
2240         int color_used = 0;
2241         static int cli_prompt_changes = 0;
2242         char term_code[20];
2243         struct passwd *pw;
2244         struct group *gr;
2245
2246         if (prompt == NULL) {
2247                 prompt = ast_str_create(100);
2248         } else if (!cli_prompt_changes) {
2249                 return ast_str_buffer(prompt);
2250         } else {
2251                 ast_str_reset(prompt);
2252         }
2253
2254         if ((pfmt = getenv("ASTERISK_PROMPT"))) {
2255                 char *t = pfmt;
2256                 struct timeval ts = ast_tvnow();
2257                 while (*t != '\0') {
2258                         if (*t == '%') {
2259                                 char hostname[MAXHOSTNAMELEN] = "";
2260                                 int i, which;
2261                                 struct ast_tm tm = { 0, };
2262                                 int fgcolor = COLOR_WHITE, bgcolor = COLOR_BLACK;
2263
2264                                 t++;
2265                                 switch (*t) {
2266                                 case 'C': /* color */
2267                                         t++;
2268                                         if (sscanf(t, "%30d;%30d%n", &fgcolor, &bgcolor, &i) == 2) {
2269                                                 ast_str_append(&prompt, 0, "%s", term_color_code(term_code, fgcolor, bgcolor, sizeof(term_code)));
2270                                                 t += i - 1;
2271                                         } else if (sscanf(t, "%30d%n", &fgcolor, &i) == 1) {
2272                                                 ast_str_append(&prompt, 0, "%s", term_color_code(term_code, fgcolor, 0, sizeof(term_code)));
2273                                                 t += i - 1;
2274                                         }
2275
2276                                         /* If the color has been reset correctly, then there's no need to reset it later */
2277                                         color_used = ((fgcolor == COLOR_WHITE) && (bgcolor == COLOR_BLACK)) ? 0 : 1;
2278                                         break;
2279                                 case 'd': /* date */
2280                                         if (ast_localtime(&ts, &tm, NULL)) {
2281                                                 ast_strftime(tmp, sizeof(tmp), "%Y-%m-%d", &tm);
2282                                                 ast_str_append(&prompt, 0, "%s", tmp);
2283                                                 cli_prompt_changes++;
2284                                         }
2285                                         break;
2286                                 case 'g': /* group */
2287                                         if ((gr = getgrgid(getgid()))) {
2288                                                 ast_str_append(&prompt, 0, "%s", gr->gr_name);
2289                                         }
2290                                         break;
2291                                 case 'h': /* hostname */
2292                                         if (!gethostname(hostname, sizeof(hostname) - 1)) {
2293                                                 ast_str_append(&prompt, 0, "%s", hostname);
2294                                         } else {
2295                                                 ast_str_append(&prompt, 0, "%s", "localhost");
2296                                         }
2297                                         break;
2298                                 case 'H': /* short hostname */
2299                                         if (!gethostname(hostname, sizeof(hostname) - 1)) {
2300                                                 char *dotptr;
2301                                                 if ((dotptr = strchr(hostname, '.'))) {
2302                                                         *dotptr = '\0';
2303                                                 }
2304                                                 ast_str_append(&prompt, 0, "%s", hostname);
2305                                         } else {
2306                                                 ast_str_append(&prompt, 0, "%s", "localhost");
2307                                         }
2308                                         break;
2309 #ifdef HAVE_GETLOADAVG
2310                                 case 'l': /* load avg */
2311                                         t++;
2312                                         if (sscanf(t, "%30d", &which) == 1 && which > 0 && which <= 3) {
2313                                                 double list[3];
2314                                                 getloadavg(list, 3);
2315                                                 ast_str_append(&prompt, 0, "%.2f", list[which - 1]);
2316                                                 cli_prompt_changes++;
2317                                         }
2318                                         break;
2319 #endif
2320                                 case 's': /* Asterisk system name (from asterisk.conf) */
2321                                         ast_str_append(&prompt, 0, "%s", ast_config_AST_SYSTEM_NAME);
2322                                         break;
2323                                 case 't': /* time */
2324                                         if (ast_localtime(&ts, &tm, NULL)) {
2325                                                 ast_strftime(tmp, sizeof(tmp), "%H:%M:%S", &tm);
2326                                                 ast_str_append(&prompt, 0, "%s", tmp);
2327                                                 cli_prompt_changes++;
2328                                         }
2329                                         break;
2330                                 case 'u': /* username */
2331                                         if ((pw = getpwuid(getuid()))) {
2332                                                 ast_str_append(&prompt, 0, "%s", pw->pw_name);
2333                                         }
2334                                         break;
2335                                 case '#': /* process console or remote? */
2336                                         ast_str_append(&prompt, 0, "%c", ast_opt_remote ? '>' : '#');
2337                                         break;
2338                                 case '%': /* literal % */
2339                                         ast_str_append(&prompt, 0, "%c", '%');
2340                                         break;
2341                                 case '\0': /* % is last character - prevent bug */
2342                                         t--;
2343                                         break;
2344                                 }
2345                         } else {
2346                                 ast_str_append(&prompt, 0, "%c", *t);
2347                         }
2348                         t++;
2349                 }
2350                 if (color_used) {
2351                         /* Force colors back to normal at end */
2352                         ast_str_append(&prompt, 0, "%s", term_color_code(term_code, 0, 0, sizeof(term_code)));
2353                 }
2354         } else if (remotehostname) {
2355                 ast_str_set(&prompt, 0, ASTERISK_PROMPT2, remotehostname);
2356         } else {
2357                 ast_str_set(&prompt, 0, "%s", ASTERISK_PROMPT);
2358         }
2359
2360         return ast_str_buffer(prompt);  
2361 }
2362
2363 static char **ast_el_strtoarr(char *buf)
2364 {
2365         char **match_list = NULL, **match_list_tmp, *retstr;
2366         size_t match_list_len;
2367         int matches = 0;
2368
2369         match_list_len = 1;
2370         while ( (retstr = strsep(&buf, " ")) != NULL) {
2371
2372                 if (!strcmp(retstr, AST_CLI_COMPLETE_EOF))
2373                         break;
2374                 if (matches + 1 >= match_list_len) {
2375                         match_list_len <<= 1;
2376                         if ((match_list_tmp = ast_realloc(match_list, match_list_len * sizeof(char *)))) {
2377                                 match_list = match_list_tmp;
2378                         } else {
2379                                 if (match_list)
2380                                         ast_free(match_list);
2381                                 return (char **) NULL;
2382                         }
2383                 }
2384
2385                 match_list[matches++] = ast_strdup(retstr);
2386         }
2387
2388         if (!match_list)
2389                 return (char **) NULL;
2390
2391         if (matches >= match_list_len) {
2392                 if ((match_list_tmp = ast_realloc(match_list, (match_list_len + 1) * sizeof(char *)))) {
2393                         match_list = match_list_tmp;
2394                 } else {
2395                         if (match_list)
2396                                 ast_free(match_list);
2397                         return (char **) NULL;
2398                 }
2399         }
2400
2401         match_list[matches] = (char *) NULL;
2402
2403         return match_list;
2404 }
2405
2406 static int ast_el_sort_compare(const void *i1, const void *i2)
2407 {
2408         char *s1, *s2;
2409
2410         s1 = ((char **)i1)[0];
2411         s2 = ((char **)i2)[0];
2412
2413         return strcasecmp(s1, s2);
2414 }
2415
2416 static int ast_cli_display_match_list(char **matches, int len, int max)
2417 {
2418         int i, idx, limit, count;
2419         int screenwidth = 0;
2420         int numoutput = 0, numoutputline = 0;
2421
2422         screenwidth = ast_get_termcols(STDOUT_FILENO);
2423
2424         /* find out how many entries can be put on one line, with two spaces between strings */
2425         limit = screenwidth / (max + 2);
2426         if (limit == 0)
2427                 limit = 1;
2428
2429         /* how many lines of output */
2430         count = len / limit;
2431         if (count * limit < len)
2432                 count++;
2433
2434         idx = 1;
2435
2436         qsort(&matches[0], (size_t)(len), sizeof(char *), ast_el_sort_compare);
2437
2438         for (; count > 0; count--) {
2439                 numoutputline = 0;
2440                 for (i = 0; i < limit && matches[idx]; i++, idx++) {
2441
2442                         /* Don't print dupes */
2443                         if ( (matches[idx+1] != NULL && strcmp(matches[idx], matches[idx+1]) == 0 ) ) {
2444                                 i--;
2445                                 ast_free(matches[idx]);
2446                                 matches[idx] = NULL;
2447                                 continue;
2448                         }
2449
2450                         numoutput++;
2451                         numoutputline++;
2452                         fprintf(stdout, "%-*s  ", max, matches[idx]);
2453                         ast_free(matches[idx]);
2454                         matches[idx] = NULL;
2455                 }
2456                 if (numoutputline > 0)
2457                         fprintf(stdout, "\n");
2458         }
2459
2460         return numoutput;
2461 }
2462
2463
2464 static char *cli_complete(EditLine *editline, int ch)
2465 {
2466         int len = 0;
2467         char *ptr;
2468         int nummatches = 0;
2469         char **matches;
2470         int retval = CC_ERROR;
2471         char buf[2048], savechr;
2472         int res;
2473
2474         LineInfo *lf = (LineInfo *)el_line(editline);
2475
2476         savechr = *(char *)lf->cursor;
2477         *(char *)lf->cursor = '\0';
2478         ptr = (char *)lf->cursor;
2479         if (ptr) {
2480                 while (ptr > lf->buffer) {
2481                         if (isspace(*ptr)) {
2482                                 ptr++;
2483                                 break;
2484                         }
2485                         ptr--;
2486                 }
2487         }
2488
2489         len = lf->cursor - ptr;
2490
2491         if (ast_opt_remote) {
2492                 snprintf(buf, sizeof(buf), "_COMMAND NUMMATCHES \"%s\" \"%s\"", lf->buffer, ptr); 
2493                 fdsend(ast_consock, buf);
2494                 res = read(ast_consock, buf, sizeof(buf) - 1);
2495                 buf[res] = '\0';
2496                 nummatches = atoi(buf);
2497
2498                 if (nummatches > 0) {
2499                         char *mbuf;
2500                         int mlen = 0, maxmbuf = 2048;
2501                         /* Start with a 2048 byte buffer */                     
2502                         if (!(mbuf = ast_malloc(maxmbuf))) {
2503                                 lf->cursor[0] = savechr;
2504                                 return (char *)(CC_ERROR);
2505                         }
2506                         snprintf(buf, sizeof(buf), "_COMMAND MATCHESARRAY \"%s\" \"%s\"", lf->buffer, ptr); 
2507                         fdsend(ast_consock, buf);
2508                         res = 0;
2509                         mbuf[0] = '\0';
2510                         while (!strstr(mbuf, AST_CLI_COMPLETE_EOF) && res != -1) {
2511                                 if (mlen + 1024 > maxmbuf) {
2512                                         /* Every step increment buffer 1024 bytes */
2513                                         maxmbuf += 1024;                                        
2514                                         if (!(mbuf = ast_realloc(mbuf, maxmbuf))) {
2515                                                 lf->cursor[0] = savechr;
2516                                                 return (char *)(CC_ERROR);
2517                                         }
2518                                 }
2519                                 /* Only read 1024 bytes at a time */
2520                                 res = read(ast_consock, mbuf + mlen, 1024);
2521                                 if (res > 0)
2522                                         mlen += res;
2523                         }
2524                         mbuf[mlen] = '\0';
2525
2526                         matches = ast_el_strtoarr(mbuf);
2527                         ast_free(mbuf);
2528                 } else
2529                         matches = (char **) NULL;
2530         } else {
2531                 char **p, *oldbuf=NULL;
2532                 nummatches = 0;
2533                 matches = ast_cli_completion_matches((char *)lf->buffer,ptr);
2534                 for (p = matches; p && *p; p++) {
2535                         if (!oldbuf || strcmp(*p,oldbuf))
2536                                 nummatches++;
2537                         oldbuf = *p;
2538                 }
2539         }
2540
2541         if (matches) {
2542                 int i;
2543                 int matches_num, maxlen, match_len;
2544
2545                 if (matches[0][0] != '\0') {
2546                         el_deletestr(editline, (int) len);
2547                         el_insertstr(editline, matches[0]);
2548                         retval = CC_REFRESH;
2549                 }
2550
2551                 if (nummatches == 1) {
2552                         /* Found an exact match */
2553                         el_insertstr(editline, " ");
2554                         retval = CC_REFRESH;
2555                 } else {
2556                         /* Must be more than one match */
2557                         for (i = 1, maxlen = 0; matches[i]; i++) {
2558                                 match_len = strlen(matches[i]);
2559                                 if (match_len > maxlen)
2560                                         maxlen = match_len;
2561                         }
2562                         matches_num = i - 1;
2563                         if (matches_num >1) {
2564                                 fprintf(stdout, "\n");
2565                                 ast_cli_display_match_list(matches, nummatches, maxlen);
2566                                 retval = CC_REDISPLAY;
2567                         } else { 
2568                                 el_insertstr(editline," ");
2569                                 retval = CC_REFRESH;
2570                         }
2571                 }
2572                 for (i = 0; matches[i]; i++)
2573                         ast_free(matches[i]);
2574                 ast_free(matches);
2575         }
2576
2577         lf->cursor[0] = savechr;
2578
2579         return (char *)(long)retval;
2580 }
2581
2582 static int ast_el_initialize(void)
2583 {
2584         HistEvent ev;
2585         char *editor, *editrc = getenv("EDITRC");
2586
2587         if (!(editor = getenv("AST_EDITMODE"))) {
2588                 if (!(editor = getenv("AST_EDITOR"))) {
2589                         editor = "emacs";
2590                 }
2591         }
2592
2593         if (el != NULL)
2594                 el_end(el);
2595         if (el_hist != NULL)
2596                 history_end(el_hist);
2597
2598         el = el_init("asterisk", stdin, stdout, stderr);
2599         el_set(el, EL_PROMPT, cli_prompt);
2600
2601         el_set(el, EL_EDITMODE, 1);             
2602         el_set(el, EL_EDITOR, editor);
2603         el_hist = history_init();
2604         if (!el || !el_hist)
2605                 return -1;
2606
2607         /* setup history with 100 entries */
2608         history(el_hist, &ev, H_SETSIZE, 100);
2609
2610         el_set(el, EL_HIST, history, el_hist);
2611
2612         el_set(el, EL_ADDFN, "ed-complete", "Complete argument", cli_complete);
2613         /* Bind <tab> to command completion */
2614         el_set(el, EL_BIND, "^I", "ed-complete", NULL);
2615         /* Bind ? to command completion */
2616         el_set(el, EL_BIND, "?", "ed-complete", NULL);
2617         /* Bind ^D to redisplay */
2618         el_set(el, EL_BIND, "^D", "ed-redisplay", NULL);
2619         /* Bind Delete to delete char left */
2620         el_set(el, EL_BIND, "\\e[3~", "ed-delete-next-char", NULL);
2621         /* Bind Home and End to move to line start and end */
2622         el_set(el, EL_BIND, "\\e[1~", "ed-move-to-beg", NULL);
2623         el_set(el, EL_BIND, "\\e[4~", "ed-move-to-end", NULL);
2624         /* Bind C-left and C-right to move by word (not all terminals) */
2625         el_set(el, EL_BIND, "\\eOC", "vi-next-word", NULL);
2626         el_set(el, EL_BIND, "\\eOD", "vi-prev-word", NULL);
2627
2628         if (editrc) {
2629                 el_source(el, editrc);
2630         }
2631
2632         return 0;
2633 }
2634
2635 #define MAX_HISTORY_COMMAND_LENGTH 256
2636
2637 static int ast_el_add_history(char *buf)
2638 {
2639         HistEvent ev;
2640
2641         if (el_hist == NULL || el == NULL)
2642                 ast_el_initialize();
2643         if (strlen(buf) > (MAX_HISTORY_COMMAND_LENGTH - 1))
2644                 return 0;
2645         return (history(el_hist, &ev, H_ENTER, ast_strip(ast_strdupa(buf))));
2646 }
2647
2648 static int ast_el_write_history(char *filename)
2649 {
2650         HistEvent ev;
2651
2652         if (el_hist == NULL || el == NULL)
2653                 ast_el_initialize();
2654
2655         return (history(el_hist, &ev, H_SAVE, filename));
2656 }
2657
2658 static int ast_el_read_history(char *filename)
2659 {
2660         char buf[MAX_HISTORY_COMMAND_LENGTH];
2661         FILE *f;
2662         int ret = -1;
2663
2664         if (el_hist == NULL || el == NULL)
2665                 ast_el_initialize();
2666
2667         if ((f = fopen(filename, "r")) == NULL)
2668                 return ret;
2669
2670         while (!feof(f)) {
2671                 if (!fgets(buf, sizeof(buf), f))
2672                         break;
2673                 if (!strcmp(buf, "_HiStOrY_V2_\n"))
2674                         continue;
2675                 if (ast_all_zeros(buf))
2676                         continue;
2677                 if ((ret = ast_el_add_history(buf)) == -1)
2678                         break;
2679         }
2680         fclose(f);
2681
2682         return ret;
2683 }
2684
2685 static void ast_remotecontrol(char *data)
2686 {
2687         char buf[80];
2688         int res;
2689         char filename[80] = "";
2690         char *hostname;
2691         char *cpid;
2692         char *version;
2693         int pid;
2694         char *stringp = NULL;
2695
2696         char *ebuf;
2697         int num = 0;
2698
2699         memset(&sig_flags, 0, sizeof(sig_flags));
2700         signal(SIGINT, __remote_quit_handler);
2701         signal(SIGTERM, __remote_quit_handler);
2702         signal(SIGHUP, __remote_quit_handler);
2703
2704         if (read(ast_consock, buf, sizeof(buf)) < 0) {
2705                 ast_log(LOG_ERROR, "read() failed: %s\n", strerror(errno));
2706                 return;
2707         }
2708         if (data) {
2709                 char prefix[] = "cli quit after ";
2710                 char *tmp = alloca(strlen(data) + strlen(prefix) + 1);
2711                 sprintf(tmp, "%s%s", prefix, data);
2712                 if (write(ast_consock, tmp, strlen(tmp) + 1) < 0) {
2713                         ast_log(LOG_ERROR, "write() failed: %s\n", strerror(errno));
2714                         if (sig_flags.need_quit || sig_flags.need_quit_handler) {
2715                                 return;
2716                         }
2717                 }
2718         }
2719         stringp = buf;
2720         hostname = strsep(&stringp, "/");
2721         cpid = strsep(&stringp, "/");
2722         version = strsep(&stringp, "\n");
2723         if (!version)
2724                 version = "<Version Unknown>";
2725         stringp = hostname;
2726         strsep(&stringp, ".");
2727         if (cpid)
2728                 pid = atoi(cpid);
2729         else
2730                 pid = -1;
2731         if (!data) {
2732                 char tmp[80];
2733                 snprintf(tmp, sizeof(tmp), "core set verbose atleast %d", option_verbose);
2734                 fdsend(ast_consock, tmp);
2735                 snprintf(tmp, sizeof(tmp), "core set debug atleast %d", option_debug);
2736                 fdsend(ast_consock, tmp);
2737                 if (!ast_opt_mute)
2738                         fdsend(ast_consock, "logger mute silent");
2739                 else 
2740                         printf("log and verbose output currently muted ('logger mute' to unmute)\n");
2741         }
2742
2743         if (ast_opt_exec && data) {  /* hack to print output then exit if asterisk -rx is used */
2744                 struct pollfd fds;
2745                 fds.fd = ast_consock;
2746                 fds.events = POLLIN;
2747                 fds.revents = 0;
2748                 while (ast_poll(&fds, 1, 60000) > 0) {
2749                         char buffer[512] = "", *curline = buffer, *nextline;
2750                         int not_written = 1;
2751
2752                         if (sig_flags.need_quit || sig_flags.need_quit_handler) {
2753                                 break;
2754                         }
2755
2756                         if (read(ast_consock, buffer, sizeof(buffer) - 1) <= 0) {
2757                                 break;
2758                         }
2759
2760                         do {
2761                                 if ((nextline = strchr(curline, '\n'))) {
2762                                         nextline++;
2763                                 } else {
2764                                         nextline = strchr(curline, '\0');
2765                                 }
2766
2767                                 /* Skip verbose lines */
2768                                 if (*curline != 127) {
2769                                         not_written = 0;
2770                                         if (write(STDOUT_FILENO, curline, nextline - curline) < 0) {
2771                                                 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
2772                                         }
2773                                 }
2774                                 curline = nextline;
2775                         } while (!ast_strlen_zero(curline));
2776
2777                         /* No non-verbose output in 60 seconds. */
2778                         if (not_written) {
2779                                 break;
2780                         }
2781                 }
2782                 return;
2783         }
2784
2785         ast_verbose("Connected to Asterisk %s currently running on %s (pid = %d)\n", version, hostname, pid);
2786         remotehostname = hostname;
2787         if (getenv("HOME")) 
2788                 snprintf(filename, sizeof(filename), "%s/.asterisk_history", getenv("HOME"));
2789         if (el_hist == NULL || el == NULL)
2790                 ast_el_initialize();
2791
2792         el_set(el, EL_GETCFN, ast_el_read_char);
2793
2794         if (!ast_strlen_zero(filename))
2795                 ast_el_read_history(filename);
2796
2797         for (;;) {
2798                 ebuf = (char *)el_gets(el, &num);
2799
2800                 if (sig_flags.need_quit || sig_flags.need_quit_handler) {
2801                         break;
2802                 }
2803
2804                 if (!ebuf && write(1, "", 1) < 0)
2805                         break;
2806
2807                 if (!ast_strlen_zero(ebuf)) {
2808                         if (ebuf[strlen(ebuf)-1] == '\n')
2809                                 ebuf[strlen(ebuf)-1] = '\0';
2810                         if (!remoteconsolehandler(ebuf)) {
2811                                 /* Strip preamble from output */
2812                                 char *temp;
2813                                 for (temp = ebuf; *temp; temp++) {
2814                                         if (*temp == 127) {
2815                                                 memmove(temp, temp + 1, strlen(temp));
2816                                                 temp--;
2817                                         }
2818                                 }
2819                                 res = write(ast_consock, ebuf, strlen(ebuf) + 1);
2820                                 if (res < 1) {
2821                                         ast_log(LOG_WARNING, "Unable to write: %s\n", strerror(errno));
2822                                         break;
2823                                 }
2824                         }
2825                 }
2826         }
2827         printf("\nDisconnected from Asterisk server\n");
2828 }
2829
2830 static int show_version(void)
2831 {
2832         printf("Asterisk %s\n", ast_get_version());
2833         return 0;
2834 }
2835
2836 static int show_cli_help(void) {
2837         printf("Asterisk %s, Copyright (C) 1999 - 2010, Digium, Inc. and others.\n", ast_get_version());
2838         printf("Usage: asterisk [OPTIONS]\n");
2839         printf("Valid Options:\n");
2840         printf("   -V              Display version number and exit\n");
2841         printf("   -C <configfile> Use an alternate configuration file\n");
2842         printf("   -G <group>      Run as a group other than the caller\n");
2843         printf("   -U <user>       Run as a user other than the caller\n");
2844         printf("   -c              Provide console CLI\n");
2845         printf("   -d              Enable extra debugging\n");
2846 #if HAVE_WORKING_FORK
2847         printf("   -f              Do not fork\n");
2848         printf("   -F              Always fork\n");
2849 #endif
2850         printf("   -g              Dump core in case of a crash\n");
2851         printf("   -h              This help screen\n");
2852         printf("   -i              Initialize crypto keys at startup\n");
2853         printf("   -I              Enable internal timing if DAHDI timer is available\n");
2854         printf("   -L <load>       Limit the maximum load average before rejecting new calls\n");
2855         printf("   -M <value>      Limit the maximum number of calls to the specified value\n");
2856         printf("   -m              Mute debugging and console output on the console\n");
2857         printf("   -n              Disable console colorization\n");
2858         printf("   -p              Run as pseudo-realtime thread\n");
2859         printf("   -q              Quiet mode (suppress output)\n");
2860         printf("   -r              Connect to Asterisk on this machine\n");
2861         printf("   -R              Same as -r, except attempt to reconnect if disconnected\n");
2862         printf("   -s <socket>     Connect to Asterisk via socket <socket> (only valid with -r)\n");
2863         printf("   -t              Record soundfiles in /var/tmp and move them where they\n");
2864         printf("                   belong after they are done\n");
2865         printf("   -T              Display the time in [Mmm dd hh:mm:ss] format for each line\n");
2866         printf("                   of output to the CLI\n");
2867         printf("   -v              Increase verbosity (multiple v's = more verbose)\n");
2868         printf("   -x <cmd>        Execute command <cmd> (only valid with -r)\n");
2869         printf("   -X              Execute includes by default (allows #exec in asterisk.conf)\n");
2870         printf("   -W              Adjust terminal colors to compensate for a light background\n");
2871         printf("\n");
2872         return 0;
2873 }
2874
2875 static void ast_readconfig(void) 
2876 {
2877         struct ast_config *cfg;
2878         struct ast_variable *v;
2879         char *config = DEFAULT_CONFIG_FILE;
2880         char hostname[MAXHOSTNAMELEN] = "";
2881         struct ast_flags config_flags = { CONFIG_FLAG_NOREALTIME };
2882         struct {
2883                 unsigned int dbdir:1;
2884                 unsigned int keydir:1;
2885         } found = { 0, 0 };
2886
2887         if (ast_opt_override_config) {
2888                 cfg = ast_config_load2(ast_config_AST_CONFIG_FILE, "" /* core, can't reload */, config_flags);
2889                 if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEUNCHANGED || cfg == CONFIG_STATUS_FILEINVALID)
2890                         ast_log(LOG_WARNING, "Unable to open specified master config file '%s', using built-in defaults\n", ast_config_AST_CONFIG_FILE);
2891         } else 
2892                 cfg = ast_config_load2(config, "" /* core, can't reload */, config_flags);
2893
2894         /* init with buildtime config */
2895         ast_copy_string(cfg_paths.config_dir, DEFAULT_CONFIG_DIR, sizeof(cfg_paths.config_dir));
2896         ast_copy_string(cfg_paths.spool_dir, DEFAULT_SPOOL_DIR, sizeof(cfg_paths.spool_dir));
2897         ast_copy_string(cfg_paths.module_dir, DEFAULT_MODULE_DIR, sizeof(cfg_paths.module_dir));
2898         snprintf(cfg_paths.monitor_dir, sizeof(cfg_paths.monitor_dir), "%s/monitor", cfg_paths.spool_dir);
2899         ast_copy_string(cfg_paths.var_dir, DEFAULT_VAR_DIR, sizeof(cfg_paths.var_dir));
2900         ast_copy_string(cfg_paths.data_dir, DEFAULT_DATA_DIR, sizeof(cfg_paths.data_dir));
2901         ast_copy_string(cfg_paths.log_dir, DEFAULT_LOG_DIR, sizeof(cfg_paths.log_dir));
2902         ast_copy_string(cfg_paths.agi_dir, DEFAULT_AGI_DIR, sizeof(cfg_paths.agi_dir));
2903         ast_copy_string(cfg_paths.db_path, DEFAULT_DB, sizeof(cfg_paths.db_path));
2904         ast_copy_string(cfg_paths.key_dir, DEFAULT_KEY_DIR, sizeof(cfg_paths.key_dir));
2905         ast_copy_string(cfg_paths.pid_path, DEFAULT_PID, sizeof(cfg_paths.pid_path));
2906         ast_copy_string(cfg_paths.socket_path, DEFAULT_SOCKET, sizeof(cfg_paths.socket_path));
2907         ast_copy_string(cfg_paths.run_dir, DEFAULT_RUN_DIR, sizeof(cfg_paths.run_dir));
2908
2909         ast_set_default_eid(&ast_eid_default);
2910
2911         /* no asterisk.conf? no problem, use buildtime config! */
2912         if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEUNCHANGED || cfg == CONFIG_STATUS_FILEINVALID) {
2913                 return;
2914         }
2915
2916         for (v = ast_variable_browse(cfg, "files"); v; v = v->next) {
2917                 if (!strcasecmp(v->name, "astctlpermissions"))
2918                         ast_copy_string(ast_config_AST_CTL_PERMISSIONS, v->value, sizeof(ast_config_AST_CTL_PERMISSIONS));
2919                 else if (!strcasecmp(v->name, "astctlowner"))
2920                         ast_copy_string(ast_config_AST_CTL_OWNER, v->value, sizeof(ast_config_AST_CTL_OWNER));
2921                 else if (!strcasecmp(v->name, "astctlgroup"))
2922                         ast_copy_string(ast_config_AST_CTL_GROUP, v->value, sizeof(ast_config_AST_CTL_GROUP));
2923                 else if (!strcasecmp(v->name, "astctl"))
2924                         ast_copy_string(ast_config_AST_CTL, v->value, sizeof(ast_config_AST_CTL));
2925         }
2926
2927         for (v = ast_variable_browse(cfg, "directories"); v; v = v->next) {
2928                 if (!strcasecmp(v->name, "astetcdir")) {
2929                         ast_copy_string(cfg_paths.config_dir, v->value, sizeof(cfg_paths.config_dir));
2930                 } else if (!strcasecmp(v->name, "astspooldir")) {
2931                         ast_copy_string(cfg_paths.spool_dir, v->value, sizeof(cfg_paths.spool_dir));
2932                         snprintf(cfg_paths.monitor_dir, sizeof(cfg_paths.monitor_dir), "%s/monitor", v->value);
2933                 } else if (!strcasecmp(v->name, "astvarlibdir")) {
2934                         ast_copy_string(cfg_paths.var_dir, v->value, sizeof(cfg_paths.var_dir));
2935                         if (!found.dbdir)
2936                                 snprintf(cfg_paths.db_path, sizeof(cfg_paths.db_path), "%s/astdb", v->value);
2937                 } else if (!strcasecmp(v->name, "astdbdir")) {
2938                         snprintf(cfg_paths.db_path, sizeof(cfg_paths.db_path), "%s/astdb", v->value);
2939                         found.dbdir = 1;
2940                 } else if (!strcasecmp(v->name, "astdatadir")) {
2941                         ast_copy_string(cfg_paths.data_dir, v->value, sizeof(cfg_paths.data_dir));
2942                         if (!found.keydir)
2943                                 snprintf(cfg_paths.key_dir, sizeof(cfg_paths.key_dir), "%s/keys", v->value);
2944                 } else if (!strcasecmp(v->name, "astkeydir")) {
2945                         snprintf(cfg_paths.key_dir, sizeof(cfg_paths.key_dir), "%s/keys", v->value);
2946                         found.keydir = 1;
2947                 } else if (!strcasecmp(v->name, "astlogdir")) {
2948                         ast_copy_string(cfg_paths.log_dir, v->value, sizeof(cfg_paths.log_dir));
2949                 } else if (!strcasecmp(v->name, "astagidir")) {
2950                         ast_copy_string(cfg_paths.agi_dir, v->value, sizeof(cfg_paths.agi_dir));
2951                 } else if (!strcasecmp(v->name, "astrundir")) {
2952                         snprintf(cfg_paths.pid_path, sizeof(cfg_paths.pid_path), "%s/%s", v->value, "asterisk.pid");
2953                         snprintf(cfg_paths.socket_path, sizeof(cfg_paths.socket_path), "%s/%s", v->value, ast_config_AST_CTL);
2954                         ast_copy_string(cfg_paths.run_dir, v->value, sizeof(cfg_paths.run_dir));
2955                 } else if (!strcasecmp(v->name, "astmoddir")) {
2956                         ast_copy_string(cfg_paths.module_dir, v->value, sizeof(cfg_paths.module_dir));
2957                 }
2958         }
2959
2960         for (v = ast_variable_browse(cfg, "options"); v; v = v->next) {
2961                 /* verbose level (-v at startup) */
2962                 if (!strcasecmp(v->name, "verbose")) {
2963                         option_verbose = atoi(v->value);
2964                 /* whether or not to force timestamping in CLI verbose output. (-T at startup) */
2965                 } else if (!strcasecmp(v->name, "timestamp")) {
2966                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_TIMESTAMP);
2967                 /* whether or not to support #exec in config files */
2968                 } else if (!strcasecmp(v->name, "execincludes")) {
2969                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_EXEC_INCLUDES);
2970                 /* debug level (-d at startup) */
2971                 } else if (!strcasecmp(v->name, "debug")) {
2972                         option_debug = 0;
2973                         if (sscanf(v->value, "%30d", &option_debug) != 1) {
2974                                 option_debug = ast_true(v->value);
2975                         }
2976 #if HAVE_WORKING_FORK
2977                 /* Disable forking (-f at startup) */
2978                 } else if (!strcasecmp(v->name, "nofork")) {
2979                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_NO_FORK);
2980                 /* Always fork, even if verbose or debug are enabled (-F at startup) */
2981                 } else if (!strcasecmp(v->name, "alwaysfork")) {
2982                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_ALWAYS_FORK);
2983 #endif
2984                 /* Run quietly (-q at startup ) */
2985                 } else if (!strcasecmp(v->name, "quiet")) {
2986                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_QUIET);
2987                 /* Run as console (-c at startup, implies nofork) */
2988                 } else if (!strcasecmp(v->name, "console")) {
2989                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_NO_FORK | AST_OPT_FLAG_CONSOLE);
2990                 /* Run with high priority if the O/S permits (-p at startup) */
2991                 } else if (!strcasecmp(v->name, "highpriority")) {
2992                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_HIGH_PRIORITY);
2993                 /* Initialize RSA auth keys (IAX2) (-i at startup) */
2994                 } else if (!strcasecmp(v->name, "initcrypto")) {
2995                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_INIT_KEYS);
2996                 /* Disable ANSI colors for console (-c at startup) */
2997                 } else if (!strcasecmp(v->name, "nocolor")) {
2998                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_NO_COLOR);
2999                 /* Disable some usage warnings for picky people :p */
3000                 } else if (!strcasecmp(v->name, "dontwarn")) {
3001                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_DONT_WARN);
3002                 /* Dump core in case of crash (-g) */
3003                 } else if (!strcasecmp(v->name, "dumpcore")) {
3004                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_DUMP_CORE);
3005                 /* Cache recorded sound files to another directory during recording */
3006                 } else if (!strcasecmp(v->name, "cache_record_files")) {
3007                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_CACHE_RECORD_FILES);
3008                 /* Specify cache directory */
3009                 }  else if (!strcasecmp(v->name, "record_cache_dir")) {
3010                         ast_copy_string(record_cache_dir, v->value, AST_CACHE_DIR_LEN);
3011                 /* Build transcode paths via SLINEAR, instead of directly */
3012                 } else if (!strcasecmp(v->name, "transcode_via_sln")) {
3013                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_TRANSCODE_VIA_SLIN);
3014                 /* Transmit SLINEAR silence while a channel is being recorded or DTMF is being generated on a channel */
3015                 } else if (!strcasecmp(v->name, "transmit_silence_during_record") || !strcasecmp(v->name, "transmit_silence")) {
3016                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_TRANSMIT_SILENCE);
3017                 /* Enable internal timing */
3018                 } else if (!strcasecmp(v->name, "internal_timing")) {
3019                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_INTERNAL_TIMING);
3020                 } else if (!strcasecmp(v->name, "maxcalls")) {
3021                         if ((sscanf(v->value, "%30d", &option_maxcalls) != 1) || (option_maxcalls < 0)) {
3022                                 option_maxcalls = 0;
3023                         }
3024                 } else if (!strcasecmp(v->name, "maxload")) {
3025                         double test[1];
3026
3027                         if (getloadavg(test, 1) == -1) {
3028                                 ast_log(LOG_ERROR, "Cannot obtain load average on this system. 'maxload' option disabled.\n");
3029                                 option_maxload = 0.0;
3030                         } else if ((sscanf(v->value, "%30lf", &option_maxload) != 1) || (option_maxload < 0.0)) {
3031                                 option_maxload = 0.0;
3032                         }
3033                 /* Set the maximum amount of open files */
3034                 } else if (!strcasecmp(v->name, "maxfiles")) {
3035                         option_maxfiles = atoi(v->value);
3036                         set_ulimit(option_maxfiles);
3037                 /* What user to run as */
3038                 } else if (!strcasecmp(v->name, "runuser")) {
3039                         ast_copy_string(cfg_paths.run_user, v->value, sizeof(cfg_paths.run_user));
3040                 /* What group to run as */
3041                 } else if (!strcasecmp(v->name, "rungroup")) {
3042                         ast_copy_string(cfg_paths.run_group, v->value, sizeof(cfg_paths.run_group));
3043                 } else if (!strcasecmp(v->name, "systemname")) {
3044                         ast_copy_string(cfg_paths.system_name, v->value, sizeof(cfg_paths.system_name));
3045                 } else if (!strcasecmp(v->name, "autosystemname")) {
3046                         if (ast_true(v->value)) {
3047                                 if (!gethostname(hostname, sizeof(hostname) - 1))
3048                                         ast_copy_string(cfg_paths.system_name, hostname, sizeof(cfg_paths.system_name));
3049                                 else {
3050                                         if (ast_strlen_zero(ast_config_AST_SYSTEM_NAME)){
3051                                                 ast_copy_string(cfg_paths.system_name, "localhost", sizeof(cfg_paths.system_name));
3052                                         }
3053                                         ast_log(LOG_ERROR, "Cannot obtain hostname for this system.  Using '%s' instead.\n", ast_config_AST_SYSTEM_NAME);
3054                                 }
3055                         }
3056                 } else if (!strcasecmp(v->name, "languageprefix")) {
3057                         ast_language_is_prefix = ast_true(v->value);
3058                 } else if (!strcasecmp(v->name, "defaultlanguage")) {
3059                         ast_copy_string(defaultlanguage, v->value, MAX_LANGUAGE);
3060                 } else if (!strcasecmp(v->name, "lockmode")) {
3061                         if (!strcasecmp(v->value, "lockfile")) {
3062                                 ast_set_lock_type(AST_LOCK_TYPE_LOCKFILE);
3063                         } else if (!strcasecmp(v->value, "flock")) {
3064                                 ast_set_lock_type(AST_LOCK_TYPE_FLOCK);
3065                         } else {
3066                                 ast_log(LOG_WARNING, "'%s' is not a valid setting for the lockmode option, "
3067                                         "defaulting to 'lockfile'\n", v->value);
3068                                 ast_set_lock_type(AST_LOCK_TYPE_LOCKFILE);
3069                         }
3070 #if defined(HAVE_SYSINFO)
3071                 } else if (!strcasecmp(v->name, "minmemfree")) {
3072                         /* specify the minimum amount of free memory to retain.  Asterisk should stop accepting new calls
3073                          * if the amount of free memory falls below this watermark */
3074                         if ((sscanf(v->value, "%30ld", &option_minmemfree) != 1) || (option_minmemfree < 0)) {
3075                                 option_minmemfree = 0;
3076                         }
3077 #endif
3078                 } else if (!strcasecmp(v->name, "entityid")) {
3079                         struct ast_eid tmp_eid;
3080                         if (!ast_str_to_eid(&tmp_eid, v->value)) {
3081                                 ast_verbose("Successfully set global EID to '%s'\n", v->value);
3082                                 ast_eid_default = tmp_eid;
3083                         } else
3084                                 ast_verbose("Invalid Entity ID '%s' provided\n", v->value);
3085                 } else if (!strcasecmp(v->name, "lightbackground")) {
3086                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_LIGHT_BACKGROUND);
3087                 } else if (!strcasecmp(v->name, "forceblackbackground")) {
3088                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_FORCE_BLACK_BACKGROUND);
3089                 } else if (!strcasecmp(v->name, "hideconnect")) {
3090                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_HIDE_CONSOLE_CONNECT);
3091                 } else if (!strcasecmp(v->name, "lockconfdir")) {
3092                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_LOCK_CONFIG_DIR);
3093                 }
3094         }
3095         for (v = ast_variable_browse(cfg, "compat"); v; v = v->next) {
3096                 float version;
3097                 if (sscanf(v->value, "%30f", &version) != 1) {
3098                         ast_log(LOG_WARNING, "Compatibility version for option '%s' is not a number: '%s'\n", v->name, v->value);
3099                         continue;
3100                 }
3101                 if (!strcasecmp(v->name, "app_set")) {
3102                         ast_set2_flag(&ast_compat, version < 1.5 ? 1 : 0, AST_COMPAT_APP_SET);
3103                 } else if (!strcasecmp(v->name, "res_agi")) {
3104                         ast_set2_flag(&ast_compat, version < 1.5 ? 1 : 0, AST_COMPAT_DELIM_RES_AGI);
3105                 } else if (!strcasecmp(v->name, "pbx_realtime")) {
3106                         ast_set2_flag(&ast_compat, version < 1.5 ? 1 : 0, AST_COMPAT_DELIM_PBX_REALTIME);
3107                 }
3108         }
3109         ast_config_destroy(cfg);
3110 }
3111
3112 static void *monitor_sig_flags(void *unused)
3113 {
3114         for (;;) {
3115                 struct pollfd p = { sig_alert_pipe[0], POLLIN, 0 };
3116                 int a;
3117                 ast_poll(&p, 1, -1);
3118                 if (sig_flags.need_reload) {
3119                         sig_flags.need_reload = 0;
3120                         ast_module_reload(NULL);
3121                 }
3122                 if (sig_flags.need_quit) {
3123                         sig_flags.need_quit = 0;
3124                         if (consolethread != AST_PTHREADT_NULL) {
3125                                 sig_flags.need_quit_handler = 1;
3126                                 pthread_kill(consolethread, SIGURG);
3127                         } else {
3128                                 quit_handler(0, 0, 1, 0);
3129                         }
3130                 }
3131                 if (read(sig_alert_pipe[0], &a, sizeof(a)) != sizeof(a)) {
3132                 }
3133         }
3134
3135         return NULL;
3136 }
3137
3138 static void *canary_thread(void *unused)
3139 {
3140         struct stat canary_stat;
3141         struct timeval now;
3142
3143         /* Give the canary time to sing */
3144         sleep(120);
3145
3146         for (;;) {
3147                 stat(canary_filename, &canary_stat);
3148                 now = ast_tvnow();
3149                 if (now.tv_sec > canary_stat.st_mtime + 60) {
3150                         ast_log(LOG_WARNING, "The canary is no more.  He has ceased to be!  He's expired and gone to meet his maker!  He's a stiff!  Bereft of life, he rests in peace.  His metabolic processes are now history!  He's off the twig!  He's kicked the bucket.  He's shuffled off his mortal coil, run down the curtain, and joined the bleeding choir invisible!!  THIS is an EX-CANARY.  (Reducing priority)\n");
3151                         ast_set_priority(0);
3152                         pthread_exit(NULL);
3153                 }
3154
3155                 /* Check the canary once a minute */
3156                 sleep(60);
3157         }
3158 }
3159
3160 /* Used by libc's atexit(3) function */
3161 static void canary_exit(void)
3162 {
3163         if (canary_pid > 0)
3164                 kill(canary_pid, SIGKILL);
3165 }
3166
3167 static void run_startup_commands(void)
3168 {
3169         int fd;
3170         struct ast_config *cfg;
3171         struct ast_flags cfg_flags = { 0 };
3172         struct ast_variable *v;
3173
3174         if (!(cfg = ast_config_load2("cli.conf", "" /* core, can't reload */, cfg_flags)))
3175                 return;
3176         if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEUNCHANGED || cfg == CONFIG_STATUS_FILEINVALID) {
3177                 return;
3178         }
3179
3180         fd = open("/dev/null", O_RDWR);
3181         if (fd < 0) {
3182                 ast_config_destroy(cfg);
3183                 return;
3184         }
3185
3186         for (v = ast_variable_browse(cfg, "startup_commands"); v; v = v->next) {
3187                 if (ast_true(v->value))
3188                         ast_cli_command(fd, v->name);
3189         }
3190
3191         close(fd);
3192         ast_config_destroy(cfg);
3193 }
3194
3195 static void env_init(void)
3196 {
3197         setenv("AST_SYSTEMNAME", ast_config_AST_SYSTEM_NAME, 1);
3198         setenv("AST_BUILD_HOST", ast_build_hostname, 1);
3199         setenv("AST_BUILD_DATE", ast_build_date, 1);
3200         setenv("AST_BUILD_KERNEL", ast_build_kernel, 1);
3201         setenv("AST_BUILD_MACHINE", ast_build_machine, 1);
3202         setenv("AST_BUILD_OS", ast_build_os, 1);
3203         setenv("AST_BUILD_USER", ast_build_user, 1);
3204         setenv("AST_VERSION", ast_get_version(), 1);
3205 }
3206
3207 int main(int argc, char *argv[])
3208 {
3209         int c;
3210         char filename[80] = "";
3211         char hostname[MAXHOSTNAMELEN] = "";
3212         char tmp[80];
3213         char * xarg = NULL;
3214         int x;
3215         FILE *f;
3216         sigset_t sigs;
3217         int num;
3218         int isroot = 1, rundir_exists = 0;
3219         char *buf;
3220         const char *runuser = NULL, *rungroup = NULL;
3221         char *remotesock = NULL;
3222         int moduleresult;         /*!< Result from the module load subsystem */
3223         struct rlimit l;
3224
3225         /* Remember original args for restart */
3226         if (argc > ARRAY_LEN(_argv) - 1) {
3227                 fprintf(stderr, "Truncating argument size to %d\n", (int)ARRAY_LEN(_argv) - 1);
3228                 argc = ARRAY_LEN(_argv) - 1;
3229         }
3230         for (x = 0; x < argc; x++)
3231                 _argv[x] = argv[x];
3232         _argv[x] = NULL;
3233
3234         if (geteuid() != 0)
3235                 isroot = 0;
3236
3237         /* if the progname is rasterisk consider it a remote console */
3238         if (argv[0] && (strstr(argv[0], "rasterisk")) != NULL) {
3239                 ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK | AST_OPT_FLAG_REMOTE);
3240         }
3241         if (gethostname(hostname, sizeof(hostname)-1))
3242                 ast_copy_string(hostname, "<Unknown>", sizeof(hostname));
3243         ast_mainpid = getpid();
3244         ast_ulaw_init();
3245         ast_alaw_init();
3246         callerid_init();
3247         ast_builtins_init();
3248         ast_utils_init();
3249         tdd_init();
3250         ast_tps_init();
3251         ast_fd_init();
3252         ast_pbx_init();
3253
3254         if (getenv("HOME")) 
3255                 snprintf(filename, sizeof(filename), "%s/.asterisk_history", getenv("HOME"));
3256         /* Check for options */
3257         while ((c = getopt(argc, argv, "BC:cde:FfG:ghIiL:M:mnpqRrs:TtU:VvWXx:")) != -1) {
3258                 /*!\note Please keep the ordering here to alphabetical, capital letters
3259                  * first.  This will make it easier in the future to select unused
3260                  * option flags for new features. */
3261                 switch (c) {
3262                 case 'B': /* Force black background */
3263                         ast_set_flag(&ast_options, AST_OPT_FLAG_FORCE_BLACK_BACKGROUND);
3264                         ast_clear_flag(&ast_options, AST_OPT_FLAG_LIGHT_BACKGROUND);
3265                         break;
3266                 case 'X':
3267                         ast_set_flag(&ast_options, AST_OPT_FLAG_EXEC_INCLUDES);
3268                         break;
3269                 case 'C':
3270                         ast_copy_string(cfg_paths.config_file, optarg, sizeof(cfg_paths.config_file));
3271                         ast_set_flag(&ast_options, AST_OPT_FLAG_OVERRIDE_CONFIG);
3272                         break;
3273                 case 'c':
3274                         ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK | AST_OPT_FLAG_CONSOLE);
3275                         break;
3276                 case 'd':
3277                         option_debug++;
3278                         ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK);
3279                         break;
3280 #if defined(HAVE_SYSINFO)
3281                 case 'e':
3282                         if ((sscanf(&optarg[1], "%30ld", &option_minmemfree) != 1) || (option_minmemfree < 0)) {
3283                                 option_minmemfree = 0;
3284                         }
3285                         break;
3286 #endif
3287 #if HAVE_WORKING_FORK
3288                 case 'F':
3289                         ast_set_flag(&ast_options, AST_OPT_FLAG_ALWAYS_FORK);
3290                         break;
3291                 case 'f':
3292                         ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK);
3293                         break;
3294 #endif
3295                 case 'G':
3296                         rungroup = ast_strdupa(optarg);
3297                         break;
3298                 case 'g':
3299                         ast_set_flag(&ast_options, AST_OPT_FLAG_DUMP_CORE);
3300                         break;
3301                 case 'h':
3302                         show_cli_help();
3303                         exit(0);
3304                 case 'I':
3305                         ast_set_flag(&ast_options, AST_OPT_FLAG_INTERNAL_TIMING);
3306                         break;
3307                 case 'i':
3308                         ast_set_flag(&ast_options, AST_OPT_FLAG_INIT_KEYS);
3309                         break;
3310                 case 'L':
3311                         if ((sscanf(optarg, "%30lf", &option_maxload) != 1) || (option_maxload < 0.0)) {
3312                                 option_maxload = 0.0;
3313                         }
3314                         break;
3315                 case 'M':
3316                         if ((sscanf(optarg, "%30d", &option_maxcalls) != 1) || (option_maxcalls < 0)) {
3317                                 option_maxcalls = 0;
3318                         }
3319                         break;
3320                 case 'm':
3321                         ast_set_flag(&ast_options, AST_OPT_FLAG_MUTE);
3322                         break;
3323                 case 'n':
3324                         ast_set_flag(&ast_options, AST_OPT_FLAG_NO_COLOR);
3325                         break;
3326                 case 'p':
3327                         ast_set_flag(&ast_options, AST_OPT_FLAG_HIGH_PRIORITY);
3328                         break;
3329                 case 'q':
3330                         ast_set_flag(&ast_options, AST_OPT_FLAG_QUIET);
3331                         break;
3332                 case 'R':
3333                         ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK | AST_OPT_FLAG_REMOTE | AST_OPT_FLAG_RECONNECT);
3334                         break;
3335                 case 'r':
3336                         ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK | AST_OPT_FLAG_REMOTE);
3337                         break;
3338                 case 's':
3339                         remotesock = ast_strdupa(optarg);
3340                         break;
3341                 case 'T':
3342                         ast_set_flag(&ast_options, AST_OPT_FLAG_TIMESTAMP);
3343                         break;
3344                 case 't':
3345                         ast_set_flag(&ast_options, AST_OPT_FLAG_CACHE_RECORD_FILES);
3346                         break;
3347                 case 'U':
3348                         runuser = ast_strdupa(optarg);
3349                         break;
3350                 case 'V':
3351                         show_version();
3352                         exit(0);
3353                 case 'v':
3354                         option_verbose++;
3355                         ast_set_flag(&ast_options, AST_OPT_FLAG_NO_FORK);
3356                         break;
3357                 case 'W': /* White background */
3358                         ast_set_flag(&ast_options, AST_OPT_FLAG_LIGHT_BACKGROUND);
3359                         ast_clear_flag(&ast_options, AST_OPT_FLAG_FORCE_BLACK_BACKGROUND);
3360                         break;
3361                 case 'x':
3362                         ast_set_flag(&ast_options, AST_OPT_FLAG_EXEC | AST_OPT_FLAG_NO_COLOR);
3363                         xarg = ast_strdupa(optarg);
3364                         break;
3365                 case '?':
3366                         exit(1);
3367                 }
3368         }
3369
3370         if (ast_opt_console || option_verbose || (ast_opt_remote && !ast_opt_exec)) {
3371                 if (ast_register_verbose(console_verboser)) {
3372                         ast_log(LOG_WARNING, "Unable to register console verboser?\n");
3373                 }
3374                 WELCOME_MESSAGE;
3375         }
3376
3377         if (ast_opt_console && !option_verbose) 
3378                 ast_verbose("[ Booting...\n");
3379
3380         /* For remote connections, change the name of the remote connection.
3381          * We do this for the benefit of init scripts (which need to know if/when
3382          * the main asterisk process has died yet). */
3383         if (ast_opt_remote) {
3384                 strcpy(argv[0], "rasterisk");
3385                 for (x = 1; x < argc; x++) {
3386                         argv[x] = argv[0] + 10;
3387                 }
3388         }
3389
3390         if (ast_opt_console && !option_verbose) {
3391                 ast_verbose("[ Reading Master Configuration ]\n");
3392         }
3393
3394         ast_readconfig();
3395         env_init();
3396
3397         if (ast_opt_remote && remotesock != NULL)
3398                 ast_copy_string((char *) cfg_paths.socket_path, remotesock, sizeof(cfg_paths.socket_path));
3399
3400         if (!ast_language_is_prefix && !ast_opt_remote)
3401                 ast_log(LOG_WARNING, "The 'languageprefix' option in asterisk.conf is deprecated; in a future release it will be removed, and your sound files will need to be organized in the 'new style' language layout.\n");
3402
3403         if (ast_opt_always_fork && (ast_opt_remote || ast_opt_console)) {
3404                 ast_log(LOG_WARNING, "'alwaysfork' is not compatible with console or remote console mode; ignored\n");
3405                 ast_clear_flag(&ast_options, AST_OPT_FLAG_ALWAYS_FORK);
3406         }
3407
3408         if (ast_opt_dump_core) {
3409                 memset(&l, 0, sizeof(l));
3410                 l.rlim_cur = RLIM_INFINITY;
3411                 l.rlim_max = RLIM_INFINITY;
3412                 if (setrlimit(RLIMIT_CORE, &l)) {
3413                         ast_log(LOG_WARNING, "Unable to disable core size resource limit: %s\n", strerror(errno));
3414                 }
3415         }
3416
3417         if (getrlimit(RLIMIT_NOFILE, &l)) {
3418                 ast_log(LOG_WARNING, "Unable to check file descriptor limit: %s\n", strerror(errno));
3419         }
3420
3421 #if !defined(CONFIGURE_RAN_AS_ROOT)
3422         /* Check if select(2) will run with more file descriptors */
3423         do {
3424                 int fd, fd2;
3425                 ast_fdset readers;
3426                 struct timeval tv = { 0, };
3427
3428                 if (l.rlim_cur <= FD_SETSIZE) {
3429                         /* The limit of select()able FDs is irrelevant, because we'll never
3430                          * open one that high. */
3431                         break;
3432                 }
3433
3434                 if (!(fd = open("/dev/null", O_RDONLY))) {
3435                         ast_log(LOG_ERROR, "Cannot open a file descriptor at boot? %s\n", strerror(errno));
3436                         break; /* XXX Should we exit() here? XXX */
3437                 }
3438
3439                 fd2 = (l.rlim_cur > sizeof(readers) * 8 ? sizeof(readers) * 8 : l.rlim_cur) - 1;
3440                 if (dup2(fd, fd2) < 0) {
3441                         ast_log(LOG_WARNING, "Cannot open maximum file descriptor %d at boot? %s\n", fd2, strerror(errno));
3442                         close(fd);
3443                         break;
3444                 }
3445
3446                 FD_ZERO(&readers);
3447                 FD_SET(fd2, &readers);
3448                 if (ast_select(fd2 + 1, &readers, NULL, NULL, &tv) < 0) {
3449                         ast_log(LOG_WARNING, "Maximum select()able file descriptor is %d\n", FD_SETSIZE);
3450                 }
3451                 ast_FD_SETSIZE = l.rlim_cur > ast_FDMAX ? ast_FDMAX : l.rlim_cur;
3452                 close(fd);
3453                 close(fd2);
3454         } while (0);
3455 #elif defined(HAVE_VARIABLE_FDSET)
3456         ast_FD_SETSIZE = l.rlim_cur > ast_FDMAX ? ast_FDMAX : l.rlim_cur;
3457 #endif /* !defined(CONFIGURE_RAN_AS_ROOT) */
3458
3459         if ((!rungroup) && !ast_strlen_zero(ast_config_AST_RUN_GROUP))
3460                 rungroup = ast_config_AST_RUN_GROUP;
3461         if ((!runuser) && !ast_strlen_zero(ast_config_AST_RUN_USER))
3462                 runuser = ast_config_AST_RUN_USER;
3463
3464         /* Must install this signal handler up here to ensure that if the canary
3465          * fails to execute that it doesn't kill the Asterisk process.
3466          */
3467         sigaction(SIGCHLD, &child_handler, NULL);
3468
3469         /* It's common on some platforms to clear /var/run at boot.  Create the
3470          * socket file directory before we drop privileges. */
3471         if (mkdir(ast_config_AST_RUN_DIR, 0755)) {
3472                 if (errno == EEXIST) {
3473                         rundir_exists = 1;
3474                 } else {
3475                         ast_log(LOG_WARNING, "Unable to create socket file directory.  Remote consoles will not be able to connect! (%s)\n", strerror(x));
3476                 }
3477         }
3478
3479 #ifndef __CYGWIN__
3480
3481         if (isroot) {
3482                 ast_set_priority(ast_opt_high_priority);
3483         }
3484
3485         if (isroot && rungroup) {
3486                 struct group *gr;
3487                 gr = getgrnam(rungroup);
3488                 if (!gr) {
3489                         ast_log(LOG_WARNING, "No such group '%s'!\n", rungroup);
3490                         exit(1);
3491                 }
3492                 if (!rundir_exists && chown(ast_config_AST_RUN_DIR, -1, gr->gr_gid)) {
3493                         ast_log(LOG_WARNING, "Unable to chgrp run directory to %d (%s)\n", (int) gr->gr_gid, rungroup);
3494                 }
3495                 if (setgid(gr->gr_gid)) {
3496                         ast_log(LOG_WARNING, "Unable to setgid to %d (%s)\n", (int)gr->gr_gid, rungroup);
3497                         exit(1);
3498                 }
3499                 if (setgroups(0, NULL)) {
3500                         ast_log(LOG_WARNING, "Unable to drop unneeded groups\n");
3501                         exit(1);
3502                 }
3503                 if (option_verbose)
3504                         ast_verbose("Running as group '%s'\n", rungroup);
3505         }
3506
3507         if (runuser && !ast_test_flag(&ast_options, AST_OPT_FLAG_REMOTE)) {
3508 #ifdef HAVE_CAP
3509                 int has_cap = 1;
3510 #endif /* HAVE_CAP */
3511                 struct passwd *pw;
3512                 pw = getpwnam(runuser);
3513                 if (!pw) {
3514                         ast_log(LOG_WARNING, "No such user '%s'!\n", runuser);
3515                         exit(1);
3516                 }
3517                 if (chown(ast_config_AST_RUN_DIR, pw->pw_uid, -1)) {
3518                         ast_log(LOG_WARNING, "Unable to chown run directory to %d (%s)\n", (int) pw->pw_uid, runuser);
3519                 }
3520 #ifdef HAVE_CAP
3521                 if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0)) {
3522                         ast_log(LOG_WARNING, "Unable to keep capabilities.\n");
3523                         has_cap = 0;
3524                 }
3525 #endif /* HAVE_CAP */
3526                 if (!isroot && pw->pw_uid != geteuid()) {
3527                         ast_log(LOG_ERROR, "Asterisk started as nonroot, but runuser '%s' requested.\n", runuser);
3528                         exit(1);
3529                 }
3530                 if (!rungroup) {
3531                         if (setgid(pw->pw_gid)) {
3532                                 ast_log(LOG_WARNING, "Unable to setgid to %d!\n", (int)pw->pw_gid);
3533                                 exit(1);
3534                         }
3535                         if (isroot && initgroups(pw->pw_name, pw->pw_gid)) {
3536                                 ast_log(LOG_WARNING, "Unable to init groups for '%s'\n", runuser);
3537                                 exit(1);
3538                         }
3539                 }
3540                 if (setuid(pw->pw_uid)) {
3541                         ast_log(LOG_WARNING, "Unable to setuid to %d (%s)\n", (int)pw->pw_uid, runuser);
3542                         exit(1);
3543                 }
3544                 if (option_verbose)
3545                         ast_verbose("Running as user '%s'\n", runuser);
3546 #ifdef HAVE_CAP
3547                 if (has_cap) {
3548                         cap_t cap;
3549
3550                         cap = cap_from_text("cap_net_admin=eip");
3551
3552                         if (cap_set_proc(cap))
3553                                 ast_log(LOG_WARNING, "Unable to install capabilities.\n");
3554
3555                         if (cap_free(cap))
3556                                 ast_log(LOG_WARNING, "Unable to drop capabilities.\n");
3557                 }
3558 #endif /* HAVE_CAP */
3559         }
3560
3561 #endif /* __CYGWIN__ */
3562
3563 #ifdef linux
3564         if (geteuid() && ast_opt_dump_core) {
3565                 if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) < 0) {
3566                         ast_log(LOG_WARNING, "Unable to set the process for core dumps after changing to a non-root user. %s\n", strerror(errno));
3567                 }
3568         }
3569 #endif
3570
3571         {
3572 #if defined(HAVE_EACCESS) || defined(HAVE_EUIDACCESS)
3573 #if defined(HAVE_EUIDACCESS) && !defined(HAVE_EACCESS)
3574 #define eaccess euidaccess
3575 #endif