ec49c65e02355cfbff079ecaca737172b00feb05
[asterisk/asterisk.git] / main / asterisk.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2015, 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 - 2015, 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 - 2015, 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                 return NULL;
2347         case CLI_GENERATE:
2348                 return NULL;
2349         }
2350
2351         if (a->argc != e->args)
2352                 return CLI_SHOWUSAGE;
2353         quit_handler(0, SHUTDOWN_NORMAL, 0 /* not restart */);
2354         return CLI_SUCCESS;
2355 }
2356
2357 static char *handle_stop_gracefully(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2358 {
2359         switch (cmd) {
2360         case CLI_INIT:
2361                 e->command = "core stop gracefully";
2362                 e->usage =
2363                         "Usage: core stop gracefully\n"
2364                         "       Causes Asterisk to not accept new calls, and exit when all\n"
2365                         "       active calls have terminated normally.\n";
2366                 return NULL;
2367         case CLI_GENERATE:
2368                 return NULL;
2369         }
2370
2371         if (a->argc != e->args)
2372                 return CLI_SHOWUSAGE;
2373         quit_handler(0, SHUTDOWN_NICE, 0 /* no restart */);
2374         return CLI_SUCCESS;
2375 }
2376
2377 static char *handle_stop_when_convenient(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2378 {
2379         switch (cmd) {
2380         case CLI_INIT:
2381                 e->command = "core stop when convenient";
2382                 e->usage =
2383                         "Usage: core stop when convenient\n"
2384                         "       Causes Asterisk to perform a shutdown when all active calls have ended.\n";
2385                 return NULL;
2386         case CLI_GENERATE:
2387                 return NULL;
2388         }
2389
2390         if (a->argc != e->args)
2391                 return CLI_SHOWUSAGE;
2392         ast_cli(a->fd, "Waiting for inactivity to perform halt\n");
2393         quit_handler(0, SHUTDOWN_REALLY_NICE, 0 /* don't restart */);
2394         return CLI_SUCCESS;
2395 }
2396
2397 static char *handle_restart_now(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2398 {
2399         switch (cmd) {
2400         case CLI_INIT:
2401                 e->command = "core restart now";
2402                 e->usage =
2403                         "Usage: core restart now\n"
2404                         "       Causes Asterisk to hangup all calls and exec() itself performing a cold\n"
2405                         "       restart.\n";
2406                 return NULL;
2407         case CLI_GENERATE:
2408                 return NULL;
2409         }
2410
2411         if (a->argc != e->args)
2412                 return CLI_SHOWUSAGE;
2413         quit_handler(0, SHUTDOWN_NORMAL, 1 /* restart */);
2414         return CLI_SUCCESS;
2415 }
2416
2417 static char *handle_restart_gracefully(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2418 {
2419         switch (cmd) {
2420         case CLI_INIT:
2421                 e->command = "core restart gracefully";
2422                 e->usage =
2423                         "Usage: core restart gracefully\n"
2424                         "       Causes Asterisk to stop accepting new calls and exec() itself performing a cold\n"
2425                         "       restart when all active calls have ended.\n";
2426                 return NULL;
2427         case CLI_GENERATE:
2428                 return NULL;
2429         }
2430
2431         if (a->argc != e->args)
2432                 return CLI_SHOWUSAGE;
2433         quit_handler(0, SHUTDOWN_NICE, 1 /* restart */);
2434         return CLI_SUCCESS;
2435 }
2436
2437 static char *handle_restart_when_convenient(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2438 {
2439         switch (cmd) {
2440         case CLI_INIT:
2441                 e->command = "core restart when convenient";
2442                 e->usage =
2443                         "Usage: core restart when convenient\n"
2444                         "       Causes Asterisk to perform a cold restart when all active calls have ended.\n";
2445                 return NULL;
2446         case CLI_GENERATE:
2447                 return NULL;
2448         }
2449
2450         if (a->argc != e->args)
2451                 return CLI_SHOWUSAGE;
2452         ast_cli(a->fd, "Waiting for inactivity to perform restart\n");
2453         quit_handler(0, SHUTDOWN_REALLY_NICE, 1 /* restart */);
2454         return CLI_SUCCESS;
2455 }
2456
2457 static char *handle_abort_shutdown(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2458 {
2459         switch (cmd) {
2460         case CLI_INIT:
2461                 e->command = "core abort shutdown";
2462                 e->usage =
2463                         "Usage: core abort shutdown\n"
2464                         "       Causes Asterisk to abort an executing shutdown or restart, and resume normal\n"
2465                         "       call operations.\n";
2466                 return NULL;
2467         case CLI_GENERATE:
2468                 return NULL;
2469         }
2470
2471         if (a->argc != e->args)
2472                 return CLI_SHOWUSAGE;
2473
2474         ast_cancel_shutdown();
2475
2476         return CLI_SUCCESS;
2477 }
2478
2479 static char *handle_bang(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2480 {
2481         switch (cmd) {
2482         case CLI_INIT:
2483                 e->command = "!";
2484                 e->usage =
2485                         "Usage: !<command>\n"
2486                         "       Executes a given shell command\n";
2487                 return NULL;
2488         case CLI_GENERATE:
2489                 return NULL;
2490         }
2491
2492         return CLI_SUCCESS;
2493 }
2494 static const char warranty_lines[] = {
2495         "\n"
2496         "                           NO WARRANTY\n"
2497         "\n"
2498         "BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY\n"
2499         "FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN\n"
2500         "OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES\n"
2501         "PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED\n"
2502         "OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\n"
2503         "MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS\n"
2504         "TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE\n"
2505         "PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,\n"
2506         "REPAIR OR CORRECTION.\n"
2507         "\n"
2508         "IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\n"
2509         "WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR\n"
2510         "REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,\n"
2511         "INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING\n"
2512         "OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED\n"
2513         "TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY\n"
2514         "YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER\n"
2515         "PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE\n"
2516         "POSSIBILITY OF SUCH DAMAGES.\n"
2517 };
2518
2519 static char *show_warranty(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2520 {
2521         switch (cmd) {
2522         case CLI_INIT:
2523                 e->command = "core show warranty";
2524                 e->usage =
2525                         "Usage: core show warranty\n"
2526                         "       Shows the warranty (if any) for this copy of Asterisk.\n";
2527                 return NULL;
2528         case CLI_GENERATE:
2529                 return NULL;
2530         }
2531
2532         ast_cli(a->fd, "%s", warranty_lines);
2533
2534         return CLI_SUCCESS;
2535 }
2536
2537 static const char license_lines[] = {
2538         "\n"
2539         "This program is free software; you can redistribute it and/or modify\n"
2540         "it under the terms of the GNU General Public License version 2 as\n"
2541         "published by the Free Software Foundation.\n"
2542         "\n"
2543         "This program also contains components licensed under other licenses.\n"
2544         "They include:\n"
2545         "\n"
2546         "This program is distributed in the hope that it will be useful,\n"
2547         "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
2548         "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n"
2549         "GNU General Public License for more details.\n"
2550         "\n"
2551         "You should have received a copy of the GNU General Public License\n"
2552         "along with this program; if not, write to the Free Software\n"
2553         "Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA\n"
2554 };
2555
2556 static char *show_license(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2557 {
2558         switch (cmd) {
2559         case CLI_INIT:
2560                 e->command = "core show license";
2561                 e->usage =
2562                         "Usage: core show license\n"
2563                         "       Shows the license(s) for this copy of Asterisk.\n";
2564                 return NULL;
2565         case CLI_GENERATE:
2566                 return NULL;
2567         }
2568
2569         ast_cli(a->fd, "%s", license_lines);
2570
2571         return CLI_SUCCESS;
2572 }
2573
2574 #define ASTERISK_PROMPT "*CLI> "
2575
2576 /*!
2577  * \brief Shutdown Asterisk CLI commands.
2578  *
2579  * \note These CLI commands cannot be unregistered at shutdown
2580  * because one of them is likely the reason for the shutdown.
2581  * The CLI generates a warning if a command is in-use when it is
2582  * unregistered.
2583  */
2584 static struct ast_cli_entry cli_asterisk_shutdown[] = {
2585         AST_CLI_DEFINE(handle_stop_now, "Shut down Asterisk immediately"),
2586         AST_CLI_DEFINE(handle_stop_gracefully, "Gracefully shut down Asterisk"),
2587         AST_CLI_DEFINE(handle_stop_when_convenient, "Shut down Asterisk at empty call volume"),
2588         AST_CLI_DEFINE(handle_restart_now, "Restart Asterisk immediately"),
2589         AST_CLI_DEFINE(handle_restart_gracefully, "Restart Asterisk gracefully"),
2590         AST_CLI_DEFINE(handle_restart_when_convenient, "Restart Asterisk at empty call volume"),
2591 };
2592
2593 static struct ast_cli_entry cli_asterisk[] = {
2594         AST_CLI_DEFINE(handle_abort_shutdown, "Cancel a running shutdown"),
2595         AST_CLI_DEFINE(show_warranty, "Show the warranty (if any) for this copy of Asterisk"),
2596         AST_CLI_DEFINE(show_license, "Show the license(s) for this copy of Asterisk"),
2597         AST_CLI_DEFINE(handle_version, "Display version info"),
2598         AST_CLI_DEFINE(handle_bang, "Execute a shell command"),
2599 #if !defined(LOW_MEMORY)
2600         AST_CLI_DEFINE(handle_show_threads, "Show running threads"),
2601 #if defined(HAVE_SYSINFO) || defined(HAVE_SYSCTL)
2602         AST_CLI_DEFINE(handle_show_sysinfo, "Show System Information"),
2603 #endif
2604         AST_CLI_DEFINE(handle_show_profile, "Display profiling info"),
2605         AST_CLI_DEFINE(handle_show_settings, "Show some core settings"),
2606         AST_CLI_DEFINE(handle_clear_profile, "Clear profiling info"),
2607 #endif /* ! LOW_MEMORY */
2608 };
2609
2610 static void send_rasterisk_connect_commands(void)
2611 {
2612         char buf[80];
2613
2614         /*
2615          * Tell the server asterisk instance about the verbose level
2616          * initially desired.
2617          */
2618         if (option_verbose) {
2619                 snprintf(buf, sizeof(buf), "core set verbose atleast %d silent", option_verbose);
2620                 fdsend(ast_consock, buf);
2621         }
2622
2623         if (option_debug) {
2624                 snprintf(buf, sizeof(buf), "core set debug atleast %d", option_debug);
2625                 fdsend(ast_consock, buf);
2626         }
2627
2628         if (!ast_opt_mute) {
2629                 fdsend(ast_consock, "logger mute silent");
2630         } else {
2631                 printf("log and verbose output currently muted ('logger mute' to unmute)\n");
2632         }
2633 }
2634
2635 static int ast_el_read_char(EditLine *editline, char *cp)
2636 {
2637         int num_read = 0;
2638         int lastpos = 0;
2639         struct pollfd fds[2];
2640         int res;
2641         int max;
2642 #define EL_BUF_SIZE 512
2643         char buf[EL_BUF_SIZE];
2644
2645         for (;;) {
2646                 max = 1;
2647                 fds[0].fd = ast_consock;
2648                 fds[0].events = POLLIN;
2649                 if (!ast_opt_exec) {
2650                         fds[1].fd = STDIN_FILENO;
2651                         fds[1].events = POLLIN;
2652                         max++;
2653                 }
2654                 res = ast_poll(fds, max, -1);
2655                 if (res < 0) {
2656                         if (sig_flags.need_quit || sig_flags.need_quit_handler)
2657                                 break;
2658                         if (errno == EINTR)
2659                                 continue;
2660                         fprintf(stderr, "poll failed: %s\n", strerror(errno));
2661                         break;
2662                 }
2663
2664                 if (!ast_opt_exec && fds[1].revents) {
2665                         num_read = read(STDIN_FILENO, cp, 1);
2666                         if (num_read < 1) {
2667                                 break;
2668                         } else {
2669                                 return (num_read);
2670                         }
2671                 }
2672                 if (fds[0].revents) {
2673                         res = read(ast_consock, buf, sizeof(buf) - 1);
2674                         /* if the remote side disappears exit */
2675                         if (res < 1) {
2676                                 fprintf(stderr, "\nDisconnected from Asterisk server\n");
2677                                 if (!ast_opt_reconnect) {
2678                                         quit_handler(0, SHUTDOWN_FAST, 0);
2679                                 } else {
2680                                         int tries;
2681                                         int reconnects_per_second = 20;
2682                                         fprintf(stderr, "Attempting to reconnect for 30 seconds\n");
2683                                         for (tries = 0; tries < 30 * reconnects_per_second; tries++) {
2684                                                 if (ast_tryconnect()) {
2685                                                         fprintf(stderr, "Reconnect succeeded after %.3f seconds\n", 1.0 / reconnects_per_second * tries);
2686                                                         printf("%s", term_quit());
2687                                                         WELCOME_MESSAGE;
2688                                                         send_rasterisk_connect_commands();
2689                                                         break;
2690                                                 } else
2691                                                         usleep(1000000 / reconnects_per_second);
2692                                         }
2693                                         if (tries >= 30 * reconnects_per_second) {
2694                                                 fprintf(stderr, "Failed to reconnect for 30 seconds.  Quitting.\n");
2695                                                 quit_handler(0, SHUTDOWN_FAST, 0);
2696                                         }
2697                                 }
2698                                 continue;
2699                         }
2700
2701                         buf[res] = '\0';
2702
2703                         /* Write over the CLI prompt */
2704                         if (!ast_opt_exec && !lastpos) {
2705                                 if (write(STDOUT_FILENO, "\r\e[0K", 5) < 0) {
2706                                 }
2707                         }
2708
2709                         console_print(buf, 0);
2710
2711                         if ((res < EL_BUF_SIZE - 1) && ((buf[res-1] == '\n') || (buf[res-2] == '\n'))) {
2712                                 *cp = CC_REFRESH;
2713                                 return(1);
2714                         } else
2715                                 lastpos = 1;
2716                 }
2717         }
2718
2719         *cp = '\0';
2720         return (0);
2721 }
2722
2723 static struct ast_str *prompt = NULL;
2724
2725 static char *cli_prompt(EditLine *editline)
2726 {
2727         char tmp[100];
2728         char *pfmt;
2729         int color_used = 0;
2730         static int cli_prompt_changes = 0;
2731         struct passwd *pw;
2732         struct group *gr;
2733
2734         if (prompt == NULL) {
2735                 prompt = ast_str_create(100);
2736         } else if (!cli_prompt_changes) {
2737                 return ast_str_buffer(prompt);
2738         } else {
2739                 ast_str_reset(prompt);
2740         }
2741
2742         if ((pfmt = getenv("ASTERISK_PROMPT"))) {
2743                 char *t = pfmt;
2744                 struct timeval ts = ast_tvnow();
2745                 while (*t != '\0') {
2746                         if (*t == '%') {
2747                                 char hostname[MAXHOSTNAMELEN] = "";
2748                                 int i, which;
2749                                 struct ast_tm tm = { 0, };
2750                                 int fgcolor = COLOR_WHITE, bgcolor = COLOR_BLACK;
2751
2752                                 t++;
2753                                 switch (*t) {
2754                                 case 'C': /* color */
2755                                         t++;
2756                                         if (sscanf(t, "%30d;%30d%n", &fgcolor, &bgcolor, &i) == 2) {
2757                                                 ast_term_color_code(&prompt, fgcolor, bgcolor);
2758                                                 t += i - 1;
2759                                         } else if (sscanf(t, "%30d%n", &fgcolor, &i) == 1) {
2760                                                 ast_term_color_code(&prompt, fgcolor, 0);
2761                                                 t += i - 1;
2762                                         }
2763
2764                                         /* If the color has been reset correctly, then there's no need to reset it later */
2765                                         color_used = ((fgcolor == COLOR_WHITE) && (bgcolor == COLOR_BLACK)) ? 0 : 1;
2766                                         break;
2767                                 case 'd': /* date */
2768                                         if (ast_localtime(&ts, &tm, NULL)) {
2769                                                 ast_strftime(tmp, sizeof(tmp), "%Y-%m-%d", &tm);
2770                                                 ast_str_append(&prompt, 0, "%s", tmp);
2771                                                 cli_prompt_changes++;
2772                                         }
2773                                         break;
2774                                 case 'g': /* group */
2775                                         if ((gr = getgrgid(getgid()))) {
2776                                                 ast_str_append(&prompt, 0, "%s", gr->gr_name);
2777                                         }
2778                                         break;
2779                                 case 'h': /* hostname */
2780                                         if (!gethostname(hostname, sizeof(hostname) - 1)) {
2781                                                 ast_str_append(&prompt, 0, "%s", hostname);
2782                                         } else {
2783                                                 ast_str_append(&prompt, 0, "%s", "localhost");
2784                                         }
2785                                         break;
2786                                 case 'H': /* short hostname */
2787                                         if (!gethostname(hostname, sizeof(hostname) - 1)) {
2788                                                 char *dotptr;
2789                                                 if ((dotptr = strchr(hostname, '.'))) {
2790                                                         *dotptr = '\0';
2791                                                 }
2792                                                 ast_str_append(&prompt, 0, "%s", hostname);
2793                                         } else {
2794                                                 ast_str_append(&prompt, 0, "%s", "localhost");
2795                                         }
2796                                         break;
2797 #ifdef HAVE_GETLOADAVG
2798                                 case 'l': /* load avg */
2799                                         t++;
2800                                         if (sscanf(t, "%30d", &which) == 1 && which > 0 && which <= 3) {
2801                                                 double list[3];
2802                                                 getloadavg(list, 3);
2803                                                 ast_str_append(&prompt, 0, "%.2f", list[which - 1]);
2804                                                 cli_prompt_changes++;
2805                                         }
2806                                         break;
2807 #endif
2808                                 case 's': /* Asterisk system name (from asterisk.conf) */
2809                                         ast_str_append(&prompt, 0, "%s", ast_config_AST_SYSTEM_NAME);
2810                                         break;
2811                                 case 't': /* time */
2812                                         if (ast_localtime(&ts, &tm, NULL)) {
2813                                                 ast_strftime(tmp, sizeof(tmp), "%H:%M:%S", &tm);
2814                                                 ast_str_append(&prompt, 0, "%s", tmp);
2815                                                 cli_prompt_changes++;
2816                                         }
2817                                         break;
2818                                 case 'u': /* username */
2819                                         if ((pw = getpwuid(getuid()))) {
2820                                                 ast_str_append(&prompt, 0, "%s", pw->pw_name);
2821                                         }
2822                                         break;
2823                                 case '#': /* process console or remote? */
2824                                         ast_str_append(&prompt, 0, "%c", ast_opt_remote ? '>' : '#');
2825                                         break;
2826                                 case '%': /* literal % */
2827                                         ast_str_append(&prompt, 0, "%c", '%');
2828                                         break;
2829                                 case '\0': /* % is last character - prevent bug */
2830                                         t--;
2831                                         break;
2832                                 }
2833                         } else {
2834                                 ast_str_append(&prompt, 0, "%c", *t);
2835                         }
2836                         t++;
2837                 }
2838                 if (color_used) {
2839                         /* Force colors back to normal at end */
2840                         ast_term_color_code(&prompt, 0, 0);
2841                 }
2842         } else {
2843                 ast_str_set(&prompt, 0, "%s%s",
2844                         remotehostname ? remotehostname : "",
2845                         ASTERISK_PROMPT);
2846         }
2847
2848         return ast_str_buffer(prompt);
2849 }
2850
2851 static void destroy_match_list(char **match_list, int matches)
2852 {
2853         if (match_list) {
2854                 int idx;
2855
2856                 for (idx = 0; idx < matches; ++idx) {
2857                         ast_free(match_list[idx]);
2858                 }
2859                 ast_free(match_list);
2860         }
2861 }
2862
2863 static char **ast_el_strtoarr(char *buf)
2864 {
2865         char *retstr;
2866         char **match_list = NULL;
2867         char **new_list;
2868         size_t match_list_len = 1;
2869         int matches = 0;
2870
2871         while ((retstr = strsep(&buf, " "))) {
2872                 if (!strcmp(retstr, AST_CLI_COMPLETE_EOF)) {
2873                         break;
2874                 }
2875                 if (matches + 1 >= match_list_len) {
2876                         match_list_len <<= 1;
2877                         new_list = ast_realloc(match_list, match_list_len * sizeof(char *));
2878                         if (!new_list) {
2879                                 destroy_match_list(match_list, matches);
2880                                 return NULL;
2881                         }
2882                         match_list = new_list;
2883                 }
2884
2885                 retstr = ast_strdup(retstr);
2886                 if (!retstr) {
2887                         destroy_match_list(match_list, matches);
2888                         return NULL;
2889                 }
2890                 match_list[matches++] = retstr;
2891         }
2892
2893         if (!match_list) {
2894                 return NULL;
2895         }
2896
2897         if (matches >= match_list_len) {
2898                 new_list = ast_realloc(match_list, (match_list_len + 1) * sizeof(char *));
2899                 if (!new_list) {
2900                         destroy_match_list(match_list, matches);
2901                         return NULL;
2902                 }
2903                 match_list = new_list;
2904         }
2905
2906         match_list[matches] = NULL;
2907
2908         return match_list;
2909 }
2910
2911 static int ast_el_sort_compare(const void *i1, const void *i2)
2912 {
2913         char *s1, *s2;
2914
2915         s1 = ((char **)i1)[0];
2916         s2 = ((char **)i2)[0];
2917
2918         return strcasecmp(s1, s2);
2919 }
2920
2921 static int ast_cli_display_match_list(char **matches, int len, int max)
2922 {
2923         int i, idx, limit, count;
2924         int screenwidth = 0;
2925         int numoutput = 0, numoutputline = 0;
2926
2927         screenwidth = ast_get_termcols(STDOUT_FILENO);
2928
2929         /* find out how many entries can be put on one line, with two spaces between strings */
2930         limit = screenwidth / (max + 2);
2931         if (limit == 0)
2932                 limit = 1;
2933
2934         /* how many lines of output */
2935         count = len / limit;
2936         if (count * limit < len)
2937                 count++;
2938
2939         idx = 1;
2940
2941         qsort(&matches[0], (size_t)(len), sizeof(char *), ast_el_sort_compare);
2942
2943         for (; count > 0; count--) {
2944                 numoutputline = 0;
2945                 for (i = 0; i < limit && matches[idx]; i++, idx++) {
2946
2947                         /* Don't print dupes */
2948                         if ( (matches[idx+1] != NULL && strcmp(matches[idx], matches[idx+1]) == 0 ) ) {
2949                                 i--;
2950                                 ast_free(matches[idx]);
2951                                 matches[idx] = NULL;
2952                                 continue;
2953                         }
2954
2955                         numoutput++;
2956                         numoutputline++;
2957                         fprintf(stdout, "%-*s  ", max, matches[idx]);
2958                         ast_free(matches[idx]);
2959                         matches[idx] = NULL;
2960                 }
2961                 if (numoutputline > 0)
2962                         fprintf(stdout, "\n");
2963         }
2964
2965         return numoutput;
2966 }
2967
2968
2969 static char *cli_complete(EditLine *editline, int ch)
2970 {
2971         int len = 0;
2972         char *ptr;
2973         int nummatches = 0;
2974         char **matches;
2975         int retval = CC_ERROR;
2976         char buf[2048], savechr;
2977         int res;
2978
2979         LineInfo *lf = (LineInfo *)el_line(editline);
2980
2981         savechr = *(char *)lf->cursor;
2982         *(char *)lf->cursor = '\0';
2983         ptr = (char *)lf->cursor;
2984         if (ptr) {
2985                 while (ptr > lf->buffer) {
2986                         if (isspace(*ptr)) {
2987                                 ptr++;
2988                                 break;
2989                         }
2990                         ptr--;
2991                 }
2992         }
2993
2994         len = lf->cursor - ptr;
2995
2996         if (ast_opt_remote) {
2997                 snprintf(buf, sizeof(buf), "_COMMAND NUMMATCHES \"%s\" \"%s\"", lf->buffer, ptr);
2998                 fdsend(ast_consock, buf);
2999                 if ((res = read(ast_consock, buf, sizeof(buf) - 1)) < 0) {
3000                         return (char*)(CC_ERROR);
3001                 }
3002                 buf[res] = '\0';
3003                 nummatches = atoi(buf);
3004
3005                 if (nummatches > 0) {
3006                         char *mbuf;
3007                         char *new_mbuf;
3008                         int mlen = 0, maxmbuf = 2048;
3009
3010                         /* Start with a 2048 byte buffer */
3011                         if (!(mbuf = ast_malloc(maxmbuf))) {
3012                                 *((char *) lf->cursor) = savechr;
3013                                 return (char *)(CC_ERROR);
3014                         }
3015                         snprintf(buf, sizeof(buf), "_COMMAND MATCHESARRAY \"%s\" \"%s\"", lf->buffer, ptr);
3016                         fdsend(ast_consock, buf);
3017                         res = 0;
3018                         mbuf[0] = '\0';
3019                         while (!strstr(mbuf, AST_CLI_COMPLETE_EOF) && res != -1) {
3020                                 if (mlen + 1024 > maxmbuf) {
3021                                         /* Every step increment buffer 1024 bytes */
3022                                         maxmbuf += 1024;
3023                                         new_mbuf = ast_realloc(mbuf, maxmbuf);
3024                                         if (!new_mbuf) {
3025                                                 ast_free(mbuf);
3026                                                 *((char *) lf->cursor) = savechr;
3027                                                 return (char *)(CC_ERROR);
3028                                         }
3029                                         mbuf = new_mbuf;
3030                                 }
3031                                 /* Only read 1024 bytes at a time */
3032                                 res = read(ast_consock, mbuf + mlen, 1024);
3033                                 if (res > 0)
3034                                         mlen += res;
3035                         }
3036                         mbuf[mlen] = '\0';
3037
3038                         matches = ast_el_strtoarr(mbuf);
3039                         ast_free(mbuf);
3040                 } else
3041                         matches = (char **) NULL;
3042         } else {
3043                 char **p, *oldbuf=NULL;
3044                 nummatches = 0;
3045                 matches = ast_cli_completion_matches((char *)lf->buffer,ptr);
3046                 for (p = matches; p && *p; p++) {
3047                         if (!oldbuf || strcmp(*p,oldbuf))
3048                                 nummatches++;
3049                         oldbuf = *p;
3050                 }
3051         }
3052
3053         if (matches) {
3054                 int i;
3055                 int matches_num, maxlen, match_len;
3056
3057                 if (matches[0][0] != '\0') {
3058                         el_deletestr(editline, (int) len);
3059                         el_insertstr(editline, matches[0]);
3060                         retval = CC_REFRESH;
3061                 }
3062
3063                 if (nummatches == 1) {
3064                         /* Found an exact match */
3065                         el_insertstr(editline, " ");
3066                         retval = CC_REFRESH;
3067                 } else {
3068                         /* Must be more than one match */
3069                         for (i = 1, maxlen = 0; matches[i]; i++) {
3070                                 match_len = strlen(matches[i]);
3071                                 if (match_len > maxlen)
3072                                         maxlen = match_len;
3073                         }
3074                         matches_num = i - 1;
3075                         if (matches_num >1) {
3076                                 fprintf(stdout, "\n");
3077                                 ast_cli_display_match_list(matches, nummatches, maxlen);
3078                                 retval = CC_REDISPLAY;
3079                         } else {
3080                                 el_insertstr(editline," ");
3081                                 retval = CC_REFRESH;
3082                         }
3083                 }
3084                 for (i = 0; matches[i]; i++)
3085                         ast_free(matches[i]);
3086                 ast_free(matches);
3087         }
3088
3089         *((char *) lf->cursor) = savechr;
3090
3091         return (char *)(long)retval;
3092 }
3093
3094 static int ast_el_initialize(void)
3095 {
3096         HistEvent ev;
3097         char *editor, *editrc = getenv("EDITRC");
3098
3099         if (!(editor = getenv("AST_EDITMODE"))) {
3100                 if (!(editor = getenv("AST_EDITOR"))) {
3101                         editor = "emacs";
3102                 }
3103         }
3104
3105         if (el != NULL)
3106                 el_end(el);
3107         if (el_hist != NULL)
3108                 history_end(el_hist);
3109
3110         el = el_init("asterisk", stdin, stdout, stderr);
3111         el_set(el, EL_PROMPT, cli_prompt);
3112
3113         el_set(el, EL_EDITMODE, 1);
3114         el_set(el, EL_EDITOR, editor);
3115         el_hist = history_init();
3116         if (!el || !el_hist)
3117                 return -1;
3118
3119         /* setup history with 100 entries */
3120         history(el_hist, &ev, H_SETSIZE, 100);
3121
3122         el_set(el, EL_HIST, history, el_hist);
3123
3124         el_set(el, EL_ADDFN, "ed-complete", "Complete argument", cli_complete);
3125         /* Bind <tab> to command completion */
3126         el_set(el, EL_BIND, "^I", "ed-complete", NULL);
3127         /* Bind ? to command completion */
3128         el_set(el, EL_BIND, "?", "ed-complete", NULL);
3129         /* Bind ^D to redisplay */
3130         el_set(el, EL_BIND, "^D", "ed-redisplay", NULL);
3131         /* Bind Delete to delete char left */
3132         el_set(el, EL_BIND, "\\e[3~", "ed-delete-next-char", NULL);
3133         /* Bind Home and End to move to line start and end */
3134         el_set(el, EL_BIND, "\\e[1~", "ed-move-to-beg", NULL);
3135         el_set(el, EL_BIND, "\\e[4~", "ed-move-to-end", NULL);
3136         /* Bind C-left and C-right to move by word (not all terminals) */
3137         el_set(el, EL_BIND, "\\eOC", "vi-next-word", NULL);
3138         el_set(el, EL_BIND, "\\eOD", "vi-prev-word", NULL);
3139
3140         if (editrc) {
3141                 el_source(el, editrc);
3142         }
3143
3144         return 0;
3145 }
3146
3147 #define MAX_HISTORY_COMMAND_LENGTH 256
3148
3149 static int ast_el_add_history(const char *buf)
3150 {
3151         HistEvent ev;
3152         char *stripped_buf;
3153
3154         if (el_hist == NULL || el == NULL) {
3155                 ast_el_initialize();
3156         }
3157         if (strlen(buf) > (MAX_HISTORY_COMMAND_LENGTH - 1)) {
3158                 return 0;
3159         }
3160
3161         stripped_buf = ast_strip(ast_strdupa(buf));
3162
3163         /* HISTCONTROL=ignoredups */
3164         if (!history(el_hist, &ev, H_FIRST) && strcmp(ev.str, stripped_buf) == 0) {
3165                 return 0;
3166         }
3167
3168         return history(el_hist, &ev, H_ENTER, stripped_buf);
3169 }
3170
3171 static int ast_el_write_history(const char *filename)
3172 {
3173         HistEvent ev;
3174
3175         if (el_hist == NULL || el == NULL)
3176                 ast_el_initialize();
3177
3178         return (history(el_hist, &ev, H_SAVE, filename));
3179 }
3180
3181 static int ast_el_read_history(const char *filename)
3182 {
3183         HistEvent ev;
3184
3185         if (el_hist == NULL || el == NULL) {
3186                 ast_el_initialize();
3187         }
3188
3189         return history(el_hist, &ev, H_LOAD, filename);
3190 }
3191
3192 static void ast_el_read_default_histfile(void)
3193 {
3194         char histfile[80] = "";
3195         const char *home = getenv("HOME");
3196
3197         if (!ast_strlen_zero(home)) {
3198                 snprintf(histfile, sizeof(histfile), "%s/.asterisk_history", home);
3199                 ast_el_read_history(histfile);
3200         }
3201 }
3202
3203 static void ast_el_write_default_histfile(void)
3204 {
3205         char histfile[80] = "";
3206         const char *home = getenv("HOME");
3207
3208         if (!ast_strlen_zero(home)) {
3209                 snprintf(histfile, sizeof(histfile), "%s/.asterisk_history", home);
3210                 ast_el_write_history(histfile);
3211         }
3212 }
3213
3214 static void ast_remotecontrol(char *data)
3215 {
3216         char buf[256] = "";
3217         int res;
3218         char *hostname;
3219         char *cpid;
3220         char *version;
3221         int pid;
3222         char *stringp = NULL;
3223
3224         char *ebuf;
3225         int num = 0;
3226
3227         ast_term_init();
3228         printf("%s", term_end());
3229         fflush(stdout);
3230
3231         memset(&sig_flags, 0, sizeof(sig_flags));
3232         signal(SIGINT, __remote_quit_handler);
3233         signal(SIGTERM, __remote_quit_handler);
3234         signal(SIGHUP, __remote_quit_handler);
3235
3236         if (read(ast_consock, buf, sizeof(buf) - 1) < 0) {
3237                 ast_log(LOG_ERROR, "read() failed: %s\n", strerror(errno));
3238                 return;
3239         }
3240         if (data) {
3241                 char prefix[] = "cli quit after ";
3242                 char *tmp = ast_alloca(strlen(data) + strlen(prefix) + 1);
3243                 sprintf(tmp, "%s%s", prefix, data);
3244                 if (write(ast_consock, tmp, strlen(tmp) + 1) < 0) {
3245                         ast_log(LOG_ERROR, "write() failed: %s\n", strerror(errno));
3246                         if (sig_flags.need_quit || sig_flags.need_quit_handler) {
3247                                 return;
3248                         }
3249                 }
3250         }
3251         stringp = buf;
3252         hostname = strsep(&stringp, "/");
3253         cpid = strsep(&stringp, "/");
3254         version = strsep(&stringp, "\n");
3255         if (!version)
3256                 version = "<Version Unknown>";
3257         stringp = hostname;
3258         strsep(&stringp, ".");
3259         if (cpid)
3260                 pid = atoi(cpid);
3261         else
3262                 pid = -1;
3263         if (!data) {
3264                 send_rasterisk_connect_commands();
3265         }
3266
3267         if (ast_opt_exec && data) {  /* hack to print output then exit if asterisk -rx is used */
3268                 int linefull = 1, prev_linefull = 1, prev_line_verbose = 0;
3269                 struct pollfd fds;
3270                 fds.fd = ast_consock;
3271                 fds.events = POLLIN;
3272                 fds.revents = 0;
3273
3274                 while (ast_poll(&fds, 1, 60000) > 0) {
3275                         char buffer[512] = "", *curline = buffer, *nextline;
3276                         int not_written = 1;
3277
3278                         if (sig_flags.need_quit || sig_flags.need_quit_handler) {
3279                                 break;
3280                         }
3281
3282                         if (read(ast_consock, buffer, sizeof(buffer) - 1) <= 0) {
3283                                 break;
3284                         }
3285
3286                         do {
3287                                 prev_linefull = linefull;
3288                                 if ((nextline = strchr(curline, '\n'))) {
3289                                         linefull = 1;
3290                                         nextline++;
3291                                 } else {
3292                                         linefull = 0;
3293                                         nextline = strchr(curline, '\0');
3294                                 }
3295
3296                                 /* Skip verbose lines */
3297                                 /* Prev line full? | Line is verbose | Last line verbose? | Print
3298                                  * TRUE            | TRUE*           | TRUE               | FALSE
3299                                  * TRUE            | TRUE*           | FALSE              | FALSE
3300                                  * TRUE            | FALSE*          | TRUE               | TRUE
3301                                  * TRUE            | FALSE*          | FALSE              | TRUE
3302                                  * FALSE           | TRUE            | TRUE*              | FALSE
3303                                  * FALSE           | TRUE            | FALSE*             | TRUE
3304                                  * FALSE           | FALSE           | TRUE*              | FALSE
3305                                  * FALSE           | FALSE           | FALSE*             | TRUE
3306                                  */
3307                                 if ((!prev_linefull && !prev_line_verbose) || (prev_linefull && *curline > 0)) {
3308                                         prev_line_verbose = 0;
3309                                         not_written = 0;
3310                                         if (write(STDOUT_FILENO, curline, nextline - curline) < 0) {
3311                                                 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
3312                                         }
3313                                 } else {
3314                                         prev_line_verbose = 1;
3315                                 }
3316                                 curline = nextline;
3317                         } while (!ast_strlen_zero(curline));
3318
3319                         /* No non-verbose output in 60 seconds. */
3320                         if (not_written) {
3321                                 break;
3322                         }
3323                 }
3324                 return;
3325         }
3326
3327         ast_verbose("Connected to Asterisk %s currently running on %s (pid = %d)\n", version, hostname, pid);
3328         remotehostname = hostname;
3329         if (el_hist == NULL || el == NULL)
3330                 ast_el_initialize();
3331         ast_el_read_default_histfile();
3332
3333         el_set(el, EL_GETCFN, ast_el_read_char);
3334
3335         for (;;) {
3336                 ebuf = (char *)el_gets(el, &num);
3337
3338                 if (sig_flags.need_quit || sig_flags.need_quit_handler) {
3339                         break;
3340                 }
3341
3342                 if (!ebuf && write(1, "", 1) < 0)
3343                         break;
3344
3345                 if (!ast_strlen_zero(ebuf)) {
3346                         if (ebuf[strlen(ebuf)-1] == '\n')
3347                                 ebuf[strlen(ebuf)-1] = '\0';
3348                         if (!remoteconsolehandler(ebuf)) {
3349                                 res = write(ast_consock, ebuf, strlen(ebuf) + 1);
3350                                 if (res < 1) {
3351                                         ast_log(LOG_WARNING, "Unable to write: %s\n", strerror(errno));
3352                                         break;
3353                                 }
3354                         }
3355                 }
3356         }
3357         printf("\nDisconnected from Asterisk server\n");
3358 }
3359
3360 static int show_version(void)
3361 {
3362         printf("Asterisk %s\n", ast_get_version());
3363         return 0;
3364 }
3365
3366 static int show_cli_help(void)
3367 {
3368         printf("Asterisk %s, Copyright (C) 1999 - 2015, Digium, Inc. and others.\n", ast_get_version());
3369         printf("Usage: asterisk [OPTIONS]\n");
3370         printf("Valid Options:\n");
3371         printf("   -V              Display version number and exit\n");
3372         printf("   -C <configfile> Use an alternate configuration file\n");
3373         printf("   -G <group>      Run as a group other than the caller\n");
3374         printf("   -U <user>       Run as a user other than the caller\n");
3375         printf("   -c              Provide console CLI\n");
3376         printf("   -d              Increase debugging (multiple d's = more debugging)\n");
3377 #if HAVE_WORKING_FORK
3378         printf("   -f              Do not fork\n");
3379         printf("   -F              Always fork\n");
3380 #endif
3381         printf("   -g              Dump core in case of a crash\n");
3382         printf("   -h              This help screen\n");
3383         printf("   -i              Initialize crypto keys at startup\n");
3384         printf("   -L <load>       Limit the maximum load average before rejecting new calls\n");
3385         printf("   -M <value>      Limit the maximum number of calls to the specified value\n");
3386         printf("   -m              Mute debugging and console output on the console\n");
3387         printf("   -n              Disable console colorization\n");
3388         printf("   -p              Run as pseudo-realtime thread\n");
3389         printf("   -q              Quiet mode (suppress output)\n");
3390         printf("   -r              Connect to Asterisk on this machine\n");
3391         printf("   -R              Same as -r, except attempt to reconnect if disconnected\n");
3392         printf("   -s <socket>     Connect to Asterisk via socket <socket> (only valid with -r)\n");
3393         printf("   -t              Record soundfiles in /var/tmp and move them where they\n");
3394         printf("                   belong after they are done\n");
3395         printf("   -T              Display the time in [Mmm dd hh:mm:ss] format for each line\n");
3396         printf("                   of output to the CLI\n");
3397         printf("   -v              Increase verbosity (multiple v's = more verbose)\n");
3398         printf("   -x <cmd>        Execute command <cmd> (implies -r)\n");
3399         printf("   -X              Enable use of #exec in asterisk.conf\n");
3400         printf("   -W              Adjust terminal colors to compensate for a light background\n");
3401         printf("\n");
3402         return 0;
3403 }
3404
3405 static void ast_readconfig(void)
3406 {
3407         struct ast_config *cfg;
3408         struct ast_variable *v;
3409         char hostname[MAXHOSTNAMELEN] = "";
3410         struct ast_flags config_flags = { CONFIG_FLAG_NOREALTIME };
3411         struct {
3412                 unsigned int dbdir:1;
3413                 unsigned int keydir:1;
3414         } found = { 0, 0 };
3415         /* Default to false for security */
3416         int live_dangerously = 0;
3417         int option_debug_new = 0;
3418         int option_verbose_new = 0;
3419
3420         /* Set default value */
3421         option_dtmfminduration = AST_MIN_DTMF_DURATION;
3422
3423         /* init with buildtime config */
3424         ast_copy_string(cfg_paths.config_dir, DEFAULT_CONFIG_DIR, sizeof(cfg_paths.config_dir));
3425         ast_copy_string(cfg_paths.spool_dir, DEFAULT_SPOOL_DIR, sizeof(cfg_paths.spool_dir));
3426         ast_copy_string(cfg_paths.module_dir, DEFAULT_MODULE_DIR, sizeof(cfg_paths.module_dir));
3427         snprintf(cfg_paths.monitor_dir, sizeof(cfg_paths.monitor_dir), "%s/monitor", cfg_paths.spool_dir);
3428         snprintf(cfg_paths.recording_dir, sizeof(cfg_paths.recording_dir), "%s/recording", cfg_paths.spool_dir);
3429         ast_copy_string(cfg_paths.var_dir, DEFAULT_VAR_DIR, sizeof(cfg_paths.var_dir));
3430         ast_copy_string(cfg_paths.data_dir, DEFAULT_DATA_DIR, sizeof(cfg_paths.data_dir));
3431         ast_copy_string(cfg_paths.log_dir, DEFAULT_LOG_DIR, sizeof(cfg_paths.log_dir));
3432         ast_copy_string(cfg_paths.agi_dir, DEFAULT_AGI_DIR, sizeof(cfg_paths.agi_dir));
3433         ast_copy_string(cfg_paths.db_path, DEFAULT_DB, sizeof(cfg_paths.db_path));
3434         ast_copy_string(cfg_paths.sbin_dir, DEFAULT_SBIN_DIR, sizeof(cfg_paths.sbin_dir));
3435         ast_copy_string(cfg_paths.key_dir, DEFAULT_KEY_DIR, sizeof(cfg_paths.key_dir));
3436         ast_copy_string(cfg_paths.pid_path, DEFAULT_PID, sizeof(cfg_paths.pid_path));
3437         ast_copy_string(cfg_paths.socket_path, DEFAULT_SOCKET, sizeof(cfg_paths.socket_path));
3438         ast_copy_string(cfg_paths.run_dir, DEFAULT_RUN_DIR, sizeof(cfg_paths.run_dir));
3439
3440 #ifdef REF_DEBUG
3441         /* The REF_DEBUG compiler flag is now only used to enable refdebug by default.
3442          * Support for debugging reference counts is always compiled in. */
3443         ast_set2_flag(&ast_options, 1, AST_OPT_FLAG_REF_DEBUG);
3444 #endif
3445
3446         ast_set_default_eid(&ast_eid_default);
3447
3448         cfg = ast_config_load2(ast_config_AST_CONFIG_FILE, "" /* core, can't reload */, config_flags);
3449
3450         /* If AST_OPT_FLAG_EXEC_INCLUDES was previously enabled with -X turn it off now.
3451          * Using #exec from other configs requires that it be enabled from asterisk.conf. */
3452         ast_clear_flag(&ast_options, AST_OPT_FLAG_EXEC_INCLUDES);
3453
3454         /* no asterisk.conf? no problem, use buildtime config! */
3455         if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEUNCHANGED || cfg == CONFIG_STATUS_FILEINVALID) {
3456                 fprintf(stderr, "Unable to open specified master config file '%s', using built-in defaults\n", ast_config_AST_CONFIG_FILE);
3457                 return;
3458         }
3459
3460         for (v = ast_variable_browse(cfg, "files"); v; v = v->next) {
3461                 if (!strcasecmp(v->name, "astctlpermissions"))
3462                         ast_copy_string(ast_config_AST_CTL_PERMISSIONS, v->value, sizeof(ast_config_AST_CTL_PERMISSIONS));
3463                 else if (!strcasecmp(v->name, "astctlowner"))
3464                         ast_copy_string(ast_config_AST_CTL_OWNER, v->value, sizeof(ast_config_AST_CTL_OWNER));
3465                 else if (!strcasecmp(v->name, "astctlgroup"))
3466                         ast_copy_string(ast_config_AST_CTL_GROUP, v->value, sizeof(ast_config_AST_CTL_GROUP));
3467                 else if (!strcasecmp(v->name, "astctl"))
3468                         ast_copy_string(ast_config_AST_CTL, v->value, sizeof(ast_config_AST_CTL));
3469         }
3470
3471         for (v = ast_variable_browse(cfg, "directories"); v; v = v->next) {
3472                 if (!strcasecmp(v->name, "astetcdir")) {
3473                         ast_copy_string(cfg_paths.config_dir, v->value, sizeof(cfg_paths.config_dir));
3474                 } else if (!strcasecmp(v->name, "astspooldir")) {
3475                         ast_copy_string(cfg_paths.spool_dir, v->value, sizeof(cfg_paths.spool_dir));
3476                         snprintf(cfg_paths.monitor_dir, sizeof(cfg_paths.monitor_dir), "%s/monitor", v->value);
3477                         snprintf(cfg_paths.recording_dir, sizeof(cfg_paths.recording_dir), "%s/recording", v->value);
3478                 } else if (!strcasecmp(v->name, "astvarlibdir")) {
3479                         ast_copy_string(cfg_paths.var_dir, v->value, sizeof(cfg_paths.var_dir));
3480                         if (!found.dbdir)
3481                                 snprintf(cfg_paths.db_path, sizeof(cfg_paths.db_path), "%s/astdb", v->value);
3482                 } else if (!strcasecmp(v->name, "astdbdir")) {
3483                         snprintf(cfg_paths.db_path, sizeof(cfg_paths.db_path), "%s/astdb", v->value);
3484                         found.dbdir = 1;
3485                 } else if (!strcasecmp(v->name, "astdatadir")) {
3486                         ast_copy_string(cfg_paths.data_dir, v->value, sizeof(cfg_paths.data_dir));
3487                         if (!found.keydir)
3488                                 snprintf(cfg_paths.key_dir, sizeof(cfg_paths.key_dir), "%s/keys", v->value);
3489                 } else if (!strcasecmp(v->name, "astkeydir")) {
3490                         snprintf(cfg_paths.key_dir, sizeof(cfg_paths.key_dir), "%s/keys", v->value);
3491                         found.keydir = 1;
3492                 } else if (!strcasecmp(v->name, "astlogdir")) {
3493                         ast_copy_string(cfg_paths.log_dir, v->value, sizeof(cfg_paths.log_dir));
3494                 } else if (!strcasecmp(v->name, "astagidir")) {
3495                         ast_copy_string(cfg_paths.agi_dir, v->value, sizeof(cfg_paths.agi_dir));
3496                 } else if (!strcasecmp(v->name, "astrundir")) {
3497                         snprintf(cfg_paths.pid_path, sizeof(cfg_paths.pid_path), "%s/%s", v->value, "asterisk.pid");
3498                         snprintf(cfg_paths.socket_path, sizeof(cfg_paths.socket_path), "%s/%s", v->value, ast_config_AST_CTL);
3499                         ast_copy_string(cfg_paths.run_dir, v->value, sizeof(cfg_paths.run_dir));
3500                 } else if (!strcasecmp(v->name, "astmoddir")) {
3501                         ast_copy_string(cfg_paths.module_dir, v->value, sizeof(cfg_paths.module_dir));
3502                 } else if (!strcasecmp(v->name, "astsbindir")) {
3503                         ast_copy_string(cfg_paths.sbin_dir, v->value, sizeof(cfg_paths.sbin_dir));
3504                 }
3505         }
3506
3507         for (v = ast_variable_browse(cfg, "options"); v; v = v->next) {
3508                 /* verbose level (-v at startup) */
3509                 if (!strcasecmp(v->name, "verbose")) {
3510                         option_verbose_new = atoi(v->value);
3511                 /* whether or not to force timestamping in CLI verbose output. (-T at startup) */
3512                 } else if (!strcasecmp(v->name, "timestamp")) {
3513                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_TIMESTAMP);
3514                 /* whether or not to support #exec in config files */
3515                 } else if (!strcasecmp(v->name, "execincludes")) {
3516                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_EXEC_INCLUDES);
3517                 /* debug level (-d at startup) */
3518                 } else if (!strcasecmp(v->name, "debug")) {
3519                         option_debug_new = 0;
3520                         if (sscanf(v->value, "%30d", &option_debug_new) != 1) {
3521                                 option_debug_new = ast_true(v->value) ? 1 : 0;
3522                         }
3523                 } else if (!strcasecmp(v->name, "refdebug")) {
3524                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_REF_DEBUG);
3525 #if HAVE_WORKING_FORK
3526                 /* Disable forking (-f at startup) */
3527                 } else if (!strcasecmp(v->name, "nofork")) {
3528                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_NO_FORK);
3529                 /* Always fork, even if verbose or debug are enabled (-F at startup) */
3530                 } else if (!strcasecmp(v->name, "alwaysfork")) {
3531                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_ALWAYS_FORK);
3532 #endif
3533                 /* Run quietly (-q at startup ) */
3534                 } else if (!strcasecmp(v->name, "quiet")) {
3535                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_QUIET);
3536                 /* Run as console (-c at startup, implies nofork) */
3537                 } else if (!strcasecmp(v->name, "console")) {
3538                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_NO_FORK | AST_OPT_FLAG_CONSOLE);
3539                 /* Run with high priority if the O/S permits (-p at startup) */
3540                 } else if (!strcasecmp(v->name, "highpriority")) {
3541                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_HIGH_PRIORITY);
3542                 /* Initialize RSA auth keys (IAX2) (-i at startup) */
3543                 } else if (!strcasecmp(v->name, "initcrypto")) {
3544                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_INIT_KEYS);
3545                 /* Disable ANSI colors for console (-c at startup) */
3546                 } else if (!strcasecmp(v->name, "nocolor")) {
3547                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_NO_COLOR);
3548                 /* Disable some usage warnings for picky people :p */
3549                 } else if (!strcasecmp(v->name, "dontwarn")) {
3550                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_DONT_WARN);
3551                 /* Dump core in case of crash (-g) */
3552                 } else if (!strcasecmp(v->name, "dumpcore")) {
3553                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_DUMP_CORE);
3554                 /* Cache recorded sound files to another directory during recording */
3555                 } else if (!strcasecmp(v->name, "cache_record_files")) {
3556                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_CACHE_RECORD_FILES);
3557                 /* Specify cache directory */
3558                 }  else if (!strcasecmp(v->name, "record_cache_dir")) {
3559                         ast_copy_string(record_cache_dir, v->value, AST_CACHE_DIR_LEN);
3560                 /* Build transcode paths via SLINEAR, instead of directly */
3561                 } else if (!strcasecmp(v->name, "transcode_via_sln")) {
3562                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_TRANSCODE_VIA_SLIN);
3563                 /* Transmit SLINEAR silence while a channel is being recorded or DTMF is being generated on a channel */
3564                 } else if (!strcasecmp(v->name, "transmit_silence_during_record") || !strcasecmp(v->name, "transmit_silence")) {
3565                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_TRANSMIT_SILENCE);
3566                 /* Enable internal timing */
3567                 } else if (!strcasecmp(v->name, "internal_timing")) {
3568                         if (!ast_opt_remote) {
3569                                 fprintf(stderr,
3570                                         "NOTICE: The internal_timing option is no longer needed.\n"
3571                                         "  It will always be enabled if you have a timing module loaded.\n");
3572                         }
3573                 } else if (!strcasecmp(v->name, "mindtmfduration")) {
3574                         if (sscanf(v->value, "%30u", &option_dtmfminduration) != 1) {
3575                                 option_dtmfminduration = AST_MIN_DTMF_DURATION;
3576                         }
3577                 } else if (!strcasecmp(v->name, "maxcalls")) {
3578                         if ((sscanf(v->value, "%30d", &ast_option_maxcalls) != 1) || (ast_option_maxcalls < 0)) {
3579                                 ast_option_maxcalls = 0;
3580                         }
3581                 } else if (!strcasecmp(v->name, "maxload")) {
3582                         double test[1];
3583
3584                         if (getloadavg(test, 1) == -1) {
3585                                 ast_log(LOG_ERROR, "Cannot obtain load average on this system. 'maxload' option disabled.\n");
3586                                 ast_option_maxload = 0.0;
3587                         } else if ((sscanf(v->value, "%30lf", &ast_option_maxload) != 1) || (ast_option_maxload < 0.0)) {
3588                                 ast_option_maxload = 0.0;
3589                         }
3590                 /* Set the maximum amount of open files */
3591                 } else if (!strcasecmp(v->name, "maxfiles")) {
3592                         ast_option_maxfiles = atoi(v->value);
3593                         set_ulimit(ast_option_maxfiles);
3594                 /* What user to run as */
3595                 } else if (!strcasecmp(v->name, "runuser")) {
3596                         ast_copy_string(cfg_paths.run_user, v->value, sizeof(cfg_paths.run_user));
3597                 /* What group to run as */
3598                 } else if (!strcasecmp(v->name, "rungroup")) {
3599                         ast_copy_string(cfg_paths.run_group, v->value, sizeof(cfg_paths.run_group));
3600                 } else if (!strcasecmp(v->name, "systemname")) {
3601                         ast_copy_string(cfg_paths.system_name, v->value, sizeof(cfg_paths.system_name));
3602                 } else if (!strcasecmp(v->name, "autosystemname")) {
3603                         if (ast_true(v->value)) {
3604                                 if (!gethostname(hostname, sizeof(hostname) - 1))
3605                                         ast_copy_string(cfg_paths.system_name, hostname, sizeof(cfg_paths.system_name));
3606                                 else {
3607                                         if (ast_strlen_zero(ast_config_AST_SYSTEM_NAME)){
3608                                                 ast_copy_string(cfg_paths.system_name, "localhost", sizeof(cfg_paths.system_name));
3609                                         }
3610                                         ast_log(LOG_ERROR, "Cannot obtain hostname for this system.  Using '%s' instead.\n", ast_config_AST_SYSTEM_NAME);
3611                                 }
3612                         }
3613                 } else if (!strcasecmp(v->name, "languageprefix")) {
3614                         ast_language_is_prefix = ast_true(v->value);
3615                 } else if (!strcasecmp(v->name, "defaultlanguage")) {
3616                         ast_copy_string(ast_defaultlanguage, v->value, MAX_LANGUAGE);
3617                 } else if (!strcasecmp(v->name, "lockmode")) {
3618                         if (!strcasecmp(v->value, "lockfile")) {
3619                                 ast_set_lock_type(AST_LOCK_TYPE_LOCKFILE);
3620                         } else if (!strcasecmp(v->value, "flock")) {
3621                                 ast_set_lock_type(AST_LOCK_TYPE_FLOCK);
3622                         } else {
3623                                 ast_log(LOG_WARNING, "'%s' is not a valid setting for the lockmode option, "
3624                                         "defaulting to 'lockfile'\n", v->value);
3625                                 ast_set_lock_type(AST_LOCK_TYPE_LOCKFILE);
3626                         }
3627 #if defined(HAVE_SYSINFO)
3628                 } else if (!strcasecmp(v->name, "minmemfree")) {
3629                         /* specify the minimum amount of free memory to retain.  Asterisk should stop accepting new calls
3630                          * if the amount of free memory falls below this watermark */
3631                         if ((sscanf(v->value, "%30ld", &option_minmemfree) != 1) || (option_minmemfree < 0)) {
3632                                 option_minmemfree = 0;
3633                         }
3634 #endif
3635                 } else if (!strcasecmp(v->name, "entityid")) {
3636                         struct ast_eid tmp_eid;
3637                         if (!ast_str_to_eid(&tmp_eid, v->value)) {
3638                                 ast_verbose("Successfully set global EID to '%s'\n", v->value);
3639                                 ast_eid_default = tmp_eid;
3640                         } else
3641                                 ast_verbose("Invalid Entity ID '%s' provided\n", v->value);
3642                 } else if (!strcasecmp(v->name, "lightbackground")) {
3643                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_LIGHT_BACKGROUND);
3644                 } else if (!strcasecmp(v->name, "forceblackbackground")) {
3645                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_FORCE_BLACK_BACKGROUND);
3646                 } else if (!strcasecmp(v->name, "hideconnect")) {
3647                         ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_HIDE_CONSOLE_CONNECT);
3648                 } else if (!strcasecmp(v->name, "lockconfdir")) {
3649          &n