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