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