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