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