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