Asterisk - The Open Source Telephony Project GIT-master-c7a8271
All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Macros Modules Pages
asterisk.c
Go to the documentation of this file.
1/*
2 * Asterisk -- An open source telephony toolkit.
3 *
4 * Copyright (C) 1999 - 2025, Sangoma Technologies Corporation
5 *
6 * Mark Spencer <markster@digium.com>
7 *
8 * See http://www.asterisk.org for more information about
9 * the Asterisk project. Please do not directly contact
10 * any of the maintainers of this project for assistance;
11 * the project provides a web site, mailing lists and IRC
12 * channels for your use.
13 *
14 * This program is free software, distributed under the terms of
15 * the GNU General Public License Version 2. See the LICENSE file
16 * at the top of the source tree.
17 */
18
19
20/* Doxygenified Copyright Header */
21/*!
22 * \mainpage Asterisk -- The Open Source Telephony Project
23 *
24 * \par Welcome
25 *
26 * This documentation created by the Doxygen project clearly explains the
27 * internals of the Asterisk software. This documentation contains basic
28 * examples, developer documentation, support information, and information
29 * for upgrading.
30 *
31 * \section community Community
32 * Asterisk is a big project and has a busy community. Look at the
33 * resources for questions and stick around to help answer questions.
34 * \li \ref asterisk_community_resources
35 *
36 * \par Developer Documentation for Asterisk
37 *
38 * This is the main developer documentation for Asterisk. It is
39 * generated by running "make progdocs" from the Asterisk source tree.
40 *
41 * In addition to the information available on the Asterisk source code,
42 * please see the appendices for information on coding guidelines,
43 * release management, commit policies, and more.
44 *
45 * \arg \ref AsteriskArchitecture
46 *
47 * \par Additional documentation
48 * \arg \ref Licensing
49 * \arg \ref DevDoc
50 * \arg \ref configuration_file
51 * \arg \ref channel_drivers
52 * \arg \ref applications
53 *
54 * \section copyright Copyright and Author
55 *
56 * Copyright (C) 1999 - 2025, Sangoma Technologies Corporation.
57 * Asterisk is a <a href="https://cdn.sangoma.com/wp-content/uploads/Sangoma-Trademark-Policy.pdf">registered trademark</a>
58 * of <a rel="nofollow" href="http://www.sangoma.com">Sangoma Technologies Corporation</a>.
59 *
60 * \author Mark Spencer <markster@digium.com>
61 *
62 * See http://www.asterisk.org for more information about
63 * the Asterisk project. Please do not directly contact
64 * any of the maintainers of this project for assistance;
65 * the project provides a web site, mailing lists, and IRC
66 * channels for your use.
67 *
68 */
69
70/*!
71 * \page asterisk_community_resources Asterisk Community Resources
72 * \par Websites
73 * \li https://www.asterisk.org Asterisk Homepage
74 * \li https://docs.asterisk.org Asterisk documentation
75 *
76 * \par Mailing Lists
77 * \par
78 * All lists: http://lists.digium.com/mailman/listinfo
79 * \li aadk-commits SVN commits to the AADK repository
80 * \li asterisk-addons-commits SVN commits to the Asterisk addons project
81 * \li asterisk-announce [no description available]
82 * \li asterisk-biz Commercial and Business-Oriented Asterisk Discussion
83 * \li Asterisk-BSD Asterisk on BSD discussion
84 * \li asterisk-bugs [no description available]
85 * \li asterisk-commits SVN commits to the Asterisk project
86 * \li asterisk-dev Asterisk Developers Mailing List
87 * \li asterisk-doc Discussions regarding The Asterisk Documentation Project
88 * \li asterisk-embedded Asterisk Embedded Development
89 * \li asterisk-gui Asterisk GUI project discussion
90 * \li asterisk-gui-commits SVN commits to the Asterisk-GUI project
91 * \li asterisk-ha-clustering Asterisk High Availability and Clustering List - Non-Commercial Discussion
92 * \li Asterisk-i18n Discussion of Asterisk internationalization
93 * \li asterisk-r2 [no description available]
94 * \li asterisk-scf-commits Commits to the Asterisk SCF project code repositories
95 * \li asterisk-scf-committee Asterisk SCF Steering Committee discussions
96 * \li asterisk-scf-dev Asterisk SCF Developers Mailing List
97 * \li asterisk-scf-wiki-changes Changes to the Asterisk SCF space on wiki.asterisk.org
98 * \li asterisk-security Asterisk Security Discussion
99 * \li asterisk-speech-rec Use of speech recognition in Asterisk
100 * \li asterisk-ss7 [no description available]
101 * \li asterisk-users Asterisk Users Mailing List - Non-Commercial Discussion
102 * \li asterisk-video Development discussion of video media support in Asterisk
103 * \li asterisk-wiki-changes Changes to the Asterisk space on wiki.asterisk.org
104 * \li asterisknow AsteriskNOW Discussion
105 * \li dahdi-commits SVN commits to the DAHDI project
106 * \li digium-announce Digium Product Announcements
107 * \li Dundi Distributed Universal Number Discovery
108 * \li libiax2-commits SVN commits to the libiax2 project
109 * \li libpri-commits SVN commits to the libpri project
110 * \li libss7-commits SVN commits to the libss7 project
111 * \li svn-commits SVN commits to the Digium repositories
112 * \li Test-results Results from automated testing
113 * \li thirdparty-commits SVN commits to the Digium third-party software repository
114 * \li zaptel-commits SVN commits to the Zaptel project
115 *
116 * \par Forums
117 * \li Forums are located at http://forums.asterisk.org/
118 *
119 * \par IRC
120 * \par
121 * Use https://libera.chat IRC server to connect with Asterisk
122 * developers and users in realtime.
123 *
124 * \li \verbatim #asterisk \endverbatim Asterisk Users Room
125 * \li \verbatim #asterisk-dev \endverbatim Asterisk Developers Room
126 *
127 * \par More
128 * \par
129 * If you would like to add a resource to this list please create an issue
130 * on the issue tracker with a patch.
131 */
132
133/*! \file
134 * \brief Top level source file for Asterisk - the Open Source PBX.
135 * Implementation of PBX core functions and CLI interface.
136 */
137
138/*! \li \ref asterisk.c uses the configuration file \ref asterisk.conf
139 * \addtogroup configuration_file
140 */
141
142/*! \page asterisk.conf asterisk.conf
143 * \verbinclude asterisk.conf.sample
144 */
145
146/*** MODULEINFO
147 <support_level>core</support_level>
148 ***/
149
150#include "asterisk.h"
151
152#include "asterisk/_private.h"
153
154#undef sched_setscheduler
155#undef setpriority
156#include <sys/time.h>
157#include <fcntl.h>
158#include <signal.h>
159#include <sched.h>
160#include <sys/un.h>
161#include <sys/wait.h>
162#include <ctype.h>
163#include <sys/resource.h>
164#include <grp.h>
165#include <pwd.h>
166#include <sys/stat.h>
167#if defined(HAVE_SYSINFO)
168#include <sys/sysinfo.h>
169#elif defined(HAVE_SYSCTL)
170#include <sys/param.h>
171#include <sys/sysctl.h>
172#include <sys/vmmeter.h>
173#if defined(__FreeBSD__) || defined(__DragonFly__)
174#include <vm/vm_param.h>
175#endif
176#if defined(HAVE_SWAPCTL)
177#include <sys/swap.h>
178#endif
179#endif
180#include <regex.h>
181#include <histedit.h>
182
183#if defined(SOLARIS)
184int daemon(int, int); /* defined in libresolv of all places */
185#include <sys/loadavg.h>
186#endif
187
188#ifdef linux
189#include <sys/prctl.h>
190#ifdef HAVE_CAP
191#include <sys/capability.h>
192#endif /* HAVE_CAP */
193#endif /* linux */
194
195/* we define here the variables so to better agree on the prototype */
196#include "asterisk/paths.h"
197#include "asterisk/network.h"
198#include "asterisk/cli.h"
199#include "asterisk/channel.h"
200#include "asterisk/translate.h"
201#include "asterisk/pickup.h"
202#include "asterisk/acl.h"
203#include "asterisk/ulaw.h"
204#include "asterisk/alaw.h"
205#include "asterisk/callerid.h"
206#include "asterisk/image.h"
207#include "asterisk/tdd.h"
208#include "asterisk/term.h"
209#include "asterisk/manager.h"
210#include "asterisk/cdr.h"
211#include "asterisk/pbx.h"
212#include "asterisk/app.h"
213#include "asterisk/mwi.h"
214#include "asterisk/lock.h"
215#include "asterisk/utils.h"
216#include "asterisk/file.h"
217#include "asterisk/io.h"
218#include "asterisk/config.h"
219#include "asterisk/ast_version.h"
220#include "asterisk/linkedlists.h"
221#include "asterisk/devicestate.h"
223#include "asterisk/module.h"
224#include "asterisk/buildinfo.h"
225#include "asterisk/xmldoc.h"
226#include "asterisk/poll-compat.h"
227#include "asterisk/test.h"
228#include "asterisk/rtp_engine.h"
229#include "asterisk/format.h"
230#include "asterisk/aoc.h"
231#include "asterisk/uuid.h"
232#include "asterisk/sorcery.h"
233#include "asterisk/bucket.h"
234#include "asterisk/stasis.h"
235#include "asterisk/json.h"
239#include "asterisk/endpoints.h"
240#include "asterisk/codec.h"
242#include "asterisk/media_cache.h"
243#include "asterisk/astdb.h"
244#include "asterisk/options.h"
245#include "asterisk/utf8.h"
246
247#include "../defaults.h"
248#include "channelstorage.h"
249
250/*** DOCUMENTATION
251 <managerEvent language="en_US" name="FullyBooted">
252 <managerEventInstance class="EVENT_FLAG_SYSTEM">
253 <since>
254 <version>12.0.0</version>
255 </since>
256 <synopsis>Raised when all Asterisk initialization procedures have finished.</synopsis>
257 <syntax>
258 <parameter name="Status">
259 <para>Informational message</para>
260 </parameter>
261 <parameter name="Uptime">
262 <para>Seconds since start</para>
263 </parameter>
264 <parameter name="LastReload">
265 <para>Seconds since last reload</para>
266 </parameter>
267 </syntax>
268 </managerEventInstance>
269 </managerEvent>
270 <managerEvent language="en_US" name="Shutdown">
271 <managerEventInstance class="EVENT_FLAG_SYSTEM">
272 <since>
273 <version>12.0.0</version>
274 </since>
275 <synopsis>Raised when Asterisk is shutdown or restarted.</synopsis>
276 <syntax>
277 <parameter name="Shutdown">
278 <para>Whether the shutdown is proceeding cleanly (all channels
279 were hungup successfully) or uncleanly (channels will be
280 terminated)</para>
281 <enumlist>
282 <enum name="Uncleanly"/>
283 <enum name="Cleanly"/>
284 </enumlist>
285 </parameter>
286 <parameter name="Restart">
287 <para>Whether or not a restart will occur.</para>
288 <enumlist>
289 <enum name="True"/>
290 <enum name="False"/>
291 </enumlist>
292 </parameter>
293 </syntax>
294 </managerEventInstance>
295 </managerEvent>
296 ***/
297
298#ifndef AF_LOCAL
299#define AF_LOCAL AF_UNIX
300#define PF_LOCAL PF_UNIX
301#endif
302
303#define AST_MAX_CONNECTS 128
304#define NUM_MSGS 64
305
306/*! Displayed copyright tag */
307#define COPYRIGHT_TAG "Copyright (C) 1999 - 2025, Sangoma Technologies Corporation and others."
308
309/*! \brief Welcome message when starting a CLI interface */
310#define WELCOME_MESSAGE \
311 ast_verbose("Asterisk %s, " COPYRIGHT_TAG "\n" \
312 "Created by Mark Spencer <markster@digium.com>\n" \
313 "Asterisk comes with ABSOLUTELY NO WARRANTY; type 'core show warranty' for details.\n" \
314 "This is free software, with components licensed under the GNU General Public\n" \
315 "License version 2 and other licenses; you are welcome to redistribute it under\n" \
316 "certain conditions. Type 'core show license' for details.\n" \
317 "=========================================================================\n", ast_get_version()) \
318
319static int ast_socket = -1; /*!< UNIX Socket for allowing remote control */
320static int ast_socket_is_sd = 0; /*!< Is socket activation responsible for ast_socket? */
321static int ast_consock = -1; /*!< UNIX Socket for controlling another asterisk */
323struct console {
324 int fd; /*!< File descriptor */
325 int p[2]; /*!< Pipe */
326 pthread_t t; /*!< Thread of handler */
327 int mute; /*!< Is the console muted for logs */
328 int uid; /*!< Remote user ID. */
329 int gid; /*!< Remote group ID. */
330 int levels[NUMLOGLEVELS]; /*!< Which log levels are enabled for the console */
331 /*! Verbosity level of this console. */
333};
334
336 void (*func)(void);
339};
340
342
343struct timeval ast_startuptime;
344struct timeval ast_lastreloadtime;
345
346static History *el_hist;
347static EditLine *el;
348static char *remotehostname;
349
351
352static int ast_el_add_history(const char *);
353static int ast_el_read_history(const char *);
354static int ast_el_write_history(const char *);
355
356static void ast_el_read_default_histfile(void);
357static void ast_el_write_default_histfile(void);
358
359static void asterisk_daemon(int isroot, const char *runuser, const char *rungroup);
360
361static char *_argv[256];
362
363typedef enum {
364 /*! Normal operation */
366 /*! Committed to shutting down. Final phase */
368 /*! Committed to shutting down. Initial phase */
370 /*!
371 * Valid values for quit_handler() niceness below.
372 * These shutdown/restart levels can be cancelled.
373 *
374 * Remote console exit right now
375 */
377 /*! core stop/restart now */
379 /*! core stop/restart gracefully */
381 /*! core stop/restart when convenient */
384
386
387/*! Prevent new channel allocation for shutdown. */
389
390static int restartnow;
392static pthread_t mon_sig_flags;
393static int canary_pid = 0;
394static char canary_filename[128];
396
397static char randompool[256];
398
399#ifdef HAVE_CAP
400static cap_t child_cap;
401#endif
402
403static int sig_alert_pipe[2] = { -1, -1 };
404static struct {
405 unsigned int need_reload:1;
406 unsigned int need_quit:1;
407 unsigned int need_quit_handler:1;
408 unsigned int need_el_end:1;
410
411#if !defined(LOW_MEMORY)
414 char *name;
415 pthread_t id;
416 int lwp;
417};
418
420
422{
423 struct thread_list_t *new = ast_calloc(1, sizeof(*new));
424
425 if (!new)
426 return;
427
429 new->id = pthread_self();
430 new->lwp = ast_get_tid();
431 new->name = name; /* steal the allocated memory for the thread name */
435}
436
438{
439 struct thread_list_t *x;
440
443 if ((void *) x->id == id) {
445 break;
446 }
447 }
450 if (x) {
451 ast_free(x->name);
452 ast_free(x);
453 }
454}
455
456/*! \brief Print the contents of a file */
457static int print_file(int fd, char *desc, const char *filename)
458{
459 FILE *f;
460 char c;
461 if (!(f = fopen(filename, "r"))) {
462 return -1;
463 }
464 ast_cli(fd, "%s", desc);
465 while ((c = fgetc(f)) != EOF) {
466 ast_cli(fd, "%c", c);
467 }
468 fclose(f);
469 /* no need for trailing new line, the file already has one */
470 return 0;
471}
472
473/*! \brief Give an overview of core settings */
474static char *handle_show_settings(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
475{
476 char buf[BUFSIZ];
477 struct ast_tm tm;
478 char eid_str[128];
479 struct rlimit limits;
480 char pbx_uuid[AST_UUID_STR_LEN];
481#if defined(HAVE_EACCESS) || defined(HAVE_EUIDACCESS)
482 char dir[PATH_MAX];
483#endif
484
485 switch (cmd) {
486 case CLI_INIT:
487 e->command = "core show settings";
488 e->usage = "Usage: core show settings\n"
489 " Show core misc settings";
490 return NULL;
491 case CLI_GENERATE:
492 return NULL;
493 }
494
495 ast_eid_to_str(eid_str, sizeof(eid_str), &ast_eid_default);
496 ast_pbx_uuid_get(pbx_uuid, sizeof(pbx_uuid));
497
498 ast_cli(a->fd, "\nPBX Core settings\n");
499 ast_cli(a->fd, "-----------------\n");
500 ast_cli(a->fd, " Version: %s\n", ast_get_version());
501 ast_cli(a->fd, " ABI related Build Options: %s\n", S_OR(ast_get_build_opts(), "(none)"));
502 ast_cli(a->fd, " All Build Options: %s\n", S_OR(ast_get_build_opts_all(), "(none)"));
504 ast_cli(a->fd, " Maximum calls: %d (Current %d)\n", ast_option_maxcalls, ast_active_channels());
505 else
506 ast_cli(a->fd, " Maximum calls: Not set\n");
507
508 if (getrlimit(RLIMIT_NOFILE, &limits)) {
509 ast_cli(a->fd, " Maximum open file handles: Error because of %s\n", strerror(errno));
510 } else if (limits.rlim_cur == RLIM_INFINITY) {
511 ast_cli(a->fd, " Maximum open file handles: Unlimited\n");
512 } else if (limits.rlim_cur < ast_option_maxfiles) {
513 ast_cli(a->fd, " Maximum open file handles: %d (is) %d (requested)\n", (int) limits.rlim_cur, ast_option_maxfiles);
514 } else {
515 ast_cli(a->fd, " Maximum open file handles: %d\n", (int) limits.rlim_cur);
516 }
517
518 ast_cli(a->fd, " Root console verbosity: %d\n", option_verbose);
519 ast_cli(a->fd, " Current console verbosity: %d\n", ast_verb_console_get());
520 ast_cli(a->fd, " Debug level: %d\n", option_debug);
521 ast_cli(a->fd, " Trace level: %d\n", option_trace);
522 ast_cli(a->fd, " Dump core on crash: %s\n", ast_opt_dump_core ? "Yes" : "No");
523 print_file(a->fd, " Core dump file: ", "/proc/sys/kernel/core_pattern");
524 ast_cli(a->fd, " Maximum load average: %lf\n", ast_option_maxload);
525#if defined(HAVE_SYSINFO)
526 ast_cli(a->fd, " Minimum free memory: %ld MB\n", option_minmemfree);
527#endif
528 if (ast_localtime(&ast_startuptime, &tm, NULL)) {
529 ast_strftime(buf, sizeof(buf), "%H:%M:%S", &tm);
530 ast_cli(a->fd, " Startup time: %s\n", buf);
531 }
533 ast_strftime(buf, sizeof(buf), "%H:%M:%S", &tm);
534 ast_cli(a->fd, " Last reload time: %s\n", buf);
535 }
536 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);
537 ast_cli(a->fd, " System name: %s\n", ast_config_AST_SYSTEM_NAME);
538 ast_cli(a->fd, " Entity ID: %s\n", eid_str);
539 ast_cli(a->fd, " PBX UUID: %s\n", pbx_uuid);
540 ast_cli(a->fd, " Default language: %s\n", ast_defaultlanguage);
541 ast_cli(a->fd, " Language prefix: %s\n", ast_language_is_prefix ? "Enabled" : "Disabled");
542 ast_cli(a->fd, " User name and group: %s/%s\n", ast_config_AST_RUN_USER, ast_config_AST_RUN_GROUP);
543#if defined(HAVE_EACCESS) || defined(HAVE_EUIDACCESS)
544#if defined(HAVE_EUIDACCESS) && !defined(HAVE_EACCESS)
545#define eaccess euidaccess
546#endif
547 if (!getcwd(dir, sizeof(dir))) {
548 if (eaccess(dir, R_OK | X_OK | F_OK)) {
549 ast_cli(a->fd, " Running directory: %s\n", "Unable to access");
550 } else {
551 ast_cli(a->fd, " Running directory: %s (%s)\n", dir, "Unable to access");
552 }
553 } else {
554 ast_cli(a->fd, " Running directory: %s\n", dir);
555 }
556#endif /* defined(HAVE_EACCESS) || defined(HAVE_EUIDACCESS) */
557 ast_cli(a->fd, " Executable includes: %s\n", ast_test_flag(&ast_options, AST_OPT_FLAG_EXEC_INCLUDES) ? "Enabled" : "Disabled");
558 ast_cli(a->fd, " Transcode via SLIN: %s\n", ast_test_flag(&ast_options, AST_OPT_FLAG_TRANSCODE_VIA_SLIN) ? "Enabled" : "Disabled");
559 ast_cli(a->fd, " Transmit silence during rec: %s\n", ast_test_flag(&ast_options, AST_OPT_FLAG_TRANSMIT_SILENCE) ? "Enabled" : "Disabled");
560 ast_cli(a->fd, " Generic PLC: %s\n", ast_test_flag(&ast_options, AST_OPT_FLAG_GENERIC_PLC) ? "Enabled" : "Disabled");
561 ast_cli(a->fd, " Generic PLC on equal codecs: %s\n", ast_test_flag(&ast_options, AST_OPT_FLAG_GENERIC_PLC_ON_EQUAL_CODECS) ? "Enabled" : "Disabled");
562 ast_cli(a->fd, " Hide Msg Chan AMI events: %s\n", ast_opt_hide_messaging_ami_events ? "Enabled" : "Disabled");
563 ast_cli(a->fd, " Sounds search custom dir: %s\n", ast_opt_sounds_search_custom ? "Enabled" : "Disabled");
564 ast_cli(a->fd, " Min DTMF duration:: %u\n", option_dtmfminduration);
565#if !defined(LOW_MEMORY)
566 ast_cli(a->fd, " Cache media frames: %s\n", ast_opt_cache_media_frames ? "Enabled" : "Disabled");
567#endif
568 ast_cli(a->fd, " RTP use dynamic payloads: %u\n", ast_option_rtpusedynamic);
569
571 ast_cli(a->fd, " RTP dynamic payload types: %u,%u-%u\n",
575 ast_cli(a->fd, " RTP dynamic payload types: %u-%u,%u-%u\n",
578 } else {
579 ast_cli(a->fd, " RTP dynamic payload types: %u-%u\n",
581 }
582 ast_cli(a->fd, " Channel storage backend: %s\n",
584 ast_cli(a->fd, " Shell on remote consoles: %s\n",
585 ast_option_disable_remote_console_shell ? "Disabled" : "Enabled");
586
587 ast_cli(a->fd, "\n* Subsystems\n");
588 ast_cli(a->fd, " -------------\n");
589 ast_cli(a->fd, " Manager (AMI): %s\n", ast_manager_check_enabled() ? "Enabled" : "Disabled");
590 ast_cli(a->fd, " Web Manager (AMI/HTTP): %s\n", ast_webmanager_check_enabled() ? "Enabled" : "Disabled");
591 ast_cli(a->fd, " Call data records: %s\n", ast_cdr_is_enabled() ? "Enabled" : "Disabled");
592 ast_cli(a->fd, " Realtime Architecture (ARA): %s\n", ast_realtime_enabled() ? "Enabled" : "Disabled");
593
594 /*! \todo we could check musiconhold, voicemail, smdi, adsi, queues */
595
596 ast_cli(a->fd, "\n* Directories\n");
597 ast_cli(a->fd, " -------------\n");
598 ast_cli(a->fd, " Configuration file: %s\n", ast_config_AST_CONFIG_FILE);
599 ast_cli(a->fd, " Configuration directory: %s\n", ast_config_AST_CONFIG_DIR);
600 ast_cli(a->fd, " Module directory: %s\n", ast_config_AST_MODULE_DIR);
601 ast_cli(a->fd, " Spool directory: %s\n", ast_config_AST_SPOOL_DIR);
602 ast_cli(a->fd, " Log directory: %s\n", ast_config_AST_LOG_DIR);
603 ast_cli(a->fd, " Run/Sockets directory: %s\n", ast_config_AST_RUN_DIR);
604 ast_cli(a->fd, " PID file: %s\n", ast_config_AST_PID);
605 ast_cli(a->fd, " VarLib directory: %s\n", ast_config_AST_VAR_DIR);
606 ast_cli(a->fd, " Data directory: %s\n", ast_config_AST_DATA_DIR);
607 ast_cli(a->fd, " ASTDB: %s\n", ast_config_AST_DB);
608 ast_cli(a->fd, " IAX2 Keys directory: %s\n", ast_config_AST_KEY_DIR);
609 ast_cli(a->fd, " AGI Scripts directory: %s\n", ast_config_AST_AGI_DIR);
610 ast_cli(a->fd, " Cache directory: %s\n", ast_config_AST_CACHE_DIR);
611 ast_cli(a->fd, "\n\n");
612 return CLI_SUCCESS;
613}
614
615static char *handle_show_threads(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
616{
617 int count = 0;
618 struct thread_list_t *cur;
619 switch (cmd) {
620 case CLI_INIT:
621 e->command = "core show threads";
622 e->usage =
623 "Usage: core show threads\n"
624 " List threads currently active in the system.\n";
625 return NULL;
626 case CLI_GENERATE:
627 return NULL;
628 }
629
631 AST_RWLIST_TRAVERSE(&thread_list, cur, list) {
632 ast_cli(a->fd, "%p %d %s\n", (void *)cur->id, cur->lwp, cur->name);
633 count++;
634 }
636 ast_cli(a->fd, "%d threads listed.\n", count);
637 return CLI_SUCCESS;
638}
639
640#if defined (HAVE_SYSCTL) && defined(HAVE_SWAPCTL)
641/*
642 * swapmode is rewritten by Tobias Weingartner <weingart@openbsd.org>
643 * to be based on the new swapctl(2) system call.
644 */
645static int swapmode(int *used, int *total)
646{
647 struct swapent *swdev;
648 int nswap, rnswap, i;
649
650 nswap = swapctl(SWAP_NSWAP, 0, 0);
651 if (nswap == 0)
652 return 0;
653
654 swdev = ast_calloc(nswap, sizeof(*swdev));
655 if (swdev == NULL)
656 return 0;
657
658 rnswap = swapctl(SWAP_STATS, swdev, nswap);
659 if (rnswap == -1) {
660 ast_free(swdev);
661 return 0;
662 }
663
664 /* if rnswap != nswap, then what? */
665
666 /* Total things up */
667 *total = *used = 0;
668 for (i = 0; i < nswap; i++) {
669 if (swdev[i].se_flags & SWF_ENABLE) {
670 *used += (swdev[i].se_inuse / (1024 / DEV_BSIZE));
671 *total += (swdev[i].se_nblks / (1024 / DEV_BSIZE));
672 }
673 }
674 ast_free(swdev);
675 return 1;
676}
677#endif
678
679#if defined(HAVE_SYSINFO) || defined(HAVE_SYSCTL)
680/*! \brief Give an overview of system statistics */
681static char *handle_show_sysinfo(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
682{
683 uint64_t physmem, freeram;
684#if defined(HAVE_SYSINFO) || defined(HAVE_SWAPCTL)
685 int totalswap = 0;
686 uint64_t freeswap = 0;
687#endif
688 int nprocs = 0;
689 long uptime = 0;
690#if defined(HAVE_SYSINFO)
691 struct sysinfo sys_info;
692#elif defined(HAVE_SYSCTL)
693 static int pageshift;
694 struct vmtotal vmtotal;
695 struct timeval boottime;
696 time_t now;
697 int mib[2], pagesize;
698#if defined(HAVE_SWAPCTL)
699 int usedswap = 0;
700#endif
701 size_t len;
702#endif
703
704 switch (cmd) {
705 case CLI_INIT:
706 e->command = "core show sysinfo";
707 e->usage =
708 "Usage: core show sysinfo\n"
709 " List current system information.\n";
710 return NULL;
711 case CLI_GENERATE:
712 return NULL;
713 }
714
715#if defined(HAVE_SYSINFO)
716 sysinfo(&sys_info);
717 uptime = sys_info.uptime / 3600;
718 physmem = sys_info.totalram * sys_info.mem_unit;
719 freeram = (sys_info.freeram * sys_info.mem_unit) / 1024;
720 totalswap = (sys_info.totalswap * sys_info.mem_unit) / 1024;
721 freeswap = (sys_info.freeswap * sys_info.mem_unit) / 1024;
722 nprocs = sys_info.procs;
723#elif defined(HAVE_SYSCTL)
724 /* calculate the uptime by looking at boottime */
725 time(&now);
726 mib[0] = CTL_KERN;
727 mib[1] = KERN_BOOTTIME;
728 len = sizeof(boottime);
729 if (sysctl(mib, 2, &boottime, &len, NULL, 0) != -1) {
730 uptime = now - boottime.tv_sec;
731 }
732 uptime = uptime/3600;
733 /* grab total physical memory */
734 mib[0] = CTL_HW;
735#if defined(HW_PHYSMEM64)
736 mib[1] = HW_PHYSMEM64;
737#else
738 mib[1] = HW_PHYSMEM;
739#endif
740 len = sizeof(physmem);
741 sysctl(mib, 2, &physmem, &len, NULL, 0);
742
743 pagesize = getpagesize();
744 pageshift = 0;
745 while (pagesize > 1) {
746 pageshift++;
747 pagesize >>= 1;
748 }
749
750 /* we only need the amount of log(2)1024 for our conversion */
751 pageshift -= 10;
752
753 /* grab vm totals */
754 mib[0] = CTL_VM;
755 mib[1] = VM_METER;
756 len = sizeof(vmtotal);
757 sysctl(mib, 2, &vmtotal, &len, NULL, 0);
758 freeram = (vmtotal.t_free << pageshift);
759 /* generate swap usage and totals */
760#if defined(HAVE_SWAPCTL)
761 swapmode(&usedswap, &totalswap);
762 freeswap = (totalswap - usedswap);
763#endif
764 /* grab number of processes */
765#if defined(__OpenBSD__)
766 mib[0] = CTL_KERN;
767 mib[1] = KERN_NPROCS;
768 len = sizeof(nprocs);
769 sysctl(mib, 2, &nprocs, &len, NULL, 0);
770#endif
771#endif
772
773 ast_cli(a->fd, "\nSystem Statistics\n");
774 ast_cli(a->fd, "-----------------\n");
775 ast_cli(a->fd, " System Uptime: %ld hours\n", uptime);
776 ast_cli(a->fd, " Total RAM: %" PRIu64 " KiB\n", physmem / 1024);
777 ast_cli(a->fd, " Free RAM: %" PRIu64 " KiB\n", freeram);
778#if defined(HAVE_SYSINFO)
779 ast_cli(a->fd, " Buffer RAM: %" PRIu64 " KiB\n", ((uint64_t) sys_info.bufferram * sys_info.mem_unit) / 1024);
780#endif
781#if defined(HAVE_SYSINFO) || defined(HAVE_SWAPCTL)
782 ast_cli(a->fd, " Total Swap Space: %d KiB\n", totalswap);
783 ast_cli(a->fd, " Free Swap Space: %" PRIu64 " KiB\n\n", freeswap);
784#endif
785 ast_cli(a->fd, " Number of Processes: %d \n\n", nprocs);
786 return CLI_SUCCESS;
787}
788#endif
789
791 const char *name;
792 uint64_t scale; /* if non-zero, values are scaled by this */
793 int64_t mark;
794 int64_t value;
795 int64_t events;
796};
797
801 struct profile_entry e[0];
802};
803
804static struct profile_data *prof_data;
805#endif /* ! LOW_MEMORY */
806
807/*! \brief allocates a counter with a given name and scale.
808 * \return Returns the identifier of the counter.
809 */
810int ast_add_profile(const char *name, uint64_t scale)
811{
812#if !defined(LOW_MEMORY)
813 int l = sizeof(struct profile_data);
814 int n = 10; /* default entries */
815
816 if (prof_data == NULL) {
817 prof_data = ast_calloc(1, l + n*sizeof(struct profile_entry));
818 if (prof_data == NULL)
819 return -1;
820 prof_data->entries = 0;
821 prof_data->max_size = n;
822 }
824 void *p;
825 n = prof_data->max_size + 20;
826 p = ast_realloc(prof_data, l + n*sizeof(struct profile_entry));
827 if (p == NULL)
828 return -1;
829 prof_data = p;
830 prof_data->max_size = n;
831 }
832 n = prof_data->entries++;
834 prof_data->e[n].value = 0;
835 prof_data->e[n].events = 0;
836 prof_data->e[n].mark = 0;
837 prof_data->e[n].scale = scale;
838 return n;
839#else /* if defined(LOW_MEMORY) */
840 return 0;
841#endif
842}
843
844int64_t ast_profile(int i, int64_t delta)
845{
846#if !defined(LOW_MEMORY)
847 if (!prof_data || i < 0 || i > prof_data->entries) /* invalid index */
848 return 0;
849 if (prof_data->e[i].scale > 1)
850 delta /= prof_data->e[i].scale;
851 prof_data->e[i].value += delta;
852 prof_data->e[i].events++;
853 return prof_data->e[i].value;
854#else /* if defined(LOW_MEMORY) */
855 return 0;
856#endif
857}
858
859#if !defined(LOW_MEMORY)
860/* The RDTSC instruction was introduced on the Pentium processor and is not
861 * implemented on certain clones, like the Cyrix 586. Hence, the previous
862 * expectation of __i386__ was in error. */
863#if defined ( __i686__) && (defined(__FreeBSD__) || defined(__NetBSD__) || defined(linux))
864#if defined(__FreeBSD__)
865#include <machine/cpufunc.h>
866#elif defined(__NetBSD__) || defined(linux)
867static __inline uint64_t
868rdtsc(void)
869{
870 uint64_t rv;
871
872 __asm __volatile(".byte 0x0f, 0x31" : "=A" (rv));
873 return (rv);
874}
875#endif
876#else /* supply a dummy function on other platforms */
877static __inline uint64_t
878rdtsc(void)
879{
880 return 0;
881}
882#endif
883#endif /* ! LOW_MEMORY */
884
885int64_t ast_mark(int i, int startstop)
886{
887#if !defined(LOW_MEMORY)
888 if (!prof_data || i < 0 || i > prof_data->entries) /* invalid index */
889 return 0;
890 if (startstop == 1)
891 prof_data->e[i].mark = rdtsc();
892 else {
893 prof_data->e[i].mark = (rdtsc() - prof_data->e[i].mark);
894 if (prof_data->e[i].scale > 1)
895 prof_data->e[i].mark /= prof_data->e[i].scale;
896 prof_data->e[i].value += prof_data->e[i].mark;
897 prof_data->e[i].events++;
898 }
899 return prof_data->e[i].mark;
900#else /* if defined(LOW_MEMORY) */
901 return 0;
902#endif
903}
904
905#if !defined(LOW_MEMORY)
906#define DEFINE_PROFILE_MIN_MAX_VALUES min = 0; \
907 max = prof_data->entries;\
908 if (a->argc > 3) { /* specific entries */ \
909 if (isdigit(a->argv[3][0])) { \
910 min = atoi(a->argv[3]); \
911 if (a->argc == 5 && strcmp(a->argv[4], "-")) \
912 max = atoi(a->argv[4]); \
913 } else \
914 search = a->argv[3]; \
915 } \
916 if (max > prof_data->entries) \
917 max = prof_data->entries;
918
919static char *handle_show_profile(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
920{
921 int i, min, max;
922 const char *search = NULL;
923 switch (cmd) {
924 case CLI_INIT:
925 e->command = "core show profile";
926 e->usage = "Usage: core show profile\n"
927 " show profile information";
928 return NULL;
929 case CLI_GENERATE:
930 return NULL;
931 }
932
933 if (prof_data == NULL)
934 return 0;
935
937 ast_cli(a->fd, "profile values (%d, allocated %d)\n-------------------\n",
939 ast_cli(a->fd, "%6s %8s %10s %12s %12s %s\n", "ID", "Scale", "Events",
940 "Value", "Average", "Name");
941 for (i = min; i < max; i++) {
942 struct profile_entry *entry = &prof_data->e[i];
943 if (!search || strstr(entry->name, search))
944 ast_cli(a->fd, "%6d: [%8ld] %10ld %12lld %12lld %s\n",
945 i,
946 (long)entry->scale,
947 (long)entry->events, (long long)entry->value,
948 (long long)(entry->events ? entry->value / entry->events : entry->value),
949 entry->name);
950 }
951 return CLI_SUCCESS;
952}
953
954static char *handle_clear_profile(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
955{
956 int i, min, max;
957 const char *search = NULL;
958 switch (cmd) {
959 case CLI_INIT:
960 e->command = "core clear profile";
961 e->usage = "Usage: core clear profile\n"
962 " clear profile information";
963 return NULL;
964 case CLI_GENERATE:
965 return NULL;
966 }
967
968 if (prof_data == NULL)
969 return 0;
970
972 for (i= min; i < max; i++) {
973 if (!search || strstr(prof_data->e[i].name, search)) {
974 prof_data->e[i].value = 0;
975 prof_data->e[i].events = 0;
976 }
977 }
978 return CLI_SUCCESS;
979}
980#undef DEFINE_PROFILE_MIN_MAX_VALUES
981
982#endif /* ! LOW_MEMORY */
983
984int ast_pbx_uuid_get(char *pbx_uuid, int length)
985{
986 return ast_db_get("pbx", "UUID", pbx_uuid, length);
987}
988
989static void publish_fully_booted(void)
990{
991 struct ast_json *json_object;
992 int uptime = 0;
993 int lastreloaded = 0;
994 struct timeval tmp;
995 struct timeval curtime = ast_tvnow();
996
997 if (ast_startuptime.tv_sec) {
998 tmp = ast_tvsub(curtime, ast_startuptime);
999 uptime = (int) tmp.tv_sec;
1000 }
1001
1002 if (ast_lastreloadtime.tv_sec) {
1003 tmp = ast_tvsub(curtime, ast_lastreloadtime);
1004 lastreloaded = (int) tmp.tv_sec;
1005 }
1006
1007 json_object = ast_json_pack("{s: s, s: i, s: i}",
1008 "Status", "Fully Booted",
1009 "Uptime", uptime,
1010 "LastReload", lastreloaded);
1011 ast_manager_publish_event("FullyBooted", EVENT_FLAG_SYSTEM, json_object);
1012 ast_json_unref(json_object);
1013}
1014
1015static void ast_run_atexits(int run_cleanups)
1016{
1017 struct ast_atexit *ae;
1018
1020 while ((ae = AST_LIST_REMOVE_HEAD(&atexits, list))) {
1021 if (ae->func && (!ae->is_cleanup || run_cleanups)) {
1022 ae->func();
1023 }
1024 ast_free(ae);
1025 }
1027}
1028
1029static void __ast_unregister_atexit(void (*func)(void))
1030{
1031 struct ast_atexit *ae;
1032
1034 if (ae->func == func) {
1036 ast_free(ae);
1037 break;
1038 }
1039 }
1041}
1042
1043static int register_atexit(void (*func)(void), int is_cleanup)
1044{
1045 struct ast_atexit *ae;
1046
1047 ae = ast_calloc(1, sizeof(*ae));
1048 if (!ae) {
1049 return -1;
1050 }
1051 ae->func = func;
1052 ae->is_cleanup = is_cleanup;
1053
1058
1059 return 0;
1060}
1061
1062int ast_register_atexit(void (*func)(void))
1063{
1064 return register_atexit(func, 0);
1065}
1066
1067int ast_register_cleanup(void (*func)(void))
1068{
1069 return register_atexit(func, 1);
1070}
1071
1072void ast_unregister_atexit(void (*func)(void))
1073{
1077}
1078
1079/* Sending commands from consoles back to the daemon requires a terminating NULL */
1080static int fdsend(int fd, const char *s)
1081{
1082 return write(fd, s, strlen(s) + 1);
1083}
1084
1085/* Sending messages from the daemon back to the display requires _excluding_ the terminating NULL */
1086static int fdprint(int fd, const char *s)
1087{
1088 return write(fd, s, strlen(s));
1089}
1090
1091/*! \brief NULL handler so we can collect the child exit status */
1092static void _null_sig_handler(int sig)
1093{
1094}
1095
1096static struct sigaction null_sig_handler = {
1097 .sa_handler = _null_sig_handler,
1098 .sa_flags = SA_RESTART,
1099};
1100
1101static struct sigaction ignore_sig_handler = {
1102 .sa_handler = SIG_IGN,
1103};
1104
1106/*! \brief Keep track of how many threads are currently trying to wait*() on
1107 * a child process
1108 */
1109static unsigned int safe_system_level = 0;
1110static struct sigaction safe_system_prev_handler;
1111
1113{
1114 unsigned int level;
1115
1117 level = safe_system_level++;
1118
1119 /* only replace the handler if it has not already been done */
1120 if (level == 0) {
1121 sigaction(SIGCHLD, &null_sig_handler, &safe_system_prev_handler);
1122 }
1123
1125}
1126
1128{
1129 unsigned int level;
1130
1132
1133 /* Wrapping around here is an error */
1135
1136 level = --safe_system_level;
1137
1138 /* only restore the handler if we are the last one */
1139 if (level == 0) {
1140 sigaction(SIGCHLD, &safe_system_prev_handler, NULL);
1141 }
1142
1144}
1145
1146/*! \brief fork and perform other preparations for spawning applications */
1147static pid_t safe_exec_prep(int dualfork)
1148{
1149 pid_t pid;
1150
1151#if defined(HAVE_WORKING_FORK) || defined(HAVE_WORKING_VFORK)
1153
1154#ifdef HAVE_WORKING_FORK
1155 pid = fork();
1156#else
1157 pid = vfork();
1158#endif
1159
1160 if (pid == 0) {
1161#ifdef HAVE_CAP
1162 cap_set_proc(child_cap);
1163#endif
1164#ifdef HAVE_WORKING_FORK
1167 }
1168 /* Close file descriptors and launch system command */
1169 ast_close_fds_above_n(STDERR_FILENO);
1170#endif
1171 if (dualfork) {
1172#ifdef HAVE_WORKING_FORK
1173 pid = fork();
1174#else
1175 pid = vfork();
1176#endif
1177 if (pid < 0) {
1178 /* Second fork failed. */
1179 /* No logger available. */
1180 _exit(1);
1181 }
1182
1183 if (pid > 0) {
1184 /* This is the first fork, exit so the reaper finishes right away. */
1185 _exit(0);
1186 }
1187
1188 /* This is the second fork. The first fork will exit immediately so
1189 * Asterisk doesn't have to wait for completion.
1190 * ast_safe_system("cmd &") would run in the background, but the '&'
1191 * cannot be added with ast_safe_execvp, so we have to double fork.
1192 */
1193 }
1194 }
1195
1196 if (pid < 0) {
1197 ast_log(LOG_WARNING, "Fork failed: %s\n", strerror(errno));
1198 }
1199#else
1200 ast_log(LOG_WARNING, "Fork failed: %s\n", strerror(ENOTSUP));
1201 pid = -1;
1202#endif
1203
1204 return pid;
1205}
1206
1207/*! \brief wait for spawned application to complete and unreplace sigchld */
1208static int safe_exec_wait(pid_t pid)
1209{
1210 int res = -1;
1211
1212#if defined(HAVE_WORKING_FORK) || defined(HAVE_WORKING_VFORK)
1213 if (pid > 0) {
1214 for (;;) {
1215 int status;
1216
1217 res = waitpid(pid, &status, 0);
1218 if (res > -1) {
1219 res = WIFEXITED(status) ? WEXITSTATUS(status) : -1;
1220 break;
1221 }
1222 if (errno != EINTR) {
1223 break;
1224 }
1225 }
1226 }
1227
1229#endif
1230
1231 return res;
1232}
1233
1234int ast_safe_execvp(int dualfork, const char *file, char *const argv[])
1235{
1236 pid_t pid = safe_exec_prep(dualfork);
1237
1238 if (pid == 0) {
1239 execvp(file, argv);
1240 _exit(1);
1241 /* noreturn from _exit */
1242 }
1243
1244 return safe_exec_wait(pid);
1245}
1246
1247int ast_safe_system(const char *s)
1248{
1249 pid_t pid = safe_exec_prep(0);
1250
1251 if (pid == 0) {
1252 execl("/bin/sh", "/bin/sh", "-c", s, (char *) NULL);
1253 _exit(1);
1254 /* noreturn from _exit */
1255 }
1256
1257 return safe_exec_wait(pid);
1258}
1259
1260/*!
1261 * \brief enable or disable a logging level to a specified console
1262 */
1263void ast_console_toggle_loglevel(int fd, int level, int state)
1264{
1265 int x;
1266
1267 if (level >= NUMLOGLEVELS) {
1268 level = NUMLOGLEVELS - 1;
1269 }
1270
1271 for (x = 0;x < AST_MAX_CONNECTS; x++) {
1272 if (fd == consoles[x].fd) {
1273 /*
1274 * Since the logging occurs when levels are false, set to
1275 * flipped iinput because this function accepts 0 as off and 1 as on
1276 */
1277 consoles[x].levels[level] = state ? 0 : 1;
1278 return;
1279 }
1280 }
1281}
1282
1283/*!
1284 * \brief mute or unmute a console from logging
1285 */
1286void ast_console_toggle_mute(int fd, int silent)
1287{
1288 int x;
1289 for (x = 0;x < AST_MAX_CONNECTS; x++) {
1290 if (fd == consoles[x].fd) {
1291 if (consoles[x].mute) {
1292 consoles[x].mute = 0;
1293 if (!silent)
1294 ast_cli(fd, "Console is not muted anymore.\n");
1295 } else {
1296 consoles[x].mute = 1;
1297 if (!silent)
1298 ast_cli(fd, "Console is muted.\n");
1299 }
1300 return;
1301 }
1302 }
1303 ast_cli(fd, "Couldn't find remote console.\n");
1304}
1305
1306/*!
1307 * \brief log the string to all attached network console clients
1308 */
1309static void ast_network_puts_mutable(const char *string, int level, int sublevel)
1310{
1311 int x;
1312
1313 for (x = 0; x < AST_MAX_CONNECTS; ++x) {
1314 if (consoles[x].fd < 0
1315 || consoles[x].mute
1316 || consoles[x].levels[level]
1317 || (level == __LOG_VERBOSE && consoles[x].option_verbose < sublevel)) {
1318 continue;
1319 }
1320 fdprint(consoles[x].p[1], string);
1321 }
1322}
1323
1324/*!
1325 * \brief log the string to the root console, and all attached
1326 * network console clients
1327 */
1328void ast_console_puts_mutable(const char *string, int level)
1329{
1330 ast_console_puts_mutable_full(string, level, 0);
1331}
1332
1333static int console_print(const char *s);
1334
1335void ast_console_puts_mutable_full(const char *message, int level, int sublevel)
1336{
1337 /* Send to the root console */
1339
1340 /* Wake up a poll()ing console */
1342 pthread_kill(consolethread, SIGURG);
1343 }
1344
1345 /* Send to any network console clients */
1346 ast_network_puts_mutable(message, level, sublevel);
1347}
1348
1349/*!
1350 * \brief write the string to all attached console clients
1351 */
1352static void ast_network_puts(const char *string)
1353{
1354 int x;
1355
1356 for (x = 0; x < AST_MAX_CONNECTS; ++x) {
1357 if (consoles[x].fd < 0) {
1358 continue;
1359 }
1360 fdprint(consoles[x].p[1], string);
1361 }
1362}
1363
1364/*!
1365 * \brief write the string to the root console, and all attached
1366 * network console clients
1367 */
1368void ast_console_puts(const char *string)
1369{
1370 /* Send to the root console */
1371 fputs(string, stdout);
1372 fflush(stdout);
1373
1374 /* Send to any network console clients */
1375 ast_network_puts(string);
1376}
1377
1378static pthread_t lthread;
1379
1380/*!
1381 * \brief read() function supporting the reception of user credentials.
1382 *
1383 * \param fd Socket file descriptor.
1384 * \param buffer Receive buffer.
1385 * \param size 'buffer' size.
1386 * \param con Console structure to set received credentials
1387 * \retval -1 on error
1388 * \retval the number of bytes received on success.
1389 */
1390static int read_credentials(int fd, char *buffer, size_t size, struct console *con)
1391{
1392#if defined(SO_PEERCRED)
1393#ifdef HAVE_STRUCT_SOCKPEERCRED_UID
1394#define HAVE_STRUCT_UCRED_UID
1395 struct sockpeercred cred;
1396#else
1397 struct ucred cred;
1398#endif
1399 socklen_t len = sizeof(cred);
1400#endif
1401#if defined(HAVE_GETPEEREID)
1402 uid_t uid;
1403 gid_t gid;
1404#else
1405 int uid, gid;
1406#endif
1407 int result;
1408
1409 result = read(fd, buffer, size);
1410 if (result < 0) {
1411 return result;
1412 }
1413
1414#if defined(SO_PEERCRED) && (defined(HAVE_STRUCT_UCRED_UID) || defined(HAVE_STRUCT_UCRED_CR_UID))
1415 if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &cred, &len)) {
1416 return result;
1417 }
1418#if defined(HAVE_STRUCT_UCRED_UID)
1419 uid = cred.uid;
1420 gid = cred.gid;
1421#else /* defined(HAVE_STRUCT_UCRED_CR_UID) */
1422 uid = cred.cr_uid;
1423 gid = cred.cr_gid;
1424#endif /* defined(HAVE_STRUCT_UCRED_UID) */
1425
1426#elif defined(HAVE_GETPEEREID)
1427 if (getpeereid(fd, &uid, &gid)) {
1428 return result;
1429 }
1430#else
1431 return result;
1432#endif
1433 con->uid = uid;
1434 con->gid = gid;
1435
1436 return result;
1437}
1438
1439/* This is the thread running the remote console on the main process. */
1440static void *netconsole(void *vconsole)
1441{
1442 struct console *con = vconsole;
1443 char hostname[MAXHOSTNAMELEN] = "";
1444 char inbuf[512];
1445 char outbuf[512];
1446 const char * const end_buf = inbuf + sizeof(inbuf);
1447 char *start_read = inbuf;
1448 int res;
1449 struct pollfd fds[2];
1450
1451 if (gethostname(hostname, sizeof(hostname)-1))
1452 ast_copy_string(hostname, "<Unknown>", sizeof(hostname));
1453 snprintf(outbuf, sizeof(outbuf), "%s/%ld/%s\n", hostname, (long)ast_mainpid, ast_get_version());
1454 fdprint(con->fd, outbuf);
1456 for (;;) {
1457 fds[0].fd = con->fd;
1458 fds[0].events = POLLIN;
1459 fds[0].revents = 0;
1460 fds[1].fd = con->p[0];
1461 fds[1].events = POLLIN;
1462 fds[1].revents = 0;
1463
1464 res = ast_poll(fds, 2, -1);
1465 if (res < 0) {
1466 if (errno != EINTR)
1467 ast_log(LOG_WARNING, "poll returned < 0: %s\n", strerror(errno));
1468 continue;
1469 }
1470 if (fds[0].revents) {
1471 int cmds_read, bytes_read;
1472 if ((bytes_read = read_credentials(con->fd, start_read, end_buf - start_read, con)) < 1) {
1473 break;
1474 }
1475 /* XXX This will only work if it is the first command, and I'm not sure fixing it is worth the effort. */
1476 if (strncmp(inbuf, "cli quit after ", 15) == 0) {
1477 ast_cli_command_multiple_full(con->uid, con->gid, con->fd, bytes_read - 15, inbuf + 15);
1478 break;
1479 }
1480 /* ast_cli_command_multiple_full will only process individual commands terminated by a
1481 * NULL and not trailing partial commands. */
1482 if (!(cmds_read = ast_cli_command_multiple_full(con->uid, con->gid, con->fd, bytes_read + start_read - inbuf, inbuf))) {
1483 /* No commands were read. We either have a short read on the first command
1484 * with space left, or a command that is too long */
1485 if (start_read + bytes_read < end_buf) {
1486 start_read += bytes_read;
1487 } else {
1488 ast_log(LOG_ERROR, "Command too long! Skipping\n");
1489 start_read = inbuf;
1490 }
1491 continue;
1492 }
1493 if (start_read[bytes_read - 1] == '\0') {
1494 /* The read ended on a command boundary, start reading again at the head of inbuf */
1495 start_read = inbuf;
1496 continue;
1497 }
1498 /* If we get this far, we have left over characters that have not been processed.
1499 * Advance to the character after the last command read by ast_cli_command_multiple_full.
1500 * We are guaranteed to have at least cmds_read NULLs */
1501 while (cmds_read-- && (start_read = strchr(start_read, '\0'))) {
1502 start_read++;
1503 }
1504 memmove(inbuf, start_read, end_buf - start_read);
1505 start_read = end_buf - start_read + inbuf;
1506 }
1507 if (fds[1].revents) {
1508 res = read_credentials(con->p[0], outbuf, sizeof(outbuf), con);
1509 if (res < 1) {
1510 ast_log(LOG_ERROR, "read returned %d\n", res);
1511 break;
1512 }
1513 res = write(con->fd, outbuf, res);
1514 if (res < 1)
1515 break;
1516 }
1517 }
1519 if (!ast_opt_hide_connect) {
1520 ast_verb(3, "Remote UNIX connection disconnected\n");
1521 }
1522 close(con->fd);
1523 close(con->p[0]);
1524 close(con->p[1]);
1525 con->fd = -1;
1526
1527 return NULL;
1528}
1529
1530static void *listener(void *unused)
1531{
1532 struct sockaddr_un sunaddr;
1533 int s;
1534 socklen_t len;
1535 int x;
1536 int poll_result;
1537 struct pollfd fds[1];
1538
1539 for (;;) {
1540 if (ast_socket < 0) {
1541 return NULL;
1542 }
1543 fds[0].fd = ast_socket;
1544 fds[0].events = POLLIN;
1545 poll_result = ast_poll(fds, 1, -1);
1546 pthread_testcancel();
1547 if (poll_result < 0) {
1548 if (errno != EINTR) {
1549 ast_log(LOG_WARNING, "poll returned error: %s\n", strerror(errno));
1550 }
1551 continue;
1552 }
1553 len = sizeof(sunaddr);
1554 s = accept(ast_socket, (struct sockaddr *)&sunaddr, &len);
1555 if (s < 0) {
1556 if (errno != EINTR)
1557 ast_log(LOG_WARNING, "Accept returned %d: %s\n", s, strerror(errno));
1558 } else {
1559#if defined(SO_PASSCRED)
1560 int sckopt = 1;
1561 /* turn on socket credentials passing. */
1562 if (setsockopt(s, SOL_SOCKET, SO_PASSCRED, &sckopt, sizeof(sckopt)) < 0) {
1563 ast_log(LOG_WARNING, "Unable to turn on socket credentials passing\n");
1564 close(s);
1565 } else
1566#endif
1567 {
1568 for (x = 0; x < AST_MAX_CONNECTS; x++) {
1569 if (consoles[x].fd >= 0) {
1570 continue;
1571 }
1572 if (socketpair(AF_LOCAL, SOCK_STREAM, 0, consoles[x].p)) {
1573 ast_log(LOG_ERROR, "Unable to create pipe: %s\n", strerror(errno));
1574 fdprint(s, "Server failed to create pipe\n");
1575 close(s);
1576 break;
1577 }
1578 ast_fd_set_flags(consoles[x].p[1], O_NONBLOCK);
1579 consoles[x].mute = 1; /* Default is muted, we will un-mute if necessary */
1580 /* Default uid and gid to -2, so then in cli.c/cli_has_permissions() we will be able
1581 to know if the user didn't send the credentials. */
1582 consoles[x].uid = -2;
1583 consoles[x].gid = -2;
1584 /* Server default of remote console verbosity level is OFF. */
1585 consoles[x].option_verbose = 0;
1586 consoles[x].fd = s;
1588 consoles[x].fd = -1;
1589 ast_log(LOG_ERROR, "Unable to spawn thread to handle connection: %s\n", strerror(errno));
1590 close(consoles[x].p[0]);
1591 close(consoles[x].p[1]);
1592 fdprint(s, "Server failed to spawn thread\n");
1593 close(s);
1594 }
1595 break;
1596 }
1597 if (x >= AST_MAX_CONNECTS) {
1598 fdprint(s, "No more connections allowed\n");
1599 ast_log(LOG_WARNING, "No more connections allowed\n");
1600 close(s);
1601 } else if ((consoles[x].fd > -1) && (!ast_opt_hide_connect)) {
1602 ast_verb(3, "Remote UNIX connection\n");
1603 }
1604 }
1605 }
1606 }
1607 return NULL;
1608}
1609
1610static int ast_makesocket(void)
1611{
1612 struct sockaddr_un sunaddr;
1613 int res;
1614 int x;
1615 uid_t uid = -1;
1616 gid_t gid = -1;
1617
1618 for (x = 0; x < AST_MAX_CONNECTS; x++) {
1619 consoles[x].fd = -1;
1620 }
1621
1622 if (ast_socket_is_sd) {
1624
1625 goto start_lthread;
1626 }
1627
1628 unlink(ast_config_AST_SOCKET);
1629 ast_socket = socket(PF_LOCAL, SOCK_STREAM, 0);
1630 if (ast_socket < 0) {
1631 ast_log(LOG_WARNING, "Unable to create control socket: %s\n", strerror(errno));
1632 return -1;
1633 }
1634 memset(&sunaddr, 0, sizeof(sunaddr));
1635 sunaddr.sun_family = AF_LOCAL;
1636 ast_copy_string(sunaddr.sun_path, ast_config_AST_SOCKET, sizeof(sunaddr.sun_path));
1637 res = bind(ast_socket, (struct sockaddr *)&sunaddr, sizeof(sunaddr));
1638 if (res) {
1639 ast_log(LOG_WARNING, "Unable to bind socket to %s: %s\n", ast_config_AST_SOCKET, strerror(errno));
1640 close(ast_socket);
1641 ast_socket = -1;
1642 return -1;
1643 }
1644 res = listen(ast_socket, 2);
1645 if (res < 0) {
1646 ast_log(LOG_WARNING, "Unable to listen on socket %s: %s\n", ast_config_AST_SOCKET, strerror(errno));
1647 close(ast_socket);
1648 ast_socket = -1;
1649 return -1;
1650 }
1651
1652start_lthread:
1654 ast_log(LOG_WARNING, "Unable to create listener thread.\n");
1655 close(ast_socket);
1656 return -1;
1657 }
1658
1659 if (ast_socket_is_sd) {
1660 /* owner/group/permissions are set by systemd, we might not even have access
1661 * to socket file so leave it alone */
1662 return 0;
1663 }
1664
1666 struct passwd *pw;
1667 if ((pw = getpwnam(ast_config_AST_CTL_OWNER)) == NULL)
1668 ast_log(LOG_WARNING, "Unable to find uid of user %s\n", ast_config_AST_CTL_OWNER);
1669 else
1670 uid = pw->pw_uid;
1671 }
1672
1674 struct group *grp;
1675 if ((grp = getgrnam(ast_config_AST_CTL_GROUP)) == NULL)
1676 ast_log(LOG_WARNING, "Unable to find gid of group %s\n", ast_config_AST_CTL_GROUP);
1677 else
1678 gid = grp->gr_gid;
1679 }
1680
1681 if (chown(ast_config_AST_SOCKET, uid, gid) < 0)
1682 ast_log(LOG_WARNING, "Unable to change ownership of %s: %s\n", ast_config_AST_SOCKET, strerror(errno));
1683
1685 unsigned int p1;
1686 mode_t p;
1687 sscanf(ast_config_AST_CTL_PERMISSIONS, "%30o", &p1);
1688 p = p1;
1689 if ((chmod(ast_config_AST_SOCKET, p)) < 0)
1690 ast_log(LOG_WARNING, "Unable to change file permissions of %s: %s\n", ast_config_AST_SOCKET, strerror(errno));
1691 }
1692
1693 return 0;
1694}
1695
1696static int ast_tryconnect(void)
1697{
1698 struct sockaddr_un sunaddr;
1699 int res;
1700 ast_consock = socket(PF_LOCAL, SOCK_STREAM, 0);
1701 if (ast_consock < 0) {
1702 fprintf(stderr, "Unable to create socket: %s\n", strerror(errno));
1703 return 0;
1704 }
1705 memset(&sunaddr, 0, sizeof(sunaddr));
1706 sunaddr.sun_family = AF_LOCAL;
1707 ast_copy_string(sunaddr.sun_path, ast_config_AST_SOCKET, sizeof(sunaddr.sun_path));
1708 res = connect(ast_consock, (struct sockaddr *)&sunaddr, sizeof(sunaddr));
1709 if (res) {
1710 close(ast_consock);
1711 ast_consock = -1;
1712 return 0;
1713 } else
1714 return 1;
1715}
1716
1717/*! \brief Urgent handler
1718 *
1719 * Called by soft_hangup to interrupt the poll, read, or other
1720 * system call. We don't actually need to do anything though.
1721 * Remember: Cannot EVER ast_log from within a signal handler
1722 */
1723static void _urg_handler(int num)
1724{
1725 return;
1726}
1727
1728static struct sigaction urg_handler = {
1729 .sa_handler = _urg_handler,
1730};
1731
1732static void _hup_handler(int num)
1733{
1734 int save_errno = errno;
1735
1736 if (restartnow) {
1737 if (el) {
1738 el_end(el);
1739 }
1740 execvp(_argv[0], _argv);
1741 }
1742
1743 printf("Received HUP signal -- Reloading configs\n");
1744 sig_flags.need_reload = 1;
1746 fprintf(stderr, "hup_handler: write() failed: %s\n", strerror(errno));
1747 }
1748 errno = save_errno;
1749}
1750
1751static struct sigaction hup_handler = {
1752 .sa_handler = _hup_handler,
1753 .sa_flags = SA_RESTART,
1754};
1755
1756static void _child_handler(int sig)
1757{
1758 /* Must not ever ast_log or ast_verbose within signal handler */
1759 int n, status, save_errno = errno;
1760
1761 /*
1762 * Reap all dead children -- not just one
1763 */
1764 for (n = 0; waitpid(-1, &status, WNOHANG) > 0; n++)
1765 ;
1766 if (n == 0 && option_debug)
1767 printf("Huh? Child handler, but nobody there?\n");
1768 errno = save_errno;
1769}
1770
1771static struct sigaction child_handler = {
1772 .sa_handler = _child_handler,
1773 .sa_flags = SA_RESTART,
1774};
1775
1776/*! \brief Set an X-term or screen title */
1777static void set_title(char *text)
1778{
1779 if (getenv("TERM") && strstr(getenv("TERM"), "xterm"))
1780 fprintf(stdout, "\033]2;%s\007", text);
1781}
1782
1783static void set_icon(char *text)
1784{
1785 if (getenv("TERM") && strstr(getenv("TERM"), "xterm"))
1786 fprintf(stdout, "\033]1;%s\007", text);
1787}
1788
1789/*! \brief Check whether we were set to high(er) priority. */
1790static int has_priority(void)
1791{
1792 /* Neither of these calls should fail with these arguments. */
1793#ifdef __linux__
1794 /* For SCHED_OTHER, SCHED_BATCH and SCHED_IDLE, this will return
1795 * 0. For the realtime priorities SCHED_RR and SCHED_FIFO, it
1796 * will return something >= 1. */
1797 return sched_getscheduler(0);
1798#else
1799 /* getpriority() can return a value in -20..19 (or even -INF..20)
1800 * where negative numbers are high priority. We don't bother
1801 * checking errno. If the query fails and it returns -1, we'll
1802 * assume that we're running at high prio; a safe assumption
1803 * that will enable the resource starvation monitor (canary)
1804 * just in case. */
1805 return (getpriority(PRIO_PROCESS, 0) < 0);
1806#endif
1807}
1808
1809/*! \brief Set priority on all known threads. */
1810static int set_priority_all(int pri)
1811{
1812#if !defined(__linux__)
1813 /* The non-linux version updates the entire process prio. */
1814 return ast_set_priority(pri);
1815#elif defined(LOW_MEMORY)
1816 ast_log(LOG_WARNING, "Unable to enumerate all threads to update priority\n");
1817 return ast_set_priority(pri);
1818#else
1819 struct thread_list_t *cur;
1820 struct sched_param sched;
1821 char const *policy_str;
1822 int policy;
1823
1824 memset(&sched, 0, sizeof(sched));
1825 if (pri) {
1826 policy = SCHED_RR;
1827 policy_str = "realtime";
1828 sched.sched_priority = 10;
1829 } else {
1830 policy = SCHED_OTHER;
1831 policy_str = "regular";
1832 sched.sched_priority = 0;
1833 }
1834 if (sched_setscheduler(getpid(), policy, &sched)) {
1835 ast_log(LOG_WARNING, "Unable to set %s thread priority on main thread\n", policy_str);
1836 return -1;
1837 }
1838 ast_verb(1, "Setting %s thread priority on all threads\n", policy_str);
1840 AST_RWLIST_TRAVERSE(&thread_list, cur, list) {
1841 /* Don't care about the return value. It should work. */
1842 sched_setscheduler(cur->lwp, policy, &sched);
1843 }
1845 return 0;
1846#endif
1847}
1848
1849/*! \brief We set ourselves to a high priority, that we might pre-empt
1850 * everything else. If your PBX has heavy activity on it, this is a
1851 * good thing.
1852 */
1854{
1855 struct sched_param sched;
1856 memset(&sched, 0, sizeof(sched));
1857#ifdef __linux__
1858 if (pri) {
1859 sched.sched_priority = 10;
1860 if (sched_setscheduler(0, SCHED_RR, &sched)) {
1861 return -1;
1862 }
1863 } else {
1864 sched.sched_priority = 0;
1865 /* According to the manpage, these parameters can never fail. */
1866 sched_setscheduler(0, SCHED_OTHER, &sched);
1867 }
1868#else
1869 if (pri) {
1870 if (setpriority(PRIO_PROCESS, 0, -10) == -1) {
1871 ast_log(LOG_WARNING, "Unable to set high priority\n");
1872 return -1;
1873 } else
1874 ast_verb(1, "Set to high priority\n");
1875 } else {
1876 /* According to the manpage, these parameters can never fail. */
1877 setpriority(PRIO_PROCESS, 0, 0);
1878 }
1879#endif
1880 return 0;
1881}
1882
1884{
1886}
1887
1889{
1890 return shutdown_pending;
1891}
1892
1894{
1895 int shutdown_aborted = 0;
1896
1898 if (shuttingdown >= SHUTDOWN_FAST) {
1900 shutdown_pending = 0;
1901 shutdown_aborted = 1;
1902 }
1904 return shutdown_aborted;
1905}
1906
1907/*!
1908 * \internal
1909 * \brief Initiate system shutdown -- prevents new channels from being allocated.
1910 */
1911static void ast_begin_shutdown(void)
1912{
1915 shutdown_pending = 1;
1916 }
1918}
1919
1920static int can_safely_quit(shutdown_nice_t niceness, int restart);
1921static void really_quit(int num, shutdown_nice_t niceness, int restart);
1922
1923static void quit_handler(int num, shutdown_nice_t niceness, int restart)
1924{
1925 if (can_safely_quit(niceness, restart)) {
1926 really_quit(num, niceness, restart);
1927 /* No one gets here. */
1928 }
1929 /* It wasn't our time. */
1930}
1931
1932#define SHUTDOWN_TIMEOUT 15 /* Seconds */
1933
1934/*!
1935 * \internal
1936 * \brief Wait for all channels to die, a timeout, or shutdown cancelled.
1937 * \since 13.3.0
1938 *
1939 * \param niceness Shutdown niceness in effect
1940 * \param seconds Number of seconds to wait or less than zero if indefinitely.
1941 *
1942 * \retval zero if waiting wasn't necessary. We were idle.
1943 * \retval non-zero if we had to wait.
1944 */
1945static int wait_for_channels_to_die(shutdown_nice_t niceness, int seconds)
1946{
1947 time_t start;
1948 time_t now;
1949 int waited = 0;
1950
1951 time(&start);
1952 for (;;) {
1953 if (!ast_undestroyed_channels() || shuttingdown != niceness) {
1954 break;
1955 }
1956 if (seconds < 0) {
1957 /* No timeout so just poll every second */
1958 sleep(1);
1959 } else {
1960 time(&now);
1961
1962 /* Wait up to the given seconds for all channels to go away */
1963 if (seconds < (now - start)) {
1964 break;
1965 }
1966
1967 /* Sleep 1/10 of a second */
1968 usleep(100000);
1969 }
1970 waited = 1;
1971 }
1972 return waited;
1973}
1974
1975static int can_safely_quit(shutdown_nice_t niceness, int restart)
1976{
1977 int waited = 0;
1978
1979 /* Check if someone else isn't already doing this. */
1981 if (shuttingdown != NOT_SHUTTING_DOWN && niceness >= shuttingdown) {
1982 /* Already in progress and other request was less nice. */
1984 ast_verbose("Ignoring asterisk %s request, already in progress.\n", restart ? "restart" : "shutdown");
1985 return 0;
1986 }
1987 shuttingdown = niceness;
1989
1990 /* Try to get as many CDRs as possible submitted to the backend engines
1991 * (if in batch mode). really_quit happens to call it again when running
1992 * the atexit handlers, otherwise this would be a bit early. */
1994
1995 /*
1996 * Shutdown the message queue for the technology agnostic message channel.
1997 * This has to occur before we pause shutdown pending ast_undestroyed_channels.
1998 *
1999 * XXX This is not reversed on shutdown cancel.
2000 */
2002
2003 if (niceness == SHUTDOWN_NORMAL) {
2004 /* Begin shutdown routine, hanging up active channels */
2006 if (ast_opt_console) {
2007 ast_verb(0, "Beginning asterisk %s....\n", restart ? "restart" : "shutdown");
2008 }
2010 waited |= wait_for_channels_to_die(niceness, SHUTDOWN_TIMEOUT);
2011 } else if (niceness >= SHUTDOWN_NICE) {
2012 if (niceness != SHUTDOWN_REALLY_NICE) {
2014 }
2015 if (ast_opt_console) {
2016 ast_verb(0, "Waiting for inactivity to perform %s...\n", restart ? "restart" : "halt");
2017 }
2018 waited |= wait_for_channels_to_die(niceness, -1);
2019 }
2020
2021 /* Re-acquire lock and check if someone changed the niceness, in which
2022 * case someone else has taken over the shutdown.
2023 */
2025 if (shuttingdown != niceness) {
2027 ast_verb(0, "Asterisk %s cancelled.\n", restart ? "restart" : "shutdown");
2028 }
2030 return 0;
2031 }
2032
2033 if (niceness >= SHUTDOWN_REALLY_NICE) {
2036
2037 /* No more Mr. Nice guy. We are committed to shutting down now. */
2041
2043 }
2046
2047 if (niceness >= SHUTDOWN_NORMAL && waited) {
2048 /*
2049 * We were not idle. Give things in progress a chance to
2050 * recognize the final shutdown phase.
2051 */
2052 sleep(1);
2053 }
2054 return 1;
2055}
2056
2057/*! Called when exiting is certain. */
2058static void really_quit(int num, shutdown_nice_t niceness, int restart)
2059{
2060 int active_channels;
2061 struct ast_json *json_object = NULL;
2062 int run_cleanups = niceness >= SHUTDOWN_NICE;
2063
2064 if (run_cleanups && modules_shutdown()) {
2065 ast_verb(0, "Some modules could not be unloaded, switching to fast shutdown\n");
2066 run_cleanups = 0;
2067 }
2068
2069 if (!restart && !ast_opt_remote) {
2070 ast_sd_notify("STOPPING=1");
2071 }
2074 if (consolethread == AST_PTHREADT_NULL || consolethread == pthread_self()) {
2075 /* Only end if we are the consolethread, otherwise there's a race with that thread. */
2076 if (el != NULL) {
2077 el_end(el);
2078 }
2079 if (el_hist != NULL) {
2080 history_end(el_hist);
2081 }
2082 } else if (!restart) {
2083 sig_flags.need_el_end = 1;
2084 pthread_kill(consolethread, SIGURG);
2085 }
2086 }
2088 /* Don't publish messages if we're a remote console - we won't have all of the Stasis
2089 * topics or message types
2090 */
2091 if (!ast_opt_remote) {
2092 json_object = ast_json_pack("{s: s, s: s}",
2093 "Shutdown", active_channels ? "Uncleanly" : "Cleanly",
2094 "Restart", restart ? "True" : "False");
2095 ast_manager_publish_event("Shutdown", EVENT_FLAG_SYSTEM, json_object);
2096 ast_json_unref(json_object);
2097 json_object = NULL;
2098 }
2099 ast_verb(0, "Asterisk %s ending (%d).\n",
2100 active_channels ? "uncleanly" : "cleanly", num);
2101
2102 ast_verb(0, "Executing last minute cleanups\n");
2103 ast_run_atexits(run_cleanups);
2104
2105 ast_debug(1, "Asterisk ending (%d).\n", num);
2106 if (ast_socket > -1) {
2107 pthread_cancel(lthread);
2108 close(ast_socket);
2109 ast_socket = -1;
2110 if (!ast_socket_is_sd) {
2111 unlink(ast_config_AST_SOCKET);
2112 }
2113 pthread_kill(lthread, SIGURG);
2114 pthread_join(lthread, NULL);
2115 }
2116 if (ast_consock > -1)
2117 close(ast_consock);
2118 if (!ast_opt_remote)
2119 unlink(ast_config_AST_PID);
2121 printf("%s", term_quit());
2122 if (restart) {
2123 int i;
2124 ast_verb(0, "Preparing for Asterisk restart...\n");
2125 /* Mark all FD's for closing on exec */
2126 for (i = 3; i < 32768; i++) {
2127 fcntl(i, F_SETFD, FD_CLOEXEC);
2128 }
2129 ast_verb(0, "Asterisk is now restarting...\n");
2130 restartnow = 1;
2131
2132 /* close logger */
2133 close_logger();
2135
2136 /* If there is a consolethread running send it a SIGHUP
2137 so it can execvp, otherwise we can do it ourselves */
2138 if ((consolethread != AST_PTHREADT_NULL) && (consolethread != pthread_self())) {
2139 pthread_kill(consolethread, SIGHUP);
2140 /* Give the signal handler some time to complete */
2141 sleep(2);
2142 } else
2143 execvp(_argv[0], _argv);
2144
2145 } else {
2146 /* close logger */
2147 close_logger();
2149 }
2150
2151 exit(0);
2152}
2153
2154static void __quit_handler(int num)
2155{
2156 sig_flags.need_quit = 1;
2158 fprintf(stderr, "quit_handler: write() failed: %s\n", strerror(errno));
2159 }
2160 /* There is no need to restore the signal handler here, since the app
2161 * is going to exit */
2162}
2163
2164static void __remote_quit_handler(int num)
2165{
2166 sig_flags.need_quit = 1;
2167}
2168
2169static void set_header(char *outbuf, int maxout, char level)
2170{
2171 const char *cmp;
2172 char date[40];
2173
2174 switch (level) {
2175 case 0: cmp = NULL;
2176 break;
2177 case 1: cmp = VERBOSE_PREFIX_1;
2178 break;
2179 case 2: cmp = VERBOSE_PREFIX_2;
2180 break;
2181 case 3: cmp = VERBOSE_PREFIX_3;
2182 break;
2183 case 4: cmp = VERBOSE_PREFIX_4;
2184 break;
2185 case 5: cmp = VERBOSE_PREFIX_5;
2186 break;
2187 case 6: cmp = VERBOSE_PREFIX_6;
2188 break;
2189 case 7: cmp = VERBOSE_PREFIX_7;
2190 break;
2191 case 8: cmp = VERBOSE_PREFIX_8;
2192 break;
2193 case 9: cmp = VERBOSE_PREFIX_9;
2194 break;
2195 default: cmp = VERBOSE_PREFIX_10;
2196 break;
2197 }
2198
2199 if (ast_opt_timestamp) {
2200 struct ast_tm tm;
2201 struct timeval now = ast_tvnow();
2202 ast_localtime(&now, &tm, NULL);
2203 ast_strftime(date, sizeof(date), ast_logger_get_dateformat(), &tm);
2204 }
2205
2206 snprintf(outbuf, maxout, "%s%s%s%s%s%s",
2207 ast_opt_timestamp ? "[" : "",
2208 ast_opt_timestamp ? date : "",
2209 ast_opt_timestamp ? "] " : "",
2210 cmp ? ast_term_color(COLOR_GRAY, 0) : "",
2211 cmp ? cmp : "",
2212 cmp ? ast_term_reset() : "");
2213}
2214
2217};
2218
2219static int console_state_init(void *ptr)
2220{
2221 struct console_state_data *state = ptr;
2222 state->verbose_line_level = 0;
2223 return 0;
2224}
2225
2227
2228static int console_print(const char *s)
2229{
2230 struct console_state_data *state =
2232
2233 char prefix[80];
2234 const char *c;
2235 int num, res = 0;
2236 unsigned int newline;
2237
2238 do {
2239 if (VERBOSE_HASMAGIC(s)) {
2240
2241 /* always use the given line's level, otherwise
2242 we'll use the last line's level */
2243 state->verbose_line_level = VERBOSE_MAGIC2LEVEL(s);
2244
2245 /* move past magic */
2246 s++;
2247
2248 set_header(prefix, sizeof(prefix), state->verbose_line_level);
2249 } else {
2250 *prefix = '\0';
2251 }
2252 c = s;
2253
2254 /* for a given line separate on verbose magic, newline, and eol */
2255 if ((s = strchr(c, '\n'))) {
2256 ++s;
2257 newline = 1;
2258 } else {
2259 s = strchr(c, '\0');
2260 newline = 0;
2261 }
2262
2263 /* check if we should write this line after calculating begin/end
2264 so we process the case of a higher level line embedded within
2265 two lower level lines */
2266 if (state->verbose_line_level > option_verbose) {
2267 continue;
2268 }
2269
2270 if (!ast_strlen_zero(prefix)) {
2271 fputs(prefix, stdout);
2272 }
2273
2274 num = s - c;
2275 if (fwrite(c, sizeof(char), num, stdout) < num) {
2276 break;
2277 }
2278
2279 if (!res) {
2280 /* if at least some info has been written
2281 we'll want to return true */
2282 res = 1;
2283 }
2284 } while (*s);
2285
2286 if (newline) {
2287 /* if ending on a newline then reset last level to zero
2288 since what follows may be not be logging output */
2289 state->verbose_line_level = 0;
2290 }
2291
2292 if (res) {
2293 fflush(stdout);
2294 }
2295
2296 return res;
2297}
2298
2299static int ast_all_zeros(const char *s)
2300{
2301 while (*s) {
2302 if (*s > 32)
2303 return 0;
2304 s++;
2305 }
2306 return 1;
2307}
2308
2309/* This is the main console CLI command handler. Run by the main() thread. */
2310static void consolehandler(const char *s)
2311{
2312 printf("%s", term_end());
2313 fflush(stdout);
2314
2315 /* Called when readline data is available */
2316 if (!ast_all_zeros(s))
2318 /* The real handler for bang */
2319 if (s[0] == '!') {
2320 if (s[1])
2321 ast_safe_system(s+1);
2322 else
2323 ast_safe_system(getenv("SHELL") ? getenv("SHELL") : "/bin/sh");
2324 } else
2325 ast_cli_command(STDOUT_FILENO, s);
2326}
2327
2328static int remoteconsolehandler(const char *s)
2329{
2330 int ret = 0;
2331
2332 /* Called when readline data is available */
2333 if (!ast_all_zeros(s))
2335
2336 while (isspace(*s)) {
2337 s++;
2338 }
2339
2340 /* The real handler for bang */
2341 if (s[0] == '!') {
2343 printf("Shell access is disabled on remote consoles\n");
2344 return 1;
2345 }
2346 if (s[1])
2347 ast_safe_system(s+1);
2348 else
2349 ast_safe_system(getenv("SHELL") ? getenv("SHELL") : "/bin/sh");
2350 ret = 1;
2351 } else if ((strncasecmp(s, "quit", 4) == 0 || strncasecmp(s, "exit", 4) == 0) &&
2352 (s[4] == '\0' || isspace(s[4]))) {
2354 ret = 1;
2355 }
2356
2357 return ret;
2358}
2359
2360static char *handle_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2361{
2362 switch (cmd) {
2363 case CLI_INIT:
2364 e->command = "core show version";
2365 e->usage =
2366 "Usage: core show version\n"
2367 " Shows Asterisk version information.\n";
2368 return NULL;
2369 case CLI_GENERATE:
2370 return NULL;
2371 }
2372
2373 if (a->argc != 3)
2374 return CLI_SHOWUSAGE;
2375 ast_cli(a->fd, "Asterisk %s built by %s @ %s on a %s running %s on %s\n",
2378 return CLI_SUCCESS;
2379}
2380
2381static char *handle_stop_now(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2382{
2383 switch (cmd) {
2384 case CLI_INIT:
2385 e->command = "core stop now";
2386 e->usage =
2387 "Usage: core stop now\n"
2388 " Shuts down a running Asterisk immediately, hanging up all active calls .\n";
2390 return NULL;
2391 case CLI_GENERATE:
2392 return NULL;
2393 }
2394
2395 if (a->argc != e->args)
2396 return CLI_SHOWUSAGE;
2397 quit_handler(0, SHUTDOWN_NORMAL, 0 /* not restart */);
2398 return CLI_SUCCESS;
2399}
2400
2401static char *handle_stop_gracefully(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2402{
2403 switch (cmd) {
2404 case CLI_INIT:
2405 e->command = "core stop gracefully";
2406 e->usage =
2407 "Usage: core stop gracefully\n"
2408 " Causes Asterisk to not accept new calls, and exit when all\n"
2409 " active calls have terminated normally.\n";
2411 return NULL;
2412 case CLI_GENERATE:
2413 return NULL;
2414 }
2415
2416 if (a->argc != e->args)
2417 return CLI_SHOWUSAGE;
2418 quit_handler(0, SHUTDOWN_NICE, 0 /* no restart */);
2419 return CLI_SUCCESS;
2420}
2421
2422static char *handle_stop_when_convenient(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2423{
2424 switch (cmd) {
2425 case CLI_INIT:
2426 e->command = "core stop when convenient";
2427 e->usage =
2428 "Usage: core stop when convenient\n"
2429 " Causes Asterisk to perform a shutdown when all active calls have ended.\n";
2431 return NULL;
2432 case CLI_GENERATE:
2433 return NULL;
2434 }
2435
2436 if (a->argc != e->args)
2437 return CLI_SHOWUSAGE;
2438 ast_cli(a->fd, "Waiting for inactivity to perform halt\n");
2439 quit_handler(0, SHUTDOWN_REALLY_NICE, 0 /* don't restart */);
2440 return CLI_SUCCESS;
2441}
2442
2443static char *handle_restart_now(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2444{
2445 switch (cmd) {
2446 case CLI_INIT:
2447 e->command = "core restart now";
2448 e->usage =
2449 "Usage: core restart now\n"
2450 " Causes Asterisk to hangup all calls and exec() itself performing a cold\n"
2451 " restart.\n";
2453 return NULL;
2454 case CLI_GENERATE:
2455 return NULL;
2456 }
2457
2458 if (a->argc != e->args)
2459 return CLI_SHOWUSAGE;
2460 quit_handler(0, SHUTDOWN_NORMAL, 1 /* restart */);
2461 return CLI_SUCCESS;
2462}
2463
2464static char *handle_restart_gracefully(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2465{
2466 switch (cmd) {
2467 case CLI_INIT:
2468 e->command = "core restart gracefully";
2469 e->usage =
2470 "Usage: core restart gracefully\n"
2471 " Causes Asterisk to stop accepting new calls and exec() itself performing a cold\n"
2472 " restart when all active calls have ended.\n";
2474 return NULL;
2475 case CLI_GENERATE:
2476 return NULL;
2477 }
2478
2479 if (a->argc != e->args)
2480 return CLI_SHOWUSAGE;
2481 quit_handler(0, SHUTDOWN_NICE, 1 /* restart */);
2482 return CLI_SUCCESS;
2483}
2484
2485static char *handle_restart_when_convenient(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2486{
2487 switch (cmd) {
2488 case CLI_INIT:
2489 e->command = "core restart when convenient";
2490 e->usage =
2491 "Usage: core restart when convenient\n"
2492 " Causes Asterisk to perform a cold restart when all active calls have ended.\n";
2494 return NULL;
2495 case CLI_GENERATE:
2496 return NULL;
2497 }
2498
2499 if (a->argc != e->args)
2500 return CLI_SHOWUSAGE;
2501 ast_cli(a->fd, "Waiting for inactivity to perform restart\n");
2502 quit_handler(0, SHUTDOWN_REALLY_NICE, 1 /* restart */);
2503 return CLI_SUCCESS;
2504}
2505
2506static char *handle_abort_shutdown(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2507{
2508 switch (cmd) {
2509 case CLI_INIT:
2510 e->command = "core abort shutdown";
2511 e->usage =
2512 "Usage: core abort shutdown\n"
2513 " Causes Asterisk to abort an executing shutdown or restart, and resume normal\n"
2514 " call operations.\n";
2516 return NULL;
2517 case CLI_GENERATE:
2518 return NULL;
2519 }
2520
2521 if (a->argc != e->args)
2522 return CLI_SHOWUSAGE;
2523
2525
2526 return CLI_SUCCESS;
2527}
2528
2529static char *handle_bang(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2530{
2531 switch (cmd) {
2532 case CLI_INIT:
2533 e->command = "!";
2534 e->usage =
2535 "Usage: !<command>\n"
2536 " Executes a given shell command\n";
2537 return NULL;
2538 case CLI_GENERATE:
2539 return NULL;
2540 }
2541
2542 return CLI_SUCCESS;
2543}
2544static const char warranty_lines[] = {
2545 "\n"
2546 " NO WARRANTY\n"
2547 "\n"
2548 "BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY\n"
2549 "FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN\n"
2550 "OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES\n"
2551 "PROVIDE THE PROGRAM \"AS IS\" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED\n"
2552 "OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF\n"
2553 "MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS\n"
2554 "TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE\n"
2555 "PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING,\n"
2556 "REPAIR OR CORRECTION.\n"
2557 "\n"
2558 "IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING\n"
2559 "WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR\n"
2560 "REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES,\n"
2561 "INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING\n"
2562 "OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED\n"
2563 "TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY\n"
2564 "YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER\n"
2565 "PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE\n"
2566 "POSSIBILITY OF SUCH DAMAGES.\n"
2567};
2568
2569static char *show_warranty(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2570{
2571 switch (cmd) {
2572 case CLI_INIT:
2573 e->command = "core show warranty";
2574 e->usage =
2575 "Usage: core show warranty\n"
2576 " Shows the warranty (if any) for this copy of Asterisk.\n";
2577 return NULL;
2578 case CLI_GENERATE:
2579 return NULL;
2580 }
2581
2582 ast_cli(a->fd, "%s", warranty_lines);
2583
2584 return CLI_SUCCESS;
2585}
2586
2587static const char license_lines[] = {
2588 "\n"
2589 "This program is free software; you can redistribute it and/or modify\n"
2590 "it under the terms of the GNU General Public License version 2 as\n"
2591 "published by the Free Software Foundation.\n"
2592 "\n"
2593 "This program also contains components licensed under other licenses.\n"
2594 "They include:\n"
2595 "\n"
2596 "This program is distributed in the hope that it will be useful,\n"
2597 "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
2598 "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n"
2599 "GNU General Public License for more details.\n"
2600 "\n"
2601 "You should have received a copy of the GNU General Public License\n"
2602 "along with this program; if not, write to the Free Software\n"
2603 "Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA\n"
2604};
2605
2606static char *show_license(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
2607{
2608 switch (cmd) {
2609 case CLI_INIT:
2610 e->command = "core show license";
2611 e->usage =
2612 "Usage: core show license\n"
2613 " Shows the license(s) for this copy of Asterisk.\n";
2614 return NULL;
2615 case CLI_GENERATE:
2616 return NULL;
2617 }
2618
2619 ast_cli(a->fd, "%s", license_lines);
2620
2621 return CLI_SUCCESS;
2622}
2623
2624#define ASTERISK_PROMPT "*CLI> "
2625
2626/*!
2627 * \brief Shutdown Asterisk CLI commands.
2628 *
2629 * \note These CLI commands cannot be unregistered at shutdown
2630 * because one of them is likely the reason for the shutdown.
2631 * The CLI generates a warning if a command is in-use when it is
2632 * unregistered.
2633 */
2635 AST_CLI_DEFINE(handle_stop_now, "Shut down Asterisk immediately"),
2636 AST_CLI_DEFINE(handle_stop_gracefully, "Gracefully shut down Asterisk"),
2637 AST_CLI_DEFINE(handle_stop_when_convenient, "Shut down Asterisk at empty call volume"),
2638 AST_CLI_DEFINE(handle_restart_now, "Restart Asterisk immediately"),
2639 AST_CLI_DEFINE(handle_restart_gracefully, "Restart Asterisk gracefully"),
2640 AST_CLI_DEFINE(handle_restart_when_convenient, "Restart Asterisk at empty call volume"),
2641};
2642
2643static struct ast_cli_entry cli_asterisk[] = {
2644 AST_CLI_DEFINE(handle_abort_shutdown, "Cancel a running shutdown"),
2645 AST_CLI_DEFINE(show_warranty, "Show the warranty (if any) for this copy of Asterisk"),
2646 AST_CLI_DEFINE(show_license, "Show the license(s) for this copy of Asterisk"),
2647 AST_CLI_DEFINE(handle_version, "Display version info"),
2648 AST_CLI_DEFINE(handle_bang, "Execute a shell command"),
2649#if !defined(LOW_MEMORY)
2650 AST_CLI_DEFINE(handle_show_threads, "Show running threads"),
2651#if defined(HAVE_SYSINFO) || defined(HAVE_SYSCTL)
2652 AST_CLI_DEFINE(handle_show_sysinfo, "Show System Information"),
2653#endif
2654 AST_CLI_DEFINE(handle_show_profile, "Display profiling info"),
2655 AST_CLI_DEFINE(handle_show_settings, "Show some core settings"),
2656 AST_CLI_DEFINE(handle_clear_profile, "Clear profiling info"),
2657#endif /* ! LOW_MEMORY */
2658};
2659
2661{
2662 char buf[80];
2663
2664 /*
2665 * Tell the server asterisk instance about the verbose level
2666 * initially desired.
2667 */
2668 if (option_verbose) {
2669 snprintf(buf, sizeof(buf), "core set verbose atleast %d silent", option_verbose);
2671 }
2672
2673 if (option_debug) {
2674 snprintf(buf, sizeof(buf), "core set debug atleast %d", option_debug);
2676 }
2677
2678 /* Leave verbose filtering to the server. */
2679 option_verbose = INT_MAX;
2680
2681 if (!ast_opt_mute) {
2682 fdsend(ast_consock, "logger mute silent");
2683 } else {
2684 printf("log and verbose output currently muted ('logger mute' to unmute)\n");
2685 }
2686}
2687
2688#ifdef HAVE_LIBEDIT_IS_UNICODE
2689#define CHAR_T_LIBEDIT wchar_t
2690#define CHAR_TO_LIBEDIT(c) btowc(c)
2691#else
2692#define CHAR_T_LIBEDIT char
2693#define CHAR_TO_LIBEDIT(c) c
2694#endif
2695
2696static int ast_el_read_char(EditLine *editline, CHAR_T_LIBEDIT *cp)
2697{
2698 int num_read = 0;
2699 int lastpos = 0;
2700 struct pollfd fds[2];
2701 int res;
2702 int max;
2703#define EL_BUF_SIZE 512
2704 char buf[EL_BUF_SIZE];
2705
2706 for (;;) {
2707 max = 1;
2708 fds[0].fd = ast_consock;
2709 fds[0].events = POLLIN;
2710 if (!ast_opt_exec) {
2711 fds[1].fd = STDIN_FILENO;
2712 fds[1].events = POLLIN;
2713 max++;
2714 }
2715 res = ast_poll(fds, max, -1);
2716 if (res < 0) {
2717 if (sig_flags.need_quit || sig_flags.need_quit_handler || sig_flags.need_el_end) {
2718 break;
2719 }
2720 if (errno == EINTR) {
2721 continue;
2722 }
2723 fprintf(stderr, "poll failed: %s\n", strerror(errno));
2724 break;
2725 }
2726
2727 if (!ast_opt_exec && fds[1].revents) {
2728 char c = '\0';
2729
2730 num_read = read(STDIN_FILENO, &c, 1);
2731 if (num_read < 1) {
2732 break;
2733 }
2734
2735 *cp = CHAR_TO_LIBEDIT(c);
2736
2737 return num_read;
2738 }
2739
2740 if (fds[0].revents) {
2741 res = read(ast_consock, buf, sizeof(buf) - 1);
2742 /* if the remote side disappears exit */
2743 if (res < 1) {
2744 fprintf(stderr, "\nDisconnected from Asterisk server\n");
2745 if (!ast_opt_reconnect) {
2747 } else {
2748 int tries;
2749 int reconnects_per_second = 20;
2750
2751 fprintf(stderr, "Attempting to reconnect for 30 seconds\n");
2752 for (tries = 0; tries < 30 * reconnects_per_second; tries++) {
2753 if (ast_tryconnect()) {
2754 fprintf(stderr, "Reconnect succeeded after %.3f seconds\n", 1.0 / reconnects_per_second * tries);
2755 printf("%s", term_quit());
2758 break;
2759 }
2760
2761 usleep(1000000 / reconnects_per_second);
2762 }
2763 if (tries >= 30 * reconnects_per_second) {
2764 fprintf(stderr, "Failed to reconnect for 30 seconds. Quitting.\n");
2766 }
2767 }
2768 continue;
2769 }
2770
2771 buf[res] = '\0';
2772
2773 /* Write over the CLI prompt */
2774 if (!ast_opt_exec && !lastpos) {
2775 if (write(STDOUT_FILENO, "\r␛[0K", 5) < 0) {
2776 }
2777 }
2778
2780
2781 if ((res < EL_BUF_SIZE - 1) && ((buf[res-1] == '\n') || (res >= 2 && buf[res-2] == '\n'))) {
2782 *cp = CHAR_TO_LIBEDIT(CC_REFRESH);
2783
2784 return 1;
2785 }
2786 lastpos = 1;
2787 }
2788 }
2789
2790 *cp = CHAR_TO_LIBEDIT('\0');
2791
2792 return 0;
2793}
2794
2795static struct ast_str *prompt = NULL;
2796
2797static char *cli_prompt(EditLine *editline)
2798{
2799 char tmp[100];
2800 char *pfmt;
2801 int color_used = 0;
2802 static int cli_prompt_changes = 0;
2803 struct passwd *pw;
2804 struct group *gr;
2805
2806 if (prompt == NULL) {
2807 prompt = ast_str_create(100);
2808 } else if (!cli_prompt_changes) {
2809 return ast_str_buffer(prompt);
2810 } else {
2812 }
2813
2814 if ((pfmt = getenv("ASTERISK_PROMPT"))) {
2815 char *t = pfmt;
2816 struct timeval ts = ast_tvnow();
2817 while (*t != '\0') {
2818 if (*t == '%') {
2819 char hostname[MAXHOSTNAMELEN] = "";
2820 int i, which;
2821 struct ast_tm tm = { 0, };
2822 int fgcolor = COLOR_WHITE, bgcolor = COLOR_BLACK;
2823
2824 t++;
2825 switch (*t) {
2826 case 'C': /* color */
2827 t++;
2828 if (sscanf(t, "%30d;%30d%n", &fgcolor, &bgcolor, &i) == 2) {
2829 ast_term_color_code(&prompt, fgcolor, bgcolor);
2830 t += i - 1;
2831 } else if (sscanf(t, "%30d%n", &fgcolor, &i) == 1) {
2832 ast_term_color_code(&prompt, fgcolor, 0);
2833 t += i - 1;
2834 }
2835
2836 /* If the color has been reset correctly, then there's no need to reset it later */
2837 color_used = ((fgcolor == COLOR_WHITE) && (bgcolor == COLOR_BLACK)) ? 0 : 1;
2838 break;
2839 case 'd': /* date */
2840 if (ast_localtime(&ts, &tm, NULL)) {
2841 ast_strftime(tmp, sizeof(tmp), "%Y-%m-%d", &tm);
2842 ast_str_append(&prompt, 0, "%s", tmp);
2843 cli_prompt_changes++;
2844 }
2845 break;
2846 case 'g': /* group */
2847 if ((gr = getgrgid(getgid()))) {
2848 ast_str_append(&prompt, 0, "%s", gr->gr_name);
2849 }
2850 break;
2851 case 'h': /* hostname */
2852 if (!gethostname(hostname, sizeof(hostname) - 1)) {
2853 ast_str_append(&prompt, 0, "%s", hostname);
2854 } else {
2855 ast_str_append(&prompt, 0, "%s", "localhost");
2856 }
2857 break;
2858 case 'H': /* short hostname */
2859 if (!gethostname(hostname, sizeof(hostname) - 1)) {
2860 char *dotptr;
2861 if ((dotptr = strchr(hostname, '.'))) {
2862 *dotptr = '\0';
2863 }
2864 ast_str_append(&prompt, 0, "%s", hostname);
2865 } else {
2866 ast_str_append(&prompt, 0, "%s", "localhost");
2867 }
2868 break;
2869#ifdef HAVE_GETLOADAVG
2870 case 'l': /* load avg */
2871 t++;
2872 if (sscanf(t, "%30d", &which) == 1 && which > 0 && which <= 3) {
2873 double list[3];
2874 getloadavg(list, 3);
2875 ast_str_append(&prompt, 0, "%.2f", list[which - 1]);
2876 cli_prompt_changes++;
2877 }
2878 break;
2879#endif
2880 case 's': /* Asterisk system name (from asterisk.conf) */
2882 break;
2883 case 't': /* time */
2884 if (ast_localtime(&ts, &tm, NULL)) {
2885 ast_strftime(tmp, sizeof(tmp), "%H:%M:%S", &tm);
2886 ast_str_append(&prompt, 0, "%s", tmp);
2887 cli_prompt_changes++;
2888 }
2889 break;
2890 case 'u': /* username */
2891 if ((pw = getpwuid(getuid()))) {
2892 ast_str_append(&prompt, 0, "%s", pw->pw_name);
2893 }
2894 break;
2895 case '#': /* process console or remote? */
2896 ast_str_append(&prompt, 0, "%c", ast_opt_remote ? '>' : '#');
2897 break;
2898 case '%': /* literal % */
2899 ast_str_append(&prompt, 0, "%c", '%');
2900 break;
2901 case '\0': /* % is last character - prevent bug */
2902 t--;
2903 break;
2904 }
2905 } else {
2906 ast_str_append(&prompt, 0, "%c", *t);
2907 }
2908 t++;
2909 }
2910 if (color_used) {
2911 /* Force colors back to normal at end */
2913 }
2914 } else {
2915 ast_str_set(&prompt, 0, "%s%s",
2918 }
2919
2920 return ast_str_buffer(prompt);
2921}
2922
2924{
2925 char *retstr;
2926 struct ast_vector_string *vec = ast_calloc(1, sizeof(*vec));
2927
2928 if (!vec) {
2929 return NULL;
2930 }
2931
2932 while ((retstr = strsep(&buf, " "))) {
2933 if (!strcmp(retstr, AST_CLI_COMPLETE_EOF)) {
2934 break;
2935 }
2936
2937 retstr = ast_strdup(retstr);
2938 if (!retstr || AST_VECTOR_APPEND(vec, retstr)) {
2939 ast_free(retstr);
2940 goto vector_cleanup;
2941 }
2942 }
2943
2944 if (!AST_VECTOR_SIZE(vec)) {
2945 goto vector_cleanup;
2946 }
2947
2948 return vec;
2949
2950vector_cleanup:
2953
2954 return NULL;
2955}
2956
2957static void ast_cli_display_match_list(struct ast_vector_string *matches, int max)
2958{
2959 int idx = 1;
2960 /* find out how many entries can be put on one line, with two spaces between strings */
2961 int limit = ast_get_termcols(STDOUT_FILENO) / (max + 2);
2962
2963 if (limit == 0) {
2964 limit = 1;
2965 }
2966
2967 for (;;) {
2968 int numoutputline;
2969
2970 for (numoutputline = 0; numoutputline < limit && idx < AST_VECTOR_SIZE(matches); idx++) {
2971 numoutputline++;
2972 fprintf(stdout, "%-*s ", max, AST_VECTOR_GET(matches, idx));
2973 }
2974
2975 if (!numoutputline) {
2976 break;
2977 }
2978
2979 fprintf(stdout, "\n");
2980 }
2981}
2982
2983
2984static char *cli_complete(EditLine *editline, int ch)
2985{
2986 int len = 0;
2987 char *ptr;
2988 struct ast_vector_string *matches;
2989 int retval = CC_ERROR;
2990 char savechr;
2991 int res;
2992
2993 LineInfo *lf = (LineInfo *)el_line(editline);
2994
2995 savechr = *(char *)lf->cursor;
2996 *(char *)lf->cursor = '\0';
2997 ptr = (char *)lf->cursor;
2998 if (ptr) {
2999 while (ptr > lf->buffer) {
3000 if (isspace(*ptr)) {
3001 ptr++;
3002 break;
3003 }
3004 ptr--;
3005 }
3006 }
3007
3008 len = lf->cursor - ptr;
3009
3010 if (ast_opt_remote) {
3011#define CMD_MATCHESARRAY "_COMMAND MATCHESARRAY \"%s\" \"%s\""
3012 char *mbuf;
3013 char *new_mbuf;
3014 int mlen = 0;
3015 int maxmbuf = ast_asprintf(&mbuf, CMD_MATCHESARRAY, lf->buffer, ptr);
3016
3017 if (maxmbuf == -1) {
3018 *((char *) lf->cursor) = savechr;
3019
3020 return (char *)(CC_ERROR);
3021 }
3022
3023 fdsend(ast_consock, mbuf);
3024 res = 0;
3025 mlen = 0;
3026 mbuf[0] = '\0';
3027
3028 while (!strstr(mbuf, AST_CLI_COMPLETE_EOF) && res != -1) {
3029 if (mlen + 1024 > maxmbuf) {
3030 /* Expand buffer to the next 1024 byte increment plus a NULL terminator. */
3031 maxmbuf = mlen + 1024;
3032 new_mbuf = ast_realloc(mbuf, maxmbuf + 1);
3033 if (!new_mbuf) {
3034 ast_free(mbuf);
3035 *((char *) lf->cursor) = savechr;
3036
3037 return (char *)(CC_ERROR);
3038 }
3039 mbuf = new_mbuf;
3040 }
3041 /* Only read 1024 bytes at a time */
3042 res = read(ast_consock, mbuf + mlen, 1024);
3043 if (res > 0) {
3044 if (!strncmp(mbuf, "Usage:", 6)) {
3045 /*
3046 * Abort on malformed tab completes
3047 * If help (tab complete) follows certain
3048 * special characters, the main Asterisk process
3049 * provides usage for the internal tab complete
3050 * helper command that the remote console processes
3051 * use.
3052 * If this happens, the AST_CLI_COMPLETE_EOF sentinel
3053 * value never gets sent. As a result, we'll just block
3054 * forever if we don't handle this case.
3055 * If we get command usage on a tab complete, then
3056 * we know this scenario just happened and we should
3057 * just silently ignore and do nothing.
3058 */
3059 break;
3060 }
3061 mlen += res;
3062 mbuf[mlen] = '\0';
3063 }
3064 }
3065 mbuf[mlen] = '\0';
3066
3067 matches = ast_el_strtoarr(mbuf);
3068 ast_free(mbuf);
3069 } else {
3070 matches = ast_cli_completion_vector((char *)lf->buffer, ptr);
3071 }
3072
3073 if (matches) {
3074 int i;
3075 int maxlen, match_len;
3076 const char *best_match = AST_VECTOR_GET(matches, 0);
3077
3078 if (!ast_strlen_zero(best_match)) {
3079 el_deletestr(editline, (int) len);
3080 el_insertstr(editline, best_match);
3081 retval = CC_REFRESH;
3082 }
3083
3084 if (AST_VECTOR_SIZE(matches) == 2) {
3085 /* Found an exact match */
3086 el_insertstr(editline, " ");
3087 retval = CC_REFRESH;
3088 } else {
3089 /* Must be more than one match */
3090 for (i = 1, maxlen = 0; i < AST_VECTOR_SIZE(matches); i++) {
3091 match_len = strlen(AST_VECTOR_GET(matches, i));
3092 if (match_len > maxlen) {
3093 maxlen = match_len;
3094 }
3095 }
3096
3097 fprintf(stdout, "\n");
3098 ast_cli_display_match_list(matches, maxlen);
3099 retval = CC_REDISPLAY;
3100 }
3102 AST_VECTOR_PTR_FREE(matches);
3103 }
3104
3105 *((char *) lf->cursor) = savechr;
3106
3107 return (char *)(long)retval;
3108}
3109
3110static int ast_el_initialize(void)
3111{
3112 HistEvent ev;
3113 char *editor, *editrc = getenv("EDITRC");
3114
3115 if (!(editor = getenv("AST_EDITMODE"))) {
3116 if (!(editor = getenv("AST_EDITOR"))) {
3117 editor = "emacs";
3118 }
3119 }
3120
3121 if (el != NULL)
3122 el_end(el);
3123 if (el_hist != NULL)
3124 history_end(el_hist);
3125
3126 el = el_init("asterisk", stdin, stdout, stderr);
3127 el_set(el, EL_PROMPT, cli_prompt);
3128
3129 el_set(el, EL_EDITMODE, 1);
3130 el_set(el, EL_EDITOR, editor);
3131 el_hist = history_init();
3132 if (!el || !el_hist)
3133 return -1;
3134
3135 /* setup history with 100 entries */
3136 history(el_hist, &ev, H_SETSIZE, 100);
3137
3138 el_set(el, EL_HIST, history, el_hist);
3139
3140 el_set(el, EL_ADDFN, "ed-complete", "Complete argument", cli_complete);
3141 /* Bind <tab> to command completion */
3142 el_set(el, EL_BIND, "^I", "ed-complete", NULL);
3143 /* Bind ? to command completion */
3144 el_set(el, EL_BIND, "?", "ed-complete", NULL);
3145 /* Bind ^D to redisplay */
3146 el_set(el, EL_BIND, "^D", "ed-redisplay", NULL);
3147 /* Bind Delete to delete char left */
3148 el_set(el, EL_BIND, "\\e[3~", "ed-delete-next-char", NULL);
3149 /* Bind Home and End to move to line start and end */
3150 el_set(el, EL_BIND, "\\e[1~", "ed-move-to-beg", NULL);
3151 el_set(el, EL_BIND, "\\e[4~", "ed-move-to-end", NULL);
3152 /* Bind C-left and C-right to move by word (not all terminals) */
3153 el_set(el, EL_BIND, "\\eOC", "vi-next-word", NULL);
3154 el_set(el, EL_BIND, "\\eOD", "vi-prev-word", NULL);
3155
3156 if (editrc) {
3157 el_source(el, editrc);
3158 }
3159
3160 return 0;
3161}
3162
3163#define MAX_HISTORY_COMMAND_LENGTH 256
3164
3165static int ast_el_add_history(const char *buf)
3166{
3167 HistEvent ev;
3168 char *stripped_buf;
3169
3170 if (el_hist == NULL || el == NULL) {
3172 }
3173 if (strlen(buf) > (MAX_HISTORY_COMMAND_LENGTH - 1)) {
3174 return 0;
3175 }
3176
3177 stripped_buf = ast_strip(ast_strdupa(buf));
3178
3179 /* HISTCONTROL=ignoredups */
3180 if (!history(el_hist, &ev, H_FIRST) && strcmp(ev.str, stripped_buf) == 0) {
3181 return 0;
3182 }
3183
3184 return history(el_hist, &ev, H_ENTER, stripped_buf);
3185}
3186
3187static int ast_el_write_history(const char *filename)
3188{
3189 HistEvent ev;
3190
3191 if (el_hist == NULL || el == NULL)
3193
3194 return (history(el_hist, &ev, H_SAVE, filename));
3195}
3196
3197static int ast_el_read_history(const char *filename)
3198{
3199 HistEvent ev;
3200
3201 if (el_hist == NULL || el == NULL) {
3203 }
3204
3205 if (access(filename, F_OK) == 0) {
3206 return history(el_hist, &ev, H_LOAD, filename);
3207 }
3208
3209 /* If the history file doesn't exist, failing to read it is unremarkable. */
3210 return 0;
3211}
3212
3213static void process_histfile(int (*readwrite)(const char *filename))
3214{
3215 struct passwd *pw = getpwuid(geteuid());
3216 int ret = 0;
3217 char *name = NULL;
3218
3219 if (!pw || ast_strlen_zero(pw->pw_dir)) {
3220 ast_log(LOG_ERROR, "Unable to determine home directory. History read/write disabled.\n");
3221 return;
3222 }
3223
3224 ret = ast_asprintf(&name, "%s/.asterisk_history", pw->pw_dir);
3225 if (ret <= 0) {
3226 ast_log(LOG_ERROR, "Unable to create history file name. History read/write disabled.\n");
3227 return;
3228 }
3229
3230 ret = readwrite(name);
3231 if (ret < 0) {
3232 ast_log(LOG_ERROR, "Unable to read or write history file '%s'\n", name);
3233 }
3234
3235 ast_free(name);
3236
3237 return;
3238}
3239
3241{
3243}
3244
3246{
3248}
3249
3250static void ast_remotecontrol(char *data)
3251{
3252 char buf[256] = "";
3253 int res;
3254 char *hostname;
3255 char *cpid;
3256 char *version;
3257 int pid;
3258 char *stringp = NULL;
3259
3260 char *ebuf;
3261 int num = 0;
3262
3263 ast_term_init();
3264 printf("%s", term_end());
3265 fflush(stdout);
3266
3267 memset(&sig_flags, 0, sizeof(sig_flags));
3268 signal(SIGINT, __remote_quit_handler);
3269 signal(SIGTERM, __remote_quit_handler);
3270 signal(SIGHUP, __remote_quit_handler);
3271
3272 if (read(ast_consock, buf, sizeof(buf) - 1) < 0) {
3273 ast_log(LOG_ERROR, "read() failed: %s\n", strerror(errno));
3274 return;
3275 }
3276 if (data) {
3277 char prefix[] = "cli quit after ";
3278 char *tmp = ast_alloca(strlen(data) + strlen(prefix) + 1);
3279 sprintf(tmp, "%s%s", prefix, data);
3280 if (write(ast_consock, tmp, strlen(tmp) + 1) < 0) {
3281 ast_log(LOG_ERROR, "write() failed: %s\n", strerror(errno));
3282 if (sig_flags.need_quit || sig_flags.need_quit_handler || sig_flags.need_el_end) {
3283 return;
3284 }
3285 }
3286 }
3287 stringp = buf;
3288 hostname = strsep(&stringp, "/");
3289 cpid = strsep(&stringp, "/");
3290 version = strsep(&stringp, "\n");
3291 if (!version)
3292 version = "<Version Unknown>";
3293 stringp = hostname;
3294 strsep(&stringp, ".");
3295 if (cpid)
3296 pid = atoi(cpid);
3297 else
3298 pid = -1;
3299 if (!data) {
3301 }
3302
3303 if (ast_opt_exec && data) { /* hack to print output then exit if asterisk -rx is used */
3304 int linefull = 1, prev_linefull = 1, prev_line_verbose = 0;
3305 struct pollfd fds;
3306 fds.fd = ast_consock;
3307 fds.events = POLLIN;
3308 fds.revents = 0;
3309
3310 while (ast_poll(&fds, 1, 60000) > 0) {
3311 char buffer[512] = "", *curline = buffer, *nextline;
3312 int not_written = 1;
3313
3314 if (sig_flags.need_quit || sig_flags.need_quit_handler || sig_flags.need_el_end) {
3315 break;
3316 }
3317
3318 if (read(ast_consock, buffer, sizeof(buffer) - 1) <= 0) {
3319 break;
3320 }
3321
3322 do {
3323 prev_linefull = linefull;
3324 if ((nextline = strchr(curline, '\n'))) {
3325 linefull = 1;
3326 nextline++;
3327 } else {
3328 linefull = 0;
3329 nextline = strchr(curline, '\0');
3330 }
3331
3332 /* Skip verbose lines */
3333 /* Prev line full? | Line is verbose | Last line verbose? | Print
3334 * TRUE | TRUE* | TRUE | FALSE
3335 * TRUE | TRUE* | FALSE | FALSE
3336 * TRUE | FALSE* | TRUE | TRUE
3337 * TRUE | FALSE* | FALSE | TRUE
3338 * FALSE | TRUE | TRUE* | FALSE
3339 * FALSE | TRUE | FALSE* | TRUE
3340 * FALSE | FALSE | TRUE* | FALSE
3341 * FALSE | FALSE | FALSE* | TRUE
3342 */
3343 if ((!prev_linefull && !prev_line_verbose) || (prev_linefull && *curline > 0)) {
3344 prev_line_verbose = 0;
3345 not_written = 0;
3346 if (write(STDOUT_FILENO, curline, nextline - curline) < 0) {
3347 ast_log(LOG_WARNING, "write() failed: %s\n", strerror(errno));
3348 }
3349 } else {
3350 prev_line_verbose = 1;
3351 }
3352 curline = nextline;
3353 } while (!ast_strlen_zero(curline));
3354
3355 /* No non-verbose output in 60 seconds. */
3356 if (not_written) {
3357 break;
3358 }
3359 }
3360 return;
3361 }
3362
3363 ast_verbose("Connected to Asterisk %s currently running on %s (pid = %d)\n", version, hostname, pid);
3365
3367 if (el_hist == NULL || el == NULL)
3370
3371 el_set(el, EL_GETCFN, ast_el_read_char);
3372
3373 for (;;) {
3374 ebuf = (char *)el_gets(el, &num);
3375
3376 if (sig_flags.need_quit || sig_flags.need_quit_handler || sig_flags.need_el_end) {
3377 break;
3378 }
3379
3380 if (!ebuf && write(1, "", 1) < 0)
3381 break;
3382
3383 if (!ast_strlen_zero(ebuf)) {
3384 if (ebuf[strlen(ebuf)-1] == '\n')
3385 ebuf[strlen(ebuf)-1] = '\0';
3386 if (!remoteconsolehandler(ebuf)) {
3387 res = write(ast_consock, ebuf, strlen(ebuf) + 1);
3388 if (res < 1) {
3389 ast_log(LOG_WARNING, "Unable to write: %s\n", strerror(errno));
3390 break;
3391 }
3392 }
3393 }
3394 }
3395 printf("\nDisconnected from Asterisk server\n");
3396}
3397
3398static int show_version(void)
3399{
3400 printf("Asterisk %s\n", ast_get_version());
3401 return 0;
3402}
3403
3404static int show_cli_help(void)
3405{
3406 printf("Asterisk %s, " COPYRIGHT_TAG "\n", ast_get_version());
3407 printf("Usage: asterisk [OPTIONS]\n");
3408 printf("Valid Options:\n");
3409 printf(" -V Display version number and exit\n");
3410 printf(" -C <configfile> Use an alternate configuration file\n");
3411 printf(" -G <group> Run as a group other than the caller\n");
3412 printf(" -U <user> Run as a user other than the caller\n");
3413 printf(" -c Provide console CLI\n");
3414 printf(" -d Increase debugging (multiple d's = more debugging)\n");
3415#if HAVE_WORKING_FORK
3416 printf(" -f Do not fork\n");
3417 printf(" -F Always fork\n");
3418#endif
3419 printf(" -g Dump core in case of a crash\n");
3420 printf(" -h This help screen\n");
3421 printf(" -i Initialize crypto keys at startup\n");
3422 printf(" -L <load> Limit the maximum load average before rejecting new calls\n");
3423 printf(" -M <value> Limit the maximum number of calls to the specified value\n");
3424 printf(" -m Mute debugging and console output on the console\n");
3425 printf(" -n Disable console colorization. Can be used only at startup.\n");
3426 printf(" -p Run as pseudo-realtime thread\n");
3427 printf(" -q Quiet mode (suppress output)\n");
3428 printf(" -r Connect to Asterisk on this machine\n");
3429 printf(" -R Same as -r, except attempt to reconnect if disconnected\n");
3430 printf(" -s <socket> Connect to Asterisk via socket <socket> (only valid with -r)\n");
3431 printf(" -t Record soundfiles in /var/tmp and move them where they\n");
3432 printf(" belong after they are done\n");
3433 printf(" -T Display the time in [Mmm dd hh:mm:ss] format for each line\n");
3434 printf(" of output to the CLI. Cannot be used with remote console mode.\n\n");
3435 printf(" -v Increase verbosity (multiple v's = more verbose)\n");
3436 printf(" -x <cmd> Execute command <cmd> (implies -r)\n");
3437 printf(" -X Enable use of #exec in asterisk.conf\n");
3438 printf(" -W Adjust terminal colors to compensate for a light background\n");
3439 printf("\n");
3440 return 0;
3441}
3442
3444{
3445 struct ast_config *cfg;
3446 struct ast_variable *v;
3447 struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE | CONFIG_FLAG_NOREALTIME };
3448
3451
3452 cfg = ast_config_load2("pjproject.conf", "" /* core, can't reload */, config_flags);
3453 if (!cfg
3455 || cfg == CONFIG_STATUS_FILEINVALID) {
3456 /* We'll have to use defaults */
3457 return;
3458 }
3459
3460 for (v = ast_variable_browse(cfg, "startup"); v; v = v->next) {
3461 if (!strcasecmp(v->name, "log_level")) {
3462 if (sscanf(v->value, "%30d", &ast_option_pjproject_log_level) != 1) {
3464 } else if (ast_option_pjproject_log_level < 0) {
3468 }
3469 } else if (!strcasecmp(v->name, "cache_pools")) {
3471 }
3472 }
3473
3474 ast_config_destroy(cfg);
3475}
3476
3477static void *monitor_sig_flags(void *unused)
3478{
3479 for (;;) {
3480 struct pollfd p = { sig_alert_pipe[0], POLLIN, 0 };
3481
3482 ast_poll(&p, 1, -1);
3483 if (sig_flags.need_reload) {
3484 sig_flags.need_reload = 0;
3486 }
3487 if (sig_flags.need_quit) {
3488 sig_flags.need_quit = 0;
3489 if ((consolethread != AST_PTHREADT_NULL) && (consolethread != pthread_self())) {
3490 sig_flags.need_quit_handler = 1;
3491 pthread_kill(consolethread, SIGURG);
3492 } else {
3494 }
3495 }
3497 }
3498
3499 return NULL;
3500}
3501
3502static void *canary_thread(void *unused)
3503{
3504 struct stat canary_stat;
3505 struct timeval now;
3506
3507 /* Give the canary time to sing */
3508 sleep(120);
3509
3510 for (;;) {
3511 now = ast_tvnow();
3512 if (stat(canary_filename, &canary_stat) || now.tv_sec > canary_stat.st_mtime + 60) {
3514 "The canary is no more. He has ceased to be! "
3515 "He's expired and gone to meet his maker! "
3516 "He's a stiff! Bereft of life, he rests in peace. "
3517 "His metabolic processes are now history! He's off the twig! "
3518 "He's kicked the bucket. He's shuffled off his mortal coil, "
3519 "run down the curtain, and joined the bleeding choir invisible!! "
3520 "THIS is an EX-CANARY. (Reducing priority)\n");
3522 pthread_exit(NULL);
3523 }
3524
3525 /* Check the canary once a minute */
3526 sleep(60);
3527 }
3528}
3529
3530/* Used by libc's atexit(3) function */
3531static void canary_exit(void)
3532{
3533 if (canary_pid > 0) {
3534 int status;
3535 kill(canary_pid, SIGKILL);
3536 waitpid(canary_pid, &status, 0);
3537 }
3538}
3539
3545
3546static const char *startup_commands_phase_str[] = {
3547 "pre-init",
3548 "pre-module",
3549 "fully-booted,yes,true,y,t,1,on"
3550};
3551
3552/* Execute CLI commands on startup. Run by main() thread. */
3554{
3555 int fd;
3556 struct ast_config *cfg;
3557 struct ast_flags cfg_flags = { 0 };
3558 struct ast_variable *v;
3559
3560 if (!(cfg = ast_config_load2("cli.conf", "" /* core, can't reload */, cfg_flags)))
3561 return;
3563 return;
3564 }
3565
3566 fd = open("/dev/null", O_RDWR);
3567 if (fd < 0) {
3568 ast_config_destroy(cfg);
3569 return;
3570 }
3571
3572 for (v = ast_variable_browse(cfg, "startup_commands"); v; v = v->next) {
3575 ast_cli_command(fd, v->name);
3576 }
3577 }
3578
3579 close(fd);
3580 ast_config_destroy(cfg);
3581}
3582
3583static void env_init(void)
3584{
3585 setenv("AST_SYSTEMNAME", ast_config_AST_SYSTEM_NAME, 1);
3586 setenv("AST_BUILD_HOST", ast_build_hostname, 1);
3587 setenv("AST_BUILD_DATE", ast_build_date, 1);
3588 setenv("AST_BUILD_KERNEL", ast_build_kernel, 1);
3589 setenv("AST_BUILD_MACHINE", ast_build_machine, 1);
3590 setenv("AST_BUILD_OS", ast_build_os, 1);
3591 setenv("AST_BUILD_USER", ast_build_user, 1);
3592 setenv("AST_VERSION", ast_get_version(), 1);
3593}
3594
3595static void print_intro_message(const char *runuser, const char *rungroup)
3596{
3599 if (runuser) {
3600 ast_verbose("Running as user '%s'\n", runuser);
3601 }
3602 if (rungroup) {
3603 ast_verbose("Running under group '%s'\n", rungroup);
3604 }
3605 }
3606}
3607
3608static void main_atexit(void)
3609{
3611}
3612
3613int main(int argc, char *argv[])
3614{
3615 int c;
3616 int x;
3617 int isroot = 1, rundir_exists = 0;
3618 RAII_VAR(char *, runuser, NULL, ast_free);
3619 RAII_VAR(char *, rungroup, NULL, ast_free);
3620 RAII_VAR(char *, xarg, NULL, ast_free);
3621 struct rlimit l;
3622 static const char *getopt_settings = "BC:cde:FfG:ghIiL:M:mnpqRrs:TtU:VvWXx:";
3623
3624 /* Remember original args for restart */
3625 if (argc > ARRAY_LEN(_argv) - 1) {
3626 fprintf(stderr, "Truncating argument size to %d\n", (int)ARRAY_LEN(_argv) - 1);
3627 argc = ARRAY_LEN(_argv) - 1;
3628 }
3629 for (x = 0; x < argc; x++)
3630 _argv[x] = argv[x];
3631 _argv[x] = NULL;
3632
3633 if (geteuid() != 0)
3634 isroot = 0;
3635
3636 /* if the progname is rasterisk consider it a remote console */
3637 if (argv[0] && (strstr(argv[0], "rasterisk")) != NULL) {
3639 }
3640 ast_mainpid = getpid();
3641
3642 /* Process command-line options that affect asterisk.conf load. */
3643 while ((c = getopt(argc, argv, getopt_settings)) != -1) {
3644 switch (c) {
3645 case 'X':
3647 break;
3648 case 'C':
3649 set_asterisk_conf_path(optarg);
3650 break;
3651 case 'd':
3652 option_debug++;
3653 break;
3654 case 'h':
3655 show_cli_help();
3656 exit(0);
3657 case 'R':
3658 case 'r':
3659 case 'x':
3660 /* ast_opt_remote is checked during config load. This is only part of what
3661 * these options do, see the second loop for the rest of the actions. */
3663 break;
3664 case 'V':
3665 show_version();
3666 exit(0);
3667 case 'v':
3669 break;
3670 case '?':
3671 exit(1);
3672 }
3673 }
3674
3675 /* Initialize env so it is available if #exec is used in asterisk.conf. */
3676 env_init();
3677
3679
3680 /* Update env to include any systemname that was set. */
3681 env_init();
3682
3683 /*! \brief Check for options
3684 *
3685 * \todo Document these options
3686 */
3687 optind = 1;
3688 while ((c = getopt(argc, argv, getopt_settings)) != -1) {
3689 /*!\note Please keep the ordering here to alphabetical, capital letters
3690 * first. This will make it easier in the future to select unused
3691 * option flags for new features. */
3692 switch (c) {
3693 case 'B': /* Force black background */
3696 break;
3697 case 'X':
3698 /* The command-line -X option enables #exec for asterisk.conf only. */
3699 break;
3700 case 'C':
3701 /* already processed. */
3702 break;
3703 case 'c':
3705 break;
3706 case 'd':
3707 /* already processed. */
3708 break;
3709#if defined(HAVE_SYSINFO)
3710 case 'e':
3711 if ((sscanf(&optarg[1], "%30ld", &option_minmemfree) != 1) || (option_minmemfree < 0)) {
3713 }
3714 break;
3715#endif
3716#if HAVE_WORKING_FORK
3717 case 'F':
3719 break;
3720 case 'f':
3722 break;
3723#endif
3724 case 'G':
3725 rungroup = ast_strdup(optarg);
3726 break;
3727 case 'g':
3729 break;
3730 case 'h':
3731 /* already processed. */
3732 break;
3733 case 'I':
3734 fprintf(stderr,
3735 "NOTICE: The -I option is no longer needed.\n"
3736 " It will always be enabled if you have a timing module loaded.\n");
3737 break;
3738 case 'i':
3740 break;
3741 case 'L':
3742 if ((sscanf(optarg, "%30lf", &ast_option_maxload) != 1) || (ast_option_maxload < 0.0)) {
3743 ast_option_maxload = 0.0;
3744 }
3745 break;
3746 case 'M':
3747 if ((sscanf(optarg, "%30d", &ast_option_maxcalls) != 1) || (ast_option_maxcalls < 0)) {
3749 }
3750 break;
3751 case 'm':
3753 break;
3754 case 'n':
3756 break;
3757 case 'p':
3759 break;
3760 case 'q':
3762 break;
3763 case 'R':
3765 break;
3766 case 'r':
3768 break;
3769 case 's':
3770 if (ast_opt_remote) {
3771 set_socket_path(optarg);
3772 }
3773 break;
3774 case 'T':
3776 break;
3777 case 't':
3779 break;
3780 case 'U':
3781 runuser = ast_strdup(optarg);
3782 break;
3783 case 'V':
3784 case 'v':
3785 /* already processed. */
3786 break;
3787 case 'W': /* White background */
3790 break;
3791 case 'x':
3792 /* -r is implied by -x so set the flags -r sets as well. */
3794
3796 xarg = ast_strdup(optarg);
3797 break;
3798 case '?':
3799 /* already processed. */
3800 break;
3801 }
3802 }
3803
3804 if (ast_opt_remote) {
3805 int didwarn = 0;
3806 optind = 1;
3807
3808 /* Not all options can be used with remote console. Warn if they're used. */
3809 while ((c = getopt(argc, argv, getopt_settings)) != -1) {
3810 switch (c) {
3811 /* okay to run with remote console */
3812 case 'B': /* force black background */
3813 case 'C': /* set config path */
3814 case 'd': /* debug */
3815 case 'h': /* help */
3816 case 'I': /* obsolete timing option: warning already thrown if used */
3817 case 'L': /* max load */
3818 case 'M': /* max calls */
3819 case 'm': /* mute */
3820 /*! \note The q option is never used anywhere, only defined */
3821 case 'q': /* quiet */
3822 case 'R': /* reconnect */
3823 case 'r': /* remote */
3824 /*! \note Can ONLY be used with remote console */
3825 case 's': /* set socket path */
3826 case 'T': /* timestamp */
3827 case 'V': /* version */
3828 case 'v': /* verbose */
3829 case 'W': /* white background */
3830 case 'x': /* remote execute */
3831 case '?': /* ? */
3832 break;
3833 /* can only be run when Asterisk is starting */
3834 case 'X': /* enables #exec for asterisk.conf only. */
3835 case 'c': /* foreground console */
3836 case 'e': /* minimum memory free */
3837 case 'F': /* always fork */
3838 case 'f': /* no fork */
3839 case 'G': /* run group */
3840 case 'g': /* dump core */
3841 case 'i': /* init keys */
3842 case 'n': /* no color */
3843 case 'p': /* high priority */
3844 case 't': /* cache record files */
3845 case 'U': /* run user */
3846 fprintf(stderr, "'%c' option is not compatible with remote console mode and has no effect.\n", c);
3847 didwarn = 1;
3848 }
3849 }
3850 if (didwarn) {
3851 fprintf(stderr, "\n"); /* if any warnings print out, make them stand out */
3852 }
3853 }
3854
3855 /* For remote connections, change the name of the remote connection.
3856 * We do this for the benefit of init scripts (which need to know if/when
3857 * the main asterisk process has died yet). */
3858 if (ast_opt_remote) {
3859 strcpy(argv[0], "rasterisk");
3860 for (x = 1; x < argc; x++) {
3861 argv[x] = argv[0] + 10;
3862 }
3863 }
3864
3866 fprintf(stderr, "The 'languageprefix' option in asterisk.conf is deprecated; in a future release it will be removed, and your sound files will need to be organized in the 'new style' language layout.\n");
3867 }
3868
3870 fprintf(stderr, "'alwaysfork' is not compatible with console or remote console mode; ignored\n");
3872 }
3873
3874 if (ast_opt_dump_core) {
3875 memset(&l, 0, sizeof(l));
3876 l.rlim_cur = RLIM_INFINITY;
3877 l.rlim_max = RLIM_INFINITY;
3878 if (setrlimit(RLIMIT_CORE, &l)) {
3879 fprintf(stderr, "Unable to disable core size resource limit: %s\n", strerror(errno));
3880 }
3881 }
3882
3883 if (getrlimit(RLIMIT_NOFILE, &l)) {
3884 fprintf(stderr, "Unable to check file descriptor limit: %s\n", strerror(errno));
3885 }
3886
3887#if !defined(CONFIGURE_RAN_AS_ROOT)
3888 /* Check if select(2) will run with more file descriptors */
3889 do {
3890 int fd, fd2;
3891 ast_fdset readers;
3892 struct timeval tv = { 0, };
3893
3894 if (l.rlim_cur <= FD_SETSIZE) {
3895 /* The limit of select()able FDs is irrelevant, because we'll never
3896 * open one that high. */
3897 break;
3898 }
3899
3900 if (!(fd = open("/dev/null", O_RDONLY))) {
3901 fprintf(stderr, "Cannot open a file descriptor at boot? %s\n", strerror(errno));
3902 break; /* XXX Should we exit() here? XXX */
3903 }
3904
3905 fd2 = ((l.rlim_cur > sizeof(readers) * 8) ? sizeof(readers) * 8 : l.rlim_cur) - 1;
3906 if (dup2(fd, fd2) < 0) {
3907 fprintf(stderr, "Cannot open maximum file descriptor %d at boot? %s\n", fd2, strerror(errno));
3908 close(fd);
3909 break;
3910 }
3911
3912 FD_ZERO(&readers);
3913 FD_SET(fd2, &readers);
3914 if (ast_select(fd2 + 1, &readers, NULL, NULL, &tv) < 0) {
3915 fprintf(stderr, "Maximum select()able file descriptor is %d\n", FD_SETSIZE);
3916 }
3917 ast_FD_SETSIZE = l.rlim_cur > ast_FDMAX ? ast_FDMAX : l.rlim_cur;
3918 close(fd);
3919 close(fd2);
3920 } while (0);
3921#elif defined(HAVE_VARIABLE_FDSET)
3922 ast_FD_SETSIZE = l.rlim_cur > ast_FDMAX ? ast_FDMAX : l.rlim_cur;
3923#endif /* !defined(CONFIGURE_RAN_AS_ROOT) */
3924
3925 if ((!rungroup) && !ast_strlen_zero(ast_config_AST_RUN_GROUP))
3927 if ((!runuser) && !ast_strlen_zero(ast_config_AST_RUN_USER))
3929
3930 /* Must install this signal handler up here to ensure that if the canary
3931 * fails to execute that it doesn't kill the Asterisk process.
3932 */
3933 sigaction(SIGCHLD, &child_handler, NULL);
3934
3935 /* It's common on some platforms to clear /var/run at boot. Create the
3936 * socket file directory before we drop privileges. */
3937 if (mkdir(ast_config_AST_RUN_DIR, 0755)) {
3938 if (errno == EEXIST) {
3939 rundir_exists = 1;
3940 } else {
3941 fprintf(stderr, "Unable to create socket file directory. Remote consoles will not be able to connect! (%s)\n", strerror(x));
3942 }
3943 }
3944
3945#ifndef __CYGWIN__
3946
3947 if (isroot) {
3949 }
3950
3951 if (isroot && rungroup) {
3952 struct group *gr;
3953 gr = getgrnam(rungroup);
3954 if (!gr) {
3955 fprintf(stderr, "No such group '%s'!\n", rungroup);
3956 exit(1);
3957 }
3958 if (!rundir_exists && chown(ast_config_AST_RUN_DIR, -1, gr->gr_gid)) {
3959 fprintf(stderr, "Unable to chgrp run directory to %d (%s)\n", (int) gr->gr_gid, rungroup);
3960 }
3961 if (setgid(gr->gr_gid)) {
3962 fprintf(stderr, "Unable to setgid to %d (%s)\n", (int)gr->gr_gid, rungroup);
3963 exit(1);
3964 }
3965 if (setgroups(0, NULL)) {
3966 fprintf(stderr, "Unable to drop unneeded groups\n");
3967 exit(1);
3968 }
3969 }
3970
3971 if (runuser && !ast_test_flag(&ast_options, AST_OPT_FLAG_REMOTE)) {
3972#ifdef HAVE_CAP
3973 int has_cap = 1;
3974#endif /* HAVE_CAP */
3975 struct passwd *pw;
3976 pw = getpwnam(runuser);
3977 if (!pw) {
3978 fprintf(stderr, "No such user '%s'!\n", runuser);
3979 exit(1);
3980 }
3981 if (chown(ast_config_AST_RUN_DIR, pw->pw_uid, -1)) {
3982 fprintf(stderr, "Unable to chown run directory to %d (%s)\n", (int) pw->pw_uid, runuser);
3983 }
3984#ifdef HAVE_CAP
3985 if (prctl(PR_SET_KEEPCAPS, 1, 0, 0, 0)) {
3986 ast_log(LOG_WARNING, "Unable to keep capabilities.\n");
3987 has_cap = 0;
3988 }
3989#endif /* HAVE_CAP */
3990 if (!isroot && pw->pw_uid != geteuid()) {
3991 fprintf(stderr, "Asterisk started as nonroot, but runuser '%s' requested.\n", runuser);
3992 exit(1);
3993 }
3994 if (!rungroup) {
3995 if (setgid(pw->pw_gid)) {
3996 fprintf(stderr, "Unable to setgid to %d!\n", (int)pw->pw_gid);
3997 exit(1);
3998 }
3999 if (isroot && initgroups(pw->pw_name, pw->pw_gid)) {
4000 fprintf(stderr, "Unable to init groups for '%s'\n", runuser);
4001 exit(1);
4002 }
4003 }
4004 if (setuid(pw->pw_uid)) {
4005 fprintf(stderr, "Unable to setuid to %d (%s)\n", (int)pw->pw_uid, runuser);
4006 exit(1);
4007 }
4008#ifdef HAVE_CAP
4009 if (has_cap) {
4010 cap_t cap;
4011
4012 cap = cap_from_text("cap_net_admin=eip");
4013
4014 if (cap_set_proc(cap)) {
4015 fprintf(stderr, "Unable to install capabilities.\n");
4016 }
4017 if (cap_free(cap)) {
4018 fprintf(stderr, "Unable to drop capabilities.\n");
4019 }
4020 }
4021#endif /* HAVE_CAP */
4022 }
4023
4024#endif /* __CYGWIN__ */
4025
4026#ifdef linux
4027 if (geteuid() && ast_opt_dump_core) {
4028 if (prctl(PR_SET_DUMPABLE, 1, 0, 0, 0) < 0) {
4029 fprintf(stderr, "Unable to set the process for core dumps after changing to a non-root user. %s\n", strerror(errno));
4030 }
4031 }
4032#endif
4033
4034 {
4035#if defined(HAVE_EACCESS) || defined(HAVE_EUIDACCESS)
4036 char dir[PATH_MAX];
4037 if (!getcwd(dir, sizeof(dir)) || eaccess(dir, R_OK | X_OK | F_OK)) {
4038 fprintf(stderr, "Unable to access the running directory (%s). Changing to '/' for compatibility.\n", strerror(errno));
4039 /* If we cannot access the CWD, then we couldn't dump core anyway,
4040 * so chdir("/") won't break anything. */
4041 if (chdir("/")) {
4042 /* chdir(/) should never fail, so this ends up being a no-op */
4043 fprintf(stderr, "chdir(\"/\") failed?!! %s\n", strerror(errno));
4044 }
4045 } else
4046#endif /* defined(HAVE_EACCESS) || defined(HAVE_EUIDACCESS) */
4048 /* Backgrounding, but no cores, so chdir won't break anything. */
4049 if (chdir("/")) {
4050 fprintf(stderr, "Unable to chdir(\"/\") ?!! %s\n", strerror(errno));
4051 }
4052 }
4053 }
4054
4055 /* Initial value of the maximum active system verbosity level. */
4057
4058 if (ast_sd_get_fd_un(SOCK_STREAM, ast_config_AST_SOCKET) > 0) {
4059 ast_socket_is_sd = 1;
4060 }
4061
4062 /* DO NOT perform check for existing daemon if systemd has CLI socket activation */
4063 if (!ast_socket_is_sd && ast_tryconnect()) {
4064 /* One is already running */
4065 if (ast_opt_remote) {
4067 if (ast_opt_exec) {
4068 ast_remotecontrol(xarg);
4070 exit(0);
4071 }
4072 ast_term_init();
4073 printf("%s", term_end());
4074 fflush(stdout);
4075
4076 print_intro_message(runuser, rungroup);
4077 printf("%s", term_quit());
4080 exit(0);
4081 } else {
4082 fprintf(stderr, "Asterisk already running on %s. Use 'asterisk -r' to connect.\n", ast_config_AST_SOCKET);
4083 printf("%s", term_quit());
4084 exit(1);
4085 }
4086 } else if (ast_opt_remote || ast_opt_exec) {
4087 fprintf(stderr, "Unable to connect to remote asterisk (does %s exist?)\n", ast_config_AST_SOCKET);
4088 printf("%s", term_quit());
4089 exit(1);
4090 }
4091
4092#ifdef HAVE_CAP
4093 child_cap = cap_from_text("cap_net_admin-eip");
4094#endif
4095 /* Not a remote console? Start the daemon. */
4096 asterisk_daemon(isroot, runuser, rungroup);
4097#ifdef HAS_CAP
4098 cap_free(child_cap);
4099#endif
4100 return 0;
4101}
4102
4103static inline void check_init(int init_result, const char *name)
4104{
4105 if (init_result) {
4107 ast_log(LOG_ERROR, "%s initialization failed. ASTERISK EXITING!\n%s", name, term_quit());
4108 } else {
4109 fprintf(stderr, "%s initialization failed. ASTERISK EXITING!\n%s", name, term_quit());
4110 }
4111 ast_run_atexits(0);
4112 exit(init_result == -2 ? 2 : 1);
4113 }
4114}
4115
4116static void asterisk_daemon(int isroot, const char *runuser, const char *rungroup)
4117{
4118 FILE *f;
4119 sigset_t sigs;
4120 int num;
4121 char *buf;
4122 char pbx_uuid[AST_UUID_STR_LEN];
4123
4124 /* Set time as soon as possible */
4126
4127 /* This needs to remain as high up in the initial start up as possible.
4128 * daemon causes a fork to occur, which has all sorts of unintended
4129 * consequences for things that interact with threads. This call *must*
4130 * occur before anything in Asterisk spawns or manipulates thread related
4131 * primitives. */
4132#if HAVE_WORKING_FORK
4134#ifndef HAVE_SBIN_LAUNCHD
4135 if (daemon(1, 0) < 0) {
4136 fprintf(stderr, "daemon() failed: %s\n", strerror(errno));
4137 } else {
4138 ast_mainpid = getpid();
4139 }
4140#else
4141 fprintf(stderr, "Mac OS X detected. Use 'launchctl load /Library/LaunchDaemon/org.asterisk.asterisk.plist'.\n");
4142#endif
4143 }
4144#endif
4145
4146 /* At this point everything has been forked successfully,
4147 * we have determined that we aren't attempting to connect to
4148 * an Asterisk instance, and that there isn't one already running. */
4150
4152
4153 /* Check whether high prio was successfully set by us or some
4154 * other incantation. */
4155 if (has_priority()) {
4157 } else {
4159 }
4160
4161 /* Spawning of astcanary must happen AFTER the call to daemon(3) */
4163 snprintf(canary_filename, sizeof(canary_filename), "%s/alt.asterisk.canary.tweet.tweet.tweet", ast_config_AST_RUN_DIR);
4164
4165 /* Don't let the canary child kill Asterisk, if it dies immediately */
4166 sigaction(SIGPIPE, &ignore_sig_handler, NULL);
4167
4168 canary_pid = fork();
4169 if (canary_pid == 0) {
4170 char canary_binary[PATH_MAX], ppid[12];
4171
4172 /* Reset signal handler */
4173 signal(SIGCHLD, SIG_DFL);
4174 signal(SIGPIPE, SIG_DFL);
4175
4178 snprintf(ppid, sizeof(ppid), "%d", (int) ast_mainpid);
4179
4180 /* Use the astcanary binary that we installed */
4181 snprintf(canary_binary, sizeof(canary_binary), "%s/astcanary", ast_config_AST_SBIN_DIR);
4182 execl(canary_binary, "astcanary", canary_filename, ppid, (char *)NULL);
4183
4184 /* Should never happen */
4185 _exit(1);
4186 } else if (canary_pid > 0) {
4187 pthread_t dont_care;
4189 }
4190
4191 /* Kill the canary when we exit */
4193 }
4194
4195 /* Blindly write the PID file. */
4196 unlink(ast_config_AST_PID);
4197 f = fopen(ast_config_AST_PID, "w");
4198 if (f) {
4199 fprintf(f, "%ld\n", (long)ast_mainpid);
4200 fclose(f);
4201 } else {
4202 fprintf(stderr, "Unable to open pid file '%s': %s\n", ast_config_AST_PID, strerror(errno));
4203 }
4204
4205 /* Initialize the terminal. Since all processes have been forked,
4206 * we can now start using the standard log messages.
4207 */
4208 ast_term_init();
4209 printf("%s", term_end());
4210 fflush(stdout);
4211
4212 print_intro_message(runuser, rungroup);
4213
4215
4216 check_init(astobj2_init(), "AO2");
4217 check_init(ast_named_locks_init(), "Named Locks");
4218
4219 if (ast_opt_console) {
4220 if (el_hist == NULL || el == NULL)
4223 }
4224
4225#ifdef AST_XML_DOCS
4226 /* Load XML documentation. */
4228#endif
4229
4230 check_init(astdb_init(), "ASTdb");
4231
4232 ast_uuid_init();
4233
4234 if (ast_pbx_uuid_get(pbx_uuid, sizeof(pbx_uuid))) {
4235 ast_uuid_generate_str(pbx_uuid, sizeof(pbx_uuid));
4236 ast_db_put("pbx", "UUID", pbx_uuid);
4237 }
4238 ast_verb(0, "PBX UUID: %s\n", pbx_uuid);
4239
4240 check_init(ast_json_init(), "libjansson");
4241 ast_ulaw_init();
4242 ast_alaw_init();
4243 ast_utf8_init();
4244 tdd_init();
4245 callerid_init();
4247
4248 check_init(ast_utils_init(), "Utilities");
4249 check_init(ast_tps_init(), "Task Processor Core");
4250 check_init(ast_fd_init(), "File Descriptor Debugging");
4251 check_init(ast_pbx_init(), "ast_pbx_init");
4252 check_init(aco_init(), "Configuration Option Framework");
4253 check_init(stasis_init(), "Stasis");
4254#ifdef TEST_FRAMEWORK
4255 check_init(ast_test_init(), "Test Framework");
4256#endif
4257 check_init(ast_translate_init(), "Translator Core");
4258
4260
4261 check_init(ast_sorcery_init(), "Sorcery");
4262 check_init(ast_codec_init(), "Codecs");
4263 check_init(ast_format_init(), "Formats");
4264 check_init(ast_format_cache_init(), "Format Cache");
4265 check_init(ast_codec_builtin_init(), "Built-in Codecs");
4266 check_init(ast_bucket_init(), "Bucket API");
4267 check_init(ast_stasis_system_init(), "Stasis system-level information");
4268 check_init(ast_endpoint_stasis_init(), "Stasis Endpoint");
4269
4271 /* GCC 4.9 gives a bogus "right-hand operand of comma expression has
4272 * no effect" warning */
4273 (void) sigemptyset(&sigs);
4274 (void) sigaddset(&sigs, SIGHUP);
4275 (void) sigaddset(&sigs, SIGTERM);
4276 (void) sigaddset(&sigs, SIGINT);
4277 (void) sigaddset(&sigs, SIGPIPE);
4278 (void) sigaddset(&sigs, SIGWINCH);
4279 pthread_sigmask(SIG_BLOCK, &sigs, NULL);
4280 sigaction(SIGURG, &urg_handler, NULL);
4281 signal(SIGINT, __quit_handler);
4282 signal(SIGTERM, __quit_handler);
4283 sigaction(SIGHUP, &hup_handler, NULL);
4284 sigaction(SIGPIPE, &ignore_sig_handler, NULL);
4285
4286 /* ensure that the random number generators are seeded with a different value every time
4287 Asterisk is started
4288 */
4289 srand((unsigned int) getpid() + (unsigned int) time(NULL));
4290 initstate((unsigned int) getpid() * 65536 + (unsigned int) time(NULL), randompool, sizeof(randompool));
4291
4293
4294 check_init(init_logger(), "Logger");
4296
4297 check_init(ast_rtp_engine_init(), "RTP Engine");
4298
4300
4301 check_init(ast_timing_init(), "Timing");
4302 check_init(ast_ssl_init(), "SSL");
4304 check_init(ast_pj_init(), "Embedded PJProject");
4305 check_init(app_init(), "App Core");
4306 check_init(mwi_init(), "MWI Core");
4307 check_init(devstate_init(), "Device State Core");
4308 check_init(ast_msg_init(), "Messaging API");
4309 check_init(ast_channels_init(), "Channel");
4310 check_init(ast_endpoint_init(), "Endpoints");
4311 check_init(ast_pickup_init(), "Call Pickup");
4312 check_init(ast_bridging_init(), "Bridging");
4313 check_init(ast_parking_stasis_init(), "Parking Core");
4314 check_init(ast_device_state_engine_init(), "Device State Engine");
4315 check_init(ast_presence_state_engine_init(), "Presence State Engine");
4316 check_init(dns_core_init(), "DNS Resolver Core");
4317 check_init(ast_dns_system_resolver_init(), "Default DNS resolver");
4318 check_init(ast_security_stasis_init(), "Security Stasis Topic and Events");
4319 check_init(ast_image_init(), "Image");
4320 check_init(ast_file_init(), "Generic File Format Support");
4321 check_init(load_pbx(), "load_pbx");
4322 check_init(load_pbx_builtins(), "Builtin PBX Applications");
4323 check_init(load_pbx_functions_cli(), "PBX Functions Support");
4324 check_init(load_pbx_variables(), "PBX Variables Support");
4325 check_init(load_pbx_switch(), "PBX Switch Support");
4326 check_init(load_pbx_app(), "PBX Application Support");
4327 check_init(load_pbx_hangup_handler(), "PBX Hangup Handler Support");
4328 check_init(ast_local_init(), "Local Proxy Channel Driver");
4329 check_init(ast_refer_init(), "Refer API");
4330
4332
4333 /* We should avoid most config loads before this point as they can't use realtime. */
4334 check_init(load_modules(), "Module");
4335
4336 /*
4337 * This has to load after the dynamic modules load, as items in the media
4338 * cache can't be constructed from items in the AstDB without their
4339 * bucket backends.
4340 */
4341 check_init(ast_media_cache_init(), "Media Cache");
4342
4343 /* loads the cli_permissions.conf file needed to implement cli restrictions. */
4345 ast_cli_channels_init(); /* Not always safe to access CLI commands until startup is complete. */
4346
4347 ast_stun_init();
4348
4350
4351 if (ast_opt_no_fork) {
4352 consolethread = pthread_self();
4353 }
4354
4356
4358
4361
4362 pthread_sigmask(SIG_UNBLOCK, &sigs, NULL);
4363
4365
4369
4371 ast_sd_notify("READY=1");
4372
4373 ast_verb(0, COLORIZE_FMT "\n", COLORIZE(COLOR_BRGREEN, 0, "Asterisk Ready."));
4374
4376
4377 if (ast_opt_console) {
4378 /* Console stuff now... */
4379 /* Register our quit function */
4380 char title[296];
4381 char hostname[MAXHOSTNAMELEN] = "";
4382
4383 if (gethostname(hostname, sizeof(hostname) - 1)) {
4384 ast_copy_string(hostname, "<Unknown>", sizeof(hostname));
4385 }
4386
4388
4389 set_icon("Asterisk");
4390 snprintf(title, sizeof(title), "Asterisk Console on '%s' (pid %ld)", hostname, (long)ast_mainpid);
4391 set_title(title);
4392
4393 el_set(el, EL_GETCFN, ast_el_read_char);
4394
4395 for (;;) {
4396 if (sig_flags.need_el_end) {
4397 el_end(el);
4398
4399 return;
4400 }
4401
4402 if (sig_flags.need_quit || sig_flags.need_quit_handler) {
4404 break;
4405 }
4406 buf = (char *) el_gets(el, &num);
4407
4408 if (!buf && write(1, "", 1) < 0)
4409 return; /* quit */
4410
4411 if (buf) {
4412 if (buf[strlen(buf)-1] == '\n')
4413 buf[strlen(buf)-1] = '\0';
4414
4416 }
4417 }
4418 }
4419
4420 /* Stall until a quit signal is given */
4422}
Prototypes for public functions only of internal interest,.
int load_pbx_variables(void)
void threadstorage_init(void)
Definition: threadstorage.c:35
void ast_process_pending_reloads(void)
Process reload requests received during startup.
Definition: loader.c:1575
int modules_shutdown(void)
Definition: loader.c:1181
int ast_bridging_init(void)
Initialize the bridging system.
Definition: bridge.c:5613
void dnsmgr_start_refresh(void)
Definition: dnsmgr.c:302
int ast_timing_init(void)
Definition: timing.c:289
int ast_device_state_engine_init(void)
Initialize the device state engine in separate thread.
Definition: devicestate.c:621
int ast_term_init(void)
Definition: term.c:165
int load_modules(void)
Definition: loader.c:2517
void ast_cli_channels_init(void)
Definition: main/cli.c:2252
void ast_msg_shutdown(void)
void logger_queue_start(void)
Start the ast_queue_log() logger.
Definition: logger.c:2161
int aco_init(void)
void load_asterisk_conf(void)
Definition: options.c:211
int ast_test_init(void)
Definition: test.c:1505
void close_logger(void)
Definition: logger.c:2220
void ast_stun_init(void)
Initialize the STUN system in Asterisk.
Definition: stun.c:576
void set_asterisk_conf_path(const char *path)
Definition: options.c:201
int astdb_init(void)
Definition: db.c:1250
int ast_pj_init(void)
Definition: libasteriskpj.c:45
int load_pbx_functions_cli(void)
int ast_tps_init(void)
void load_astmm_phase_2(void)
Initialize malloc debug phase 2.
Definition: astmm.c:1529
int ast_msg_init(void)
int load_pbx_hangup_handler(void)
int ast_local_init(void)
Initialize the local proxy channel.
Definition: core_local.c:1151
int load_pbx_builtins(void)
int load_pbx_switch(void)
Definition: pbx_switch.c:125
int ast_rtp_engine_init(void)
initializes the rtp engine arrays
Definition: rtp_engine.c:3846
int ast_xmldoc_load_documentation(void)
Load XML documentation. Provided by xmldoc.c.
Definition: xmldoc.c:3141
int ast_named_locks_init(void)
Definition: named_locks.c:52
int ast_channels_init(void)
Definition: channel.c:8006
void clean_time_zones(void)
Definition: localtime.c:1590
void load_astmm_phase_1(void)
Initialize malloc debug phase 1.
Definition: astmm.c:1525
void ast_builtins_init(void)
initialize the _full_cmd string in * each of the builtins.
Definition: main/cli.c:2245
void ast_autoservice_init(void)
Definition: autoservice.c:387
int init_logger(void)
Definition: logger.c:2177
int ast_endpoint_init(void)
Endpoint support initialization.
int dns_core_init(void)
Definition: dns_core.c:616
int load_pbx(void)
Definition: pbx.c:8436
int astobj2_init(void)
Definition: astobj2.c:1169
int load_pbx_app(void)
Definition: pbx_app.c:538
int ast_dns_system_resolver_init(void)
Initializes the resolver.
int ast_ssl_init(void)
int ast_cli_perms_init(int reload)
Definition: main/cli.c:2112
void set_socket_path(const char *path)
Definition: options.c:206
int ast_file_init(void)
Definition: file.c:2059
int ast_refer_init(void)
Definition: refer.c:531
int ast_parking_stasis_init(void)
initializes the rtp engine arrays
Definition: parking.c:53
Access Control of various sorts.
A-Law to Signed linear conversion.
void ast_alaw_init(void)
To init the alaw to slinear conversion stuff, this needs to be run.
Definition: alaw.c:152
void ast_alertpipe_close(int alert_pipe[2])
Close an alert pipe.
Definition: alertpipe.c:79
ssize_t ast_alertpipe_write(int alert_pipe[2])
Write an event to an alert pipe.
Definition: alertpipe.c:120
int ast_alertpipe_init(int alert_pipe[2])
Initialize an alert pipe.
Definition: alertpipe.c:38
ast_alert_status_t ast_alertpipe_read(int alert_pipe[2])
Read an event from an alert pipe.
Definition: alertpipe.c:102
Generic Advice of Charge encode and decode routines.
int ast_aoc_cli_init(void)
enable aoc cli options
Definition: aoc.c:2029
jack_status_t status
Definition: app_jack.c:149
char * text
Definition: app_queue.c:1809
enum queue_result id
Definition: app_queue.c:1808
if(!yyg->yy_init)
Definition: ast_expr2f.c:854
Asterisk version information.
const char * ast_get_build_opts(void)
const char * ast_get_version(void)
Retrieve the Asterisk version string.
const char * ast_get_build_opts_all(void)
Persistent data storage (akin to *doze registry)
int ast_db_put(const char *family, const char *key, const char *value)
Store value addressed by family/key.
Definition: db.c:335
int ast_db_get(const char *family, const char *key, char *value, int valuelen)
Get key value specified by family/key.
Definition: db.c:421
int setenv(const char *name, const char *value, int overwrite)
int getloadavg(double *list, int nelem)
char * strsep(char **str, const char *delims)
static int ast_el_add_history(const char *)
Definition: asterisk.c:3165
static char * remotehostname
Definition: asterisk.c:348
static char * handle_stop_gracefully(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: asterisk.c:2401
static void __ast_unregister_atexit(void(*func)(void))
Definition: asterisk.c:1029
static char * cli_complete(EditLine *editline, int ch)
Definition: asterisk.c:2984
int64_t ast_mark(int i, int startstop)
Definition: asterisk.c:885
int main(int argc, char *argv[])
Definition: asterisk.c:3613
static int ast_socket_is_sd
Definition: asterisk.c:320
int ast_shutdown_final(void)
Definition: asterisk.c:1883
static void canary_exit(void)
Definition: asterisk.c:3531
static shutdown_nice_t shuttingdown
Definition: asterisk.c:385
static void check_init(int init_result, const char *name)
Definition: asterisk.c:4103
static void __remote_quit_handler(int num)
Definition: asterisk.c:2164
static void _urg_handler(int num)
Urgent handler.
Definition: asterisk.c:1723
static char * show_license(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: asterisk.c:2606
#define CHAR_T_LIBEDIT
Definition: asterisk.c:2689
static char * handle_show_threads(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: asterisk.c:615
static void ast_run_atexits(int run_cleanups)
Definition: asterisk.c:1015
static int console_state_init(void *ptr)
Definition: asterisk.c:2219
static struct profile_data * prof_data
Definition: asterisk.c:804
startup_commands_phase
Definition: asterisk.c:3540
@ STARTUP_COMMANDS_PRE_MODULE
Definition: asterisk.c:3542
@ STARTUP_COMMANDS_PRE_INIT
Definition: asterisk.c:3541
@ STARTUP_COMMANDS_FULLY_BOOTED
Definition: asterisk.c:3543
static char * handle_stop_when_convenient(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: asterisk.c:2422
static int remoteconsolehandler(const char *s)
Definition: asterisk.c:2328
static struct ast_str * prompt
Definition: asterisk.c:2795
unsigned int need_reload
Definition: asterisk.c:405
static void publish_fully_booted(void)
Definition: asterisk.c:989
static int show_version(void)
Definition: asterisk.c:3398
static struct @299 sig_flags
static void main_atexit(void)
Definition: asterisk.c:3608
static int safe_exec_wait(pid_t pid)
wait for spawned application to complete and unreplace sigchld
Definition: asterisk.c:1208
int ast_add_profile(const char *name, uint64_t scale)
allocates a counter with a given name and scale.
Definition: asterisk.c:810
static void ast_cli_display_match_list(struct ast_vector_string *matches, int max)
Definition: asterisk.c:2957
static void _hup_handler(int num)
Definition: asterisk.c:1732
static char * handle_version(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: asterisk.c:2360
static pthread_t lthread
Definition: asterisk.c:1378
static unsigned int safe_system_level
Keep track of how many threads are currently trying to wait*() on a child process.
Definition: asterisk.c:1109
static void ast_network_puts_mutable(const char *string, int level, int sublevel)
log the string to all attached network console clients
Definition: asterisk.c:1309
static char randompool[256]
Definition: asterisk.c:397
static char * handle_show_sysinfo(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Give an overview of system statistics.
Definition: asterisk.c:681
#define WELCOME_MESSAGE
Welcome message when starting a CLI interface.
Definition: asterisk.c:310
int ast_safe_execvp(int dualfork, const char *file, char *const argv[])
Safely spawn an external program while closing file descriptors.
Definition: asterisk.c:1234
int ast_register_cleanup(void(*func)(void))
Register a function to be executed before Asterisk gracefully exits.
Definition: asterisk.c:1067
static void set_header(char *outbuf, int maxout, char level)
Definition: asterisk.c:2169
static int ast_el_read_char(EditLine *editline, CHAR_T_LIBEDIT *cp)
Definition: asterisk.c:2696
static char * handle_stop_now(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: asterisk.c:2381
static char canary_filename[128]
Definition: asterisk.c:394
#define CMD_MATCHESARRAY
static __inline uint64_t rdtsc(void)
Definition: asterisk.c:878
static struct sigaction child_handler
Definition: asterisk.c:1771
int ast_set_priority(int pri)
We set ourselves to a high priority, that we might pre-empt everything else. If your PBX has heavy ac...
Definition: asterisk.c:1853
static void asterisk_daemon(int isroot, const char *runuser, const char *rungroup)
Definition: asterisk.c:4116
void ast_console_toggle_loglevel(int fd, int level, int state)
enable or disable a logging level to a specified console
Definition: asterisk.c:1263
static char * handle_show_settings(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Give an overview of core settings.
Definition: asterisk.c:474
static int has_priority(void)
Check whether we were set to high(er) priority.
Definition: asterisk.c:1790
#define PF_LOCAL
Definition: asterisk.c:300
unsigned int need_el_end
Definition: asterisk.c:408
void ast_console_toggle_mute(int fd, int silent)
mute or unmute a console from logging
Definition: asterisk.c:1286
static void send_rasterisk_connect_commands(void)
Definition: asterisk.c:2660
unsigned int need_quit
Definition: asterisk.c:406
#define ASTERISK_PROMPT
Definition: asterisk.c:2624
static struct sigaction safe_system_prev_handler
Definition: asterisk.c:1110
static char * handle_bang(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: asterisk.c:2529
static struct sigaction hup_handler
Definition: asterisk.c:1751
static pthread_t mon_sig_flags
Definition: asterisk.c:392
static int fdprint(int fd, const char *s)
Definition: asterisk.c:1086
static pthread_t consolethread
Definition: asterisk.c:391
static EditLine * el
Definition: asterisk.c:347
static void * netconsole(void *vconsole)
Definition: asterisk.c:1440
static int ast_el_initialize(void)
Definition: asterisk.c:3110
static int set_priority_all(int pri)
Set priority on all known threads.
Definition: asterisk.c:1810
static void ast_begin_shutdown(void)
Definition: asterisk.c:1911
static char * handle_restart_now(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: asterisk.c:2443
static char * handle_restart_when_convenient(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: asterisk.c:2485
static int ast_el_read_history(const char *)
Definition: asterisk.c:3197
static char * handle_abort_shutdown(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: asterisk.c:2506
int ast_shutting_down(void)
Definition: asterisk.c:1888
static void _child_handler(int sig)
Definition: asterisk.c:1756
void ast_console_puts_mutable(const char *string, int level)
log the string to the root console, and all attached network console clients
Definition: asterisk.c:1328
#define AST_MAX_CONNECTS
Definition: asterisk.c:303
int ast_pbx_uuid_get(char *pbx_uuid, int length)
Retrieve the PBX UUID.
Definition: asterisk.c:984
void ast_replace_sigchld(void)
Replace the SIGCHLD handler.
Definition: asterisk.c:1112
int ast_cancel_shutdown(void)
Cancel an existing shutdown and return to normal operation.
Definition: asterisk.c:1893
static void ast_network_puts(const char *string)
write the string to all attached console clients
Definition: asterisk.c:1352
static int read_credentials(int fd, char *buffer, size_t size, struct console *con)
read() function supporting the reception of user credentials.
Definition: asterisk.c:1390
#define CHAR_TO_LIBEDIT(c)
Definition: asterisk.c:2690
static int shutdown_pending
Definition: asterisk.c:388
static void _null_sig_handler(int sig)
NULL handler so we can collect the child exit status.
Definition: asterisk.c:1092
static void process_histfile(int(*readwrite)(const char *filename))
Definition: asterisk.c:3213
static int sig_alert_pipe[2]
Definition: asterisk.c:403
struct timeval ast_lastreloadtime
Definition: asterisk.c:344
static const char warranty_lines[]
Definition: asterisk.c:2544
void ast_console_puts(const char *string)
write the string to the root console, and all attached network console clients
Definition: asterisk.c:1368
void ast_unregister_atexit(void(*func)(void))
Unregister a function registered with ast_register_atexit().
Definition: asterisk.c:1072
static int console_print(const char *s)
Definition: asterisk.c:2228
static void quit_handler(int num, shutdown_nice_t niceness, int restart)
Definition: asterisk.c:1923
static History * el_hist
Definition: asterisk.c:346
static char * handle_restart_gracefully(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: asterisk.c:2464
static void * monitor_sig_flags(void *unused)
Definition: asterisk.c:3477
#define COPYRIGHT_TAG
Definition: asterisk.c:307
#define EL_BUF_SIZE
static char * show_warranty(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: asterisk.c:2569
#define MAX_HISTORY_COMMAND_LENGTH
Definition: asterisk.c:3163
void ast_register_thread(char *name)
Definition: asterisk.c:421
static void ast_remotecontrol(char *data)
Definition: asterisk.c:3250
static int restartnow
Definition: asterisk.c:390
static int print_file(int fd, char *desc, const char *filename)
Print the contents of a file.
Definition: asterisk.c:457
void ast_unregister_thread(void *id)
Definition: asterisk.c:437
static void consolehandler(const char *s)
Definition: asterisk.c:2310
static struct ast_cli_entry cli_asterisk_shutdown[]
Shutdown Asterisk CLI commands.
Definition: asterisk.c:2634
int ast_register_atexit(void(*func)(void))
Register a function to be executed before Asterisk exits.
Definition: asterisk.c:1062
shutdown_nice_t
Definition: asterisk.c:363
@ SHUTDOWN_FAST
Definition: asterisk.c:376
@ SHUTDOWN_NORMAL
Definition: asterisk.c:378
@ SHUTDOWN_NICE
Definition: asterisk.c:380
@ SHUTDOWN_REALLY_NICE
Definition: asterisk.c:382
@ SHUTTING_DOWN
Definition: asterisk.c:369
@ SHUTTING_DOWN_FINAL
Definition: asterisk.c:367
@ NOT_SHUTTING_DOWN
Definition: asterisk.c:365
static ast_mutex_t safe_system_lock
Definition: asterisk.c:1105
static pid_t safe_exec_prep(int dualfork)
fork and perform other preparations for spawning applications
Definition: asterisk.c:1147
int ast_safe_system(const char *s)
Safely spawn an OS shell command while closing file descriptors.
Definition: asterisk.c:1247
static int ast_all_zeros(const char *s)
Definition: asterisk.c:2299
#define SHUTDOWN_TIMEOUT
Definition: asterisk.c:1932
static int can_safely_quit(shutdown_nice_t niceness, int restart)
Definition: asterisk.c:1975
static char * cli_prompt(EditLine *editline)
Definition: asterisk.c:2797
static void set_title(char *text)
Set an X-term or screen title.
Definition: asterisk.c:1777
static char * _argv[256]
Definition: asterisk.c:361
static int register_atexit(void(*func)(void), int is_cleanup)
Definition: asterisk.c:1043
static char * handle_clear_profile(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: asterisk.c:954
static int wait_for_channels_to_die(shutdown_nice_t niceness, int seconds)
Definition: asterisk.c:1945
static struct ast_threadstorage console_state
Definition: asterisk.c:2226
static int ast_makesocket(void)
Definition: asterisk.c:1610
#define DEFINE_PROFILE_MIN_MAX_VALUES
Definition: asterisk.c:906
unsigned int need_quit_handler
Definition: asterisk.c:407
static int canary_pid
Definition: asterisk.c:393
static int ast_tryconnect(void)
Definition: asterisk.c:1696
static void * canary_thread(void *unused)
Definition: asterisk.c:3502
static void * listener(void *unused)
Definition: asterisk.c:1530
static struct ast_cli_entry cli_asterisk[]
Definition: asterisk.c:2643
static int fdsend(int fd, const char *s)
Definition: asterisk.c:1080
static int ast_el_write_history(const char *)
Definition: asterisk.c:3187
static int show_cli_help(void)
Definition: asterisk.c:3404
static void ast_el_read_default_histfile(void)
Definition: asterisk.c:3240
static char * handle_show_profile(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: asterisk.c:919
static void env_init(void)
Definition: asterisk.c:3583
static int ast_consock
Definition: asterisk.c:321
struct timeval ast_startuptime
Definition: asterisk.c:343
static const char * startup_commands_phase_str[]
Definition: asterisk.c:3546
static void read_pjproject_startup_options(void)
Definition: asterisk.c:3443
static const char license_lines[]
Definition: asterisk.c:2587
void ast_unreplace_sigchld(void)
Restore the SIGCHLD handler.
Definition: asterisk.c:1127
static void really_quit(int num, shutdown_nice_t niceness, int restart)
Definition: asterisk.c:2058
static int ast_socket
Definition: asterisk.c:319
pid_t ast_mainpid
Definition: asterisk.c:322
static void ast_el_write_default_histfile(void)
Definition: asterisk.c:3245
#define AF_LOCAL
Definition: asterisk.c:299
static int multi_thread_safe
Definition: asterisk.c:395
static struct ast_vector_string * ast_el_strtoarr(char *buf)
Definition: asterisk.c:2923
static void __quit_handler(int num)
Definition: asterisk.c:2154
void ast_console_puts_mutable_full(const char *message, int level, int sublevel)
log the string to the console, and all attached console clients
Definition: asterisk.c:1335
static void set_icon(char *text)
Definition: asterisk.c:1783
static void print_intro_message(const char *runuser, const char *rungroup)
Definition: asterisk.c:3595
static struct sigaction ignore_sig_handler
Definition: asterisk.c:1101
static struct sigaction null_sig_handler
Definition: asterisk.c:1096
struct console consoles[AST_MAX_CONNECTS]
Definition: asterisk.c:350
int64_t ast_profile(int i, int64_t delta)
Definition: asterisk.c:844
static struct sigaction urg_handler
Definition: asterisk.c:1728
static void run_startup_commands(enum startup_commands_phase phase)
Definition: asterisk.c:3553
Asterisk main include file. File version handling, generic pbx functions.
#define sched_setscheduler
Definition: asterisk.h:51
int ast_pbx_init(void)
Definition: pbx.c:9004
#define setpriority
Definition: asterisk.h:50
int ast_fd_init(void)
Definition: astfd.c:371
#define PATH_MAX
Definition: asterisk.h:40
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: astmm.h:288
#define ast_free(a)
Definition: astmm.h:180
#define ast_realloc(p, len)
A wrapper for realloc()
Definition: astmm.h:226
#define ast_strdup(str)
A wrapper for strdup()
Definition: astmm.h:241
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: astmm.h:298
void ast_free_ptr(void *ptr)
free() wrapper
Definition: astmm.c:1739
#define ast_asprintf(ret, fmt,...)
A wrapper for asprintf()
Definition: astmm.h:267
#define ast_calloc(num, len)
A wrapper for calloc()
Definition: astmm.h:202
#define ast_log
Definition: astobj2.c:42
Bucket File API.
int ast_bucket_init(void)
Initialize bucket support.
Definition: bucket.c:924
const char * ast_build_os
Definition: buildinfo.c:32
const char * ast_build_machine
Definition: buildinfo.c:31
const char * ast_build_hostname
Definition: buildinfo.c:29
const char * ast_build_user
Definition: buildinfo.c:34
const char * ast_build_date
Definition: buildinfo.c:33
const char * ast_build_kernel
Definition: buildinfo.c:30
CallerID (and other GR30) management and generation Includes code and algorithms from the Zapata libr...
void callerid_init(void)
CallerID Initialization.
Definition: callerid.c:116
Call Detail Record API.
int ast_cdr_is_enabled(void)
Return TRUE if CDR subsystem is enabled.
Definition: cdr.c:2981
void ast_cdr_engine_term(void)
Definition: cdr.c:4736
static const char desc[]
Definition: cdr_radius.c:84
static PGresult * result
Definition: cel_pgsql.c:84
static char version[AST_MAX_EXTENSION]
Definition: chan_ooh323.c:391
General Asterisk PBX channel definitions.
void ast_softhangup_all(void)
Soft hangup all active channels.
Definition: channel.c:492
const char * ast_channel_get_current_storage_driver_name(void)
Get the name of the current channel storage driver.
Definition: channel.c:7978
int ast_undestroyed_channels(void)
Definition: channel.c:503
int ast_active_channels(void)
returns number of active/allocated channels
Definition: channel.c:498
static int active_channels(struct ast_channelstorage_instance *driver)
returns number of active/allocated channels
Standard Command Line Interface.
#define CLI_SHOWUSAGE
Definition: cli.h:45
#define AST_CLI_COMPLETE_EOF
Definition: cli.h:52
#define CLI_SUCCESS
Definition: cli.h:44
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: clicompat.c:30
#define AST_CLI_DEFINE(fn, txt,...)
Definition: cli.h:197
void ast_cli(int fd, const char *fmt,...)
Definition: clicompat.c:6
int ast_cli_allow_at_shutdown(struct ast_cli_entry *e)
Allow a CLI command to be executed while Asterisk is shutting down.
Definition: main/cli.c:3068
int ast_cli_command_multiple_full(int uid, int gid, int fd, size_t size, const char *s)
Executes multiple CLI commands Interpret strings separated by NULL and execute each one,...
Definition: main/cli.c:3046
ast_cli_command
calling arguments for new-style handlers.
Definition: cli.h:151
@ CLI_INIT
Definition: cli.h:152
@ CLI_GENERATE
Definition: cli.h:153
struct ast_vector_string * ast_cli_completion_vector(const char *text, const char *word)
Generates a vector of strings for CLI completion.
Definition: main/cli.c:2773
#define ast_cli_register_multiple(e, len)
Register multiple commands.
Definition: cli.h:265
Codec API.
int ast_codec_init(void)
Initialize codec support within the core.
Definition: codec.c:250
int ast_codec_builtin_init(void)
Initialize built-in codecs within the core.
Device state management.
int devstate_init(void)
Initialize the device state core.
Definition: devicestate.c:899
char buf[BUFSIZE]
Definition: eagi_proxy.c:66
Endpoint abstractions.
void ast_verbose(const char *fmt,...)
Definition: extconf.c:2206
#define min(a, b)
Definition: f2c.h:197
#define max(a, b)
Definition: f2c.h:198
Generic File Format Support. Should be included by clients of the file handling routines....
Media Format API.
int ast_format_init(void)
Initialize media format support.
Definition: format.c:77
Media Format Cache API.
int ast_format_cache_init(void)
Initialize format cache support within the core.
Definition: format_cache.c:364
static const char name[]
Definition: format_mp3.c:68
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
int ast_manager_check_enabled(void)
Check if AMI is enabled.
Definition: manager.c:684
int ast_webmanager_check_enabled(void)
Check if AMI/HTTP is enabled.
Definition: manager.c:689
void ast_manager_publish_event(const char *type, int class_type, struct ast_json *obj)
Publish an event to AMI.
Definition: manager.c:638
void ast_init_logger_for_socket_console(void)
load logger.conf configuration for console socket connections
Definition: logger.c:710
int ast_option_rtpusedynamic
Definition: options.c:89
int ast_option_maxfiles
Definition: options.c:82
int option_debug
Definition: options.c:70
int ast_verb_sys_level
Definition: options.c:65
int ast_option_maxcalls
Definition: options.c:80
int ast_option_disable_remote_console_shell
Definition: options.c:91
int ast_option_pjproject_log_level
Definition: options.c:75
double ast_option_maxload
Definition: options.c:78
unsigned int ast_option_rtpptdynamic
Definition: options.c:90
int option_verbose
Definition: options.c:68
struct ast_flags ast_options
Definition: options.c:62
unsigned int option_dtmfminduration
Definition: options.c:84
int ast_option_pjproject_cache_pools
Definition: options.c:76
long option_minmemfree
Definition: options.c:87
int option_trace
Definition: options.c:72
@ AST_OPT_FLAG_HIGH_PRIORITY
Definition: options.h:49
@ AST_OPT_FLAG_GENERIC_PLC
Definition: options.h:101
@ AST_OPT_FLAG_TRANSCODE_VIA_SLIN
Definition: options.h:61
@ AST_OPT_FLAG_EXEC_INCLUDES
Definition: options.h:41
@ AST_OPT_FLAG_NO_COLOR
Definition: options.h:57
@ AST_OPT_FLAG_NO_FORK
Definition: options.h:43
@ AST_OPT_FLAG_TRANSMIT_SILENCE
Definition: options.h:75
@ AST_OPT_FLAG_ALWAYS_FORK
Definition: options.h:83
@ AST_OPT_FLAG_QUIET
Definition: options.h:45
@ AST_OPT_FLAG_GENERIC_PLC_ON_EQUAL_CODECS
Definition: options.h:103
@ AST_OPT_FLAG_MUTE
Definition: options.h:85
@ AST_OPT_FLAG_TIMESTAMP
Definition: options.h:69
@ AST_OPT_FLAG_EXEC
Definition: options.h:55
@ AST_OPT_FLAG_CACHE_RECORD_FILES
Definition: options.h:67
@ AST_OPT_FLAG_FULLY_BOOTED
Definition: options.h:59
@ AST_OPT_FLAG_INIT_KEYS
Definition: options.h:51
@ AST_OPT_FLAG_CONSOLE
Definition: options.h:47
@ AST_OPT_FLAG_FORCE_BLACK_BACKGROUND
Definition: options.h:95
@ AST_OPT_FLAG_LIGHT_BACKGROUND
Definition: options.h:91
@ AST_OPT_FLAG_REMOTE
Definition: options.h:53
@ AST_OPT_FLAG_DUMP_CORE
Definition: options.h:65
@ AST_OPT_FLAG_RECONNECT
Definition: options.h:73
static char prefix[MAX_PREFIX]
Definition: http.c:144
General Asterisk channel definitions for image handling.
int ast_image_init(void)
Initialize image stuff Initializes all the various image stuff. Basically just registers the cli stuf...
Definition: image.c:212
Application convenience functions, designed to give consistent look and feel to Asterisk apps.
int app_init(void)
Initialize the application core.
Definition: main/app.c:3365
void ast_close_fds_above_n(int n)
Common routine for child processes, to close all fds prior to exec(2)
Definition: main/app.c:3202
Configuration File Parser.
struct ast_config * ast_config_load2(const char *filename, const char *who_asked, struct ast_flags flags)
Load a config file.
Definition: main/config.c:3541
#define CONFIG_STATUS_FILEMISSING
@ CONFIG_FLAG_NOCACHE
@ CONFIG_FLAG_NOREALTIME
int ast_realtime_enabled(void)
Check if there's any realtime engines loaded.
Definition: main/config.c:3764
#define CONFIG_STATUS_FILEUNCHANGED
#define CONFIG_STATUS_FILEINVALID
void ast_config_destroy(struct ast_config *cfg)
Destroys a config.
Definition: extconf.c:1289
struct ast_variable * ast_variable_browse(const struct ast_config *config, const char *category_name)
Definition: extconf.c:1215
int register_config_cli(void)
Exposed initialization method for core process.
Definition: main/config.c:4456
#define VERBOSE_PREFIX_3
void ast_verb_console_unregister(void)
Unregister this thread's console verbosity level.
Definition: logger.c:2637
void ast_verb_console_register(int *level)
Register this thread's console verbosity level pointer.
Definition: logger.c:2621
#define NUMLOGLEVELS
#define ast_debug(level,...)
Log a DEBUG message.
#define VERBOSE_PREFIX_10
#define VERBOSE_PREFIX_6
int ast_is_logger_initialized(void)
Test if logger is initialized.
Definition: logger.c:2150
#define VERBOSE_PREFIX_2
#define VERBOSE_PREFIX_8
#define VERBOSE_PREFIX_7
#define VERBOSE_PREFIX_4
#define __LOG_VERBOSE
#define VERBOSE_PREFIX_5
#define VERBOSE_PREFIX_1
#define LOG_ERROR
#define VERBOSE_PREFIX_9
#define ast_verb(level,...)
#define LOG_WARNING
int ast_verb_console_get(void)
Get this thread's console verbosity level.
Definition: logger.c:2648
const char * ast_logger_get_dateformat(void)
Get the logger configured date format.
Definition: logger.c:2902
#define VERBOSE_MAGIC2LEVEL(x)
#define VERBOSE_HASMAGIC(x)
I/O Management (derived from Cheops-NG)
int ast_get_termcols(int fd)
Columns of Terminal.
Definition: io.c:373
int ast_sd_notify(const char *state)
a wrapper for sd_notify(): notify systemd of any state changes.
Definition: io.c:392
int ast_sd_get_fd_un(int type, const char *path)
Find a listening AF_LOCAL file descriptor provided by socket activation.
Definition: io.c:454
Asterisk JSON abstraction layer.
void ast_json_unref(struct ast_json *value)
Decrease refcount on value. If refcount reaches zero, value is freed.
Definition: json.c:73
struct ast_json * ast_json_pack(char const *format,...)
Helper for creating complex JSON values.
Definition: json.c:612
int ast_json_init(void)
Initialize the JSON library.
Definition: json.c:726
A set of macros to manage forward-linked lists.
#define AST_RWLIST_REMOVE_CURRENT
Definition: linkedlists.h:570
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:78
#define AST_LIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a list of specified type, statically initialized.
Definition: linkedlists.h:291
#define AST_RWLIST_TRAVERSE_SAFE_BEGIN
Definition: linkedlists.h:545
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:52
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:151
#define AST_RWLIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a read/write list of specified type, statically initialized.
Definition: linkedlists.h:333
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
Definition: linkedlists.h:410
#define AST_RWLIST_TRAVERSE_SAFE_END
Definition: linkedlists.h:617
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:615
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:40
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:494
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Definition: linkedlists.h:711
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:529
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: linkedlists.h:557
#define AST_RWLIST_INSERT_HEAD
Definition: linkedlists.h:718
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:833
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:140
#define AST_RWLIST_ENTRY
Definition: linkedlists.h:415
struct ast_tm * ast_localtime(const struct timeval *timep, struct ast_tm *p_tm, const char *zone)
Timezone-independent version of localtime_r(3).
Definition: localtime.c:1739
int ast_strftime(char *buf, size_t len, const char *format, const struct ast_tm *tm)
Special version of strftime(3) that handles fractions of a second. Takes the same arguments as strfti...
Definition: localtime.c:2524
Asterisk locking-related definitions:
#define AST_PTHREADT_NULL
Definition: lock.h:73
#define ast_mutex_unlock(a)
Definition: lock.h:197
#define ast_mutex_lock(a)
Definition: lock.h:196
#define AST_MUTEX_DEFINE_STATIC(mutex)
Definition: lock.h:527
static char * levels[NUMLOGLEVELS]
Logging channels used in the Asterisk logging system.
Definition: logger.c:211
static char hostname[MAXHOSTNAMELEN]
Definition: logger.c:116
#define WEXITSTATUS(status)
#define WIFEXITED(status)
int errno
The AMI - Asterisk Manager Interface - is a TCP protocol created to manage Asterisk with third-party ...
#define EVENT_FLAG_SYSTEM
Definition: manager.h:75
An in-memory media cache.
int ast_media_cache_init(void)
Initialize the media cache.
Definition: media_cache.c:671
Asterisk module definitions.
enum ast_module_reload_result ast_module_reload(const char *name)
Reload asterisk modules.
Definition: loader.c:1730
Asterisk MWI API.
int mwi_init(void)
Initialize the mwi core.
Definition: mwi.c:507
Wrapper for network related headers, masking differences between various operating systems....
#define MAXHOSTNAMELEN
Definition: network.h:69
Options provided by main asterisk program.
#define ast_opt_dump_core
Definition: options.h:120
#define ast_opt_remote
Definition: options.h:115
int ast_language_is_prefix
The following variable controls the layout of localized sound files. If 0, use the historical layout ...
Definition: file.c:67
#define MAX_PJ_LOG_MAX_LEVEL
Definition: options.h:142
#define ast_opt_exec
Definition: options.h:116
#define ast_opt_reconnect
Definition: options.h:124
#define DEFAULT_PJPROJECT_CACHE_POOLS
Definition: options.h:179
#define ast_opt_console
Definition: options.h:112
#define ast_opt_hide_connect
Definition: options.h:133
#define ast_opt_mute
Definition: options.h:128
#define ast_opt_high_priority
Definition: options.h:113
#define ast_opt_timestamp
Definition: options.h:123
#define ast_opt_always_fork
Definition: options.h:127
#define ast_opt_no_fork
Definition: options.h:110
#define ast_opt_hide_messaging_ami_events
Definition: options.h:138
#define ast_opt_sounds_search_custom
Definition: options.h:139
#define DEFAULT_PJ_LOG_MAX_LEVEL
Definition: options.h:150
#define ast_opt_cache_media_frames
Definition: options.h:122
char ast_defaultlanguage[]
Definition: options.c:99
Asterisk file paths, configured in asterisk.conf.
const char * ast_config_AST_KEY_DIR
Definition: options.c:162
const char * ast_config_AST_CACHE_DIR
Definition: options.c:151
const char * ast_config_AST_RUN_GROUP
Definition: options.c:170
const char * ast_config_AST_SOCKET
Definition: options.c:168
const char * ast_config_AST_RUN_USER
Definition: options.c:169
const char * ast_config_AST_CTL_PERMISSIONS
Definition: options.c:173
const char * ast_config_AST_CTL_GROUP
Definition: options.c:175
const char * ast_config_AST_MODULE_DIR
Definition: options.c:154
const char * ast_config_AST_PID
Definition: options.c:167
const char * ast_config_AST_RUN_DIR
Definition: options.c:163
const char * ast_config_AST_DATA_DIR
Definition: options.c:159
const char * ast_config_AST_CONFIG_DIR
Definition: options.c:152
const char * ast_config_AST_SPOOL_DIR
Definition: options.c:155
const char * ast_config_AST_AGI_DIR
Definition: options.c:161
const char * ast_config_AST_VAR_DIR
Definition: options.c:158
const char * ast_config_AST_SYSTEM_NAME
Definition: options.c:171
const char * ast_config_AST_SBIN_DIR
Definition: options.c:164
const char * ast_config_AST_CONFIG_FILE
Definition: options.c:153
const char * ast_config_AST_LOG_DIR
Definition: options.c:160
const char * ast_config_AST_CTL_OWNER
Definition: options.c:174
const char * ast_config_AST_DB
Definition: options.c:166
Core PBX routines and definitions.
Call Pickup API.
int ast_pickup_init(void)
Initialize pickup.
Definition: pickup.c:402
#define ast_poll(a, b, c)
Definition: poll-compat.h:88
Presence state management.
int ast_presence_state_engine_init(void)
static int total
Definition: res_adsi.c:970
#define NULL
Definition: resample.c:96
Pluggable RTP Architecture.
#define AST_RTP_PT_LAST_REASSIGN
Definition: rtp_engine.h:95
#define AST_RTP_MAX_PT
Definition: rtp_engine.h:83
#define AST_RTP_PT_FIRST_DYNAMIC
Definition: rtp_engine.h:92
Scheduler Routines (derived from cheops)
Security Event Reporting API.
int ast_security_stasis_init(void)
initializes stasis topic/event types for ast_security_topic and ast_security_event_type
#define FD_SET(fd, fds)
Definition: select.h:58
#define ast_FDMAX
Definition: select.h:41
unsigned int ast_FD_SETSIZE
Definition: poll.c:86
static int ast_select(int nfds, ast_fdset *rfds, ast_fdset *wfds, ast_fdset *efds, struct timeval *tvp)
Waits for activity on a group of channels.
Definition: select.h:79
#define FD_ZERO(a)
Definition: select.h:49
Sorcery Data Access Layer API.
int ast_sorcery_init(void)
Initialize the sorcery API.
Definition: sorcery.c:387
Stasis Message Bus API. See Stasis Message Bus API for detailed documentation.
int stasis_init(void)
Initialize the Stasis subsystem.
Definition: stasis.c:3088
Endpoint abstractions.
int ast_endpoint_stasis_init(void)
Initialization function for endpoint stasis support.
int ast_stasis_system_init(void)
Initialize the stasis system topic and message types.
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition: strings.h:1139
static force_inline char * ast_str_to_lower(char *str)
Convert a string to all lower-case.
Definition: strings.h:1321
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:761
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one.
Definition: strings.h:80
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:65
int attribute_pure ast_false(const char *val)
Make sure something is false. Determine if a string containing a boolean value is "false"....
Definition: utils.c:2216
void ast_str_reset(struct ast_str *buf)
Reset the content of a dynamic string. Useful before a series of ast_str_append.
Definition: strings.h:693
int ast_in_delimited_string(const char *needle, const char *haystack, char delim)
Check if there is an exact match for 'needle' between delimiters in 'haystack'.
Definition: strings.c:466
#define ast_str_create(init_len)
Create a malloc'ed dynamic length string.
Definition: strings.h:659
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:1113
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:425
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
Definition: strings.h:223
int is_cleanup
Definition: asterisk.c:337
void(* func)(void)
Definition: asterisk.c:336
struct ast_atexit::@300 list
descriptor for a cli entry.
Definition: cli.h:171
int args
This gets set in ast_cli_register()
Definition: cli.h:185
char * command
Definition: cli.h:186
const char * usage
Definition: cli.h:177
Structure used to handle boolean flags.
Definition: utils.h:199
Abstract JSON element (object, array, string, int, ...).
Support for dynamic strings.
Definition: strings.h:623
Structure for variables, used for configurations and for channel variables.
struct ast_variable * next
String vector definitions.
Definition: vector.h:55
int mute
Definition: asterisk.c:327
int uid
Definition: asterisk.c:328
int gid
Definition: asterisk.c:329
int p[2]
Definition: asterisk.c:325
int fd
Definition: asterisk.c:324
int option_verbose
Definition: asterisk.c:332
pthread_t t
Definition: asterisk.c:326
int levels[NUMLOGLEVELS]
Definition: asterisk.c:330
int max_size
Definition: asterisk.c:800
struct profile_entry e[0]
Definition: asterisk.c:801
Definition: asterisk.c:790
int64_t events
Definition: asterisk.c:795
int64_t mark
Definition: asterisk.c:793
const char * name
Definition: asterisk.c:791
int64_t value
Definition: asterisk.c:794
uint64_t scale
Definition: asterisk.c:792
Definition: sched.c:76
int value
Definition: syslog.c:37
TTY/TDD Generation support.
void tdd_init(void)
Definition: tdd.c:94
Handy terminal functions for vt* terms.
#define COLOR_BRGREEN
Definition: term.h:55
const char * term_quit(void)
Definition: term.c:412
#define COLOR_GRAY
Definition: term.h:51
int ast_term_color_code(struct ast_str **str, int fgcolor, int bgcolor)
Append a color sequence to an ast_str.
Definition: term.c:296
const char * ast_term_reset(void)
Returns the terminal reset code.
Definition: term.c:357
#define COLOR_WHITE
Definition: term.h:64
const char * ast_term_color(int fgcolor, int bgcolor)
Return a color sequence string.
Definition: term.c:341
const char * term_end(void)
Definition: term.c:407
#define COLOR_BLACK
Definition: term.h:50
#define COLORIZE(fg, bg, str)
Definition: term.h:72
#define COLORIZE_FMT
Shortcut macros for coloring a set of text.
Definition: term.h:71
Test Framework API.
static struct test_val a
static struct test_val c
#define AST_THREADSTORAGE_CUSTOM(a, b, c)
Define a thread storage variable, with custom initialization and cleanup.
void * ast_threadstorage_get(struct ast_threadstorage *ts, size_t init_size)
Retrieve thread storage.
struct timeval ast_tvsub(struct timeval a, struct timeval b)
Returns the difference of two timevals a - b.
Definition: extconf.c:2297
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:159
Support for translation of data formats. translate.c.
int ast_translate_init(void)
Initialize the translation matrix and index to format conversion table.
Definition: translate.c:1675
u-Law to Signed linear conversion
void ast_ulaw_init(void)
Set up mu-law conversion table.
Definition: ulaw.c:173
UTF-8 information and validation functions.
int ast_utf8_init(void)
Register UTF-8 tests.
Definition: utf8.c:919
static int inbuf(struct baseio *bio, FILE *fi)
utility used by inchar(), for base_encode()
Definition: utils.c:590
Utility functions.
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define RAII_VAR(vartype, varname, initval, dtor)
Declare a variable that will call a destructor function when it goes out of scope.
Definition: utils.h:941
#define ast_assert(a)
Definition: utils.h:739
#define ast_pthread_create_background(a, b, c, d)
Definition: utils.h:592
char * ast_eid_to_str(char *s, int maxlen, struct ast_eid *eid)
Convert an EID to a string.
Definition: utils.c:2839
int ast_get_tid(void)
Get current thread ID.
Definition: utils.c:2752
#define ast_clear_flag(p, flag)
Definition: utils.h:77
int ast_utils_init(void)
Definition: utils.c:2617
#define ast_pthread_create_detached(a, b, c, d)
Definition: utils.h:588
#define ast_fd_set_flags(fd, flags)
Set flags on the given file descriptor.
Definition: utils.h:1039
#define ast_pthread_create_detached_background(a, b, c, d)
Definition: utils.h:597
#define ast_set_flag(p, flag)
Definition: utils.h:70
#define ARRAY_LEN(a)
Definition: utils.h:666
struct ast_eid ast_eid_default
Global EID.
Definition: options.c:94
Universally unique identifier support.
#define AST_UUID_STR_LEN
Definition: uuid.h:27
void ast_uuid_init(void)
Initialize the UUID system.
Definition: uuid.c:192
char * ast_uuid_generate_str(char *buf, size_t size)
Generate a UUID string.
Definition: uuid.c:141
#define AST_VECTOR_SIZE(vec)
Get the number of elements in a vector.
Definition: vector.h:620
#define AST_VECTOR_PTR_FREE(vec)
Deallocates this vector pointer.
Definition: vector.h:200
#define AST_VECTOR_APPEND(vec, elem)
Append an element to a vector, growing the vector if needed.
Definition: vector.h:267
#define AST_VECTOR_CALLBACK_VOID(vec, callback,...)
Execute a callback on every element in a vector disregarding callback return.
Definition: vector.h:873
#define AST_VECTOR_GET(vec, idx)
Get an element from a vector.
Definition: vector.h:691
Asterisk XML Documentation API.