2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 1999 - 2014, Digium, Inc.
6 * Mark Spencer <markster@digium.com>
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.
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.
20 /* Doxygenified Copyright Header */
22 * \mainpage Asterisk -- The Open Source Telephony Project
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
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
36 * \par Developer Documentation for Asterisk
38 * This is the main developer documentation for Asterisk. It is
39 * generated by running "make progdocs" from the Asterisk source tree.
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.
45 * \arg \ref AsteriskArchitecture
47 * \par Additional documentation
50 * \arg \ref configuration_file
51 * \arg \ref channel_drivers
52 * \arg \ref applications
54 * \section copyright Copyright and Author
56 * Copyright (C) 1999 - 2014, 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>.
60 * \author Mark Spencer <markster@digium.com>
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.
71 * \page asterisk_community_resources Asterisk Community Resources
73 * \li http://www.asterisk.org Asterisk Homepage
74 * \li http://wiki.asterisk.org Asterisk Wiki
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
117 * \li Forums are located at http://forums.asterisk.org/
121 * Use http://www.freenode.net IRC server to connect with Asterisk
122 * developers and users in realtime.
124 * \li \verbatim #asterisk \endverbatim Asterisk Users Room
125 * \li \verbatim #asterisk-dev \endverbatim Asterisk Developers Room
129 * If you would like to add a resource to this list please create an issue
130 * on the issue tracker with a patch.
134 * \brief Top level source file for Asterisk - the Open Source PBX.
135 * Implementation of PBX core functions and CLI interface.
138 /*! \li \ref asterisk.c uses the configuration file \ref asterisk.conf
139 * \addtogroup configuration_file
142 /*! \page asterisk.conf asterisk.conf
143 * \verbinclude asterisk.conf.sample
147 <support_level>core</support_level>
150 #include "asterisk.h"
152 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
154 #include "asterisk/_private.h"
156 #undef sched_setscheduler
158 #include <sys/time.h>
163 #include <sys/wait.h>
165 #include <sys/resource.h>
168 #include <sys/stat.h>
169 #if defined(HAVE_SYSINFO)
170 #include <sys/sysinfo.h>
171 #elif defined(HAVE_SYSCTL)
172 #include <sys/param.h>
173 #include <sys/sysctl.h>
174 #if !defined(__OpenBSD__)
175 #include <sys/vmmeter.h>
176 #if defined(__FreeBSD__)
177 #include <vm/vm_param.h>
180 #if defined(HAVE_SWAPCTL)
181 #include <sys/swap.h>
185 #include <histedit.h>
188 int daemon(int, int); /* defined in libresolv of all places */
189 #include <sys/loadavg.h>
193 #include <sys/prctl.h>
195 #include <sys/capability.h>
196 #endif /* HAVE_CAP */
199 /* we define here the variables so to better agree on the prototype */
200 #include "asterisk/paths.h"
201 #include "asterisk/network.h"
202 #include "asterisk/cli.h"
203 #include "asterisk/channel.h"
204 #include "asterisk/translate.h"
205 #include "asterisk/pickup.h"
206 #include "asterisk/features.h"
207 #include "asterisk/acl.h"
208 #include "asterisk/ulaw.h"
209 #include "asterisk/alaw.h"
210 #include "asterisk/callerid.h"
211 #include "asterisk/image.h"
212 #include "asterisk/tdd.h"
213 #include "asterisk/term.h"
214 #include "asterisk/manager.h"
215 #include "asterisk/cdr.h"
216 #include "asterisk/cel.h"
217 #include "asterisk/pbx.h"
218 #include "asterisk/enum.h"
219 #include "asterisk/http.h"
220 #include "asterisk/udptl.h"
221 #include "asterisk/app.h"
222 #include "asterisk/lock.h"
223 #include "asterisk/utils.h"
224 #include "asterisk/file.h"
225 #include "asterisk/io.h"
226 #include "editline/histedit.h"
227 #include "asterisk/config.h"
228 #include "asterisk/ast_version.h"
229 #include "asterisk/linkedlists.h"
230 #include "asterisk/devicestate.h"
231 #include "asterisk/presencestate.h"
232 #include "asterisk/module.h"
233 #include "asterisk/dsp.h"
234 #include "asterisk/buildinfo.h"
235 #include "asterisk/xmldoc.h"
236 #include "asterisk/poll-compat.h"
237 #include "asterisk/ccss.h"
238 #include "asterisk/test.h"
239 #include "asterisk/rtp_engine.h"
240 #include "asterisk/format.h"
241 #include "asterisk/aoc.h"
242 #include "asterisk/uuid.h"
243 #include "asterisk/sorcery.h"
244 #include "asterisk/bucket.h"
245 #include "asterisk/stasis.h"
246 #include "asterisk/json.h"
247 #include "asterisk/stasis_endpoints.h"
248 #include "asterisk/stasis_system.h"
249 #include "asterisk/security_events.h"
250 #include "asterisk/endpoints.h"
251 #include "asterisk/codec.h"
252 #include "asterisk/format_cache.h"
254 #include "../defaults.h"
257 <managerEvent language="en_US" name="FullyBooted">
258 <managerEventInstance class="EVENT_FLAG_SYSTEM">
259 <synopsis>Raised when all Asterisk initialization procedures have finished.</synopsis>
261 <parameter name="Status">
262 <para>Informational message</para>
265 </managerEventInstance>
267 <managerEvent language="en_US" name="Shutdown">
268 <managerEventInstance class="EVENT_FLAG_SYSTEM">
269 <synopsis>Raised when Asterisk is shutdown or restarted.</synopsis>
271 <parameter name="Shutdown">
272 <para>Whether the shutdown is proceeding cleanly (all channels
273 were hungup successfully) or uncleanly (channels will be
276 <enum name="Uncleanly"/>
277 <enum name="Cleanly"/>
280 <parameter name="Restart">
281 <para>Whether or not a restart will occur.</para>
288 </managerEventInstance>
293 #define AF_LOCAL AF_UNIX
294 #define PF_LOCAL PF_UNIX
297 #define AST_MAX_CONNECTS 128
300 /*! Default minimum DTMF digit length - 80ms */
301 #define AST_MIN_DTMF_DURATION 80
304 /*! \brief Welcome message when starting a CLI interface */
305 #define WELCOME_MESSAGE \
306 ast_verbose("Asterisk %s, Copyright (C) 1999 - 2014, Digium, Inc. and others.\n" \
307 "Created by Mark Spencer <markster@digium.com>\n" \
308 "Asterisk comes with ABSOLUTELY NO WARRANTY; type 'core show warranty' for details.\n" \
309 "This is free software, with components licensed under the GNU General Public\n" \
310 "License version 2 and other licenses; you are welcome to redistribute it under\n" \
311 "certain conditions. Type 'core show license' for details.\n" \
312 "=========================================================================\n", ast_get_version()) \
314 /*! \defgroup main_options Main Configuration Options
315 * \brief Main configuration options from asterisk.conf or OS command line on starting Asterisk.
316 * \arg \ref Config_ast "asterisk.conf"
317 * \note Some of them can be changed in the CLI
321 struct ast_flags ast_options = { AST_DEFAULT_OPTIONS };
323 /*! Maximum active system verbosity level. */
324 int ast_verb_sys_level;
326 int option_verbose; /*!< Verbosity level */
327 int option_debug; /*!< Debug level */
328 double ast_option_maxload; /*!< Max load avg on system */
329 int ast_option_maxcalls; /*!< Max number of active calls */
330 int ast_option_maxfiles; /*!< Max number of open file handles (files, sockets) */
331 unsigned int option_dtmfminduration; /*!< Minimum duration of DTMF. */
332 #if defined(HAVE_SYSINFO)
333 long option_minmemfree; /*!< Minimum amount of free system memory - stop accepting calls if free memory falls below this watermark */
338 struct ast_eid ast_eid_default;
340 /* XXX tmpdir is a subdir of the spool directory, and no way to remap it */
341 char record_cache_dir[AST_CACHE_DIR_LEN] = DEFAULT_TMP_DIR;
343 static int ast_socket = -1; /*!< UNIX Socket for allowing remote control */
344 static int ast_consock = -1; /*!< UNIX Socket for controlling another asterisk */
347 int fd; /*!< File descriptor */
348 int p[2]; /*!< Pipe */
349 pthread_t t; /*!< Thread of handler */
350 int mute; /*!< Is the console muted for logs */
351 int uid; /*!< Remote user ID. */
352 int gid; /*!< Remote group ID. */
353 int levels[NUMLOGLEVELS]; /*!< Which log levels are enabled for the console */
354 /*! Verbosity level of this console. */
361 AST_LIST_ENTRY(ast_atexit) list;
364 static AST_LIST_HEAD_STATIC(atexits, ast_atexit);
366 struct timeval ast_startuptime;
367 struct timeval ast_lastreloadtime;
369 static History *el_hist;
371 static char *remotehostname;
373 struct console consoles[AST_MAX_CONNECTS];
375 char ast_defaultlanguage[MAX_LANGUAGE] = DEFAULT_LANGUAGE;
377 static int ast_el_add_history(char *);
378 static int ast_el_read_history(char *);
379 static int ast_el_write_history(char *);
382 char config_dir[PATH_MAX];
383 char module_dir[PATH_MAX];
384 char spool_dir[PATH_MAX];
385 char monitor_dir[PATH_MAX];
386 char recording_dir[PATH_MAX];
387 char var_dir[PATH_MAX];
388 char data_dir[PATH_MAX];
389 char log_dir[PATH_MAX];
390 char agi_dir[PATH_MAX];
391 char run_dir[PATH_MAX];
392 char key_dir[PATH_MAX];
394 char config_file[PATH_MAX];
395 char db_path[PATH_MAX];
396 char sbin_dir[PATH_MAX];
397 char pid_path[PATH_MAX];
398 char socket_path[PATH_MAX];
399 char run_user[PATH_MAX];
400 char run_group[PATH_MAX];
401 char system_name[128];
404 static struct _cfg_paths cfg_paths;
406 const char *ast_config_AST_CONFIG_DIR = cfg_paths.config_dir;
407 const char *ast_config_AST_CONFIG_FILE = cfg_paths.config_file;
408 const char *ast_config_AST_MODULE_DIR = cfg_paths.module_dir;
409 const char *ast_config_AST_SPOOL_DIR = cfg_paths.spool_dir;
410 const char *ast_config_AST_MONITOR_DIR = cfg_paths.monitor_dir;
411 const char *ast_config_AST_RECORDING_DIR = cfg_paths.recording_dir;
412 const char *ast_config_AST_VAR_DIR = cfg_paths.var_dir;
413 const char *ast_config_AST_DATA_DIR = cfg_paths.data_dir;
414 const char *ast_config_AST_LOG_DIR = cfg_paths.log_dir;
415 const char *ast_config_AST_AGI_DIR = cfg_paths.agi_dir;
416 const char *ast_config_AST_KEY_DIR = cfg_paths.key_dir;
417 const char *ast_config_AST_RUN_DIR = cfg_paths.run_dir;
418 const char *ast_config_AST_SBIN_DIR = cfg_paths.sbin_dir;
420 const char *ast_config_AST_DB = cfg_paths.db_path;
421 const char *ast_config_AST_PID = cfg_paths.pid_path;
422 const char *ast_config_AST_SOCKET = cfg_paths.socket_path;
423 const char *ast_config_AST_RUN_USER = cfg_paths.run_user;
424 const char *ast_config_AST_RUN_GROUP = cfg_paths.run_group;
425 const char *ast_config_AST_SYSTEM_NAME = cfg_paths.system_name;
427 static char ast_config_AST_CTL_PERMISSIONS[PATH_MAX];
428 static char ast_config_AST_CTL_OWNER[PATH_MAX] = "\0";
429 static char ast_config_AST_CTL_GROUP[PATH_MAX] = "\0";
430 static char ast_config_AST_CTL[PATH_MAX] = "asterisk.ctl";
432 extern unsigned int ast_FD_SETSIZE;
434 static char *_argv[256];
436 NOT_SHUTTING_DOWN = -2,
438 /* Valid values for quit_handler niceness below: */
444 static shutdown_nice_t shuttingdown = NOT_SHUTTING_DOWN;
445 static int restartnow;
446 static pthread_t consolethread = AST_PTHREADT_NULL;
447 static pthread_t mon_sig_flags;
448 static int canary_pid = 0;
449 static char canary_filename[128];
450 static int multi_thread_safe;
452 static char randompool[256];
454 static int sig_alert_pipe[2] = { -1, -1 };
456 unsigned int need_reload:1;
457 unsigned int need_quit:1;
458 unsigned int need_quit_handler:1;
461 #if !defined(LOW_MEMORY)
462 struct file_version {
463 AST_RWLIST_ENTRY(file_version) list;
468 static AST_RWLIST_HEAD_STATIC(file_versions, file_version);
470 void ast_register_file_version(const char *file, const char *version)
472 struct file_version *new;
474 size_t version_length;
476 work = ast_strdupa(version);
477 work = ast_strip(ast_strip_quoted(work, "$", "$"));
478 version_length = strlen(work) + 1;
480 if (!(new = ast_calloc(1, sizeof(*new) + version_length)))
484 new->version = (char *) new + sizeof(*new);
485 memcpy(new->version, work, version_length);
486 AST_RWLIST_WRLOCK(&file_versions);
487 AST_RWLIST_INSERT_HEAD(&file_versions, new, list);
488 AST_RWLIST_UNLOCK(&file_versions);
491 void ast_unregister_file_version(const char *file)
493 struct file_version *find;
495 AST_RWLIST_WRLOCK(&file_versions);
496 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&file_versions, find, list) {
497 if (!strcasecmp(find->file, file)) {
498 AST_RWLIST_REMOVE_CURRENT(list);
502 AST_RWLIST_TRAVERSE_SAFE_END;
503 AST_RWLIST_UNLOCK(&file_versions);
509 char *ast_complete_source_filename(const char *partial, int n)
511 struct file_version *find;
512 size_t len = strlen(partial);
516 AST_RWLIST_RDLOCK(&file_versions);
517 AST_RWLIST_TRAVERSE(&file_versions, find, list) {
518 if (!strncasecmp(find->file, partial, len) && ++count > n) {
519 res = ast_strdup(find->file);
523 AST_RWLIST_UNLOCK(&file_versions);
527 /*! \brief Find version for given module name */
528 const char *ast_file_version_find(const char *file)
530 struct file_version *iterator;
532 AST_RWLIST_WRLOCK(&file_versions);
533 AST_RWLIST_TRAVERSE(&file_versions, iterator, list) {
534 if (!strcasecmp(iterator->file, file))
537 AST_RWLIST_UNLOCK(&file_versions);
539 return iterator->version;
543 struct thread_list_t {
544 AST_RWLIST_ENTRY(thread_list_t) list;
550 static AST_RWLIST_HEAD_STATIC(thread_list, thread_list_t);
552 void ast_register_thread(char *name)
554 struct thread_list_t *new = ast_calloc(1, sizeof(*new));
559 ast_assert(multi_thread_safe);
560 new->id = pthread_self();
561 new->lwp = ast_get_tid();
562 new->name = name; /* steal the allocated memory for the thread name */
563 AST_RWLIST_WRLOCK(&thread_list);
564 AST_RWLIST_INSERT_HEAD(&thread_list, new, list);
565 AST_RWLIST_UNLOCK(&thread_list);
568 void ast_unregister_thread(void *id)
570 struct thread_list_t *x;
572 AST_RWLIST_WRLOCK(&thread_list);
573 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&thread_list, x, list) {
574 if ((void *) x->id == id) {
575 AST_RWLIST_REMOVE_CURRENT(list);
579 AST_RWLIST_TRAVERSE_SAFE_END;
580 AST_RWLIST_UNLOCK(&thread_list);
587 /*! \brief Give an overview of core settings */
588 static char *handle_show_settings(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
596 e->command = "core show settings";
597 e->usage = "Usage: core show settings\n"
598 " Show core misc settings";
604 ast_eid_to_str(eid_str, sizeof(eid_str), &ast_eid_default);
606 ast_cli(a->fd, "\nPBX Core settings\n");
607 ast_cli(a->fd, "-----------------\n");
608 ast_cli(a->fd, " Version: %s\n", ast_get_version());
609 ast_cli(a->fd, " Build Options: %s\n", S_OR(AST_BUILDOPTS, "(none)"));
610 if (ast_option_maxcalls)
611 ast_cli(a->fd, " Maximum calls: %d (Current %d)\n", ast_option_maxcalls, ast_active_channels());
613 ast_cli(a->fd, " Maximum calls: Not set\n");
614 if (ast_option_maxfiles)
615 ast_cli(a->fd, " Maximum open file handles: %d\n", ast_option_maxfiles);
617 ast_cli(a->fd, " Maximum open file handles: Not set\n");
618 ast_cli(a->fd, " Root console verbosity: %d\n", option_verbose);
619 ast_cli(a->fd, " Current console verbosity: %d\n", ast_verb_console_get());
620 ast_cli(a->fd, " Debug level: %d\n", option_debug);
621 ast_cli(a->fd, " Maximum load average: %lf\n", ast_option_maxload);
622 #if defined(HAVE_SYSINFO)
623 ast_cli(a->fd, " Minimum free memory: %ld MB\n", option_minmemfree);
625 if (ast_localtime(&ast_startuptime, &tm, NULL)) {
626 ast_strftime(buf, sizeof(buf), "%H:%M:%S", &tm);
627 ast_cli(a->fd, " Startup time: %s\n", buf);
629 if (ast_localtime(&ast_lastreloadtime, &tm, NULL)) {
630 ast_strftime(buf, sizeof(buf), "%H:%M:%S", &tm);
631 ast_cli(a->fd, " Last reload time: %s\n", buf);
633 ast_cli(a->fd, " System: %s/%s built by %s on %s %s\n", ast_build_os, ast_build_kernel, ast_build_user, ast_build_machine, ast_build_date);
634 ast_cli(a->fd, " System name: %s\n", ast_config_AST_SYSTEM_NAME);
635 ast_cli(a->fd, " Entity ID: %s\n", eid_str);
636 ast_cli(a->fd, " Default language: %s\n", ast_defaultlanguage);
637 ast_cli(a->fd, " Language prefix: %s\n", ast_language_is_prefix ? "Enabled" : "Disabled");
638 ast_cli(a->fd, " User name and group: %s/%s\n", ast_config_AST_RUN_USER, ast_config_AST_RUN_GROUP);
639 ast_cli(a->fd, " Executable includes: %s\n", ast_test_flag(&ast_options, AST_OPT_FLAG_EXEC_INCLUDES) ? "Enabled" : "Disabled");
640 ast_cli(a->fd, " Transcode via SLIN: %s\n", ast_test_flag(&ast_options, AST_OPT_FLAG_TRANSCODE_VIA_SLIN) ? "Enabled" : "Disabled");
641 ast_cli(a->fd, " Transmit silence during rec: %s\n", ast_test_flag(&ast_options, AST_OPT_FLAG_TRANSMIT_SILENCE) ? "Enabled" : "Disabled");
642 ast_cli(a->fd, " Generic PLC: %s\n", ast_test_flag(&ast_options, AST_OPT_FLAG_GENERIC_PLC) ? "Enabled" : "Disabled");
643 ast_cli(a->fd, " Min DTMF duration:: %u\n", option_dtmfminduration);
645 ast_cli(a->fd, "\n* Subsystems\n");
646 ast_cli(a->fd, " -------------\n");
647 ast_cli(a->fd, " Manager (AMI): %s\n", check_manager_enabled() ? "Enabled" : "Disabled");
648 ast_cli(a->fd, " Web Manager (AMI/HTTP): %s\n", check_webmanager_enabled() ? "Enabled" : "Disabled");
649 ast_cli(a->fd, " Call data records: %s\n", ast_cdr_is_enabled() ? "Enabled" : "Disabled");
650 ast_cli(a->fd, " Realtime Architecture (ARA): %s\n", ast_realtime_enabled() ? "Enabled" : "Disabled");
652 /*! \todo we could check musiconhold, voicemail, smdi, adsi, queues */
654 ast_cli(a->fd, "\n* Directories\n");
655 ast_cli(a->fd, " -------------\n");
656 ast_cli(a->fd, " Configuration file: %s\n", ast_config_AST_CONFIG_FILE);
657 ast_cli(a->fd, " Configuration directory: %s\n", ast_config_AST_CONFIG_DIR);
658 ast_cli(a->fd, " Module directory: %s\n", ast_config_AST_MODULE_DIR);
659 ast_cli(a->fd, " Spool directory: %s\n", ast_config_AST_SPOOL_DIR);
660 ast_cli(a->fd, " Log directory: %s\n", ast_config_AST_LOG_DIR);
661 ast_cli(a->fd, " Run/Sockets directory: %s\n", ast_config_AST_RUN_DIR);
662 ast_cli(a->fd, " PID file: %s\n", ast_config_AST_PID);
663 ast_cli(a->fd, " VarLib directory: %s\n", ast_config_AST_VAR_DIR);
664 ast_cli(a->fd, " Data directory: %s\n", ast_config_AST_DATA_DIR);
665 ast_cli(a->fd, " ASTDB: %s\n", ast_config_AST_DB);
666 ast_cli(a->fd, " IAX2 Keys directory: %s\n", ast_config_AST_KEY_DIR);
667 ast_cli(a->fd, " AGI Scripts directory: %s\n", ast_config_AST_AGI_DIR);
668 ast_cli(a->fd, "\n\n");
672 static char *handle_show_threads(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
675 struct thread_list_t *cur;
678 e->command = "core show threads";
680 "Usage: core show threads\n"
681 " List threads currently active in the system.\n";
687 AST_RWLIST_RDLOCK(&thread_list);
688 AST_RWLIST_TRAVERSE(&thread_list, cur, list) {
689 ast_cli(a->fd, "%p %d %s\n", (void *)cur->id, cur->lwp, cur->name);
692 AST_RWLIST_UNLOCK(&thread_list);
693 ast_cli(a->fd, "%d threads listed.\n", count);
697 #if defined (HAVE_SYSCTL) && defined(HAVE_SWAPCTL)
699 * swapmode is rewritten by Tobias Weingartner <weingart@openbsd.org>
700 * to be based on the new swapctl(2) system call.
702 static int swapmode(int *used, int *total)
704 struct swapent *swdev;
705 int nswap, rnswap, i;
707 nswap = swapctl(SWAP_NSWAP, 0, 0);
711 swdev = ast_calloc(nswap, sizeof(*swdev));
715 rnswap = swapctl(SWAP_STATS, swdev, nswap);
721 /* if rnswap != nswap, then what? */
723 /* Total things up */
725 for (i = 0; i < nswap; i++) {
726 if (swdev[i].se_flags & SWF_ENABLE) {
727 *used += (swdev[i].se_inuse / (1024 / DEV_BSIZE));
728 *total += (swdev[i].se_nblks / (1024 / DEV_BSIZE));
734 #elif defined(HAVE_SYSCTL) && !defined(HAVE_SYSINFO)
735 static int swapmode(int *used, int *total)
742 #if defined(HAVE_SYSINFO) || defined(HAVE_SYSCTL)
743 /*! \brief Give an overview of system statistics */
744 static char *handle_show_sysinfo(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
746 uint64_t physmem, freeram;
747 uint64_t freeswap = 0;
751 #if defined(HAVE_SYSINFO)
752 struct sysinfo sys_info;
754 uptime = sys_info.uptime / 3600;
755 physmem = sys_info.totalram * sys_info.mem_unit;
756 freeram = (sys_info.freeram * sys_info.mem_unit) / 1024;
757 totalswap = (sys_info.totalswap * sys_info.mem_unit) / 1024;
758 freeswap = (sys_info.freeswap * sys_info.mem_unit) / 1024;
759 nprocs = sys_info.procs;
760 #elif defined(HAVE_SYSCTL)
761 static int pageshift;
762 struct vmtotal vmtotal;
763 struct timeval boottime;
765 int mib[2], pagesize, usedswap = 0;
767 /* calculate the uptime by looking at boottime */
770 mib[1] = KERN_BOOTTIME;
771 len = sizeof(boottime);
772 if (sysctl(mib, 2, &boottime, &len, NULL, 0) != -1) {
773 uptime = now - boottime.tv_sec;
775 uptime = uptime/3600;
776 /* grab total physical memory */
778 #if defined(HW_PHYSMEM64)
779 mib[1] = HW_PHYSMEM64;
783 len = sizeof(physmem);
784 sysctl(mib, 2, &physmem, &len, NULL, 0);
786 pagesize = getpagesize();
788 while (pagesize > 1) {
793 /* we only need the amount of log(2)1024 for our conversion */
799 len = sizeof(vmtotal);
800 sysctl(mib, 2, &vmtotal, &len, NULL, 0);
801 freeram = (vmtotal.t_free << pageshift);
802 /* generate swap usage and totals */
803 swapmode(&usedswap, &totalswap);
804 freeswap = (totalswap - usedswap);
805 /* grab number of processes */
806 #if defined(__OpenBSD__)
808 mib[1] = KERN_NPROCS;
809 len = sizeof(nprocs);
810 sysctl(mib, 2, &nprocs, &len, NULL, 0);
816 e->command = "core show sysinfo";
818 "Usage: core show sysinfo\n"
819 " List current system information.\n";
825 ast_cli(a->fd, "\nSystem Statistics\n");
826 ast_cli(a->fd, "-----------------\n");
827 ast_cli(a->fd, " System Uptime: %ld hours\n", uptime);
828 ast_cli(a->fd, " Total RAM: %" PRIu64 " KiB\n", physmem / 1024);
829 ast_cli(a->fd, " Free RAM: %" PRIu64 " KiB\n", freeram);
830 #if defined(HAVE_SYSINFO)
831 ast_cli(a->fd, " Buffer RAM: %" PRIu64 " KiB\n", ((uint64_t) sys_info.bufferram * sys_info.mem_unit) / 1024);
833 #if defined (HAVE_SYSCTL) || defined(HAVE_SWAPCTL)
834 ast_cli(a->fd, " Total Swap Space: %d KiB\n", totalswap);
835 ast_cli(a->fd, " Free Swap Space: %" PRIu64 " KiB\n\n", freeswap);
837 ast_cli(a->fd, " Number of Processes: %d \n\n", nprocs);
842 struct profile_entry {
844 uint64_t scale; /* if non-zero, values are scaled by this */
850 struct profile_data {
853 struct profile_entry e[0];
856 static struct profile_data *prof_data;
858 /*! \brief allocates a counter with a given name and scale.
859 * \return Returns the identifier of the counter.
861 int ast_add_profile(const char *name, uint64_t scale)
863 int l = sizeof(struct profile_data);
864 int n = 10; /* default entries */
866 if (prof_data == NULL) {
867 prof_data = ast_calloc(1, l + n*sizeof(struct profile_entry));
868 if (prof_data == NULL)
870 prof_data->entries = 0;
871 prof_data->max_size = n;
873 if (prof_data->entries >= prof_data->max_size) {
875 n = prof_data->max_size + 20;
876 p = ast_realloc(prof_data, l + n*sizeof(struct profile_entry));
880 prof_data->max_size = n;
882 n = prof_data->entries++;
883 prof_data->e[n].name = ast_strdup(name);
884 prof_data->e[n].value = 0;
885 prof_data->e[n].events = 0;
886 prof_data->e[n].mark = 0;
887 prof_data->e[n].scale = scale;
891 int64_t ast_profile(int i, int64_t delta)
893 if (!prof_data || i < 0 || i > prof_data->entries) /* invalid index */
895 if (prof_data->e[i].scale > 1)
896 delta /= prof_data->e[i].scale;
897 prof_data->e[i].value += delta;
898 prof_data->e[i].events++;
899 return prof_data->e[i].value;
902 /* The RDTSC instruction was introduced on the Pentium processor and is not
903 * implemented on certain clones, like the Cyrix 586. Hence, the previous
904 * expectation of __i386__ was in error. */
905 #if defined ( __i686__) && (defined(__FreeBSD__) || defined(linux))
906 #if defined(__FreeBSD__)
907 #include <machine/cpufunc.h>
909 static __inline uint64_t
914 __asm __volatile(".byte 0x0f, 0x31" : "=A" (rv));
918 #else /* supply a dummy function on other platforms */
919 static __inline uint64_t
926 int64_t ast_mark(int i, int startstop)
928 if (!prof_data || i < 0 || i > prof_data->entries) /* invalid index */
931 prof_data->e[i].mark = rdtsc();
933 prof_data->e[i].mark = (rdtsc() - prof_data->e[i].mark);
934 if (prof_data->e[i].scale > 1)
935 prof_data->e[i].mark /= prof_data->e[i].scale;
936 prof_data->e[i].value += prof_data->e[i].mark;
937 prof_data->e[i].events++;
939 return prof_data->e[i].mark;
942 #define DEFINE_PROFILE_MIN_MAX_VALUES min = 0; \
943 max = prof_data->entries;\
944 if (a->argc > 3) { /* specific entries */ \
945 if (isdigit(a->argv[3][0])) { \
946 min = atoi(a->argv[3]); \
947 if (a->argc == 5 && strcmp(a->argv[4], "-")) \
948 max = atoi(a->argv[4]); \
950 search = a->argv[3]; \
952 if (max > prof_data->entries) \
953 max = prof_data->entries;
955 static char *handle_show_profile(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
958 const char *search = NULL;
961 e->command = "core show profile";
962 e->usage = "Usage: core show profile\n"
963 " show profile information";
969 if (prof_data == NULL)
972 DEFINE_PROFILE_MIN_MAX_VALUES;
973 ast_cli(a->fd, "profile values (%d, allocated %d)\n-------------------\n",
974 prof_data->entries, prof_data->max_size);
975 ast_cli(a->fd, "%6s %8s %10s %12s %12s %s\n", "ID", "Scale", "Events",
976 "Value", "Average", "Name");
977 for (i = min; i < max; i++) {
978 struct profile_entry *entry = &prof_data->e[i];
979 if (!search || strstr(entry->name, search))
980 ast_cli(a->fd, "%6d: [%8ld] %10ld %12lld %12lld %s\n",
983 (long)entry->events, (long long)entry->value,
984 (long long)(entry->events ? entry->value / entry->events : entry->value),
990 static char *handle_clear_profile(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
993 const char *search = NULL;
996 e->command = "core clear profile";
997 e->usage = "Usage: core clear profile\n"
998 " clear profile information";
1004 if (prof_data == NULL)
1007 DEFINE_PROFILE_MIN_MAX_VALUES;
1008 for (i= min; i < max; i++) {
1009 if (!search || strstr(prof_data->e[i].name, search)) {
1010 prof_data->e[i].value = 0;
1011 prof_data->e[i].events = 0;
1016 #undef DEFINE_PROFILE_MIN_MAX_VALUES
1018 /*! \brief CLI command to list module versions */
1019 static char *handle_show_version_files(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1021 #define FORMAT "%-25.25s %-40.40s\n"
1022 struct file_version *iterator;
1024 int havepattern = 0;
1026 int count_files = 0;
1028 int matchlen, which = 0;
1029 struct file_version *find;
1033 e->command = "core show file version [like]";
1035 "Usage: core show file version [like <pattern>]\n"
1036 " Lists the revision numbers of the files used to build this copy of Asterisk.\n"
1037 " Optional regular expression pattern is used to filter the file list.\n";
1040 matchlen = strlen(a->word);
1043 AST_RWLIST_RDLOCK(&file_versions);
1044 AST_RWLIST_TRAVERSE(&file_versions, find, list) {
1045 if (!strncasecmp(a->word, find->file, matchlen) && ++which > a->n) {
1046 ret = ast_strdup(find->file);
1050 AST_RWLIST_UNLOCK(&file_versions);
1057 if (!strcasecmp(a->argv[4], "like")) {
1058 if (regcomp(®exbuf, a->argv[5], REG_EXTENDED | REG_NOSUB))
1059 return CLI_SHOWUSAGE;
1062 return CLI_SHOWUSAGE;
1070 return CLI_SHOWUSAGE;
1073 ast_cli(a->fd, FORMAT, "File", "Revision");
1074 ast_cli(a->fd, FORMAT, "----", "--------");
1075 AST_RWLIST_RDLOCK(&file_versions);
1076 AST_RWLIST_TRAVERSE(&file_versions, iterator, list) {
1077 if (havename && strcasecmp(iterator->file, a->argv[4]))
1080 if (havepattern && regexec(®exbuf, iterator->file, 0, NULL, 0))
1083 ast_cli(a->fd, FORMAT, iterator->file, iterator->version);
1088 AST_RWLIST_UNLOCK(&file_versions);
1090 ast_cli(a->fd, "%d files listed.\n", count_files);
1100 #endif /* ! LOW_MEMORY */
1102 static void publish_fully_booted(void)
1104 RAII_VAR(struct ast_json *, json_object, NULL, ast_json_unref);
1106 json_object = ast_json_pack("{s: s}",
1107 "Status", "Fully Booted");
1108 ast_manager_publish_event("FullyBooted", EVENT_FLAG_SYSTEM, json_object);
1111 static void ast_run_atexits(int run_cleanups)
1113 struct ast_atexit *ae;
1115 AST_LIST_LOCK(&atexits);
1116 while ((ae = AST_LIST_REMOVE_HEAD(&atexits, list))) {
1117 if (ae->func && (!ae->is_cleanup || run_cleanups)) {
1122 AST_LIST_UNLOCK(&atexits);
1125 static void __ast_unregister_atexit(void (*func)(void))
1127 struct ast_atexit *ae;
1129 AST_LIST_TRAVERSE_SAFE_BEGIN(&atexits, ae, list) {
1130 if (ae->func == func) {
1131 AST_LIST_REMOVE_CURRENT(list);
1136 AST_LIST_TRAVERSE_SAFE_END;
1139 static int register_atexit(void (*func)(void), int is_cleanup)
1141 struct ast_atexit *ae;
1143 ae = ast_calloc(1, sizeof(*ae));
1148 ae->is_cleanup = is_cleanup;
1150 AST_LIST_LOCK(&atexits);
1151 __ast_unregister_atexit(func);
1152 AST_LIST_INSERT_HEAD(&atexits, ae, list);
1153 AST_LIST_UNLOCK(&atexits);
1158 int ast_register_atexit(void (*func)(void))
1160 return register_atexit(func, 0);
1163 int ast_register_cleanup(void (*func)(void))
1165 return register_atexit(func, 1);
1168 void ast_unregister_atexit(void (*func)(void))
1170 AST_LIST_LOCK(&atexits);
1171 __ast_unregister_atexit(func);
1172 AST_LIST_UNLOCK(&atexits);
1175 /* Sending commands from consoles back to the daemon requires a terminating NULL */
1176 static int fdsend(int fd, const char *s)
1178 return write(fd, s, strlen(s) + 1);
1181 /* Sending messages from the daemon back to the display requires _excluding_ the terminating NULL */
1182 static int fdprint(int fd, const char *s)
1184 return write(fd, s, strlen(s));
1187 /*! \brief NULL handler so we can collect the child exit status */
1188 static void _null_sig_handler(int sig)
1192 static struct sigaction null_sig_handler = {
1193 .sa_handler = _null_sig_handler,
1194 .sa_flags = SA_RESTART,
1197 static struct sigaction ignore_sig_handler = {
1198 .sa_handler = SIG_IGN,
1201 AST_MUTEX_DEFINE_STATIC(safe_system_lock);
1202 /*! \brief Keep track of how many threads are currently trying to wait*() on
1205 static unsigned int safe_system_level = 0;
1206 static struct sigaction safe_system_prev_handler;
1208 void ast_replace_sigchld(void)
1212 ast_mutex_lock(&safe_system_lock);
1213 level = safe_system_level++;
1215 /* only replace the handler if it has not already been done */
1217 sigaction(SIGCHLD, &null_sig_handler, &safe_system_prev_handler);
1220 ast_mutex_unlock(&safe_system_lock);
1223 void ast_unreplace_sigchld(void)
1227 ast_mutex_lock(&safe_system_lock);
1228 level = --safe_system_level;
1230 /* only restore the handler if we are the last one */
1232 sigaction(SIGCHLD, &safe_system_prev_handler, NULL);
1235 ast_mutex_unlock(&safe_system_lock);
1238 int ast_safe_system(const char *s)
1244 #if defined(HAVE_WORKING_FORK) || defined(HAVE_WORKING_VFORK)
1245 ast_replace_sigchld();
1247 #ifdef HAVE_WORKING_FORK
1255 cap_t cap = cap_from_text("cap_net_admin-eip");
1257 if (cap_set_proc(cap)) {
1258 /* Careful with order! Logging cannot happen after we close FDs */
1259 ast_log(LOG_WARNING, "Unable to remove capabilities.\n");
1263 #ifdef HAVE_WORKING_FORK
1264 if (ast_opt_high_priority)
1265 ast_set_priority(0);
1266 /* Close file descriptors and launch system command */
1267 ast_close_fds_above_n(STDERR_FILENO);
1269 execl("/bin/sh", "/bin/sh", "-c", s, (char *) NULL);
1271 } else if (pid > 0) {
1273 res = waitpid(pid, &status, 0);
1275 res = WIFEXITED(status) ? WEXITSTATUS(status) : -1;
1277 } else if (errno != EINTR)
1281 ast_log(LOG_WARNING, "Fork failed: %s\n", strerror(errno));
1285 ast_unreplace_sigchld();
1286 #else /* !defined(HAVE_WORKING_FORK) && !defined(HAVE_WORKING_VFORK) */
1294 * \brief enable or disable a logging level to a specified console
1296 void ast_console_toggle_loglevel(int fd, int level, int state)
1300 if (level >= NUMLOGLEVELS) {
1301 level = NUMLOGLEVELS - 1;
1304 for (x = 0;x < AST_MAX_CONNECTS; x++) {
1305 if (fd == consoles[x].fd) {
1307 * Since the logging occurs when levels are false, set to
1308 * flipped iinput because this function accepts 0 as off and 1 as on
1310 consoles[x].levels[level] = state ? 0 : 1;
1317 * \brief mute or unmute a console from logging
1319 void ast_console_toggle_mute(int fd, int silent)
1322 for (x = 0;x < AST_MAX_CONNECTS; x++) {
1323 if (fd == consoles[x].fd) {
1324 if (consoles[x].mute) {
1325 consoles[x].mute = 0;
1327 ast_cli(fd, "Console is not muted anymore.\n");
1329 consoles[x].mute = 1;
1331 ast_cli(fd, "Console is muted.\n");
1336 ast_cli(fd, "Couldn't find remote console.\n");
1340 * \brief log the string to all attached network console clients
1342 static void ast_network_puts_mutable(const char *string, int level)
1346 for (x = 0; x < AST_MAX_CONNECTS; ++x) {
1347 if (consoles[x].fd < 0
1349 || consoles[x].levels[level]) {
1352 fdprint(consoles[x].p[1], string);
1357 * \brief log the string to the root console, and all attached
1358 * network console clients
1360 void ast_console_puts_mutable(const char *string, int level)
1362 /* Send to the root console */
1363 fputs(string, stdout);
1366 /* Send to any network console clients */
1367 ast_network_puts_mutable(string, level);
1371 * \brief write the string to all attached console clients
1373 static void ast_network_puts(const char *string)
1377 for (x = 0; x < AST_MAX_CONNECTS; ++x) {
1378 if (consoles[x].fd < 0) {
1381 fdprint(consoles[x].p[1], string);
1386 * \brief write the string to the root console, and all attached
1387 * network console clients
1389 void ast_console_puts(const char *string)
1391 /* Send to the root console */
1392 fputs(string, stdout);
1395 /* Send to any network console clients */
1396 ast_network_puts(string);
1399 static void network_verboser(const char *string)
1404 /* Send to any network console clients if client verbocity allows. */
1405 verb_level = VERBOSE_MAGIC2LEVEL(string);
1406 for (x = 0; x < AST_MAX_CONNECTS; ++x) {
1407 if (consoles[x].fd < 0
1409 || consoles[x].levels[__LOG_VERBOSE]
1410 || consoles[x].option_verbose < verb_level) {
1413 fdprint(consoles[x].p[1], string);
1417 static pthread_t lthread;
1420 * \brief read() function supporting the reception of user credentials.
1422 * \param fd Socket file descriptor.
1423 * \param buffer Receive buffer.
1424 * \param size 'buffer' size.
1425 * \param con Console structure to set received credentials
1426 * \retval -1 on error
1427 * \retval the number of bytes received on success.
1429 static int read_credentials(int fd, char *buffer, size_t size, struct console *con)
1431 #if defined(SO_PEERCRED)
1432 #ifdef HAVE_STRUCT_SOCKPEERCRED_UID
1433 #define HAVE_STRUCT_UCRED_UID
1434 struct sockpeercred cred;
1438 socklen_t len = sizeof(cred);
1440 #if defined(HAVE_GETPEEREID)
1448 result = read(fd, buffer, size);
1453 #if defined(SO_PEERCRED) && (defined(HAVE_STRUCT_UCRED_UID) || defined(HAVE_STRUCT_UCRED_CR_UID))
1454 if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &cred, &len)) {
1457 #if defined(HAVE_STRUCT_UCRED_UID)
1460 #else /* defined(HAVE_STRUCT_UCRED_CR_UID) */
1463 #endif /* defined(HAVE_STRUCT_UCRED_UID) */
1465 #elif defined(HAVE_GETPEEREID)
1466 if (getpeereid(fd, &uid, &gid)) {
1478 /* This is the thread running the remote console on the main process. */
1479 static void *netconsole(void *vconsole)
1481 struct console *con = vconsole;
1482 char hostname[MAXHOSTNAMELEN] = "";
1485 const char * const end_buf = inbuf + sizeof(inbuf);
1486 char *start_read = inbuf;
1488 struct pollfd fds[2];
1490 if (gethostname(hostname, sizeof(hostname)-1))
1491 ast_copy_string(hostname, "<Unknown>", sizeof(hostname));
1492 snprintf(outbuf, sizeof(outbuf), "%s/%ld/%s\n", hostname, (long)ast_mainpid, ast_get_version());
1493 fdprint(con->fd, outbuf);
1494 ast_verb_console_register(&con->option_verbose);
1496 fds[0].fd = con->fd;
1497 fds[0].events = POLLIN;
1499 fds[1].fd = con->p[0];
1500 fds[1].events = POLLIN;
1503 res = ast_poll(fds, 2, -1);
1506 ast_log(LOG_WARNING, "poll returned < 0: %s\n", strerror(errno));
1509 if (fds[0].revents) {
1510 int cmds_read, bytes_read;
1511 if ((bytes_read = read_credentials(con->fd, start_read, end_buf - start_read, con)) < 1) {
1514 /* XXX This will only work if it is the first command, and I'm not sure fixing it is worth the effort. */
1515 if (strncmp(inbuf, "cli quit after ", 15) == 0) {
1516 ast_cli_command_multiple_full(con->uid, con->gid, con->fd, bytes_read - 15, inbuf + 15);
1519 /* ast_cli_command_multiple_full will only process individual commands terminated by a
1520 * NULL and not trailing partial commands. */
1521 if (!(cmds_read = ast_cli_command_multiple_full(con->uid, con->gid, con->fd, bytes_read + start_read - inbuf, inbuf))) {
1522 /* No commands were read. We either have a short read on the first command
1523 * with space left, or a command that is too long */
1524 if (start_read + bytes_read < end_buf) {
1525 start_read += bytes_read;
1527 ast_log(LOG_ERROR, "Command too long! Skipping\n");
1532 if (start_read[bytes_read - 1] == '\0') {
1533 /* The read ended on a command boundary, start reading again at the head of inbuf */
1537 /* If we get this far, we have left over characters that have not been processed.
1538 * Advance to the character after the last command read by ast_cli_command_multiple_full.
1539 * We are guaranteed to have at least cmds_read NULLs */
1540 while (cmds_read-- && (start_read = strchr(start_read, '\0'))) {
1543 memmove(inbuf, start_read, end_buf - start_read);
1544 start_read = end_buf - start_read + inbuf;
1546 if (fds[1].revents) {
1547 res = read_credentials(con->p[0], outbuf, sizeof(outbuf), con);
1549 ast_log(LOG_ERROR, "read returned %d\n", res);
1552 res = write(con->fd, outbuf, res);
1557 ast_verb_console_unregister();
1558 if (!ast_opt_hide_connect) {
1559 ast_verb(3, "Remote UNIX connection disconnected\n");
1569 static void *listener(void *unused)
1571 struct sockaddr_un sunaddr;
1576 struct pollfd fds[1];
1580 fds[0].fd = ast_socket;
1581 fds[0].events = POLLIN;
1582 s = ast_poll(fds, 1, -1);
1583 pthread_testcancel();
1586 ast_log(LOG_WARNING, "poll returned error: %s\n", strerror(errno));
1589 len = sizeof(sunaddr);
1590 s = accept(ast_socket, (struct sockaddr *)&sunaddr, &len);
1593 ast_log(LOG_WARNING, "Accept returned %d: %s\n", s, strerror(errno));
1595 #if !defined(SO_PASSCRED)
1599 /* turn on socket credentials passing. */
1600 if (setsockopt(s, SOL_SOCKET, SO_PASSCRED, &sckopt, sizeof(sckopt)) < 0) {
1601 ast_log(LOG_WARNING, "Unable to turn on socket credentials passing\n");
1604 for (x = 0; x < AST_MAX_CONNECTS; x++) {
1605 if (consoles[x].fd >= 0) {
1608 if (socketpair(AF_LOCAL, SOCK_STREAM, 0, consoles[x].p)) {
1609 ast_log(LOG_ERROR, "Unable to create pipe: %s\n", strerror(errno));
1610 fdprint(s, "Server failed to create pipe\n");
1614 flags = fcntl(consoles[x].p[1], F_GETFL);
1615 fcntl(consoles[x].p[1], F_SETFL, flags | O_NONBLOCK);
1616 consoles[x].mute = 1; /* Default is muted, we will un-mute if necessary */
1617 /* Default uid and gid to -2, so then in cli.c/cli_has_permissions() we will be able
1618 to know if the user didn't send the credentials. */
1619 consoles[x].uid = -2;
1620 consoles[x].gid = -2;
1621 /* Server default of remote console verbosity level is OFF. */
1622 consoles[x].option_verbose = 0;
1624 if (ast_pthread_create_detached_background(&consoles[x].t, NULL, netconsole, &consoles[x])) {
1625 consoles[x].fd = -1;
1626 ast_log(LOG_ERROR, "Unable to spawn thread to handle connection: %s\n", strerror(errno));
1627 close(consoles[x].p[0]);
1628 close(consoles[x].p[1]);
1629 fdprint(s, "Server failed to spawn thread\n");
1634 if (x >= AST_MAX_CONNECTS) {
1635 fdprint(s, "No more connections allowed\n");
1636 ast_log(LOG_WARNING, "No more connections allowed\n");
1638 } else if ((consoles[x].fd > -1) && (!ast_opt_hide_connect)) {
1639 ast_verb(3, "Remote UNIX connection\n");
1647 static int ast_makesocket(void)
1649 struct sockaddr_un sunaddr;
1655 for (x = 0; x < AST_MAX_CONNECTS; x++)
1656 consoles[x].fd = -1;
1657 unlink(ast_config_AST_SOCKET);
1658 ast_socket = socket(PF_LOCAL, SOCK_STREAM, 0);
1659 if (ast_socket < 0) {
1660 ast_log(LOG_WARNING, "Unable to create control socket: %s\n", strerror(errno));
1663 memset(&sunaddr, 0, sizeof(sunaddr));
1664 sunaddr.sun_family = AF_LOCAL;
1665 ast_copy_string(sunaddr.sun_path, ast_config_AST_SOCKET, sizeof(sunaddr.sun_path));
1666 res = bind(ast_socket, (struct sockaddr *)&sunaddr, sizeof(sunaddr));
1668 ast_log(LOG_WARNING, "Unable to bind socket to %s: %s\n", ast_config_AST_SOCKET, strerror(errno));
1673 res = listen(ast_socket, 2);
1675 ast_log(LOG_WARNING, "Unable to listen on socket %s: %s\n", ast_config_AST_SOCKET, strerror(errno));
1680 if (ast_register_verbose(network_verboser)) {
1681 ast_log(LOG_WARNING, "Unable to register network verboser?\n");
1684 if (ast_pthread_create_background(<hread, NULL, listener, NULL)) {
1685 ast_log(LOG_WARNING, "Unable to create listener thread.\n");
1690 if (!ast_strlen_zero(ast_config_AST_CTL_OWNER)) {
1692 if ((pw = getpwnam(ast_config_AST_CTL_OWNER)) == NULL)
1693 ast_log(LOG_WARNING, "Unable to find uid of user %s\n", ast_config_AST_CTL_OWNER);
1698 if (!ast_strlen_zero(ast_config_AST_CTL_GROUP)) {
1700 if ((grp = getgrnam(ast_config_AST_CTL_GROUP)) == NULL)
1701 ast_log(LOG_WARNING, "Unable to find gid of group %s\n", ast_config_AST_CTL_GROUP);
1706 if (chown(ast_config_AST_SOCKET, uid, gid) < 0)
1707 ast_log(LOG_WARNING, "Unable to change ownership of %s: %s\n", ast_config_AST_SOCKET, strerror(errno));
1709 if (!ast_strlen_zero(ast_config_AST_CTL_PERMISSIONS)) {
1712 sscanf(ast_config_AST_CTL_PERMISSIONS, "%30o", &p1);
1714 if ((chmod(ast_config_AST_SOCKET, p)) < 0)
1715 ast_log(LOG_WARNING, "Unable to change file permissions of %s: %s\n", ast_config_AST_SOCKET, strerror(errno));
1721 static int ast_tryconnect(void)
1723 struct sockaddr_un sunaddr;
1725 ast_consock = socket(PF_LOCAL, SOCK_STREAM, 0);
1726 if (ast_consock < 0) {
1727 fprintf(stderr, "Unable to create socket: %s\n", strerror(errno));
1730 memset(&sunaddr, 0, sizeof(sunaddr));
1731 sunaddr.sun_family = AF_LOCAL;
1732 ast_copy_string(sunaddr.sun_path, ast_config_AST_SOCKET, sizeof(sunaddr.sun_path));
1733 res = connect(ast_consock, (struct sockaddr *)&sunaddr, sizeof(sunaddr));
1742 /*! \brief Urgent handler
1744 * Called by soft_hangup to interrupt the poll, read, or other
1745 * system call. We don't actually need to do anything though.
1746 * Remember: Cannot EVER ast_log from within a signal handler
1748 static void _urg_handler(int num)
1753 static struct sigaction urg_handler = {
1754 .sa_handler = _urg_handler,
1755 .sa_flags = SA_RESTART,
1758 static void _hup_handler(int num)
1760 int a = 0, save_errno = errno;
1761 printf("Received HUP signal -- Reloading configs\n");
1763 execvp(_argv[0], _argv);
1764 sig_flags.need_reload = 1;
1765 if (sig_alert_pipe[1] != -1) {
1766 if (write(sig_alert_pipe[1], &a, sizeof(a)) < 0) {
1767 fprintf(stderr, "hup_handler: write() failed: %s\n", strerror(errno));
1773 static struct sigaction hup_handler = {
1774 .sa_handler = _hup_handler,
1775 .sa_flags = SA_RESTART,
1778 static void _child_handler(int sig)
1780 /* Must not ever ast_log or ast_verbose within signal handler */
1781 int n, status, save_errno = errno;
1784 * Reap all dead children -- not just one
1786 for (n = 0; waitpid(-1, &status, WNOHANG) > 0; n++)
1788 if (n == 0 && option_debug)
1789 printf("Huh? Child handler, but nobody there?\n");
1793 static struct sigaction child_handler = {
1794 .sa_handler = _child_handler,
1795 .sa_flags = SA_RESTART,
1798 /*! \brief Set maximum open files */
1799 static void set_ulimit(int value)
1801 struct rlimit l = {0, 0};
1804 ast_log(LOG_WARNING, "Unable to change max files open to invalid value %i\n",value);
1811 if (setrlimit(RLIMIT_NOFILE, &l)) {
1812 ast_log(LOG_WARNING, "Unable to disable core size resource limit: %s\n",strerror(errno));
1816 ast_log(LOG_NOTICE, "Setting max files open to %d\n",value);
1821 /*! \brief Set an X-term or screen title */
1822 static void set_title(char *text)
1824 if (getenv("TERM") && strstr(getenv("TERM"), "xterm"))
1825 fprintf(stdout, "\033]2;%s\007", text);
1828 static void set_icon(char *text)
1830 if (getenv("TERM") && strstr(getenv("TERM"), "xterm"))
1831 fprintf(stdout, "\033]1;%s\007", text);
1834 /*! \brief We set ourselves to a high priority, that we might pre-empt
1835 * everything else. If your PBX has heavy activity on it, this is a
1838 int ast_set_priority(int pri)
1840 struct sched_param sched;
1841 memset(&sched, 0, sizeof(sched));
1844 sched.sched_priority = 10;
1845 if (sched_setscheduler(0, SCHED_RR, &sched)) {
1846 ast_log(LOG_WARNING, "Unable to set high priority\n");
1849 ast_verb(1, "Set to realtime thread\n");
1851 sched.sched_priority = 0;
1852 /* According to the manpage, these parameters can never fail. */
1853 sched_setscheduler(0, SCHED_OTHER, &sched);
1857 if (setpriority(PRIO_PROCESS, 0, -10) == -1) {
1858 ast_log(LOG_WARNING, "Unable to set high priority\n");
1861 ast_verb(1, "Set to high priority\n");
1863 /* According to the manpage, these parameters can never fail. */
1864 setpriority(PRIO_PROCESS, 0, 0);
1870 static int can_safely_quit(shutdown_nice_t niceness, int restart);
1871 static void really_quit(int num, shutdown_nice_t niceness, int restart);
1873 static void quit_handler(int num, shutdown_nice_t niceness, int restart)
1875 if (can_safely_quit(niceness, restart)) {
1876 really_quit(num, niceness, restart);
1877 /* No one gets here. */
1879 /* It wasn't our time. */
1882 static int can_safely_quit(shutdown_nice_t niceness, int restart)
1884 /* Check if someone else isn't already doing this. */
1885 ast_mutex_lock(&safe_system_lock);
1886 if (shuttingdown != NOT_SHUTTING_DOWN && niceness >= shuttingdown) {
1887 /* Already in progress and other request was less nice. */
1888 ast_mutex_unlock(&safe_system_lock);
1889 ast_verbose("Ignoring asterisk %s request, already in progress.\n", restart ? "restart" : "shutdown");
1892 shuttingdown = niceness;
1893 ast_mutex_unlock(&safe_system_lock);
1895 /* Try to get as many CDRs as possible submitted to the backend engines
1896 * (if in batch mode). really_quit happens to call it again when running
1897 * the atexit handlers, otherwise this would be a bit early. */
1898 ast_cdr_engine_term();
1900 /* Shutdown the message queue for the technology agnostic message channel.
1901 * This has to occur before we pause shutdown pending ast_undestroyed_channels. */
1904 if (niceness == SHUTDOWN_NORMAL) {
1906 /* Begin shutdown routine, hanging up active channels */
1907 ast_begin_shutdown(1);
1908 if (ast_opt_console) {
1909 ast_verb(0, "Beginning asterisk %s....\n", restart ? "restart" : "shutdown");
1914 /* Wait up to 15 seconds for all channels to go away */
1915 if ((e - s) > 15 || !ast_undestroyed_channels() || shuttingdown != niceness) {
1918 /* Sleep 1/10 of a second */
1921 } else if (niceness >= SHUTDOWN_NICE) {
1922 if (niceness != SHUTDOWN_REALLY_NICE) {
1923 ast_begin_shutdown(0);
1925 if (ast_opt_console) {
1926 ast_verb(0, "Waiting for inactivity to perform %s...\n", restart ? "restart" : "halt");
1929 if (!ast_undestroyed_channels() || shuttingdown != niceness) {
1936 /* Re-acquire lock and check if someone changed the niceness, in which
1937 * case someone else has taken over the shutdown.
1939 ast_mutex_lock(&safe_system_lock);
1940 if (shuttingdown != niceness) {
1941 if (shuttingdown == NOT_SHUTTING_DOWN && ast_opt_console) {
1942 ast_verb(0, "Asterisk %s cancelled.\n", restart ? "restart" : "shutdown");
1944 ast_mutex_unlock(&safe_system_lock);
1947 shuttingdown = SHUTTING_DOWN;
1948 ast_mutex_unlock(&safe_system_lock);
1953 /*! Called when exiting is certain. */
1954 static void really_quit(int num, shutdown_nice_t niceness, int restart)
1956 int active_channels;
1957 struct ast_json *json_object = NULL;
1958 int run_cleanups = niceness >= SHUTDOWN_NICE;
1961 ast_module_shutdown();
1964 if (ast_opt_console || (ast_opt_remote && !ast_opt_exec)) {
1965 char filename[80] = "";
1966 if (getenv("HOME")) {
1967 snprintf(filename, sizeof(filename), "%s/.asterisk_history", getenv("HOME"));
1969 if (!ast_strlen_zero(filename)) {
1970 ast_el_write_history(filename);
1972 if (consolethread == AST_PTHREADT_NULL || consolethread == pthread_self()) {
1973 /* Only end if we are the consolethread, otherwise there's a race with that thread. */
1977 if (el_hist != NULL) {
1978 history_end(el_hist);
1980 } else if (mon_sig_flags == pthread_self()) {
1981 if (consolethread != AST_PTHREADT_NULL) {
1982 pthread_kill(consolethread, SIGURG);
1986 active_channels = ast_active_channels();
1987 /* Don't publish messages if we're a remote console - we won't have all of the Stasis
1988 * topics or message types
1990 if (!ast_opt_remote) {
1991 json_object = ast_json_pack("{s: s, s: s}",
1992 "Shutdown", active_channels ? "Uncleanly" : "Cleanly",
1993 "Restart", restart ? "True" : "False");
1994 ast_manager_publish_event("Shutdown", EVENT_FLAG_SYSTEM, json_object);
1995 ast_json_unref(json_object);
1998 ast_verb(0, "Asterisk %s ending (%d).\n",
1999 active_channels ? "uncleanly" : "cleanly", num);
2001 ast_verb(0, "Executing last minute cleanups\n");
2002 ast_run_atexits(run_cleanups);
2004 ast_debug(1, "Asterisk ending (%d).\n", num);
2005 if (ast_socket > -1) {
2006 pthread_cancel(lthread);
2009 unlink(ast_config_AST_SOCKET);
2010 pthread_kill(lthread, SIGURG);
2011 pthread_join(lthread, NULL);
2013 if (ast_consock > -1)
2015 if (!ast_opt_remote)
2016 unlink(ast_config_AST_PID);
2017 if (sig_alert_pipe[0])
2018 close(sig_alert_pipe[0]);
2019 if (sig_alert_pipe[1])
2020 close(sig_alert_pipe[1]);
2021 printf("%s", term_quit());
2024 ast_verb(0, "Preparing for Asterisk restart...\n");
2025 /* Mark all FD's for closing on exec */
2026 for (i = 3; i < 32768; i++) {
2027 fcntl(i, F_SETFD, FD_CLOEXEC);
2029 ast_verb(0, "Asterisk is now restarting...\n");
2036 /* If there is a consolethread running send it a SIGHUP
2037 so it can execvp, otherwise we can do it ourselves */
2038 if ((consolethread != AST_PTHREADT_NULL) && (consolethread != pthread_self())) {
2039 pthread_kill(consolethread, SIGHUP);
2040 /* Give the signal handler some time to complete */
2043 execvp(_argv[0], _argv);
2054 static void __quit_handler(int num)
2057 sig_flags.need_quit = 1;
2058 if (sig_alert_pipe[1] != -1) {
2059 if (write(sig_alert_pipe[1], &a, sizeof(a)) < 0) {
2060 fprintf(stderr, "quit_handler: write() failed: %s\n", strerror(errno));
2063 /* There is no need to restore the signal handler here, since the app
2064 * is going to exit */
2067 static void __remote_quit_handler(int num)
2069 sig_flags.need_quit = 1;
2072 static void set_header(char *outbuf, int maxout, char level)
2080 case 1: cmp = VERBOSE_PREFIX_1;
2082 case 2: cmp = VERBOSE_PREFIX_2;
2084 case 3: cmp = VERBOSE_PREFIX_3;
2086 default: cmp = VERBOSE_PREFIX_4;
2090 if (ast_opt_timestamp) {
2092 struct timeval now = ast_tvnow();
2093 ast_localtime(&now, &tm, NULL);
2094 ast_strftime(date, sizeof(date), ast_logger_get_dateformat(), &tm);
2097 snprintf(outbuf, maxout, "%s%s%s%s%s%s",
2098 ast_opt_timestamp ? "[" : "",
2099 ast_opt_timestamp ? date : "",
2100 ast_opt_timestamp ? "] " : "",
2101 cmp ? ast_term_color(COLOR_GRAY, 0) : "",
2103 cmp ? ast_term_reset() : "");
2106 struct console_state_data {
2107 char verbose_line_level;
2110 static int console_state_init(void *ptr)
2112 struct console_state_data *state = ptr;
2113 state->verbose_line_level = 0;
2117 AST_THREADSTORAGE_CUSTOM(console_state, console_state_init, ast_free_ptr);
2119 static int console_print(const char *s, int local)
2121 struct console_state_data *state =
2122 ast_threadstorage_get(&console_state, sizeof(*state));
2127 unsigned int newline;
2130 if (VERBOSE_HASMAGIC(s)) {
2132 /* always use the given line's level, otherwise
2133 we'll use the last line's level */
2134 state->verbose_line_level = VERBOSE_MAGIC2LEVEL(s);
2136 /* move past magic */
2139 set_header(prefix, sizeof(prefix), state->verbose_line_level);
2145 /* for a given line separate on verbose magic, newline, and eol */
2146 if ((s = strchr(c, '\n'))) {
2150 s = strchr(c, '\0');
2154 /* check if we should write this line after calculating begin/end
2155 so we process the case of a higher level line embedded within
2156 two lower level lines */
2157 if (state->verbose_line_level > option_verbose) {
2161 if (!ast_strlen_zero(prefix)) {
2162 fputs(prefix, stdout);
2166 if (fwrite(c, sizeof(char), num, stdout) < num) {
2171 /* if at least some info has been written
2172 we'll want to return true */
2178 /* if ending on a newline then reset last level to zero
2179 since what follows may be not be logging output */
2180 state->verbose_line_level = 0;
2190 static void console_verboser(const char *s)
2192 if (!console_print(s, 1)) {
2196 /* Wake up a poll()ing console */
2197 if (ast_opt_console && consolethread != AST_PTHREADT_NULL) {
2198 pthread_kill(consolethread, SIGURG);
2202 static int ast_all_zeros(char *s)
2212 /* This is the main console CLI command handler. Run by the main() thread. */
2213 static void consolehandler(char *s)
2215 printf("%s", term_end());
2218 /* Called when readline data is available */
2219 if (!ast_all_zeros(s))
2220 ast_el_add_history(s);
2221 /* The real handler for bang */
2224 ast_safe_system(s+1);
2226 ast_safe_system(getenv("SHELL") ? getenv("SHELL") : "/bin/sh");
2228 ast_cli_command(STDOUT_FILENO, s);
2231 static int remoteconsolehandler(char *s)
2235 /* Called when readline data is available */
2236 if (!ast_all_zeros(s))
2237 ast_el_add_history(s);
2239 while (isspace(*s)) {
2243 /* The real handler for bang */
2246 ast_safe_system(s+1);
2248 ast_safe_system(getenv("SHELL") ? getenv("SHELL") : "/bin/sh");
2250 } else if ((strncasecmp(s, "quit", 4) == 0 || strncasecmp(s, "exit", 4) == 0) &&
2251 (s[4] == '\0' || isspace(s[4]))) {
2252 quit_handler(0, SHUTDOWN_FAST, 0);
2255 char *shrunk = ast_strdupa(s);
2260 * Remove duplicate spaces from shrunk for matching purposes.
2262 * shrunk has at least one character in it to start with or we
2263 * couldn't get here.
2265 for (prev = shrunk, cur = shrunk + 1; *cur; ++cur) {
2266 if (*prev == ' ' && *cur == ' ') {
2267 /* Skip repeated space delimiter. */
2274 if (strncasecmp(shrunk, "core set verbose ", 17) == 0) {
2276 * We need to still set the rasterisk option_verbose in case we are
2277 * talking to an earlier version which doesn't prefilter verbose
2278 * levels. This is really a compromise as we should always take
2279 * whatever the server sends.
2282 if (!strncasecmp(shrunk + 17, "off", 3)) {
2283 ast_verb_console_set(0);
2289 if (strncasecmp(shrunk + 17, "atleast ", atleast)) {
2293 if (sscanf(shrunk + 17 + atleast, "%30d", &verbose_new) == 1) {
2294 if (!atleast || ast_verb_console_get() < verbose_new) {
2295 ast_verb_console_set(verbose_new);
2305 static char *handle_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2309 e->command = "core show version";
2311 "Usage: core show version\n"
2312 " Shows Asterisk version information.\n";
2319 return CLI_SHOWUSAGE;
2320 ast_cli(a->fd, "Asterisk %s built by %s @ %s on a %s running %s on %s\n",
2321 ast_get_version(), ast_build_user, ast_build_hostname,
2322 ast_build_machine, ast_build_os, ast_build_date);
2327 static int handle_quit(int fd, int argc, char *argv[])
2330 return RESULT_SHOWUSAGE;
2331 quit_handler(0, SHUTDOWN_NORMAL, 0);
2332 return RESULT_SUCCESS;
2336 static char *handle_stop_now(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2340 e->command = "core stop now";
2342 "Usage: core stop now\n"
2343 " Shuts down a running Asterisk immediately, hanging up all active calls .\n";
2349 if (a->argc != e->args)
2350 return CLI_SHOWUSAGE;
2351 quit_handler(0, SHUTDOWN_NORMAL, 0 /* not restart */);
2355 static char *handle_stop_gracefully(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2359 e->command = "core stop gracefully";
2361 "Usage: core stop gracefully\n"
2362 " Causes Asterisk to not accept new calls, and exit when all\n"
2363 " active calls have terminated normally.\n";
2369 if (a->argc != e->args)
2370 return CLI_SHOWUSAGE;
2371 quit_handler(0, SHUTDOWN_NICE, 0 /* no restart */);
2375 static char *handle_stop_when_convenient(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2379 e->command = "core stop when convenient";
2381 "Usage: core stop when convenient\n"
2382 " Causes Asterisk to perform a shutdown when all active calls have ended.\n";
2388 if (a->argc != e->args)
2389 return CLI_SHOWUSAGE;
2390 ast_cli(a->fd, "Waiting for inactivity to perform halt\n");
2391 quit_handler(0, SHUTDOWN_REALLY_NICE, 0 /* don't restart */);
2395 static char *handle_restart_now(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2399 e->command = "core restart now";
2401 "Usage: core restart now\n"
2402 " Causes Asterisk to hangup all calls and exec() itself performing a cold\n"
2409 if (a->argc != e->args)
2410 return CLI_SHOWUSAGE;
2411 quit_handler(0, SHUTDOWN_NORMAL, 1 /* restart */);
2415 static char *handle_restart_gracefully(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2419 e->command = "core restart gracefully";
2421 "Usage: core restart gracefully\n"
2422 " Causes Asterisk to stop accepting new calls and exec() itself performing a cold\n"
2423 " restart when all active calls have ended.\n";
2429 if (a->argc != e->args)
2430 return CLI_SHOWUSAGE;
2431 quit_handler(0, SHUTDOWN_NICE, 1 /* restart */);
2435 static char *handle_restart_when_convenient(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2439 e->command = "core restart when convenient";
2441 "Usage: core restart when convenient\n"
2442 " Causes Asterisk to perform a cold restart when all active calls have ended.\n";
2448 if (a->argc != e->args)
2449 return CLI_SHOWUSAGE;
2450 ast_cli(a->fd, "Waiting for inactivity to perform restart\n");
2451 quit_handler(0, SHUTDOWN_REALLY_NICE, 1 /* restart */);
2455 static char *handle_abort_shutdown(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2457 int aborting_shutdown = 0;
2461 e->command = "core abort shutdown";
2463 "Usage: core abort shutdown\n"
2464 " Causes Asterisk to abort an executing shutdown or restart, and resume normal\n"
2465 " call operations.\n";
2471 if (a->argc != e->args)
2472 return CLI_SHOWUSAGE;
2474 ast_mutex_lock(&safe_system_lock);
2475 if (shuttingdown >= SHUTDOWN_FAST) {
2476 aborting_shutdown = 1;
2477 shuttingdown = NOT_SHUTTING_DOWN;
2479 ast_mutex_unlock(&safe_system_lock);
2481 if (aborting_shutdown) {
2482 ast_cancel_shutdown();
2487 static char *handle_bang(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2493 "Usage: !<command>\n"
2494 " Executes a given shell command\n";
2502 static const char warranty_lines[] = {
2506 "BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY\n"
2507 "FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN\n"
2508 "OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES\n"
2509 "PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED\n"
2510 "OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\n"
2511 "MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS\n"
2512 "TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE\n"
2513 "PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,\n"
2514 "REPAIR OR CORRECTION.\n"
2516 "IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\n"
2517 "WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR\n"
2518 "REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,\n"
2519 "INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING\n"
2520 "OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED\n"
2521 "TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY\n"
2522 "YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER\n"
2523 "PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE\n"
2524 "POSSIBILITY OF SUCH DAMAGES.\n"
2527 static char *show_warranty(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2531 e->command = "core show warranty";
2533 "Usage: core show warranty\n"
2534 " Shows the warranty (if any) for this copy of Asterisk.\n";
2540 ast_cli(a->fd, "%s", warranty_lines);
2545 static const char license_lines[] = {
2547 "This program is free software; you can redistribute it and/or modify\n"
2548 "it under the terms of the GNU General Public License version 2 as\n"
2549 "published by the Free Software Foundation.\n"
2551 "This program also contains components licensed under other licenses.\n"
2554 "This program is distributed in the hope that it will be useful,\n"
2555 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
2556 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
2557 "GNU General Public License for more details.\n"
2559 "You should have received a copy of the GNU General Public License\n"
2560 "along with this program; if not, write to the Free Software\n"
2561 "Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\n"
2564 static char *show_license(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2568 e->command = "core show license";
2570 "Usage: core show license\n"
2571 " Shows the license(s) for this copy of Asterisk.\n";
2577 ast_cli(a->fd, "%s", license_lines);
2582 #define ASTERISK_PROMPT "*CLI> "
2585 * \brief Shutdown Asterisk CLI commands.
2587 * \note These CLI commands cannot be unregistered at shutdown
2588 * because one of them is likely the reason for the shutdown.
2589 * The CLI generates a warning if a command is in-use when it is
2592 static struct ast_cli_entry cli_asterisk_shutdown[] = {
2593 AST_CLI_DEFINE(handle_stop_now, "Shut down Asterisk immediately"),
2594 AST_CLI_DEFINE(handle_stop_gracefully, "Gracefully shut down Asterisk"),
2595 AST_CLI_DEFINE(handle_stop_when_convenient, "Shut down Asterisk at empty call volume"),
2596 AST_CLI_DEFINE(handle_restart_now, "Restart Asterisk immediately"),
2597 AST_CLI_DEFINE(handle_restart_gracefully, "Restart Asterisk gracefully"),
2598 AST_CLI_DEFINE(handle_restart_when_convenient, "Restart Asterisk at empty call volume"),
2601 static struct ast_cli_entry cli_asterisk[] = {
2602 AST_CLI_DEFINE(handle_abort_shutdown, "Cancel a running shutdown"),
2603 AST_CLI_DEFINE(show_warranty, "Show the warranty (if any) for this copy of Asterisk"),
2604 AST_CLI_DEFINE(show_license, "Show the license(s) for this copy of Asterisk"),
2605 AST_CLI_DEFINE(handle_version, "Display version info"),
2606 AST_CLI_DEFINE(handle_bang, "Execute a shell command"),
2607 #if !defined(LOW_MEMORY)
2608 AST_CLI_DEFINE(handle_show_version_files, "List versions of files used to build Asterisk"),
2609 AST_CLI_DEFINE(handle_show_threads, "Show running threads"),
2610 #if defined(HAVE_SYSINFO) || defined(HAVE_SYSCTL)
2611 AST_CLI_DEFINE(handle_show_sysinfo, "Show System Information"),
2613 AST_CLI_DEFINE(handle_show_profile, "Display profiling info"),
2614 AST_CLI_DEFINE(handle_show_settings, "Show some core settings"),
2615 AST_CLI_DEFINE(handle_clear_profile, "Clear profiling info"),
2616 #endif /* ! LOW_MEMORY */
2619 static void send_rasterisk_connect_commands(void)
2624 * Tell the server asterisk instance about the verbose level
2625 * initially desired.
2627 if (option_verbose) {
2628 snprintf(buf, sizeof(buf), "core set verbose atleast %d silent", option_verbose);
2629 fdsend(ast_consock, buf);
2633 snprintf(buf, sizeof(buf), "core set debug atleast %d", option_debug);
2634 fdsend(ast_consock, buf);
2637 if (!ast_opt_mute) {
2638 fdsend(ast_consock, "logger mute silent");
2640 printf("log and verbose output currently muted ('logger mute' to unmute)\n");
2644 static int ast_el_read_char(EditLine *editline, char *cp)
2648 struct pollfd fds[2];
2651 #define EL_BUF_SIZE 512
2652 char buf[EL_BUF_SIZE];
2656 fds[0].fd = ast_consock;
2657 fds[0].events = POLLIN;
2658 if (!ast_opt_exec) {
2659 fds[1].fd = STDIN_FILENO;
2660 fds[1].events = POLLIN;
2663 res = ast_poll(fds, max, -1);
2665 if (sig_flags.need_quit || sig_flags.need_quit_handler)
2669 fprintf(stderr, "poll failed: %s\n", strerror(errno));
2673 if (!ast_opt_exec && fds[1].revents) {
2674 num_read = read(STDIN_FILENO, cp, 1);
2681 if (fds[0].revents) {
2682 res = read(ast_consock, buf, sizeof(buf) - 1);
2683 /* if the remote side disappears exit */
2685 fprintf(stderr, "\nDisconnected from Asterisk server\n");
2686 if (!ast_opt_reconnect) {
2687 quit_handler(0, SHUTDOWN_FAST, 0);
2690 int reconnects_per_second = 20;
2691 fprintf(stderr, "Attempting to reconnect for 30 seconds\n");
2692 for (tries = 0; tries < 30 * reconnects_per_second; tries++) {
2693 if (ast_tryconnect()) {
2694 fprintf(stderr, "Reconnect succeeded after %.3f seconds\n", 1.0 / reconnects_per_second * tries);
2695 printf("%s", term_quit());
2697 send_rasterisk_connect_commands();
2700 usleep(1000000 / reconnects_per_second);
2702 if (tries >= 30 * reconnects_per_second) {
2703 fprintf(stderr, "Failed to reconnect for 30 seconds. Quitting.\n");
2704 quit_handler(0, SHUTDOWN_FAST, 0);
2712 /* Write over the CLI prompt */
2713 if (!ast_opt_exec && !lastpos) {
2714 if (write(STDOUT_FILENO, "\r
\e[0K", 5) < 0) {
2718 console_print(buf, 0);
2720 if ((res < EL_BUF_SIZE - 1) && ((buf[res-1] == '\n') || (buf[res-2] == '\n'))) {
2732 static struct ast_str *prompt = NULL;
2734 static char *cli_prompt(EditLine *editline)
2739 static int cli_prompt_changes = 0;
2743 if (prompt == NULL) {
2744 prompt = ast_str_create(100);
2745 } else if (!cli_prompt_changes) {
2746 return ast_str_buffer(prompt);
2748 ast_str_reset(prompt);
2751 if ((pfmt = getenv("ASTERISK_PROMPT"))) {
2753 struct timeval ts = ast_tvnow();
2754 while (*t != '\0') {
2756 char hostname[MAXHOSTNAMELEN] = "";
2758 struct ast_tm tm = { 0, };
2759 int fgcolor = COLOR_WHITE, bgcolor = COLOR_BLACK;
2763 case 'C': /* color */
2765 if (sscanf(t, "%30d;%30d%n", &fgcolor, &bgcolor, &i) == 2) {
2766 ast_term_color_code(&prompt, fgcolor, bgcolor);
2768 } else if (sscanf(t, "%30d%n", &fgcolor, &i) == 1) {
2769 ast_term_color_code(&prompt, fgcolor, 0);
2773 /* If the color has been reset correctly, then there's no need to reset it later */
2774 color_used = ((fgcolor == COLOR_WHITE) && (bgcolor == COLOR_BLACK)) ? 0 : 1;
2776 case 'd': /* date */
2777 if (ast_localtime(&ts, &tm, NULL)) {
2778 ast_strftime(tmp, sizeof(tmp), "%Y-%m-%d", &tm);
2779 ast_str_append(&prompt, 0, "%s", tmp);
2780 cli_prompt_changes++;
2783 case 'g': /* group */
2784 if ((gr = getgrgid(getgid()))) {
2785 ast_str_append(&prompt, 0, "%s", gr->gr_name);
2788 case 'h': /* hostname */
2789 if (!gethostname(hostname, sizeof(hostname) - 1)) {
2790 ast_str_append(&prompt, 0, "%s", hostname);
2792 ast_str_append(&prompt, 0, "%s", "localhost");
2795 case 'H': /* short hostname */
2796 if (!gethostname(hostname, sizeof(hostname) - 1)) {
2798 if ((dotptr = strchr(hostname, '.'))) {
2801 ast_str_append(&prompt, 0, "%s", hostname);
2803 ast_str_append(&prompt, 0, "%s", "localhost");
2806 #ifdef HAVE_GETLOADAVG
2807 case 'l': /* load avg */
2809 if (sscanf(t, "%30d", &which) == 1 && which > 0 && which <= 3) {
2811 getloadavg(list, 3);
2812 ast_str_append(&prompt, 0, "%.2f", list[which - 1]);
2813 cli_prompt_changes++;
2817 case 's': /* Asterisk system name (from asterisk.conf) */
2818 ast_str_append(&prompt, 0, "%s", ast_config_AST_SYSTEM_NAME);
2820 case 't': /* time */
2821 if (ast_localtime(&ts, &tm, NULL)) {
2822 ast_strftime(tmp, sizeof(tmp), "%H:%M:%S", &tm);
2823 ast_str_append(&prompt, 0, "%s", tmp);
2824 cli_prompt_changes++;
2827 case 'u': /* username */
2828 if ((pw = getpwuid(getuid()))) {
2829 ast_str_append(&prompt, 0, "%s", pw->pw_name);
2832 case '#': /* process console or remote? */
2833 ast_str_append(&prompt, 0, "%c", ast_opt_remote ? '>' : '#');
2835 case '%': /* literal % */
2836 ast_str_append(&prompt, 0, "%c", '%');
2838 case '\0': /* % is last character - prevent bug */
2843 ast_str_append(&prompt, 0, "%c", *t);
2848 /* Force colors back to normal at end */
2849 ast_term_color_code(&prompt, 0, 0);
2852 ast_str_set(&prompt, 0, "%s%s",
2853 remotehostname ? remotehostname : "",
2857 return ast_str_buffer(prompt);
2860 static void destroy_match_list(char **match_list, int matches)
2865 for (idx = 0; idx < matches; ++idx) {
2866 ast_free(match_list[idx]);
2868 ast_free(match_list);
2872 static char **ast_el_strtoarr(char *buf)
2875 char **match_list = NULL;
2877 size_t match_list_len = 1;
2880 while ((retstr = strsep(&buf, " "))) {
2881 if (!strcmp(retstr, AST_CLI_COMPLETE_EOF)) {
2884 if (matches + 1 >= match_list_len) {
2885 match_list_len <<= 1;
2886 new_list = ast_realloc(match_list, match_list_len * sizeof(char *));
2888 destroy_match_list(match_list, matches);
2891 match_list = new_list;
2894 retstr = ast_strdup(retstr);
2896 destroy_match_list(match_list, matches);
2899 match_list[matches++] = retstr;
2906 if (matches >= match_list_len) {
2907 new_list = ast_realloc(match_list, (match_list_len + 1) * sizeof(char *));
2909 destroy_match_list(match_list, matches);
2912 match_list = new_list;
2915 match_list[matches] = NULL;
2920 static int ast_el_sort_compare(const void *i1, const void *i2)
2924 s1 = ((char **)i1)[0];
2925 s2 = ((char **)i2)[0];
2927 return strcasecmp(s1, s2);
2930 static int ast_cli_display_match_list(char **matches, int len, int max)
2932 int i, idx, limit, count;
2933 int screenwidth = 0;
2934 int numoutput = 0, numoutputline = 0;
2936 screenwidth = ast_get_termcols(STDOUT_FILENO);
2938 /* find out how many entries can be put on one line, with two spaces between strings */
2939 limit = screenwidth / (max + 2);
2943 /* how many lines of output */
2944 count = len / limit;
2945 if (count * limit < len)
2950 qsort(&matches[0], (size_t)(len), sizeof(char *), ast_el_sort_compare);
2952 for (; count > 0; count--) {
2954 for (i = 0; i < limit && matches[idx]; i++, idx++) {
2956 /* Don't print dupes */
2957 if ( (matches[idx+1] != NULL && strcmp(matches[idx], matches[idx+1]) == 0 ) ) {
2959 ast_free(matches[idx]);
2960 matches[idx] = NULL;
2966 fprintf(stdout, "%-*s ", max, matches[idx]);
2967 ast_free(matches[idx]);
2968 matches[idx] = NULL;
2970 if (numoutputline > 0)
2971 fprintf(stdout, "\n");
2978 static char *cli_complete(EditLine *editline, int ch)
2984 int retval = CC_ERROR;
2985 char buf[2048], savechr;
2988 LineInfo *lf = (LineInfo *)el_line(editline);
2990 savechr = *(char *)lf->cursor;
2991 *(char *)lf->cursor = '\0';
2992 ptr = (char *)lf->cursor;
2994 while (ptr > lf->buffer) {
2995 if (isspace(*ptr)) {
3003 len = lf->cursor - ptr;
3005 if (ast_opt_remote) {
3006 snprintf(buf, sizeof(buf), "_COMMAND NUMMATCHES \"%s\" \"%s\"", lf->buffer, ptr);
3007 fdsend(ast_consock, buf);
3008 if ((res = read(ast_consock, buf, sizeof(buf) - 1)) < 0) {
3009 return (char*)(CC_ERROR);
3012 nummatches = atoi(buf);
3014 if (nummatches > 0) {
3017 int mlen = 0, maxmbuf = 2048;
3019 /* Start with a 2048 byte buffer */
3020 if (!(mbuf = ast_malloc(maxmbuf))) {
3021 *((char *) lf->cursor) = savechr;
3022 return (char *)(CC_ERROR);
3024 snprintf(buf, sizeof(buf), "_COMMAND MATCHESARRAY \"%s\" \"%s\"", lf->buffer, ptr);
3025 fdsend(ast_consock, buf);
3028 while (!strstr(mbuf, AST_CLI_COMPLETE_EOF) && res != -1) {
3029 if (mlen + 1024 > maxmbuf) {
3030 /* Every step increment buffer 1024 bytes */
3032 new_mbuf = ast_realloc(mbuf, maxmbuf);
3035 *((char *) lf->cursor) = savechr;
3036 return (char *)(CC_ERROR);
3040 /* Only read 1024 bytes at a time */
3041 res = read(ast_consock, mbuf + mlen, 1024);
3047 matches = ast_el_strtoarr(mbuf);
3050 matches = (char **) NULL;
3052 char **p, *oldbuf=NULL;
3054 matches = ast_cli_completion_matches((char *)lf->buffer,ptr);
3055 for (p = matches; p && *p; p++) {
3056 if (!oldbuf || strcmp(*p,oldbuf))
3064 int matches_num, maxlen, match_len;
3066 if (matches[0][0] != '\0') {
3067 el_deletestr(editline, (int) len);
3068 el_insertstr(editline, matches[0]);
3069 retval = CC_REFRESH;
3072 if (nummatches == 1) {
3073 /* Found an exact match */
3074 el_insertstr(editline, " ");
3075 retval = CC_REFRESH;
3077 /* Must be more than one match */
3078 for (i = 1, maxlen = 0; matches[i]; i++) {
3079 match_len = strlen(matches[i]);
3080 if (match_len > maxlen)
3083 matches_num = i - 1;
3084 if (matches_num >1) {
3085 fprintf(stdout, "\n");
3086 ast_cli_display_match_list(matches, nummatches, maxlen);
3087 retval = CC_REDISPLAY;
3089 el_insertstr(editline," ");
3090 retval = CC_REFRESH;
3093 for (i = 0; matches[i]; i++)
3094 ast_free(matches[i]);
3098 *((char *) lf->cursor) = savechr;
3100 return (char *)(long)retval;
3103 static int ast_el_initialize(void)
3106 char *editor, *editrc = getenv("EDITRC");
3108 if (!(editor = getenv("AST_EDITMODE"))) {
3109 if (!(editor = getenv("AST_EDITOR"))) {
3116 if (el_hist != NULL)
3117 history_end(el_hist);
3119 el = el_init("asterisk", stdin, stdout, stderr);
3120 el_set(el, EL_PROMPT, cli_prompt);
3122 el_set(el, EL_EDITMODE, 1);
3123 el_set(el, EL_EDITOR, editor);
3124 el_hist = history_init();
3125 if (!el || !el_hist)
3128 /* setup history with 100 entries */
3129 history(el_hist, &ev, H_SETSIZE, 100);
3131 el_set(el, EL_HIST, history, el_hist);
3133 el_set(el, EL_ADDFN, "ed-complete", "Complete argument", cli_complete);
3134 /* Bind <tab> to command completion */
3135 el_set(el, EL_BIND, "^I", "ed-complete", NULL);
3136 /* Bind ? to command completion */
3137 el_set(el, EL_BIND, "?", "ed-complete", NULL);
3138 /* Bind ^D to redisplay */
3139 el_set(el, EL_BIND, "^D", "ed-redisplay", NULL);
3140 /* Bind Delete to delete char left */
3141 el_set(el, EL_BIND, "\\e[3~", "ed-delete-next-char", NULL);
3142 /* Bind Home and End to move to line start and end */
3143 el_set(el, EL_BIND, "\\e[1~", "ed-move-to-beg", NULL);
3144 el_set(el, EL_BIND, "\\e[4~", "ed-move-to-end", NULL);
3145 /* Bind C-left and C-right to move by word (not all terminals) */
3146 el_set(el, EL_BIND, "\\eOC", "vi-next-word", NULL);
3147 el_set(el, EL_BIND, "\\eOD", "vi-prev-word", NULL);
3150 el_source(el, editrc);
3156 #define MAX_HISTORY_COMMAND_LENGTH 256
3158 static int ast_el_add_history(char *buf)
3163 if (el_hist == NULL || el == NULL) {
3164 ast_el_initialize();
3166 if (strlen(buf) > (MAX_HISTORY_COMMAND_LENGTH - 1)) {
3170 stripped_buf = ast_strip(ast_strdupa(buf));
3172 /* HISTCONTROL=ignoredups */
3173 if (!history(el_hist, &ev, H_FIRST) && strcmp(ev.str, stripped_buf) == 0) {
3177 return history(el_hist, &ev, H_ENTER, stripped_buf);
3180 static int ast_el_write_history(char *filename)
3184 if (el_hist == NULL || el == NULL)
3185 ast_el_initialize();
3187 return (history(el_hist, &ev, H_SAVE, filename));
3190 static int ast_el_read_history(char *filename)
3194 if (el_hist == NULL || el == NULL) {
3195 ast_el_initialize();
3198 return history(el_hist, &ev, H_LOAD, filename);
3201 static void ast_remotecontrol(char *data)
3205 char filename[80] = "";
3210 char *stringp = NULL;
3215 memset(&sig_flags, 0, sizeof(sig_flags));
3216 signal(SIGINT, __remote_quit_handler);
3217 signal(SIGTERM, __remote_quit_handler);
3218 signal(SIGHUP, __remote_quit_handler);
3220 if (read(ast_consock, buf, sizeof(buf)) < 0) {
3221 ast_log(LOG_ERROR, "read() failed: %s\n", strerror(errno));
3225 char prefix[] = "cli quit after ";
3226 char *tmp = ast_alloca(strlen(data) + strlen(prefix) + 1);
3227 sprintf(tmp, "%s%s", prefix, data);
3228 if (write(ast_consock, tmp, strlen(tmp) + 1) < 0) {
3229 ast_log(LOG_ERROR, "write() failed: %s\n", strerror(errno));
3230 if (sig_flags.need_quit || sig_flags.need_quit_handler) {
3236 hostname = strsep(&stringp, "/");
3237 cpid = strsep(&stringp, "/");
3238 version = strsep(&stringp, "\n");
3240 version = "<Version Unknown>";
3242 strsep(&stringp, ".");
3248 send_rasterisk_connect_commands();
3251 if (ast_opt_exec && data) { /* hack to print output then exit if asterisk -rx is used */
3252 int linefull = 1, prev_linefull = 1, prev_line_verbose = 0;
3254 fds.fd = ast_consock;
3255 fds.events = POLLIN;
3258 while (ast_poll(&fds, 1, 60000) > 0) {
3259 char buffer[512] = "", *curline = buffer, *nextline;
3260 int not_written = 1;
3262 if (sig_flags.need_quit || sig_flags.need_quit_handler) {
3266 if (read(ast_consock, buffer, sizeof(buffer) - 1) <= 0) {
3271 prev_linefull = linefull;
3272 if ((nextline = strchr(curline, '\n'))) {
3277 nextline = strchr(curline, '\0');
3280 /* Skip verbose lines */
3281 /* Prev line full? | Line is verbose | Last line verbose? | Print
3282 * TRUE | TRUE* | TRUE | FALSE
3283 * TRUE | TRUE* | FALSE | FALSE
3284 * TRUE | FALSE* | TRUE | TRUE
3285 * TRUE | FALSE* | FALSE | TRUE
3286 * FALSE | TRUE | TRUE* | FALSE
3287 * FALSE | TRUE | FALSE* | TRUE
3288 * FALSE | FALSE | TRUE* | FALSE
3289 * FALSE | FALSE | FALSE* | TRUE
3291 if ((!prev_linefull && !prev_line_verbose) || (prev_linefull && *curline > 0)) {
3292 prev_line_verbose = 0;
3294 if (write(STDOUT_FILENO, curline, nextline - curline) < 0) {
3295 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
3298 prev_line_verbose = 1;
3301 } while (!ast_strlen_zero(curline));
3303 /* No non-verbose output in 60 seconds. */
3311 ast_verbose("Connected to Asterisk %s currently running on %s (pid = %d)\n", version, hostname, pid);
3312 remotehostname = hostname;
3314 snprintf(filename, sizeof(filename), "%s/.asterisk_history", getenv("HOME"));
3315 if (el_hist == NULL || el == NULL)
3316 ast_el_initialize();
3318 el_set(el, EL_GETCFN, ast_el_read_char);
3320 if (!ast_strlen_zero(filename))
3321 ast_el_read_history(filename);
3324 ebuf = (char *)el_gets(el, &num);
3326 if (sig_flags.need_quit || sig_flags.need_quit_handler) {
3330 if (!ebuf && write(1, "", 1) < 0)
3333 if (!ast_strlen_zero(ebuf)) {
3334 if (ebuf[strlen(ebuf)-1] == '\n')
3335 ebuf[strlen(ebuf)-1] = '\0';
3336 if (!remoteconsolehandler(ebuf)) {
3337 res = write(ast_consock, ebuf, strlen(ebuf) + 1);
3339 ast_log(LOG_WARNING, "Unable to write: %s\n", strerror(errno));
3345 printf("\nDisconnected from Asterisk server\n");
3348 static int show_version(void)
3350 printf("Asterisk %s\n", ast_get_version());
3354 static int show_cli_help(void)
3356 printf("Asterisk %s, Copyright (C) 1999 - 2014, Digium, Inc. and others.\n", ast_get_version());
3357 printf("Usage: asterisk [OPTIONS]\n");
3358 printf("Valid Options:\n");
3359 printf(" -V Display version number and exit\n");
3360 printf(" -C <configfile> Use an alternate configuration file\n");
3361 printf(" -G <group> Run as a group other than the caller\n");
3362 printf(" -U <user> Run as a user other than the caller\n");
3363 printf(" -c Provide console CLI\n");
3364 printf(" -d Enable extra debugging\n");
3365 #if HAVE_WORKING_FORK
3366 printf(" -f Do not fork\n");
3367 printf(" -F Always fork\n");
3369 printf(" -g Dump core in case of a crash\n");
3370 printf(" -h This help screen\n");
3371 printf(" -i Initialize crypto keys at startup\n");
3372 printf(" -L <load> Limit the maximum load average before rejecting new calls\n");
3373 printf(" -M <value> Limit the maximum number of calls to the specified value\n");
3374 printf(" -m Mute debugging and console output on the console\n");
3375 printf(" -n Disable console colorization\n");
3376 printf(" -p Run as pseudo-realtime thread\n");
3377 printf(" -q Quiet mode (suppress output)\n");
3378 printf(" -r Connect to Asterisk on this machine\n");
3379 printf(" -R Same as -r, except attempt to reconnect if disconnected\n");
3380 printf(" -s <socket> Connect to Asterisk via socket <socket> (only valid with -r)\n");
3381 printf(" -t Record soundfiles in /var/tmp and move them where they\n");
3382 printf(" belong after they are done\n");
3383 printf(" -T Display the time in [Mmm dd hh:mm:ss] format for each line\n");
3384 printf(" of output to the CLI\n");
3385 printf(" -v Increase verbosity (multiple v's = more verbose)\n");
3386 printf(" -x <cmd> Execute command <cmd> (implies -r)\n");
3387 printf(" -X Execute includes by default (allows #exec in asterisk.conf)\n");
3388 printf(" -W Adjust terminal colors to compensate for a light background\n");
3393 static void ast_readconfig(void)
3395 struct ast_config *cfg;
3396 struct ast_variable *v;
3397 char *config = DEFAULT_CONFIG_FILE;
3398 char hostname[MAXHOSTNAMELEN] = "";
3399 struct ast_flags config_flags = { CONFIG_FLAG_NOREALTIME };
3401 unsigned int dbdir:1;
3402 unsigned int keydir:1;
3404 /* Default to false for security */
3405 int live_dangerously = 0;
3407 /* Set default value */
3408 option_dtmfminduration = AST_MIN_DTMF_DURATION;
3410 if (ast_opt_override_config) {
3411 cfg = ast_config_load2(ast_config_AST_CONFIG_FILE, "" /* core, can't reload */, config_flags);
3412 if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEUNCHANGED || cfg == CONFIG_STATUS_FILEINVALID) {
3413 fprintf(stderr, "Unable to open specified master config file '%s', using built-in defaults\n", ast_config_AST_CONFIG_FILE);
3416 cfg = ast_config_load2(config, "" /* core, can't reload */, config_flags);
3419 /* init with buildtime config */
3420 ast_copy_string(cfg_paths.config_dir, DEFAULT_CONFIG_DIR, sizeof(cfg_paths.config_dir));
3421 ast_copy_string(cfg_paths.spool_dir, DEFAULT_SPOOL_DIR, sizeof(cfg_paths.spool_dir));
3422 ast_copy_string(cfg_paths.module_dir, DEFAULT_MODULE_DIR, sizeof(cfg_paths.module_dir));
3423 snprintf(cfg_paths.monitor_dir, sizeof(cfg_paths.monitor_dir), "%s/monitor", cfg_paths.spool_dir);
3424 snprintf(cfg_paths.recording_dir, sizeof(cfg_paths.recording_dir), "%s/recording", cfg_paths.spool_dir);
3425 ast_copy_string(cfg_paths.var_dir, DEFAULT_VAR_DIR, sizeof(cfg_paths.var_dir));
3426 ast_copy_string(cfg_paths.data_dir, DEFAULT_DATA_DIR, sizeof(cfg_paths.data_dir));
3427 ast_copy_string(cfg_paths.log_dir, DEFAULT_LOG_DIR, sizeof(cfg_paths.log_dir));
3428 ast_copy_string(cfg_paths.agi_dir, DEFAULT_AGI_DIR, sizeof(cfg_paths.agi_dir));
3429 ast_copy_string(cfg_paths.db_path, DEFAULT_DB, sizeof(cfg_paths.db_path));
3430 ast_copy_string(cfg_paths.sbin_dir, DEFAULT_SBIN_DIR, sizeof(cfg_paths.sbin_dir));
3431 ast_copy_string(cfg_paths.key_dir, DEFAULT_KEY_DIR, sizeof(cfg_paths.key_dir));
3432 ast_copy_string(cfg_paths.pid_path, DEFAULT_PID, sizeof(cfg_paths.pid_path));
3433 ast_copy_string(cfg_paths.socket_path, DEFAULT_SOCKET, sizeof(cfg_paths.socket_path));
3434 ast_copy_string(cfg_paths.run_dir, DEFAULT_RUN_DIR, sizeof(cfg_paths.run_dir));
3436 ast_set_default_eid(&ast_eid_default);
3438 /* no asterisk.conf? no problem, use buildtime config! */
3439 if (cfg == CONFIG_STATUS_FILEMISSING || cfg == CONFIG_STATUS_FILEUNCHANGED || cfg == CONFIG_STATUS_FILEINVALID) {
3443 for (v = ast_variable_browse(cfg, "files"); v; v = v->next) {
3444 if (!strcasecmp(v->name, "astctlpermissions"))
3445 ast_copy_string(ast_config_AST_CTL_PERMISSIONS, v->value, sizeof(ast_config_AST_CTL_PERMISSIONS));
3446 else if (!strcasecmp(v->name, "astctlowner"))
3447 ast_copy_string(ast_config_AST_CTL_OWNER, v->value, sizeof(ast_config_AST_CTL_OWNER));
3448 else if (!strcasecmp(v->name, "astctlgroup"))
3449 ast_copy_string(ast_config_AST_CTL_GROUP, v->value, sizeof(ast_config_AST_CTL_GROUP));
3450 else if (!strcasecmp(v->name, "astctl"))
3451 ast_copy_string(ast_config_AST_CTL, v->value, sizeof(ast_config_AST_CTL));
3454 for (v = ast_variable_browse(cfg, "directories"); v; v = v->next) {
3455 if (!strcasecmp(v->name, "astetcdir")) {
3456 ast_copy_string(cfg_paths.config_dir, v->value, sizeof(cfg_paths.config_dir));
3457 } else if (!strcasecmp(v->name, "astspooldir")) {
3458 ast_copy_string(cfg_paths.spool_dir, v->value, sizeof(cfg_paths.spool_dir));
3459 snprintf(cfg_paths.monitor_dir, sizeof(cfg_paths.monitor_dir), "%s/monitor", v->value);
3460 snprintf(cfg_paths.recording_dir, sizeof(cfg_paths.recording_dir), "%s/recording", v->value);
3461 } else if (!strcasecmp(v->name, "astvarlibdir")) {
3462 ast_copy_string(cfg_paths.var_dir, v->value, sizeof(cfg_paths.var_dir));
3464 snprintf(cfg_paths.db_path, sizeof(cfg_paths.db_path), "%s/astdb", v->value);
3465 } else if (!strcasecmp(v->name, "astdbdir")) {
3466 snprintf(cfg_paths.db_path, sizeof(cfg_paths.db_path), "%s/astdb", v->value);
3468 } else if (!strcasecmp(v->name, "astdatadir")) {
3469 ast_copy_string(cfg_paths.data_dir, v->value, sizeof(cfg_paths.data_dir));
3471 snprintf(cfg_paths.key_dir, sizeof(cfg_paths.key_dir), "%s/keys", v->value);
3472 } else if (!strcasecmp(v->name, "astkeydir")) {
3473 snprintf(cfg_paths.key_dir, sizeof(cfg_paths.key_dir), "%s/keys", v->value);
3475 } else if (!strcasecmp(v->name, "astlogdir")) {
3476 ast_copy_string(cfg_paths.log_dir, v->value, sizeof(cfg_paths.log_dir));
3477 } else if (!strcasecmp(v->name, "astagidir")) {
3478 ast_copy_string(cfg_paths.agi_dir, v->value, sizeof(cfg_paths.agi_dir));
3479 } else if (!strcasecmp(v->name, "astrundir")) {
3480 snprintf(cfg_paths.pid_path, sizeof(cfg_paths.pid_path), "%s/%s", v->value, "asterisk.pid");
3481 snprintf(cfg_paths.socket_path, sizeof(cfg_paths.socket_path), "%s/%s", v->value, ast_config_AST_CTL);
3482 ast_copy_string(cfg_paths.run_dir, v->value, sizeof(cfg_paths.run_dir));
3483 } else if (!strcasecmp(v->name, "astmoddir")) {
3484 ast_copy_string(cfg_paths.module_dir, v->value, sizeof(cfg_paths.module_dir));
3485 } else if (!strcasecmp(v->name, "astsbindir")) {
3486 ast_copy_string(cfg_paths.sbin_dir, v->value, sizeof(cfg_paths.sbin_dir));
3490 for (v = ast_variable_browse(cfg, "options"); v; v = v->next) {
3491 /* verbose level (-v at startup) */
3492 if (!strcasecmp(v->name, "verbose")) {
3493 option_verbose = atoi(v->value);
3494 /* whether or not to force timestamping in CLI verbose output. (-T at startup) */
3495 } else if (!strcasecmp(v->name, "timestamp")) {
3496 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_TIMESTAMP);
3497 /* whether or not to support #exec in config files */
3498 } else if (!strcasecmp(v->name, "execincludes")) {
3499 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_EXEC_INCLUDES);
3500 /* debug level (-d at startup) */
3501 } else if (!strcasecmp(v->name, "debug")) {
3503 if (sscanf(v->value, "%30d", &option_debug) != 1) {
3504 option_debug = ast_true(v->value);
3506 #if HAVE_WORKING_FORK
3507 /* Disable forking (-f at startup) */
3508 } else if (!strcasecmp(v->name, "nofork")) {
3509 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_NO_FORK);
3510 /* Always fork, even if verbose or debug are enabled (-F at startup) */
3511 } else if (!strcasecmp(v->name, "alwaysfork")) {
3512 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_ALWAYS_FORK);
3514 /* Run quietly (-q at startup ) */
3515 } else if (!strcasecmp(v->name, "quiet")) {
3516 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_QUIET);
3517 /* Run as console (-c at startup, implies nofork) */
3518 } else if (!strcasecmp(v->name, "console")) {
3519 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_NO_FORK | AST_OPT_FLAG_CONSOLE);
3520 /* Run with high priority if the O/S permits (-p at startup) */
3521 } else if (!strcasecmp(v->name, "highpriority")) {
3522 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_HIGH_PRIORITY);
3523 /* Initialize RSA auth keys (IAX2) (-i at startup) */
3524 } else if (!strcasecmp(v->name, "initcrypto")) {
3525 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_INIT_KEYS);
3526 /* Disable ANSI colors for console (-c at startup) */
3527 } else if (!strcasecmp(v->name, "nocolor")) {
3528 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_NO_COLOR);
3529 /* Disable some usage warnings for picky people :p */
3530 } else if (!strcasecmp(v->name, "dontwarn")) {
3531 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_DONT_WARN);
3532 /* Dump core in case of crash (-g) */
3533 } else if (!strcasecmp(v->name, "dumpcore")) {
3534 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_DUMP_CORE);
3535 /* Cache recorded sound files to another directory during recording */
3536 } else if (!strcasecmp(v->name, "cache_record_files")) {
3537 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_CACHE_RECORD_FILES);
3538 /* Specify cache directory */
3539 } else if (!strcasecmp(v->name, "record_cache_dir")) {
3540 ast_copy_string(record_cache_dir, v->value, AST_CACHE_DIR_LEN);
3541 /* Build transcode paths via SLINEAR, instead of directly */
3542 } else if (!strcasecmp(v->name, "transcode_via_sln")) {
3543 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_TRANSCODE_VIA_SLIN);
3544 /* Transmit SLINEAR silence while a channel is being recorded or DTMF is being generated on a channel */
3545 } else if (!strcasecmp(v->name, "transmit_silence_during_record") || !strcasecmp(v->name, "transmit_silence")) {
3546 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_TRANSMIT_SILENCE);
3547 /* Enable internal timing */
3548 } else if (!strcasecmp(v->name, "internal_timing")) {
3549 if (!ast_opt_remote) {
3551 "NOTICE: The internal_timing option is no longer needed.\n"
3552 " It will always be enabled if you have a timing module loaded.\n");
3554 } else if (!strcasecmp(v->name, "mindtmfduration")) {
3555 if (sscanf(v->value, "%30u", &option_dtmfminduration) != 1) {
3556 option_dtmfminduration = AST_MIN_DTMF_DURATION;
3558 } else if (!strcasecmp(v->name, "maxcalls")) {
3559 if ((sscanf(v->value, "%30d", &ast_option_maxcalls) != 1) || (ast_option_maxcalls < 0)) {
3560 ast_option_maxcalls = 0;
3562 } else if (!strcasecmp(v->name, "maxload")) {
3565 if (getloadavg(test, 1) == -1) {
3566 ast_log(LOG_ERROR, "Cannot obtain load average on this system. 'maxload' option disabled.\n");
3567 ast_option_maxload = 0.0;
3568 } else if ((sscanf(v->value, "%30lf", &ast_option_maxload) != 1) || (ast_option_maxload < 0.0)) {
3569 ast_option_maxload = 0.0;
3571 /* Set the maximum amount of open files */
3572 } else if (!strcasecmp(v->name, "maxfiles")) {
3573 ast_option_maxfiles = atoi(v->value);
3574 set_ulimit(ast_option_maxfiles);
3575 /* What user to run as */
3576 } else if (!strcasecmp(v->name, "runuser")) {
3577 ast_copy_string(cfg_paths.run_user, v->value, sizeof(cfg_paths.run_user));
3578 /* What group to run as */
3579 } else if (!strcasecmp(v->name, "rungroup")) {
3580 ast_copy_string(cfg_paths.run_group, v->value, sizeof(cfg_paths.run_group));
3581 } else if (!strcasecmp(v->name, "systemname")) {
3582 ast_copy_string(cfg_paths.system_name, v->value, sizeof(cfg_paths.system_name));
3583 } else if (!strcasecmp(v->name, "autosystemname")) {
3584 if (ast_true(v->value)) {
3585 if (!gethostname(hostname, sizeof(hostname) - 1))
3586 ast_copy_string(cfg_paths.system_name, hostname, sizeof(cfg_paths.system_name));
3588 if (ast_strlen_zero(ast_config_AST_SYSTEM_NAME)){
3589 ast_copy_string(cfg_paths.system_name, "localhost", sizeof(cfg_paths.system_name));
3591 ast_log(LOG_ERROR, "Cannot obtain hostname for this system. Using '%s' instead.\n", ast_config_AST_SYSTEM_NAME);
3594 } else if (!strcasecmp(v->name, "languageprefix")) {
3595 ast_language_is_prefix = ast_true(v->value);
3596 } else if (!strcasecmp(v->name, "defaultlanguage")) {
3597 ast_copy_string(ast_defaultlanguage, v->value, MAX_LANGUAGE);
3598 } else if (!strcasecmp(v->name, "lockmode")) {
3599 if (!strcasecmp(v->value, "lockfile")) {
3600 ast_set_lock_type(AST_LOCK_TYPE_LOCKFILE);
3601 } else if (!strcasecmp(v->value, "flock")) {
3602 ast_set_lock_type(AST_LOCK_TYPE_FLOCK);
3604 ast_log(LOG_WARNING, "'%s' is not a valid setting for the lockmode option, "
3605 "defaulting to 'lockfile'\n", v->value);
3606 ast_set_lock_type(AST_LOCK_TYPE_LOCKFILE);
3608 #if defined(HAVE_SYSINFO)
3609 } else if (!strcasecmp(v->name, "minmemfree")) {
3610 /* specify the minimum amount of free memory to retain. Asterisk should stop accepting new calls
3611 * if the amount of free memory falls below this watermark */
3612 if ((sscanf(v->value, "%30ld", &option_minmemfree) != 1) || (option_minmemfree < 0)) {
3613 option_minmemfree = 0;
3616 } else if (!strcasecmp(v->name, "entityid")) {
3617 struct ast_eid tmp_eid;
3618 if (!ast_str_to_eid(&tmp_eid, v->value)) {
3619 ast_verbose("Successfully set global EID to '%s'\n", v->value);
3620 ast_eid_default = tmp_eid;
3622 ast_verbose("Invalid Entity ID '%s' provided\n", v->value);
3623 } else if (!strcasecmp(v->name, "lightbackground")) {
3624 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_LIGHT_BACKGROUND);
3625 } else if (!strcasecmp(v->name, "forceblackbackground")) {
3626 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_FORCE_BLACK_BACKGROUND);
3627 } else if (!strcasecmp(v->name, "hideconnect")) {
3628 ast_set2_flag(&ast_options, ast_true(v->value), AST_OPT_FLAG_HIDE_CONSOLE_CONNECT);
3629 } else if (!strcasecmp(v->name, "lockconfdir")) {