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