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