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