1999-11-15 04:57:28 +00:00
/*
2005-09-14 20:46:50 +00:00
* Asterisk - - An open source telephony toolkit .
1999-11-15 04:57:28 +00:00
*
2018-03-27 13:27:09 +00:00
* Copyright ( C ) 1999 - 2018 , Digium , Inc .
1999-11-15 04:57:28 +00:00
*
2004-08-27 03:28:32 +00:00
* Mark Spencer < markster @ digium . com >
1999-11-15 04:57:28 +00:00
*
2005-09-14 20:46:50 +00:00
* See http : //www.asterisk.org for more information about
* the Asterisk project . Please do not directly contact
* any of the maintainers of this project for assistance ;
* the project provides a web site , mailing lists and IRC
* channels for your use .
*
1999-11-15 04:57:28 +00:00
* This program is free software , distributed under the terms of
2005-09-14 20:46:50 +00:00
* the GNU General Public License Version 2. See the LICENSE file
* at the top of the source tree .
*/
2005-10-24 20:12:06 +00:00
/* Doxygenified Copyright Header */
/*!
2009-10-30 04:08:39 +00:00
* \ mainpage Asterisk - - The Open Source Telephony Project
2005-10-24 20:12:06 +00:00
*
2012-09-21 17:14:59 +00:00
* \ par Welcome
*
* This documentation created by the Doxygen project clearly explains the
* internals of the Asterisk software . This documentation contains basic
* examples , developer documentation , support information , and information
* for upgrading .
2013-07-05 17:33:33 +00:00
*
2012-10-01 23:39:45 +00:00
* \ section community Community
* Asterisk is a big project and has a busy community . Look at the
* resources for questions and stick around to help answer questions .
* \ li \ ref asterisk_community_resources
*
2005-11-14 19:00:38 +00:00
* \ par Developer Documentation for Asterisk
2008-12-09 22:38:41 +00:00
*
2012-03-22 19:51:16 +00:00
* This is the main developer documentation for Asterisk . It is
* generated by running " make progdocs " from the Asterisk source tree .
2008-12-09 22:38:41 +00:00
*
2012-03-22 19:51:16 +00:00
* In addition to the information available on the Asterisk source code ,
* please see the appendices for information on coding guidelines ,
2008-12-09 22:38:41 +00:00
* release management , commit policies , and more .
*
2009-10-30 04:08:39 +00:00
* \ arg \ ref AsteriskArchitecture
*
2005-11-14 19:00:38 +00:00
* \ par Additional documentation
2008-07-25 14:57:11 +00:00
* \ arg \ ref Licensing
2012-03-22 19:51:16 +00:00
* \ arg \ ref DevDoc
2012-10-01 23:39:45 +00:00
* \ arg \ ref configuration_file
2012-10-18 14:17:40 +00:00
* \ arg \ ref channel_drivers
* \ arg \ ref applications
2005-10-24 20:12:06 +00:00
*
2008-12-09 22:38:41 +00:00
* \ section copyright Copyright and Author
2005-10-24 20:12:06 +00:00
*
2018-03-27 13:27:09 +00:00
* Copyright ( C ) 1999 - 2018 , Digium , Inc .
2008-12-09 22:38:41 +00:00
* Asterisk is a < a href = " http://www.digium.com/en/company/view-policy.php?id=Trademark-Policy " > registered trademark < / a >
2014-03-03 02:08:58 +00:00
* of < a rel = " nofollow " href = " http://www.digium.com " > Digium , Inc < / a > .
2005-10-24 20:12:06 +00:00
*
* \ author Mark Spencer < markster @ digium . com >
*
* See http : //www.asterisk.org for more information about
* the Asterisk project . Please do not directly contact
* any of the maintainers of this project for assistance ;
2008-12-09 22:38:41 +00:00
* the project provides a web site , mailing lists , and IRC
2005-10-24 20:12:06 +00:00
* channels for your use .
2012-09-21 17:14:59 +00:00
*
2012-10-01 23:39:45 +00:00
*/
/*!
* \ page asterisk_community_resources Asterisk Community Resources
* \ par Websites
* \ li http : //www.asterisk.org Asterisk Homepage
* \ li http : //wiki.asterisk.org Asterisk Wiki
*
* \ par Mailing Lists
* \ par
* All lists : http : //lists.digium.com/mailman/listinfo
* \ li aadk - commits SVN commits to the AADK repository
* \ li asterisk - addons - commits SVN commits to the Asterisk addons project
* \ li asterisk - announce [ no description available ]
* \ li asterisk - biz Commercial and Business - Oriented Asterisk Discussion
* \ li Asterisk - BSD Asterisk on BSD discussion
* \ li asterisk - bugs [ no description available ]
* \ li asterisk - commits SVN commits to the Asterisk project
* \ li asterisk - dev Asterisk Developers Mailing List
* \ li asterisk - doc Discussions regarding The Asterisk Documentation Project
* \ li asterisk - embedded Asterisk Embedded Development
* \ li asterisk - gui Asterisk GUI project discussion
* \ li asterisk - gui - commits SVN commits to the Asterisk - GUI project
* \ li asterisk - ha - clustering Asterisk High Availability and Clustering List - Non - Commercial Discussion
* \ li Asterisk - i18n Discussion of Asterisk internationalization
* \ li asterisk - r2 [ no description available ]
* \ li asterisk - scf - commits Commits to the Asterisk SCF project code repositories
* \ li asterisk - scf - committee Asterisk SCF Steering Committee discussions
* \ li asterisk - scf - dev Asterisk SCF Developers Mailing List
* \ li asterisk - scf - wiki - changes Changes to the Asterisk SCF space on wiki . asterisk . org
* \ li asterisk - security Asterisk Security Discussion
* \ li asterisk - speech - rec Use of speech recognition in Asterisk
* \ li asterisk - ss7 [ no description available ]
* \ li asterisk - users Asterisk Users Mailing List - Non - Commercial Discussion
* \ li asterisk - video Development discussion of video media support in Asterisk
* \ li asterisk - wiki - changes Changes to the Asterisk space on wiki . asterisk . org
* \ li asterisknow AsteriskNOW Discussion
* \ li dahdi - commits SVN commits to the DAHDI project
* \ li digium - announce Digium Product Announcements
* \ li Dundi Distributed Universal Number Discovery
* \ li libiax2 - commits SVN commits to the libiax2 project
* \ li libpri - commits SVN commits to the libpri project
* \ li libss7 - commits SVN commits to the libss7 project
* \ li svn - commits SVN commits to the Digium repositories
* \ li Test - results Results from automated testing
* \ li thirdparty - commits SVN commits to the Digium third - party software repository
* \ li zaptel - commits SVN commits to the Zaptel project
*
* \ par Forums
* \ li Forums are located at http : //forums.asterisk.org/
*
* \ par IRC
* \ par
* Use http : //www.freenode.net IRC server to connect with Asterisk
* developers and users in realtime .
2013-07-05 17:33:33 +00:00
*
2012-10-01 23:39:45 +00:00
* \ li \ verbatim # asterisk \ endverbatim Asterisk Users Room
* \ li \ verbatim # asterisk - dev \ endverbatim Asterisk Developers Room
*
* \ par More
* \ par
* If you would like to add a resource to this list please create an issue
* on the issue tracker with a patch .
2005-10-24 20:12:06 +00:00
*/
/*! \file
2012-09-21 17:14:59 +00:00
* \ brief Top level source file for Asterisk - the Open Source PBX .
* Implementation of PBX core functions and CLI interface .
1999-11-15 04:57:28 +00:00
*/
2012-10-18 14:17:40 +00:00
/*! \li \ref asterisk.c uses the configuration file \ref asterisk.conf
2012-10-01 23:39:45 +00:00
* \ addtogroup configuration_file
*/
/*! \page asterisk.conf asterisk.conf
* \ verbinclude asterisk . conf . sample
*/
2012-06-15 16:20:16 +00:00
/*** MODULEINFO
< support_level > core < / support_level >
* * */
2006-06-07 18:54:56 +00:00
# include "asterisk.h"
2007-11-20 22:18:21 +00:00
# include "asterisk/_private.h"
2007-04-09 03:04:07 +00:00
# undef sched_setscheduler
# undef setpriority
2005-04-29 17:24:58 +00:00
# include <sys/time.h>
2005-04-22 13:11:34 +00:00
# include <fcntl.h>
# include <signal.h>
# include <sched.h>
# include <sys/un.h>
# include <sys/wait.h>
# include <ctype.h>
# include <sys/resource.h>
# include <grp.h>
# include <pwd.h>
# include <sys/stat.h>
2007-08-01 19:37:59 +00:00
# if defined(HAVE_SYSINFO)
2007-04-11 19:11:32 +00:00
# include <sys/sysinfo.h>
2008-12-16 20:08:34 +00:00
# elif defined(HAVE_SYSCTL)
# include <sys/param.h>
# include <sys/sysctl.h>
2009-01-14 19:36:57 +00:00
# include <sys/vmmeter.h>
2018-04-20 10:50:03 +00:00
# if defined(__FreeBSD__) || defined(__DragonFly__)
2009-01-14 19:36:57 +00:00
# include <vm/vm_param.h>
# endif
2009-01-12 14:35:09 +00:00
# if defined(HAVE_SWAPCTL)
2008-12-16 20:08:34 +00:00
# include <sys/swap.h>
2007-04-11 20:59:08 +00:00
# endif
2009-01-12 14:35:09 +00:00
# endif
2005-06-06 20:27:51 +00:00
# include <regex.h>
2012-07-25 12:21:54 +00:00
# include <histedit.h>
2005-04-22 13:11:34 +00:00
2006-03-02 22:27:50 +00:00
# if defined(SOLARIS)
2006-06-07 18:54:56 +00:00
int daemon ( int , int ) ; /* defined in libresolv of all places */
2007-09-12 16:24:45 +00:00
# include <sys/loadavg.h>
2006-03-02 22:27:50 +00:00
# endif
2005-04-22 13:11:34 +00:00
2008-04-08 17:00:55 +00:00
# ifdef linux
# include <sys/prctl.h>
# ifdef HAVE_CAP
# include <sys/capability.h>
# endif /* HAVE_CAP */
# endif /* linux */
2012-09-22 20:43:30 +00:00
/* we define here the variables so to better agree on the prototype */
# include "asterisk/paths.h"
2007-11-17 14:11:53 +00:00
# include "asterisk/network.h"
2005-04-21 06:02:45 +00:00
# include "asterisk/cli.h"
# include "asterisk/channel.h"
2011-02-03 16:22:10 +00:00
# include "asterisk/translate.h"
2013-08-02 02:32:44 +00:00
# include "asterisk/pickup.h"
2012-07-11 18:33:36 +00:00
# include "asterisk/acl.h"
2005-04-21 06:02:45 +00:00
# include "asterisk/ulaw.h"
# include "asterisk/alaw.h"
# include "asterisk/callerid.h"
# include "asterisk/image.h"
# include "asterisk/tdd.h"
# include "asterisk/term.h"
# include "asterisk/manager.h"
2005-06-03 01:42:31 +00:00
# include "asterisk/cdr.h"
2005-04-21 06:02:45 +00:00
# include "asterisk/pbx.h"
# include "asterisk/app.h"
# include "asterisk/lock.h"
# include "asterisk/utils.h"
# include "asterisk/file.h"
# include "asterisk/io.h"
# include "asterisk/config.h"
2008-02-26 20:33:08 +00:00
# include "asterisk/ast_version.h"
2005-06-06 20:27:51 +00:00
# include "asterisk/linkedlists.h"
2005-07-08 21:14:34 +00:00
# include "asterisk/devicestate.h"
2012-06-04 20:26:12 +00:00
# include "asterisk/presencestate.h"
2007-06-05 15:54:36 +00:00
# include "asterisk/module.h"
2008-10-30 16:49:02 +00:00
# include "asterisk/buildinfo.h"
2008-11-10 13:53:23 +00:00
# include "asterisk/xmldoc.h"
Merged revisions 182810 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/1.4
........
r182810 | russell | 2009-03-17 21:09:13 -0500 (Tue, 17 Mar 2009) | 44 lines
Fix cases where the internal poll() was not being used when it needed to be.
We have seen a number of problems caused by poll() not working properly on
Mac OSX. If you search around, you'll find a number of references to using
select() instead of poll() to work around these issues. In Asterisk, we've
had poll.c which implements poll() using select() internally. However, we
were still getting reports of problems.
vadim investigated a bit and realized that at least on his system, even
though we were compiling in poll.o, the system poll() was still being used.
So, the primary purpose of this patch is to ensure that we're using the
internal poll() when we want it to be used.
The changes are:
1) Remove logic for when internal poll should be used from the Makefile.
Instead, put it in the configure script. The logic in the configure
script is the same as it was in the Makefile. Ideally, we would have
a functionality test for the problem, but that's not actually possible,
since we would have to be able to run an application on the _target_
system to test poll() behavior.
2) Always include poll.o in the build, but it will be empty if AST_POLL_COMPAT
is not defined.
3) Change uses of poll() throughout the source tree to ast_poll(). I feel
that it is good practice to give the API call a new name when we are
changing its behavior and not using the system version directly in all cases.
So, normally, ast_poll() is just redefined to poll(). On systems where
AST_POLL_COMPAT is defined, ast_poll() is redefined to ast_internal_poll().
4) Change poll() in main/poll.c to be ast_internal_poll().
It's worth noting that any code that still uses poll() directly will work fine
(if they worked fine before). So, for example, out of tree modules that are
using poll() will not stop working or anything. However, for modules to work
properly on Mac OSX, ast_poll() needs to be used.
(closes issue #13404)
Reported by: agalbraith
Tested by: russell, vadim
http://reviewboard.digium.com/r/198/
........
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@182847 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-03-18 02:28:55 +00:00
# include "asterisk/poll-compat.h"
2009-12-22 16:09:11 +00:00
# include "asterisk/test.h"
Media Project Phase2: SILK 8khz-24khz, SLINEAR 8khz-192khz, SPEEX 32khz, hd audio ConfBridge, and other stuff
-Functional changes
1. Dynamic global format list build by codecs defined in codecs.conf
2. SILK 8khz, 12khz, 16khz, and 24khz with custom attributes defined in codecs.conf
3. Negotiation of SILK attributes in chan_sip.
4. SPEEX 32khz with translation
5. SLINEAR 8khz, 12khz, 24khz, 32khz, 44.1khz, 48khz, 96khz, 192khz with translation
using codec_resample.c
6. Various changes to RTP code required to properly handle the dynamic format list
and formats with attributes.
7. ConfBridge now dynamically jumps to the best possible sample rate. This allows
for conferences to take advantage of HD audio (Which sounds awesome)
8. Audiohooks are no longer limited to 8khz audio, and most effects have been
updated to take advantage of this such as Volume, DENOISE, PITCH_SHIFT.
9. codec_resample now uses its own code rather than depending on libresample.
-Organizational changes
Global format list is moved from frame.c to format.c
Various format specific functions moved from frame.c to format.c
Review: https://reviewboard.asterisk.org/r/1104/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@308582 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2011-02-22 23:04:49 +00:00
# include "asterisk/rtp_engine.h"
2011-02-03 16:22:10 +00:00
# include "asterisk/format.h"
Generic Advice of Charge.
Asterisk Generic AOC Representation
- Generic AOC encode/decode routines.
(Generic AOC must be encoded to be passed on the wire in the AST_CONTROL_AOC frame)
- AST_CONTROL_AOC frame type to represent generic encoded AOC data
- Manager events for AOC-S, AOC-D, and AOC-E messages
Asterisk App Support
- app_dial AOC-S pass-through support on call setup
- app_queue AOC-S pass-through support on call setup
AOC Unit Tests
- AOC Unit Tests for encode/decode routines
- AOC Unit Test for manager event representation.
SIP AOC Support
- Pass-through of generic AOC-D and AOC-E messages to snom phones via the
snom AOC specification.
- Creation of chan_sip page3 flags for the addition of the new
'snom_aoc_enabled' sip.conf option.
IAX AOC Support
- Natively supports AOC pass-through through the use of the new
AST_CONTROL_AOC frame type
DAHDI AOC Support
- ETSI PRI full AOC Pass-through support
- 'aoc_enable' chan_dahdi.conf option for independently enabling
pass-through of AOC-S, AOC-D, AOC-E.
- 'aoce_delayhangup' option for retrieving AOC-E on disconnect.
- DAHDI A() dial string option for requesting AOC services.
example usage:
;requests AOC-S, AOC-D, and AOC-E on call setup
exten=>1111,1,Dial(DAHDI/g1/1112/A(s,d,e))
Review: https://reviewboard.asterisk.org/r/552/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@267096 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2010-06-02 18:10:15 +00:00
# include "asterisk/aoc.h"
2012-12-11 21:04:45 +00:00
# include "asterisk/uuid.h"
2013-01-25 14:01:04 +00:00
# include "asterisk/sorcery.h"
2013-08-23 21:49:47 +00:00
# include "asterisk/bucket.h"
2013-03-08 15:15:13 +00:00
# include "asterisk/stasis.h"
2013-03-22 19:26:37 +00:00
# include "asterisk/json.h"
2013-05-08 13:39:08 +00:00
# include "asterisk/stasis_endpoints.h"
2013-07-08 14:42:57 +00:00
# include "asterisk/stasis_system.h"
2013-05-25 17:41:25 +00:00
# include "asterisk/security_events.h"
2013-10-04 16:01:48 +00:00
# include "asterisk/endpoints.h"
media formats: re-architect handling of media for performance improvements
In the old times media formats were represented using a bit field. This was
fast but had a few limitations.
1. Asterisk was limited in how many formats it could handle.
2. Formats, being a bit field, could not include any attribute information.
A format was strictly its type, e.g., "this is ulaw".
This was changed in Asterisk 10 (see
https://wiki.asterisk.org/wiki/display/AST/Media+Architecture+Proposal for
notes on that work) which led to the creation of the ast_format structure.
This structure allowed Asterisk to handle attributes and bundle information
with a format.
Additionally, ast_format_cap was created to act as a container for multiple
formats that, together, formed the capability of some entity. Another
mechanism was added to allow logic to be registered which performed format
attribute negotiation. Everywhere throughout the codebase Asterisk was
changed to use this strategy.
Unfortunately, in software, there is no free lunch. These new capabilities
came at a cost.
Performance analysis and profiling showed that we spend an inordinate
amount of time comparing, copying, and generally manipulating formats and
their related structures. Basic prototyping has shown that a reasonably
large performance improvement could be made in this area. This patch is the
result of that project, which overhauled the media format architecture
and its usage in Asterisk to improve performance.
Generally, the new philosophy for handling formats is as follows:
* The ast_format structure is reference counted. This removed a large amount
of the memory allocations and copying that was done in prior versions.
* In order to prevent race conditions while keeping things performant, the
ast_format structure is immutable by convention and lock-free. Violate this
tenet at your peril!
* Because formats are reference counted, codecs are also reference counted.
The Asterisk core generally provides built-in codecs and caches the
ast_format structures created to represent them. Generally, to prevent
inordinate amounts of module reference bumping, codecs and formats can be
added at run-time but cannot be removed.
* All compatibility with the bit field representation of codecs/formats has
been moved to a compatibility API. The primary user of this representation
is chan_iax2, which must continue to maintain its bit-field usage of formats
for interoperability concerns.
* When a format is negotiated with attributes, or when a format cannot be
represented by one of the cached formats, a new format object is created or
cloned from an existing format. That format may have the same codec
underlying it, but is a different format than a version of the format with
different attributes or without attributes.
* While formats are reference counted objects, the reference count maintained
on the format should be manipulated with care. Formats are generally cached
and will persist for the lifetime of Asterisk and do not explicitly need
to have their lifetime modified. An exception to this is when the user of a
format does not know where the format came from *and* the user may outlive
the provider of the format. This occurs, for example, when a format is read
from a channel: the channel may have a format with attributes (hence,
non-cached) and the user of the format may last longer than the channel (if
the reference to the channel is released prior to the format's reference).
For more information on this work, see the API design notes:
https://wiki.asterisk.org/wiki/display/AST/Media+Format+Rewrite
Finally, this work was the culmination of a large number of developer's
efforts. Extra thanks goes to Corey Farrell, who took on a large amount of the
work in the Asterisk core, chan_sip, and was an invaluable resource in peer
reviews throughout this project.
There were a substantial number of patches contributed during this work; the
following issues/patch names simply reflect some of the work (and will cause
the release scripts to give attribution to the individuals who work on them).
Reviews:
https://reviewboard.asterisk.org/r/3814
https://reviewboard.asterisk.org/r/3808
https://reviewboard.asterisk.org/r/3805
https://reviewboard.asterisk.org/r/3803
https://reviewboard.asterisk.org/r/3801
https://reviewboard.asterisk.org/r/3798
https://reviewboard.asterisk.org/r/3800
https://reviewboard.asterisk.org/r/3794
https://reviewboard.asterisk.org/r/3793
https://reviewboard.asterisk.org/r/3792
https://reviewboard.asterisk.org/r/3791
https://reviewboard.asterisk.org/r/3790
https://reviewboard.asterisk.org/r/3789
https://reviewboard.asterisk.org/r/3788
https://reviewboard.asterisk.org/r/3787
https://reviewboard.asterisk.org/r/3786
https://reviewboard.asterisk.org/r/3784
https://reviewboard.asterisk.org/r/3783
https://reviewboard.asterisk.org/r/3778
https://reviewboard.asterisk.org/r/3774
https://reviewboard.asterisk.org/r/3775
https://reviewboard.asterisk.org/r/3772
https://reviewboard.asterisk.org/r/3761
https://reviewboard.asterisk.org/r/3754
https://reviewboard.asterisk.org/r/3753
https://reviewboard.asterisk.org/r/3751
https://reviewboard.asterisk.org/r/3750
https://reviewboard.asterisk.org/r/3748
https://reviewboard.asterisk.org/r/3747
https://reviewboard.asterisk.org/r/3746
https://reviewboard.asterisk.org/r/3742
https://reviewboard.asterisk.org/r/3740
https://reviewboard.asterisk.org/r/3739
https://reviewboard.asterisk.org/r/3738
https://reviewboard.asterisk.org/r/3737
https://reviewboard.asterisk.org/r/3736
https://reviewboard.asterisk.org/r/3734
https://reviewboard.asterisk.org/r/3722
https://reviewboard.asterisk.org/r/3713
https://reviewboard.asterisk.org/r/3703
https://reviewboard.asterisk.org/r/3689
https://reviewboard.asterisk.org/r/3687
https://reviewboard.asterisk.org/r/3674
https://reviewboard.asterisk.org/r/3671
https://reviewboard.asterisk.org/r/3667
https://reviewboard.asterisk.org/r/3665
https://reviewboard.asterisk.org/r/3625
https://reviewboard.asterisk.org/r/3602
https://reviewboard.asterisk.org/r/3519
https://reviewboard.asterisk.org/r/3518
https://reviewboard.asterisk.org/r/3516
https://reviewboard.asterisk.org/r/3515
https://reviewboard.asterisk.org/r/3512
https://reviewboard.asterisk.org/r/3506
https://reviewboard.asterisk.org/r/3413
https://reviewboard.asterisk.org/r/3410
https://reviewboard.asterisk.org/r/3387
https://reviewboard.asterisk.org/r/3388
https://reviewboard.asterisk.org/r/3389
https://reviewboard.asterisk.org/r/3390
https://reviewboard.asterisk.org/r/3321
https://reviewboard.asterisk.org/r/3320
https://reviewboard.asterisk.org/r/3319
https://reviewboard.asterisk.org/r/3318
https://reviewboard.asterisk.org/r/3266
https://reviewboard.asterisk.org/r/3265
https://reviewboard.asterisk.org/r/3234
https://reviewboard.asterisk.org/r/3178
ASTERISK-23114 #close
Reported by: mjordan
media_formats_translation_core.diff uploaded by kharwell (License 6464)
rb3506.diff uploaded by mjordan (License 6283)
media_format_app_file.diff uploaded by kharwell (License 6464)
misc-2.diff uploaded by file (License 5000)
chan_mild-3.diff uploaded by file (License 5000)
chan_obscure.diff uploaded by file (License 5000)
jingle.diff uploaded by file (License 5000)
funcs.diff uploaded by file (License 5000)
formats.diff uploaded by file (License 5000)
core.diff uploaded by file (License 5000)
bridges.diff uploaded by file (License 5000)
mf-codecs-2.diff uploaded by file (License 5000)
mf-app_fax.diff uploaded by file (License 5000)
mf-apps-3.diff uploaded by file (License 5000)
media-formats-3.diff uploaded by file (License 5000)
ASTERISK-23715
rb3713.patch uploaded by coreyfarrell (License 5909)
rb3689.patch uploaded by mjordan (License 6283)
ASTERISK-23957
rb3722.patch uploaded by mjordan (License 6283)
mf-attributes-3.diff uploaded by file (License 5000)
ASTERISK-23958
Tested by: jrose
rb3822.patch uploaded by coreyfarrell (License 5909)
rb3800.patch uploaded by jrose (License 6182)
chan_sip.diff uploaded by mjordan (License 6283)
rb3747.patch uploaded by jrose (License 6182)
ASTERISK-23959 #close
Tested by: sgriepentrog, mjordan, coreyfarrell
sip_cleanup.diff uploaded by opticron (License 6273)
chan_sip_caps.diff uploaded by mjordan (License 6283)
rb3751.patch uploaded by coreyfarrell (License 5909)
chan_sip-3.diff uploaded by file (License 5000)
ASTERISK-23960 #close
Tested by: opticron
direct_media.diff uploaded by opticron (License 6273)
pjsip-direct-media.diff uploaded by file (License 5000)
format_cap_remove.diff uploaded by opticron (License 6273)
media_format_fixes.diff uploaded by opticron (License 6273)
chan_pjsip-2.diff uploaded by file (License 5000)
ASTERISK-23966 #close
Tested by: rmudgett
rb3803.patch uploaded by rmudgetti (License 5621)
chan_dahdi.diff uploaded by file (License 5000)
ASTERISK-24064 #close
Tested by: coreyfarrell, mjordan, opticron, file, rmudgett, sgriepentrog, jrose
rb3814.patch uploaded by rmudgett (License 5621)
moh_cleanup.diff uploaded by opticron (License 6273)
bridge_leak.diff uploaded by opticron (License 6273)
translate.diff uploaded by file (License 5000)
rb3795.patch uploaded by rmudgett (License 5621)
tls_fix.diff uploaded by mjordan (License 6283)
fax-mf-fix-2.diff uploaded by file (License 5000)
rtp_transfer_stuff uploaded by mjordan (License 6283)
rb3787.patch uploaded by rmudgett (License 5621)
media-formats-explicit-translate-format-3.diff uploaded by file (License 5000)
format_cache_case_fix.diff uploaded by opticron (License 6273)
rb3774.patch uploaded by rmudgett (License 5621)
rb3775.patch uploaded by rmudgett (License 5621)
rtp_engine_fix.diff uploaded by opticron (License 6273)
rtp_crash_fix.diff uploaded by opticron (License 6273)
rb3753.patch uploaded by mjordan (License 6283)
rb3750.patch uploaded by mjordan (License 6283)
rb3748.patch uploaded by rmudgett (License 5621)
media_format_fixes.diff uploaded by opticron (License 6273)
rb3740.patch uploaded by mjordan (License 6283)
rb3739.patch uploaded by mjordan (License 6283)
rb3734.patch uploaded by mjordan (License 6283)
rb3689.patch uploaded by mjordan (License 6283)
rb3674.patch uploaded by coreyfarrell (License 5909)
rb3671.patch uploaded by coreyfarrell (License 5909)
rb3667.patch uploaded by coreyfarrell (License 5909)
rb3665.patch uploaded by mjordan (License 6283)
rb3625.patch uploaded by coreyfarrell (License 5909)
rb3602.patch uploaded by coreyfarrell (License 5909)
format_compatibility-2.diff uploaded by file (License 5000)
core.diff uploaded by file (License 5000)
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@419044 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2014-07-20 22:06:33 +00:00
# include "asterisk/codec.h"
# include "asterisk/format_cache.h"
2015-01-29 14:38:23 +00:00
# include "asterisk/media_cache.h"
2016-07-23 13:51:48 +00:00
# include "asterisk/astdb.h"
2016-09-13 09:08:34 +00:00
# include "asterisk/options.h"
2005-06-06 03:04:58 +00:00
2006-08-21 02:11:39 +00:00
# include "../defaults.h"
2004-04-28 13:53:01 +00:00
2012-07-11 02:06:05 +00:00
/*** DOCUMENTATION
2013-05-24 20:44:07 +00:00
< managerEvent language = " en_US " name = " FullyBooted " >
< managerEventInstance class = " EVENT_FLAG_SYSTEM " >
< synopsis > Raised when all Asterisk initialization procedures have finished . < / synopsis >
< syntax >
< parameter name = " Status " >
< para > Informational message < / para >
< / parameter >
2016-05-25 13:45:08 +00:00
< parameter name = " Uptime " >
< para > Seconds since start < / para >
< / parameter >
< parameter name = " LastReload " >
< para > Seconds since last reload < / para >
< / parameter >
2013-05-24 20:44:07 +00:00
< / syntax >
< / managerEventInstance >
< / managerEvent >
< managerEvent language = " en_US " name = " Shutdown " >
< managerEventInstance class = " EVENT_FLAG_SYSTEM " >
< synopsis > Raised when Asterisk is shutdown or restarted . < / synopsis >
< syntax >
< parameter name = " Shutdown " >
< para > Whether the shutdown is proceeding cleanly ( all channels
were hungup successfully ) or uncleanly ( channels will be
terminated ) < / para >
< enumlist >
< enum name = " Uncleanly " / >
< enum name = " Cleanly " / >
< / enumlist >
< / parameter >
< parameter name = " Restart " >
< para > Whether or not a restart will occur . < / para >
< enumlist >
< enum name = " True " / >
< enum name = " False " / >
< / enumlist >
< / parameter >
< / syntax >
< / managerEventInstance >
< / managerEvent >
2012-07-11 02:06:05 +00:00
* * */
2004-12-14 23:36:30 +00:00
# ifndef AF_LOCAL
# define AF_LOCAL AF_UNIX
# define PF_LOCAL PF_UNIX
# endif
2001-05-09 03:11:22 +00:00
# define AST_MAX_CONNECTS 128
# define NUM_MSGS 64
2018-07-20 21:21:51 +00:00
/*! Displayed copyright tag */
# define COPYRIGHT_TAG "Copyright (C) 1999 - 2018, Digium, Inc. and others."
2005-11-14 19:00:38 +00:00
/*! \brief Welcome message when starting a CLI interface */
2005-12-23 03:04:38 +00:00
# define WELCOME_MESSAGE \
2018-07-20 21:21:51 +00:00
ast_verbose ( " Asterisk %s, " COPYRIGHT_TAG " \n " \
2007-02-13 06:02:57 +00:00
" Created by Mark Spencer <markster@digium.com> \n " \
" Asterisk comes with ABSOLUTELY NO WARRANTY; type 'core show warranty' for details. \n " \
" This is free software, with components licensed under the GNU General Public \n " \
" License version 2 and other licenses; you are welcome to redistribute it under \n " \
" certain conditions. Type 'core show license' for details. \n " \
2008-02-12 15:39:44 +00:00
" ========================================================================= \n " , ast_get_version ( ) ) \
2004-06-25 21:14:03 +00:00
2005-10-24 20:12:06 +00:00
static int ast_socket = - 1 ; /*!< UNIX Socket for allowing remote control */
2017-06-19 00:24:04 +00:00
static int ast_socket_is_sd = 0 ; /*!< Is socket activation responsible for ast_socket? */
2005-10-24 20:12:06 +00:00
static int ast_consock = - 1 ; /*!< UNIX Socket for controlling another asterisk */
2006-05-08 12:32:44 +00:00
pid_t ast_mainpid ;
2001-05-09 03:11:22 +00:00
struct console {
2005-10-24 20:12:06 +00:00
int fd ; /*!< File descriptor */
int p [ 2 ] ; /*!< Pipe */
pthread_t t ; /*!< Thread of handler */
2006-05-26 19:48:17 +00:00
int mute ; /*!< Is the console muted for logs */
2008-12-01 18:52:14 +00:00
int uid ; /*!< Remote user ID. */
int gid ; /*!< Remote group ID. */
2008-05-29 21:30:37 +00:00
int levels [ NUMLOGLEVELS ] ; /*!< Which log levels are enabled for the console */
2014-01-14 18:14:02 +00:00
/*! Verbosity level of this console. */
int option_verbose ;
2001-05-09 03:11:22 +00:00
} ;
2006-01-24 20:27:09 +00:00
struct ast_atexit {
2003-08-07 03:48:00 +00:00
void ( * func ) ( void ) ;
Avoid unnecessary cleanups during immediate shutdown
This patch addresses issues during immediate shutdowns, where modules
are not unloaded, but Asterisk atexit handlers are run.
In the typical case, this usually isn't a big deal. But the
introduction of the Stasis message bus makes it much more likely for
asynchronous activity to be happening off in some thread during
shutdown.
During an immediate shutdown, Asterisk skips unloading modules. But
while it is processing the atexit handlers, there is a window of time
where some of the core message types have been cleaned up, but the
message bus is still running. Specifically, it's still running
module subscriptions that might be using the core message types. If a
message is received by that subscription in that window, it will
attempt to use a message type that has been cleaned up.
To solve this problem, this patch introduces ast_register_cleanup().
This function operates identically to ast_register_atexit(), except
that cleanup calls are not invoked on an immediate shutdown. All of
the core message type and topic cleanup was moved from atexit handlers
to cleanup handlers.
This ensures that core type and topic cleanup only happens if the
modules that used them are first unloaded.
This patch also changes the ast_assert() when accessing a cleaned up
or uninitialized message type to an error log message. Message type
functions are actually NULL safe across the board, so the assert was a
bit heavy handed. Especially for anyone with DO_CRASH enabled.
Review: https://reviewboard.asterisk.org/r/2562/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@390122 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2013-05-30 17:05:53 +00:00
int is_cleanup ;
2012-12-03 23:00:08 +00:00
AST_LIST_ENTRY ( ast_atexit ) list ;
2006-01-24 20:27:09 +00:00
} ;
2005-10-24 20:12:06 +00:00
2012-12-03 23:00:08 +00:00
static AST_LIST_HEAD_STATIC ( atexits , ast_atexit ) ;
2003-08-07 03:48:00 +00:00
2007-07-18 19:47:20 +00:00
struct timeval ast_startuptime ;
struct timeval ast_lastreloadtime ;
2003-05-02 15:37:34 +00:00
2006-12-27 22:14:33 +00:00
static History * el_hist ;
static EditLine * el ;
2003-02-06 06:15:25 +00:00
static char * remotehostname ;
2001-05-09 03:11:22 +00:00
struct console consoles [ AST_MAX_CONNECTS ] ;
2015-11-25 19:29:55 +00:00
static int ast_el_add_history ( const char * ) ;
static int ast_el_read_history ( const char * ) ;
static int ast_el_write_history ( const char * ) ;
static void ast_el_read_default_histfile ( void ) ;
static void ast_el_write_default_histfile ( void ) ;
static void asterisk_daemon ( int isroot , const char * runuser , const char * rungroup ) ;
2003-02-06 06:15:25 +00:00
2004-02-23 03:43:21 +00:00
static char * _argv [ 256 ] ;
2015-02-11 17:39:13 +00:00
2012-01-15 20:16:08 +00:00
typedef enum {
2015-02-11 17:39:13 +00:00
/*! Normal operation */
NOT_SHUTTING_DOWN ,
/*! Committed to shutting down. Final phase */
SHUTTING_DOWN_FINAL ,
/*! Committed to shutting down. Initial phase */
SHUTTING_DOWN ,
/*!
* Valid values for quit_handler ( ) niceness below .
* These shutdown / restart levels can be cancelled .
*
* Remote console exit right now
*/
2012-01-15 20:16:08 +00:00
SHUTDOWN_FAST ,
2015-02-11 17:39:13 +00:00
/*! core stop/restart now */
2012-01-15 20:16:08 +00:00
SHUTDOWN_NORMAL ,
2015-02-11 17:39:13 +00:00
/*! core stop/restart gracefully */
2012-01-15 20:16:08 +00:00
SHUTDOWN_NICE ,
2015-02-11 17:39:13 +00:00
/*! core stop/restart when convenient */
2012-01-15 20:16:08 +00:00
SHUTDOWN_REALLY_NICE
} shutdown_nice_t ;
2015-02-11 17:39:13 +00:00
2012-01-15 20:16:08 +00:00
static shutdown_nice_t shuttingdown = NOT_SHUTTING_DOWN ;
2015-02-11 17:39:13 +00:00
/*! Prevent new channel allocation for shutdown. */
static int shutdown_pending ;
2006-12-27 22:14:33 +00:00
static int restartnow ;
2004-03-15 07:51:22 +00:00
static pthread_t consolethread = AST_PTHREADT_NULL ;
2010-10-08 03:00:40 +00:00
static pthread_t mon_sig_flags ;
2007-12-18 23:06:05 +00:00
static int canary_pid = 0 ;
static char canary_filename [ 128 ] ;
2012-11-18 20:27:45 +00:00
static int multi_thread_safe ;
2004-02-23 03:43:21 +00:00
2006-01-10 00:55:45 +00:00
static char randompool [ 256 ] ;
2007-02-23 23:25:22 +00:00
static int sig_alert_pipe [ 2 ] = { - 1 , - 1 } ;
static struct {
unsigned int need_reload : 1 ;
unsigned int need_quit : 1 ;
2011-07-18 12:54:29 +00:00
unsigned int need_quit_handler : 1 ;
2018-11-11 13:34:53 +00:00
unsigned int need_el_end : 1 ;
2007-02-23 23:25:22 +00:00
} sig_flags ;
2007-01-30 17:23:56 +00:00
2016-09-19 09:46:27 +00:00
# if !defined(LOW_MEMORY)
2006-04-12 20:40:46 +00:00
struct thread_list_t {
2007-06-18 16:37:14 +00:00
AST_RWLIST_ENTRY ( thread_list_t ) list ;
2006-04-12 20:40:46 +00:00
char * name ;
pthread_t id ;
2010-12-12 03:58:33 +00:00
int lwp ;
2006-04-12 20:40:46 +00:00
} ;
2007-06-18 16:37:14 +00:00
static AST_RWLIST_HEAD_STATIC ( thread_list , thread_list_t ) ;
2006-04-12 20:40:46 +00:00
void ast_register_thread ( char * name )
2012-03-22 19:51:16 +00:00
{
2006-04-12 20:40:46 +00:00
struct thread_list_t * new = ast_calloc ( 1 , sizeof ( * new ) ) ;
if ( ! new )
return ;
2012-11-18 20:27:45 +00:00
ast_assert ( multi_thread_safe ) ;
2006-04-12 20:40:46 +00:00
new - > id = pthread_self ( ) ;
2010-12-12 03:58:33 +00:00
new - > lwp = ast_get_tid ( ) ;
2006-10-04 19:51:38 +00:00
new - > name = name ; /* steal the allocated memory for the thread name */
2007-06-18 16:37:14 +00:00
AST_RWLIST_WRLOCK ( & thread_list ) ;
AST_RWLIST_INSERT_HEAD ( & thread_list , new , list ) ;
AST_RWLIST_UNLOCK ( & thread_list ) ;
2006-04-12 20:40:46 +00:00
}
void ast_unregister_thread ( void * id )
{
struct thread_list_t * x ;
2007-06-18 16:37:14 +00:00
AST_RWLIST_WRLOCK ( & thread_list ) ;
AST_RWLIST_TRAVERSE_SAFE_BEGIN ( & thread_list , x , list ) {
2006-10-04 19:51:38 +00:00
if ( ( void * ) x - > id = = id ) {
2007-11-08 05:28:47 +00:00
AST_RWLIST_REMOVE_CURRENT ( list ) ;
2006-04-12 20:40:46 +00:00
break ;
}
}
2007-06-18 16:37:14 +00:00
AST_RWLIST_TRAVERSE_SAFE_END ;
AST_RWLIST_UNLOCK ( & thread_list ) ;
2006-04-12 20:40:46 +00:00
if ( x ) {
2007-06-06 21:20:11 +00:00
ast_free ( x - > name ) ;
ast_free ( x ) ;
2006-04-12 20:40:46 +00:00
}
}
2007-02-14 20:22:20 +00:00
/*! \brief Give an overview of core settings */
2007-10-11 19:03:06 +00:00
static char * handle_show_settings ( struct ast_cli_entry * e , int cmd , struct ast_cli_args * a )
2007-02-14 20:22:20 +00:00
{
char buf [ BUFSIZ ] ;
2007-07-18 19:47:20 +00:00
struct ast_tm tm ;
2008-06-10 12:48:50 +00:00
char eid_str [ 128 ] ;
2016-06-08 11:15:15 +00:00
struct rlimit limits ;
2016-07-23 13:51:48 +00:00
char pbx_uuid [ AST_UUID_STR_LEN ] ;
2007-02-14 20:22:20 +00:00
2007-10-11 19:03:06 +00:00
switch ( cmd ) {
case CLI_INIT :
e - > command = " core show settings " ;
e - > usage = " Usage: core show settings \n "
" Show core misc settings " ;
return NULL ;
case CLI_GENERATE :
return NULL ;
}
2009-03-27 14:00:18 +00:00
ast_eid_to_str ( eid_str , sizeof ( eid_str ) , & ast_eid_default ) ;
2016-07-23 13:51:48 +00:00
ast_pbx_uuid_get ( pbx_uuid , sizeof ( pbx_uuid ) ) ;
2008-06-10 12:48:50 +00:00
2007-10-11 19:03:06 +00:00
ast_cli ( a - > fd , " \n PBX Core settings \n " ) ;
ast_cli ( a - > fd , " ----------------- \n " ) ;
Now that the version.h file was getting properly regenerated every time the svn
revision changed, every module that used the version was getting rebuilt after
every svn update. This severly annoyed me pretty quickly, so I have improved
the situation.
Now, instead of generating version.h, main/version.c is generated. version.c
includes the version information, as well as a couple of API calls for modules
to retrieve the version. So now, only version.c will get rebuilt, and the main
asterisk binary relinked, which is must faster than rebuilding http.c, manager.c,
asterisk.c, relinking the asterisk binary, chan_sip.c, func_version.c, res_agi ...
The only minor change in behavior here is that the version information reported by
chan_sip, for example, is the version of the Asterisk core, and not necessarily the
Asterisk version that the chan_sip module came from.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@96717 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2008-01-05 22:09:06 +00:00
ast_cli ( a - > fd , " Version: %s \n " , ast_get_version ( ) ) ;
2015-10-31 03:57:58 +00:00
ast_cli ( a - > fd , " Build Options: %s \n " , S_OR ( ast_get_build_opts ( ) , " (none) " ) ) ;
2013-08-05 14:35:00 +00:00
if ( ast_option_maxcalls )
ast_cli ( a - > fd , " Maximum calls: %d (Current %d) \n " , ast_option_maxcalls , ast_active_channels ( ) ) ;
2007-02-14 20:22:20 +00:00
else
2008-02-18 19:47:40 +00:00
ast_cli ( a - > fd , " Maximum calls: Not set \n " ) ;
2016-06-08 11:15:15 +00:00
if ( getrlimit ( RLIMIT_NOFILE , & limits ) ) {
ast_cli ( a - > fd , " Maximum open file handles: Error because of %s \n " , strerror ( errno ) ) ;
} else if ( limits . rlim_cur = = RLIM_INFINITY ) {
ast_cli ( a - > fd , " Maximum open file handles: Unlimited \n " ) ;
} else if ( limits . rlim_cur < ast_option_maxfiles ) {
ast_cli ( a - > fd , " Maximum open file handles: %d (is) %d (requested) \n " , ( int ) limits . rlim_cur , ast_option_maxfiles ) ;
} else {
ast_cli ( a - > fd , " Maximum open file handles: %d \n " , ( int ) limits . rlim_cur ) ;
}
2014-01-14 18:14:02 +00:00
ast_cli ( a - > fd , " Root console verbosity: %d \n " , option_verbose ) ;
ast_cli ( a - > fd , " Current console verbosity: %d \n " , ast_verb_console_get ( ) ) ;
2007-10-11 19:03:06 +00:00
ast_cli ( a - > fd , " Debug level: %d \n " , option_debug ) ;
2013-08-05 14:35:00 +00:00
ast_cli ( a - > fd , " Maximum load average: %lf \n " , ast_option_maxload ) ;
2007-08-01 19:37:59 +00:00
# if defined(HAVE_SYSINFO)
2008-02-18 19:47:40 +00:00
ast_cli ( a - > fd , " Minimum free memory: %ld MB \n " , option_minmemfree ) ;
2007-04-11 20:59:08 +00:00
# endif
2007-06-14 22:09:20 +00:00
if ( ast_localtime ( & ast_startuptime , & tm , NULL ) ) {
2007-07-18 19:47:20 +00:00
ast_strftime ( buf , sizeof ( buf ) , " %H:%M:%S " , & tm ) ;
2007-10-11 19:03:06 +00:00
ast_cli ( a - > fd , " Startup time: %s \n " , buf ) ;
2007-02-14 20:22:20 +00:00
}
2007-06-14 22:09:20 +00:00
if ( ast_localtime ( & ast_lastreloadtime , & tm , NULL ) ) {
2007-07-18 19:47:20 +00:00
ast_strftime ( buf , sizeof ( buf ) , " %H:%M:%S " , & tm ) ;
2007-10-11 19:03:06 +00:00
ast_cli ( a - > fd , " Last reload time: %s \n " , buf ) ;
2007-02-14 20:22:20 +00:00
}
2007-10-11 19:03:06 +00:00
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 ) ;
ast_cli ( a - > fd , " System name: %s \n " , ast_config_AST_SYSTEM_NAME ) ;
2008-06-10 12:48:50 +00:00
ast_cli ( a - > fd , " Entity ID: %s \n " , eid_str ) ;
2016-07-23 13:51:48 +00:00
ast_cli ( a - > fd , " PBX UUID: %s \n " , pbx_uuid ) ;
2013-08-05 14:35:00 +00:00
ast_cli ( a - > fd , " Default language: %s \n " , ast_defaultlanguage ) ;
2007-10-11 19:03:06 +00:00
ast_cli ( a - > fd , " Language prefix: %s \n " , ast_language_is_prefix ? " Enabled " : " Disabled " ) ;
ast_cli ( a - > fd , " User name and group: %s/%s \n " , ast_config_AST_RUN_USER , ast_config_AST_RUN_GROUP ) ;
ast_cli ( a - > fd , " Executable includes: %s \n " , ast_test_flag ( & ast_options , AST_OPT_FLAG_EXEC_INCLUDES ) ? " Enabled " : " Disabled " ) ;
ast_cli ( a - > fd , " Transcode via SLIN: %s \n " , ast_test_flag ( & ast_options , AST_OPT_FLAG_TRANSCODE_VIA_SLIN ) ? " Enabled " : " Disabled " ) ;
2009-04-17 19:36:38 +00:00
ast_cli ( a - > fd , " Transmit silence during rec: %s \n " , ast_test_flag ( & ast_options , AST_OPT_FLAG_TRANSMIT_SILENCE ) ? " Enabled " : " Disabled " ) ;
Fix transcode_via_sln option with SIP calls and improve PLC usage.
From reviewboard:
The problem here is a bit complex, so try to bear with me...
It was noticed by a Digium customer that generic PLC (as configured in
codecs.conf) did not appear to actually be having any sort of benefit when
packet loss was introduced on an RTP stream. I reproduced this issue myself
by streaming a file across an RTP stream and dropping approx. 5% of the
RTP packets. I saw no real difference between when PLC was enabled or disabled
when using wireshark to analyze the RTP streams.
After analyzing what was going on, it became clear that one of the problems
faced was that when running my tests, the translation paths were being set
up in such a way that PLC could not possibly work as expected. To illustrate,
if packets are lost on channel A's read stream, then we expect that PLC will
be applied to channel B's write stream. The problem is that generic PLC can
only be done when there is a translation path that moves from some codec to
SLINEAR. When I would run my tests, I found that every single time, read
and write translation paths would be set up on channel A instead of channel
B. There appeared to be no real way to predict which channel the translation
paths would be set up on.
This is where Kevin swooped in to let me know about the transcode_via_sln
option in asterisk.conf. It is supposed to work by placing a read translation
path on both channels from the channel's rawreadformat to SLINEAR. It also
will place a write translation path on both channels from SLINEAR to the
channel's rawwriteformat. Using this option allows one to predictably set up
translation paths on all channels. There are two problems with this, though.
First and foremost, the transcode_via_sln option did not appear to be working
properly when I was placing a SIP call between two endpoints which did not
share any common formats. Second, even if this option were to work, for PLC
to be applied, there had to be a write translation path that would go from
some format to SLINEAR. It would not work properly if the starting format
of translation was SLINEAR.
The one-line change presented in this review request in chan_sip.c fixed the
first issue for me. The problem was that in sip_request_call, the
jointcapability of the outbound channel was being set to the format passed to
sip_request_call. This is nativeformats of the inbound channel. Because of this,
when ast_channel_make_compatible was called by app_dial, both channels already
had compatibly read and write formats. Thus, no translation path was set up at
the time. My change is to set the jointcapability of the sip_pvt created during
sip_request_call to the intersection of the inbound channel's nativeformats and
the configured peer capability that we determined during the earlier call to
create_addr. Doing this got the translation paths set up as expected when using
transcode_via_sln.
The changes presented in channel.c fixed the second issue for me. First and
foremost, when Asterisk is started, we'll read codecs.conf to see the value of
the genericplc option. If this option is set, and ast_write is called for a
frame with no data, then we will attempt to fill in the missing samples for
the frame. The implementation uses a channel datastore for maintaining the
PLC state and for creating a buffer to store PLC samples in. Even when we
receive a frame with data, we'll call plc_rx so that the PLC state will have
knowledge of the previous voice frame, which it can use as a basis for when
it comes time to actually do a PLC fill-in.
So, reviewers, now I ask for your help. First off, there's the one line change
in chan_sip that I have put in. Is it right? By my logic it seems correct, but
I'm sure someone can tell me why it is not going to work. This is probably the
change I'm least concerned about, though. What concerns me much more is the
set of changes in channel.c. First off, am I even doing it right? When I run
tests, I can clearly see that when PLC is activated, I see a significant increase
in RTP traffic where I would expect it to be. However, in my humble opinion, the
audio sounds kind of crappy whenever the PLC fill-in is done. It sounds worse to
me than when no PLC is used at all. I need someone to review the logic I have used
to be sure that I'm not misusing anything. As far as I can see my pointer arithmetic
is correct, and my use of AST_FRIENDLY_OFFSET should be correct as well, but I'm
sure someone can point out somewhere where I've done something incorrectly.
As I was writing this review request up, I decided to give the code a test run under
valgrind, and I find that for some reason, calls to plc_rx are causing some invalid
reads. Apparently I'm reading past the end of a buffer somehow. I'll have to dig around
a bit to see why that is the case. If it's obvious to someone reviewing, speak up!
Finally, I have one other proposal that is not reflected in my code review. Since
without transcode_via_sln set, one cannot predict or control where a translation
path will be up, it seems to me that the current practice of using PLC only when
transcoding to SLINEAR is not useful. I recommend that once it has been determined
that the method used in this code review is correct and works as expected, then
the code in translate.c that invokes PLC should be removed.
Review: https://reviewboard.asterisk.org/r/622/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@264452 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2010-05-19 21:29:08 +00:00
ast_cli ( a - > fd , " Generic PLC: %s \n " , ast_test_flag ( & ast_options , AST_OPT_FLAG_GENERIC_PLC ) ? " Enabled " : " Disabled " ) ;
2018-03-16 15:19:11 +00:00
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 " ) ;
2012-04-25 09:32:21 +00:00
ast_cli ( a - > fd , " Min DTMF duration:: %u \n " , option_dtmfminduration ) ;
2017-11-11 19:01:47 +00:00
# if !defined(LOW_MEMORY)
ast_cli ( a - > fd , " Cache media frames: %s \n " , ast_opt_cache_media_frames ? " Enabled " : " Disabled " ) ;
# endif
2017-03-20 18:27:31 +00:00
ast_cli ( a - > fd , " RTP use dynamic payloads: %u \n " , ast_option_rtpusedynamic ) ;
2007-10-11 19:03:06 +00:00
2016-09-13 09:08:34 +00:00
if ( ast_option_rtpptdynamic = = AST_RTP_PT_LAST_REASSIGN ) {
ast_cli ( a - > fd , " RTP dynamic payload types: %u,%u-%u \n " ,
ast_option_rtpptdynamic ,
AST_RTP_PT_FIRST_DYNAMIC , AST_RTP_MAX_PT - 1 ) ;
} else if ( ast_option_rtpptdynamic < AST_RTP_PT_LAST_REASSIGN ) {
ast_cli ( a - > fd , " RTP dynamic payload types: %u-%u,%u-%u \n " ,
ast_option_rtpptdynamic , AST_RTP_PT_LAST_REASSIGN ,
AST_RTP_PT_FIRST_DYNAMIC , AST_RTP_MAX_PT - 1 ) ;
} else {
ast_cli ( a - > fd , " RTP dynamic payload types: %u-%u \n " ,
AST_RTP_PT_FIRST_DYNAMIC , AST_RTP_MAX_PT - 1 ) ;
}
2007-10-11 19:03:06 +00:00
ast_cli ( a - > fd , " \n * Subsystems \n " ) ;
ast_cli ( a - > fd , " ------------- \n " ) ;
ast_cli ( a - > fd , " Manager (AMI): %s \n " , check_manager_enabled ( ) ? " Enabled " : " Disabled " ) ;
ast_cli ( a - > fd , " Web Manager (AMI/HTTP): %s \n " , check_webmanager_enabled ( ) ? " Enabled " : " Disabled " ) ;
2013-06-17 03:00:38 +00:00
ast_cli ( a - > fd , " Call data records: %s \n " , ast_cdr_is_enabled ( ) ? " Enabled " : " Disabled " ) ;
2007-10-11 19:03:06 +00:00
ast_cli ( a - > fd , " Realtime Architecture (ARA): %s \n " , ast_realtime_enabled ( ) ? " Enabled " : " Disabled " ) ;
2007-02-14 20:22:20 +00:00
/*! \todo we could check musiconhold, voicemail, smdi, adsi, queues */
2007-10-11 19:03:06 +00:00
ast_cli ( a - > fd , " \n * Directories \n " ) ;
ast_cli ( a - > fd , " ------------- \n " ) ;
ast_cli ( a - > fd , " Configuration file: %s \n " , ast_config_AST_CONFIG_FILE ) ;
ast_cli ( a - > fd , " Configuration directory: %s \n " , ast_config_AST_CONFIG_DIR ) ;
ast_cli ( a - > fd , " Module directory: %s \n " , ast_config_AST_MODULE_DIR ) ;
ast_cli ( a - > fd , " Spool directory: %s \n " , ast_config_AST_SPOOL_DIR ) ;
ast_cli ( a - > fd , " Log directory: %s \n " , ast_config_AST_LOG_DIR ) ;
2010-03-23 22:48:03 +00:00
ast_cli ( a - > fd , " Run/Sockets directory: %s \n " , ast_config_AST_RUN_DIR ) ;
ast_cli ( a - > fd , " PID file: %s \n " , ast_config_AST_PID ) ;
ast_cli ( a - > fd , " VarLib directory: %s \n " , ast_config_AST_VAR_DIR ) ;
ast_cli ( a - > fd , " Data directory: %s \n " , ast_config_AST_DATA_DIR ) ;
ast_cli ( a - > fd , " ASTDB: %s \n " , ast_config_AST_DB ) ;
ast_cli ( a - > fd , " IAX2 Keys directory: %s \n " , ast_config_AST_KEY_DIR ) ;
ast_cli ( a - > fd , " AGI Scripts directory: %s \n " , ast_config_AST_AGI_DIR ) ;
2007-10-11 19:03:06 +00:00
ast_cli ( a - > fd , " \n \n " ) ;
return CLI_SUCCESS ;
2007-02-14 20:22:20 +00:00
}
2007-10-11 19:03:06 +00:00
static char * handle_show_threads ( struct ast_cli_entry * e , int cmd , struct ast_cli_args * a )
2006-04-12 20:40:46 +00:00
{
int count = 0 ;
struct thread_list_t * cur ;
2007-10-11 19:03:06 +00:00
switch ( cmd ) {
case CLI_INIT :
e - > command = " core show threads " ;
2012-03-22 19:51:16 +00:00
e - > usage =
2007-10-11 19:03:06 +00:00
" Usage: core show threads \n "
" List threads currently active in the system. \n " ;
return NULL ;
case CLI_GENERATE :
return NULL ;
}
2006-04-12 20:40:46 +00:00
2007-06-18 16:37:14 +00:00
AST_RWLIST_RDLOCK ( & thread_list ) ;
AST_RWLIST_TRAVERSE ( & thread_list , cur , list ) {
2010-12-12 03:58:33 +00:00
ast_cli ( a - > fd , " %p %d %s \n " , ( void * ) cur - > id , cur - > lwp , cur - > name ) ;
2006-04-12 20:40:46 +00:00
count + + ;
}
2012-03-22 19:51:16 +00:00
AST_RWLIST_UNLOCK ( & thread_list ) ;
2007-10-11 19:03:06 +00:00
ast_cli ( a - > fd , " %d threads listed. \n " , count ) ;
return CLI_SUCCESS ;
2006-04-12 20:40:46 +00:00
}
2008-12-16 20:08:34 +00:00
# if defined (HAVE_SYSCTL) && defined(HAVE_SWAPCTL)
/*
* swapmode is rewritten by Tobias Weingartner < weingart @ openbsd . org >
* to be based on the new swapctl ( 2 ) system call .
*/
static int swapmode ( int * used , int * total )
{
struct swapent * swdev ;
int nswap , rnswap , i ;
nswap = swapctl ( SWAP_NSWAP , 0 , 0 ) ;
if ( nswap = = 0 )
return 0 ;
swdev = ast_calloc ( nswap , sizeof ( * swdev ) ) ;
if ( swdev = = NULL )
return 0 ;
rnswap = swapctl ( SWAP_STATS , swdev , nswap ) ;
if ( rnswap = = - 1 ) {
ast_free ( swdev ) ;
return 0 ;
}
/* if rnswap != nswap, then what? */
/* Total things up */
* total = * used = 0 ;
for ( i = 0 ; i < nswap ; i + + ) {
if ( swdev [ i ] . se_flags & SWF_ENABLE ) {
* used + = ( swdev [ i ] . se_inuse / ( 1024 / DEV_BSIZE ) ) ;
* total + = ( swdev [ i ] . se_nblks / ( 1024 / DEV_BSIZE ) ) ;
}
}
ast_free ( swdev ) ;
return 1 ;
}
# endif
2009-02-21 14:37:04 +00:00
# if defined(HAVE_SYSINFO) || defined(HAVE_SYSCTL)
2007-04-11 19:11:32 +00:00
/*! \brief Give an overview of system statistics */
2007-10-11 19:03:06 +00:00
static char * handle_show_sysinfo ( struct ast_cli_entry * e , int cmd , struct ast_cli_args * a )
2007-04-11 19:11:32 +00:00
{
2010-05-24 18:19:08 +00:00
uint64_t physmem , freeram ;
2017-12-20 16:13:13 +00:00
# if defined(HAVE_SYSINFO) || defined(HAVE_SWAPCTL)
2018-01-27 15:44:21 +00:00
int totalswap = 0 ;
2010-05-28 20:53:04 +00:00
uint64_t freeswap = 0 ;
2017-12-20 16:13:13 +00:00
# endif
2010-05-24 18:19:08 +00:00
int nprocs = 0 ;
2008-12-16 20:08:34 +00:00
long uptime = 0 ;
# if defined(HAVE_SYSINFO)
2007-04-11 19:11:32 +00:00
struct sysinfo sys_info ;
2017-12-09 06:35:12 +00:00
# elif defined(HAVE_SYSCTL)
static int pageshift ;
struct vmtotal vmtotal ;
struct timeval boottime ;
time_t now ;
2018-01-27 15:44:21 +00:00
int mib [ 2 ] , pagesize ;
# if defined(HAVE_SWAPCTL)
int usedswap = 0 ;
# endif
2017-12-09 06:35:12 +00:00
size_t len ;
# endif
switch ( cmd ) {
case CLI_INIT :
e - > command = " core show sysinfo " ;
e - > usage =
" Usage: core show sysinfo \n "
" List current system information. \n " ;
return NULL ;
case CLI_GENERATE :
return NULL ;
}
# if defined(HAVE_SYSINFO)
2008-12-16 20:49:25 +00:00
sysinfo ( & sys_info ) ;
2010-05-24 18:19:08 +00:00
uptime = sys_info . uptime / 3600 ;
2008-12-16 20:08:34 +00:00
physmem = sys_info . totalram * sys_info . mem_unit ;
freeram = ( sys_info . freeram * sys_info . mem_unit ) / 1024 ;
totalswap = ( sys_info . totalswap * sys_info . mem_unit ) / 1024 ;
freeswap = ( sys_info . freeswap * sys_info . mem_unit ) / 1024 ;
2008-12-16 20:49:25 +00:00
nprocs = sys_info . procs ;
2008-12-16 20:08:34 +00:00
# elif defined(HAVE_SYSCTL)
/* calculate the uptime by looking at boottime */
time ( & now ) ;
mib [ 0 ] = CTL_KERN ;
mib [ 1 ] = KERN_BOOTTIME ;
len = sizeof ( boottime ) ;
if ( sysctl ( mib , 2 , & boottime , & len , NULL , 0 ) ! = - 1 ) {
uptime = now - boottime . tv_sec ;
}
uptime = uptime / 3600 ;
/* grab total physical memory */
mib [ 0 ] = CTL_HW ;
2009-01-19 18:36:24 +00:00
# if defined(HW_PHYSMEM64)
2008-12-16 20:08:34 +00:00
mib [ 1 ] = HW_PHYSMEM64 ;
2009-01-14 19:36:57 +00:00
# else
mib [ 1 ] = HW_PHYSMEM ;
# endif
2008-12-16 20:08:34 +00:00
len = sizeof ( physmem ) ;
sysctl ( mib , 2 , & physmem , & len , NULL , 0 ) ;
pagesize = getpagesize ( ) ;
pageshift = 0 ;
while ( pagesize > 1 ) {
pageshift + + ;
pagesize > > = 1 ;
}
/* we only need the amount of log(2)1024 for our conversion */
pageshift - = 10 ;
/* grab vm totals */
mib [ 0 ] = CTL_VM ;
mib [ 1 ] = VM_METER ;
len = sizeof ( vmtotal ) ;
sysctl ( mib , 2 , & vmtotal , & len , NULL , 0 ) ;
freeram = ( vmtotal . t_free < < pageshift ) ;
/* generate swap usage and totals */
2018-01-27 15:44:21 +00:00
# if defined(HAVE_SWAPCTL)
2010-05-24 18:19:08 +00:00
swapmode ( & usedswap , & totalswap ) ;
2008-12-16 20:08:34 +00:00
freeswap = ( totalswap - usedswap ) ;
2018-01-27 15:44:21 +00:00
# endif
2008-12-16 20:08:34 +00:00
/* grab number of processes */
2009-01-14 19:36:57 +00:00
# if defined(__OpenBSD__)
2008-12-16 20:08:34 +00:00
mib [ 0 ] = CTL_KERN ;
mib [ 1 ] = KERN_NPROCS ;
len = sizeof ( nprocs ) ;
sysctl ( mib , 2 , & nprocs , & len , NULL , 0 ) ;
2009-01-14 19:36:57 +00:00
# endif
2008-12-16 20:08:34 +00:00
# endif
2007-10-11 19:03:06 +00:00
ast_cli ( a - > fd , " \n System Statistics \n " ) ;
ast_cli ( a - > fd , " ----------------- \n " ) ;
2014-05-09 22:49:26 +00:00
ast_cli ( a - > fd , " System Uptime: %ld hours \n " , uptime ) ;
2010-05-24 18:19:08 +00:00
ast_cli ( a - > fd , " Total RAM: % " PRIu64 " KiB \n " , physmem / 1024 ) ;
ast_cli ( a - > fd , " Free RAM: % " PRIu64 " KiB \n " , freeram ) ;
2008-12-16 20:08:34 +00:00
# if defined(HAVE_SYSINFO)
2010-05-24 18:19:08 +00:00
ast_cli ( a - > fd , " Buffer RAM: % " PRIu64 " KiB \n " , ( ( uint64_t ) sys_info . bufferram * sys_info . mem_unit ) / 1024 ) ;
2008-12-16 20:08:34 +00:00
# endif
2017-12-20 16:13:13 +00:00
# if defined(HAVE_SYSINFO) || defined(HAVE_SWAPCTL)
2014-05-09 22:49:26 +00:00
ast_cli ( a - > fd , " Total Swap Space: %d KiB \n " , totalswap ) ;
2010-05-24 18:19:08 +00:00
ast_cli ( a - > fd , " Free Swap Space: % " PRIu64 " KiB \n \n " , freeswap ) ;
2010-05-28 20:53:04 +00:00
# endif
2008-12-16 20:08:34 +00:00
ast_cli ( a - > fd , " Number of Processes: %d \n \n " , nprocs ) ;
2007-10-11 19:03:06 +00:00
return CLI_SUCCESS ;
2007-04-11 19:11:32 +00:00
}
2009-02-21 14:37:04 +00:00
# endif
2007-04-11 19:11:32 +00:00
2006-04-12 20:40:46 +00:00
struct profile_entry {
const char * name ;
uint64_t scale ; /* if non-zero, values are scaled by this */
int64_t mark ;
int64_t value ;
int64_t events ;
} ;
struct profile_data {
int entries ;
int max_size ;
struct profile_entry e [ 0 ] ;
} ;
static struct profile_data * prof_data ;
2016-09-19 09:46:27 +00:00
# endif /* ! LOW_MEMORY */
2006-04-12 20:40:46 +00:00
2006-06-08 18:03:08 +00:00
/*! \brief allocates a counter with a given name and scale.
* \ return Returns the identifier of the counter .
2006-04-12 20:40:46 +00:00
*/
int ast_add_profile ( const char * name , uint64_t scale )
{
2016-09-19 09:46:27 +00:00
# if !defined(LOW_MEMORY)
2006-04-12 20:40:46 +00:00
int l = sizeof ( struct profile_data ) ;
int n = 10 ; /* default entries */
if ( prof_data = = NULL ) {
prof_data = ast_calloc ( 1 , l + n * sizeof ( struct profile_entry ) ) ;
if ( prof_data = = NULL )
return - 1 ;
prof_data - > entries = 0 ;
prof_data - > max_size = n ;
}
if ( prof_data - > entries > = prof_data - > max_size ) {
void * p ;
n = prof_data - > max_size + 20 ;
p = ast_realloc ( prof_data , l + n * sizeof ( struct profile_entry ) ) ;
if ( p = = NULL )
return - 1 ;
prof_data = p ;
prof_data - > max_size = n ;
}
n = prof_data - > entries + + ;
prof_data - > e [ n ] . name = ast_strdup ( name ) ;
prof_data - > e [ n ] . value = 0 ;
prof_data - > e [ n ] . events = 0 ;
prof_data - > e [ n ] . mark = 0 ;
prof_data - > e [ n ] . scale = scale ;
return n ;
2016-09-19 09:46:27 +00:00
# else /* if defined(LOW_MEMORY) */
return 0 ;
# endif
2006-04-12 20:40:46 +00:00
}
int64_t ast_profile ( int i , int64_t delta )
{
2016-09-19 09:46:27 +00:00
# if !defined(LOW_MEMORY)
2006-04-12 20:40:46 +00:00
if ( ! prof_data | | i < 0 | | i > prof_data - > entries ) /* invalid index */
return 0 ;
if ( prof_data - > e [ i ] . scale > 1 )
delta / = prof_data - > e [ i ] . scale ;
prof_data - > e [ i ] . value + = delta ;
prof_data - > e [ i ] . events + + ;
return prof_data - > e [ i ] . value ;
2016-09-19 09:46:27 +00:00
# else /* if defined(LOW_MEMORY) */
return 0 ;
# endif
2006-04-12 20:40:46 +00:00
}
2016-09-19 09:46:27 +00:00
# if !defined(LOW_MEMORY)
2008-06-19 16:08:29 +00:00
/* The RDTSC instruction was introduced on the Pentium processor and is not
* implemented on certain clones , like the Cyrix 586. Hence , the previous
* expectation of __i386__ was in error . */
# if defined ( __i686__) && (defined(__FreeBSD__) || defined(linux))
2006-04-12 20:40:46 +00:00
# if defined(__FreeBSD__)
# include <machine/cpufunc.h>
# elif defined(linux)
2006-08-22 05:34:44 +00:00
static __inline uint64_t
2006-04-12 20:40:46 +00:00
rdtsc ( void )
2012-03-22 19:51:16 +00:00
{
2006-04-12 20:40:46 +00:00
uint64_t rv ;
__asm __volatile ( " .byte 0x0f, 0x31 " : " =A " ( rv ) ) ;
return ( rv ) ;
}
# endif
# else /* supply a dummy function on other platforms */
2006-08-22 05:34:44 +00:00
static __inline uint64_t
2006-04-12 20:40:46 +00:00
rdtsc ( void )
{
return 0 ;
}
# endif
2016-09-19 09:46:27 +00:00
# endif /* ! LOW_MEMORY */
2006-04-12 20:40:46 +00:00
int64_t ast_mark ( int i , int startstop )
{
2016-09-19 09:46:27 +00:00
# if !defined(LOW_MEMORY)
2006-04-12 20:40:46 +00:00
if ( ! prof_data | | i < 0 | | i > prof_data - > entries ) /* invalid index */
return 0 ;
if ( startstop = = 1 )
prof_data - > e [ i ] . mark = rdtsc ( ) ;
else {
prof_data - > e [ i ] . mark = ( rdtsc ( ) - prof_data - > e [ i ] . mark ) ;
if ( prof_data - > e [ i ] . scale > 1 )
prof_data - > e [ i ] . mark / = prof_data - > e [ i ] . scale ;
prof_data - > e [ i ] . value + = prof_data - > e [ i ] . mark ;
prof_data - > e [ i ] . events + + ;
}
return prof_data - > e [ i ] . mark ;
2016-09-19 09:46:27 +00:00
# else /* if defined(LOW_MEMORY) */
return 0 ;
# endif
2006-04-12 20:40:46 +00:00
}
2016-09-19 09:46:27 +00:00
# if !defined(LOW_MEMORY)
2007-10-11 19:03:06 +00:00
# define DEFINE_PROFILE_MIN_MAX_VALUES min = 0; \
max = prof_data - > entries ; \
if ( a - > argc > 3 ) { /* specific entries */ \
if ( isdigit ( a - > argv [ 3 ] [ 0 ] ) ) { \
min = atoi ( a - > argv [ 3 ] ) ; \
if ( a - > argc = = 5 & & strcmp ( a - > argv [ 4 ] , " - " ) ) \
max = atoi ( a - > argv [ 4 ] ) ; \
} else \
search = a - > argv [ 3 ] ; \
} \
if ( max > prof_data - > entries ) \
max = prof_data - > entries ;
static char * handle_show_profile ( struct ast_cli_entry * e , int cmd , struct ast_cli_args * a )
2006-09-18 19:54:18 +00:00
{
int i , min , max ;
2009-05-21 21:13:09 +00:00
const char * search = NULL ;
2007-10-11 19:03:06 +00:00
switch ( cmd ) {
case CLI_INIT :
e - > command = " core show profile " ;
e - > usage = " Usage: core show profile \n "
" show profile information " ;
return NULL ;
case CLI_GENERATE :
return NULL ;
}
2006-09-18 19:54:18 +00:00
if ( prof_data = = NULL )
return 0 ;
2007-10-11 19:03:06 +00:00
DEFINE_PROFILE_MIN_MAX_VALUES ;
ast_cli ( a - > fd , " profile values (%d, allocated %d) \n ------------------- \n " ,
2006-09-18 19:54:18 +00:00
prof_data - > entries , prof_data - > max_size ) ;
2007-10-11 19:03:06 +00:00
ast_cli ( a - > fd , " %6s %8s %10s %12s %12s %s \n " , " ID " , " Scale " , " Events " ,
2006-09-18 19:54:18 +00:00
" Value " , " Average " , " Name " ) ;
for ( i = min ; i < max ; i + + ) {
2008-08-10 19:35:50 +00:00
struct profile_entry * entry = & prof_data - > e [ i ] ;
2008-08-10 20:23:50 +00:00
if ( ! search | | strstr ( entry - > name , search ) )
2007-10-11 19:03:06 +00:00
ast_cli ( a - > fd , " %6d: [%8ld] %10ld %12lld %12lld %s \n " ,
2006-09-18 19:54:18 +00:00
i ,
2008-08-10 19:35:50 +00:00
( long ) entry - > scale ,
( long ) entry - > events , ( long long ) entry - > value ,
( long long ) ( entry - > events ? entry - > value / entry - > events : entry - > value ) ,
entry - > name ) ;
2006-09-18 19:54:18 +00:00
}
2007-10-11 19:03:06 +00:00
return CLI_SUCCESS ;
2006-09-18 19:54:18 +00:00
}
2007-10-11 19:03:06 +00:00
static char * handle_clear_profile ( struct ast_cli_entry * e , int cmd , struct ast_cli_args * a )
{
int i , min , max ;
2009-05-21 21:13:09 +00:00
const char * search = NULL ;
2007-10-11 19:03:06 +00:00
switch ( cmd ) {
case CLI_INIT :
e - > command = " core clear profile " ;
e - > usage = " Usage: core clear profile \n "
" clear profile information " ;
return NULL ;
case CLI_GENERATE :
return NULL ;
}
if ( prof_data = = NULL )
return 0 ;
DEFINE_PROFILE_MIN_MAX_VALUES ;
for ( i = min ; i < max ; i + + ) {
if ( ! search | | strstr ( prof_data - > e [ i ] . name , search ) ) {
prof_data - > e [ i ] . value = 0 ;
prof_data - > e [ i ] . events = 0 ;
}
}
return CLI_SUCCESS ;
}
# undef DEFINE_PROFILE_MIN_MAX_VALUES
2005-06-06 20:27:51 +00:00
2005-06-07 16:07:06 +00:00
# endif /* ! LOW_MEMORY */
2005-06-06 20:27:51 +00:00
2016-09-20 20:17:42 +00:00
int ast_pbx_uuid_get ( char * pbx_uuid , int length )
{
return ast_db_get ( " pbx " , " UUID " , pbx_uuid , length ) ;
}
2013-05-24 20:44:07 +00:00
static void publish_fully_booted ( void )
{
2018-02-13 04:15:41 +00:00
struct ast_json * json_object ;
2016-05-25 13:45:08 +00:00
int uptime = 0 ;
int lastreloaded = 0 ;
struct timeval tmp ;
struct timeval curtime = ast_tvnow ( ) ;
2013-05-24 20:44:07 +00:00
2016-05-25 13:45:08 +00:00
if ( ast_startuptime . tv_sec ) {
tmp = ast_tvsub ( curtime , ast_startuptime ) ;
uptime = ( int ) tmp . tv_sec ;
}
if ( ast_lastreloadtime . tv_sec ) {
tmp = ast_tvsub ( curtime , ast_lastreloadtime ) ;
lastreloaded = ( int ) tmp . tv_sec ;
}
json_object = ast_json_pack ( " {s: s, s: i, s: i} " ,
" Status " , " Fully Booted " ,
" Uptime " , uptime ,
" LastReload " , lastreloaded ) ;
2013-05-31 14:36:08 +00:00
ast_manager_publish_event ( " FullyBooted " , EVENT_FLAG_SYSTEM , json_object ) ;
2018-02-13 04:15:41 +00:00
ast_json_unref ( json_object ) ;
2013-05-24 20:44:07 +00:00
}
Avoid unnecessary cleanups during immediate shutdown
This patch addresses issues during immediate shutdowns, where modules
are not unloaded, but Asterisk atexit handlers are run.
In the typical case, this usually isn't a big deal. But the
introduction of the Stasis message bus makes it much more likely for
asynchronous activity to be happening off in some thread during
shutdown.
During an immediate shutdown, Asterisk skips unloading modules. But
while it is processing the atexit handlers, there is a window of time
where some of the core message types have been cleaned up, but the
message bus is still running. Specifically, it's still running
module subscriptions that might be using the core message types. If a
message is received by that subscription in that window, it will
attempt to use a message type that has been cleaned up.
To solve this problem, this patch introduces ast_register_cleanup().
This function operates identically to ast_register_atexit(), except
that cleanup calls are not invoked on an immediate shutdown. All of
the core message type and topic cleanup was moved from atexit handlers
to cleanup handlers.
This ensures that core type and topic cleanup only happens if the
modules that used them are first unloaded.
This patch also changes the ast_assert() when accessing a cleaned up
or uninitialized message type to an error log message. Message type
functions are actually NULL safe across the board, so the assert was a
bit heavy handed. Especially for anyone with DO_CRASH enabled.
Review: https://reviewboard.asterisk.org/r/2562/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@390122 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2013-05-30 17:05:53 +00:00
static void ast_run_atexits ( int run_cleanups )
2012-12-03 23:00:08 +00:00
{
struct ast_atexit * ae ;
AST_LIST_LOCK ( & atexits ) ;
while ( ( ae = AST_LIST_REMOVE_HEAD ( & atexits , list ) ) ) {
Avoid unnecessary cleanups during immediate shutdown
This patch addresses issues during immediate shutdowns, where modules
are not unloaded, but Asterisk atexit handlers are run.
In the typical case, this usually isn't a big deal. But the
introduction of the Stasis message bus makes it much more likely for
asynchronous activity to be happening off in some thread during
shutdown.
During an immediate shutdown, Asterisk skips unloading modules. But
while it is processing the atexit handlers, there is a window of time
where some of the core message types have been cleaned up, but the
message bus is still running. Specifically, it's still running
module subscriptions that might be using the core message types. If a
message is received by that subscription in that window, it will
attempt to use a message type that has been cleaned up.
To solve this problem, this patch introduces ast_register_cleanup().
This function operates identically to ast_register_atexit(), except
that cleanup calls are not invoked on an immediate shutdown. All of
the core message type and topic cleanup was moved from atexit handlers
to cleanup handlers.
This ensures that core type and topic cleanup only happens if the
modules that used them are first unloaded.
This patch also changes the ast_assert() when accessing a cleaned up
or uninitialized message type to an error log message. Message type
functions are actually NULL safe across the board, so the assert was a
bit heavy handed. Especially for anyone with DO_CRASH enabled.
Review: https://reviewboard.asterisk.org/r/2562/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@390122 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2013-05-30 17:05:53 +00:00
if ( ae - > func & & ( ! ae - > is_cleanup | | run_cleanups ) ) {
2012-12-03 23:00:08 +00:00
ae - > func ( ) ;
}
ast_free ( ae ) ;
}
AST_LIST_UNLOCK ( & atexits ) ;
}
static void __ast_unregister_atexit ( void ( * func ) ( void ) )
{
struct ast_atexit * ae ;
AST_LIST_TRAVERSE_SAFE_BEGIN ( & atexits , ae , list ) {
if ( ae - > func = = func ) {
AST_LIST_REMOVE_CURRENT ( list ) ;
ast_free ( ae ) ;
break ;
}
}
AST_LIST_TRAVERSE_SAFE_END ;
}
Avoid unnecessary cleanups during immediate shutdown
This patch addresses issues during immediate shutdowns, where modules
are not unloaded, but Asterisk atexit handlers are run.
In the typical case, this usually isn't a big deal. But the
introduction of the Stasis message bus makes it much more likely for
asynchronous activity to be happening off in some thread during
shutdown.
During an immediate shutdown, Asterisk skips unloading modules. But
while it is processing the atexit handlers, there is a window of time
where some of the core message types have been cleaned up, but the
message bus is still running. Specifically, it's still running
module subscriptions that might be using the core message types. If a
message is received by that subscription in that window, it will
attempt to use a message type that has been cleaned up.
To solve this problem, this patch introduces ast_register_cleanup().
This function operates identically to ast_register_atexit(), except
that cleanup calls are not invoked on an immediate shutdown. All of
the core message type and topic cleanup was moved from atexit handlers
to cleanup handlers.
This ensures that core type and topic cleanup only happens if the
modules that used them are first unloaded.
This patch also changes the ast_assert() when accessing a cleaned up
or uninitialized message type to an error log message. Message type
functions are actually NULL safe across the board, so the assert was a
bit heavy handed. Especially for anyone with DO_CRASH enabled.
Review: https://reviewboard.asterisk.org/r/2562/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@390122 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2013-05-30 17:05:53 +00:00
static int register_atexit ( void ( * func ) ( void ) , int is_cleanup )
2003-08-07 03:48:00 +00:00
{
struct ast_atexit * ae ;
2007-09-08 18:45:51 +00:00
2012-12-03 23:00:08 +00:00
ae = ast_calloc ( 1 , sizeof ( * ae ) ) ;
if ( ! ae ) {
2007-09-08 18:45:51 +00:00
return - 1 ;
2012-12-03 23:00:08 +00:00
}
2007-09-08 18:45:51 +00:00
ae - > func = func ;
Avoid unnecessary cleanups during immediate shutdown
This patch addresses issues during immediate shutdowns, where modules
are not unloaded, but Asterisk atexit handlers are run.
In the typical case, this usually isn't a big deal. But the
introduction of the Stasis message bus makes it much more likely for
asynchronous activity to be happening off in some thread during
shutdown.
During an immediate shutdown, Asterisk skips unloading modules. But
while it is processing the atexit handlers, there is a window of time
where some of the core message types have been cleaned up, but the
message bus is still running. Specifically, it's still running
module subscriptions that might be using the core message types. If a
message is received by that subscription in that window, it will
attempt to use a message type that has been cleaned up.
To solve this problem, this patch introduces ast_register_cleanup().
This function operates identically to ast_register_atexit(), except
that cleanup calls are not invoked on an immediate shutdown. All of
the core message type and topic cleanup was moved from atexit handlers
to cleanup handlers.
This ensures that core type and topic cleanup only happens if the
modules that used them are first unloaded.
This patch also changes the ast_assert() when accessing a cleaned up
or uninitialized message type to an error log message. Message type
functions are actually NULL safe across the board, so the assert was a
bit heavy handed. Especially for anyone with DO_CRASH enabled.
Review: https://reviewboard.asterisk.org/r/2562/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@390122 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2013-05-30 17:05:53 +00:00
ae - > is_cleanup = is_cleanup ;
2007-09-08 18:45:51 +00:00
2012-12-03 23:00:08 +00:00
AST_LIST_LOCK ( & atexits ) ;
__ast_unregister_atexit ( func ) ;
AST_LIST_INSERT_HEAD ( & atexits , ae , list ) ;
AST_LIST_UNLOCK ( & atexits ) ;
2007-09-08 18:45:51 +00:00
return 0 ;
2003-08-07 03:48:00 +00:00
}
Avoid unnecessary cleanups during immediate shutdown
This patch addresses issues during immediate shutdowns, where modules
are not unloaded, but Asterisk atexit handlers are run.
In the typical case, this usually isn't a big deal. But the
introduction of the Stasis message bus makes it much more likely for
asynchronous activity to be happening off in some thread during
shutdown.
During an immediate shutdown, Asterisk skips unloading modules. But
while it is processing the atexit handlers, there is a window of time
where some of the core message types have been cleaned up, but the
message bus is still running. Specifically, it's still running
module subscriptions that might be using the core message types. If a
message is received by that subscription in that window, it will
attempt to use a message type that has been cleaned up.
To solve this problem, this patch introduces ast_register_cleanup().
This function operates identically to ast_register_atexit(), except
that cleanup calls are not invoked on an immediate shutdown. All of
the core message type and topic cleanup was moved from atexit handlers
to cleanup handlers.
This ensures that core type and topic cleanup only happens if the
modules that used them are first unloaded.
This patch also changes the ast_assert() when accessing a cleaned up
or uninitialized message type to an error log message. Message type
functions are actually NULL safe across the board, so the assert was a
bit heavy handed. Especially for anyone with DO_CRASH enabled.
Review: https://reviewboard.asterisk.org/r/2562/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@390122 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2013-05-30 17:05:53 +00:00
int ast_register_atexit ( void ( * func ) ( void ) )
{
return register_atexit ( func , 0 ) ;
}
int ast_register_cleanup ( void ( * func ) ( void ) )
{
return register_atexit ( func , 1 ) ;
}
2003-08-07 03:48:00 +00:00
void ast_unregister_atexit ( void ( * func ) ( void ) )
{
2012-12-03 23:00:08 +00:00
AST_LIST_LOCK ( & atexits ) ;
__ast_unregister_atexit ( func ) ;
AST_LIST_UNLOCK ( & atexits ) ;
2003-08-07 03:48:00 +00:00
}
2008-05-27 18:59:06 +00:00
/* Sending commands from consoles back to the daemon requires a terminating NULL */
static int fdsend ( int fd , const char * s )
2001-05-09 03:11:22 +00:00
{
return write ( fd , s , strlen ( s ) + 1 ) ;
}
2008-05-27 18:59:06 +00:00
/* Sending messages from the daemon back to the display requires _excluding_ the terminating NULL */
static int fdprint ( int fd , const char * s )
{
return write ( fd , s , strlen ( s ) ) ;
}
2006-06-08 18:03:08 +00:00
/*! \brief NULL handler so we can collect the child exit status */
2010-05-26 21:17:46 +00:00
static void _null_sig_handler ( int sig )
2004-08-22 18:33:19 +00:00
{
}
2010-05-26 21:17:46 +00:00
static struct sigaction null_sig_handler = {
. sa_handler = _null_sig_handler ,
2010-06-10 08:15:45 +00:00
. sa_flags = SA_RESTART ,
2010-05-26 21:17:46 +00:00
} ;
static struct sigaction ignore_sig_handler = {
. sa_handler = SIG_IGN ,
} ;
2005-09-14 22:40:54 +00:00
AST_MUTEX_DEFINE_STATIC ( safe_system_lock ) ;
2006-06-08 18:03:08 +00:00
/*! \brief Keep track of how many threads are currently trying to wait*() on
2012-09-21 17:14:59 +00:00
* a child process
*/
2005-09-14 22:40:54 +00:00
static unsigned int safe_system_level = 0 ;
2010-05-26 21:17:46 +00:00
static struct sigaction safe_system_prev_handler ;
2005-09-14 22:40:54 +00:00
2006-05-25 18:31:19 +00:00
void ast_replace_sigchld ( void )
2004-03-21 18:15:37 +00:00
{
2005-09-14 22:40:54 +00:00
unsigned int level ;
ast_mutex_lock ( & safe_system_lock ) ;
level = safe_system_level + + ;
/* only replace the handler if it has not already been done */
2010-05-26 21:17:46 +00:00
if ( level = = 0 ) {
sigaction ( SIGCHLD , & null_sig_handler , & safe_system_prev_handler ) ;
}
2005-09-14 22:40:54 +00:00
ast_mutex_unlock ( & safe_system_lock ) ;
2006-05-25 18:31:19 +00:00
}
void ast_unreplace_sigchld ( void )
{
unsigned int level ;
ast_mutex_lock ( & safe_system_lock ) ;
level = - - safe_system_level ;
/* only restore the handler if we are the last one */
2010-05-26 21:17:46 +00:00
if ( level = = 0 ) {
sigaction ( SIGCHLD , & safe_system_prev_handler , NULL ) ;
}
2006-05-25 18:31:19 +00:00
ast_mutex_unlock ( & safe_system_lock ) ;
}
2017-07-02 00:24:27 +00:00
/*! \brief fork and perform other preparations for spawning applications */
static pid_t safe_exec_prep ( int dualfork )
2006-05-25 18:31:19 +00:00
{
pid_t pid ;
2006-09-16 23:53:58 +00:00
# if defined(HAVE_WORKING_FORK) || defined(HAVE_WORKING_VFORK)
ast_replace_sigchld ( ) ;
2005-09-14 22:40:54 +00:00
2006-09-18 19:58:27 +00:00
# ifdef HAVE_WORKING_FORK
2004-03-21 18:15:37 +00:00
pid = fork ( ) ;
2006-09-18 19:58:27 +00:00
# else
pid = vfork ( ) ;
2012-03-22 19:51:16 +00:00
# endif
2005-09-14 22:40:54 +00:00
2004-03-21 18:15:37 +00:00
if ( pid = = 0 ) {
2009-01-29 23:15:40 +00:00
# ifdef HAVE_CAP
cap_t cap = cap_from_text ( " cap_net_admin-eip " ) ;
if ( cap_set_proc ( cap ) ) {
/* Careful with order! Logging cannot happen after we close FDs */
ast_log ( LOG_WARNING , " Unable to remove capabilities. \n " ) ;
}
cap_free ( cap ) ;
# endif
2006-10-18 21:05:52 +00:00
# ifdef HAVE_WORKING_FORK
2017-07-02 00:24:27 +00:00
if ( ast_opt_high_priority ) {
2006-05-01 21:48:30 +00:00
ast_set_priority ( 0 ) ;
2017-07-02 00:24:27 +00:00
}
2004-03-21 18:15:37 +00:00
/* Close file descriptors and launch system command */
2008-04-16 22:57:54 +00:00
ast_close_fds_above_n ( STDERR_FILENO ) ;
2006-10-18 21:05:52 +00:00
# endif
2017-07-02 00:24:27 +00:00
if ( dualfork ) {
# ifdef HAVE_WORKING_FORK
pid = fork ( ) ;
# else
pid = vfork ( ) ;
# endif
if ( pid < 0 ) {
/* Second fork failed. */
/* No logger available. */
_exit ( 1 ) ;
}
if ( pid > 0 ) {
/* This is the first fork, exit so the reaper finishes right away. */
_exit ( 0 ) ;
}
/* This is the second fork. The first fork will exit immediately so
* Asterisk doesn ' t have to wait for completion .
* ast_safe_system ( " cmd & " ) would run in the background , but the ' & '
* cannot be added with ast_safe_execvp , so we have to double fork .
*/
}
}
if ( pid < 0 ) {
ast_log ( LOG_WARNING , " Fork failed: %s \n " , strerror ( errno ) ) ;
}
# else
ast_log ( LOG_WARNING , " Fork failed: %s \n " , strerror ( ENOTSUP ) ) ;
pid = - 1 ;
# endif
return pid ;
}
/*! \brief wait for spawned application to complete and unreplace sigchld */
static int safe_exec_wait ( pid_t pid )
{
int res = - 1 ;
# if defined(HAVE_WORKING_FORK) || defined(HAVE_WORKING_VFORK)
if ( pid > 0 ) {
2007-01-23 00:11:32 +00:00
for ( ; ; ) {
2017-07-02 00:24:27 +00:00
int status ;
2013-11-08 14:58:13 +00:00
res = waitpid ( pid , & status , 0 ) ;
2004-03-21 18:15:37 +00:00
if ( res > - 1 ) {
2005-09-14 22:40:54 +00:00
res = WIFEXITED ( status ) ? WEXITSTATUS ( status ) : - 1 ;
break ;
2017-07-02 00:24:27 +00:00
}
if ( errno ! = EINTR ) {
2004-06-21 19:12:20 +00:00
break ;
2017-07-02 00:24:27 +00:00
}
2004-03-21 18:15:37 +00:00
}
}
2005-09-14 22:40:54 +00:00
2006-05-25 18:31:19 +00:00
ast_unreplace_sigchld ( ) ;
2006-08-21 20:12:18 +00:00
# endif
2005-09-14 22:40:54 +00:00
2004-03-21 18:15:37 +00:00
return res ;
}
2017-07-02 00:24:27 +00:00
int ast_safe_execvp ( int dualfork , const char * file , char * const argv [ ] )
{
pid_t pid = safe_exec_prep ( dualfork ) ;
if ( pid = = 0 ) {
execvp ( file , argv ) ;
_exit ( 1 ) ;
/* noreturn from _exit */
}
return safe_exec_wait ( pid ) ;
}
int ast_safe_system ( const char * s )
{
pid_t pid = safe_exec_prep ( 0 ) ;
if ( pid = = 0 ) {
execl ( " /bin/sh " , " /bin/sh " , " -c " , s , ( char * ) NULL ) ;
_exit ( 1 ) ;
/* noreturn from _exit */
}
return safe_exec_wait ( pid ) ;
}
2011-06-06 19:15:10 +00:00
/*!
* \ brief enable or disable a logging level to a specified console
*/
2008-05-29 21:30:37 +00:00
void ast_console_toggle_loglevel ( int fd , int level , int state )
{
int x ;
Fix a variety of potential buffer overflows
* chan_mobile: Fixed an overrun where the cind_state buffer (an integer array
of size 16) would be overrun due to improper bounds checking. At worst, the
buffer can be overrun by a total of 48 bytes (assuming 4-byte integers),
which would still leave it within the allocated memory of struct hfp. This
would corrupt other elements in that struct but not necessarily cause any
further issues.
* app_sms: The array imsg is of size 250, while the array (ud) that the data
is copied into is of size 160. If the size of the inbound message is
greater then 160, up to 90 bytes could be overrun in ud. This would corrupt
the user data header (array udh) adjacent to ud.
* chan_unistim: A number of invalid memmoves are corrected. These would move
data (which may or may not be valid) into the ends of these buffers.
* asterisk: ast_console_toggle_loglevel does not check that the console log
level being set is less then or equal to the allowed log levels of 32.
* format_pref: In ast_codec_pref_prepend, if any occurrence of the specified
codec is not found, the value used to index into the array pref->order
would be one greater then the maximum size of the array.
* jitterbuf: If the element being placed into the jitter buffer lands in the
last available slot in the jitter history buffer, the insertion sort attempts
to move the last entry in the buffer into one slot past the maximum length
of the buffer. Note that this occurred for both the min and max jitter
history buffers.
* tdd: If a read from fsk_serial returns a character that is greater then 32,
an attempt to read past one of the statically defined arrays containing the
values that character maps to would occur.
* localtime: struct ast_time and tm are not the same size - ast_time is larger,
although it contains the elements of tm within it in the same layout. Hence,
when using memcpy to copy the contents of tm into ast_time, the size of tm
should be used, as opposed to the size of ast_time.
* extconf: this treats ast_timing's minmask array as if it had a length of 48,
when it has defined the size of the array as 24. pbx.h defines minmask as
having a size of 48.
(issue ASTERISK-19668)
Reported by: Matt Jordan
........
Merged revisions 362485 from http://svn.asterisk.org/svn/asterisk/branches/1.8
........
Merged revisions 362496 from http://svn.asterisk.org/svn/asterisk/branches/10
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@362497 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2012-04-19 02:40:55 +00:00
if ( level > = NUMLOGLEVELS ) {
level = NUMLOGLEVELS - 1 ;
}
2008-05-29 21:30:37 +00:00
for ( x = 0 ; x < AST_MAX_CONNECTS ; x + + ) {
if ( fd = = consoles [ x ] . fd ) {
2011-06-06 19:15:10 +00:00
/*
* Since the logging occurs when levels are false , set to
* flipped iinput because this function accepts 0 as off and 1 as on
*/
consoles [ x ] . levels [ level ] = state ? 0 : 1 ;
2008-05-29 21:30:37 +00:00
return ;
}
}
}
2006-05-26 19:48:17 +00:00
/*!
2006-06-08 18:03:08 +00:00
* \ brief mute or unmute a console from logging
2006-05-26 19:48:17 +00:00
*/
2012-01-09 17:06:30 +00:00
void ast_console_toggle_mute ( int fd , int silent )
{
2006-05-26 19:48:17 +00:00
int x ;
2006-05-26 21:47:52 +00:00
for ( x = 0 ; x < AST_MAX_CONNECTS ; x + + ) {
2006-05-26 19:48:17 +00:00
if ( fd = = consoles [ x ] . fd ) {
if ( consoles [ x ] . mute ) {
2006-05-26 21:47:52 +00:00
consoles [ x ] . mute = 0 ;
2007-10-13 05:53:19 +00:00
if ( ! silent )
ast_cli ( fd , " Console is not muted anymore. \n " ) ;
2006-05-26 19:48:17 +00:00
} else {
2006-05-26 21:47:52 +00:00
consoles [ x ] . mute = 1 ;
2007-10-13 05:53:19 +00:00
if ( ! silent )
ast_cli ( fd , " Console is muted. \n " ) ;
2006-05-26 19:48:17 +00:00
}
return ;
}
}
ast_cli ( fd , " Couldn't find remote console. \n " ) ;
}
/*!
2014-01-14 18:14:02 +00:00
* \ brief log the string to all attached network console clients
2006-05-26 19:48:17 +00:00
*/
logger: Support JSON logging with Verbose messages
When 2d7a4a3357 was merged, it missed the fact that Verbose log messages
are formatted and handled by 'verbosers'. Verbosers are registered
functions that handle verbose messages only; they exist as a separate
class of callbacks. This was done to handle the 'magic' that must be
inserted into Verbose messages sent to remote consoles, so that the
consoles can format the messages correctly, i.e., the leading
tabs/characters.
In reality, verbosers are a weird appendage: they're a separate class of
formatters/message handlers outside of what handles all other log
messages in Asterisk. After some code inspection, it became clear that
simply passing a Verbose message along with its 'sublevel' importance
through the normal logging mechanisms removes the need for verbosers
altogether.
This patch removes the verbosers, and makes the default log formatter
aware that, if the log channel is a console log, it should simply insert
the 'verbose magic' into the log messages itself. This allows the
console handlers to interpret and format the verbose message
themselves.
This simplifies the code quite a lot, and should improve the performance
of printing verbose messages by a reasonable factor:
(1) It removes a number of memory allocations that were done on each
verobse message
(2) It removes the need to strip the verbose magic out of the verbose
log messages before passing them to non-console log channels
(3) It now performs fewer iterations over lists when handling verbose
messages
Since verbose messages are now handled like other log messages (for the
most part), the JSON formatting of the messages works as well.
ASTERISK-25425
Change-Id: I21bf23f0a1e489b5102f8a035fe8871552ce4f96
2016-05-14 12:24:07 +00:00
static void ast_network_puts_mutable ( const char * string , int level , int sublevel )
2006-05-26 19:48:17 +00:00
{
int x ;
2014-01-14 18:14:02 +00:00
for ( x = 0 ; x < AST_MAX_CONNECTS ; + + x ) {
if ( consoles [ x ] . fd < 0
| | consoles [ x ] . mute
logger: Support JSON logging with Verbose messages
When 2d7a4a3357 was merged, it missed the fact that Verbose log messages
are formatted and handled by 'verbosers'. Verbosers are registered
functions that handle verbose messages only; they exist as a separate
class of callbacks. This was done to handle the 'magic' that must be
inserted into Verbose messages sent to remote consoles, so that the
consoles can format the messages correctly, i.e., the leading
tabs/characters.
In reality, verbosers are a weird appendage: they're a separate class of
formatters/message handlers outside of what handles all other log
messages in Asterisk. After some code inspection, it became clear that
simply passing a Verbose message along with its 'sublevel' importance
through the normal logging mechanisms removes the need for verbosers
altogether.
This patch removes the verbosers, and makes the default log formatter
aware that, if the log channel is a console log, it should simply insert
the 'verbose magic' into the log messages itself. This allows the
console handlers to interpret and format the verbose message
themselves.
This simplifies the code quite a lot, and should improve the performance
of printing verbose messages by a reasonable factor:
(1) It removes a number of memory allocations that were done on each
verobse message
(2) It removes the need to strip the verbose magic out of the verbose
log messages before passing them to non-console log channels
(3) It now performs fewer iterations over lists when handling verbose
messages
Since verbose messages are now handled like other log messages (for the
most part), the JSON formatting of the messages works as well.
ASTERISK-25425
Change-Id: I21bf23f0a1e489b5102f8a035fe8871552ce4f96
2016-05-14 12:24:07 +00:00
| | consoles [ x ] . levels [ level ]
| | ( level = = __LOG_VERBOSE & & consoles [ x ] . option_verbose < sublevel ) ) {
2006-05-26 21:47:52 +00:00
continue ;
2008-05-29 21:30:37 +00:00
}
2014-01-14 18:14:02 +00:00
fdprint ( consoles [ x ] . p [ 1 ] , string ) ;
2006-05-26 19:48:17 +00:00
}
}
/*!
2014-01-14 18:14:02 +00:00
* \ brief log the string to the root console , and all attached
* network console clients
2006-05-26 19:48:17 +00:00
*/
2008-05-29 21:30:37 +00:00
void ast_console_puts_mutable ( const char * string , int level )
logger: Support JSON logging with Verbose messages
When 2d7a4a3357 was merged, it missed the fact that Verbose log messages
are formatted and handled by 'verbosers'. Verbosers are registered
functions that handle verbose messages only; they exist as a separate
class of callbacks. This was done to handle the 'magic' that must be
inserted into Verbose messages sent to remote consoles, so that the
consoles can format the messages correctly, i.e., the leading
tabs/characters.
In reality, verbosers are a weird appendage: they're a separate class of
formatters/message handlers outside of what handles all other log
messages in Asterisk. After some code inspection, it became clear that
simply passing a Verbose message along with its 'sublevel' importance
through the normal logging mechanisms removes the need for verbosers
altogether.
This patch removes the verbosers, and makes the default log formatter
aware that, if the log channel is a console log, it should simply insert
the 'verbose magic' into the log messages itself. This allows the
console handlers to interpret and format the verbose message
themselves.
This simplifies the code quite a lot, and should improve the performance
of printing verbose messages by a reasonable factor:
(1) It removes a number of memory allocations that were done on each
verobse message
(2) It removes the need to strip the verbose magic out of the verbose
log messages before passing them to non-console log channels
(3) It now performs fewer iterations over lists when handling verbose
messages
Since verbose messages are now handled like other log messages (for the
most part), the JSON formatting of the messages works as well.
ASTERISK-25425
Change-Id: I21bf23f0a1e489b5102f8a035fe8871552ce4f96
2016-05-14 12:24:07 +00:00
{
ast_console_puts_mutable_full ( string , level , 0 ) ;
}
static int console_print ( const char * s ) ;
void ast_console_puts_mutable_full ( const char * message , int level , int sublevel )
2006-05-26 19:48:17 +00:00
{
2014-01-14 18:14:02 +00:00
/* Send to the root console */
logger: Support JSON logging with Verbose messages
When 2d7a4a3357 was merged, it missed the fact that Verbose log messages
are formatted and handled by 'verbosers'. Verbosers are registered
functions that handle verbose messages only; they exist as a separate
class of callbacks. This was done to handle the 'magic' that must be
inserted into Verbose messages sent to remote consoles, so that the
consoles can format the messages correctly, i.e., the leading
tabs/characters.
In reality, verbosers are a weird appendage: they're a separate class of
formatters/message handlers outside of what handles all other log
messages in Asterisk. After some code inspection, it became clear that
simply passing a Verbose message along with its 'sublevel' importance
through the normal logging mechanisms removes the need for verbosers
altogether.
This patch removes the verbosers, and makes the default log formatter
aware that, if the log channel is a console log, it should simply insert
the 'verbose magic' into the log messages itself. This allows the
console handlers to interpret and format the verbose message
themselves.
This simplifies the code quite a lot, and should improve the performance
of printing verbose messages by a reasonable factor:
(1) It removes a number of memory allocations that were done on each
verobse message
(2) It removes the need to strip the verbose magic out of the verbose
log messages before passing them to non-console log channels
(3) It now performs fewer iterations over lists when handling verbose
messages
Since verbose messages are now handled like other log messages (for the
most part), the JSON formatting of the messages works as well.
ASTERISK-25425
Change-Id: I21bf23f0a1e489b5102f8a035fe8871552ce4f96
2016-05-14 12:24:07 +00:00
console_print ( message ) ;
/* Wake up a poll()ing console */
if ( ast_opt_console & & consolethread ! = AST_PTHREADT_NULL ) {
pthread_kill ( consolethread , SIGURG ) ;
}
2014-01-14 18:14:02 +00:00
/* Send to any network console clients */
logger: Support JSON logging with Verbose messages
When 2d7a4a3357 was merged, it missed the fact that Verbose log messages
are formatted and handled by 'verbosers'. Verbosers are registered
functions that handle verbose messages only; they exist as a separate
class of callbacks. This was done to handle the 'magic' that must be
inserted into Verbose messages sent to remote consoles, so that the
consoles can format the messages correctly, i.e., the leading
tabs/characters.
In reality, verbosers are a weird appendage: they're a separate class of
formatters/message handlers outside of what handles all other log
messages in Asterisk. After some code inspection, it became clear that
simply passing a Verbose message along with its 'sublevel' importance
through the normal logging mechanisms removes the need for verbosers
altogether.
This patch removes the verbosers, and makes the default log formatter
aware that, if the log channel is a console log, it should simply insert
the 'verbose magic' into the log messages itself. This allows the
console handlers to interpret and format the verbose message
themselves.
This simplifies the code quite a lot, and should improve the performance
of printing verbose messages by a reasonable factor:
(1) It removes a number of memory allocations that were done on each
verobse message
(2) It removes the need to strip the verbose magic out of the verbose
log messages before passing them to non-console log channels
(3) It now performs fewer iterations over lists when handling verbose
messages
Since verbose messages are now handled like other log messages (for the
most part), the JSON formatting of the messages works as well.
ASTERISK-25425
Change-Id: I21bf23f0a1e489b5102f8a035fe8871552ce4f96
2016-05-14 12:24:07 +00:00
ast_network_puts_mutable ( message , level , sublevel ) ;
2006-05-26 19:48:17 +00:00
}
2005-10-24 20:12:06 +00:00
/*!
2006-06-08 18:03:08 +00:00
* \ brief write the string to all attached console clients
2004-01-12 05:05:35 +00:00
*/
static void ast_network_puts ( const char * string )
{
2004-06-29 04:42:19 +00:00
int x ;
2014-01-14 18:14:02 +00:00
for ( x = 0 ; x < AST_MAX_CONNECTS ; + + x ) {
if ( consoles [ x ] . fd < 0 ) {
continue ;
}
fdprint ( consoles [ x ] . p [ 1 ] , string ) ;
2004-06-29 04:42:19 +00:00
}
2004-01-12 05:05:35 +00:00
}
2005-10-24 20:12:06 +00:00
/*!
2014-01-14 18:14:02 +00:00
* \ brief write the string to the root console , and all attached
* network console clients
2004-01-12 05:05:35 +00:00
*/
void ast_console_puts ( const char * string )
{
2014-01-14 18:14:02 +00:00
/* Send to the root console */
2004-06-29 04:42:19 +00:00
fputs ( string , stdout ) ;
fflush ( stdout ) ;
2014-01-14 18:14:02 +00:00
/* Send to any network console clients */
2004-06-29 04:42:19 +00:00
ast_network_puts ( string ) ;
2004-01-12 05:05:35 +00:00
}
2001-05-09 03:11:22 +00:00
static pthread_t lthread ;
2008-12-01 18:52:14 +00:00
/*!
* \ brief read ( ) function supporting the reception of user credentials .
*
* \ param fd Socket file descriptor .
* \ param buffer Receive buffer .
* \ param size ' buffer ' size .
* \ param con Console structure to set received credentials
* \ retval - 1 on error
* \ retval the number of bytes received on success .
*/
static int read_credentials ( int fd , char * buffer , size_t size , struct console * con )
{
# if defined(SO_PEERCRED)
2012-01-13 21:42:12 +00:00
# ifdef HAVE_STRUCT_SOCKPEERCRED_UID
# define HAVE_STRUCT_UCRED_UID
struct sockpeercred cred ;
# else
2008-12-01 18:52:14 +00:00
struct ucred cred ;
2012-01-13 21:42:12 +00:00
# endif
2008-12-01 18:52:14 +00:00
socklen_t len = sizeof ( cred ) ;
# endif
2009-01-14 19:36:57 +00:00
# if defined(HAVE_GETPEEREID)
uid_t uid ;
gid_t gid ;
# else
int uid , gid ;
# endif
int result ;
2008-12-01 18:52:14 +00:00
result = read ( fd , buffer , size ) ;
if ( result < 0 ) {
return result ;
}
2010-11-29 07:30:09 +00:00
# if defined(SO_PEERCRED) && (defined(HAVE_STRUCT_UCRED_UID) || defined(HAVE_STRUCT_UCRED_CR_UID))
2008-12-01 18:52:14 +00:00
if ( getsockopt ( fd , SOL_SOCKET , SO_PEERCRED , & cred , & len ) ) {
return result ;
}
2010-11-29 07:30:09 +00:00
# if defined(HAVE_STRUCT_UCRED_UID)
2008-12-01 18:52:14 +00:00
uid = cred . uid ;
gid = cred . gid ;
2010-11-29 07:30:09 +00:00
# else /* defined(HAVE_STRUCT_UCRED_CR_UID) */
uid = cred . cr_uid ;
gid = cred . cr_gid ;
# endif /* defined(HAVE_STRUCT_UCRED_UID) */
2008-12-01 18:52:14 +00:00
# elif defined(HAVE_GETPEEREID)
if ( getpeereid ( fd , & uid , & gid ) ) {
return result ;
}
# else
return result ;
# endif
con - > uid = uid ;
con - > gid = gid ;
return result ;
}
2014-01-14 18:14:02 +00:00
/* This is the thread running the remote console on the main process. */
2001-05-09 03:11:22 +00:00
static void * netconsole ( void * vconsole )
{
struct console * con = vconsole ;
2006-03-31 00:33:28 +00:00
char hostname [ MAXHOSTNAMELEN ] = " " ;
2012-04-19 14:35:56 +00:00
char inbuf [ 512 ] ;
char outbuf [ 512 ] ;
2012-04-26 19:33:49 +00:00
const char * const end_buf = inbuf + sizeof ( inbuf ) ;
2012-04-19 14:35:56 +00:00
char * start_read = inbuf ;
2001-05-09 03:11:22 +00:00
int res ;
2004-04-25 20:42:45 +00:00
struct pollfd fds [ 2 ] ;
2012-03-22 19:51:16 +00:00
2005-05-08 16:44:25 +00:00
if ( gethostname ( hostname , sizeof ( hostname ) - 1 ) )
2005-06-05 16:32:16 +00:00
ast_copy_string ( hostname , " <Unknown> " , sizeof ( hostname ) ) ;
2012-04-19 14:35:56 +00:00
snprintf ( outbuf , sizeof ( outbuf ) , " %s/%ld/%s \n " , hostname , ( long ) ast_mainpid , ast_get_version ( ) ) ;
fdprint ( con - > fd , outbuf ) ;
2014-01-14 18:14:02 +00:00
ast_verb_console_register ( & con - > option_verbose ) ;
2007-01-23 00:11:32 +00:00
for ( ; ; ) {
2004-04-25 20:42:45 +00:00
fds [ 0 ] . fd = con - > fd ;
fds [ 0 ] . events = POLLIN ;
2005-08-31 22:12:23 +00:00
fds [ 0 ] . revents = 0 ;
2004-04-25 20:42:45 +00:00
fds [ 1 ] . fd = con - > p [ 0 ] ;
fds [ 1 ] . events = POLLIN ;
2005-08-31 22:12:23 +00:00
fds [ 1 ] . revents = 0 ;
2004-04-25 20:42:45 +00:00
Merged revisions 182810 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/1.4
........
r182810 | russell | 2009-03-17 21:09:13 -0500 (Tue, 17 Mar 2009) | 44 lines
Fix cases where the internal poll() was not being used when it needed to be.
We have seen a number of problems caused by poll() not working properly on
Mac OSX. If you search around, you'll find a number of references to using
select() instead of poll() to work around these issues. In Asterisk, we've
had poll.c which implements poll() using select() internally. However, we
were still getting reports of problems.
vadim investigated a bit and realized that at least on his system, even
though we were compiling in poll.o, the system poll() was still being used.
So, the primary purpose of this patch is to ensure that we're using the
internal poll() when we want it to be used.
The changes are:
1) Remove logic for when internal poll should be used from the Makefile.
Instead, put it in the configure script. The logic in the configure
script is the same as it was in the Makefile. Ideally, we would have
a functionality test for the problem, but that's not actually possible,
since we would have to be able to run an application on the _target_
system to test poll() behavior.
2) Always include poll.o in the build, but it will be empty if AST_POLL_COMPAT
is not defined.
3) Change uses of poll() throughout the source tree to ast_poll(). I feel
that it is good practice to give the API call a new name when we are
changing its behavior and not using the system version directly in all cases.
So, normally, ast_poll() is just redefined to poll(). On systems where
AST_POLL_COMPAT is defined, ast_poll() is redefined to ast_internal_poll().
4) Change poll() in main/poll.c to be ast_internal_poll().
It's worth noting that any code that still uses poll() directly will work fine
(if they worked fine before). So, for example, out of tree modules that are
using poll() will not stop working or anything. However, for modules to work
properly on Mac OSX, ast_poll() needs to be used.
(closes issue #13404)
Reported by: agalbraith
Tested by: russell, vadim
http://reviewboard.digium.com/r/198/
........
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@182847 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-03-18 02:28:55 +00:00
res = ast_poll ( fds , 2 , - 1 ) ;
2001-05-09 03:11:22 +00:00
if ( res < 0 ) {
2004-05-07 14:08:50 +00:00
if ( errno ! = EINTR )
ast_log ( LOG_WARNING , " poll returned < 0: %s \n " , strerror ( errno ) ) ;
2001-05-09 03:11:22 +00:00
continue ;
}
2004-04-25 20:42:45 +00:00
if ( fds [ 0 ] . revents ) {
2012-04-19 14:35:56 +00:00
int cmds_read , bytes_read ;
if ( ( bytes_read = read_credentials ( con - > fd , start_read , end_buf - start_read , con ) ) < 1 ) {
2001-05-09 03:11:22 +00:00
break ;
2001-10-11 18:51:39 +00:00
}
2012-04-19 14:35:56 +00:00
/* XXX This will only work if it is the first command, and I'm not sure fixing it is worth the effort. */
if ( strncmp ( inbuf , " cli quit after " , 15 ) = = 0 ) {
ast_cli_command_multiple_full ( con - > uid , con - > gid , con - > fd , bytes_read - 15 , inbuf + 15 ) ;
2008-07-08 20:17:08 +00:00
break ;
}
2012-04-19 14:35:56 +00:00
/* ast_cli_command_multiple_full will only process individual commands terminated by a
* NULL and not trailing partial commands . */
if ( ! ( cmds_read = ast_cli_command_multiple_full ( con - > uid , con - > gid , con - > fd , bytes_read + start_read - inbuf , inbuf ) ) ) {
/* No commands were read. We either have a short read on the first command
* with space left , or a command that is too long */
if ( start_read + bytes_read < end_buf ) {
start_read + = bytes_read ;
} else {
ast_log ( LOG_ERROR , " Command too long! Skipping \n " ) ;
start_read = inbuf ;
}
continue ;
}
if ( start_read [ bytes_read - 1 ] = = ' \0 ' ) {
/* The read ended on a command boundary, start reading again at the head of inbuf */
start_read = inbuf ;
continue ;
}
/* If we get this far, we have left over characters that have not been processed.
* Advance to the character after the last command read by ast_cli_command_multiple_full .
* We are guaranteed to have at least cmds_read NULLs */
2012-04-24 17:52:26 +00:00
while ( cmds_read - - & & ( start_read = strchr ( start_read , ' \0 ' ) ) ) {
2012-04-19 14:35:56 +00:00
start_read + + ;
}
memmove ( inbuf , start_read , end_buf - start_read ) ;
start_read = end_buf - start_read + inbuf ;
2001-05-09 03:11:22 +00:00
}
2004-04-25 20:42:45 +00:00
if ( fds [ 1 ] . revents ) {
2012-04-19 14:35:56 +00:00
res = read_credentials ( con - > p [ 0 ] , outbuf , sizeof ( outbuf ) , con ) ;
2001-05-09 03:11:22 +00:00
if ( res < 1 ) {
ast_log ( LOG_ERROR , " read returned %d \n " , res ) ;
break ;
}
2012-04-19 14:35:56 +00:00
res = write ( con - > fd , outbuf , res ) ;
2001-05-09 03:11:22 +00:00
if ( res < 1 )
break ;
}
}
2014-01-14 18:14:02 +00:00
ast_verb_console_unregister ( ) ;
2009-01-13 23:00:27 +00:00
if ( ! ast_opt_hide_connect ) {
ast_verb ( 3 , " Remote UNIX connection disconnected \n " ) ;
}
2001-05-09 03:11:22 +00:00
close ( con - > fd ) ;
close ( con - > p [ 0 ] ) ;
close ( con - > p [ 1 ] ) ;
con - > fd = - 1 ;
2012-03-22 19:51:16 +00:00
2001-05-09 03:11:22 +00:00
return NULL ;
}
static void * listener ( void * unused )
{
2004-12-14 23:36:30 +00:00
struct sockaddr_un sunaddr ;
2001-05-09 03:11:22 +00:00
int s ;
2005-05-15 03:21:51 +00:00
socklen_t len ;
2001-05-09 03:11:22 +00:00
int x ;
2017-12-19 02:12:47 +00:00
int poll_result ;
2004-04-25 20:42:45 +00:00
struct pollfd fds [ 1 ] ;
2017-12-19 02:12:47 +00:00
2006-03-31 00:33:28 +00:00
for ( ; ; ) {
2017-12-19 02:12:47 +00:00
if ( ast_socket < 0 ) {
2002-09-12 03:22:07 +00:00
return NULL ;
2017-12-19 02:12:47 +00:00
}
2004-04-25 20:42:45 +00:00
fds [ 0 ] . fd = ast_socket ;
2006-03-31 00:33:28 +00:00
fds [ 0 ] . events = POLLIN ;
2017-12-19 02:12:47 +00:00
poll_result = ast_poll ( fds , 1 , - 1 ) ;
2006-07-03 05:14:06 +00:00
pthread_testcancel ( ) ;
2017-12-19 02:12:47 +00:00
if ( poll_result < 0 ) {
if ( errno ! = EINTR ) {
2004-04-25 20:42:45 +00:00
ast_log ( LOG_WARNING , " poll returned error: %s \n " , strerror ( errno ) ) ;
2017-12-19 02:12:47 +00:00
}
2003-09-29 20:20:04 +00:00
continue ;
}
2004-12-14 23:36:30 +00:00
len = sizeof ( sunaddr ) ;
s = accept ( ast_socket , ( struct sockaddr * ) & sunaddr , & len ) ;
2001-05-09 03:11:22 +00:00
if ( s < 0 ) {
2004-03-02 16:58:17 +00:00
if ( errno ! = EINTR )
2004-03-03 00:05:00 +00:00
ast_log ( LOG_WARNING , " Accept returned %d: %s \n " , s , strerror ( errno ) ) ;
2001-05-09 03:11:22 +00:00
} else {
2015-02-21 02:51:35 +00:00
# if defined(SO_PASSCRED)
2008-12-01 18:52:14 +00:00
int sckopt = 1 ;
/* turn on socket credentials passing. */
if ( setsockopt ( s , SOL_SOCKET , SO_PASSCRED , & sckopt , sizeof ( sckopt ) ) < 0 ) {
ast_log ( LOG_WARNING , " Unable to turn on socket credentials passing \n " ) ;
2017-12-19 02:12:47 +00:00
close ( s ) ;
2015-02-21 02:51:35 +00:00
} else
2008-12-01 18:52:14 +00:00
# endif
2015-02-21 02:51:35 +00:00
{
2008-12-01 18:52:14 +00:00
for ( x = 0 ; x < AST_MAX_CONNECTS ; x + + ) {
if ( consoles [ x ] . fd > = 0 ) {
continue ;
}
2001-10-11 18:51:39 +00:00
if ( socketpair ( AF_LOCAL , SOCK_STREAM , 0 , consoles [ x ] . p ) ) {
2001-05-09 03:11:22 +00:00
ast_log ( LOG_ERROR , " Unable to create pipe: %s \n " , strerror ( errno ) ) ;
fdprint ( s , " Server failed to create pipe \n " ) ;
close ( s ) ;
break ;
}
2017-12-07 15:52:39 +00:00
ast_fd_set_flags ( consoles [ x ] . p [ 1 ] , O_NONBLOCK ) ;
2007-10-13 05:53:19 +00:00
consoles [ x ] . mute = 1 ; /* Default is muted, we will un-mute if necessary */
2008-12-01 18:52:14 +00:00
/* Default uid and gid to -2, so then in cli.c/cli_has_permissions() we will be able
to know if the user didn ' t send the credentials . */
consoles [ x ] . uid = - 2 ;
consoles [ x ] . gid = - 2 ;
2014-01-14 18:14:02 +00:00
/* Server default of remote console verbosity level is OFF. */
consoles [ x ] . option_verbose = 0 ;
consoles [ x ] . fd = s ;
2007-05-24 18:30:19 +00:00
if ( ast_pthread_create_detached_background ( & consoles [ x ] . t , NULL , netconsole , & consoles [ x ] ) ) {
2014-01-14 18:14:02 +00:00
consoles [ x ] . fd = - 1 ;
2004-05-07 14:08:50 +00:00
ast_log ( LOG_ERROR , " Unable to spawn thread to handle connection: %s \n " , strerror ( errno ) ) ;
2006-04-11 21:58:44 +00:00
close ( consoles [ x ] . p [ 0 ] ) ;
close ( consoles [ x ] . p [ 1 ] ) ;
2001-05-09 03:11:22 +00:00
fdprint ( s , " Server failed to spawn thread \n " ) ;
close ( s ) ;
}
break ;
}
2008-12-01 18:52:14 +00:00
if ( x > = AST_MAX_CONNECTS ) {
fdprint ( s , " No more connections allowed \n " ) ;
ast_log ( LOG_WARNING , " No more connections allowed \n " ) ;
close ( s ) ;
2009-01-13 23:00:27 +00:00
} else if ( ( consoles [ x ] . fd > - 1 ) & & ( ! ast_opt_hide_connect ) ) {
2008-12-01 18:52:14 +00:00
ast_verb ( 3 , " Remote UNIX connection \n " ) ;
2009-01-13 23:00:27 +00:00
}
2001-05-09 03:11:22 +00:00
}
}
}
return NULL ;
}
static int ast_makesocket ( void )
{
2004-12-14 23:36:30 +00:00
struct sockaddr_un sunaddr ;
2001-05-09 03:11:22 +00:00
int res ;
int x ;
2005-07-25 23:09:13 +00:00
uid_t uid = - 1 ;
gid_t gid = - 1 ;
2005-02-11 21:16:34 +00:00
2017-06-19 00:24:04 +00:00
for ( x = 0 ; x < AST_MAX_CONNECTS ; x + + ) {
2001-05-09 03:11:22 +00:00
consoles [ x ] . fd = - 1 ;
2017-06-19 00:24:04 +00:00
}
if ( ast_socket_is_sd ) {
ast_socket = ast_sd_get_fd_un ( SOCK_STREAM , ast_config_AST_SOCKET ) ;
goto start_lthread ;
}
2005-07-25 23:09:13 +00:00
unlink ( ast_config_AST_SOCKET ) ;
2001-05-09 03:11:22 +00:00
ast_socket = socket ( PF_LOCAL , SOCK_STREAM , 0 ) ;
if ( ast_socket < 0 ) {
ast_log ( LOG_WARNING , " Unable to create control socket: %s \n " , strerror ( errno ) ) ;
return - 1 ;
2012-03-22 19:51:16 +00:00
}
2004-12-14 23:36:30 +00:00
memset ( & sunaddr , 0 , sizeof ( sunaddr ) ) ;
sunaddr . sun_family = AF_LOCAL ;
2005-07-25 23:09:13 +00:00
ast_copy_string ( sunaddr . sun_path , ast_config_AST_SOCKET , sizeof ( sunaddr . sun_path ) ) ;
2004-12-14 23:36:30 +00:00
res = bind ( ast_socket , ( struct sockaddr * ) & sunaddr , sizeof ( sunaddr ) ) ;
2001-05-09 03:11:22 +00:00
if ( res ) {
2005-07-25 23:09:13 +00:00
ast_log ( LOG_WARNING , " Unable to bind socket to %s: %s \n " , ast_config_AST_SOCKET , strerror ( errno ) ) ;
2001-05-09 03:11:22 +00:00
close ( ast_socket ) ;
ast_socket = - 1 ;
return - 1 ;
}
res = listen ( ast_socket , 2 ) ;
if ( res < 0 ) {
2005-07-25 23:09:13 +00:00
ast_log ( LOG_WARNING , " Unable to listen on socket %s: %s \n " , ast_config_AST_SOCKET , strerror ( errno ) ) ;
2001-05-09 03:11:22 +00:00
close ( ast_socket ) ;
ast_socket = - 1 ;
return - 1 ;
}
2008-05-02 02:33:04 +00:00
2017-06-19 00:24:04 +00:00
start_lthread :
2012-05-10 18:35:14 +00:00
if ( ast_pthread_create_background ( & lthread , NULL , listener , NULL ) ) {
ast_log ( LOG_WARNING , " Unable to create listener thread. \n " ) ;
close ( ast_socket ) ;
return - 1 ;
}
2005-02-11 21:16:34 +00:00
2017-06-19 00:24:04 +00:00
if ( ast_socket_is_sd ) {
/* owner/group/permissions are set by systemd, we might not even have access
* to socket file so leave it alone */
return 0 ;
}
2005-07-25 23:09:13 +00:00
if ( ! ast_strlen_zero ( ast_config_AST_CTL_OWNER ) ) {
2005-02-11 21:16:34 +00:00
struct passwd * pw ;
2006-10-29 20:47:01 +00:00
if ( ( pw = getpwnam ( ast_config_AST_CTL_OWNER ) ) = = NULL )
2005-07-25 23:09:13 +00:00
ast_log ( LOG_WARNING , " Unable to find uid of user %s \n " , ast_config_AST_CTL_OWNER ) ;
2006-10-29 20:47:01 +00:00
else
2005-07-25 23:09:13 +00:00
uid = pw - > pw_uid ;
2005-02-11 21:16:34 +00:00
}
2012-03-22 19:51:16 +00:00
2005-07-25 23:09:13 +00:00
if ( ! ast_strlen_zero ( ast_config_AST_CTL_GROUP ) ) {
2005-02-11 21:16:34 +00:00
struct group * grp ;
2006-10-29 20:47:01 +00:00
if ( ( grp = getgrnam ( ast_config_AST_CTL_GROUP ) ) = = NULL )
2005-07-25 23:09:13 +00:00
ast_log ( LOG_WARNING , " Unable to find gid of group %s \n " , ast_config_AST_CTL_GROUP ) ;
2006-10-29 20:47:01 +00:00
else
2005-07-25 23:09:13 +00:00
gid = grp - > gr_gid ;
2005-02-11 21:16:34 +00:00
}
2005-07-25 23:09:13 +00:00
if ( chown ( ast_config_AST_SOCKET , uid , gid ) < 0 )
ast_log ( LOG_WARNING , " Unable to change ownership of %s: %s \n " , ast_config_AST_SOCKET , strerror ( errno ) ) ;
if ( ! ast_strlen_zero ( ast_config_AST_CTL_PERMISSIONS ) ) {
2014-05-09 22:49:26 +00:00
unsigned int p1 ;
2005-02-11 21:16:34 +00:00
mode_t p ;
2009-08-10 19:20:57 +00:00
sscanf ( ast_config_AST_CTL_PERMISSIONS , " %30o " , & p1 ) ;
2005-12-26 18:35:28 +00:00
p = p1 ;
2005-07-25 23:09:13 +00:00
if ( ( chmod ( ast_config_AST_SOCKET , p ) ) < 0 )
ast_log ( LOG_WARNING , " Unable to change file permissions of %s: %s \n " , ast_config_AST_SOCKET , strerror ( errno ) ) ;
2005-02-11 21:16:34 +00:00
}
2001-05-09 03:11:22 +00:00
return 0 ;
}
static int ast_tryconnect ( void )
{
2004-12-14 23:36:30 +00:00
struct sockaddr_un sunaddr ;
2001-05-09 03:11:22 +00:00
int res ;
ast_consock = socket ( PF_LOCAL , SOCK_STREAM , 0 ) ;
if ( ast_consock < 0 ) {
2012-11-18 20:27:45 +00:00
fprintf ( stderr , " Unable to create socket: %s \n " , strerror ( errno ) ) ;
2001-05-09 03:11:22 +00:00
return 0 ;
}
2004-12-14 23:36:30 +00:00
memset ( & sunaddr , 0 , sizeof ( sunaddr ) ) ;
sunaddr . sun_family = AF_LOCAL ;
2007-12-18 09:46:18 +00:00
ast_copy_string ( sunaddr . sun_path , ast_config_AST_SOCKET , sizeof ( sunaddr . sun_path ) ) ;
2004-12-14 23:36:30 +00:00
res = connect ( ast_consock , ( struct sockaddr * ) & sunaddr , sizeof ( sunaddr ) ) ;
2001-05-09 03:11:22 +00:00
if ( res ) {
close ( ast_consock ) ;
ast_consock = - 1 ;
return 0 ;
} else
return 1 ;
}
2006-06-08 18:03:08 +00:00
/*! \brief Urgent handler
2012-09-21 17:14:59 +00:00
*
* Called by soft_hangup to interrupt the poll , read , or other
* system call . We don ' t actually need to do anything though .
* Remember : Cannot EVER ast_log from within a signal handler
2005-10-24 20:12:06 +00:00
*/
2010-05-26 21:17:46 +00:00
static void _urg_handler ( int num )
1999-11-15 04:57:28 +00:00
{
return ;
}
2010-05-26 21:17:46 +00:00
static struct sigaction urg_handler = {
. sa_handler = _urg_handler ,
} ;
static void _hup_handler ( int num )
2001-05-09 03:11:22 +00:00
{
2017-11-10 01:47:27 +00:00
int save_errno = errno ;
2018-11-15 11:33:11 +00:00
if ( restartnow ) {
if ( el ) {
el_end ( el ) ;
}
2004-02-23 03:43:21 +00:00
execvp ( _argv [ 0 ] , _argv ) ;
2018-11-15 11:33:11 +00:00
}
printf ( " Received HUP signal -- Reloading configs \n " ) ;
2007-02-23 23:25:22 +00:00
sig_flags . need_reload = 1 ;
2017-11-10 01:47:27 +00:00
if ( ast_alertpipe_write ( sig_alert_pipe ) ) {
fprintf ( stderr , " hup_handler: write() failed: %s \n " , strerror ( errno ) ) ;
2008-11-02 18:52:13 +00:00
}
2011-06-27 16:32:19 +00:00
errno = save_errno ;
2001-05-09 03:11:22 +00:00
}
2010-05-26 21:17:46 +00:00
static struct sigaction hup_handler = {
. sa_handler = _hup_handler ,
2010-06-10 08:15:45 +00:00
. sa_flags = SA_RESTART ,
2010-05-26 21:17:46 +00:00
} ;
static void _child_handler ( int sig )
2001-05-09 03:11:22 +00:00
{
2003-12-01 02:47:19 +00:00
/* Must not ever ast_log or ast_verbose within signal handler */
2011-06-27 16:32:19 +00:00
int n , status , save_errno = errno ;
2003-09-16 19:35:57 +00:00
/*
* Reap all dead children - - not just one
*/
2013-11-08 14:58:13 +00:00
for ( n = 0 ; waitpid ( - 1 , & status , WNOHANG ) > 0 ; n + + )
2003-09-16 19:35:57 +00:00
;
2012-03-22 19:51:16 +00:00
if ( n = = 0 & & option_debug )
2003-12-01 02:47:19 +00:00
printf ( " Huh? Child handler, but nobody there? \n " ) ;
2011-06-27 16:32:19 +00:00
errno = save_errno ;
2001-05-09 03:11:22 +00:00
}
2003-09-16 19:35:57 +00:00
2010-05-26 21:17:46 +00:00
static struct sigaction child_handler = {
. sa_handler = _child_handler ,
2010-06-10 08:15:45 +00:00
. sa_flags = SA_RESTART ,
2010-05-26 21:17:46 +00:00
} ;
2006-06-08 18:03:08 +00:00
/*! \brief Set an X-term or screen title */
2000-10-25 23:22:50 +00:00
static void set_title ( char * text )
{
if ( getenv ( " TERM " ) & & strstr ( getenv ( " TERM " ) , " xterm " ) )
fprintf ( stdout , " \033 ]2;%s \007 " , text ) ;
}
static void set_icon ( char * text )
{
if ( getenv ( " TERM " ) & & strstr ( getenv ( " TERM " ) , " xterm " ) )
fprintf ( stdout , " \033 ]1;%s \007 " , text ) ;
}
2016-09-19 19:21:23 +00:00
/*! \brief Check whether we were set to high(er) priority. */
static int has_priority ( void )
{
/* Neither of these calls should fail with these arguments. */
# ifdef __linux__
/* For SCHED_OTHER, SCHED_BATCH and SCHED_IDLE, this will return
* 0. For the realtime priorities SCHED_RR and SCHED_FIFO , it
* will return something > = 1. */
return sched_getscheduler ( 0 ) ;
# else
/* getpriority() can return a value in -20..19 (or even -INF..20)
* where negative numbers are high priority . We don ' t bother
* checking errno . If the query fails and it returns - 1 , we ' ll
* assume that we ' re running at high prio ; a safe assumption
* that will enable the resource starvation monitor ( canary )
* just in case . */
return ( getpriority ( PRIO_PROCESS , 0 ) < 0 ) ;
# endif
}
2016-09-19 14:40:40 +00:00
/*! \brief Set priority on all known threads. */
static int set_priority_all ( int pri )
{
# if !defined(__linux__)
/* The non-linux version updates the entire process prio. */
return ast_set_priority ( pri ) ;
# elif defined(LOW_MEMORY)
ast_log ( LOG_WARNING , " Unable to enumerate all threads to update priority \n " ) ;
return ast_set_priority ( pri ) ;
# else
struct thread_list_t * cur ;
struct sched_param sched ;
char const * policy_str ;
int policy ;
memset ( & sched , 0 , sizeof ( sched ) ) ;
if ( pri ) {
policy = SCHED_RR ;
policy_str = " realtime " ;
sched . sched_priority = 10 ;
} else {
policy = SCHED_OTHER ;
policy_str = " regular " ;
sched . sched_priority = 0 ;
}
if ( sched_setscheduler ( getpid ( ) , policy , & sched ) ) {
ast_log ( LOG_WARNING , " Unable to set %s thread priority on main thread \n " , policy_str ) ;
return - 1 ;
}
ast_verb ( 1 , " Setting %s thread priority on all threads \n " , policy_str ) ;
AST_RWLIST_RDLOCK ( & thread_list ) ;
AST_RWLIST_TRAVERSE ( & thread_list , cur , list ) {
/* Don't care about the return value. It should work. */
sched_setscheduler ( cur - > lwp , policy , & sched ) ;
}
AST_RWLIST_UNLOCK ( & thread_list ) ;
return 0 ;
# endif
}
2012-09-21 17:14:59 +00:00
/*! \brief We set ourselves to a high priority, that we might pre-empt
* everything else . If your PBX has heavy activity on it , this is a
* good thing .
*/
2005-08-23 01:30:22 +00:00
int ast_set_priority ( int pri )
1999-12-19 22:38:55 +00:00
{
struct sched_param sched ;
2001-03-22 04:14:04 +00:00
memset ( & sched , 0 , sizeof ( sched ) ) ;
2003-04-23 20:22:14 +00:00
# ifdef __linux__
2012-03-22 19:51:16 +00:00
if ( pri ) {
2001-03-22 04:14:04 +00:00
sched . sched_priority = 10 ;
if ( sched_setscheduler ( 0 , SCHED_RR , & sched ) ) {
1999-12-19 22:38:55 +00:00
ast_log ( LOG_WARNING , " Unable to set high priority \n " ) ;
return - 1 ;
2001-03-22 04:14:04 +00:00
} else
2012-02-14 20:27:16 +00:00
ast_verb ( 1 , " Set to realtime thread \n " ) ;
1999-12-19 22:38:55 +00:00
} else {
sched . sched_priority = 0 ;
2007-04-09 03:04:07 +00:00
/* According to the manpage, these parameters can never fail. */
sched_setscheduler ( 0 , SCHED_OTHER , & sched ) ;
1999-12-19 22:38:55 +00:00
}
2003-04-23 20:22:14 +00:00
# else
if ( pri ) {
if ( setpriority ( PRIO_PROCESS , 0 , - 10 ) = = - 1 ) {
ast_log ( LOG_WARNING , " Unable to set high priority \n " ) ;
return - 1 ;
} else
2012-02-14 20:27:16 +00:00
ast_verb ( 1 , " Set to high priority \n " ) ;
2003-04-23 20:22:14 +00:00
} else {
2007-04-09 03:04:07 +00:00
/* According to the manpage, these parameters can never fail. */
setpriority ( PRIO_PROCESS , 0 , 0 ) ;
2003-04-23 20:22:14 +00:00
}
# endif
1999-12-19 22:38:55 +00:00
return 0 ;
}
2015-02-11 17:39:13 +00:00
int ast_shutdown_final ( void )
{
return shuttingdown = = SHUTTING_DOWN_FINAL ;
}
int ast_shutting_down ( void )
{
return shutdown_pending ;
}
int ast_cancel_shutdown ( void )
{
int shutdown_aborted = 0 ;
ast_mutex_lock ( & safe_system_lock ) ;
if ( shuttingdown > = SHUTDOWN_FAST ) {
shuttingdown = NOT_SHUTTING_DOWN ;
shutdown_pending = 0 ;
shutdown_aborted = 1 ;
}
ast_mutex_unlock ( & safe_system_lock ) ;
return shutdown_aborted ;
}
/*!
* \ internal
* \ brief Initiate system shutdown - - prevents new channels from being allocated .
*/
static void ast_begin_shutdown ( void )
{
ast_mutex_lock ( & safe_system_lock ) ;
if ( shuttingdown ! = NOT_SHUTTING_DOWN ) {
shutdown_pending = 1 ;
}
ast_mutex_unlock ( & safe_system_lock ) ;
}
2012-01-15 20:16:08 +00:00
static int can_safely_quit ( shutdown_nice_t niceness , int restart ) ;
static void really_quit ( int num , shutdown_nice_t niceness , int restart ) ;
static void quit_handler ( int num , shutdown_nice_t niceness , int restart )
1999-11-15 04:57:28 +00:00
{
2012-01-15 20:16:08 +00:00
if ( can_safely_quit ( niceness , restart ) ) {
really_quit ( num , niceness , restart ) ;
/* No one gets here. */
}
/* It wasn't our time. */
}
2015-02-11 17:39:13 +00:00
# define SHUTDOWN_TIMEOUT 15 /* Seconds */
/*!
* \ internal
* \ brief Wait for all channels to die , a timeout , or shutdown cancelled .
* \ since 13.3 .0
*
* \ param niceness Shutdown niceness in effect
* \ param seconds Number of seconds to wait or less than zero if indefinitely .
*
* \ retval zero if waiting wasn ' t necessary . We were idle .
* \ retval non - zero if we had to wait .
*/
static int wait_for_channels_to_die ( shutdown_nice_t niceness , int seconds )
{
time_t start ;
time_t now ;
int waited = 0 ;
time ( & start ) ;
for ( ; ; ) {
if ( ! ast_undestroyed_channels ( ) | | shuttingdown ! = niceness ) {
break ;
}
if ( seconds < 0 ) {
/* No timeout so just poll every second */
sleep ( 1 ) ;
} else {
time ( & now ) ;
/* Wait up to the given seconds for all channels to go away */
if ( seconds < ( now - start ) ) {
break ;
}
/* Sleep 1/10 of a second */
usleep ( 100000 ) ;
}
waited = 1 ;
}
return waited ;
}
2012-01-15 20:16:08 +00:00
static int can_safely_quit ( shutdown_nice_t niceness , int restart )
{
2015-02-11 17:39:13 +00:00
int waited = 0 ;
2012-01-15 20:16:08 +00:00
/* Check if someone else isn't already doing this. */
ast_mutex_lock ( & safe_system_lock ) ;
if ( shuttingdown ! = NOT_SHUTTING_DOWN & & niceness > = shuttingdown ) {
/* Already in progress and other request was less nice. */
ast_mutex_unlock ( & safe_system_lock ) ;
ast_verbose ( " Ignoring asterisk %s request, already in progress. \n " , restart ? " restart " : " shutdown " ) ;
return 0 ;
}
shuttingdown = niceness ;
ast_mutex_unlock ( & safe_system_lock ) ;
/* Try to get as many CDRs as possible submitted to the backend engines
* ( if in batch mode ) . really_quit happens to call it again when running
* the atexit handlers , otherwise this would be a bit early . */
2005-06-03 01:42:31 +00:00
ast_cdr_engine_term ( ) ;
2012-10-02 01:47:16 +00:00
2015-02-11 17:39:13 +00:00
/*
* Shutdown the message queue for the technology agnostic message channel .
* This has to occur before we pause shutdown pending ast_undestroyed_channels .
*
* XXX This is not reversed on shutdown cancel .
*/
2012-09-11 21:17:53 +00:00
ast_msg_shutdown ( ) ;
2012-01-15 20:16:08 +00:00
if ( niceness = = SHUTDOWN_NORMAL ) {
/* Begin shutdown routine, hanging up active channels */
2015-02-11 17:39:13 +00:00
ast_begin_shutdown ( ) ;
2013-08-29 22:49:24 +00:00
if ( ast_opt_console ) {
ast_verb ( 0 , " Beginning asterisk %s.... \n " , restart ? " restart " : " shutdown " ) ;
2012-01-15 20:16:08 +00:00
}
2015-02-11 17:39:13 +00:00
ast_softhangup_all ( ) ;
waited | = wait_for_channels_to_die ( niceness , SHUTDOWN_TIMEOUT ) ;
2012-01-15 20:16:08 +00:00
} else if ( niceness > = SHUTDOWN_NICE ) {
if ( niceness ! = SHUTDOWN_REALLY_NICE ) {
2015-02-11 17:39:13 +00:00
ast_begin_shutdown ( ) ;
2012-01-15 20:16:08 +00:00
}
2013-08-29 22:49:24 +00:00
if ( ast_opt_console ) {
2012-02-14 20:27:16 +00:00
ast_verb ( 0 , " Waiting for inactivity to perform %s... \n " , restart ? " restart " : " halt " ) ;
2012-01-15 20:16:08 +00:00
}
2015-02-11 17:39:13 +00:00
waited | = wait_for_channels_to_die ( niceness , - 1 ) ;
2012-01-15 20:16:08 +00:00
}
2002-05-14 14:43:52 +00:00
2012-01-15 20:16:08 +00:00
/* Re-acquire lock and check if someone changed the niceness, in which
2012-09-21 17:14:59 +00:00
* case someone else has taken over the shutdown .
*/
2012-01-15 20:16:08 +00:00
ast_mutex_lock ( & safe_system_lock ) ;
if ( shuttingdown ! = niceness ) {
2013-08-29 22:49:24 +00:00
if ( shuttingdown = = NOT_SHUTTING_DOWN & & ast_opt_console ) {
2012-02-14 20:27:16 +00:00
ast_verb ( 0 , " Asterisk %s cancelled. \n " , restart ? " restart " : " shutdown " ) ;
2002-05-14 14:43:52 +00:00
}
2012-01-15 20:16:08 +00:00
ast_mutex_unlock ( & safe_system_lock ) ;
return 0 ;
}
2015-02-11 17:39:13 +00:00
if ( niceness > = SHUTDOWN_REALLY_NICE ) {
shuttingdown = SHUTTING_DOWN ;
ast_mutex_unlock ( & safe_system_lock ) ;
/* No more Mr. Nice guy. We are committed to shutting down now. */
ast_begin_shutdown ( ) ;
ast_softhangup_all ( ) ;
waited | = wait_for_channels_to_die ( SHUTTING_DOWN , SHUTDOWN_TIMEOUT ) ;
ast_mutex_lock ( & safe_system_lock ) ;
}
shuttingdown = SHUTTING_DOWN_FINAL ;
2012-01-15 20:16:08 +00:00
ast_mutex_unlock ( & safe_system_lock ) ;
2015-02-11 17:39:13 +00:00
if ( niceness > = SHUTDOWN_NORMAL & & waited ) {
/*
* We were not idle . Give things in progress a chance to
* recognize the final shutdown phase .
*/
sleep ( 1 ) ;
}
2012-01-15 20:16:08 +00:00
return 1 ;
}
2007-06-05 15:54:36 +00:00
2012-12-03 23:00:08 +00:00
/*! Called when exiting is certain. */
2012-01-15 20:16:08 +00:00
static void really_quit ( int num , shutdown_nice_t niceness , int restart )
{
2012-12-03 20:46:11 +00:00
int active_channels ;
2013-08-29 21:37:29 +00:00
struct ast_json * json_object = NULL ;
Avoid unnecessary cleanups during immediate shutdown
This patch addresses issues during immediate shutdowns, where modules
are not unloaded, but Asterisk atexit handlers are run.
In the typical case, this usually isn't a big deal. But the
introduction of the Stasis message bus makes it much more likely for
asynchronous activity to be happening off in some thread during
shutdown.
During an immediate shutdown, Asterisk skips unloading modules. But
while it is processing the atexit handlers, there is a window of time
where some of the core message types have been cleaned up, but the
message bus is still running. Specifically, it's still running
module subscriptions that might be using the core message types. If a
message is received by that subscription in that window, it will
attempt to use a message type that has been cleaned up.
To solve this problem, this patch introduces ast_register_cleanup().
This function operates identically to ast_register_atexit(), except
that cleanup calls are not invoked on an immediate shutdown. All of
the core message type and topic cleanup was moved from atexit handlers
to cleanup handlers.
This ensures that core type and topic cleanup only happens if the
modules that used them are first unloaded.
This patch also changes the ast_assert() when accessing a cleaned up
or uninitialized message type to an error log message. Message type
functions are actually NULL safe across the board, so the assert was a
bit heavy handed. Especially for anyone with DO_CRASH enabled.
Review: https://reviewboard.asterisk.org/r/2562/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@390122 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2013-05-30 17:05:53 +00:00
int run_cleanups = niceness > = SHUTDOWN_NICE ;
2012-12-03 20:46:11 +00:00
2016-10-28 02:49:43 +00:00
if ( run_cleanups & & modules_shutdown ( ) ) {
ast_verb ( 0 , " Some modules could not be unloaded, switching to fast shutdown \n " ) ;
run_cleanups = 0 ;
2002-05-14 14:43:52 +00:00
}
2012-01-15 20:16:08 +00:00
2016-06-27 19:26:54 +00:00
if ( ! restart ) {
ast_sd_notify ( " STOPPING=1 " ) ;
}
2008-11-05 22:19:18 +00:00
if ( ast_opt_console | | ( ast_opt_remote & & ! ast_opt_exec ) ) {
2015-11-25 19:29:55 +00:00
ast_el_write_default_histfile ( ) ;
2011-07-18 12:54:29 +00:00
if ( consolethread = = AST_PTHREADT_NULL | | consolethread = = pthread_self ( ) ) {
/* Only end if we are the consolethread, otherwise there's a race with that thread. */
2010-07-23 16:43:34 +00:00
if ( el ! = NULL ) {
el_end ( el ) ;
}
if ( el_hist ! = NULL ) {
history_end ( el_hist ) ;
}
2018-11-15 11:33:11 +00:00
} else if ( ! restart ) {
2018-11-11 13:34:53 +00:00
sig_flags . need_el_end = 1 ;
pthread_kill ( consolethread , SIGURG ) ;
2010-07-23 16:43:34 +00:00
}
2001-05-09 03:11:22 +00:00
}
2012-12-03 20:46:11 +00:00
active_channels = ast_active_channels ( ) ;
2013-05-26 04:47:17 +00:00
/* Don't publish messages if we're a remote console - we won't have all of the Stasis
* topics or message types
*/
if ( ! ast_opt_remote ) {
json_object = ast_json_pack ( " {s: s, s: s} " ,
" Shutdown " , active_channels ? " Uncleanly " : " Cleanly " ,
" Restart " , restart ? " True " : " False " ) ;
2013-05-31 14:36:08 +00:00
ast_manager_publish_event ( " Shutdown " , EVENT_FLAG_SYSTEM , json_object ) ;
2013-08-29 21:37:29 +00:00
ast_json_unref ( json_object ) ;
json_object = NULL ;
2013-05-26 04:47:17 +00:00
}
2012-12-03 23:00:08 +00:00
ast_verb ( 0 , " Asterisk %s ending (%d). \n " ,
active_channels ? " uncleanly " : " cleanly " , num ) ;
2012-10-02 21:26:27 +00:00
ast_verb ( 0 , " Executing last minute cleanups \n " ) ;
Avoid unnecessary cleanups during immediate shutdown
This patch addresses issues during immediate shutdowns, where modules
are not unloaded, but Asterisk atexit handlers are run.
In the typical case, this usually isn't a big deal. But the
introduction of the Stasis message bus makes it much more likely for
asynchronous activity to be happening off in some thread during
shutdown.
During an immediate shutdown, Asterisk skips unloading modules. But
while it is processing the atexit handlers, there is a window of time
where some of the core message types have been cleaned up, but the
message bus is still running. Specifically, it's still running
module subscriptions that might be using the core message types. If a
message is received by that subscription in that window, it will
attempt to use a message type that has been cleaned up.
To solve this problem, this patch introduces ast_register_cleanup().
This function operates identically to ast_register_atexit(), except
that cleanup calls are not invoked on an immediate shutdown. All of
the core message type and topic cleanup was moved from atexit handlers
to cleanup handlers.
This ensures that core type and topic cleanup only happens if the
modules that used them are first unloaded.
This patch also changes the ast_assert() when accessing a cleaned up
or uninitialized message type to an error log message. Message type
functions are actually NULL safe across the board, so the assert was a
bit heavy handed. Especially for anyone with DO_CRASH enabled.
Review: https://reviewboard.asterisk.org/r/2562/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@390122 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2013-05-30 17:05:53 +00:00
ast_run_atexits ( run_cleanups ) ;
2012-12-03 23:00:08 +00:00
2012-10-02 21:26:27 +00:00
ast_debug ( 1 , " Asterisk ending (%d). \n " , num ) ;
2002-09-12 03:22:07 +00:00
if ( ast_socket > - 1 ) {
2006-07-03 05:14:06 +00:00
pthread_cancel ( lthread ) ;
2001-05-09 03:11:22 +00:00
close ( ast_socket ) ;
2002-09-12 03:22:07 +00:00
ast_socket = - 1 ;
2017-06-19 00:24:04 +00:00
if ( ! ast_socket_is_sd ) {
unlink ( ast_config_AST_SOCKET ) ;
}
2013-10-24 17:00:27 +00:00
pthread_kill ( lthread , SIGURG ) ;
pthread_join ( lthread , NULL ) ;
2002-09-12 03:22:07 +00:00
}
2001-05-09 03:11:22 +00:00
if ( ast_consock > - 1 )
close ( ast_consock ) ;
2005-12-04 20:40:46 +00:00
if ( ! ast_opt_remote )
unlink ( ast_config_AST_PID ) ;
2017-11-10 01:47:27 +00:00
ast_alertpipe_close ( sig_alert_pipe ) ;
2008-03-18 15:43:34 +00:00
printf ( " %s " , term_quit ( ) ) ;
2002-05-14 14:43:52 +00:00
if ( restart ) {
2012-01-15 20:16:08 +00:00
int i ;
2012-02-14 20:27:16 +00:00
ast_verb ( 0 , " Preparing for Asterisk restart... \n " ) ;
2002-05-14 14:43:52 +00:00
/* Mark all FD's for closing on exec */
2012-01-15 20:16:08 +00:00
for ( i = 3 ; i < 32768 ; i + + ) {
fcntl ( i , F_SETFD , FD_CLOEXEC ) ;
2002-05-14 14:43:52 +00:00
}
2012-02-14 20:27:16 +00:00
ast_verb ( 0 , " Asterisk is now restarting... \n " ) ;
2004-02-23 03:43:21 +00:00
restartnow = 1 ;
2004-06-17 01:13:10 +00:00
/* close logger */
close_logger ( ) ;
2012-12-03 20:46:11 +00:00
clean_time_zones ( ) ;
2004-06-17 01:13:10 +00:00
2012-03-22 19:51:16 +00:00
/* If there is a consolethread running send it a SIGHUP
2004-02-23 03:43:21 +00:00
so it can execvp , otherwise we can do it ourselves */
2005-09-25 16:52:04 +00:00
if ( ( consolethread ! = AST_PTHREADT_NULL ) & & ( consolethread ! = pthread_self ( ) ) ) {
2004-02-23 03:43:21 +00:00
pthread_kill ( consolethread , SIGHUP ) ;
2004-03-02 23:50:03 +00:00
/* Give the signal handler some time to complete */
sleep ( 2 ) ;
} else
2004-02-23 03:43:21 +00:00
execvp ( _argv [ 0 ] , _argv ) ;
2012-03-22 19:51:16 +00:00
2004-06-17 01:13:10 +00:00
} else {
/* close logger */
close_logger ( ) ;
2012-12-03 20:46:11 +00:00
clean_time_zones ( ) ;
2003-08-07 03:48:00 +00:00
}
2012-01-15 20:16:08 +00:00
2003-08-07 03:48:00 +00:00
exit ( 0 ) ;
2002-05-14 14:43:52 +00:00
}
static void __quit_handler ( int num )
{
2007-02-23 23:25:22 +00:00
sig_flags . need_quit = 1 ;
2017-11-10 01:47:27 +00:00
if ( ast_alertpipe_write ( sig_alert_pipe ) ) {
fprintf ( stderr , " quit_handler: write() failed: %s \n " , strerror ( errno ) ) ;
2008-11-02 18:52:13 +00:00
}
2007-02-23 23:25:22 +00:00
/* There is no need to restore the signal handler here, since the app
* is going to exit */
1999-11-15 04:57:28 +00:00
}
2008-12-11 23:38:56 +00:00
static void __remote_quit_handler ( int num )
{
sig_flags . need_quit = 1 ;
}
2014-05-28 22:54:12 +00:00
static void set_header ( char * outbuf , int maxout , char level )
2002-05-14 14:43:52 +00:00
{
2013-08-29 22:49:24 +00:00
const char * cmp ;
2014-05-28 22:54:12 +00:00
char date [ 40 ] ;
2013-08-29 22:49:24 +00:00
switch ( level ) {
2014-05-28 22:54:12 +00:00
case 0 : cmp = NULL ;
break ;
2013-08-29 22:49:24 +00:00
case 1 : cmp = VERBOSE_PREFIX_1 ;
break ;
case 2 : cmp = VERBOSE_PREFIX_2 ;
break ;
case 3 : cmp = VERBOSE_PREFIX_3 ;
break ;
default : cmp = VERBOSE_PREFIX_4 ;
break ;
}
2008-05-05 23:00:31 +00:00
2014-05-28 22:54:12 +00:00
if ( ast_opt_timestamp ) {
struct ast_tm tm ;
struct timeval now = ast_tvnow ( ) ;
ast_localtime ( & now , & tm , NULL ) ;
ast_strftime ( date , sizeof ( date ) , ast_logger_get_dateformat ( ) , & tm ) ;
2002-05-14 14:43:52 +00:00
}
2013-08-29 22:49:24 +00:00
2014-05-28 22:54:12 +00:00
snprintf ( outbuf , maxout , " %s%s%s%s%s%s " ,
ast_opt_timestamp ? " [ " : " " ,
ast_opt_timestamp ? date : " " ,
ast_opt_timestamp ? " ] " : " " ,
cmp ? ast_term_color ( COLOR_GRAY , 0 ) : " " ,
cmp ? cmp : " " ,
cmp ? ast_term_reset ( ) : " " ) ;
2002-05-14 14:43:52 +00:00
}
2013-08-29 22:49:24 +00:00
struct console_state_data {
char verbose_line_level ;
} ;
static int console_state_init ( void * ptr )
{
struct console_state_data * state = ptr ;
state - > verbose_line_level = 0 ;
return 0 ;
}
AST_THREADSTORAGE_CUSTOM ( console_state , console_state_init , ast_free_ptr ) ;
logger: Support JSON logging with Verbose messages
When 2d7a4a3357 was merged, it missed the fact that Verbose log messages
are formatted and handled by 'verbosers'. Verbosers are registered
functions that handle verbose messages only; they exist as a separate
class of callbacks. This was done to handle the 'magic' that must be
inserted into Verbose messages sent to remote consoles, so that the
consoles can format the messages correctly, i.e., the leading
tabs/characters.
In reality, verbosers are a weird appendage: they're a separate class of
formatters/message handlers outside of what handles all other log
messages in Asterisk. After some code inspection, it became clear that
simply passing a Verbose message along with its 'sublevel' importance
through the normal logging mechanisms removes the need for verbosers
altogether.
This patch removes the verbosers, and makes the default log formatter
aware that, if the log channel is a console log, it should simply insert
the 'verbose magic' into the log messages itself. This allows the
console handlers to interpret and format the verbose message
themselves.
This simplifies the code quite a lot, and should improve the performance
of printing verbose messages by a reasonable factor:
(1) It removes a number of memory allocations that were done on each
verobse message
(2) It removes the need to strip the verbose magic out of the verbose
log messages before passing them to non-console log channels
(3) It now performs fewer iterations over lists when handling verbose
messages
Since verbose messages are now handled like other log messages (for the
most part), the JSON formatting of the messages works as well.
ASTERISK-25425
Change-Id: I21bf23f0a1e489b5102f8a035fe8871552ce4f96
2016-05-14 12:24:07 +00:00
static int console_print ( const char * s )
1999-12-19 22:38:55 +00:00
{
2013-08-29 22:49:24 +00:00
struct console_state_data * state =
ast_threadstorage_get ( & console_state , sizeof ( * state ) ) ;
char prefix [ 80 ] ;
2013-09-17 18:44:11 +00:00
const char * c ;
2013-08-30 15:39:09 +00:00
int num , res = 0 ;
2013-09-17 18:44:11 +00:00
unsigned int newline ;
2013-08-29 22:49:24 +00:00
do {
if ( VERBOSE_HASMAGIC ( s ) ) {
2014-05-28 22:54:12 +00:00
2013-09-17 18:44:11 +00:00
/* always use the given line's level, otherwise
we ' ll use the last line ' s level */
2013-08-29 22:49:24 +00:00
state - > verbose_line_level = VERBOSE_MAGIC2LEVEL ( s ) ;
2014-05-28 22:54:12 +00:00
2013-08-29 22:49:24 +00:00
/* move past magic */
s + + ;
2014-05-28 22:54:12 +00:00
set_header ( prefix , sizeof ( prefix ) , state - > verbose_line_level ) ;
2013-09-17 18:44:11 +00:00
} else {
2013-08-29 22:49:24 +00:00
* prefix = ' \0 ' ;
}
2013-09-17 18:44:11 +00:00
c = s ;
2013-08-29 22:49:24 +00:00
2013-09-17 18:44:11 +00:00
/* for a given line separate on verbose magic, newline, and eol */
if ( ( s = strchr ( c , ' \n ' ) ) ) {
2013-08-29 22:49:24 +00:00
+ + s ;
2013-09-17 18:44:11 +00:00
newline = 1 ;
} else {
s = strchr ( c , ' \0 ' ) ;
newline = 0 ;
2013-08-29 22:49:24 +00:00
}
/* check if we should write this line after calculating begin/end
so we process the case of a higher level line embedded within
two lower level lines */
if ( state - > verbose_line_level > option_verbose ) {
continue ;
}
2014-05-28 22:54:12 +00:00
if ( ! ast_strlen_zero ( prefix ) ) {
2013-08-29 22:49:24 +00:00
fputs ( prefix , stdout ) ;
}
2013-08-30 15:39:09 +00:00
num = s - c ;
if ( fwrite ( c , sizeof ( char ) , num , stdout ) < num ) {
break ;
}
2013-08-29 22:49:24 +00:00
if ( ! res ) {
/* if at least some info has been written
we ' ll want to return true */
res = 1 ;
}
} while ( * s ) ;
2013-09-17 18:44:11 +00:00
if ( newline ) {
/* if ending on a newline then reset last level to zero
since what follows may be not be logging output */
state - > verbose_line_level = 0 ;
}
2013-08-29 22:49:24 +00:00
if ( res ) {
fflush ( stdout ) ;
2008-05-21 18:12:19 +00:00
}
Merge team/russell/ast_verbose_threadstorage
- instead of defining a free() wrapper in a bunch of files, define it as
ast_free() in utils.h and remove the copies from all the files.
- centralize and abstract the code used for doing thread storage. The code
lives in threadstorage.h, with one function being implemented in utils.c.
This new API includes generic thread storage as well as special functions
for handling thread local dynamic length string buffers.
- update ast_inet_ntoa() to use the new threadstorage API
- update ast_state2str() to use the new threadstorage API
- update ast_cli() to use the new threadstorage API
- Modify manager_event() to use thread storage. Instead of using a buffer of
4096 characters as the workspace for building the manager event, use a thread
local dynamic string. Now there is no length limitation on the length of the
body of a manager event.
- Significantly simplify the handling of ast_verbose() ...
- Instead of using a static char buffer and a lock to make sure only one
thread can be using ast_verbose() at a time, use a thread local dynamic
string as the workspace for preparing the verbose message. Instead of
locking around the entire function, the only locking done now is when the
message has been built and is being deliviered to the list of registered
verbose message handlers.
- This function was doing a strdup() on every message passed to it and
keeping a queue of the last 200 messages in memory. This has been
completely removed. The only place this was used was that if there were
any messages in the verbose queue when a verbose handler was registered,
all of the messages in the queue would be fed to it. So, I just made sure
that the console verbose handler and the network verbose handler (for
remote asterisk consoles) were registered before any verbose messages.
pbx_gtkconsole and pbx_kdeconsole will now lose a few verbose messages at
startup, but I didn't feel the performance hit of this message queue was
worth saving the initial verbose output for these very rarely used modules.
- I have removed the last three arguments to the verbose handlers, leaving
only the string itself because they aren't needed anymore. For example,
ast_verbose had some logic for telling the verbose handler to add
a newline if the buffer was completely full. Now that the buffer can grow
as needed, this doesn't matter anymore.
- remove unused function, ast_verbose_dmesg() which was to dispatch the
message queue
- Convert the list of verbose handlers to use the linked list macros.
- add missing newline characters to a few ast_verbose() calls
- convert the list of log channels to use the linked list macros in logger.c
- fix close_logger() to close all of the files it opened for logging
- update ast_log() to use a thread local dynamic string for its workspace
for preparing log messages instead of a buffer of size BUFSIZ (8kB on my
system) allocated on the stack. The dynamic string in this case is limited
to only growing to a maximum size of BUFSIZ.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@39272 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2006-08-08 06:32:04 +00:00
2013-08-29 22:49:24 +00:00
return res ;
}
2015-11-25 19:29:55 +00:00
static int ast_all_zeros ( const char * s )
2004-08-01 18:12:52 +00:00
{
2006-03-31 00:33:28 +00:00
while ( * s ) {
2004-08-01 18:12:52 +00:00
if ( * s > 32 )
return 0 ;
2012-03-22 19:51:16 +00:00
s + + ;
2004-08-01 18:12:52 +00:00
}
return 1 ;
}
2014-01-14 18:14:02 +00:00
/* This is the main console CLI command handler. Run by the main() thread. */
2015-11-25 19:29:55 +00:00
static void consolehandler ( const char * s )
1999-12-19 22:38:55 +00:00
{
2008-03-18 15:43:34 +00:00
printf ( " %s " , term_end ( ) ) ;
2002-05-14 14:43:52 +00:00
fflush ( stdout ) ;
2006-07-12 14:04:16 +00:00
1999-12-19 22:38:55 +00:00
/* Called when readline data is available */
2006-07-12 14:04:16 +00:00
if ( ! ast_all_zeros ( s ) )
2003-02-06 06:15:25 +00:00
ast_el_add_history ( s ) ;
2006-07-12 14:04:16 +00:00
/* The real handler for bang */
if ( s [ 0 ] = = ' ! ' ) {
if ( s [ 1 ] )
ast_safe_system ( s + 1 ) ;
else
ast_safe_system ( getenv ( " SHELL " ) ? getenv ( " SHELL " ) : " /bin/sh " ) ;
2012-03-22 19:51:16 +00:00
} else
1999-12-19 22:38:55 +00:00
ast_cli_command ( STDOUT_FILENO , s ) ;
}
2015-11-25 19:29:55 +00:00
static int remoteconsolehandler ( const char * s )
2001-05-09 03:11:22 +00:00
{
2003-02-06 06:15:25 +00:00
int ret = 0 ;
2006-07-12 14:04:16 +00:00
2001-05-09 03:11:22 +00:00
/* Called when readline data is available */
2006-07-12 14:04:16 +00:00
if ( ! ast_all_zeros ( s ) )
2003-02-06 06:15:25 +00:00
ast_el_add_history ( s ) ;
2013-08-15 16:37:06 +00:00
while ( isspace ( * s ) ) {
s + + ;
}
2006-07-12 14:04:16 +00:00
/* The real handler for bang */
if ( s [ 0 ] = = ' ! ' ) {
if ( s [ 1 ] )
ast_safe_system ( s + 1 ) ;
else
ast_safe_system ( getenv ( " SHELL " ) ? getenv ( " SHELL " ) : " /bin/sh " ) ;
ret = 1 ;
2014-01-14 18:14:02 +00:00
} else if ( ( strncasecmp ( s , " quit " , 4 ) = = 0 | | strncasecmp ( s , " exit " , 4 ) = = 0 ) & &
( s [ 4 ] = = ' \0 ' | | isspace ( s [ 4 ] ) ) ) {
quit_handler ( 0 , SHUTDOWN_FAST , 0 ) ;
ret = 1 ;
2006-07-12 14:04:16 +00:00
}
2003-02-06 06:15:25 +00:00
return ret ;
2001-05-09 03:11:22 +00:00
}
2007-10-11 19:03:06 +00:00
static char * handle_version ( struct ast_cli_entry * e , int cmd , struct ast_cli_args * a )
2006-04-29 00:15:28 +00:00
{
2007-10-11 19:03:06 +00:00
switch ( cmd ) {
case CLI_INIT :
e - > command = " core show version " ;
2012-03-22 19:51:16 +00:00
e - > usage =
2007-10-11 19:03:06 +00:00
" Usage: core show version \n "
" Shows Asterisk version information. \n " ;
return NULL ;
case CLI_GENERATE :
return NULL ;
}
if ( a - > argc ! = 3 )
return CLI_SHOWUSAGE ;
ast_cli ( a - > fd , " Asterisk %s built by %s @ %s on a %s running %s on %s \n " ,
Now that the version.h file was getting properly regenerated every time the svn
revision changed, every module that used the version was getting rebuilt after
every svn update. This severly annoyed me pretty quickly, so I have improved
the situation.
Now, instead of generating version.h, main/version.c is generated. version.c
includes the version information, as well as a couple of API calls for modules
to retrieve the version. So now, only version.c will get rebuilt, and the main
asterisk binary relinked, which is must faster than rebuilding http.c, manager.c,
asterisk.c, relinking the asterisk binary, chan_sip.c, func_version.c, res_agi ...
The only minor change in behavior here is that the version information reported by
chan_sip, for example, is the version of the Asterisk core, and not necessarily the
Asterisk version that the chan_sip module came from.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@96717 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2008-01-05 22:09:06 +00:00
ast_get_version ( ) , ast_build_user , ast_build_hostname ,
2006-04-29 00:15:28 +00:00
ast_build_machine , ast_build_os , ast_build_date ) ;
2007-10-11 19:03:06 +00:00
return CLI_SUCCESS ;
2006-04-29 00:15:28 +00:00
}
2007-10-11 19:03:06 +00:00
static char * handle_stop_now ( struct ast_cli_entry * e , int cmd , struct ast_cli_args * a )
2002-05-14 14:43:52 +00:00
{
2007-10-11 19:03:06 +00:00
switch ( cmd ) {
case CLI_INIT :
2008-02-08 21:26:32 +00:00
e - > command = " core stop now " ;
2012-03-22 19:51:16 +00:00
e - > usage =
2008-02-08 21:26:32 +00:00
" Usage: core stop now \n "
2007-10-11 19:03:06 +00:00
" Shuts down a running Asterisk immediately, hanging up all active calls . \n " ;
2016-03-10 22:58:49 +00:00
ast_cli_allow_at_shutdown ( e ) ;
2007-10-11 19:03:06 +00:00
return NULL ;
case CLI_GENERATE :
return NULL ;
}
2008-02-08 21:26:32 +00:00
if ( a - > argc ! = e - > args )
2007-10-11 19:03:06 +00:00
return CLI_SHOWUSAGE ;
2012-01-15 20:16:08 +00:00
quit_handler ( 0 , SHUTDOWN_NORMAL , 0 /* not restart */ ) ;
2007-10-11 19:03:06 +00:00
return CLI_SUCCESS ;
2002-05-14 14:43:52 +00:00
}
2007-10-11 19:03:06 +00:00
static char * handle_stop_gracefully ( struct ast_cli_entry * e , int cmd , struct ast_cli_args * a )
2002-05-14 14:43:52 +00:00
{
2007-10-11 19:03:06 +00:00
switch ( cmd ) {
case CLI_INIT :
2008-02-08 21:26:32 +00:00
e - > command = " core stop gracefully " ;
2012-03-22 19:51:16 +00:00
e - > usage =
2008-02-08 21:26:32 +00:00
" Usage: core stop gracefully \n "
2007-10-11 19:03:06 +00:00
" Causes Asterisk to not accept new calls, and exit when all \n "
" active calls have terminated normally. \n " ;
2016-03-10 22:58:49 +00:00
ast_cli_allow_at_shutdown ( e ) ;
2007-10-11 19:03:06 +00:00
return NULL ;
case CLI_GENERATE :
return NULL ;
}
2008-02-08 21:26:32 +00:00
if ( a - > argc ! = e - > args )
2007-10-11 19:03:06 +00:00
return CLI_SHOWUSAGE ;
2012-01-15 20:16:08 +00:00
quit_handler ( 0 , SHUTDOWN_NICE , 0 /* no restart */ ) ;
2007-10-11 19:03:06 +00:00
return CLI_SUCCESS ;
2002-05-14 14:43:52 +00:00
}
2007-10-11 19:03:06 +00:00
static char * handle_stop_when_convenient ( struct ast_cli_entry * e , int cmd , struct ast_cli_args * a )
2003-04-23 16:24:09 +00:00
{
2007-10-11 19:03:06 +00:00
switch ( cmd ) {
case CLI_INIT :
2008-02-08 21:26:32 +00:00
e - > command = " core stop when convenient " ;
2012-03-22 19:51:16 +00:00
e - > usage =
2008-02-08 21:26:32 +00:00
" Usage: core stop when convenient \n "
2007-10-11 19:03:06 +00:00
" Causes Asterisk to perform a shutdown when all active calls have ended. \n " ;
2016-03-10 22:58:49 +00:00
ast_cli_allow_at_shutdown ( e ) ;
2007-10-11 19:03:06 +00:00
return NULL ;
case CLI_GENERATE :
return NULL ;
}
2008-02-08 21:26:32 +00:00
if ( a - > argc ! = e - > args )
2007-10-11 19:03:06 +00:00
return CLI_SHOWUSAGE ;
ast_cli ( a - > fd , " Waiting for inactivity to perform halt \n " ) ;
2012-01-15 20:16:08 +00:00
quit_handler ( 0 , SHUTDOWN_REALLY_NICE , 0 /* don't restart */ ) ;
2007-10-11 19:03:06 +00:00
return CLI_SUCCESS ;
2003-04-23 16:24:09 +00:00
}
2007-10-11 19:03:06 +00:00
static char * handle_restart_now ( struct ast_cli_entry * e , int cmd , struct ast_cli_args * a )
2002-05-14 14:43:52 +00:00
{
2007-10-11 19:03:06 +00:00
switch ( cmd ) {
case CLI_INIT :
2008-02-08 21:26:32 +00:00
e - > command = " core restart now " ;
2012-03-22 19:51:16 +00:00
e - > usage =
2008-02-08 21:26:32 +00:00
" Usage: core restart now \n "
2007-10-11 19:03:06 +00:00
" Causes Asterisk to hangup all calls and exec() itself performing a cold \n "
" restart. \n " ;
2016-03-10 22:58:49 +00:00
ast_cli_allow_at_shutdown ( e ) ;
2007-10-11 19:03:06 +00:00
return NULL ;
case CLI_GENERATE :
return NULL ;
}
2008-02-08 21:26:32 +00:00
if ( a - > argc ! = e - > args )
2007-10-11 19:03:06 +00:00
return CLI_SHOWUSAGE ;
2012-01-15 20:16:08 +00:00
quit_handler ( 0 , SHUTDOWN_NORMAL , 1 /* restart */ ) ;
2007-10-11 19:03:06 +00:00
return CLI_SUCCESS ;
2002-05-14 14:43:52 +00:00
}
2007-10-11 19:03:06 +00:00
static char * handle_restart_gracefully ( struct ast_cli_entry * e , int cmd , struct ast_cli_args * a )
2002-05-14 14:43:52 +00:00
{
2007-10-11 19:03:06 +00:00
switch ( cmd ) {
case CLI_INIT :
2008-02-08 21:26:32 +00:00
e - > command = " core restart gracefully " ;
2012-03-22 19:51:16 +00:00
e - > usage =
2008-02-08 21:26:32 +00:00
" Usage: core restart gracefully \n "
2007-10-11 19:03:06 +00:00
" Causes Asterisk to stop accepting new calls and exec() itself performing a cold \n "
" restart when all active calls have ended. \n " ;
2016-03-10 22:58:49 +00:00
ast_cli_allow_at_shutdown ( e ) ;
2007-10-11 19:03:06 +00:00
return NULL ;
case CLI_GENERATE :
return NULL ;
}
2008-02-08 21:26:32 +00:00
if ( a - > argc ! = e - > args )
2007-10-11 19:03:06 +00:00
return CLI_SHOWUSAGE ;
2012-01-15 20:16:08 +00:00
quit_handler ( 0 , SHUTDOWN_NICE , 1 /* restart */ ) ;
2007-10-11 19:03:06 +00:00
return CLI_SUCCESS ;
2002-05-14 14:43:52 +00:00
}
2007-10-11 19:03:06 +00:00
static char * handle_restart_when_convenient ( struct ast_cli_entry * e , int cmd , struct ast_cli_args * a )
2002-05-14 14:43:52 +00:00
{
2007-10-11 19:03:06 +00:00
switch ( cmd ) {
case CLI_INIT :
2008-02-08 21:26:32 +00:00
e - > command = " core restart when convenient " ;
2012-03-22 19:51:16 +00:00
e - > usage =
2008-02-08 21:26:32 +00:00
" Usage: core restart when convenient \n "
2007-10-11 19:03:06 +00:00
" Causes Asterisk to perform a cold restart when all active calls have ended. \n " ;
2016-03-10 22:58:49 +00:00
ast_cli_allow_at_shutdown ( e ) ;
2007-10-11 19:03:06 +00:00
return NULL ;
case CLI_GENERATE :
return NULL ;
}
2008-02-08 21:26:32 +00:00
if ( a - > argc ! = e - > args )
2007-10-11 19:03:06 +00:00
return CLI_SHOWUSAGE ;
ast_cli ( a - > fd , " Waiting for inactivity to perform restart \n " ) ;
2012-01-15 20:16:08 +00:00
quit_handler ( 0 , SHUTDOWN_REALLY_NICE , 1 /* restart */ ) ;
2007-10-11 19:03:06 +00:00
return CLI_SUCCESS ;
2002-05-14 14:43:52 +00:00
}
2007-10-11 19:03:06 +00:00
static char * handle_abort_shutdown ( struct ast_cli_entry * e , int cmd , struct ast_cli_args * a )
2002-05-14 14:43:52 +00:00
{
2007-10-11 19:03:06 +00:00
switch ( cmd ) {
case CLI_INIT :
2008-02-08 21:26:32 +00:00
e - > command = " core abort shutdown " ;
2012-03-22 19:51:16 +00:00
e - > usage =
2008-02-08 21:26:32 +00:00
" Usage: core abort shutdown \n "
2007-10-11 19:03:06 +00:00
" Causes Asterisk to abort an executing shutdown or restart, and resume normal \n "
" call operations. \n " ;
2016-03-10 22:58:49 +00:00
ast_cli_allow_at_shutdown ( e ) ;
2007-10-11 19:03:06 +00:00
return NULL ;
case CLI_GENERATE :
return NULL ;
}
2008-02-08 21:26:32 +00:00
if ( a - > argc ! = e - > args )
2007-10-11 19:03:06 +00:00
return CLI_SHOWUSAGE ;
2012-01-15 20:16:08 +00:00
2015-02-11 17:39:13 +00:00
ast_cancel_shutdown ( ) ;
2012-01-15 20:16:08 +00:00
2007-10-11 19:03:06 +00:00
return CLI_SUCCESS ;
1999-12-19 22:38:55 +00:00
}
2007-10-11 19:03:06 +00:00
static char * handle_bang ( struct ast_cli_entry * e , int cmd , struct ast_cli_args * a )
2003-10-22 03:46:36 +00:00
{
2007-10-11 19:03:06 +00:00
switch ( cmd ) {
case CLI_INIT :
e - > command = " ! " ;
2012-03-22 19:51:16 +00:00
e - > usage =
2007-10-11 19:03:06 +00:00
" Usage: !<command> \n "
" Executes a given shell command \n " ;
return NULL ;
case CLI_GENERATE :
return NULL ;
}
return CLI_SUCCESS ;
2003-10-22 03:46:36 +00:00
}
2007-02-13 05:57:52 +00:00
static const char warranty_lines [ ] = {
" \n "
" NO WARRANTY \n "
" \n "
" BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY \n "
" FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW. EXCEPT WHEN \n "
" OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES \n "
" PROVIDE THE PROGRAM \" AS IS \" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED \n "
" OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF \n "
" MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. THE ENTIRE RISK AS \n "
" TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU. SHOULD THE \n "
" PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, \n "
" REPAIR OR CORRECTION. \n "
" \n "
" IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING \n "
" WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR \n "
" REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, \n "
" INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING \n "
" OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED \n "
" TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY \n "
" YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER \n "
" PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE \n "
" POSSIBILITY OF SUCH DAMAGES. \n "
2005-12-23 03:04:38 +00:00
} ;
2007-10-11 19:03:06 +00:00
static char * show_warranty ( struct ast_cli_entry * e , int cmd , struct ast_cli_args * a )
2005-12-23 03:04:38 +00:00
{
2007-10-11 19:03:06 +00:00
switch ( cmd ) {
case CLI_INIT :
e - > command = " core show warranty " ;
2012-03-22 19:51:16 +00:00
e - > usage =
2007-10-11 19:03:06 +00:00
" Usage: core show warranty \n "
" Shows the warranty (if any) for this copy of Asterisk. \n " ;
return NULL ;
case CLI_GENERATE :
return NULL ;
}
2005-12-23 03:04:38 +00:00
2008-11-02 18:52:13 +00:00
ast_cli ( a - > fd , " %s " , warranty_lines ) ;
2007-10-11 19:03:06 +00:00
return CLI_SUCCESS ;
2005-12-23 03:04:38 +00:00
}
2007-02-13 05:57:52 +00:00
static const char license_lines [ ] = {
" \n "
" This program is free software; you can redistribute it and/or modify \n "
" it under the terms of the GNU General Public License version 2 as \n "
" published by the Free Software Foundation. \n "
" \n "
" This program also contains components licensed under other licenses. \n "
" They include: \n "
" \n "
" This program is distributed in the hope that it will be useful, \n "
" but WITHOUT ANY WARRANTY; without even the implied warranty of \n "
" MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the \n "
" GNU General Public License for more details. \n "
" \n "
" You should have received a copy of the GNU General Public License \n "
" along with this program; if not, write to the Free Software \n "
" Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA \n "
2005-12-23 03:04:38 +00:00
} ;
2007-10-11 19:03:06 +00:00
static char * show_license ( struct ast_cli_entry * e , int cmd , struct ast_cli_args * a )
2005-12-23 03:04:38 +00:00
{
2007-10-11 19:03:06 +00:00
switch ( cmd ) {
case CLI_INIT :
e - > command = " core show license " ;
2012-03-22 19:51:16 +00:00
e - > usage =
2007-10-11 19:03:06 +00:00
" Usage: core show license \n "
" Shows the license(s) for this copy of Asterisk. \n " ;
return NULL ;
case CLI_GENERATE :
return NULL ;
}
2005-12-23 03:04:38 +00:00
2008-11-02 18:52:13 +00:00
ast_cli ( a - > fd , " %s " , license_lines ) ;
2007-10-11 19:03:06 +00:00
return CLI_SUCCESS ;
2005-12-23 03:04:38 +00:00
}
2003-10-22 03:46:36 +00:00
1999-12-19 22:38:55 +00:00
# define ASTERISK_PROMPT "*CLI> "
2012-12-03 20:46:11 +00:00
/*!
* \ brief Shutdown Asterisk CLI commands .
*
* \ note These CLI commands cannot be unregistered at shutdown
* because one of them is likely the reason for the shutdown .
* The CLI generates a warning if a command is in - use when it is
* unregistered .
*/
static struct ast_cli_entry cli_asterisk_shutdown [ ] = {
2008-11-12 06:46:04 +00:00
AST_CLI_DEFINE ( handle_stop_now , " Shut down Asterisk immediately " ) ,
AST_CLI_DEFINE ( handle_stop_gracefully , " Gracefully shut down Asterisk " ) ,
AST_CLI_DEFINE ( handle_stop_when_convenient , " Shut down Asterisk at empty call volume " ) ,
2012-03-22 19:51:16 +00:00
AST_CLI_DEFINE ( handle_restart_now , " Restart Asterisk immediately " ) ,
2008-11-12 06:46:04 +00:00
AST_CLI_DEFINE ( handle_restart_gracefully , " Restart Asterisk gracefully " ) ,
AST_CLI_DEFINE ( handle_restart_when_convenient , " Restart Asterisk at empty call volume " ) ,
2012-12-03 20:46:11 +00:00
} ;
static struct ast_cli_entry cli_asterisk [ ] = {
AST_CLI_DEFINE ( handle_abort_shutdown , " Cancel a running shutdown " ) ,
2007-10-22 20:05:18 +00:00
AST_CLI_DEFINE ( show_warranty , " Show the warranty (if any) for this copy of Asterisk " ) ,
AST_CLI_DEFINE ( show_license , " Show the license(s) for this copy of Asterisk " ) ,
AST_CLI_DEFINE ( handle_version , " Display version info " ) ,
AST_CLI_DEFINE ( handle_bang , " Execute a shell command " ) ,
2006-09-18 19:54:18 +00:00
# if !defined(LOW_MEMORY)
2007-10-22 20:05:18 +00:00
AST_CLI_DEFINE ( handle_show_threads , " Show running threads " ) ,
2008-12-16 20:08:34 +00:00
# if defined(HAVE_SYSINFO) || defined(HAVE_SYSCTL)
2007-10-22 20:05:18 +00:00
AST_CLI_DEFINE ( handle_show_sysinfo , " Show System Information " ) ,
2007-04-11 20:59:08 +00:00
# endif
2007-10-22 20:05:18 +00:00
AST_CLI_DEFINE ( handle_show_profile , " Display profiling info " ) ,
AST_CLI_DEFINE ( handle_show_settings , " Show some core settings " ) ,
AST_CLI_DEFINE ( handle_clear_profile , " Clear profiling info " ) ,
2005-06-07 16:07:06 +00:00
# endif /* ! LOW_MEMORY */
2005-06-03 03:04:08 +00:00
} ;
2001-05-09 03:11:22 +00:00
2014-01-14 18:14:02 +00:00
static void send_rasterisk_connect_commands ( void )
{
char buf [ 80 ] ;
/*
* Tell the server asterisk instance about the verbose level
* initially desired .
*/
if ( option_verbose ) {
snprintf ( buf , sizeof ( buf ) , " core set verbose atleast %d silent " , option_verbose ) ;
fdsend ( ast_consock , buf ) ;
}
if ( option_debug ) {
snprintf ( buf , sizeof ( buf ) , " core set debug atleast %d " , option_debug ) ;
fdsend ( ast_consock , buf ) ;
}
2017-12-13 15:50:59 +00:00
/* Leave verbose filtering to the server. */
option_verbose = INT_MAX ;
2014-01-14 18:14:02 +00:00
if ( ! ast_opt_mute ) {
fdsend ( ast_consock , " logger mute silent " ) ;
} else {
printf ( " log and verbose output currently muted ('logger mute' to unmute) \n " ) ;
}
}
2016-11-14 18:16:03 +00:00
# ifdef HAVE_LIBEDIT_IS_UNICODE
2018-03-17 21:41:13 +00:00
# define CHAR_T_LIBEDIT wchar_t
# define CHAR_TO_LIBEDIT(c) btowc(c)
2016-11-14 18:16:03 +00:00
# else
2018-03-17 21:41:13 +00:00
# define CHAR_T_LIBEDIT char
# define CHAR_TO_LIBEDIT(c) c
2016-11-14 18:16:03 +00:00
# endif
2018-03-17 21:41:13 +00:00
static int ast_el_read_char ( EditLine * editline , CHAR_T_LIBEDIT * cp )
2003-02-06 06:15:25 +00:00
{
2006-03-31 00:33:28 +00:00
int num_read = 0 ;
int lastpos = 0 ;
2004-04-25 20:42:45 +00:00
struct pollfd fds [ 2 ] ;
2003-02-06 06:15:25 +00:00
int res ;
int max ;
2007-12-16 09:37:41 +00:00
# define EL_BUF_SIZE 512
char buf [ EL_BUF_SIZE ] ;
2003-02-06 06:15:25 +00:00
for ( ; ; ) {
2004-04-25 20:42:45 +00:00
max = 1 ;
fds [ 0 ] . fd = ast_consock ;
fds [ 0 ] . events = POLLIN ;
2005-12-04 20:40:46 +00:00
if ( ! ast_opt_exec ) {
2004-04-25 20:42:45 +00:00
fds [ 1 ] . fd = STDIN_FILENO ;
fds [ 1 ] . events = POLLIN ;
max + + ;
2003-06-23 16:40:12 +00:00
}
Merged revisions 182810 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/1.4
........
r182810 | russell | 2009-03-17 21:09:13 -0500 (Tue, 17 Mar 2009) | 44 lines
Fix cases where the internal poll() was not being used when it needed to be.
We have seen a number of problems caused by poll() not working properly on
Mac OSX. If you search around, you'll find a number of references to using
select() instead of poll() to work around these issues. In Asterisk, we've
had poll.c which implements poll() using select() internally. However, we
were still getting reports of problems.
vadim investigated a bit and realized that at least on his system, even
though we were compiling in poll.o, the system poll() was still being used.
So, the primary purpose of this patch is to ensure that we're using the
internal poll() when we want it to be used.
The changes are:
1) Remove logic for when internal poll should be used from the Makefile.
Instead, put it in the configure script. The logic in the configure
script is the same as it was in the Makefile. Ideally, we would have
a functionality test for the problem, but that's not actually possible,
since we would have to be able to run an application on the _target_
system to test poll() behavior.
2) Always include poll.o in the build, but it will be empty if AST_POLL_COMPAT
is not defined.
3) Change uses of poll() throughout the source tree to ast_poll(). I feel
that it is good practice to give the API call a new name when we are
changing its behavior and not using the system version directly in all cases.
So, normally, ast_poll() is just redefined to poll(). On systems where
AST_POLL_COMPAT is defined, ast_poll() is redefined to ast_internal_poll().
4) Change poll() in main/poll.c to be ast_internal_poll().
It's worth noting that any code that still uses poll() directly will work fine
(if they worked fine before). So, for example, out of tree modules that are
using poll() will not stop working or anything. However, for modules to work
properly on Mac OSX, ast_poll() needs to be used.
(closes issue #13404)
Reported by: agalbraith
Tested by: russell, vadim
http://reviewboard.digium.com/r/198/
........
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@182847 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-03-18 02:28:55 +00:00
res = ast_poll ( fds , max , - 1 ) ;
2003-02-06 06:15:25 +00:00
if ( res < 0 ) {
2018-11-11 13:34:53 +00:00
if ( sig_flags . need_quit | | sig_flags . need_quit_handler | | sig_flags . need_el_end ) {
2008-12-12 22:04:26 +00:00
break ;
2018-03-17 21:41:13 +00:00
}
if ( errno = = EINTR ) {
2003-02-06 06:15:25 +00:00
continue ;
2018-03-17 21:41:13 +00:00
}
2012-11-18 20:27:45 +00:00
fprintf ( stderr , " poll failed: %s \n " , strerror ( errno ) ) ;
2003-02-06 06:15:25 +00:00
break ;
}
2005-12-04 20:40:46 +00:00
if ( ! ast_opt_exec & & fds [ 1 ] . revents ) {
2016-11-14 18:16:03 +00:00
char c = ' \0 ' ;
2018-03-17 21:41:13 +00:00
2016-11-14 18:16:03 +00:00
num_read = read ( STDIN_FILENO , & c , 1 ) ;
2003-02-06 06:15:25 +00:00
if ( num_read < 1 ) {
break ;
2011-11-29 18:43:16 +00:00
}
2018-03-17 21:41:13 +00:00
* cp = CHAR_TO_LIBEDIT ( c ) ;
return num_read ;
2003-02-06 06:15:25 +00:00
}
2018-03-17 21:41:13 +00:00
2004-04-25 20:42:45 +00:00
if ( fds [ 0 ] . revents ) {
2003-02-06 06:15:25 +00:00
res = read ( ast_consock , buf , sizeof ( buf ) - 1 ) ;
/* if the remote side disappears exit */
if ( res < 1 ) {
fprintf ( stderr , " \n Disconnected from Asterisk server \n " ) ;
2005-12-04 20:40:46 +00:00
if ( ! ast_opt_reconnect ) {
2012-01-15 20:16:08 +00:00
quit_handler ( 0 , SHUTDOWN_FAST , 0 ) ;
2004-06-25 14:39:38 +00:00
} else {
int tries ;
2004-06-25 21:14:03 +00:00
int reconnects_per_second = 20 ;
2018-03-17 21:41:13 +00:00
2004-06-25 21:14:03 +00:00
fprintf ( stderr , " Attempting to reconnect for 30 seconds \n " ) ;
2008-02-11 18:27:47 +00:00
for ( tries = 0 ; tries < 30 * reconnects_per_second ; tries + + ) {
2004-06-25 14:39:38 +00:00
if ( ast_tryconnect ( ) ) {
2004-06-25 21:14:03 +00:00
fprintf ( stderr , " Reconnect succeeded after %.3f seconds \n " , 1.0 / reconnects_per_second * tries ) ;
2008-03-18 15:43:34 +00:00
printf ( " %s " , term_quit ( ) ) ;
2004-06-25 21:14:03 +00:00
WELCOME_MESSAGE ;
2014-01-14 18:14:02 +00:00
send_rasterisk_connect_commands ( ) ;
2004-06-25 14:39:38 +00:00
break ;
2018-03-17 21:41:13 +00:00
}
usleep ( 1000000 / reconnects_per_second ) ;
2004-06-25 14:39:38 +00:00
}
2004-12-28 07:51:25 +00:00
if ( tries > = 30 * reconnects_per_second ) {
2004-06-25 14:39:38 +00:00
fprintf ( stderr , " Failed to reconnect for 30 seconds. Quitting. \n " ) ;
2012-01-15 20:16:08 +00:00
quit_handler ( 0 , SHUTDOWN_FAST , 0 ) ;
2004-06-25 14:39:38 +00:00
}
}
2012-04-17 21:08:05 +00:00
continue ;
2003-02-06 06:15:25 +00:00
}
buf [ res ] = ' \0 ' ;
2008-05-05 23:00:31 +00:00
/* Write over the CLI prompt */
2008-11-02 18:52:13 +00:00
if ( ! ast_opt_exec & & ! lastpos ) {
2010-06-01 15:18:59 +00:00
if ( write ( STDOUT_FILENO , " \r [0K" , 5 ) < 0 ) {
2008-11-02 18:52:13 +00:00
}
}
2012-02-14 20:27:16 +00:00
logger: Support JSON logging with Verbose messages
When 2d7a4a3357 was merged, it missed the fact that Verbose log messages
are formatted and handled by 'verbosers'. Verbosers are registered
functions that handle verbose messages only; they exist as a separate
class of callbacks. This was done to handle the 'magic' that must be
inserted into Verbose messages sent to remote consoles, so that the
consoles can format the messages correctly, i.e., the leading
tabs/characters.
In reality, verbosers are a weird appendage: they're a separate class of
formatters/message handlers outside of what handles all other log
messages in Asterisk. After some code inspection, it became clear that
simply passing a Verbose message along with its 'sublevel' importance
through the normal logging mechanisms removes the need for verbosers
altogether.
This patch removes the verbosers, and makes the default log formatter
aware that, if the log channel is a console log, it should simply insert
the 'verbose magic' into the log messages itself. This allows the
console handlers to interpret and format the verbose message
themselves.
This simplifies the code quite a lot, and should improve the performance
of printing verbose messages by a reasonable factor:
(1) It removes a number of memory allocations that were done on each
verobse message
(2) It removes the need to strip the verbose magic out of the verbose
log messages before passing them to non-console log channels
(3) It now performs fewer iterations over lists when handling verbose
messages
Since verbose messages are now handled like other log messages (for the
most part), the JSON formatting of the messages works as well.
ASTERISK-25425
Change-Id: I21bf23f0a1e489b5102f8a035fe8871552ce4f96
2016-05-14 12:24:07 +00:00
console_print ( buf ) ;
2012-02-14 20:27:16 +00:00
2016-01-18 09:49:48 +00:00
if ( ( res < EL_BUF_SIZE - 1 ) & & ( ( buf [ res - 1 ] = = ' \n ' ) | | ( res > = 2 & & buf [ res - 2 ] = = ' \n ' ) ) ) {
2018-03-17 21:41:13 +00:00
* cp = CHAR_TO_LIBEDIT ( CC_REFRESH ) ;
return 1 ;
2016-01-18 09:49:48 +00:00
}
2018-03-17 21:41:13 +00:00
lastpos = 1 ;
2003-02-06 06:15:25 +00:00
}
}
2018-03-17 21:41:13 +00:00
* cp = CHAR_TO_LIBEDIT ( ' \0 ' ) ;
2016-11-14 18:16:03 +00:00
2018-03-17 21:41:13 +00:00
return 0 ;
2003-02-06 06:15:25 +00:00
}
2008-07-30 15:30:18 +00:00
static struct ast_str * prompt = NULL ;
2008-08-10 19:35:50 +00:00
static char * cli_prompt ( EditLine * editline )
1999-12-19 22:38:55 +00:00
{
2008-07-30 15:30:18 +00:00
char tmp [ 100 ] ;
2004-03-26 04:59:41 +00:00
char * pfmt ;
2006-03-31 00:33:28 +00:00
int color_used = 0 ;
2008-07-30 15:30:18 +00:00
static int cli_prompt_changes = 0 ;
struct passwd * pw ;
struct group * gr ;
if ( prompt = = NULL ) {
prompt = ast_str_create ( 100 ) ;
} else if ( ! cli_prompt_changes ) {
2008-12-13 08:36:35 +00:00
return ast_str_buffer ( prompt ) ;
2008-07-30 15:30:18 +00:00
} else {
ast_str_reset ( prompt ) ;
}
2004-03-26 04:59:41 +00:00
if ( ( pfmt = getenv ( " ASTERISK_PROMPT " ) ) ) {
2008-07-30 15:30:18 +00:00
char * t = pfmt ;
struct timeval ts = ast_tvnow ( ) ;
while ( * t ! = ' \0 ' ) {
2004-03-26 04:59:41 +00:00
if ( * t = = ' % ' ) {
2008-07-30 15:30:18 +00:00
char hostname [ MAXHOSTNAMELEN ] = " " ;
int i , which ;
2007-07-18 19:47:20 +00:00
struct ast_tm tm = { 0 , } ;
2004-05-02 19:13:16 +00:00
int fgcolor = COLOR_WHITE , bgcolor = COLOR_BLACK ;
2004-03-26 04:59:41 +00:00
t + + ;
switch ( * t ) {
2006-03-31 00:33:28 +00:00
case ' C ' : /* color */
t + + ;
2009-08-10 19:20:57 +00:00
if ( sscanf ( t , " %30d;%30d%n " , & fgcolor , & bgcolor , & i ) = = 2 ) {
2013-02-14 18:47:56 +00:00
ast_term_color_code ( & prompt , fgcolor , bgcolor ) ;
2006-03-31 00:33:28 +00:00
t + = i - 1 ;
2009-08-10 19:20:57 +00:00
} else if ( sscanf ( t , " %30d%n " , & fgcolor , & i ) = = 1 ) {
2013-02-14 18:47:56 +00:00
ast_term_color_code ( & prompt , fgcolor , 0 ) ;
2006-03-31 00:33:28 +00:00
t + = i - 1 ;
}
2004-05-02 19:13:16 +00:00
2006-03-31 00:33:28 +00:00
/* If the color has been reset correctly, then there's no need to reset it later */
2006-10-29 20:47:01 +00:00
color_used = ( ( fgcolor = = COLOR_WHITE ) & & ( bgcolor = = COLOR_BLACK ) ) ? 0 : 1 ;
2006-03-31 00:33:28 +00:00
break ;
case ' d ' : /* date */
2008-07-30 15:30:18 +00:00
if ( ast_localtime ( & ts , & tm , NULL ) ) {
ast_strftime ( tmp , sizeof ( tmp ) , " %Y-%m-%d " , & tm ) ;
ast_str_append ( & prompt , 0 , " %s " , tmp ) ;
cli_prompt_changes + + ;
}
break ;
case ' g ' : /* group */
if ( ( gr = getgrgid ( getgid ( ) ) ) ) {
ast_str_append ( & prompt , 0 , " %s " , gr - > gr_name ) ;
}
2006-03-31 00:33:28 +00:00
break ;
case ' h ' : /* hostname */
2008-07-30 15:30:18 +00:00
if ( ! gethostname ( hostname , sizeof ( hostname ) - 1 ) ) {
ast_str_append ( & prompt , 0 , " %s " , hostname ) ;
} else {
ast_str_append ( & prompt , 0 , " %s " , " localhost " ) ;
}
2006-03-31 00:33:28 +00:00
break ;
case ' H ' : /* short hostname */
if ( ! gethostname ( hostname , sizeof ( hostname ) - 1 ) ) {
2008-07-30 15:30:18 +00:00
char * dotptr ;
if ( ( dotptr = strchr ( hostname , ' . ' ) ) ) {
* dotptr = ' \0 ' ;
2004-05-02 19:13:16 +00:00
}
2008-07-30 15:30:18 +00:00
ast_str_append ( & prompt , 0 , " %s " , hostname ) ;
} else {
ast_str_append ( & prompt , 0 , " %s " , " localhost " ) ;
}
2006-03-31 00:33:28 +00:00
break ;
2008-07-30 15:30:18 +00:00
# ifdef HAVE_GETLOADAVG
2006-03-31 00:33:28 +00:00
case ' l ' : /* load avg */
t + + ;
2009-08-10 19:20:57 +00:00
if ( sscanf ( t , " %30d " , & which ) = = 1 & & which > 0 & & which < = 3 ) {
2008-07-30 15:30:18 +00:00
double list [ 3 ] ;
getloadavg ( list , 3 ) ;
ast_str_append ( & prompt , 0 , " %.2f " , list [ which - 1 ] ) ;
cli_prompt_changes + + ;
2006-03-31 00:33:28 +00:00
}
break ;
2004-03-26 04:59:41 +00:00
# endif
2006-05-11 13:54:00 +00:00
case ' s ' : /* Asterisk system name (from asterisk.conf) */
2008-07-30 15:30:18 +00:00
ast_str_append ( & prompt , 0 , " %s " , ast_config_AST_SYSTEM_NAME ) ;
2006-05-11 13:54:00 +00:00
break ;
2006-03-31 00:33:28 +00:00
case ' t ' : /* time */
2008-07-30 15:30:18 +00:00
if ( ast_localtime ( & ts , & tm , NULL ) ) {
ast_strftime ( tmp , sizeof ( tmp ) , " %H:%M:%S " , & tm ) ;
ast_str_append ( & prompt , 0 , " %s " , tmp ) ;
cli_prompt_changes + + ;
}
break ;
case ' u ' : /* username */
if ( ( pw = getpwuid ( getuid ( ) ) ) ) {
ast_str_append ( & prompt , 0 , " %s " , pw - > pw_name ) ;
}
2006-03-31 00:33:28 +00:00
break ;
case ' # ' : /* process console or remote? */
2008-07-30 15:30:18 +00:00
ast_str_append ( & prompt , 0 , " %c " , ast_opt_remote ? ' > ' : ' # ' ) ;
2006-03-31 00:33:28 +00:00
break ;
case ' % ' : /* literal % */
2008-07-30 15:30:18 +00:00
ast_str_append ( & prompt , 0 , " %c " , ' % ' ) ;
2006-03-31 00:33:28 +00:00
break ;
case ' \0 ' : /* % is last character - prevent bug */
t - - ;
break ;
2004-03-26 04:59:41 +00:00
}
} else {
2008-12-13 08:36:35 +00:00
ast_str_append ( & prompt , 0 , " %c " , * t ) ;
2004-03-26 04:59:41 +00:00
}
2009-01-03 20:29:54 +00:00
t + + ;
2004-03-26 04:59:41 +00:00
}
2004-05-02 19:13:16 +00:00
if ( color_used ) {
/* Force colors back to normal at end */
2013-02-14 18:47:56 +00:00
ast_term_color_code ( & prompt , 0 , 0 ) ;
2004-05-02 19:13:16 +00:00
}
2008-07-30 15:30:18 +00:00
} else {
2014-05-28 22:54:12 +00:00
ast_str_set ( & prompt , 0 , " %s%s " ,
remotehostname ? remotehostname : " " ,
ASTERISK_PROMPT ) ;
2008-07-30 15:30:18 +00:00
}
2003-02-06 06:15:25 +00:00
2012-03-22 19:51:16 +00:00
return ast_str_buffer ( prompt ) ;
2003-02-06 06:15:25 +00:00
}
2017-11-20 22:48:22 +00:00
static struct ast_vector_string * ast_el_strtoarr ( char * buf )
2003-02-06 06:15:25 +00:00
{
2013-09-10 18:05:47 +00:00
char * retstr ;
2017-11-07 20:13:57 +00:00
struct ast_vector_string * vec = ast_calloc ( 1 , sizeof ( * vec ) ) ;
if ( ! vec ) {
return NULL ;
}
2003-02-06 06:15:25 +00:00
2013-09-10 18:05:47 +00:00
while ( ( retstr = strsep ( & buf , " " ) ) ) {
if ( ! strcmp ( retstr , AST_CLI_COMPLETE_EOF ) ) {
2004-04-06 07:42:01 +00:00
break ;
2013-09-10 18:05:47 +00:00
}
2003-02-06 06:15:25 +00:00
2013-09-10 18:05:47 +00:00
retstr = ast_strdup ( retstr ) ;
2017-11-20 22:58:37 +00:00
if ( ! retstr | | AST_VECTOR_APPEND ( vec , retstr ) ) {
2017-11-07 20:13:57 +00:00
ast_free ( retstr ) ;
goto vector_cleanup ;
2013-09-10 18:05:47 +00:00
}
2003-02-06 06:15:25 +00:00
}
2017-11-07 20:13:57 +00:00
if ( ! AST_VECTOR_SIZE ( vec ) ) {
goto vector_cleanup ;
2013-09-10 18:05:47 +00:00
}
2003-02-06 06:15:25 +00:00
2017-11-20 22:48:22 +00:00
return vec ;
2017-11-07 20:13:57 +00:00
vector_cleanup :
AST_VECTOR_CALLBACK_VOID ( vec , ast_free ) ;
AST_VECTOR_PTR_FREE ( vec ) ;
return NULL ;
2003-02-06 06:15:25 +00:00
}
2017-11-20 22:48:22 +00:00
static void ast_cli_display_match_list ( struct ast_vector_string * matches , int max )
2003-02-06 06:15:25 +00:00
{
2017-11-07 20:47:51 +00:00
int idx = 1 ;
2003-02-06 06:15:25 +00:00
/* find out how many entries can be put on one line, with two spaces between strings */
2017-11-07 20:47:51 +00:00
int limit = ast_get_termcols ( STDOUT_FILENO ) / ( max + 2 ) ;
2003-02-06 06:15:25 +00:00
2017-11-07 20:47:51 +00:00
if ( limit = = 0 ) {
limit = 1 ;
}
2003-02-06 06:15:25 +00:00
2017-11-07 20:47:51 +00:00
for ( ; ; ) {
int numoutputline ;
2003-02-06 06:15:25 +00:00
2017-11-20 22:48:22 +00:00
for ( numoutputline = 0 ; numoutputline < limit & & idx < AST_VECTOR_SIZE ( matches ) ; idx + + ) {
2004-10-01 18:35:35 +00:00
numoutputline + + ;
2017-11-20 22:48:22 +00:00
fprintf ( stdout , " %-*s " , max , AST_VECTOR_GET ( matches , idx ) ) ;
2003-02-06 06:15:25 +00:00
}
2017-11-07 20:47:51 +00:00
if ( ! numoutputline ) {
break ;
}
fprintf ( stdout , " \n " ) ;
}
1999-12-19 22:38:55 +00:00
}
2003-02-06 06:15:25 +00:00
2008-08-10 19:35:50 +00:00
static char * cli_complete ( EditLine * editline , int ch )
2001-05-09 03:11:22 +00:00
{
2006-03-31 00:33:28 +00:00
int len = 0 ;
2003-02-06 06:15:25 +00:00
char * ptr ;
2017-11-20 22:48:22 +00:00
struct ast_vector_string * matches ;
2003-02-06 06:15:25 +00:00
int retval = CC_ERROR ;
2017-11-07 21:34:40 +00:00
char savechr ;
2001-05-09 03:11:22 +00:00
int res ;
2003-02-06 06:15:25 +00:00
2008-08-10 19:35:50 +00:00
LineInfo * lf = ( LineInfo * ) el_line ( editline ) ;
2003-02-06 06:15:25 +00:00
2009-03-25 14:38:19 +00:00
savechr = * ( char * ) lf - > cursor ;
2003-09-04 03:55:41 +00:00
* ( char * ) lf - > cursor = ' \0 ' ;
2003-02-21 06:00:08 +00:00
ptr = ( char * ) lf - > cursor ;
2003-02-06 06:15:25 +00:00
if ( ptr ) {
while ( ptr > lf - > buffer ) {
if ( isspace ( * ptr ) ) {
ptr + + ;
break ;
}
ptr - - ;
}
}
len = lf - > cursor - ptr ;
2005-12-04 20:40:46 +00:00
if ( ast_opt_remote ) {
2017-11-07 21:34:40 +00:00
# define CMD_MATCHESARRAY "_COMMAND MATCHESARRAY \"%s\" \"%s\""
char * mbuf ;
char * new_mbuf ;
2017-12-19 02:12:47 +00:00
int mlen = 0 ;
int maxmbuf = ast_asprintf ( & mbuf , CMD_MATCHESARRAY , lf - > buffer , ptr ) ;
2017-11-07 21:34:40 +00:00
2017-12-19 02:12:47 +00:00
if ( maxmbuf = = - 1 ) {
2017-11-07 21:34:40 +00:00
* ( ( char * ) lf - > cursor ) = savechr ;
return ( char * ) ( CC_ERROR ) ;
}
fdsend ( ast_consock , mbuf ) ;
res = 0 ;
mlen = 0 ;
mbuf [ 0 ] = ' \0 ' ;
while ( ! strstr ( mbuf , AST_CLI_COMPLETE_EOF ) & & res ! = - 1 ) {
if ( mlen + 1024 > maxmbuf ) {
2017-12-19 02:12:47 +00:00
/* Expand buffer to the next 1024 byte increment plus a NULL terminator. */
2017-11-07 21:34:40 +00:00
maxmbuf = mlen + 1024 ;
2017-12-19 02:12:47 +00:00
new_mbuf = ast_realloc ( mbuf , maxmbuf + 1 ) ;
2017-11-07 21:34:40 +00:00
if ( ! new_mbuf ) {
ast_free ( mbuf ) ;
* ( ( char * ) lf - > cursor ) = savechr ;
return ( char * ) ( CC_ERROR ) ;
2004-04-06 07:42:01 +00:00
}
2017-11-07 21:34:40 +00:00
mbuf = new_mbuf ;
}
/* Only read 1024 bytes at a time */
res = read ( ast_consock , mbuf + mlen , 1024 ) ;
if ( res > 0 ) {
mlen + = res ;
2017-12-19 02:12:47 +00:00
mbuf [ mlen ] = ' \0 ' ;
2004-04-06 07:42:01 +00:00
}
2017-11-07 21:34:40 +00:00
}
mbuf [ mlen ] = ' \0 ' ;
2003-02-06 06:15:25 +00:00
2017-11-07 21:34:40 +00:00
matches = ast_el_strtoarr ( mbuf ) ;
ast_free ( mbuf ) ;
2004-10-01 18:35:35 +00:00
} else {
2017-11-20 22:48:22 +00:00
matches = ast_cli_completion_vector ( ( char * ) lf - > buffer , ptr ) ;
2003-02-06 06:15:25 +00:00
}
if ( matches ) {
int i ;
2017-11-07 21:34:40 +00:00
int maxlen , match_len ;
2017-11-20 22:48:22 +00:00
const char * best_match = AST_VECTOR_GET ( matches , 0 ) ;
2017-11-07 21:34:40 +00:00
2017-11-20 22:48:22 +00:00
if ( ! ast_strlen_zero ( best_match ) ) {
2008-08-10 19:35:50 +00:00
el_deletestr ( editline , ( int ) len ) ;
2017-11-20 22:48:22 +00:00
el_insertstr ( editline , best_match ) ;
2003-02-06 06:15:25 +00:00
retval = CC_REFRESH ;
}
2017-11-20 22:48:22 +00:00
if ( AST_VECTOR_SIZE ( matches ) = = 2 ) {
2003-02-06 06:15:25 +00:00
/* Found an exact match */
2008-08-10 19:35:50 +00:00
el_insertstr ( editline , " " ) ;
2003-02-06 06:15:25 +00:00
retval = CC_REFRESH ;
} else {
/* Must be more than one match */
2017-11-20 22:48:22 +00:00
for ( i = 1 , maxlen = 0 ; i < AST_VECTOR_SIZE ( matches ) ; i + + ) {
match_len = strlen ( AST_VECTOR_GET ( matches , i ) ) ;
2017-11-07 21:34:40 +00:00
if ( match_len > maxlen ) {
2003-02-06 06:15:25 +00:00
maxlen = match_len ;
2017-11-07 21:34:40 +00:00
}
2003-02-06 06:15:25 +00:00
}
2017-11-07 21:34:40 +00:00
fprintf ( stdout , " \n " ) ;
ast_cli_display_match_list ( matches , maxlen ) ;
retval = CC_REDISPLAY ;
2003-02-06 06:15:25 +00:00
}
2017-11-20 22:48:22 +00:00
AST_VECTOR_CALLBACK_VOID ( matches , ast_free ) ;
AST_VECTOR_PTR_FREE ( matches ) ;
2003-02-06 06:15:25 +00:00
}
2012-07-25 12:21:54 +00:00
* ( ( char * ) lf - > cursor ) = savechr ;
2009-03-25 14:38:19 +00:00
2004-06-13 21:25:10 +00:00
return ( char * ) ( long ) retval ;
2003-02-06 06:15:25 +00:00
}
static int ast_el_initialize ( void )
{
HistEvent ev ;
2011-05-05 21:20:00 +00:00
char * editor , * editrc = getenv ( " EDITRC " ) ;
if ( ! ( editor = getenv ( " AST_EDITMODE " ) ) ) {
if ( ! ( editor = getenv ( " AST_EDITOR " ) ) ) {
editor = " emacs " ;
}
}
2003-02-06 06:15:25 +00:00
if ( el ! = NULL )
el_end ( el ) ;
if ( el_hist ! = NULL )
history_end ( el_hist ) ;
el = el_init ( " asterisk " , stdin , stdout , stderr ) ;
el_set ( el , EL_PROMPT , cli_prompt ) ;
2012-03-22 19:51:16 +00:00
el_set ( el , EL_EDITMODE , 1 ) ;
2011-05-05 21:20:00 +00:00
el_set ( el , EL_EDITOR , editor ) ;
2003-02-06 06:15:25 +00:00
el_hist = history_init ( ) ;
if ( ! el | | ! el_hist )
return - 1 ;
/* setup history with 100 entries */
history ( el_hist , & ev , H_SETSIZE , 100 ) ;
el_set ( el , EL_HIST , history , el_hist ) ;
el_set ( el , EL_ADDFN , " ed-complete " , " Complete argument " , cli_complete ) ;
/* Bind <tab> to command completion */
el_set ( el , EL_BIND , " ^I " , " ed-complete " , NULL ) ;
/* Bind ? to command completion */
el_set ( el , EL_BIND , " ? " , " ed-complete " , NULL ) ;
2004-03-29 04:12:13 +00:00
/* Bind ^D to redisplay */
el_set ( el , EL_BIND , " ^D " , " ed-redisplay " , NULL ) ;
2011-05-05 21:20:00 +00:00
/* Bind Delete to delete char left */
el_set ( el , EL_BIND , " \\ e[3~ " , " ed-delete-next-char " , NULL ) ;
/* Bind Home and End to move to line start and end */
el_set ( el , EL_BIND , " \\ e[1~ " , " ed-move-to-beg " , NULL ) ;
el_set ( el , EL_BIND , " \\ e[4~ " , " ed-move-to-end " , NULL ) ;
/* Bind C-left and C-right to move by word (not all terminals) */
el_set ( el , EL_BIND , " \\ eOC " , " vi-next-word " , NULL ) ;
el_set ( el , EL_BIND , " \\ eOD " , " vi-prev-word " , NULL ) ;
if ( editrc ) {
el_source ( el , editrc ) ;
}
2003-02-06 06:15:25 +00:00
return 0 ;
}
2008-10-04 16:20:31 +00:00
# define MAX_HISTORY_COMMAND_LENGTH 256
2015-11-25 19:29:55 +00:00
static int ast_el_add_history ( const char * buf )
2003-02-06 06:15:25 +00:00
{
HistEvent ev ;
2013-08-22 12:28:33 +00:00
char * stripped_buf ;
2003-02-06 06:15:25 +00:00
2013-08-22 12:28:33 +00:00
if ( el_hist = = NULL | | el = = NULL ) {
2003-02-06 06:15:25 +00:00
ast_el_initialize ( ) ;
2013-08-22 12:28:33 +00:00
}
if ( strlen ( buf ) > ( MAX_HISTORY_COMMAND_LENGTH - 1 ) ) {
return 0 ;
}
stripped_buf = ast_strip ( ast_strdupa ( buf ) ) ;
/* HISTCONTROL=ignoredups */
if ( ! history ( el_hist , & ev , H_FIRST ) & & strcmp ( ev . str , stripped_buf ) = = 0 ) {
2004-01-23 19:12:44 +00:00
return 0 ;
2013-08-22 12:28:33 +00:00
}
return history ( el_hist , & ev , H_ENTER , stripped_buf ) ;
2003-02-06 06:15:25 +00:00
}
2015-11-25 19:29:55 +00:00
static int ast_el_write_history ( const char * filename )
2003-02-06 06:15:25 +00:00
{
HistEvent ev ;
if ( el_hist = = NULL | | el = = NULL )
ast_el_initialize ( ) ;
return ( history ( el_hist , & ev , H_SAVE , filename ) ) ;
}
2015-11-25 19:29:55 +00:00
static int ast_el_read_history ( const char * filename )
2003-02-06 06:15:25 +00:00
{
2012-07-25 12:21:54 +00:00
HistEvent ev ;
2003-02-06 06:15:25 +00:00
2012-07-25 12:21:54 +00:00
if ( el_hist = = NULL | | el = = NULL ) {
2003-02-06 06:15:25 +00:00
ast_el_initialize ( ) ;
}
2012-07-25 12:21:54 +00:00
return history ( el_hist , & ev , H_LOAD , filename ) ;
2001-05-09 03:11:22 +00:00
}
2015-11-25 19:29:55 +00:00
static void ast_el_read_default_histfile ( void )
{
char histfile [ 80 ] = " " ;
const char * home = getenv ( " HOME " ) ;
if ( ! ast_strlen_zero ( home ) ) {
snprintf ( histfile , sizeof ( histfile ) , " %s/.asterisk_history " , home ) ;
ast_el_read_history ( histfile ) ;
}
}
static void ast_el_write_default_histfile ( void )
{
char histfile [ 80 ] = " " ;
const char * home = getenv ( " HOME " ) ;
if ( ! ast_strlen_zero ( home ) ) {
snprintf ( histfile , sizeof ( histfile ) , " %s/.asterisk_history " , home ) ;
ast_el_write_history ( histfile ) ;
}
}
2008-11-02 18:52:13 +00:00
static void ast_remotecontrol ( char * data )
2001-05-09 03:11:22 +00:00
{
2014-12-09 20:47:05 +00:00
char buf [ 256 ] = " " ;
2001-05-09 03:11:22 +00:00
int res ;
char * hostname ;
char * cpid ;
char * version ;
int pid ;
2006-03-31 00:33:28 +00:00
char * stringp = NULL ;
2003-02-06 06:15:25 +00:00
char * ebuf ;
int num = 0 ;
2015-11-25 19:29:55 +00:00
ast_term_init ( ) ;
printf ( " %s " , term_end ( ) ) ;
fflush ( stdout ) ;
2008-12-11 23:38:56 +00:00
memset ( & sig_flags , 0 , sizeof ( sig_flags ) ) ;
signal ( SIGINT , __remote_quit_handler ) ;
signal ( SIGTERM , __remote_quit_handler ) ;
signal ( SIGHUP , __remote_quit_handler ) ;
2014-12-09 20:47:05 +00:00
if ( read ( ast_consock , buf , sizeof ( buf ) - 1 ) < 0 ) {
2008-11-02 18:52:13 +00:00
ast_log ( LOG_ERROR , " read() failed: %s \n " , strerror ( errno ) ) ;
return ;
}
2008-07-08 20:17:08 +00:00
if ( data ) {
char prefix [ ] = " cli quit after " ;
2012-07-31 20:21:43 +00:00
char * tmp = ast_alloca ( strlen ( data ) + strlen ( prefix ) + 1 ) ;
2008-07-08 20:17:08 +00:00
sprintf ( tmp , " %s%s " , prefix , data ) ;
2008-11-02 18:52:13 +00:00
if ( write ( ast_consock , tmp , strlen ( tmp ) + 1 ) < 0 ) {
ast_log ( LOG_ERROR , " write() failed: %s \n " , strerror ( errno ) ) ;
2018-11-11 13:34:53 +00:00
if ( sig_flags . need_quit | | sig_flags . need_quit_handler | | sig_flags . need_el_end ) {
2008-12-11 23:38:56 +00:00
return ;
}
2008-11-02 18:52:13 +00:00
}
2008-07-08 20:17:08 +00:00
}
2006-03-31 00:33:28 +00:00
stringp = buf ;
2003-02-06 06:15:25 +00:00
hostname = strsep ( & stringp , " / " ) ;
cpid = strsep ( & stringp , " / " ) ;
2003-09-05 04:36:58 +00:00
version = strsep ( & stringp , " \n " ) ;
2001-05-09 03:11:22 +00:00
if ( ! version )
version = " <Version Unknown> " ;
2006-03-31 00:33:28 +00:00
stringp = hostname ;
2003-02-06 06:15:25 +00:00
strsep ( & stringp , " . " ) ;
2001-05-09 03:11:22 +00:00
if ( cpid )
pid = atoi ( cpid ) ;
else
pid = - 1 ;
2007-10-13 05:53:19 +00:00
if ( ! data ) {
2014-01-14 18:14:02 +00:00
send_rasterisk_connect_commands ( ) ;
2006-05-26 19:48:17 +00:00
}
2003-02-06 06:15:25 +00:00
2005-12-04 20:40:46 +00:00
if ( ast_opt_exec & & data ) { /* hack to print output then exit if asterisk -rx is used */
2012-02-14 20:27:16 +00:00
int linefull = 1 , prev_linefull = 1 , prev_line_verbose = 0 ;
2006-06-13 03:56:09 +00:00
struct pollfd fds ;
fds . fd = ast_consock ;
fds . events = POLLIN ;
fds . revents = 0 ;
2012-02-14 20:27:16 +00:00
2010-03-18 18:18:43 +00:00
while ( ast_poll ( & fds , 1 , 60000 ) > 0 ) {
2008-08-10 19:35:50 +00:00
char buffer [ 512 ] = " " , * curline = buffer , * nextline ;
2008-05-05 23:00:31 +00:00
int not_written = 1 ;
2018-11-11 13:34:53 +00:00
if ( sig_flags . need_quit | | sig_flags . need_quit_handler | | sig_flags . need_el_end ) {
2008-12-11 23:38:56 +00:00
break ;
}
2008-08-10 19:35:50 +00:00
if ( read ( ast_consock , buffer , sizeof ( buffer ) - 1 ) < = 0 ) {
2008-05-05 23:00:31 +00:00
break ;
}
do {
2012-02-14 20:27:16 +00:00
prev_linefull = linefull ;
2008-05-05 23:00:31 +00:00
if ( ( nextline = strchr ( curline , ' \n ' ) ) ) {
2012-02-14 20:27:16 +00:00
linefull = 1 ;
2008-05-05 23:00:31 +00:00
nextline + + ;
} else {
2012-02-14 20:27:16 +00:00
linefull = 0 ;
2008-05-05 23:00:31 +00:00
nextline = strchr ( curline , ' \0 ' ) ;
}
/* Skip verbose lines */
2012-02-14 20:27:16 +00:00
/* Prev line full? | Line is verbose | Last line verbose? | Print
* TRUE | TRUE * | TRUE | FALSE
* TRUE | TRUE * | FALSE | FALSE
* TRUE | FALSE * | TRUE | TRUE
* TRUE | FALSE * | FALSE | TRUE
* FALSE | TRUE | TRUE * | FALSE
* FALSE | TRUE | FALSE * | TRUE
* FALSE | FALSE | TRUE * | FALSE
* FALSE | FALSE | FALSE * | TRUE
*/
if ( ( ! prev_linefull & & ! prev_line_verbose ) | | ( prev_linefull & & * curline > 0 ) ) {
prev_line_verbose = 0 ;
2008-05-05 23:00:31 +00:00
not_written = 0 ;
2008-11-02 18:52:13 +00:00
if ( write ( STDOUT_FILENO , curline , nextline - curline ) < 0 ) {
ast_log ( LOG_WARNING , " write() failed: %s \n " , strerror ( errno ) ) ;
}
2012-02-14 20:27:16 +00:00
} else {
prev_line_verbose = 1 ;
2008-05-05 23:00:31 +00:00
}
curline = nextline ;
} while ( ! ast_strlen_zero ( curline ) ) ;
2010-03-18 18:23:07 +00:00
/* No non-verbose output in 60 seconds. */
2008-05-05 23:00:31 +00:00
if ( not_written ) {
break ;
}
}
2003-06-23 16:40:12 +00:00
return ;
}
2008-11-05 22:19:18 +00:00
ast_verbose ( " Connected to Asterisk %s currently running on %s (pid = %d) \n " , version , hostname , pid ) ;
remotehostname = hostname ;
if ( el_hist = = NULL | | el = = NULL )
ast_el_initialize ( ) ;
2015-11-25 19:29:55 +00:00
ast_el_read_default_histfile ( ) ;
2008-11-05 22:19:18 +00:00
el_set ( el , EL_GETCFN , ast_el_read_char ) ;
2006-03-31 00:33:28 +00:00
for ( ; ; ) {
2003-02-06 06:15:25 +00:00
ebuf = ( char * ) el_gets ( el , & num ) ;
2018-11-11 13:34:53 +00:00
if ( sig_flags . need_quit | | sig_flags . need_quit_handler | | sig_flags . need_el_end ) {
2008-12-11 23:38:56 +00:00
break ;
}
2007-06-27 23:30:31 +00:00
if ( ! ebuf & & write ( 1 , " " , 1 ) < 0 )
break ;
2005-10-26 18:54:24 +00:00
if ( ! ast_strlen_zero ( ebuf ) ) {
2003-02-06 06:15:25 +00:00
if ( ebuf [ strlen ( ebuf ) - 1 ] = = ' \n ' )
ebuf [ strlen ( ebuf ) - 1 ] = ' \0 ' ;
if ( ! remoteconsolehandler ( ebuf ) ) {
res = write ( ast_consock , ebuf , strlen ( ebuf ) + 1 ) ;
2001-05-09 03:11:22 +00:00
if ( res < 1 ) {
ast_log ( LOG_WARNING , " Unable to write: %s \n " , strerror ( errno ) ) ;
break ;
}
}
}
}
printf ( " \n Disconnected from Asterisk server \n " ) ;
}
2004-07-18 17:58:05 +00:00
static int show_version ( void )
{
Now that the version.h file was getting properly regenerated every time the svn
revision changed, every module that used the version was getting rebuilt after
every svn update. This severly annoyed me pretty quickly, so I have improved
the situation.
Now, instead of generating version.h, main/version.c is generated. version.c
includes the version information, as well as a couple of API calls for modules
to retrieve the version. So now, only version.c will get rebuilt, and the main
asterisk binary relinked, which is must faster than rebuilding http.c, manager.c,
asterisk.c, relinking the asterisk binary, chan_sip.c, func_version.c, res_agi ...
The only minor change in behavior here is that the version information reported by
chan_sip, for example, is the version of the Asterisk core, and not necessarily the
Asterisk version that the chan_sip module came from.
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@96717 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2008-01-05 22:09:06 +00:00
printf ( " Asterisk %s \n " , ast_get_version ( ) ) ;
2004-07-18 17:58:05 +00:00
return 0 ;
}
2012-01-09 17:06:30 +00:00
static int show_cli_help ( void )
{
2018-07-20 21:21:51 +00:00
printf ( " Asterisk %s, " COPYRIGHT_TAG " \n " , ast_get_version ( ) ) ;
2002-09-12 03:22:07 +00:00
printf ( " Usage: asterisk [OPTIONS] \n " ) ;
printf ( " Valid Options: \n " ) ;
2004-07-18 17:58:05 +00:00
printf ( " -V Display version number and exit \n " ) ;
2004-05-13 19:57:45 +00:00
printf ( " -C <configfile> Use an alternate configuration file \n " ) ;
2004-07-18 16:20:54 +00:00
printf ( " -G <group> Run as a group other than the caller \n " ) ;
printf ( " -U <user> Run as a user other than the caller \n " ) ;
2004-05-13 19:57:45 +00:00
printf ( " -c Provide console CLI \n " ) ;
2015-05-06 13:31:33 +00:00
printf ( " -d Increase debugging (multiple d's = more debugging) \n " ) ;
2006-08-21 20:12:18 +00:00
# if HAVE_WORKING_FORK
2004-05-13 19:57:45 +00:00
printf ( " -f Do not fork \n " ) ;
2006-08-21 20:12:18 +00:00
printf ( " -F Always fork \n " ) ;
# endif
2004-05-13 19:57:45 +00:00
printf ( " -g Dump core in case of a crash \n " ) ;
printf ( " -h This help screen \n " ) ;
2004-12-28 07:51:25 +00:00
printf ( " -i Initialize crypto keys at startup \n " ) ;
2006-03-31 00:33:28 +00:00
printf ( " -L <load> Limit the maximum load average before rejecting new calls \n " ) ;
printf ( " -M <value> Limit the maximum number of calls to the specified value \n " ) ;
2007-09-12 15:19:11 +00:00
printf ( " -m Mute debugging and console output on the console \n " ) ;
2004-05-13 19:57:45 +00:00
printf ( " -n Disable console colorization \n " ) ;
printf ( " -p Run as pseudo-realtime thread \n " ) ;
2004-12-28 07:51:25 +00:00
printf ( " -q Quiet mode (suppress output) \n " ) ;
2004-05-13 19:57:45 +00:00
printf ( " -r Connect to Asterisk on this machine \n " ) ;
2007-09-12 15:19:11 +00:00
printf ( " -R Same as -r, except attempt to reconnect if disconnected \n " ) ;
2008-08-25 23:13:32 +00:00
printf ( " -s <socket> Connect to Asterisk via socket <socket> (only valid with -r) \n " ) ;
2007-09-12 15:19:11 +00:00
printf ( " -t Record soundfiles in /var/tmp and move them where they \n " ) ;
printf ( " belong after they are done \n " ) ;
printf ( " -T Display the time in [Mmm dd hh:mm:ss] format for each line \n " ) ;
printf ( " of output to the CLI \n " ) ;
2004-05-13 19:57:45 +00:00
printf ( " -v Increase verbosity (multiple v's = more verbose) \n " ) ;
2012-01-09 17:06:30 +00:00
printf ( " -x <cmd> Execute command <cmd> (implies -r) \n " ) ;
2015-05-06 13:31:33 +00:00
printf ( " -X Enable use of #exec in asterisk.conf \n " ) ;
2008-08-25 23:13:32 +00:00
printf ( " -W Adjust terminal colors to compensate for a light background \n " ) ;
2002-09-12 03:22:07 +00:00
printf ( " \n " ) ;
return 0 ;
}
2016-11-24 00:27:54 +00:00
static void read_pjproject_startup_options ( void )
{
struct ast_config * cfg ;
struct ast_variable * v ;
struct ast_flags config_flags = { CONFIG_FLAG_NOCACHE | CONFIG_FLAG_NOREALTIME } ;
ast_option_pjproject_log_level = DEFAULT_PJ_LOG_MAX_LEVEL ;
2018-02-27 21:40:18 +00:00
ast_option_pjproject_cache_pools = DEFAULT_PJPROJECT_CACHE_POOLS ;
2016-11-24 00:27:54 +00:00
cfg = ast_config_load2 ( " pjproject.conf " , " " /* core, can't reload */ , config_flags ) ;
if ( ! cfg
| | cfg = = CONFIG_STATUS_FILEUNCHANGED
| | cfg = = CONFIG_STATUS_FILEINVALID ) {
/* We'll have to use defaults */
return ;
}
for ( v = ast_variable_browse ( cfg , " startup " ) ; v ; v = v - > next ) {
if ( ! strcasecmp ( v - > name , " log_level " ) ) {
if ( sscanf ( v - > value , " %30d " , & ast_option_pjproject_log_level ) ! = 1 ) {
ast_option_pjproject_log_level = DEFAULT_PJ_LOG_MAX_LEVEL ;
} else if ( ast_option_pjproject_log_level < 0 ) {
ast_option_pjproject_log_level = 0 ;
} else if ( MAX_PJ_LOG_MAX_LEVEL < ast_option_pjproject_log_level ) {
ast_option_pjproject_log_level = MAX_PJ_LOG_MAX_LEVEL ;
}
2018-02-27 21:40:18 +00:00
} else if ( ! strcasecmp ( v - > name , " cache_pools " ) ) {
ast_option_pjproject_cache_pools = ! ast_false ( v - > value ) ;
2016-11-24 00:27:54 +00:00
}
}
ast_config_destroy ( cfg ) ;
}
2007-02-23 23:25:22 +00:00
static void * monitor_sig_flags ( void * unused )
{
for ( ; ; ) {
struct pollfd p = { sig_alert_pipe [ 0 ] , POLLIN , 0 } ;
2017-11-10 01:47:27 +00:00
Merged revisions 182810 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/1.4
........
r182810 | russell | 2009-03-17 21:09:13 -0500 (Tue, 17 Mar 2009) | 44 lines
Fix cases where the internal poll() was not being used when it needed to be.
We have seen a number of problems caused by poll() not working properly on
Mac OSX. If you search around, you'll find a number of references to using
select() instead of poll() to work around these issues. In Asterisk, we've
had poll.c which implements poll() using select() internally. However, we
were still getting reports of problems.
vadim investigated a bit and realized that at least on his system, even
though we were compiling in poll.o, the system poll() was still being used.
So, the primary purpose of this patch is to ensure that we're using the
internal poll() when we want it to be used.
The changes are:
1) Remove logic for when internal poll should be used from the Makefile.
Instead, put it in the configure script. The logic in the configure
script is the same as it was in the Makefile. Ideally, we would have
a functionality test for the problem, but that's not actually possible,
since we would have to be able to run an application on the _target_
system to test poll() behavior.
2) Always include poll.o in the build, but it will be empty if AST_POLL_COMPAT
is not defined.
3) Change uses of poll() throughout the source tree to ast_poll(). I feel
that it is good practice to give the API call a new name when we are
changing its behavior and not using the system version directly in all cases.
So, normally, ast_poll() is just redefined to poll(). On systems where
AST_POLL_COMPAT is defined, ast_poll() is redefined to ast_internal_poll().
4) Change poll() in main/poll.c to be ast_internal_poll().
It's worth noting that any code that still uses poll() directly will work fine
(if they worked fine before). So, for example, out of tree modules that are
using poll() will not stop working or anything. However, for modules to work
properly on Mac OSX, ast_poll() needs to be used.
(closes issue #13404)
Reported by: agalbraith
Tested by: russell, vadim
http://reviewboard.digium.com/r/198/
........
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@182847 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-03-18 02:28:55 +00:00
ast_poll ( & p , 1 , - 1 ) ;
2007-02-23 23:25:22 +00:00
if ( sig_flags . need_reload ) {
sig_flags . need_reload = 0 ;
ast_module_reload ( NULL ) ;
}
if ( sig_flags . need_quit ) {
sig_flags . need_quit = 0 ;
2012-01-05 16:16:51 +00:00
if ( ( consolethread ! = AST_PTHREADT_NULL ) & & ( consolethread ! = pthread_self ( ) ) ) {
2011-07-18 12:54:29 +00:00
sig_flags . need_quit_handler = 1 ;
pthread_kill ( consolethread , SIGURG ) ;
} else {
2012-01-15 20:16:08 +00:00
quit_handler ( 0 , SHUTDOWN_NORMAL , 0 ) ;
2011-07-18 12:54:29 +00:00
}
2007-02-23 23:25:22 +00:00
}
2017-11-10 01:47:27 +00:00
ast_alertpipe_read ( sig_alert_pipe ) ;
2007-02-23 23:25:22 +00:00
}
return NULL ;
}
2007-12-18 23:06:05 +00:00
static void * canary_thread ( void * unused )
{
struct stat canary_stat ;
2008-08-10 19:35:50 +00:00
struct timeval now ;
2007-12-18 23:06:05 +00:00
/* Give the canary time to sing */
sleep ( 120 ) ;
for ( ; ; ) {
2008-08-10 19:35:50 +00:00
now = ast_tvnow ( ) ;
2012-05-10 18:35:14 +00:00
if ( stat ( canary_filename , & canary_stat ) | | now . tv_sec > canary_stat . st_mtime + 60 ) {
2012-01-09 17:06:30 +00:00
ast_log ( LOG_WARNING ,
" The canary is no more. He has ceased to be! "
" He's expired and gone to meet his maker! "
" He's a stiff! Bereft of life, he rests in peace. "
" His metabolic processes are now history! He's off the twig! "
" He's kicked the bucket. He's shuffled off his mortal coil, "
" run down the curtain, and joined the bleeding choir invisible!! "
" THIS is an EX-CANARY. (Reducing priority) \n " ) ;
2016-09-19 14:40:40 +00:00
set_priority_all ( 0 ) ;
2007-12-18 23:06:05 +00:00
pthread_exit ( NULL ) ;
}
/* Check the canary once a minute */
sleep ( 60 ) ;
}
}
/* Used by libc's atexit(3) function */
static void canary_exit ( void )
{
2016-09-19 19:21:23 +00:00
if ( canary_pid > 0 ) {
int status ;
2007-12-18 23:06:05 +00:00
kill ( canary_pid , SIGKILL ) ;
2016-09-19 19:21:23 +00:00
waitpid ( canary_pid , & status , 0 ) ;
}
2007-12-18 23:06:05 +00:00
}
2014-01-14 18:14:02 +00:00
/* Execute CLI commands on startup. Run by main() thread. */
2008-01-17 00:05:13 +00:00
static void run_startup_commands ( void )
{
int fd ;
2008-01-22 20:33:16 +00:00
struct ast_config * cfg ;
struct ast_flags cfg_flags = { 0 } ;
struct ast_variable * v ;
2008-01-17 00:05:13 +00:00
2008-03-26 18:39:06 +00:00
if ( ! ( cfg = ast_config_load2 ( " cli.conf " , " " /* core, can't reload */ , cfg_flags ) ) )
2008-01-17 00:05:13 +00:00
return ;
2008-09-12 23:30:03 +00:00
if ( cfg = = CONFIG_STATUS_FILEMISSING | | cfg = = CONFIG_STATUS_FILEUNCHANGED | | cfg = = CONFIG_STATUS_FILEINVALID ) {
return ;
}
2008-01-17 00:05:13 +00:00
2008-01-22 20:33:16 +00:00
fd = open ( " /dev/null " , O_RDWR ) ;
2008-07-14 22:22:57 +00:00
if ( fd < 0 ) {
ast_config_destroy ( cfg ) ;
2008-01-22 20:33:16 +00:00
return ;
2008-07-14 22:22:57 +00:00
}
2008-01-17 00:05:13 +00:00
2008-01-22 20:41:05 +00:00
for ( v = ast_variable_browse ( cfg , " startup_commands " ) ; v ; v = v - > next ) {
if ( ast_true ( v - > value ) )
ast_cli_command ( fd , v - > name ) ;
}
2008-01-17 00:05:13 +00:00
close ( fd ) ;
2008-01-22 20:33:16 +00:00
ast_config_destroy ( cfg ) ;
2008-01-17 00:05:13 +00:00
}
2010-05-28 22:50:06 +00:00
static void env_init ( void )
{
setenv ( " AST_SYSTEMNAME " , ast_config_AST_SYSTEM_NAME , 1 ) ;
setenv ( " AST_BUILD_HOST " , ast_build_hostname , 1 ) ;
setenv ( " AST_BUILD_DATE " , ast_build_date , 1 ) ;
setenv ( " AST_BUILD_KERNEL " , ast_build_kernel , 1 ) ;
setenv ( " AST_BUILD_MACHINE " , ast_build_machine , 1 ) ;
setenv ( " AST_BUILD_OS " , ast_build_os , 1 ) ;
setenv ( " AST_BUILD_USER " , ast_build_user , 1 ) ;
setenv ( " AST_VERSION " , ast_get_version ( ) , 1 ) ;
}
2012-11-18 20:27:45 +00:00
static void print_intro_message ( const char * runuser , const char * rungroup )
{
2013-08-29 22:49:24 +00:00
if ( ast_opt_console | | option_verbose | | ( ast_opt_remote & & ! ast_opt_exec ) ) {
2012-11-18 20:27:45 +00:00
WELCOME_MESSAGE ;
if ( runuser ) {
ast_verbose ( " Running as user '%s' \n " , runuser ) ;
}
if ( rungroup ) {
ast_verbose ( " Running under group '%s' \n " , rungroup ) ;
}
}
}
2012-12-03 20:46:11 +00:00
static void main_atexit ( void )
{
ast_cli_unregister_multiple ( cli_asterisk , ARRAY_LEN ( cli_asterisk ) ) ;
}
1999-11-15 04:57:28 +00:00
int main ( int argc , char * argv [ ] )
{
2004-01-28 21:32:48 +00:00
int c ;
2001-05-09 03:11:22 +00:00
char * xarg = NULL ;
2002-05-14 14:43:52 +00:00
int x ;
2010-06-28 21:50:57 +00:00
int isroot = 1 , rundir_exists = 0 ;
2007-12-18 10:24:58 +00:00
const char * runuser = NULL , * rungroup = NULL ;
2010-09-02 05:02:54 +00:00
struct rlimit l ;
2015-05-06 13:31:33 +00:00
static const char * getopt_settings = " BC:cde:FfG:ghIiL:M:mnpqRrs:TtU:VvWXx: " ;
2001-05-09 03:11:22 +00:00
2002-05-14 14:43:52 +00:00
/* Remember original args for restart */
2008-07-11 18:09:35 +00:00
if ( argc > ARRAY_LEN ( _argv ) - 1 ) {
fprintf ( stderr , " Truncating argument size to %d \n " , ( int ) ARRAY_LEN ( _argv ) - 1 ) ;
argc = ARRAY_LEN ( _argv ) - 1 ;
2002-05-14 14:43:52 +00:00
}
2008-02-11 18:27:47 +00:00
for ( x = 0 ; x < argc ; x + + )
2002-05-14 14:43:52 +00:00
_argv [ x ] = argv [ x ] ;
_argv [ x ] = NULL ;
2007-10-17 15:39:24 +00:00
if ( geteuid ( ) ! = 0 )
isroot = 0 ;
2004-03-20 07:26:54 +00:00
/* if the progname is rasterisk consider it a remote console */
2004-10-01 18:35:35 +00:00
if ( argv [ 0 ] & & ( strstr ( argv [ 0 ] , " rasterisk " ) ) ! = NULL ) {
2005-12-04 20:40:46 +00:00
ast_set_flag ( & ast_options , AST_OPT_FLAG_NO_FORK | AST_OPT_FLAG_REMOTE ) ;
2004-03-20 07:26:54 +00:00
}
2004-03-20 21:13:12 +00:00
ast_mainpid = getpid ( ) ;
2007-10-17 15:39:24 +00:00
2015-05-06 13:31:33 +00:00
/* Process command-line options that effect asterisk.conf load. */
while ( ( c = getopt ( argc , argv , getopt_settings ) ) ! = - 1 ) {
switch ( c ) {
case ' X ' :
ast_set_flag ( & ast_options , AST_OPT_FLAG_EXEC_INCLUDES ) ;
break ;
case ' C ' :
2018-03-22 03:00:56 +00:00
set_asterisk_conf_path ( optarg ) ;
2015-05-06 13:31:33 +00:00
break ;
case ' d ' :
option_debug + + ;
break ;
case ' h ' :
show_cli_help ( ) ;
exit ( 0 ) ;
case ' R ' :
case ' r ' :
case ' x ' :
/* ast_opt_remote is checked during config load. This is only part of what
* these options do , see the second loop for the rest of the actions . */
ast_set_flag ( & ast_options , AST_OPT_FLAG_REMOTE ) ;
break ;
case ' V ' :
show_version ( ) ;
exit ( 0 ) ;
case ' v ' :
option_verbose + + ;
break ;
case ' ? ' :
exit ( 1 ) ;
}
}
/* Initialize env so it is available if #exec is used in asterisk.conf. */
env_init ( ) ;
2018-03-22 03:00:56 +00:00
load_asterisk_conf ( ) ;
2015-05-06 13:31:33 +00:00
/* Update env to include any systemname that was set. */
env_init ( ) ;
2012-09-21 17:14:59 +00:00
/*! \brief Check for options
*
* \ todo Document these options
*/
2018-03-26 12:42:52 +00:00
optind = 1 ;
2015-05-06 13:31:33 +00:00
while ( ( c = getopt ( argc , argv , getopt_settings ) ) ! = - 1 ) {
2009-11-26 02:09:58 +00:00
/*!\note Please keep the ordering here to alphabetical, capital letters
* first . This will make it easier in the future to select unused
* option flags for new features . */
2006-03-31 00:33:28 +00:00
switch ( c ) {
2009-11-26 02:09:58 +00:00
case ' B ' : /* Force black background */
ast_set_flag ( & ast_options , AST_OPT_FLAG_FORCE_BLACK_BACKGROUND ) ;
ast_clear_flag ( & ast_options , AST_OPT_FLAG_LIGHT_BACKGROUND ) ;
break ;
2009-12-02 20:10:07 +00:00
case ' X ' :
2015-05-06 13:31:33 +00:00
/* The command-line -X option enables #exec for asterisk.conf only. */
2009-12-02 20:10:07 +00:00
break ;
2009-11-26 02:09:58 +00:00
case ' C ' :
2015-05-06 13:31:33 +00:00
/* already processed. */
2009-11-26 02:09:58 +00:00
break ;
case ' c ' :
ast_set_flag ( & ast_options , AST_OPT_FLAG_NO_FORK | AST_OPT_FLAG_CONSOLE ) ;
break ;
case ' d ' :
2015-05-06 13:31:33 +00:00
/* already processed. */
2009-11-26 02:09:58 +00:00
break ;
2007-08-01 19:37:59 +00:00
# if defined(HAVE_SYSINFO)
2007-04-11 19:11:32 +00:00
case ' e ' :
2009-08-10 19:20:57 +00:00
if ( ( sscanf ( & optarg [ 1 ] , " %30ld " , & option_minmemfree ) ! = 1 ) | | ( option_minmemfree < 0 ) ) {
2007-04-11 19:11:32 +00:00
option_minmemfree = 0 ;
}
break ;
2007-04-11 20:59:08 +00:00
# endif
2006-08-21 20:12:18 +00:00
# if HAVE_WORKING_FORK
2006-04-30 14:55:05 +00:00
case ' F ' :
ast_set_flag ( & ast_options , AST_OPT_FLAG_ALWAYS_FORK ) ;
break ;
2006-08-21 20:12:18 +00:00
case ' f ' :
ast_set_flag ( & ast_options , AST_OPT_FLAG_NO_FORK ) ;
break ;
# endif
2009-11-26 02:09:58 +00:00
case ' G ' :
rungroup = ast_strdupa ( optarg ) ;
2001-03-22 04:14:04 +00:00
break ;
2009-11-26 02:09:58 +00:00
case ' g ' :
ast_set_flag ( & ast_options , AST_OPT_FLAG_DUMP_CORE ) ;
2002-05-14 14:43:52 +00:00
break ;
2009-11-26 02:09:58 +00:00
case ' h ' :
2015-05-06 13:31:33 +00:00
/* already processed. */
break ;
2014-04-08 21:25:15 +00:00
case ' I ' :
fprintf ( stderr ,
" NOTICE: The -I option is no longer needed. \n "
" It will always be enabled if you have a timing module loaded. \n " ) ;
break ;
2009-11-26 02:09:58 +00:00
case ' i ' :
ast_set_flag ( & ast_options , AST_OPT_FLAG_INIT_KEYS ) ;
2004-06-25 14:39:38 +00:00
break ;
2009-11-26 02:09:58 +00:00
case ' L ' :
2013-08-05 14:35:00 +00:00
if ( ( sscanf ( optarg , " %30lf " , & ast_option_maxload ) ! = 1 ) | | ( ast_option_maxload < 0.0 ) ) {
ast_option_maxload = 0.0 ;
2009-11-26 02:09:58 +00:00
}
1999-11-15 04:57:28 +00:00
break ;
2009-11-26 02:09:58 +00:00
case ' M ' :
2013-08-05 14:35:00 +00:00
if ( ( sscanf ( optarg , " %30d " , & ast_option_maxcalls ) ! = 1 ) | | ( ast_option_maxcalls < 0 ) ) {
ast_option_maxcalls = 0 ;
2009-11-26 02:09:58 +00:00
}
1999-11-15 04:57:28 +00:00
break ;
2006-05-26 19:48:17 +00:00
case ' m ' :
2006-05-26 21:47:52 +00:00
ast_set_flag ( & ast_options , AST_OPT_FLAG_MUTE ) ;
2006-05-26 19:48:17 +00:00
break ;
2009-11-26 02:09:58 +00:00
case ' n ' :
ast_set_flag ( & ast_options , AST_OPT_FLAG_NO_COLOR ) ;
2005-05-18 01:49:13 +00:00
break ;
2009-11-26 02:09:58 +00:00
case ' p ' :
ast_set_flag ( & ast_options , AST_OPT_FLAG_HIGH_PRIORITY ) ;
2005-10-26 03:58:32 +00:00
break ;
1999-11-15 04:57:28 +00:00
case ' q ' :
2005-12-04 20:40:46 +00:00
ast_set_flag ( & ast_options , AST_OPT_FLAG_QUIET ) ;
1999-11-15 04:57:28 +00:00
break ;
2009-11-26 02:09:58 +00:00
case ' R ' :
ast_set_flag ( & ast_options , AST_OPT_FLAG_NO_FORK | AST_OPT_FLAG_REMOTE | AST_OPT_FLAG_RECONNECT ) ;
2005-03-11 07:24:10 +00:00
break ;
2009-11-26 02:09:58 +00:00
case ' r ' :
ast_set_flag ( & ast_options , AST_OPT_FLAG_NO_FORK | AST_OPT_FLAG_REMOTE ) ;
2001-05-09 03:11:22 +00:00
break ;
2009-11-26 02:09:58 +00:00
case ' s ' :
2015-05-06 13:31:33 +00:00
if ( ast_opt_remote ) {
2018-03-22 03:00:56 +00:00
set_socket_path ( optarg ) ;
2015-05-06 13:31:33 +00:00
}
2003-02-06 06:15:25 +00:00
break ;
2009-11-26 02:09:58 +00:00
case ' T ' :
ast_set_flag ( & ast_options , AST_OPT_FLAG_TIMESTAMP ) ;
2006-03-30 06:07:04 +00:00
break ;
2009-11-26 02:09:58 +00:00
case ' t ' :
ast_set_flag ( & ast_options , AST_OPT_FLAG_CACHE_RECORD_FILES ) ;
2001-12-25 21:12:07 +00:00
break ;
2009-11-26 02:09:58 +00:00
case ' U ' :
runuser = ast_strdupa ( optarg ) ;
2003-02-06 06:15:25 +00:00
break ;
2004-07-18 17:58:05 +00:00
case ' V ' :
2009-11-26 02:09:58 +00:00
case ' v ' :
2015-05-06 13:31:33 +00:00
/* already processed. */
2007-12-19 07:01:40 +00:00
break ;
2008-08-25 23:13:32 +00:00
case ' W ' : /* White background */
ast_set_flag ( & ast_options , AST_OPT_FLAG_LIGHT_BACKGROUND ) ;
2008-10-07 17:44:32 +00:00
ast_clear_flag ( & ast_options , AST_OPT_FLAG_FORCE_BLACK_BACKGROUND ) ;
break ;
2009-11-26 02:09:58 +00:00
case ' x ' :
2012-01-09 17:06:30 +00:00
/* -r is implied by -x so set the flags -r sets as well. */
ast_set_flag ( & ast_options , AST_OPT_FLAG_NO_FORK | AST_OPT_FLAG_REMOTE ) ;
2011-02-10 22:43:51 +00:00
ast_set_flag ( & ast_options , AST_OPT_FLAG_EXEC | AST_OPT_FLAG_NO_COLOR ) ;
2009-11-26 02:09:58 +00:00
xarg = ast_strdupa ( optarg ) ;
2008-08-25 23:13:32 +00:00
break ;
1999-11-15 04:57:28 +00:00
case ' ? ' :
2015-05-06 13:31:33 +00:00
/* already processed. */
break ;
1999-11-15 04:57:28 +00:00
}
}
2002-05-14 14:43:52 +00:00
2005-09-29 02:38:24 +00:00
/* For remote connections, change the name of the remote connection.
* We do this for the benefit of init scripts ( which need to know if / when
* the main asterisk process has died yet ) . */
2005-12-04 20:40:46 +00:00
if ( ast_opt_remote ) {
2005-09-29 02:38:24 +00:00
strcpy ( argv [ 0 ] , " rasterisk " ) ;
for ( x = 1 ; x < argc ; x + + ) {
argv [ x ] = argv [ 0 ] + 10 ;
}
}
2012-11-18 20:27:45 +00:00
if ( ! ast_language_is_prefix & & ! ast_opt_remote ) {
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 " ) ;
}
2006-12-27 21:18:27 +00:00
2008-11-12 17:38:20 +00:00
if ( ast_opt_always_fork & & ( ast_opt_remote | | ast_opt_console ) ) {
2012-11-18 20:27:45 +00:00
fprintf ( stderr , " 'alwaysfork' is not compatible with console or remote console mode; ignored \n " ) ;
2008-11-12 17:38:20 +00:00
ast_clear_flag ( & ast_options , AST_OPT_FLAG_ALWAYS_FORK ) ;
}
2005-12-04 20:40:46 +00:00
if ( ast_opt_dump_core ) {
2003-02-06 06:15:25 +00:00
memset ( & l , 0 , sizeof ( l ) ) ;
l . rlim_cur = RLIM_INFINITY ;
l . rlim_max = RLIM_INFINITY ;
if ( setrlimit ( RLIMIT_CORE , & l ) ) {
2012-11-18 20:27:45 +00:00
fprintf ( stderr , " Unable to disable core size resource limit: %s \n " , strerror ( errno ) ) ;
2003-02-06 06:15:25 +00:00
}
}
2010-09-02 05:02:54 +00:00
if ( getrlimit ( RLIMIT_NOFILE , & l ) ) {
2012-11-18 20:27:45 +00:00
fprintf ( stderr , " Unable to check file descriptor limit: %s \n " , strerror ( errno ) ) ;
2010-09-02 05:02:54 +00:00
}
# if !defined(CONFIGURE_RAN_AS_ROOT)
/* Check if select(2) will run with more file descriptors */
do {
int fd , fd2 ;
ast_fdset readers ;
struct timeval tv = { 0 , } ;
if ( l . rlim_cur < = FD_SETSIZE ) {
/* The limit of select()able FDs is irrelevant, because we'll never
* open one that high . */
break ;
}
if ( ! ( fd = open ( " /dev/null " , O_RDONLY ) ) ) {
2012-11-18 20:27:45 +00:00
fprintf ( stderr , " Cannot open a file descriptor at boot? %s \n " , strerror ( errno ) ) ;
2010-09-02 05:02:54 +00:00
break ; /* XXX Should we exit() here? XXX */
}
2012-04-17 18:57:40 +00:00
fd2 = ( ( l . rlim_cur > sizeof ( readers ) * 8 ) ? sizeof ( readers ) * 8 : l . rlim_cur ) - 1 ;
2010-09-21 19:09:15 +00:00
if ( dup2 ( fd , fd2 ) < 0 ) {
2012-11-18 20:27:45 +00:00
fprintf ( stderr , " Cannot open maximum file descriptor %d at boot? %s \n " , fd2 , strerror ( errno ) ) ;
2011-04-01 10:59:32 +00:00
close ( fd ) ;
2010-09-02 05:02:54 +00:00
break ;
}
FD_ZERO ( & readers ) ;
FD_SET ( fd2 , & readers ) ;
if ( ast_select ( fd2 + 1 , & readers , NULL , NULL , & tv ) < 0 ) {
2012-11-18 20:27:45 +00:00
fprintf ( stderr , " Maximum select()able file descriptor is %d \n " , FD_SETSIZE ) ;
2010-09-02 05:02:54 +00:00
}
2011-04-01 10:59:32 +00:00
ast_FD_SETSIZE = l . rlim_cur > ast_FDMAX ? ast_FDMAX : l . rlim_cur ;
close ( fd ) ;
close ( fd2 ) ;
2010-09-02 05:02:54 +00:00
} while ( 0 ) ;
# elif defined(HAVE_VARIABLE_FDSET)
2011-04-01 10:59:32 +00:00
ast_FD_SETSIZE = l . rlim_cur > ast_FDMAX ? ast_FDMAX : l . rlim_cur ;
2010-09-02 05:02:54 +00:00
# endif /* !defined(CONFIGURE_RAN_AS_ROOT) */
2005-11-08 00:30:29 +00:00
if ( ( ! rungroup ) & & ! ast_strlen_zero ( ast_config_AST_RUN_GROUP ) )
rungroup = ast_config_AST_RUN_GROUP ;
if ( ( ! runuser ) & & ! ast_strlen_zero ( ast_config_AST_RUN_USER ) )
runuser = ast_config_AST_RUN_USER ;
2006-03-31 00:33:28 +00:00
2007-12-18 23:06:05 +00:00
/* Must install this signal handler up here to ensure that if the canary
* fails to execute that it doesn ' t kill the Asterisk process .
*/
2010-05-26 21:17:46 +00:00
sigaction ( SIGCHLD , & child_handler , NULL ) ;
2007-12-18 23:06:05 +00:00
2010-02-25 21:22:39 +00:00
/* It's common on some platforms to clear /var/run at boot. Create the
* socket file directory before we drop privileges . */
2010-06-28 21:50:57 +00:00
if ( mkdir ( ast_config_AST_RUN_DIR , 0755 ) ) {
if ( errno = = EEXIST ) {
rundir_exists = 1 ;
} else {
2012-11-18 20:27:45 +00:00
fprintf ( stderr , " Unable to create socket file directory. Remote consoles will not be able to connect! (%s) \n " , strerror ( x ) ) ;
2010-06-28 21:50:57 +00:00
}
2010-02-25 21:22:39 +00:00
}
2005-11-01 21:53:30 +00:00
# ifndef __CYGWIN__
2007-12-18 23:06:05 +00:00
if ( isroot ) {
2005-12-04 20:40:46 +00:00
ast_set_priority ( ast_opt_high_priority ) ;
2007-12-18 23:06:05 +00:00
}
2005-03-26 07:16:18 +00:00
2007-10-17 15:39:24 +00:00
if ( isroot & & rungroup ) {
2004-07-18 16:20:54 +00:00
struct group * gr ;
gr = getgrnam ( rungroup ) ;
if ( ! gr ) {
2012-11-18 20:27:45 +00:00
fprintf ( stderr , " No such group '%s'! \n " , rungroup ) ;
2004-07-18 16:20:54 +00:00
exit ( 1 ) ;
}
2010-06-28 21:50:57 +00:00
if ( ! rundir_exists & & chown ( ast_config_AST_RUN_DIR , - 1 , gr - > gr_gid ) ) {
2012-11-18 20:27:45 +00:00
fprintf ( stderr , " Unable to chgrp run directory to %d (%s) \n " , ( int ) gr - > gr_gid , rungroup ) ;
2010-02-25 21:22:39 +00:00
}
2004-07-18 18:52:36 +00:00
if ( setgid ( gr - > gr_gid ) ) {
2012-11-18 20:27:45 +00:00
fprintf ( stderr , " Unable to setgid to %d (%s) \n " , ( int ) gr - > gr_gid , rungroup ) ;
2004-07-18 16:20:54 +00:00
exit ( 1 ) ;
}
2005-11-08 00:30:29 +00:00
if ( setgroups ( 0 , NULL ) ) {
2012-11-18 20:27:45 +00:00
fprintf ( stderr , " Unable to drop unneeded groups \n " ) ;
2005-11-08 00:30:29 +00:00
exit ( 1 ) ;
}
2004-07-18 16:20:54 +00:00
}
2007-10-17 15:39:24 +00:00
if ( runuser & & ! ast_test_flag ( & ast_options , AST_OPT_FLAG_REMOTE ) ) {
2006-09-27 21:48:01 +00:00
# ifdef HAVE_CAP
int has_cap = 1 ;
# endif /* HAVE_CAP */
2004-07-18 16:20:54 +00:00
struct passwd * pw ;
pw = getpwnam ( runuser ) ;
if ( ! pw ) {
2012-11-18 20:27:45 +00:00
fprintf ( stderr , " No such user '%s'! \n " , runuser ) ;
2004-07-18 16:20:54 +00:00
exit ( 1 ) ;
}
2010-02-25 21:22:39 +00:00
if ( chown ( ast_config_AST_RUN_DIR , pw - > pw_uid , - 1 ) ) {
2012-11-18 20:27:45 +00:00
fprintf ( stderr , " Unable to chown run directory to %d (%s) \n " , ( int ) pw - > pw_uid , runuser ) ;
2010-02-25 21:22:39 +00:00
}
2006-09-27 21:48:01 +00:00
# ifdef HAVE_CAP
if ( prctl ( PR_SET_KEEPCAPS , 1 , 0 , 0 , 0 ) ) {
ast_log ( LOG_WARNING , " Unable to keep capabilities. \n " ) ;
2006-10-02 16:00:11 +00:00
has_cap = 0 ;
2006-09-27 21:48:01 +00:00
}
# endif /* HAVE_CAP */
2007-10-17 15:39:24 +00:00
if ( ! isroot & & pw - > pw_uid ! = geteuid ( ) ) {
2012-11-18 20:27:45 +00:00
fprintf ( stderr , " Asterisk started as nonroot, but runuser '%s' requested. \n " , runuser ) ;
2007-10-17 15:39:24 +00:00
exit ( 1 ) ;
}
2006-01-08 20:27:22 +00:00
if ( ! rungroup ) {
if ( setgid ( pw - > pw_gid ) ) {
2012-11-18 20:27:45 +00:00
fprintf ( stderr , " Unable to setgid to %d! \n " , ( int ) pw - > pw_gid ) ;
2006-01-08 20:27:22 +00:00
exit ( 1 ) ;
}
2007-12-21 15:14:52 +00:00
if ( isroot & & initgroups ( pw - > pw_name , pw - > pw_gid ) ) {
2012-11-18 20:27:45 +00:00
fprintf ( stderr , " Unable to init groups for '%s' \n " , runuser ) ;
2006-01-07 20:08:51 +00:00
exit ( 1 ) ;
}
2006-01-07 19:42:05 +00:00
}
2004-07-18 16:20:54 +00:00
if ( setuid ( pw - > pw_uid ) ) {
2012-11-18 20:27:45 +00:00
fprintf ( stderr , " Unable to setuid to %d (%s) \n " , ( int ) pw - > pw_uid , runuser ) ;
2004-07-18 16:20:54 +00:00
exit ( 1 ) ;
}
2006-09-27 21:48:01 +00:00
# ifdef HAVE_CAP
if ( has_cap ) {
2006-10-02 16:00:11 +00:00
cap_t cap ;
2009-01-29 23:15:40 +00:00
cap = cap_from_text ( " cap_net_admin=eip " ) ;
2006-10-02 16:00:11 +00:00
2012-11-18 20:27:45 +00:00
if ( cap_set_proc ( cap ) ) {
fprintf ( stderr , " Unable to install capabilities. \n " ) ;
}
if ( cap_free ( cap ) ) {
fprintf ( stderr , " Unable to drop capabilities. \n " ) ;
}
2006-09-27 21:48:01 +00:00
}
# endif /* HAVE_CAP */
2004-07-18 16:20:54 +00:00
}
2005-11-01 21:53:30 +00:00
# endif /* __CYGWIN__ */
2006-02-14 18:47:16 +00:00
# ifdef linux
2006-02-14 02:41:42 +00:00
if ( geteuid ( ) & & ast_opt_dump_core ) {
if ( prctl ( PR_SET_DUMPABLE , 1 , 0 , 0 , 0 ) < 0 ) {
2012-11-18 20:27:45 +00:00
fprintf ( stderr , " Unable to set the process for core dumps after changing to a non-root user. %s \n " , strerror ( errno ) ) ;
2009-04-30 17:40:58 +00:00
}
2006-02-14 02:41:42 +00:00
}
2009-04-30 17:40:58 +00:00
# endif
2009-04-30 06:47:13 +00:00
{
2009-04-30 17:40:58 +00:00
# if defined(HAVE_EACCESS) || defined(HAVE_EUIDACCESS)
# if defined(HAVE_EUIDACCESS) && !defined(HAVE_EACCESS)
# define eaccess euidaccess
# endif
2009-04-30 06:47:13 +00:00
char dir [ PATH_MAX ] ;
if ( ! getcwd ( dir , sizeof ( dir ) ) | | eaccess ( dir , R_OK | X_OK | F_OK ) ) {
2012-11-18 20:27:45 +00:00
fprintf ( stderr , " Unable to access the running directory (%s). Changing to '/' for compatibility. \n " , strerror ( errno ) ) ;
2009-04-30 06:47:13 +00:00
/* If we cannot access the CWD, then we couldn't dump core anyway,
* so chdir ( " / " ) won ' t break anything . */
if ( chdir ( " / " ) ) {
2009-04-30 17:40:58 +00:00
/* chdir(/) should never fail, so this ends up being a no-op */
2012-11-18 20:27:45 +00:00
fprintf ( stderr , " chdir( \" / \" ) failed?!! %s \n " , strerror ( errno ) ) ;
2009-04-30 06:47:13 +00:00
}
2009-04-30 17:40:58 +00:00
} else
# endif /* defined(HAVE_EACCESS) || defined(HAVE_EUIDACCESS) */
if ( ! ast_opt_no_fork & & ! ast_opt_dump_core ) {
2009-04-30 06:47:13 +00:00
/* Backgrounding, but no cores, so chdir won't break anything. */
if ( chdir ( " / " ) ) {
2012-11-18 20:27:45 +00:00
fprintf ( stderr , " Unable to chdir( \" / \" ) ?!! %s \n " , strerror ( errno ) ) ;
2009-04-30 06:47:13 +00:00
}
}
}
2006-02-14 02:41:42 +00:00
2014-01-14 18:14:02 +00:00
/* Initial value of the maximum active system verbosity level. */
ast_verb_sys_level = option_verbose ;
2017-06-19 00:24:04 +00:00
if ( ast_sd_get_fd_un ( SOCK_STREAM , ast_config_AST_SOCKET ) > 0 ) {
ast_socket_is_sd = 1 ;
}
/* DO NOT perform check for existing daemon if systemd has CLI socket activation */
if ( ! ast_socket_is_sd & & ast_tryconnect ( ) ) {
2001-05-09 03:11:22 +00:00
/* One is already running */
2005-12-04 20:40:46 +00:00
if ( ast_opt_remote ) {
2012-11-18 20:27:45 +00:00
multi_thread_safe = 1 ;
2005-12-04 20:40:46 +00:00
if ( ast_opt_exec ) {
2001-05-09 03:11:22 +00:00
ast_remotecontrol ( xarg ) ;
2012-01-15 20:16:08 +00:00
quit_handler ( 0 , SHUTDOWN_FAST , 0 ) ;
2001-05-09 03:11:22 +00:00
exit ( 0 ) ;
}
2015-11-25 19:29:55 +00:00
ast_term_init ( ) ;
printf ( " %s " , term_end ( ) ) ;
fflush ( stdout ) ;
2012-11-18 20:27:45 +00:00
print_intro_message ( runuser , rungroup ) ;
2008-03-18 15:43:34 +00:00
printf ( " %s " , term_quit ( ) ) ;
2001-05-09 03:11:22 +00:00
ast_remotecontrol ( NULL ) ;
2012-01-15 20:16:08 +00:00
quit_handler ( 0 , SHUTDOWN_FAST , 0 ) ;
2001-05-09 03:11:22 +00:00
exit ( 0 ) ;
} else {
2012-11-18 20:27:45 +00:00
fprintf ( stderr , " Asterisk already running on %s. Use 'asterisk -r' to connect. \n " , ast_config_AST_SOCKET ) ;
2008-03-18 15:43:34 +00:00
printf ( " %s " , term_quit ( ) ) ;
2001-05-09 03:11:22 +00:00
exit ( 1 ) ;
}
2005-12-04 20:40:46 +00:00
} else if ( ast_opt_remote | | ast_opt_exec ) {
2012-11-18 20:27:45 +00:00
fprintf ( stderr , " Unable to connect to remote asterisk (does %s exist?) \n " , ast_config_AST_SOCKET ) ;
2008-03-18 15:43:34 +00:00
printf ( " %s " , term_quit ( ) ) ;
2001-05-09 03:11:22 +00:00
exit ( 1 ) ;
}
2001-12-25 21:12:07 +00:00
2015-11-25 19:29:55 +00:00
/* Not a remote console? Start the daemon. */
asterisk_daemon ( isroot , runuser , rungroup ) ;
return 0 ;
}
2016-08-12 03:12:32 +00:00
static inline void check_init ( int init_result , const char * name )
{
if ( init_result ) {
2017-04-11 16:07:39 +00:00
if ( ast_is_logger_initialized ( ) ) {
ast_log ( LOG_ERROR , " %s initialization failed. ASTERISK EXITING! \n %s " , name , term_quit ( ) ) ;
} else {
fprintf ( stderr , " %s initialization failed. ASTERISK EXITING! \n %s " , name , term_quit ( ) ) ;
}
2016-08-12 03:12:32 +00:00
ast_run_atexits ( 0 ) ;
exit ( init_result = = - 2 ? 2 : 1 ) ;
}
}
2015-11-25 19:29:55 +00:00
static void asterisk_daemon ( int isroot , const char * runuser , const char * rungroup )
{
FILE * f ;
sigset_t sigs ;
int num ;
char * buf ;
2016-07-23 13:51:48 +00:00
char pbx_uuid [ AST_UUID_STR_LEN ] ;
2015-11-25 19:29:55 +00:00
2016-05-25 13:45:08 +00:00
/* Set time as soon as possible */
ast_lastreloadtime = ast_startuptime = ast_tvnow ( ) ;
2012-11-18 20:27:45 +00:00
/* This needs to remain as high up in the initial start up as possible.
* daemon causes a fork to occur , which has all sorts of unintended
* consequences for things that interact with threads . This call * must *
* occur before anything in Asterisk spawns or manipulates thread related
* primitives . */
2006-08-21 20:12:18 +00:00
# if HAVE_WORKING_FORK
2006-04-30 14:55:05 +00:00
if ( ast_opt_always_fork | | ! ast_opt_no_fork ) {
2008-02-04 21:15:18 +00:00
# ifndef HAVE_SBIN_LAUNCHD
2008-11-02 18:52:13 +00:00
if ( daemon ( 1 , 0 ) < 0 ) {
2012-11-18 20:27:45 +00:00
fprintf ( stderr , " daemon() failed: %s \n " , strerror ( errno ) ) ;
2013-01-19 00:19:19 +00:00
} else {
ast_mainpid = getpid ( ) ;
2008-11-02 18:52:13 +00:00
}
2008-02-04 21:15:18 +00:00
# else
2012-11-18 20:27:45 +00:00
fprintf ( stderr , " Mac OS X detected. Use 'launchctl load /Library/LaunchDaemon/org.asterisk.asterisk.plist'. \n " ) ;
2008-02-04 21:15:18 +00:00
# endif
2001-05-09 03:11:22 +00:00
}
2006-08-21 20:12:18 +00:00
# endif
2001-12-25 21:12:07 +00:00
2012-11-18 20:27:45 +00:00
/* At this point everything has been forked successfully,
* we have determined that we aren ' t attempting to connect to
* an Asterisk instance , and that there isn ' t one already running . */
multi_thread_safe = 1 ;
2018-08-01 04:54:11 +00:00
load_astmm_phase_1 ( ) ;
2012-11-29 00:48:12 +00:00
2016-09-19 19:21:23 +00:00
/* Check whether high prio was succesfully set by us or some
* other incantation . */
if ( has_priority ( ) ) {
ast_set_flag ( & ast_options , AST_OPT_FLAG_HIGH_PRIORITY ) ;
} else {
ast_clear_flag ( & ast_options , AST_OPT_FLAG_HIGH_PRIORITY ) ;
}
2009-05-18 19:17:15 +00:00
/* Spawning of astcanary must happen AFTER the call to daemon(3) */
2016-09-19 19:21:23 +00:00
if ( ast_opt_high_priority ) {
2009-05-18 19:17:15 +00:00
snprintf ( canary_filename , sizeof ( canary_filename ) , " %s/alt.asterisk.canary.tweet.tweet.tweet " , ast_config_AST_RUN_DIR ) ;
/* Don't let the canary child kill Asterisk, if it dies immediately */
2010-05-26 21:17:46 +00:00
sigaction ( SIGPIPE , & ignore_sig_handler , NULL ) ;
2009-05-18 19:17:15 +00:00
canary_pid = fork ( ) ;
if ( canary_pid = = 0 ) {
2011-12-07 20:15:29 +00:00
char canary_binary [ PATH_MAX ] , ppid [ 12 ] ;
2009-05-18 19:17:15 +00:00
/* Reset signal handler */
signal ( SIGCHLD , SIG_DFL ) ;
signal ( SIGPIPE , SIG_DFL ) ;
ast_close_fds_above_n ( 0 ) ;
ast_set_priority ( 0 ) ;
2010-04-02 20:19:01 +00:00
snprintf ( ppid , sizeof ( ppid ) , " %d " , ( int ) ast_mainpid ) ;
2009-05-18 19:17:15 +00:00
2011-12-07 20:15:29 +00:00
/* Use the astcanary binary that we installed */
snprintf ( canary_binary , sizeof ( canary_binary ) , " %s/astcanary " , ast_config_AST_SBIN_DIR ) ;
execl ( canary_binary , " astcanary " , canary_filename , ppid , ( char * ) NULL ) ;
2009-05-18 19:17:15 +00:00
/* Should never happen */
_exit ( 1 ) ;
} else if ( canary_pid > 0 ) {
pthread_t dont_care ;
ast_pthread_create_detached ( & dont_care , NULL , canary_thread , NULL ) ;
}
/* Kill the canary when we exit */
2010-01-15 21:40:14 +00:00
ast_register_atexit ( canary_exit ) ;
2009-05-18 19:17:15 +00:00
}
2012-11-18 20:27:45 +00:00
/* Blindly write the PID file. */
unlink ( ast_config_AST_PID ) ;
f = fopen ( ast_config_AST_PID , " w " ) ;
if ( f ) {
2013-01-19 00:19:19 +00:00
fprintf ( f , " %ld \n " , ( long ) ast_mainpid ) ;
2012-11-18 20:27:45 +00:00
fclose ( f ) ;
} else {
fprintf ( stderr , " Unable to open pid file '%s': %s \n " , ast_config_AST_PID , strerror ( errno ) ) ;
}
/* Initialize the terminal. Since all processes have been forked,
* we can now start using the standard log messages .
*/
ast_term_init ( ) ;
printf ( " %s " , term_end ( ) ) ;
fflush ( stdout ) ;
print_intro_message ( runuser , rungroup ) ;
register_config_cli ( ) ;
2016-08-12 03:12:32 +00:00
check_init ( astobj2_init ( ) , " AO2 " ) ;
check_init ( ast_named_locks_init ( ) , " Named Locks " ) ;
2016-04-01 01:04:29 +00:00
2012-11-18 20:27:45 +00:00
if ( ast_opt_console ) {
if ( el_hist = = NULL | | el = = NULL )
ast_el_initialize ( ) ;
2015-11-25 19:29:55 +00:00
ast_el_read_default_histfile ( ) ;
2012-11-18 20:27:45 +00:00
}
2016-07-23 13:51:48 +00:00
# ifdef AST_XML_DOCS
/* Load XML documentation. */
ast_xmldoc_load_documentation ( ) ;
# endif
2016-08-12 03:12:32 +00:00
check_init ( astdb_init ( ) , " ASTdb " ) ;
2016-07-23 13:51:48 +00:00
ast_uuid_init ( ) ;
if ( ast_pbx_uuid_get ( pbx_uuid , sizeof ( pbx_uuid ) ) ) {
ast_uuid_generate_str ( pbx_uuid , sizeof ( pbx_uuid ) ) ;
ast_db_put ( " pbx " , " UUID " , pbx_uuid ) ;
}
ast_verb ( 0 , " PBX UUID: %s \n " , pbx_uuid ) ;
2013-03-22 19:26:37 +00:00
ast_json_init ( ) ;
2012-11-18 20:27:45 +00:00
ast_ulaw_init ( ) ;
ast_alaw_init ( ) ;
tdd_init ( ) ;
callerid_init ( ) ;
ast_builtins_init ( ) ;
2016-08-12 03:12:32 +00:00
check_init ( ast_utils_init ( ) , " Utilities " ) ;
check_init ( ast_tps_init ( ) , " Task Processor Core " ) ;
check_init ( ast_fd_init ( ) , " File Descriptor Debugging " ) ;
check_init ( ast_pbx_init ( ) , " ast_pbx_init " ) ;
2018-11-30 11:40:40 +00:00
check_init ( aco_init ( ) , " Configuration Option Framework " ) ;
check_init ( stasis_init ( ) , " Stasis " ) ;
2009-12-22 16:09:11 +00:00
# ifdef TEST_FRAMEWORK
2016-08-12 03:12:32 +00:00
check_init ( ast_test_init ( ) , " Test Framework " ) ;
2009-12-22 16:09:11 +00:00
# endif
2016-08-12 03:12:32 +00:00
check_init ( ast_translate_init ( ) , " Translator Core " ) ;
2011-02-03 16:22:10 +00:00
Generic Advice of Charge.
Asterisk Generic AOC Representation
- Generic AOC encode/decode routines.
(Generic AOC must be encoded to be passed on the wire in the AST_CONTROL_AOC frame)
- AST_CONTROL_AOC frame type to represent generic encoded AOC data
- Manager events for AOC-S, AOC-D, and AOC-E messages
Asterisk App Support
- app_dial AOC-S pass-through support on call setup
- app_queue AOC-S pass-through support on call setup
AOC Unit Tests
- AOC Unit Tests for encode/decode routines
- AOC Unit Test for manager event representation.
SIP AOC Support
- Pass-through of generic AOC-D and AOC-E messages to snom phones via the
snom AOC specification.
- Creation of chan_sip page3 flags for the addition of the new
'snom_aoc_enabled' sip.conf option.
IAX AOC Support
- Natively supports AOC pass-through through the use of the new
AST_CONTROL_AOC frame type
DAHDI AOC Support
- ETSI PRI full AOC Pass-through support
- 'aoc_enable' chan_dahdi.conf option for independently enabling
pass-through of AOC-S, AOC-D, AOC-E.
- 'aoce_delayhangup' option for retrieving AOC-E on disconnect.
- DAHDI A() dial string option for requesting AOC services.
example usage:
;requests AOC-S, AOC-D, and AOC-E on call setup
exten=>1111,1,Dial(DAHDI/g1/1112/A(s,d,e))
Review: https://reviewboard.asterisk.org/r/552/
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@267096 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2010-06-02 18:10:15 +00:00
ast_aoc_cli_init ( ) ;
2016-08-12 03:12:32 +00:00
check_init ( ast_sorcery_init ( ) , " Sorcery " ) ;
check_init ( ast_codec_init ( ) , " Codecs " ) ;
check_init ( ast_format_init ( ) , " Formats " ) ;
check_init ( ast_format_cache_init ( ) , " Format Cache " ) ;
check_init ( ast_codec_builtin_init ( ) , " Built-in Codecs " ) ;
check_init ( ast_bucket_init ( ) , " Bucket API " ) ;
check_init ( ast_stasis_system_init ( ) , " Stasis system-level information " ) ;
check_init ( ast_endpoint_stasis_init ( ) , " Stasis Endpoint " ) ;
2013-05-08 13:39:08 +00:00
2001-05-09 03:11:22 +00:00
ast_makesocket ( ) ;
2015-01-26 14:50:40 +00:00
/* GCC 4.9 gives a bogus "right-hand operand of comma expression has
* no effect " warning */
( void ) sigemptyset ( & sigs ) ;
( void ) sigaddset ( & sigs , SIGHUP ) ;
( void ) sigaddset ( & sigs , SIGTERM ) ;
( void ) sigaddset ( & sigs , SIGINT ) ;
( void ) sigaddset ( & sigs , SIGPIPE ) ;
( void ) sigaddset ( & sigs , SIGWINCH ) ;
2001-05-09 03:11:22 +00:00
pthread_sigmask ( SIG_BLOCK , & sigs , NULL ) ;
2010-05-26 21:17:46 +00:00
sigaction ( SIGURG , & urg_handler , NULL ) ;
2002-05-14 14:43:52 +00:00
signal ( SIGINT , __quit_handler ) ;
signal ( SIGTERM , __quit_handler ) ;
2010-05-26 21:17:46 +00:00
sigaction ( SIGHUP , & hup_handler , NULL ) ;
sigaction ( SIGPIPE , & ignore_sig_handler , NULL ) ;
2003-09-16 19:35:57 +00:00
2005-04-13 04:47:39 +00:00
/* ensure that the random number generators are seeded with a different value every time
Asterisk is started
*/
srand ( ( unsigned int ) getpid ( ) + ( unsigned int ) time ( NULL ) ) ;
2006-01-10 00:55:45 +00:00
initstate ( ( unsigned int ) getpid ( ) * 65536 + ( unsigned int ) time ( NULL ) , randompool , sizeof ( randompool ) ) ;
2005-04-13 04:47:39 +00:00
2007-01-04 23:18:36 +00:00
threadstorage_init ( ) ;
2016-09-20 14:22:45 +00:00
check_init ( init_logger ( ) , " Logger " ) ;
2016-08-12 03:12:32 +00:00
check_init ( ast_rtp_engine_init ( ) , " RTP Engine " ) ;
2011-02-03 16:22:10 +00:00
3) In addition to merging the changes below, change trunk back to a regular
LIST instead of an RWLIST. The way this list works makes it such that
a RWLIST provides no additional benefit. Also, a mutex is needed for
use with the thread condition.
Merged revisions 105563 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/1.4
........
r105563 | russell | 2008-03-03 09:50:43 -0600 (Mon, 03 Mar 2008) | 24 lines
Merge in some changes from team/russell/autoservice-nochans-1.4
These changes fix up some dubious code that I came across while auditing what
happens in the autoservice thread when there are no channels currently in
autoservice.
1) Change it so that autoservice thread doesn't keep looping around calling
ast_waitfor_n() on 0 channels twice a second. Instead, use a thread condition
so that the thread properly goes to sleep and does not wake up until a
channel is put into autoservice.
This actually fixes an interesting bug, as well. If the autoservice thread
is already running (almost always is the case), then when the thread goes
from having 0 channels to have 1 channel to autoservice, that channel would
have to wait for up to 1/2 of a second to have the first frame read from it.
2) Fix up the code in ast_waitfor_nandfds() for when it gets called with no
channels and no fds to poll() on, such as was the case with the previous code
for the autoservice thread. In this case, the code would call alloca(0), and
pass the result as the first argument to poll(). In this case, the 2nd
argument to poll() specified that there were no fds, so this invalid pointer
shouldn't actually get dereferenced, but, this code makes it explicit and
ensures the pointers are NULL unless we have valid data to put there.
(related to issue #12116)
........
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@105564 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2008-03-03 15:59:50 +00:00
ast_autoservice_init ( ) ;
2016-08-12 03:12:32 +00:00
check_init ( ast_timing_init ( ) , " Timing " ) ;
check_init ( ast_ssl_init ( ) , " SSL " ) ;
2016-11-24 00:27:54 +00:00
read_pjproject_startup_options ( ) ;
2016-08-12 03:12:32 +00:00
check_init ( ast_pj_init ( ) , " Embedded PJProject " ) ;
check_init ( app_init ( ) , " App Core " ) ;
check_init ( devstate_init ( ) , " Device State Core " ) ;
check_init ( ast_msg_init ( ) , " Messaging API " ) ;
check_init ( ast_channels_init ( ) , " Channel " ) ;
check_init ( ast_endpoint_init ( ) , " Endpoints " ) ;
check_init ( ast_pickup_init ( ) , " Call Pickup " ) ;
check_init ( ast_bridging_init ( ) , " Bridging " ) ;
check_init ( ast_parking_stasis_init ( ) , " Parking Core " ) ;
check_init ( ast_device_state_engine_init ( ) , " Device State Engine " ) ;
check_init ( ast_presence_state_engine_init ( ) , " Presence State Engine " ) ;
2018-03-10 09:33:33 +00:00
check_init ( dns_core_init ( ) , " DNS Resolver Core " ) ;
2016-08-12 03:12:32 +00:00
check_init ( ast_dns_system_resolver_init ( ) , " Default DNS resolver " ) ;
check_init ( ast_security_stasis_init ( ) , " Security Stasis Topic and Events " ) ;
check_init ( ast_image_init ( ) , " Image " ) ;
check_init ( ast_file_init ( ) , " Generic File Format Support " ) ;
check_init ( load_pbx ( ) , " load_pbx " ) ;
check_init ( load_pbx_builtins ( ) , " Builtin PBX Applications " ) ;
check_init ( load_pbx_functions_cli ( ) , " PBX Functions Support " ) ;
check_init ( load_pbx_variables ( ) , " PBX Variables Support " ) ;
check_init ( load_pbx_switch ( ) , " PBX Switch Support " ) ;
check_init ( load_pbx_app ( ) , " PBX Application Support " ) ;
check_init ( load_pbx_hangup_handler ( ) , " PBX Hangup Handler Support " ) ;
check_init ( ast_local_init ( ) , " Local Proxy Channel Driver " ) ;
2018-01-01 21:59:57 +00:00
/* We should avoid most config loads before this point as they can't use realtime. */
2018-07-15 18:58:15 +00:00
check_init ( load_modules ( ) , " Module " ) ;
2006-08-21 22:23:26 +00:00
2015-01-29 14:38:23 +00:00
/*
* This has to load after the dynamic modules load , as items in the media
* cache can ' t be constructed from items in the AstDB without their
* bucket backends .
*/
2016-08-12 03:12:32 +00:00
check_init ( ast_media_cache_init ( ) , " Media Cache " ) ;
2015-01-29 14:38:23 +00:00
2008-12-01 18:52:14 +00:00
/* loads the cli_permissoins.conf file needed to implement cli restrictions. */
ast_cli_perms_init ( 0 ) ;
2009-05-22 21:11:03 +00:00
ast_stun_init ( ) ;
2005-11-08 01:29:14 +00:00
dnsmgr_start_refresh ( ) ;
2012-02-14 20:27:16 +00:00
if ( ast_opt_no_fork ) {
2004-03-02 23:50:03 +00:00
consolethread = pthread_self ( ) ;
2012-02-14 20:27:16 +00:00
}
2006-08-21 02:11:39 +00:00
2017-11-10 01:47:27 +00:00
ast_alertpipe_init ( sig_alert_pipe ) ;
2007-02-23 23:25:22 +00:00
2015-04-09 23:08:10 +00:00
ast_process_pending_reloads ( ) ;
2005-12-04 20:40:46 +00:00
ast_set_flag ( & ast_options , AST_OPT_FLAG_FULLY_BOOTED ) ;
2013-05-24 20:44:07 +00:00
publish_fully_booted ( ) ;
Merged revisions 199022 via svnmerge from
https://origsvn.digium.com/svn/asterisk/branches/1.4
........
r199022 | seanbright | 2009-06-04 10:14:57 -0400 (Thu, 04 Jun 2009) | 40 lines
Safely handle AMI connections/reload requests that occur during startup.
During asterisk startup, a lock on the list of modules is obtained by the
primary thread while each module is initialized. Issue 13778 pointed out a
problem with this approach, however. Because the AMI is loaded before other
modules, it is possible for a module reload to be issued by a connected client
(via Action: Command), causing a deadlock.
The resolution for 13778 was to move initialization of the manager to happen
after the other modules had already been lodaded. While this fixed this
particular issue, it caused a problem for users (like FreePBX) who call AMI
scripts via an #exec in a configuration file (See issue 15189).
The solution I have come up with is to defer any reload requests that come in
until after the server is fully booted. When a call comes in to
ast_module_reload (from wherever) before we are fully booted, the request is
added to a queue of pending requests. Once we are done booting up, we then
execute these deferred requests in turn.
Note that I have tried to make this a bit more intelligent in that it will not
queue up more than 1 request for the same module to be reloaded, and if a
general reload request comes in ('module reload') the queue is flushed and we
only issue a single deferred reload for the entire system.
As for how this will impact existing installations - Before 13778, a reload
issued before module initialization was completed would result in a deadlock.
After 13778, you simply couldn't connect to the manager during startup (which
causes problems with #exec-that-calls-AMI configuration files). I believe this
is a good general purpose solution that won't negatively impact existing
installations.
(closes issue #15189)
(closes issue #13778)
Reported by: p_lindheimer
Patches:
06032009_15189_deferred_reloads.diff uploaded by seanbright (license 71)
Tested by: p_lindheimer, seanbright
Review: https://reviewboard.asterisk.org/r/272/
........
git-svn-id: https://origsvn.digium.com/svn/asterisk/trunk@199051 65c4cc65-6c06-0410-ace0-fbb531ad65f3
2009-06-04 14:31:24 +00:00
2001-05-09 03:11:22 +00:00
pthread_sigmask ( SIG_UNBLOCK , & sigs , NULL ) ;
2006-08-21 02:11:39 +00:00
2018-08-01 04:54:11 +00:00
load_astmm_phase_2 ( ) ;
2006-08-21 02:11:39 +00:00
2012-12-03 20:46:11 +00:00
ast_cli_register_multiple ( cli_asterisk_shutdown , ARRAY_LEN ( cli_asterisk_shutdown ) ) ;
2008-12-05 10:31:25 +00:00
ast_cli_register_multiple ( cli_asterisk , ARRAY_LEN ( cli_asterisk ) ) ;
2015-03-26 22:24:26 +00:00
ast_register_cleanup ( main_atexit ) ;
2006-08-21 02:11:39 +00:00
2008-01-17 00:05:13 +00:00
run_startup_commands ( ) ;
2016-06-27 19:26:54 +00:00
ast_sd_notify ( " READY=1 " ) ;
2008-01-17 00:05:13 +00:00
2014-05-28 22:54:12 +00:00
ast_verb ( 0 , COLORIZE_FMT " \n " , COLORIZE ( COLOR_BRGREEN , 0 , " Asterisk Ready. " ) ) ;
2014-12-22 20:08:35 +00:00
logger_queue_start ( ) ;
2005-12-04 20:40:46 +00:00
if ( ast_opt_console ) {
2000-01-02 20:59:00 +00:00
/* Console stuff now... */
/* Register our quit function */
2000-10-25 23:22:50 +00:00
char title [ 256 ] ;
2015-11-25 19:29:55 +00:00
char hostname [ MAXHOSTNAMELEN ] = " " ;
if ( gethostname ( hostname , sizeof ( hostname ) - 1 ) ) {
ast_copy_string ( hostname , " <Unknown> " , sizeof ( hostname ) ) ;
}
2007-02-23 23:25:22 +00:00
2010-10-08 03:00:40 +00:00
ast_pthread_create_detached ( & mon_sig_flags , NULL , monitor_sig_flags , NULL ) ;
2007-02-23 23:25:22 +00:00
2000-10-25 23:22:50 +00:00
set_icon ( " Asterisk " ) ;
2006-05-08 12:32:44 +00:00
snprintf ( title , sizeof ( title ) , " Asterisk Console on '%s' (pid %ld) " , hostname , ( long ) ast_mainpid ) ;
2000-10-25 23:22:50 +00:00
set_title ( title ) ;
2003-02-06 06:15:25 +00:00
2011-07-18 12:54:29 +00:00
el_set ( el , EL_GETCFN , ast_el_read_char ) ;
2003-05-22 14:24:06 +00:00
for ( ; ; ) {
2018-11-11 13:34:53 +00:00
if ( sig_flags . need_el_end ) {
el_end ( el ) ;
return ;
}
2011-07-18 12:54:29 +00:00
if ( sig_flags . need_quit | | sig_flags . need_quit_handler ) {
2012-01-15 20:16:08 +00:00
quit_handler ( 0 , SHUTDOWN_FAST , 0 ) ;
2011-07-18 12:54:29 +00:00
break ;
}
2007-09-20 19:42:33 +00:00
buf = ( char * ) el_gets ( el , & num ) ;
2007-06-27 20:47:45 +00:00
2007-06-27 23:30:31 +00:00
if ( ! buf & & write ( 1 , " " , 1 ) < 0 )
2015-11-25 19:29:55 +00:00
return ; /* quit */
2007-06-27 23:30:31 +00:00
2007-06-24 20:07:15 +00:00
if ( buf ) {
if ( buf [ strlen ( buf ) - 1 ] = = ' \n ' )
buf [ strlen ( buf ) - 1 ] = ' \0 ' ;
2003-05-22 14:24:06 +00:00
2015-11-25 19:29:55 +00:00
consolehandler ( buf ) ;
2003-08-21 02:34:03 +00:00
}
2003-02-06 06:15:25 +00:00
}
2000-01-02 20:59:00 +00:00
}
2007-02-23 23:25:22 +00:00
2015-11-25 19:29:55 +00:00
/* Stall until a quit signal is given */
2007-02-23 23:25:22 +00:00
monitor_sig_flags ( NULL ) ;
1999-11-15 04:57:28 +00:00
}