2 * Asterisk -- An open source telephony toolkit.
4 * Copyright (C) 1999 - 2013, 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 - 2013, 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 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/features.h"
206 #include "asterisk/acl.h"
207 #include "asterisk/ulaw.h"
208 #include "asterisk/alaw.h"
209 #include "asterisk/callerid.h"
210 #include "asterisk/image.h"
211 #include "asterisk/tdd.h"
212 #include "asterisk/term.h"
213 #include "asterisk/manager.h"
214 #include "asterisk/cdr.h"
215 #include "asterisk/cel.h"
216 #include "asterisk/pbx.h"
217 #include "asterisk/enum.h"
218 #include "asterisk/http.h"
219 #include "asterisk/udptl.h"
220 #include "asterisk/app.h"
221 #include "asterisk/lock.h"
222 #include "asterisk/utils.h"
223 #include "asterisk/file.h"
224 #include "asterisk/io.h"
225 #include "editline/histedit.h"
226 #include "asterisk/config.h"
227 #include "asterisk/ast_version.h"
228 #include "asterisk/linkedlists.h"
229 #include "asterisk/devicestate.h"
230 #include "asterisk/presencestate.h"
231 #include "asterisk/module.h"
232 #include "asterisk/dsp.h"
233 #include "asterisk/buildinfo.h"
234 #include "asterisk/xmldoc.h"
235 #include "asterisk/poll-compat.h"
236 #include "asterisk/ccss.h"
237 #include "asterisk/test.h"
238 #include "asterisk/rtp_engine.h"
239 #include "asterisk/format.h"
240 #include "asterisk/aoc.h"
241 #include "asterisk/uuid.h"
242 #include "asterisk/sorcery.h"
243 #include "asterisk/stasis.h"
244 #include "asterisk/json.h"
245 #include "asterisk/stasis_endpoints.h"
246 #include "asterisk/stasis_system.h"
247 #include "asterisk/security_events.h"
249 #include "../defaults.h"
252 <managerEvent language="en_US" name="FullyBooted">
253 <managerEventInstance class="EVENT_FLAG_SYSTEM">
254 <synopsis>Raised when all Asterisk initialization procedures have finished.</synopsis>
256 <parameter name="Status">
257 <para>Informational message</para>
260 </managerEventInstance>
262 <managerEvent language="en_US" name="Shutdown">
263 <managerEventInstance class="EVENT_FLAG_SYSTEM">
264 <synopsis>Raised when Asterisk is shutdown or restarted.</synopsis>
266 <parameter name="Shutdown">
267 <para>Whether the shutdown is proceeding cleanly (all channels
268 were hungup successfully) or uncleanly (channels will be
271 <enum name="Uncleanly"/>
272 <enum name="Cleanly"/>
275 <parameter name="Restart">
276 <para>Whether or not a restart will occur.</para>
283 </managerEventInstance>
288 #define AF_LOCAL AF_UNIX
289 #define PF_LOCAL PF_UNIX
292 #define AST_MAX_CONNECTS 128
295 /*! Default minimum DTMF digit length - 80ms */
296 #define AST_MIN_DTMF_DURATION 80
299 /*! \brief Welcome message when starting a CLI interface */
300 #define WELCOME_MESSAGE \
301 ast_verbose("Asterisk %s, Copyright (C) 1999 - 2013 Digium, Inc. and others.\n" \
302 "Created by Mark Spencer <markster@digium.com>\n" \
303 "Asterisk comes with ABSOLUTELY NO WARRANTY; type 'core show warranty' for details.\n" \
304 "This is free software, with components licensed under the GNU General Public\n" \
305 "License version 2 and other licenses; you are welcome to redistribute it under\n" \
306 "certain conditions. Type 'core show license' for details.\n" \
307 "=========================================================================\n", ast_get_version()) \
309 /*! \defgroup main_options Main Configuration Options
310 * \brief Main configuration options from asterisk.conf or OS command line on starting Asterisk.
311 * \arg \ref Config_ast "asterisk.conf"
312 * \note Some of them can be changed in the CLI
316 struct ast_flags ast_options = { AST_DEFAULT_OPTIONS };
317 struct ast_flags ast_compat = { 0 };
319 int option_verbose; /*!< Verbosity level */
320 int option_debug; /*!< Debug level */
321 double option_maxload; /*!< Max load avg on system */
322 int option_maxcalls; /*!< Max number of active calls */
323 int option_maxfiles; /*!< Max number of open file handles (files, sockets) */
324 unsigned int option_dtmfminduration; /*!< Minimum duration of DTMF. */
325 #if defined(HAVE_SYSINFO)
326 long option_minmemfree; /*!< Minimum amount of free system memory - stop accepting calls if free memory falls below this watermark */
331 struct ast_eid ast_eid_default;
333 /* XXX tmpdir is a subdir of the spool directory, and no way to remap it */
334 char record_cache_dir[AST_CACHE_DIR_LEN] = DEFAULT_TMP_DIR;
336 static int ast_socket = -1; /*!< UNIX Socket for allowing remote control */
337 static int ast_consock = -1; /*!< UNIX Socket for controlling another asterisk */
340 int fd; /*!< File descriptor */
341 int p[2]; /*!< Pipe */
342 pthread_t t; /*!< Thread of handler */
343 int mute; /*!< Is the console muted for logs */
344 int uid; /*!< Remote user ID. */
345 int gid; /*!< Remote group ID. */
346 int levels[NUMLOGLEVELS]; /*!< Which log levels are enabled for the console */
352 AST_LIST_ENTRY(ast_atexit) list;
355 static AST_LIST_HEAD_STATIC(atexits, ast_atexit);
357 struct timeval ast_startuptime;
358 struct timeval ast_lastreloadtime;
360 static History *el_hist;
362 static char *remotehostname;
364 struct console consoles[AST_MAX_CONNECTS];
366 char defaultlanguage[MAX_LANGUAGE] = DEFAULT_LANGUAGE;
368 static int ast_el_add_history(char *);
369 static int ast_el_read_history(char *);
370 static int ast_el_write_history(char *);
373 char config_dir[PATH_MAX];
374 char module_dir[PATH_MAX];
375 char spool_dir[PATH_MAX];
376 char monitor_dir[PATH_MAX];
377 char recording_dir[PATH_MAX];
378 char var_dir[PATH_MAX];
379 char data_dir[PATH_MAX];
380 char log_dir[PATH_MAX];
381 char agi_dir[PATH_MAX];
382 char run_dir[PATH_MAX];
383 char key_dir[PATH_MAX];
385 char config_file[PATH_MAX];
386 char db_path[PATH_MAX];
387 char sbin_dir[PATH_MAX];
388 char pid_path[PATH_MAX];
389 char socket_path[PATH_MAX];
390 char run_user[PATH_MAX];
391 char run_group[PATH_MAX];
392 char system_name[128];
395 static struct _cfg_paths cfg_paths;
397 const char *ast_config_AST_CONFIG_DIR = cfg_paths.config_dir;
398 const char *ast_config_AST_CONFIG_FILE = cfg_paths.config_file;
399 const char *ast_config_AST_MODULE_DIR = cfg_paths.module_dir;
400 const char *ast_config_AST_SPOOL_DIR = cfg_paths.spool_dir;
401 const char *ast_config_AST_MONITOR_DIR = cfg_paths.monitor_dir;
402 const char *ast_config_AST_RECORDING_DIR = cfg_paths.recording_dir;
403 const char *ast_config_AST_VAR_DIR = cfg_paths.var_dir;
404 const char *ast_config_AST_DATA_DIR = cfg_paths.data_dir;
405 const char *ast_config_AST_LOG_DIR = cfg_paths.log_dir;
406 const char *ast_config_AST_AGI_DIR = cfg_paths.agi_dir;
407 const char *ast_config_AST_KEY_DIR = cfg_paths.key_dir;
408 const char *ast_config_AST_RUN_DIR = cfg_paths.run_dir;
409 const char *ast_config_AST_SBIN_DIR = cfg_paths.sbin_dir;
411 const char *ast_config_AST_DB = cfg_paths.db_path;
412 const char *ast_config_AST_PID = cfg_paths.pid_path;
413 const char *ast_config_AST_SOCKET = cfg_paths.socket_path;
414 const char *ast_config_AST_RUN_USER = cfg_paths.run_user;
415 const char *ast_config_AST_RUN_GROUP = cfg_paths.run_group;
416 const char *ast_config_AST_SYSTEM_NAME = cfg_paths.system_name;
418 static char ast_config_AST_CTL_PERMISSIONS[PATH_MAX];
419 static char ast_config_AST_CTL_OWNER[PATH_MAX] = "\0";
420 static char ast_config_AST_CTL_GROUP[PATH_MAX] = "\0";
421 static char ast_config_AST_CTL[PATH_MAX] = "asterisk.ctl";
423 extern unsigned int ast_FD_SETSIZE;
425 static char *_argv[256];
427 NOT_SHUTTING_DOWN = -2,
429 /* Valid values for quit_handler niceness below: */
435 static shutdown_nice_t shuttingdown = NOT_SHUTTING_DOWN;
436 static int restartnow;
437 static pthread_t consolethread = AST_PTHREADT_NULL;
438 static pthread_t mon_sig_flags;
439 static int canary_pid = 0;
440 static char canary_filename[128];
441 static int multi_thread_safe;
443 static char randompool[256];
445 static int sig_alert_pipe[2] = { -1, -1 };
447 unsigned int need_reload:1;
448 unsigned int need_quit:1;
449 unsigned int need_quit_handler:1;
452 #if !defined(LOW_MEMORY)
453 struct file_version {
454 AST_RWLIST_ENTRY(file_version) list;
459 static AST_RWLIST_HEAD_STATIC(file_versions, file_version);
461 void ast_register_file_version(const char *file, const char *version)
463 struct file_version *new;
465 size_t version_length;
467 work = ast_strdupa(version);
468 work = ast_strip(ast_strip_quoted(work, "$", "$"));
469 version_length = strlen(work) + 1;
471 if (!(new = ast_calloc(1, sizeof(*new) + version_length)))
475 new->version = (char *) new + sizeof(*new);
476 memcpy(new->version, work, version_length);
477 AST_RWLIST_WRLOCK(&file_versions);
478 AST_RWLIST_INSERT_HEAD(&file_versions, new, list);
479 AST_RWLIST_UNLOCK(&file_versions);
482 void ast_unregister_file_version(const char *file)
484 struct file_version *find;
486 AST_RWLIST_WRLOCK(&file_versions);
487 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&file_versions, find, list) {
488 if (!strcasecmp(find->file, file)) {
489 AST_RWLIST_REMOVE_CURRENT(list);
493 AST_RWLIST_TRAVERSE_SAFE_END;
494 AST_RWLIST_UNLOCK(&file_versions);
500 char *ast_complete_source_filename(const char *partial, int n)
502 struct file_version *find;
503 size_t len = strlen(partial);
507 AST_RWLIST_RDLOCK(&file_versions);
508 AST_RWLIST_TRAVERSE(&file_versions, find, list) {
509 if (!strncasecmp(find->file, partial, len) && ++count > n) {
510 res = ast_strdup(find->file);
514 AST_RWLIST_UNLOCK(&file_versions);
518 /*! \brief Find version for given module name */
519 const char *ast_file_version_find(const char *file)
521 struct file_version *iterator;
523 AST_RWLIST_WRLOCK(&file_versions);
524 AST_RWLIST_TRAVERSE(&file_versions, iterator, list) {
525 if (!strcasecmp(iterator->file, file))
528 AST_RWLIST_UNLOCK(&file_versions);
530 return iterator->version;
534 struct thread_list_t {
535 AST_RWLIST_ENTRY(thread_list_t) list;
541 static AST_RWLIST_HEAD_STATIC(thread_list, thread_list_t);
543 void ast_register_thread(char *name)
545 struct thread_list_t *new = ast_calloc(1, sizeof(*new));
550 ast_assert(multi_thread_safe);
551 new->id = pthread_self();
552 new->lwp = ast_get_tid();
553 new->name = name; /* steal the allocated memory for the thread name */
554 AST_RWLIST_WRLOCK(&thread_list);
555 AST_RWLIST_INSERT_HEAD(&thread_list, new, list);
556 AST_RWLIST_UNLOCK(&thread_list);
559 void ast_unregister_thread(void *id)
561 struct thread_list_t *x;
563 AST_RWLIST_WRLOCK(&thread_list);
564 AST_RWLIST_TRAVERSE_SAFE_BEGIN(&thread_list, x, list) {
565 if ((void *) x->id == id) {
566 AST_RWLIST_REMOVE_CURRENT(list);
570 AST_RWLIST_TRAVERSE_SAFE_END;
571 AST_RWLIST_UNLOCK(&thread_list);
578 /*! \brief Give an overview of core settings */
579 static char *handle_show_settings(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
587 e->command = "core show settings";
588 e->usage = "Usage: core show settings\n"
589 " Show core misc settings";
595 ast_eid_to_str(eid_str, sizeof(eid_str), &ast_eid_default);
597 ast_cli(a->fd, "\nPBX Core settings\n");
598 ast_cli(a->fd, "-----------------\n");
599 ast_cli(a->fd, " Version: %s\n", ast_get_version());
600 ast_cli(a->fd, " Build Options: %s\n", S_OR(AST_BUILDOPTS, "(none)"));
602 ast_cli(a->fd, " Maximum calls: %d (Current %d)\n", option_maxcalls, ast_active_channels());
604 ast_cli(a->fd, " Maximum calls: Not set\n");
606 ast_cli(a->fd, " Maximum open file handles: %d\n", option_maxfiles);
608 ast_cli(a->fd, " Maximum open file handles: Not set\n");
609 ast_cli(a->fd, " Verbosity: %d\n", option_verbose);
610 ast_cli(a->fd, " Debug level: %d\n", option_debug);
611 ast_cli(a->fd, " Maximum load average: %lf\n", option_maxload);
612 #if defined(HAVE_SYSINFO)
613 ast_cli(a->fd, " Minimum free memory: %ld MB\n", option_minmemfree);
615 if (ast_localtime(&ast_startuptime, &tm, NULL)) {
616 ast_strftime(buf, sizeof(buf), "%H:%M:%S", &tm);
617 ast_cli(a->fd, " Startup time: %s\n", buf);
619 if (ast_localtime(&ast_lastreloadtime, &tm, NULL)) {
620 ast_strftime(buf, sizeof(buf), "%H:%M:%S", &tm);
621 ast_cli(a->fd, " Last reload time: %s\n", buf);
623 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);
624 ast_cli(a->fd, " System name: %s\n", ast_config_AST_SYSTEM_NAME);
625 ast_cli(a->fd, " Entity ID: %s\n", eid_str);
626 ast_cli(a->fd, " Default language: %s\n", defaultlanguage);
627 ast_cli(a->fd, " Language prefix: %s\n", ast_language_is_prefix ? "Enabled" : "Disabled");
628 ast_cli(a->fd, " User name and group: %s/%s\n", ast_config_AST_RUN_USER, ast_config_AST_RUN_GROUP);
629 ast_cli(a->fd, " Executable includes: %s\n", ast_test_flag(&ast_options, AST_OPT_FLAG_EXEC_INCLUDES) ? "Enabled" : "Disabled");
630 ast_cli(a->fd, " Transcode via SLIN: %s\n", ast_test_flag(&ast_options, AST_OPT_FLAG_TRANSCODE_VIA_SLIN) ? "Enabled" : "Disabled");
631 ast_cli(a->fd, " Internal timing: %s\n", ast_test_flag(&ast_options, AST_OPT_FLAG_INTERNAL_TIMING) ? "Enabled" : "Disabled");
632 ast_cli(a->fd, " Transmit silence during rec: %s\n", ast_test_flag(&ast_options, AST_OPT_FLAG_TRANSMIT_SILENCE) ? "Enabled" : "Disabled");
633 ast_cli(a->fd, " Generic PLC: %s\n", ast_test_flag(&ast_options, AST_OPT_FLAG_GENERIC_PLC) ? "Enabled" : "Disabled");
634 ast_cli(a->fd, " Min DTMF duration:: %u\n", option_dtmfminduration);
636 ast_cli(a->fd, "\n* Subsystems\n");
637 ast_cli(a->fd, " -------------\n");
638 ast_cli(a->fd, " Manager (AMI): %s\n", check_manager_enabled() ? "Enabled" : "Disabled");
639 ast_cli(a->fd, " Web Manager (AMI/HTTP): %s\n", check_webmanager_enabled() ? "Enabled" : "Disabled");
640 ast_cli(a->fd, " Call data records: %s\n", ast_cdr_is_enabled() ? "Enabled" : "Disabled");
641 ast_cli(a->fd, " Realtime Architecture (ARA): %s\n", ast_realtime_enabled() ? "Enabled" : "Disabled");
643 /*! \todo we could check musiconhold, voicemail, smdi, adsi, queues */
645 ast_cli(a->fd, "\n* Directories\n");
646 ast_cli(a->fd, " -------------\n");
647 ast_cli(a->fd, " Configuration file: %s\n", ast_config_AST_CONFIG_FILE);
648 ast_cli(a->fd, " Configuration directory: %s\n", ast_config_AST_CONFIG_DIR);
649 ast_cli(a->fd, " Module directory: %s\n", ast_config_AST_MODULE_DIR);
650 ast_cli(a->fd, " Spool directory: %s\n", ast_config_AST_SPOOL_DIR);
651 ast_cli(a->fd, " Log directory: %s\n", ast_config_AST_LOG_DIR);
652 ast_cli(a->fd, " Run/Sockets directory: %s\n", ast_config_AST_RUN_DIR);
653 ast_cli(a->fd, " PID file: %s\n", ast_config_AST_PID);
654 ast_cli(a->fd, " VarLib directory: %s\n", ast_config_AST_VAR_DIR);
655 ast_cli(a->fd, " Data directory: %s\n", ast_config_AST_DATA_DIR);
656 ast_cli(a->fd, " ASTDB: %s\n", ast_config_AST_DB);
657 ast_cli(a->fd, " IAX2 Keys directory: %s\n", ast_config_AST_KEY_DIR);
658 ast_cli(a->fd, " AGI Scripts directory: %s\n", ast_config_AST_AGI_DIR);
659 ast_cli(a->fd, "\n\n");
663 static char *handle_show_threads(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
666 struct thread_list_t *cur;
669 e->command = "core show threads";
671 "Usage: core show threads\n"
672 " List threads currently active in the system.\n";
678 AST_RWLIST_RDLOCK(&thread_list);
679 AST_RWLIST_TRAVERSE(&thread_list, cur, list) {
680 ast_cli(a->fd, "%p %d %s\n", (void *)cur->id, cur->lwp, cur->name);
683 AST_RWLIST_UNLOCK(&thread_list);
684 ast_cli(a->fd, "%d threads listed.\n", count);
688 #if defined (HAVE_SYSCTL) && defined(HAVE_SWAPCTL)
690 * swapmode is rewritten by Tobias Weingartner <weingart@openbsd.org>
691 * to be based on the new swapctl(2) system call.
693 static int swapmode(int *used, int *total)
695 struct swapent *swdev;
696 int nswap, rnswap, i;
698 nswap = swapctl(SWAP_NSWAP, 0, 0);
702 swdev = ast_calloc(nswap, sizeof(*swdev));
706 rnswap = swapctl(SWAP_STATS, swdev, nswap);
712 /* if rnswap != nswap, then what? */
714 /* Total things up */
716 for (i = 0; i < nswap; i++) {
717 if (swdev[i].se_flags & SWF_ENABLE) {
718 *used += (swdev[i].se_inuse / (1024 / DEV_BSIZE));
719 *total += (swdev[i].se_nblks / (1024 / DEV_BSIZE));
725 #elif defined(HAVE_SYSCTL) && !defined(HAVE_SYSINFO)
726 static int swapmode(int *used, int *total)
733 #if defined(HAVE_SYSINFO) || defined(HAVE_SYSCTL)
734 /*! \brief Give an overview of system statistics */
735 static char *handle_show_sysinfo(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
737 uint64_t physmem, freeram;
738 uint64_t freeswap = 0;
742 #if defined(HAVE_SYSINFO)
743 struct sysinfo sys_info;
745 uptime = sys_info.uptime / 3600;
746 physmem = sys_info.totalram * sys_info.mem_unit;
747 freeram = (sys_info.freeram * sys_info.mem_unit) / 1024;
748 totalswap = (sys_info.totalswap * sys_info.mem_unit) / 1024;
749 freeswap = (sys_info.freeswap * sys_info.mem_unit) / 1024;
750 nprocs = sys_info.procs;
751 #elif defined(HAVE_SYSCTL)
752 static int pageshift;
753 struct vmtotal vmtotal;
754 struct timeval boottime;
756 int mib[2], pagesize, usedswap = 0;
758 /* calculate the uptime by looking at boottime */
761 mib[1] = KERN_BOOTTIME;
762 len = sizeof(boottime);
763 if (sysctl(mib, 2, &boottime, &len, NULL, 0) != -1) {
764 uptime = now - boottime.tv_sec;
766 uptime = uptime/3600;
767 /* grab total physical memory */
769 #if defined(HW_PHYSMEM64)
770 mib[1] = HW_PHYSMEM64;
774 len = sizeof(physmem);
775 sysctl(mib, 2, &physmem, &len, NULL, 0);
777 pagesize = getpagesize();
779 while (pagesize > 1) {
784 /* we only need the amount of log(2)1024 for our conversion */
790 len = sizeof(vmtotal);
791 sysctl(mib, 2, &vmtotal, &len, NULL, 0);
792 freeram = (vmtotal.t_free << pageshift);
793 /* generate swap usage and totals */
794 swapmode(&usedswap, &totalswap);
795 freeswap = (totalswap - usedswap);
796 /* grab number of processes */
797 #if defined(__OpenBSD__)
799 mib[1] = KERN_NPROCS;
800 len = sizeof(nprocs);
801 sysctl(mib, 2, &nprocs, &len, NULL, 0);
807 e->command = "core show sysinfo";
809 "Usage: core show sysinfo\n"
810 " List current system information.\n";
816 ast_cli(a->fd, "\nSystem Statistics\n");
817 ast_cli(a->fd, "-----------------\n");
818 ast_cli(a->fd, " System Uptime: %lu hours\n", uptime);
819 ast_cli(a->fd, " Total RAM: %" PRIu64 " KiB\n", physmem / 1024);
820 ast_cli(a->fd, " Free RAM: %" PRIu64 " KiB\n", freeram);
821 #if defined(HAVE_SYSINFO)
822 ast_cli(a->fd, " Buffer RAM: %" PRIu64 " KiB\n", ((uint64_t) sys_info.bufferram * sys_info.mem_unit) / 1024);
824 #if defined (HAVE_SYSCTL) || defined(HAVE_SWAPCTL)
825 ast_cli(a->fd, " Total Swap Space: %u KiB\n", totalswap);
826 ast_cli(a->fd, " Free Swap Space: %" PRIu64 " KiB\n\n", freeswap);
828 ast_cli(a->fd, " Number of Processes: %d \n\n", nprocs);
833 struct profile_entry {
835 uint64_t scale; /* if non-zero, values are scaled by this */
841 struct profile_data {
844 struct profile_entry e[0];
847 static struct profile_data *prof_data;
849 /*! \brief allocates a counter with a given name and scale.
850 * \return Returns the identifier of the counter.
852 int ast_add_profile(const char *name, uint64_t scale)
854 int l = sizeof(struct profile_data);
855 int n = 10; /* default entries */
857 if (prof_data == NULL) {
858 prof_data = ast_calloc(1, l + n*sizeof(struct profile_entry));
859 if (prof_data == NULL)
861 prof_data->entries = 0;
862 prof_data->max_size = n;
864 if (prof_data->entries >= prof_data->max_size) {
866 n = prof_data->max_size + 20;
867 p = ast_realloc(prof_data, l + n*sizeof(struct profile_entry));
871 prof_data->max_size = n;
873 n = prof_data->entries++;
874 prof_data->e[n].name = ast_strdup(name);
875 prof_data->e[n].value = 0;
876 prof_data->e[n].events = 0;
877 prof_data->e[n].mark = 0;
878 prof_data->e[n].scale = scale;
882 int64_t ast_profile(int i, int64_t delta)
884 if (!prof_data || i < 0 || i > prof_data->entries) /* invalid index */
886 if (prof_data->e[i].scale > 1)
887 delta /= prof_data->e[i].scale;
888 prof_data->e[i].value += delta;
889 prof_data->e[i].events++;
890 return prof_data->e[i].value;
893 /* The RDTSC instruction was introduced on the Pentium processor and is not
894 * implemented on certain clones, like the Cyrix 586. Hence, the previous
895 * expectation of __i386__ was in error. */
896 #if defined ( __i686__) && (defined(__FreeBSD__) || defined(linux))
897 #if defined(__FreeBSD__)
898 #include <machine/cpufunc.h>
900 static __inline uint64_t
905 __asm __volatile(".byte 0x0f, 0x31" : "=A" (rv));
909 #else /* supply a dummy function on other platforms */
910 static __inline uint64_t
917 int64_t ast_mark(int i, int startstop)
919 if (!prof_data || i < 0 || i > prof_data->entries) /* invalid index */
922 prof_data->e[i].mark = rdtsc();
924 prof_data->e[i].mark = (rdtsc() - prof_data->e[i].mark);
925 if (prof_data->e[i].scale > 1)
926 prof_data->e[i].mark /= prof_data->e[i].scale;
927 prof_data->e[i].value += prof_data->e[i].mark;
928 prof_data->e[i].events++;
930 return prof_data->e[i].mark;
933 #define DEFINE_PROFILE_MIN_MAX_VALUES min = 0; \
934 max = prof_data->entries;\
935 if (a->argc > 3) { /* specific entries */ \
936 if (isdigit(a->argv[3][0])) { \
937 min = atoi(a->argv[3]); \
938 if (a->argc == 5 && strcmp(a->argv[4], "-")) \
939 max = atoi(a->argv[4]); \
941 search = a->argv[3]; \
943 if (max > prof_data->entries) \
944 max = prof_data->entries;
946 static char *handle_show_profile(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
949 const char *search = NULL;
952 e->command = "core show profile";
953 e->usage = "Usage: core show profile\n"
954 " show profile information";
960 if (prof_data == NULL)
963 DEFINE_PROFILE_MIN_MAX_VALUES;
964 ast_cli(a->fd, "profile values (%d, allocated %d)\n-------------------\n",
965 prof_data->entries, prof_data->max_size);
966 ast_cli(a->fd, "%6s %8s %10s %12s %12s %s\n", "ID", "Scale", "Events",
967 "Value", "Average", "Name");
968 for (i = min; i < max; i++) {
969 struct profile_entry *entry = &prof_data->e[i];
970 if (!search || strstr(entry->name, search))
971 ast_cli(a->fd, "%6d: [%8ld] %10ld %12lld %12lld %s\n",
974 (long)entry->events, (long long)entry->value,
975 (long long)(entry->events ? entry->value / entry->events : entry->value),
981 static char *handle_clear_profile(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
984 const char *search = NULL;
987 e->command = "core clear profile";
988 e->usage = "Usage: core clear profile\n"
989 " clear profile information";
995 if (prof_data == NULL)
998 DEFINE_PROFILE_MIN_MAX_VALUES;
999 for (i= min; i < max; i++) {
1000 if (!search || strstr(prof_data->e[i].name, search)) {
1001 prof_data->e[i].value = 0;
1002 prof_data->e[i].events = 0;
1007 #undef DEFINE_PROFILE_MIN_MAX_VALUES
1009 /*! \brief CLI command to list module versions */
1010 static char *handle_show_version_files(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1012 #define FORMAT "%-25.25s %-40.40s\n"
1013 struct file_version *iterator;
1015 int havepattern = 0;
1017 int count_files = 0;
1019 int matchlen, which = 0;
1020 struct file_version *find;
1024 e->command = "core show file version [like]";
1026 "Usage: core show file version [like <pattern>]\n"
1027 " Lists the revision numbers of the files used to build this copy of Asterisk.\n"
1028 " Optional regular expression pattern is used to filter the file list.\n";
1031 matchlen = strlen(a->word);
1034 AST_RWLIST_RDLOCK(&file_versions);
1035 AST_RWLIST_TRAVERSE(&file_versions, find, list) {
1036 if (!strncasecmp(a->word, find->file, matchlen) && ++which > a->n) {
1037 ret = ast_strdup(find->file);
1041 AST_RWLIST_UNLOCK(&file_versions);
1048 if (!strcasecmp(a->argv[4], "like")) {
1049 if (regcomp(®exbuf, a->argv[5], REG_EXTENDED | REG_NOSUB))
1050 return CLI_SHOWUSAGE;
1053 return CLI_SHOWUSAGE;
1061 return CLI_SHOWUSAGE;
1064 ast_cli(a->fd, FORMAT, "File", "Revision");
1065 ast_cli(a->fd, FORMAT, "----", "--------");
1066 AST_RWLIST_RDLOCK(&file_versions);
1067 AST_RWLIST_TRAVERSE(&file_versions, iterator, list) {
1068 if (havename && strcasecmp(iterator->file, a->argv[4]))
1071 if (havepattern && regexec(®exbuf, iterator->file, 0, NULL, 0))
1074 ast_cli(a->fd, FORMAT, iterator->file, iterator->version);
1079 AST_RWLIST_UNLOCK(&file_versions);
1081 ast_cli(a->fd, "%d files listed.\n", count_files);
1091 #endif /* ! LOW_MEMORY */
1093 static void publish_fully_booted(void)
1095 RAII_VAR(struct ast_json *, json_object, NULL, ast_json_unref);
1097 json_object = ast_json_pack("{s: s}",
1098 "Status", "Fully Booted");
1099 ast_manager_publish_event("FullyBooted", EVENT_FLAG_SYSTEM, json_object);
1102 static void ast_run_atexits(int run_cleanups)
1104 struct ast_atexit *ae;
1106 AST_LIST_LOCK(&atexits);
1107 while ((ae = AST_LIST_REMOVE_HEAD(&atexits, list))) {
1108 if (ae->func && (!ae->is_cleanup || run_cleanups)) {
1113 AST_LIST_UNLOCK(&atexits);
1116 static void __ast_unregister_atexit(void (*func)(void))
1118 struct ast_atexit *ae;
1120 AST_LIST_TRAVERSE_SAFE_BEGIN(&atexits, ae, list) {
1121 if (ae->func == func) {
1122 AST_LIST_REMOVE_CURRENT(list);
1127 AST_LIST_TRAVERSE_SAFE_END;
1130 static int register_atexit(void (*func)(void), int is_cleanup)
1132 struct ast_atexit *ae;
1134 ae = ast_calloc(1, sizeof(*ae));
1139 ae->is_cleanup = is_cleanup;
1141 AST_LIST_LOCK(&atexits);
1142 __ast_unregister_atexit(func);
1143 AST_LIST_INSERT_HEAD(&atexits, ae, list);
1144 AST_LIST_UNLOCK(&atexits);
1149 int ast_register_atexit(void (*func)(void))
1151 return register_atexit(func, 0);
1154 int ast_register_cleanup(void (*func)(void))
1156 return register_atexit(func, 1);
1159 void ast_unregister_atexit(void (*func)(void))
1161 AST_LIST_LOCK(&atexits);
1162 __ast_unregister_atexit(func);
1163 AST_LIST_UNLOCK(&atexits);
1166 /* Sending commands from consoles back to the daemon requires a terminating NULL */
1167 static int fdsend(int fd, const char *s)
1169 return write(fd, s, strlen(s) + 1);
1172 /* Sending messages from the daemon back to the display requires _excluding_ the terminating NULL */
1173 static int fdprint(int fd, const char *s)
1175 return write(fd, s, strlen(s));
1178 /*! \brief NULL handler so we can collect the child exit status */
1179 static void _null_sig_handler(int sig)
1183 static struct sigaction null_sig_handler = {
1184 .sa_handler = _null_sig_handler,
1185 .sa_flags = SA_RESTART,
1188 static struct sigaction ignore_sig_handler = {
1189 .sa_handler = SIG_IGN,
1192 AST_MUTEX_DEFINE_STATIC(safe_system_lock);
1193 /*! \brief Keep track of how many threads are currently trying to wait*() on
1196 static unsigned int safe_system_level = 0;
1197 static struct sigaction safe_system_prev_handler;
1199 void ast_replace_sigchld(void)
1203 ast_mutex_lock(&safe_system_lock);
1204 level = safe_system_level++;
1206 /* only replace the handler if it has not already been done */
1208 sigaction(SIGCHLD, &null_sig_handler, &safe_system_prev_handler);
1211 ast_mutex_unlock(&safe_system_lock);
1214 void ast_unreplace_sigchld(void)
1218 ast_mutex_lock(&safe_system_lock);
1219 level = --safe_system_level;
1221 /* only restore the handler if we are the last one */
1223 sigaction(SIGCHLD, &safe_system_prev_handler, NULL);
1226 ast_mutex_unlock(&safe_system_lock);
1229 int ast_safe_system(const char *s)
1233 struct rusage rusage;
1236 #if defined(HAVE_WORKING_FORK) || defined(HAVE_WORKING_VFORK)
1237 ast_replace_sigchld();
1239 #ifdef HAVE_WORKING_FORK
1247 cap_t cap = cap_from_text("cap_net_admin-eip");
1249 if (cap_set_proc(cap)) {
1250 /* Careful with order! Logging cannot happen after we close FDs */
1251 ast_log(LOG_WARNING, "Unable to remove capabilities.\n");
1255 #ifdef HAVE_WORKING_FORK
1256 if (ast_opt_high_priority)
1257 ast_set_priority(0);
1258 /* Close file descriptors and launch system command */
1259 ast_close_fds_above_n(STDERR_FILENO);
1261 execl("/bin/sh", "/bin/sh", "-c", s, (char *) NULL);
1263 } else if (pid > 0) {
1265 res = wait4(pid, &status, 0, &rusage);
1267 res = WIFEXITED(status) ? WEXITSTATUS(status) : -1;
1269 } else if (errno != EINTR)
1273 ast_log(LOG_WARNING, "Fork failed: %s\n", strerror(errno));
1277 ast_unreplace_sigchld();
1278 #else /* !defined(HAVE_WORKING_FORK) && !defined(HAVE_WORKING_VFORK) */
1286 * \brief enable or disable a logging level to a specified console
1288 void ast_console_toggle_loglevel(int fd, int level, int state)
1292 if (level >= NUMLOGLEVELS) {
1293 level = NUMLOGLEVELS - 1;
1296 for (x = 0;x < AST_MAX_CONNECTS; x++) {
1297 if (fd == consoles[x].fd) {
1299 * Since the logging occurs when levels are false, set to
1300 * flipped iinput because this function accepts 0 as off and 1 as on
1302 consoles[x].levels[level] = state ? 0 : 1;
1309 * \brief mute or unmute a console from logging
1311 void ast_console_toggle_mute(int fd, int silent)
1314 for (x = 0;x < AST_MAX_CONNECTS; x++) {
1315 if (fd == consoles[x].fd) {
1316 if (consoles[x].mute) {
1317 consoles[x].mute = 0;
1319 ast_cli(fd, "Console is not muted anymore.\n");
1321 consoles[x].mute = 1;
1323 ast_cli(fd, "Console is muted.\n");
1328 ast_cli(fd, "Couldn't find remote console.\n");
1332 * \brief log the string to all attached console clients
1334 static void ast_network_puts_mutable(const char *string, int level)
1337 for (x = 0;x < AST_MAX_CONNECTS; x++) {
1338 if (consoles[x].mute)
1340 if (consoles[x].fd > -1) {
1341 if (!consoles[x].levels[level])
1342 fdprint(consoles[x].p[1], string);
1348 * \brief log the string to the console, and all attached
1351 void ast_console_puts_mutable(const char *string, int level)
1353 fputs(string, stdout);
1355 ast_network_puts_mutable(string, level);
1359 * \brief write the string to all attached console clients
1361 static void ast_network_puts(const char *string)
1364 for (x = 0; x < AST_MAX_CONNECTS; x++) {
1365 if (consoles[x].fd > -1)
1366 fdprint(consoles[x].p[1], string);
1371 * \brief write the string to the console, and all attached
1374 void ast_console_puts(const char *string)
1376 fputs(string, stdout);
1378 ast_network_puts(string);
1381 static void network_verboser(const char *s)
1383 ast_network_puts_mutable(s, __LOG_VERBOSE);
1386 static pthread_t lthread;
1389 * \brief read() function supporting the reception of user credentials.
1391 * \param fd Socket file descriptor.
1392 * \param buffer Receive buffer.
1393 * \param size 'buffer' size.
1394 * \param con Console structure to set received credentials
1395 * \retval -1 on error
1396 * \retval the number of bytes received on success.
1398 static int read_credentials(int fd, char *buffer, size_t size, struct console *con)
1400 #if defined(SO_PEERCRED)
1401 #ifdef HAVE_STRUCT_SOCKPEERCRED_UID
1402 #define HAVE_STRUCT_UCRED_UID
1403 struct sockpeercred cred;
1407 socklen_t len = sizeof(cred);
1409 #if defined(HAVE_GETPEEREID)
1417 result = read(fd, buffer, size);
1422 #if defined(SO_PEERCRED) && (defined(HAVE_STRUCT_UCRED_UID) || defined(HAVE_STRUCT_UCRED_CR_UID))
1423 if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &cred, &len)) {
1426 #if defined(HAVE_STRUCT_UCRED_UID)
1429 #else /* defined(HAVE_STRUCT_UCRED_CR_UID) */
1432 #endif /* defined(HAVE_STRUCT_UCRED_UID) */
1434 #elif defined(HAVE_GETPEEREID)
1435 if (getpeereid(fd, &uid, &gid)) {
1447 static void *netconsole(void *vconsole)
1449 struct console *con = vconsole;
1450 char hostname[MAXHOSTNAMELEN] = "";
1453 const char * const end_buf = inbuf + sizeof(inbuf);
1454 char *start_read = inbuf;
1456 struct pollfd fds[2];
1458 if (gethostname(hostname, sizeof(hostname)-1))
1459 ast_copy_string(hostname, "<Unknown>", sizeof(hostname));
1460 snprintf(outbuf, sizeof(outbuf), "%s/%ld/%s\n", hostname, (long)ast_mainpid, ast_get_version());
1461 fdprint(con->fd, outbuf);
1463 fds[0].fd = con->fd;
1464 fds[0].events = POLLIN;
1466 fds[1].fd = con->p[0];
1467 fds[1].events = POLLIN;
1470 res = ast_poll(fds, 2, -1);
1473 ast_log(LOG_WARNING, "poll returned < 0: %s\n", strerror(errno));
1476 if (fds[0].revents) {
1477 int cmds_read, bytes_read;
1478 if ((bytes_read = read_credentials(con->fd, start_read, end_buf - start_read, con)) < 1) {
1481 /* XXX This will only work if it is the first command, and I'm not sure fixing it is worth the effort. */
1482 if (strncmp(inbuf, "cli quit after ", 15) == 0) {
1483 ast_cli_command_multiple_full(con->uid, con->gid, con->fd, bytes_read - 15, inbuf + 15);
1486 /* ast_cli_command_multiple_full will only process individual commands terminated by a
1487 * NULL and not trailing partial commands. */
1488 if (!(cmds_read = ast_cli_command_multiple_full(con->uid, con->gid, con->fd, bytes_read + start_read - inbuf, inbuf))) {
1489 /* No commands were read. We either have a short read on the first command
1490 * with space left, or a command that is too long */
1491 if (start_read + bytes_read < end_buf) {
1492 start_read += bytes_read;
1494 ast_log(LOG_ERROR, "Command too long! Skipping\n");
1499 if (start_read[bytes_read - 1] == '\0') {
1500 /* The read ended on a command boundary, start reading again at the head of inbuf */
1504 /* If we get this far, we have left over characters that have not been processed.
1505 * Advance to the character after the last command read by ast_cli_command_multiple_full.
1506 * We are guaranteed to have at least cmds_read NULLs */
1507 while (cmds_read-- && (start_read = strchr(start_read, '\0'))) {
1510 memmove(inbuf, start_read, end_buf - start_read);
1511 start_read = end_buf - start_read + inbuf;
1513 if (fds[1].revents) {
1514 res = read_credentials(con->p[0], outbuf, sizeof(outbuf), con);
1516 ast_log(LOG_ERROR, "read returned %d\n", res);
1519 res = write(con->fd, outbuf, res);
1524 if (!ast_opt_hide_connect) {
1525 ast_verb(3, "Remote UNIX connection disconnected\n");
1535 static void *listener(void *unused)
1537 struct sockaddr_un sunaddr;
1542 struct pollfd fds[1];
1546 fds[0].fd = ast_socket;
1547 fds[0].events = POLLIN;
1548 s = ast_poll(fds, 1, -1);
1549 pthread_testcancel();
1552 ast_log(LOG_WARNING, "poll returned error: %s\n", strerror(errno));
1555 len = sizeof(sunaddr);
1556 s = accept(ast_socket, (struct sockaddr *)&sunaddr, &len);
1559 ast_log(LOG_WARNING, "Accept returned %d: %s\n", s, strerror(errno));
1561 #if !defined(SO_PASSCRED)
1565 /* turn on socket credentials passing. */
1566 if (setsockopt(s, SOL_SOCKET, SO_PASSCRED, &sckopt, sizeof(sckopt)) < 0) {
1567 ast_log(LOG_WARNING, "Unable to turn on socket credentials passing\n");
1570 for (x = 0; x < AST_MAX_CONNECTS; x++) {
1571 if (consoles[x].fd >= 0) {
1574 if (socketpair(AF_LOCAL, SOCK_STREAM, 0, consoles[x].p)) {
1575 ast_log(LOG_ERROR, "Unable to create pipe: %s\n", strerror(errno));
1576 consoles[x].fd = -1;
1577 fdprint(s, "Server failed to create pipe\n");
1581 flags = fcntl(consoles[x].p[1], F_GETFL);
1582 fcntl(consoles[x].p[1], F_SETFL, flags | O_NONBLOCK);
1584 consoles[x].mute = 1; /* Default is muted, we will un-mute if necessary */
1585 /* Default uid and gid to -2, so then in cli.c/cli_has_permissions() we will be able
1586 to know if the user didn't send the credentials. */
1587 consoles[x].uid = -2;
1588 consoles[x].gid = -2;
1589 if (ast_pthread_create_detached_background(&consoles[x].t, NULL, netconsole, &consoles[x])) {
1590 ast_log(LOG_ERROR, "Unable to spawn thread to handle connection: %s\n", strerror(errno));
1591 close(consoles[x].p[0]);
1592 close(consoles[x].p[1]);
1593 consoles[x].fd = -1;
1594 fdprint(s, "Server failed to spawn thread\n");
1599 if (x >= AST_MAX_CONNECTS) {
1600 fdprint(s, "No more connections allowed\n");
1601 ast_log(LOG_WARNING, "No more connections allowed\n");
1603 } else if ((consoles[x].fd > -1) && (!ast_opt_hide_connect)) {
1604 ast_verb(3, "Remote UNIX connection\n");
1612 static int ast_makesocket(void)
1614 struct sockaddr_un sunaddr;
1620 for (x = 0; x < AST_MAX_CONNECTS; x++)
1621 consoles[x].fd = -1;
1622 unlink(ast_config_AST_SOCKET);
1623 ast_socket = socket(PF_LOCAL, SOCK_STREAM, 0);
1624 if (ast_socket < 0) {
1625 ast_log(LOG_WARNING, "Unable to create control socket: %s\n", strerror(errno));
1628 memset(&sunaddr, 0, sizeof(sunaddr));
1629 sunaddr.sun_family = AF_LOCAL;
1630 ast_copy_string(sunaddr.sun_path, ast_config_AST_SOCKET, sizeof(sunaddr.sun_path));
1631 res = bind(ast_socket, (struct sockaddr *)&sunaddr, sizeof(sunaddr));
1633 ast_log(LOG_WARNING, "Unable to bind socket to %s: %s\n", ast_config_AST_SOCKET, strerror(errno));
1638 res = listen(ast_socket, 2);
1640 ast_log(LOG_WARNING, "Unable to listen on socket %s: %s\n", ast_config_AST_SOCKET, strerror(errno));
1645 if (ast_register_verbose(network_verboser)) {
1646 ast_log(LOG_WARNING, "Unable to register network verboser?\n");
1649 if (ast_pthread_create_background(<hread, NULL, listener, NULL)) {
1650 ast_log(LOG_WARNING, "Unable to create listener thread.\n");
1655 if (!ast_strlen_zero(ast_config_AST_CTL_OWNER)) {
1657 if ((pw = getpwnam(ast_config_AST_CTL_OWNER)) == NULL)
1658 ast_log(LOG_WARNING, "Unable to find uid of user %s\n", ast_config_AST_CTL_OWNER);
1663 if (!ast_strlen_zero(ast_config_AST_CTL_GROUP)) {
1665 if ((grp = getgrnam(ast_config_AST_CTL_GROUP)) == NULL)
1666 ast_log(LOG_WARNING, "Unable to find gid of group %s\n", ast_config_AST_CTL_GROUP);
1671 if (chown(ast_config_AST_SOCKET, uid, gid) < 0)
1672 ast_log(LOG_WARNING, "Unable to change ownership of %s: %s\n", ast_config_AST_SOCKET, strerror(errno));
1674 if (!ast_strlen_zero(ast_config_AST_CTL_PERMISSIONS)) {
1677 sscanf(ast_config_AST_CTL_PERMISSIONS, "%30o", &p1);
1679 if ((chmod(ast_config_AST_SOCKET, p)) < 0)
1680 ast_log(LOG_WARNING, "Unable to change file permissions of %s: %s\n", ast_config_AST_SOCKET, strerror(errno));
1686 static int ast_tryconnect(void)
1688 struct sockaddr_un sunaddr;
1690 ast_consock = socket(PF_LOCAL, SOCK_STREAM, 0);
1691 if (ast_consock < 0) {
1692 fprintf(stderr, "Unable to create socket: %s\n", strerror(errno));
1695 memset(&sunaddr, 0, sizeof(sunaddr));
1696 sunaddr.sun_family = AF_LOCAL;
1697 ast_copy_string(sunaddr.sun_path, ast_config_AST_SOCKET, sizeof(sunaddr.sun_path));
1698 res = connect(ast_consock, (struct sockaddr *)&sunaddr, sizeof(sunaddr));
1707 /*! \brief Urgent handler
1709 * Called by soft_hangup to interrupt the poll, read, or other
1710 * system call. We don't actually need to do anything though.
1711 * Remember: Cannot EVER ast_log from within a signal handler
1713 static void _urg_handler(int num)
1718 static struct sigaction urg_handler = {
1719 .sa_handler = _urg_handler,
1720 .sa_flags = SA_RESTART,
1723 static void _hup_handler(int num)
1725 int a = 0, save_errno = errno;
1726 printf("Received HUP signal -- Reloading configs\n");
1728 execvp(_argv[0], _argv);
1729 sig_flags.need_reload = 1;
1730 if (sig_alert_pipe[1] != -1) {
1731 if (write(sig_alert_pipe[1], &a, sizeof(a)) < 0) {
1732 fprintf(stderr, "hup_handler: write() failed: %s\n", strerror(errno));
1738 static struct sigaction hup_handler = {
1739 .sa_handler = _hup_handler,
1740 .sa_flags = SA_RESTART,
1743 static void _child_handler(int sig)
1745 /* Must not ever ast_log or ast_verbose within signal handler */
1746 int n, status, save_errno = errno;
1749 * Reap all dead children -- not just one
1751 for (n = 0; wait4(-1, &status, WNOHANG, NULL) > 0; n++)
1753 if (n == 0 && option_debug)
1754 printf("Huh? Child handler, but nobody there?\n");
1758 static struct sigaction child_handler = {
1759 .sa_handler = _child_handler,
1760 .sa_flags = SA_RESTART,
1763 /*! \brief Set maximum open files */
1764 static void set_ulimit(int value)
1766 struct rlimit l = {0, 0};
1769 ast_log(LOG_WARNING, "Unable to change max files open to invalid value %i\n",value);
1776 if (setrlimit(RLIMIT_NOFILE, &l)) {
1777 ast_log(LOG_WARNING, "Unable to disable core size resource limit: %s\n",strerror(errno));
1781 ast_log(LOG_NOTICE, "Setting max files open to %d\n",value);
1786 /*! \brief Set an X-term or screen title */
1787 static void set_title(char *text)
1789 if (getenv("TERM") && strstr(getenv("TERM"), "xterm"))
1790 fprintf(stdout, "\033]2;%s\007", text);
1793 static void set_icon(char *text)
1795 if (getenv("TERM") && strstr(getenv("TERM"), "xterm"))
1796 fprintf(stdout, "\033]1;%s\007", text);
1799 /*! \brief We set ourselves to a high priority, that we might pre-empt
1800 * everything else. If your PBX has heavy activity on it, this is a
1803 int ast_set_priority(int pri)
1805 struct sched_param sched;
1806 memset(&sched, 0, sizeof(sched));
1809 sched.sched_priority = 10;
1810 if (sched_setscheduler(0, SCHED_RR, &sched)) {
1811 ast_log(LOG_WARNING, "Unable to set high priority\n");
1814 ast_verb(1, "Set to realtime thread\n");
1816 sched.sched_priority = 0;
1817 /* According to the manpage, these parameters can never fail. */
1818 sched_setscheduler(0, SCHED_OTHER, &sched);
1822 if (setpriority(PRIO_PROCESS, 0, -10) == -1) {
1823 ast_log(LOG_WARNING, "Unable to set high priority\n");
1826 ast_verb(1, "Set to high priority\n");
1828 /* According to the manpage, these parameters can never fail. */
1829 setpriority(PRIO_PROCESS, 0, 0);
1835 static int can_safely_quit(shutdown_nice_t niceness, int restart);
1836 static void really_quit(int num, shutdown_nice_t niceness, int restart);
1838 static void quit_handler(int num, shutdown_nice_t niceness, int restart)
1840 if (can_safely_quit(niceness, restart)) {
1841 really_quit(num, niceness, restart);
1842 /* No one gets here. */
1844 /* It wasn't our time. */
1847 static int can_safely_quit(shutdown_nice_t niceness, int restart)
1849 /* Check if someone else isn't already doing this. */
1850 ast_mutex_lock(&safe_system_lock);
1851 if (shuttingdown != NOT_SHUTTING_DOWN && niceness >= shuttingdown) {
1852 /* Already in progress and other request was less nice. */
1853 ast_mutex_unlock(&safe_system_lock);
1854 ast_verbose("Ignoring asterisk %s request, already in progress.\n", restart ? "restart" : "shutdown");
1857 shuttingdown = niceness;
1858 ast_mutex_unlock(&safe_system_lock);
1860 /* Try to get as many CDRs as possible submitted to the backend engines
1861 * (if in batch mode). really_quit happens to call it again when running
1862 * the atexit handlers, otherwise this would be a bit early. */
1863 ast_cdr_engine_term();
1865 /* Shutdown the message queue for the technology agnostic message channel.
1866 * This has to occur before we pause shutdown pending ast_undestroyed_channels. */
1869 if (niceness == SHUTDOWN_NORMAL) {
1871 /* Begin shutdown routine, hanging up active channels */
1872 ast_begin_shutdown(1);
1873 if (option_verbose && ast_opt_console) {
1874 ast_verbose("Beginning asterisk %s....\n", restart ? "restart" : "shutdown");
1879 /* Wait up to 15 seconds for all channels to go away */
1880 if ((e - s) > 15 || !ast_undestroyed_channels() || shuttingdown != niceness) {
1883 /* Sleep 1/10 of a second */
1886 } else if (niceness >= SHUTDOWN_NICE) {
1887 if (niceness != SHUTDOWN_REALLY_NICE) {
1888 ast_begin_shutdown(0);
1890 if (option_verbose && ast_opt_console) {
1891 ast_verb(0, "Waiting for inactivity to perform %s...\n", restart ? "restart" : "halt");
1894 if (!ast_undestroyed_channels() || shuttingdown != niceness) {
1901 /* Re-acquire lock and check if someone changed the niceness, in which
1902 * case someone else has taken over the shutdown.
1904 ast_mutex_lock(&safe_system_lock);
1905 if (shuttingdown != niceness) {
1906 if (shuttingdown == NOT_SHUTTING_DOWN && option_verbose && ast_opt_console) {
1907 ast_verb(0, "Asterisk %s cancelled.\n", restart ? "restart" : "shutdown");
1909 ast_mutex_unlock(&safe_system_lock);
1912 shuttingdown = SHUTTING_DOWN;
1913 ast_mutex_unlock(&safe_system_lock);
1918 /*! Called when exiting is certain. */
1919 static void really_quit(int num, shutdown_nice_t niceness, int restart)
1921 int active_channels;
1922 RAII_VAR(struct ast_json *, json_object, NULL, ast_json_unref);
1923 int run_cleanups = niceness >= SHUTDOWN_NICE;
1926 ast_module_shutdown();
1929 if (ast_opt_console || (ast_opt_remote && !ast_opt_exec)) {
1930 char filename[80] = "";
1931 if (getenv("HOME")) {
1932 snprintf(filename, sizeof(filename), "%s/.asterisk_history", getenv("HOME"));
1934 if (!ast_strlen_zero(filename)) {
1935 ast_el_write_history(filename);
1937 if (consolethread == AST_PTHREADT_NULL || consolethread == pthread_self()) {
1938 /* Only end if we are the consolethread, otherwise there's a race with that thread. */
1942 if (el_hist != NULL) {
1943 history_end(el_hist);
1945 } else if (mon_sig_flags == pthread_self()) {
1946 if (consolethread != AST_PTHREADT_NULL) {
1947 pthread_kill(consolethread, SIGURG);
1951 active_channels = ast_active_channels();
1952 /* Don't publish messages if we're a remote console - we won't have all of the Stasis
1953 * topics or message types
1955 if (!ast_opt_remote) {
1956 json_object = ast_json_pack("{s: s, s: s}",
1957 "Shutdown", active_channels ? "Uncleanly" : "Cleanly",
1958 "Restart", restart ? "True" : "False");
1959 ast_manager_publish_event("Shutdown", EVENT_FLAG_SYSTEM, json_object);
1961 ast_verb(0, "Asterisk %s ending (%d).\n",
1962 active_channels ? "uncleanly" : "cleanly", num);
1964 ast_verb(0, "Executing last minute cleanups\n");
1965 ast_run_atexits(run_cleanups);
1967 ast_debug(1, "Asterisk ending (%d).\n", num);
1968 if (ast_socket > -1) {
1969 pthread_cancel(lthread);
1972 unlink(ast_config_AST_SOCKET);
1974 if (ast_consock > -1)
1976 if (!ast_opt_remote)
1977 unlink(ast_config_AST_PID);
1978 printf("%s", term_quit());
1981 ast_verb(0, "Preparing for Asterisk restart...\n");
1982 /* Mark all FD's for closing on exec */
1983 for (i = 3; i < 32768; i++) {
1984 fcntl(i, F_SETFD, FD_CLOEXEC);
1986 ast_verb(0, "Asterisk is now restarting...\n");
1993 /* If there is a consolethread running send it a SIGHUP
1994 so it can execvp, otherwise we can do it ourselves */
1995 if ((consolethread != AST_PTHREADT_NULL) && (consolethread != pthread_self())) {
1996 pthread_kill(consolethread, SIGHUP);
1997 /* Give the signal handler some time to complete */
2000 execvp(_argv[0], _argv);
2011 static void __quit_handler(int num)
2014 sig_flags.need_quit = 1;
2015 if (sig_alert_pipe[1] != -1) {
2016 if (write(sig_alert_pipe[1], &a, sizeof(a)) < 0) {
2017 fprintf(stderr, "quit_handler: write() failed: %s\n", strerror(errno));
2020 /* There is no need to restore the signal handler here, since the app
2021 * is going to exit */
2024 static void __remote_quit_handler(int num)
2026 sig_flags.need_quit = 1;
2029 static const char *fix_header(char *outbuf, int maxout, const char *s, char *cmp)
2033 if (!strncmp(s, cmp, strlen(cmp))) {
2034 c = s + strlen(cmp);
2035 term_color(outbuf, cmp, COLOR_GRAY, 0, maxout);
2041 /* These gymnastics are due to platforms which designate char as unsigned by
2042 * default. Level is the negative character -- offset by 1, because \0 is the
2044 #define VERBOSE_MAGIC2LEVEL(x) (((char) -*(signed char *) (x)) - 1)
2045 #define VERBOSE_HASMAGIC(x) (*(signed char *) (x) < 0)
2047 static void console_verboser(const char *s)
2050 const char *c = NULL;
2053 if (VERBOSE_HASMAGIC(s)) {
2054 level = VERBOSE_MAGIC2LEVEL(s);
2056 if (level > option_verbose) {
2061 if ((c = fix_header(tmp, sizeof(tmp), s, VERBOSE_PREFIX_4)) ||
2062 (c = fix_header(tmp, sizeof(tmp), s, VERBOSE_PREFIX_3)) ||
2063 (c = fix_header(tmp, sizeof(tmp), s, VERBOSE_PREFIX_2)) ||
2064 (c = fix_header(tmp, sizeof(tmp), s, VERBOSE_PREFIX_1))) {
2073 /* Wake up a poll()ing console */
2074 if (ast_opt_console && consolethread != AST_PTHREADT_NULL) {
2075 pthread_kill(consolethread, SIGURG);
2079 static int ast_all_zeros(char *s)
2089 static void consolehandler(char *s)
2091 printf("%s", term_end());
2094 /* Called when readline data is available */
2095 if (!ast_all_zeros(s))
2096 ast_el_add_history(s);
2097 /* The real handler for bang */
2100 ast_safe_system(s+1);
2102 ast_safe_system(getenv("SHELL") ? getenv("SHELL") : "/bin/sh");
2104 ast_cli_command(STDOUT_FILENO, s);
2107 static int remoteconsolehandler(char *s)
2111 /* Called when readline data is available */
2112 if (!ast_all_zeros(s))
2113 ast_el_add_history(s);
2114 /* The real handler for bang */
2117 ast_safe_system(s+1);
2119 ast_safe_system(getenv("SHELL") ? getenv("SHELL") : "/bin/sh");
2121 } else if (strncasecmp(s, "core set verbose ", 17) == 0) {
2122 int old_verbose = option_verbose;
2123 if (strncasecmp(s + 17, "atleast ", 8) == 0) {
2125 if (sscanf(s + 25, "%d", &tmp) != 1) {
2126 fprintf(stderr, "Usage: core set verbose [atleast] <level>\n");
2128 if (tmp > option_verbose) {
2129 option_verbose = tmp;
2131 if (old_verbose != option_verbose) {
2132 fprintf(stdout, "Set remote console verbosity from %d to %d\n", old_verbose, option_verbose);
2134 fprintf(stdout, "Verbosity level unchanged.\n");
2138 if (sscanf(s + 17, "%d", &option_verbose) != 1) {
2139 fprintf(stderr, "Usage: core set verbose [atleast] <level>\n");
2141 if (old_verbose != option_verbose) {
2142 fprintf(stdout, "Set remote console verbosity to %d\n", option_verbose);
2144 fprintf(stdout, "Verbosity level unchanged.\n");
2149 } else if ((strncasecmp(s, "quit", 4) == 0 || strncasecmp(s, "exit", 4) == 0) &&
2150 (s[4] == '\0' || isspace(s[4]))) {
2151 quit_handler(0, SHUTDOWN_FAST, 0);
2158 static char *handle_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2162 e->command = "core show version";
2164 "Usage: core show version\n"
2165 " Shows Asterisk version information.\n";
2172 return CLI_SHOWUSAGE;
2173 ast_cli(a->fd, "Asterisk %s built by %s @ %s on a %s running %s on %s\n",
2174 ast_get_version(), ast_build_user, ast_build_hostname,
2175 ast_build_machine, ast_build_os, ast_build_date);
2180 static int handle_quit(int fd, int argc, char *argv[])
2183 return RESULT_SHOWUSAGE;
2184 quit_handler(0, SHUTDOWN_NORMAL, 0);
2185 return RESULT_SUCCESS;
2189 static char *handle_stop_now(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2193 e->command = "core stop now";
2195 "Usage: core stop now\n"
2196 " Shuts down a running Asterisk immediately, hanging up all active calls .\n";
2202 if (a->argc != e->args)
2203 return CLI_SHOWUSAGE;
2204 quit_handler(0, SHUTDOWN_NORMAL, 0 /* not restart */);
2208 static char *handle_stop_gracefully(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2212 e->command = "core stop gracefully";
2214 "Usage: core stop gracefully\n"
2215 " Causes Asterisk to not accept new calls, and exit when all\n"
2216 " active calls have terminated normally.\n";
2222 if (a->argc != e->args)
2223 return CLI_SHOWUSAGE;
2224 quit_handler(0, SHUTDOWN_NICE, 0 /* no restart */);
2228 static char *handle_stop_when_convenient(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2232 e->command = "core stop when convenient";
2234 "Usage: core stop when convenient\n"
2235 " Causes Asterisk to perform a shutdown when all active calls have ended.\n";
2241 if (a->argc != e->args)
2242 return CLI_SHOWUSAGE;
2243 ast_cli(a->fd, "Waiting for inactivity to perform halt\n");
2244 quit_handler(0, SHUTDOWN_REALLY_NICE, 0 /* don't restart */);
2248 static char *handle_restart_now(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2252 e->command = "core restart now";
2254 "Usage: core restart now\n"
2255 " Causes Asterisk to hangup all calls and exec() itself performing a cold\n"
2262 if (a->argc != e->args)
2263 return CLI_SHOWUSAGE;
2264 quit_handler(0, SHUTDOWN_NORMAL, 1 /* restart */);
2268 static char *handle_restart_gracefully(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2272 e->command = "core restart gracefully";
2274 "Usage: core restart gracefully\n"
2275 " Causes Asterisk to stop accepting new calls and exec() itself performing a cold\n"
2276 " restart when all active calls have ended.\n";
2282 if (a->argc != e->args)
2283 return CLI_SHOWUSAGE;
2284 quit_handler(0, SHUTDOWN_NICE, 1 /* restart */);
2288 static char *handle_restart_when_convenient(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2292 e->command = "core restart when convenient";
2294 "Usage: core restart when convenient\n"
2295 " Causes Asterisk to perform a cold restart when all active calls have ended.\n";
2301 if (a->argc != e->args)
2302 return CLI_SHOWUSAGE;
2303 ast_cli(a->fd, "Waiting for inactivity to perform restart\n");
2304 quit_handler(0, SHUTDOWN_REALLY_NICE, 1 /* restart */);
2308 static char *handle_abort_shutdown(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2310 int aborting_shutdown = 0;
2314 e->command = "core abort shutdown";
2316 "Usage: core abort shutdown\n"
2317 " Causes Asterisk to abort an executing shutdown or restart, and resume normal\n"
2318 " call operations.\n";
2324 if (a->argc != e->args)
2325 return CLI_SHOWUSAGE;
2327 ast_mutex_lock(&safe_system_lock);
2328 if (shuttingdown >= SHUTDOWN_FAST) {
2329 aborting_shutdown = 1;
2330 shuttingdown = NOT_SHUTTING_DOWN;
2332 ast_mutex_unlock(&safe_system_lock);
2334 if (aborting_shutdown) {
2335 ast_cancel_shutdown();
2340 static char *handle_bang(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2346 "Usage: !<command>\n"
2347 " Executes a given shell command\n";
2355 static const char warranty_lines[] = {
2359 "BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY\n"
2360 "FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN\n"
2361 "OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES\n"
2362 "PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED\n"
2363 "OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\n"
2364 "MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS\n"
2365 "TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE\n"
2366 "PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,\n"
2367 "REPAIR OR CORRECTION.\n"
2369 "IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\n"
2370 "WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR\n"
2371 "REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,\n"
2372 "INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING\n"
2373 "OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED\n"
2374 "TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY\n"
2375 "YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER\n"
2376 "PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE\n"
2377 "POSSIBILITY OF SUCH DAMAGES.\n"
2380 static char *show_warranty(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2384 e->command = "core show warranty";
2386 "Usage: core show warranty\n"
2387 " Shows the warranty (if any) for this copy of Asterisk.\n";
2393 ast_cli(a->fd, "%s", warranty_lines);
2398 static const char license_lines[] = {
2400 "This program is free software; you can redistribute it and/or modify\n"
2401 "it under the terms of the GNU General Public License version 2 as\n"
2402 "published by the Free Software Foundation.\n"
2404 "This program also contains components licensed under other licenses.\n"
2407 "This program is distributed in the hope that it will be useful,\n"
2408 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
2409 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
2410 "GNU General Public License for more details.\n"
2412 "You should have received a copy of the GNU General Public License\n"
2413 "along with this program; if not, write to the Free Software\n"
2414 "Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\n"
2417 static char *show_license(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2421 e->command = "core show license";
2423 "Usage: core show license\n"
2424 " Shows the license(s) for this copy of Asterisk.\n";
2430 ast_cli(a->fd, "%s", license_lines);
2435 #define ASTERISK_PROMPT "*CLI> "
2437 #define ASTERISK_PROMPT2 "%s*CLI> "
2440 * \brief Shutdown Asterisk CLI commands.
2442 * \note These CLI commands cannot be unregistered at shutdown
2443 * because one of them is likely the reason for the shutdown.
2444 * The CLI generates a warning if a command is in-use when it is
2447 static struct ast_cli_entry cli_asterisk_shutdown[] = {
2448 AST_CLI_DEFINE(handle_stop_now, "Shut down Asterisk immediately"),
2449 AST_CLI_DEFINE(handle_stop_gracefully, "Gracefully shut down Asterisk"),
2450 AST_CLI_DEFINE(handle_stop_when_convenient, "Shut down Asterisk at empty call volume"),
2451 AST_CLI_DEFINE(handle_restart_now, "Restart Asterisk immediately"),
2452 AST_CLI_DEFINE(handle_restart_gracefully, "Restart Asterisk gracefully"),
2453 AST_CLI_DEFINE(handle_restart_when_convenient, "Restart Asterisk at empty call volume"),
2456 static struct ast_cli_entry cli_asterisk[] = {
2457 AST_CLI_DEFINE(handle_abort_shutdown, "Cancel a running shutdown"),
2458 AST_CLI_DEFINE(show_warranty, "Show the warranty (if any) for this copy of Asterisk"),
2459 AST_CLI_DEFINE(show_license, "Show the license(s) for this copy of Asterisk"),
2460 AST_CLI_DEFINE(handle_version, "Display version info"),
2461 AST_CLI_DEFINE(handle_bang, "Execute a shell command"),
2462 #if !defined(LOW_MEMORY)
2463 AST_CLI_DEFINE(handle_show_version_files, "List versions of files used to build Asterisk"),
2464 AST_CLI_DEFINE(handle_show_threads, "Show running threads"),
2465 #if defined(HAVE_SYSINFO) || defined(HAVE_SYSCTL)
2466 AST_CLI_DEFINE(handle_show_sysinfo, "Show System Information"),
2468 AST_CLI_DEFINE(handle_show_profile, "Display profiling info"),
2469 AST_CLI_DEFINE(handle_show_settings, "Show some core settings"),
2470 AST_CLI_DEFINE(handle_clear_profile, "Clear profiling info"),
2471 #endif /* ! LOW_MEMORY */
2474 struct el_read_char_state_struct {
2475 unsigned int line_full:1;
2476 unsigned int prev_line_full:1;
2477 char prev_line_verbosity;
2480 static int el_read_char_state_init(void *ptr)
2482 struct el_read_char_state_struct *state = ptr;
2483 state->line_full = 1;
2484 state->prev_line_full = 1;
2485 state->prev_line_verbosity = 0;
2489 AST_THREADSTORAGE_CUSTOM(el_read_char_state, el_read_char_state_init, ast_free_ptr);
2491 static int ast_el_read_char(EditLine *editline, char *cp)
2495 struct pollfd fds[2];
2498 #define EL_BUF_SIZE 512
2499 char buf[EL_BUF_SIZE];
2500 struct el_read_char_state_struct *state = ast_threadstorage_get(&el_read_char_state, sizeof(*state));
2504 fds[0].fd = ast_consock;
2505 fds[0].events = POLLIN;
2506 if (!ast_opt_exec) {
2507 fds[1].fd = STDIN_FILENO;
2508 fds[1].events = POLLIN;
2511 res = ast_poll(fds, max, -1);
2513 if (sig_flags.need_quit || sig_flags.need_quit_handler)
2517 fprintf(stderr, "poll failed: %s\n", strerror(errno));
2521 if (!ast_opt_exec && fds[1].revents) {
2522 num_read = read(STDIN_FILENO, cp, 1);
2529 if (fds[0].revents) {
2531 char *curline = buf, *nextline;
2532 res = read(ast_consock, buf, sizeof(buf) - 1);
2533 /* if the remote side disappears exit */
2535 fprintf(stderr, "\nDisconnected from Asterisk server\n");
2536 if (!ast_opt_reconnect) {
2537 quit_handler(0, SHUTDOWN_FAST, 0);
2540 int reconnects_per_second = 20;
2541 fprintf(stderr, "Attempting to reconnect for 30 seconds\n");
2542 for (tries = 0; tries < 30 * reconnects_per_second; tries++) {
2543 if (ast_tryconnect()) {
2544 fprintf(stderr, "Reconnect succeeded after %.3f seconds\n", 1.0 / reconnects_per_second * tries);
2545 printf("%s", term_quit());
2548 fdsend(ast_consock, "logger mute silent");
2550 printf("log and verbose output currently muted ('logger mute' to unmute)\n");
2553 usleep(1000000 / reconnects_per_second);
2555 if (tries >= 30 * reconnects_per_second) {
2556 fprintf(stderr, "Failed to reconnect for 30 seconds. Quitting.\n");
2557 quit_handler(0, SHUTDOWN_FAST, 0);
2565 /* Write over the CLI prompt */
2566 if (!ast_opt_exec && !lastpos) {
2567 if (write(STDOUT_FILENO, "\r
\e[0K", 5) < 0) {
2572 state->prev_line_full = state->line_full;
2573 if ((nextline = strchr(curline, '\n'))) {
2574 state->line_full = 1;
2577 state->line_full = 0;
2578 nextline = strchr(curline, '\0');
2581 if (state->prev_line_full && VERBOSE_HASMAGIC(curline)) {
2582 level = VERBOSE_MAGIC2LEVEL(curline);
2584 } else if (state->prev_line_full && !VERBOSE_HASMAGIC(curline)) {
2585 /* Non-verbose output */
2588 level = state->prev_line_verbosity;
2590 if ((!state->prev_line_full && state->prev_line_verbosity <= option_verbose) || (state->prev_line_full && level <= option_verbose)) {
2591 if (write(STDOUT_FILENO, curline, nextline - curline) < 0) {
2595 state->prev_line_verbosity = level;
2597 } while (!ast_strlen_zero(curline));
2599 if ((res < EL_BUF_SIZE - 1) && ((buf[res-1] == '\n') || (buf[res-2] == '\n'))) {
2611 static struct ast_str *prompt = NULL;
2613 static char *cli_prompt(EditLine *editline)
2618 static int cli_prompt_changes = 0;
2622 if (prompt == NULL) {
2623 prompt = ast_str_create(100);
2624 } else if (!cli_prompt_changes) {
2625 return ast_str_buffer(prompt);
2627 ast_str_reset(prompt);
2630 if ((pfmt = getenv("ASTERISK_PROMPT"))) {
2632 struct timeval ts = ast_tvnow();
2633 while (*t != '\0') {
2635 char hostname[MAXHOSTNAMELEN] = "";
2637 struct ast_tm tm = { 0, };
2638 int fgcolor = COLOR_WHITE, bgcolor = COLOR_BLACK;
2642 case 'C': /* color */
2644 if (sscanf(t, "%30d;%30d%n", &fgcolor, &bgcolor, &i) == 2) {
2645 ast_term_color_code(&prompt, fgcolor, bgcolor);
2647 } else if (sscanf(t, "%30d%n", &fgcolor, &i) == 1) {
2648 ast_term_color_code(&prompt, fgcolor, 0);
2652 /* If the color has been reset correctly, then there's no need to reset it later */
2653 color_used = ((fgcolor == COLOR_WHITE) && (bgcolor == COLOR_BLACK)) ? 0 : 1;
2655 case 'd': /* date */
2656 if (ast_localtime(&ts, &tm, NULL)) {
2657 ast_strftime(tmp, sizeof(tmp), "%Y-%m-%d", &tm);
2658 ast_str_append(&prompt, 0, "%s", tmp);
2659 cli_prompt_changes++;
2662 case 'g': /* group */
2663 if ((gr = getgrgid(getgid()))) {
2664 ast_str_append(&prompt, 0, "%s", gr->gr_name);
2667 case 'h': /* hostname */
2668 if (!gethostname(hostname, sizeof(hostname) - 1)) {
2669 ast_str_append(&prompt, 0, "%s", hostname);
2671 ast_str_append(&prompt, 0, "%s", "localhost");
2674 case 'H': /* short hostname */
2675 if (!gethostname(hostname, sizeof(hostname) - 1)) {
2677 if ((dotptr = strchr(hostname, '.'))) {
2680 ast_str_append(&prompt, 0, "%s", hostname);
2682 ast_str_append(&prompt, 0, "%s", "localhost");
2685 #ifdef HAVE_GETLOADAVG
2686 case 'l': /* load avg */
2688 if (sscanf(t, "%30d", &which) == 1 && which > 0 && which <= 3) {
2690 getloadavg(list, 3);
2691 ast_str_append(&prompt, 0, "%.2f", list[which - 1]);
2692 cli_prompt_changes++;
2696 case 's': /* Asterisk system name (from asterisk.conf) */
2697 ast_str_append(&prompt, 0, "%s", ast_config_AST_SYSTEM_NAME);
2699 case 't': /* time */
2700 if (ast_localtime(&ts, &tm, NULL)) {
2701 ast_strftime(tmp, sizeof(tmp), "%H:%M:%S", &tm);
2702 ast_str_append(&prompt, 0, "%s", tmp);
2703 cli_prompt_changes++;
2706 case 'u': /* username */
2707 if ((pw = getpwuid(getuid()))) {
2708 ast_str_append(&prompt, 0, "%s", pw->pw_name);
2711 case '#': /* process console or remote? */
2712 ast_str_append(&prompt, 0, "%c", ast_opt_remote ? '>' : '#');
2714 case '%': /* literal % */
2715 ast_str_append(&prompt, 0, "%c", '%');
2717 case '\0': /* % is last character - prevent bug */
2722 ast_str_append(&prompt, 0, "%c", *t);
2727 /* Force colors back to normal at end */
2728 ast_term_color_code(&prompt, 0, 0);
2730 } else if (remotehostname) {
2731 ast_str_set(&prompt, 0, ASTERISK_PROMPT2, remotehostname);
2733 ast_str_set(&prompt, 0, "%s", ASTERISK_PROMPT);
2736 return ast_str_buffer(prompt);
2739 static char **ast_el_strtoarr(char *buf)
2741 char **match_list = NULL, **match_list_tmp, *retstr;
2742 size_t match_list_len;
2746 while ( (retstr = strsep(&buf, " ")) != NULL) {
2748 if (!strcmp(retstr, AST_CLI_COMPLETE_EOF))
2750 if (matches + 1 >= match_list_len) {
2751 match_list_len <<= 1;
2752 if ((match_list_tmp = ast_realloc(match_list, match_list_len * sizeof(char *)))) {
2753 match_list = match_list_tmp;
2756 ast_free(match_list);
2757 return (char **) NULL;
2761 match_list[matches++] = ast_strdup(retstr);
2765 return (char **) NULL;
2767 if (matches >= match_list_len) {
2768 if ((match_list_tmp = ast_realloc(match_list, (match_list_len + 1) * sizeof(char *)))) {
2769 match_list = match_list_tmp;
2772 ast_free(match_list);
2773 return (char **) NULL;
2777 match_list[matches] = (char *) NULL;
2782 static int ast_el_sort_compare(const void *i1, const void *i2)
2786 s1 = ((char **)i1)[0];
2787 s2 = ((char **)i2)[0];
2789 return strcasecmp(s1, s2);
2792 static int ast_cli_display_match_list(char **matches, int len, int max)
2794 int i, idx, limit, count;
2795 int screenwidth = 0;
2796 int numoutput = 0, numoutputline = 0;
2798 screenwidth = ast_get_termcols(STDOUT_FILENO);
2800 /* find out how many entries can be put on one line, with two spaces between strings */
2801 limit = screenwidth / (max + 2);
2805 /* how many lines of output */
2806 count = len / limit;
2807 if (count * limit < len)
2812 qsort(&matches[0], (size_t)(len), sizeof(char *), ast_el_sort_compare);
2814 for (; count > 0; count--) {
2816 for (i = 0; i < limit && matches[idx]; i++, idx++) {
2818 /* Don't print dupes */
2819 if ( (matches[idx+1] != NULL && strcmp(matches[idx], matches[idx+1]) == 0 ) ) {
2821 ast_free(matches[idx]);
2822 matches[idx] = NULL;
2828 fprintf(stdout, "%-*s ", max, matches[idx]);
2829 ast_free(matches[idx]);
2830 matches[idx] = NULL;
2832 if (numoutputline > 0)
2833 fprintf(stdout, "\n");
2840 static char *cli_complete(EditLine *editline, int ch)
2846 int retval = CC_ERROR;
2847 char buf[2048], savechr;
2850 LineInfo *lf = (LineInfo *)el_line(editline);
2852 savechr = *(char *)lf->cursor;
2853 *(char *)lf->cursor = '\0';
2854 ptr = (char *)lf->cursor;
2856 while (ptr > lf->buffer) {
2857 if (isspace(*ptr)) {
2865 len = lf->cursor - ptr;
2867 if (ast_opt_remote) {
2868 snprintf(buf, sizeof(buf), "_COMMAND NUMMATCHES \"%s\" \"%s\"", lf->buffer, ptr);
2869 fdsend(ast_consock, buf);
2870 if ((res = read(ast_consock, buf, sizeof(buf) - 1)) < 0) {
2871 return (char*)(CC_ERROR);
2874 nummatches = atoi(buf);
2876 if (nummatches > 0) {
2878 int mlen = 0, maxmbuf = 2048;
2879 /* Start with a 2048 byte buffer */
2880 if (!(mbuf = ast_malloc(maxmbuf))) {
2881 *((char *) lf->cursor) = savechr;
2882 return (char *)(CC_ERROR);
2884 snprintf(buf, sizeof(buf), "_COMMAND MATCHESARRAY \"%s\" \"%s\"", lf->buffer, ptr);
2885 fdsend(ast_consock, buf);
2888 while (!strstr(mbuf, AST_CLI_COMPLETE_EOF) && res != -1) {
2889 if (mlen + 1024 > maxmbuf) {
2890 /* Every step increment buffer 1024 bytes */
2892 if (!(mbuf = ast_realloc(mbuf, maxmbuf))) {
2893 *((char *) lf->cursor) = savechr;
2894 return (char *)(CC_ERROR);
2897 /* Only read 1024 bytes at a time */
2898 res = read(ast_consock, mbuf + mlen, 1024);
2904 matches = ast_el_strtoarr(mbuf);
2907 matches = (char **) NULL;
2909 char **p, *oldbuf=NULL;
2911 matches = ast_cli_completion_matches((char *)lf->buffer,ptr);
2912 for (p = matches; p && *p; p++) {
2913 if (!oldbuf || strcmp(*p,oldbuf))
2921 int matches_num, maxlen, match_len;
2923 if (matches[0][0] != '\0') {
2924 el_deletestr(editline, (int) len);
2925 el_insertstr(editline, matches[0]);
2926 retval = CC_REFRESH;
2929 if (nummatches == 1) {
2930 /* Found an exact match */
2931 el_insertstr(editline, " ");
2932 retval = CC_REFRESH;
2934 /* Must be more than one match */
2935 for (i = 1, maxlen = 0; matches[i]; i++) {
2936 match_len = strlen(matches[i]);
2937 if (match_len > maxlen)
2940 matches_num = i - 1;
2941 if (matches_num >1) {
2942 fprintf(stdout, "\n");
2943 ast_cli_display_match_list(matches, nummatches, maxlen);
2944 retval = CC_REDISPLAY;
2946 el_insertstr(editline," ");
2947 retval = CC_REFRESH;
2950 for (i = 0; matches[i]; i++)
2951 ast_free(matches[i]);
2955 *((char *) lf->cursor) = savechr;
2957 return (char *)(long)retval;
2960 static int ast_el_initialize(void)
2963 char *editor, *editrc = getenv("EDITRC");
2965 if (!(editor = getenv("AST_EDITMODE"))) {
2966 if (!(editor = getenv("AST_EDITOR"))) {
2973 if (el_hist != NULL)
2974 history_end(el_hist);
2976 el = el_init("asterisk", stdin, stdout, stderr);
2977 el_set(el, EL_PROMPT, cli_prompt);
2979 el_set(el, EL_EDITMODE, 1);
2980 el_set(el, EL_EDITOR, editor);
2981 el_hist = history_init();
2982 if (!el || !el_hist)
2985 /* setup history with 100 entries */
2986 history(el_hist, &ev, H_SETSIZE, 100);
2988 el_set(el, EL_HIST, history, el_hist);
2990 el_set(el, EL_ADDFN, "ed-complete", "Complete argument", cli_complete);
2991 /* Bind <tab> to command completion */
2992 el_set(el, EL_BIND, "^I", "ed-complete", NULL);
2993 /* Bind ? to command completion */
2994 el_set(el, EL_BIND, "?", "ed-complete", NULL);
2995 /* Bind ^D to redisplay */
2996 el_set(el, EL_BIND, "^D", "ed-redisplay", NULL);
2997 /* Bind Delete to delete char left */
2998 el_set(el, EL_BIND, "\\e[3~", "ed-delete-next-char", NULL);
2999 /* Bind Home and End to move to line start and end */
3000 el_set(el, EL_BIND, "\\e[1~", "ed-move-to-beg", NULL);
3001 el_set(el, EL_BIND, "\\e[4~", "ed-move-to-end", NULL);
3002 /* Bind C-left and C-right to move by word (not all terminals) */
3003 el_set(el, EL_BIND, "\\eOC", "vi-next-word", NULL);
3004 el_set(el, EL_BIND, "\\eOD", "vi-prev-word", NULL);
3007 el_source(el, editrc);
3013 #define MAX_HISTORY_COMMAND_LENGTH 256
3015 static int ast_el_add_history(char *buf)
3019 if (el_hist == NULL || el == NULL)
3020 ast_el_initialize();
3021 if (strlen(buf) > (MAX_HISTORY_COMMAND_LENGTH - 1))
3023 return (history(el_hist, &ev, H_ENTER, ast_strip(ast_strdupa(buf))));
3026 static int ast_el_write_history(char *filename)
3030 if (el_hist == NULL || el == NULL)
3031 ast_el_initialize();
3033 return (history(el_hist, &ev, H_SAVE, filename));
3036 static int ast_el_read_history(char *filename)
3040 if (el_hist == NULL || el == NULL) {
3041 ast_el_initialize();
3044 return history(el_hist, &ev, H_LOAD, filename);
3047 static void ast_remotecontrol(char *data)
3051 char filename[80] = "";
3056 char *stringp = NULL;
3061 memset(&sig_flags, 0, sizeof(sig_flags));
3062 signal(SIGINT, __remote_quit_handler);
3063 signal(SIGTERM, __remote_quit_handler);
3064 signal(SIGHUP, __remote_quit_handler);
3066 if (read(ast_consock, buf, sizeof(buf)) < 0) {
3067 ast_log(LOG_ERROR, "read() failed: %s\n", strerror(errno));
3071 char prefix[] = "cli quit after ";
3072 char *tmp = ast_alloca(strlen(data) + strlen(prefix) + 1);
3073 sprintf(tmp, "%s%s", prefix, data);
3074 if (write(ast_consock, tmp, strlen(tmp) + 1) < 0) {
3075 ast_log(LOG_ERROR, "write() failed: %s\n", strerror(errno));
3076 if (sig_flags.need_quit || sig_flags.need_quit_handler) {
3082 hostname = strsep(&stringp, "/");
3083 cpid = strsep(&stringp, "/");
3084 version = strsep(&stringp, "\n");
3086 version = "<Version Unknown>";
3088 strsep(&stringp, ".");
3094 if (!ast_opt_mute) {
3095 fdsend(ast_consock, "logger mute silent");
3097 printf("log and verbose output currently muted ('logger mute' to unmute)\n");
3101 if (ast_opt_exec && data) { /* hack to print output then exit if asterisk -rx is used */
3102 int linefull = 1, prev_linefull = 1, prev_line_verbose = 0;
3104 fds.fd = ast_consock;
3105 fds.events = POLLIN;
3108 while (ast_poll(&fds, 1, 60000) > 0) {
3109 char buffer[512] = "", *curline = buffer, *nextline;
3110 int not_written = 1;
3112 if (sig_flags.need_quit || sig_flags.need_quit_handler) {
3116 if (read(ast_consock, buffer, sizeof(buffer) - 1) <= 0) {
3121 prev_linefull = linefull;
3122 if ((nextline = strchr(curline, '\n'))) {
3127 nextline = strchr(curline, '\0');
3130 /* Skip verbose lines */
3131 /* Prev line full? | Line is verbose | Last line verbose? | Print
3132 * TRUE | TRUE* | TRUE | FALSE
3133 * TRUE | TRUE* | FALSE | FALSE
3134 * TRUE | FALSE* | TRUE | TRUE
3135 * TRUE | FALSE* | FALSE | TRUE
3136 * FALSE | TRUE | TRUE* | FALSE
3137 * FALSE | TRUE | FALSE* | TRUE
3138 * FALSE | FALSE | TRUE* | FALSE
3139 * FALSE | FALSE | FALSE* | TRUE
3141 if ((!prev_linefull && !prev_line_verbose) || (prev_linefull && *curline > 0)) {
3142 prev_line_verbose = 0;
3144 if (write(STDOUT_FILENO, curline, nextline - curline) < 0) {
3145 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
3148 prev_line_verbose = 1;
3151 } while (!ast_strlen_zero(curline));
3153 /* No non-verbose output in 60 seconds. */
3161 ast_verbose("Connected to Asterisk %s currently running on %s (pid = %d)\n", version, hostname, pid);
3162 remotehostname = hostname;
3164 snprintf(filename, sizeof(filename), "%s/.asterisk_history", getenv("HOME"));
3165 if (el_hist == NULL || el == NULL)
3166 ast_el_initialize();
3168 el_set(el, EL_GETCFN, ast_el_read_char);
3170 if (!ast_strlen_zero(filename))
3171 ast_el_read_history(filename);
3174 ebuf = (char *)el_gets(el, &num);
3176 if (sig_flags.need_quit || sig_flags.need_quit_handler) {
3180 if (!ebuf && write(1, "", 1) < 0)
3183 if (!ast_strlen_zero(ebuf)) {
3184 if (ebuf[strlen(ebuf)-1] == '\n')
3185 ebuf[strlen(ebuf)-1] = '\0';