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