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