pbx.c

Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C) 1999 - 2008, Digium, Inc.
00005  *
00006  * Mark Spencer <markster@digium.com>
00007  *
00008  * See http://www.asterisk.org for more information about
00009  * the Asterisk project. Please do not directly contact
00010  * any of the maintainers of this project for assistance;
00011  * the project provides a web site, mailing lists and IRC
00012  * channels for your use.
00013  *
00014  * This program is free software, distributed under the terms of
00015  * the GNU General Public License Version 2. See the LICENSE file
00016  * at the top of the source tree.
00017  */
00018 
00019 /*! \file
00020  *
00021  * \brief Core PBX routines.
00022  *
00023  * \author Mark Spencer <markster@digium.com>
00024  */
00025 
00026 /*** MODULEINFO
00027    <support_level>core</support_level>
00028  ***/
00029 
00030 #include "asterisk.h"
00031 
00032 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 433498 $")
00033 
00034 #include "asterisk/_private.h"
00035 #include "asterisk/paths.h"   /* use ast_config_AST_SYSTEM_NAME */
00036 #include <ctype.h>
00037 #include <time.h>
00038 #include <sys/time.h>
00039 #if defined(HAVE_SYSINFO)
00040 #include <sys/sysinfo.h>
00041 #endif
00042 #if defined(SOLARIS)
00043 #include <sys/loadavg.h>
00044 #endif
00045 
00046 #include "asterisk/lock.h"
00047 #include "asterisk/cli.h"
00048 #include "asterisk/pbx.h"
00049 #include "asterisk/channel.h"
00050 #include "asterisk/file.h"
00051 #include "asterisk/callerid.h"
00052 #include "asterisk/cdr.h"
00053 #include "asterisk/config.h"
00054 #include "asterisk/term.h"
00055 #include "asterisk/time.h"
00056 #include "asterisk/manager.h"
00057 #include "asterisk/ast_expr.h"
00058 #include "asterisk/linkedlists.h"
00059 #define  SAY_STUBS   /* generate declarations and stubs for say methods */
00060 #include "asterisk/say.h"
00061 #include "asterisk/utils.h"
00062 #include "asterisk/causes.h"
00063 #include "asterisk/musiconhold.h"
00064 #include "asterisk/app.h"
00065 #include "asterisk/devicestate.h"
00066 #include "asterisk/presencestate.h"
00067 #include "asterisk/hashtab.h"
00068 #include "asterisk/module.h"
00069 #include "asterisk/indications.h"
00070 #include "asterisk/taskprocessor.h"
00071 #include "asterisk/xmldoc.h"
00072 #include "asterisk/astobj2.h"
00073 #include "asterisk/stasis_channels.h"
00074 #include "asterisk/dial.h"
00075 
00076 /*!
00077  * \note I M P O R T A N T :
00078  *
00079  *    The speed of extension handling will likely be among the most important
00080  * aspects of this PBX.  The switching scheme as it exists right now isn't
00081  * terribly bad (it's O(N+M), where N is the # of extensions and M is the avg #
00082  * of priorities, but a constant search time here would be great ;-)
00083  *
00084  * A new algorithm to do searching based on a 'compiled' pattern tree is introduced
00085  * here, and shows a fairly flat (constant) search time, even for over
00086  * 10000 patterns.
00087  *
00088  * Also, using a hash table for context/priority name lookup can help prevent
00089  * the find_extension routines from absorbing exponential cpu cycles as the number
00090  * of contexts/priorities grow. I've previously tested find_extension with red-black trees,
00091  * which have O(log2(n)) speed. Right now, I'm using hash tables, which do
00092  * searches (ideally) in O(1) time. While these techniques do not yield much
00093  * speed in small dialplans, they are worth the trouble in large dialplans.
00094  *
00095  */
00096 
00097 /*** DOCUMENTATION
00098    <application name="Answer" language="en_US">
00099       <synopsis>
00100          Answer a channel if ringing.
00101       </synopsis>
00102       <syntax>
00103          <parameter name="delay">
00104             <para>Asterisk will wait this number of milliseconds before returning to
00105             the dialplan after answering the call.</para>
00106          </parameter>
00107       </syntax>
00108       <description>
00109          <para>If the call has not been answered, this application will
00110          answer it. Otherwise, it has no effect on the call.</para>
00111       </description>
00112       <see-also>
00113          <ref type="application">Hangup</ref>
00114       </see-also>
00115    </application>
00116    <application name="BackGround" language="en_US">
00117       <synopsis>
00118          Play an audio file while waiting for digits of an extension to go to.
00119       </synopsis>
00120       <syntax>
00121          <parameter name="filenames" required="true" argsep="&amp;">
00122             <argument name="filename1" required="true" />
00123             <argument name="filename2" multiple="true" />
00124          </parameter>
00125          <parameter name="options">
00126             <optionlist>
00127                <option name="s">
00128                   <para>Causes the playback of the message to be skipped
00129                   if the channel is not in the <literal>up</literal> state (i.e. it
00130                   hasn't been answered yet). If this happens, the
00131                   application will return immediately.</para>
00132                </option>
00133                <option name="n">
00134                   <para>Don't answer the channel before playing the files.</para>
00135                </option>
00136                <option name="m">
00137                   <para>Only break if a digit hit matches a one digit
00138                   extension in the destination context.</para>
00139                </option>
00140             </optionlist>
00141          </parameter>
00142          <parameter name="langoverride">
00143             <para>Explicitly specifies which language to attempt to use for the requested sound files.</para>
00144          </parameter>
00145          <parameter name="context">
00146             <para>This is the dialplan context that this application will use when exiting
00147             to a dialed extension.</para>
00148          </parameter>
00149       </syntax>
00150       <description>
00151          <para>This application will play the given list of files <emphasis>(do not put extension)</emphasis>
00152          while waiting for an extension to be dialed by the calling channel. To continue waiting
00153          for digits after this application has finished playing files, the <literal>WaitExten</literal>
00154          application should be used.</para>
00155          <para>If one of the requested sound files does not exist, call processing will be terminated.</para>
00156          <para>This application sets the following channel variable upon completion:</para>
00157          <variablelist>
00158             <variable name="BACKGROUNDSTATUS">
00159                <para>The status of the background attempt as a text string.</para>
00160                <value name="SUCCESS" />
00161                <value name="FAILED" />
00162             </variable>
00163          </variablelist>
00164       </description>
00165       <see-also>
00166          <ref type="application">ControlPlayback</ref>
00167          <ref type="application">WaitExten</ref>
00168          <ref type="application">BackgroundDetect</ref>
00169          <ref type="function">TIMEOUT</ref>
00170       </see-also>
00171    </application>
00172    <application name="Busy" language="en_US">
00173       <synopsis>
00174          Indicate the Busy condition.
00175       </synopsis>
00176       <syntax>
00177          <parameter name="timeout">
00178             <para>If specified, the calling channel will be hung up after the specified number of seconds.
00179             Otherwise, this application will wait until the calling channel hangs up.</para>
00180          </parameter>
00181       </syntax>
00182       <description>
00183          <para>This application will indicate the busy condition to the calling channel.</para>
00184       </description>
00185       <see-also>
00186          <ref type="application">Congestion</ref>
00187          <ref type="application">Progress</ref>
00188          <ref type="application">Playtones</ref>
00189          <ref type="application">Hangup</ref>
00190       </see-also>
00191    </application>
00192    <application name="Congestion" language="en_US">
00193       <synopsis>
00194          Indicate the Congestion condition.
00195       </synopsis>
00196       <syntax>
00197          <parameter name="timeout">
00198             <para>If specified, the calling channel will be hung up after the specified number of seconds.
00199             Otherwise, this application will wait until the calling channel hangs up.</para>
00200          </parameter>
00201       </syntax>
00202       <description>
00203          <para>This application will indicate the congestion condition to the calling channel.</para>
00204       </description>
00205       <see-also>
00206          <ref type="application">Busy</ref>
00207          <ref type="application">Progress</ref>
00208          <ref type="application">Playtones</ref>
00209          <ref type="application">Hangup</ref>
00210       </see-also>
00211    </application>
00212    <application name="ExecIfTime" language="en_US">
00213       <synopsis>
00214          Conditional application execution based on the current time.
00215       </synopsis>
00216       <syntax argsep="?">
00217          <parameter name="day_condition" required="true">
00218             <argument name="times" required="true" />
00219             <argument name="weekdays" required="true" />
00220             <argument name="mdays" required="true" />
00221             <argument name="months" required="true" />
00222             <argument name="timezone" required="false" />
00223          </parameter>
00224          <parameter name="appname" required="true" hasparams="optional">
00225             <argument name="appargs" required="true" />
00226          </parameter>
00227       </syntax>
00228       <description>
00229          <para>This application will execute the specified dialplan application, with optional
00230          arguments, if the current time matches the given time specification.</para>
00231       </description>
00232       <see-also>
00233          <ref type="application">Exec</ref>
00234          <ref type="application">ExecIf</ref>
00235          <ref type="application">TryExec</ref>
00236          <ref type="application">GotoIfTime</ref>
00237       </see-also>
00238    </application>
00239    <application name="Goto" language="en_US">
00240       <synopsis>
00241          Jump to a particular priority, extension, or context.
00242       </synopsis>
00243       <syntax>
00244          <parameter name="context" />
00245          <parameter name="extensions" />
00246          <parameter name="priority" required="true" />
00247       </syntax>
00248       <description>
00249          <para>This application will set the current context, extension, and priority in the channel structure.
00250          After it completes, the pbx engine will continue dialplan execution at the specified location.
00251          If no specific <replaceable>extension</replaceable>, or <replaceable>extension</replaceable> and
00252          <replaceable>context</replaceable>, are specified, then this application will
00253          just set the specified <replaceable>priority</replaceable> of the current extension.</para>
00254          <para>At least a <replaceable>priority</replaceable> is required as an argument, or the goto will
00255          return a <literal>-1</literal>,  and the channel and call will be terminated.</para>
00256          <para>If the location that is put into the channel information is bogus, and asterisk cannot
00257          find that location in the dialplan, then the execution engine will try to find and execute the code in
00258          the <literal>i</literal> (invalid) extension in the current context. If that does not exist, it will try to execute the
00259          <literal>h</literal> extension. If neither the <literal>h</literal> nor <literal>i</literal> extensions
00260          have been defined, the channel is hung up, and the execution of instructions on the channel is terminated.
00261          What this means is that, for example, you specify a context that does not exist, then
00262          it will not be possible to find the <literal>h</literal> or <literal>i</literal> extensions,
00263          and the call will terminate!</para>
00264       </description>
00265       <see-also>
00266          <ref type="application">GotoIf</ref>
00267          <ref type="application">GotoIfTime</ref>
00268          <ref type="application">Gosub</ref>
00269          <ref type="application">Macro</ref>
00270       </see-also>
00271    </application>
00272    <application name="GotoIf" language="en_US">
00273       <synopsis>
00274          Conditional goto.
00275       </synopsis>
00276       <syntax argsep="?">
00277          <parameter name="condition" required="true" />
00278          <parameter name="destination" required="true" argsep=":">
00279             <argument name="labeliftrue">
00280                <para>Continue at <replaceable>labeliftrue</replaceable> if the condition is true.
00281                Takes the form similar to Goto() of [[context,]extension,]priority.</para>
00282             </argument>
00283             <argument name="labeliffalse">
00284                <para>Continue at <replaceable>labeliffalse</replaceable> if the condition is false.
00285                Takes the form similar to Goto() of [[context,]extension,]priority.</para>
00286             </argument>
00287          </parameter>
00288       </syntax>
00289       <description>
00290          <para>This application will set the current context, extension, and priority in the channel structure
00291          based on the evaluation of the given condition. After this application completes, the
00292          pbx engine will continue dialplan execution at the specified location in the dialplan.
00293          The labels are specified with the same syntax as used within the Goto application.
00294          If the label chosen by the condition is omitted, no jump is performed, and the execution passes to the
00295          next instruction. If the target location is bogus, and does not exist, the execution engine will try
00296          to find and execute the code in the <literal>i</literal> (invalid) extension in the current context.
00297          If that does not exist, it will try to execute the <literal>h</literal> extension.
00298          If neither the <literal>h</literal> nor <literal>i</literal> extensions have been defined,
00299          the channel is hung up, and the execution of instructions on the channel is terminated.
00300          Remember that this command can set the current context, and if the context specified
00301          does not exist, then it will not be able to find any 'h' or 'i' extensions there, and
00302          the channel and call will both be terminated!.</para>
00303       </description>
00304       <see-also>
00305          <ref type="application">Goto</ref>
00306          <ref type="application">GotoIfTime</ref>
00307          <ref type="application">GosubIf</ref>
00308          <ref type="application">MacroIf</ref>
00309       </see-also>
00310    </application>
00311    <application name="GotoIfTime" language="en_US">
00312       <synopsis>
00313          Conditional Goto based on the current time.
00314       </synopsis>
00315       <syntax argsep="?">
00316          <parameter name="condition" required="true">
00317             <argument name="times" required="true" />
00318             <argument name="weekdays" required="true" />
00319             <argument name="mdays" required="true" />
00320             <argument name="months" required="true" />
00321             <argument name="timezone" required="false" />
00322          </parameter>
00323          <parameter name="destination" required="true" argsep=":">
00324             <argument name="labeliftrue">
00325                <para>Continue at <replaceable>labeliftrue</replaceable> if the condition is true.
00326                Takes the form similar to Goto() of [[context,]extension,]priority.</para>
00327             </argument>
00328             <argument name="labeliffalse">
00329                <para>Continue at <replaceable>labeliffalse</replaceable> if the condition is false.
00330                Takes the form similar to Goto() of [[context,]extension,]priority.</para>
00331             </argument>
00332          </parameter>
00333       </syntax>
00334       <description>
00335          <para>This application will set the context, extension, and priority in the channel structure
00336          based on the evaluation of the given time specification. After this application completes,
00337          the pbx engine will continue dialplan execution at the specified location in the dialplan.
00338          If the current time is within the given time specification, the channel will continue at
00339          <replaceable>labeliftrue</replaceable>. Otherwise the channel will continue at <replaceable>labeliffalse</replaceable>.
00340          If the label chosen by the condition is omitted, no jump is performed, and execution passes to the next
00341          instruction. If the target jump location is bogus, the same actions would be taken as for <literal>Goto</literal>.
00342          Further information on the time specification can be found in examples
00343          illustrating how to do time-based context includes in the dialplan.</para>
00344       </description>
00345       <see-also>
00346          <ref type="application">GotoIf</ref>
00347          <ref type="application">Goto</ref>
00348          <ref type="function">IFTIME</ref>
00349          <ref type="function">TESTTIME</ref>
00350       </see-also>
00351    </application>
00352    <application name="ImportVar" language="en_US">
00353       <synopsis>
00354          Import a variable from a channel into a new variable.
00355       </synopsis>
00356       <syntax argsep="=">
00357          <parameter name="newvar" required="true" />
00358          <parameter name="vardata" required="true">
00359             <argument name="channelname" required="true" />
00360             <argument name="variable" required="true" />
00361          </parameter>
00362       </syntax>
00363       <description>
00364          <para>This application imports a <replaceable>variable</replaceable> from the specified
00365          <replaceable>channel</replaceable> (as opposed to the current one) and stores it as a variable
00366          (<replaceable>newvar</replaceable>) in the current channel (the channel that is calling this
00367          application). Variables created by this application have the same inheritance properties as those
00368          created with the <literal>Set</literal> application.</para>
00369       </description>
00370       <see-also>
00371          <ref type="application">Set</ref>
00372       </see-also>
00373    </application>
00374    <application name="Hangup" language="en_US">
00375       <synopsis>
00376          Hang up the calling channel.
00377       </synopsis>
00378       <syntax>
00379          <parameter name="causecode">
00380             <para>If a <replaceable>causecode</replaceable> is given the channel's
00381             hangup cause will be set to the given value.</para>
00382          </parameter>
00383       </syntax>
00384       <description>
00385          <para>This application will hang up the calling channel.</para>
00386       </description>
00387       <see-also>
00388          <ref type="application">Answer</ref>
00389          <ref type="application">Busy</ref>
00390          <ref type="application">Congestion</ref>
00391       </see-also>
00392    </application>
00393    <application name="Incomplete" language="en_US">
00394       <synopsis>
00395          Returns AST_PBX_INCOMPLETE value.
00396       </synopsis>
00397       <syntax>
00398          <parameter name="n">
00399             <para>If specified, then Incomplete will not attempt to answer the channel first.</para>
00400             <note><para>Most channel types need to be in Answer state in order to receive DTMF.</para></note>
00401          </parameter>
00402       </syntax>
00403       <description>
00404          <para>Signals the PBX routines that the previous matched extension is incomplete
00405          and that further input should be allowed before matching can be considered
00406          to be complete.  Can be used within a pattern match when certain criteria warrants
00407          a longer match.</para>
00408       </description>
00409    </application>
00410    <application name="NoOp" language="en_US">
00411       <synopsis>
00412          Do Nothing (No Operation).
00413       </synopsis>
00414       <syntax>
00415          <parameter name="text">
00416             <para>Any text provided can be viewed at the Asterisk CLI.</para>
00417          </parameter>
00418       </syntax>
00419       <description>
00420          <para>This application does nothing. However, it is useful for debugging purposes.</para>
00421          <para>This method can be used to see the evaluations of variables or functions without having any effect.</para>
00422       </description>
00423       <see-also>
00424          <ref type="application">Verbose</ref>
00425          <ref type="application">Log</ref>
00426       </see-also>
00427    </application>
00428    <application name="Proceeding" language="en_US">
00429       <synopsis>
00430          Indicate proceeding.
00431       </synopsis>
00432       <syntax />
00433       <description>
00434          <para>This application will request that a proceeding message be provided to the calling channel.</para>
00435       </description>
00436    </application>
00437    <application name="Progress" language="en_US">
00438       <synopsis>
00439          Indicate progress.
00440       </synopsis>
00441       <syntax />
00442       <description>
00443          <para>This application will request that in-band progress information be provided to the calling channel.</para>
00444       </description>
00445       <see-also>
00446          <ref type="application">Busy</ref>
00447          <ref type="application">Congestion</ref>
00448          <ref type="application">Ringing</ref>
00449          <ref type="application">Playtones</ref>
00450       </see-also>
00451    </application>
00452    <application name="RaiseException" language="en_US">
00453       <synopsis>
00454          Handle an exceptional condition.
00455       </synopsis>
00456       <syntax>
00457          <parameter name="reason" required="true" />
00458       </syntax>
00459       <description>
00460          <para>This application will jump to the <literal>e</literal> extension in the current context, setting the
00461          dialplan function EXCEPTION(). If the <literal>e</literal> extension does not exist, the call will hangup.</para>
00462       </description>
00463       <see-also>
00464          <ref type="function">Exception</ref>
00465       </see-also>
00466    </application>
00467    <application name="Ringing" language="en_US">
00468       <synopsis>
00469          Indicate ringing tone.
00470       </synopsis>
00471       <syntax />
00472       <description>
00473          <para>This application will request that the channel indicate a ringing tone to the user.</para>
00474       </description>
00475       <see-also>
00476          <ref type="application">Busy</ref>
00477          <ref type="application">Congestion</ref>
00478          <ref type="application">Progress</ref>
00479          <ref type="application">Playtones</ref>
00480       </see-also>
00481    </application>
00482    <application name="SayAlpha" language="en_US">
00483       <synopsis>
00484          Say Alpha.
00485       </synopsis>
00486       <syntax>
00487          <parameter name="string" required="true" />
00488       </syntax>
00489       <description>
00490          <para>This application will play the sounds that correspond to the letters
00491          of the given <replaceable>string</replaceable>. If the channel variable
00492          <variable>SAY_DTMF_INTERRUPT</variable> is set to 'true' (case insensitive),
00493          then this application will react to DTMF in the same way as
00494          <literal>Background</literal>.</para>
00495       </description>
00496       <see-also>
00497          <ref type="application">SayDigits</ref>
00498          <ref type="application">SayNumber</ref>
00499          <ref type="application">SayPhonetic</ref>
00500          <ref type="function">CHANNEL</ref>
00501       </see-also>
00502    </application>
00503    <application name="SayAlphaCase" language="en_US">
00504       <synopsis>
00505          Say Alpha.
00506       </synopsis>
00507       <syntax>
00508          <parameter name="casetype" required="true" >
00509             <enumlist>
00510                <enum name="a">
00511                   <para>Case sensitive (all) pronunciation.
00512                   (Ex: SayAlphaCase(a,aBc); - lowercase a uppercase b lowercase c).</para>
00513                </enum>
00514                <enum name="l">
00515                   <para>Case sensitive (lower) pronunciation.
00516                   (Ex: SayAlphaCase(l,aBc); - lowercase a b lowercase c).</para>
00517                </enum>
00518                <enum name="n">
00519                   <para>Case insensitive pronunciation. Equivalent to SayAlpha.
00520                   (Ex: SayAlphaCase(n,aBc) - a b c).</para>
00521                </enum>
00522                <enum name="u">
00523                   <para>Case sensitive (upper) pronunciation.
00524                   (Ex: SayAlphaCase(u,aBc); - a uppercase b c).</para>
00525                </enum>
00526             </enumlist>
00527          </parameter>
00528          <parameter name="string" required="true" />
00529       </syntax>
00530       <description>
00531          <para>This application will play the sounds that correspond to the letters of the
00532          given <replaceable>string</replaceable>.  Optionally, a <replaceable>casetype</replaceable> may be
00533          specified.  This will be used for case-insensitive or case-sensitive pronunciations. If the channel
00534          variable <variable>SAY_DTMF_INTERRUPT</variable> is set to 'true' (case insensitive), then this
00535          application will react to DTMF in the same way as <literal>Background</literal>.</para>
00536       </description>
00537       <see-also>
00538          <ref type="application">SayDigits</ref>
00539          <ref type="application">SayNumber</ref>
00540          <ref type="application">SayPhonetic</ref>
00541          <ref type="application">SayAlpha</ref>
00542          <ref type="function">CHANNEL</ref>
00543       </see-also>
00544    </application>
00545    <application name="SayDigits" language="en_US">
00546       <synopsis>
00547          Say Digits.
00548       </synopsis>
00549       <syntax>
00550          <parameter name="digits" required="true" />
00551       </syntax>
00552       <description>
00553          <para>This application will play the sounds that correspond to the digits of
00554          the given number. This will use the language that is currently set for the channel.
00555          If the channel variable <variable>SAY_DTMF_INTERRUPT</variable> is set to 'true'
00556          (case insensitive), then this application will react to DTMF in the same way as
00557          <literal>Background</literal>.</para>
00558       </description>
00559       <see-also>
00560          <ref type="application">SayAlpha</ref>
00561          <ref type="application">SayNumber</ref>
00562          <ref type="application">SayPhonetic</ref>
00563          <ref type="function">CHANNEL</ref>
00564       </see-also>
00565    </application>
00566    <application name="SayNumber" language="en_US">
00567       <synopsis>
00568          Say Number.
00569       </synopsis>
00570       <syntax>
00571          <parameter name="digits" required="true" />
00572          <parameter name="gender" />
00573       </syntax>
00574       <description>
00575          <para>This application will play the sounds that correspond to the given
00576          <replaceable>digits</replaceable>. Optionally, a <replaceable>gender</replaceable> may be
00577          specified. This will use the language that is currently set for the channel. See the CHANNEL()
00578          function for more information on setting the language for the channel. If the channel variable
00579          <variable>SAY_DTMF_INTERRUPT</variable> is set to 'true' (case insensitive), then this
00580          application will react to DTMF in the same way as <literal>Background</literal>.</para>
00581       </description>
00582       <see-also>
00583          <ref type="application">SayAlpha</ref>
00584          <ref type="application">SayDigits</ref>
00585          <ref type="application">SayPhonetic</ref>
00586          <ref type="function">CHANNEL</ref>
00587       </see-also>
00588    </application>
00589    <application name="SayPhonetic" language="en_US">
00590       <synopsis>
00591          Say Phonetic.
00592       </synopsis>
00593       <syntax>
00594          <parameter name="string" required="true" />
00595       </syntax>
00596       <description>
00597          <para>This application will play the sounds from the phonetic alphabet that correspond to the
00598          letters in the given <replaceable>string</replaceable>. If the channel variable
00599          <variable>SAY_DTMF_INTERRUPT</variable> is set to 'true' (case insensitive), then this
00600          application will react to DTMF in the same way as <literal>Background</literal>.</para>
00601       </description>
00602       <see-also>
00603          <ref type="application">SayAlpha</ref>
00604          <ref type="application">SayDigits</ref>
00605          <ref type="application">SayNumber</ref>
00606       </see-also>
00607    </application>
00608    <application name="Set" language="en_US">
00609       <synopsis>
00610          Set channel variable or function value.
00611       </synopsis>
00612       <syntax argsep="=">
00613          <parameter name="name" required="true" />
00614          <parameter name="value" required="true" />
00615       </syntax>
00616       <description>
00617          <para>This function can be used to set the value of channel variables or dialplan functions.
00618          When setting variables, if the variable name is prefixed with <literal>_</literal>,
00619          the variable will be inherited into channels created from the current channel.
00620          If the variable name is prefixed with <literal>__</literal>, the variable will be
00621          inherited into channels created from the current channel and all children channels.</para>
00622          <note><para>If (and only if), in <filename>/etc/asterisk/asterisk.conf</filename>, you have
00623          a <literal>[compat]</literal> category, and you have <literal>app_set = 1.4</literal> under that, then
00624          the behavior of this app changes, and strips surrounding quotes from the right hand side as
00625          it did previously in 1.4.
00626          The advantages of not stripping out quoting, and not caring about the separator characters (comma and vertical bar)
00627          were sufficient to make these changes in 1.6. Confusion about how many backslashes would be needed to properly
00628          protect separators and quotes in various database access strings has been greatly
00629          reduced by these changes.</para></note>
00630       </description>
00631       <see-also>
00632          <ref type="application">MSet</ref>
00633          <ref type="function">GLOBAL</ref>
00634          <ref type="function">SET</ref>
00635          <ref type="function">ENV</ref>
00636       </see-also>
00637    </application>
00638    <application name="MSet" language="en_US">
00639       <synopsis>
00640          Set channel variable(s) or function value(s).
00641       </synopsis>
00642       <syntax>
00643          <parameter name="set1" required="true" argsep="=">
00644             <argument name="name1" required="true" />
00645             <argument name="value1" required="true" />
00646          </parameter>
00647          <parameter name="set2" multiple="true" argsep="=">
00648             <argument name="name2" required="true" />
00649             <argument name="value2" required="true" />
00650          </parameter>
00651       </syntax>
00652       <description>
00653          <para>This function can be used to set the value of channel variables or dialplan functions.
00654          When setting variables, if the variable name is prefixed with <literal>_</literal>,
00655          the variable will be inherited into channels created from the current channel
00656          If the variable name is prefixed with <literal>__</literal>, the variable will be
00657          inherited into channels created from the current channel and all children channels.
00658          MSet behaves in a similar fashion to the way Set worked in 1.2/1.4 and is thus
00659          prone to doing things that you may not expect. For example, it strips surrounding
00660          double-quotes from the right-hand side (value). If you need to put a separator
00661          character (comma or vert-bar), you will need to escape them by inserting a backslash
00662          before them. Avoid its use if possible.</para>
00663       </description>
00664       <see-also>
00665          <ref type="application">Set</ref>
00666       </see-also>
00667    </application>
00668    <application name="SetAMAFlags" language="en_US">
00669       <synopsis>
00670          Set the AMA Flags.
00671       </synopsis>
00672       <syntax>
00673          <parameter name="flag" />
00674       </syntax>
00675       <description>
00676          <para>This application will set the channel's AMA Flags for billing purposes.</para>
00677          <warning><para>This application is deprecated. Please use the CHANNEL function instead.</para></warning>
00678       </description>
00679       <see-also>
00680          <ref type="function">CDR</ref>
00681          <ref type="function">CHANNEL</ref>
00682       </see-also>
00683    </application>
00684    <application name="Wait" language="en_US">
00685       <synopsis>
00686          Waits for some time.
00687       </synopsis>
00688       <syntax>
00689          <parameter name="seconds" required="true">
00690             <para>Can be passed with fractions of a second. For example, <literal>1.5</literal> will ask the
00691             application to wait for 1.5 seconds.</para>
00692          </parameter>
00693       </syntax>
00694       <description>
00695          <para>This application waits for a specified number of <replaceable>seconds</replaceable>.</para>
00696       </description>
00697    </application>
00698    <application name="WaitExten" language="en_US">
00699       <synopsis>
00700          Waits for an extension to be entered.
00701       </synopsis>
00702       <syntax>
00703          <parameter name="seconds">
00704             <para>Can be passed with fractions of a second. For example, <literal>1.5</literal> will ask the
00705             application to wait for 1.5 seconds.</para>
00706          </parameter>
00707          <parameter name="options">
00708             <optionlist>
00709                <option name="m">
00710                   <para>Provide music on hold to the caller while waiting for an extension.</para>
00711                   <argument name="x">
00712                      <para>Specify the class for music on hold. <emphasis>CHANNEL(musicclass) will
00713                      be used instead if set</emphasis></para>
00714                   </argument>
00715                </option>
00716             </optionlist>
00717          </parameter>
00718       </syntax>
00719       <description>
00720          <para>This application waits for the user to enter a new extension for a specified number
00721          of <replaceable>seconds</replaceable>.</para>
00722          <xi:include xpointer="xpointer(/docs/application[@name='Macro']/description/warning[2])" />
00723       </description>
00724       <see-also>
00725          <ref type="application">Background</ref>
00726          <ref type="function">TIMEOUT</ref>
00727       </see-also>
00728    </application>
00729    <function name="EXCEPTION" language="en_US">
00730       <synopsis>
00731          Retrieve the details of the current dialplan exception.
00732       </synopsis>
00733       <syntax>
00734          <parameter name="field" required="true">
00735             <para>The following fields are available for retrieval:</para>
00736             <enumlist>
00737                <enum name="reason">
00738                   <para>INVALID, ERROR, RESPONSETIMEOUT, ABSOLUTETIMEOUT, or custom
00739                   value set by the RaiseException() application</para>
00740                </enum>
00741                <enum name="context">
00742                   <para>The context executing when the exception occurred.</para>
00743                </enum>
00744                <enum name="exten">
00745                   <para>The extension executing when the exception occurred.</para>
00746                </enum>
00747                <enum name="priority">
00748                   <para>The numeric priority executing when the exception occurred.</para>
00749                </enum>
00750             </enumlist>
00751          </parameter>
00752       </syntax>
00753       <description>
00754          <para>Retrieve the details (specified <replaceable>field</replaceable>) of the current dialplan exception.</para>
00755       </description>
00756       <see-also>
00757          <ref type="application">RaiseException</ref>
00758       </see-also>
00759    </function>
00760    <function name="TESTTIME" language="en_US">
00761       <synopsis>
00762          Sets a time to be used with the channel to test logical conditions.
00763       </synopsis>
00764       <syntax>
00765          <parameter name="date" required="true" argsep=" ">
00766             <para>Date in ISO 8601 format</para>
00767          </parameter>
00768          <parameter name="time" required="true" argsep=" ">
00769             <para>Time in HH:MM:SS format (24-hour time)</para>
00770          </parameter>
00771          <parameter name="zone" required="false">
00772             <para>Timezone name</para>
00773          </parameter>
00774       </syntax>
00775       <description>
00776          <para>To test dialplan timing conditions at times other than the current time, use
00777          this function to set an alternate date and time.  For example, you may wish to evaluate
00778          whether a location will correctly identify to callers that the area is closed on Christmas
00779          Day, when Christmas would otherwise fall on a day when the office is normally open.</para>
00780       </description>
00781       <see-also>
00782          <ref type="application">GotoIfTime</ref>
00783       </see-also>
00784    </function>
00785    <manager name="ShowDialPlan" language="en_US">
00786       <synopsis>
00787          Show dialplan contexts and extensions
00788       </synopsis>
00789       <syntax>
00790          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00791          <parameter name="Extension">
00792             <para>Show a specific extension.</para>
00793          </parameter>
00794          <parameter name="Context">
00795             <para>Show a specific context.</para>
00796          </parameter>
00797       </syntax>
00798       <description>
00799          <para>Show dialplan contexts and extensions. Be aware that showing the full dialplan
00800          may take a lot of capacity.</para>
00801       </description>
00802    </manager>
00803    <manager name="ExtensionStateList" language="en_US">
00804       <synopsis>
00805          List the current known extension states.
00806       </synopsis>
00807       <syntax>
00808          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00809       </syntax>
00810       <description>
00811          <para>This will list out all known extension states in a
00812          sequence of <replaceable>ExtensionStatus</replaceable> events.
00813          When finished, a <replaceable>ExtensionStateListComplete</replaceable> event
00814          will be emitted.</para>
00815       </description>
00816       <see-also>
00817          <ref type="manager">ExtensionState</ref>
00818          <ref type="function">HINT</ref>
00819          <ref type="function">EXTENSION_STATE</ref>
00820       </see-also>
00821       <responses>
00822          <list-elements>
00823             <xi:include xpointer="xpointer(/docs/managerEvent[@name='ExtensionStatus'])" />
00824          </list-elements>
00825          <managerEvent name="ExtensionStateListComplete" language="en_US">
00826             <managerEventInstance class="EVENT_FLAG_COMMAND">
00827                <synopsis>
00828                   Indicates the end of the list the current known extension states.
00829                </synopsis>
00830                <syntax>
00831                   <parameter name="EventList">
00832                      <para>Conveys the status of the event list.</para>
00833                   </parameter>
00834                   <parameter name="ListItems">
00835                      <para>Conveys the number of statuses reported.</para>
00836                   </parameter>
00837                </syntax>
00838             </managerEventInstance>
00839          </managerEvent>
00840       </responses>
00841    </manager>
00842  ***/
00843 
00844 #ifdef LOW_MEMORY
00845 #define EXT_DATA_SIZE 256
00846 #else
00847 #define EXT_DATA_SIZE 8192
00848 #endif
00849 
00850 #define SWITCH_DATA_LENGTH 256
00851 
00852 #define VAR_BUF_SIZE 4096
00853 
00854 #define  VAR_NORMAL     1
00855 #define  VAR_SOFTTRAN   2
00856 #define  VAR_HARDTRAN   3
00857 
00858 #define BACKGROUND_SKIP    (1 << 0)
00859 #define BACKGROUND_NOANSWER   (1 << 1)
00860 #define BACKGROUND_MATCHEXTEN (1 << 2)
00861 #define BACKGROUND_PLAYBACK   (1 << 3)
00862 
00863 AST_APP_OPTIONS(background_opts, {
00864    AST_APP_OPTION('s', BACKGROUND_SKIP),
00865    AST_APP_OPTION('n', BACKGROUND_NOANSWER),
00866    AST_APP_OPTION('m', BACKGROUND_MATCHEXTEN),
00867    AST_APP_OPTION('p', BACKGROUND_PLAYBACK),
00868 });
00869 
00870 #define WAITEXTEN_MOH      (1 << 0)
00871 #define WAITEXTEN_DIALTONE (1 << 1)
00872 
00873 AST_APP_OPTIONS(waitexten_opts, {
00874    AST_APP_OPTION_ARG('m', WAITEXTEN_MOH, 0),
00875    AST_APP_OPTION_ARG('d', WAITEXTEN_DIALTONE, 0),
00876 });
00877 
00878 struct ast_context;
00879 struct ast_app;
00880 
00881 AST_THREADSTORAGE(switch_data);
00882 AST_THREADSTORAGE(extensionstate_buf);
00883 /*!
00884  * \brief A thread local indicating whether the current thread can run
00885  * 'dangerous' dialplan functions.
00886  */
00887 AST_THREADSTORAGE(thread_inhibit_escalations_tl);
00888 
00889 /*!
00890  * \brief Set to true (non-zero) to globally allow all dangerous dialplan
00891  * functions to run.
00892  */
00893 static int live_dangerously;
00894 
00895 /*!
00896    \brief ast_exten: An extension
00897    The dialplan is saved as a linked list with each context
00898    having it's own linked list of extensions - one item per
00899    priority.
00900 */
00901 struct ast_exten {
00902    char *exten;         /*!< Extension name */
00903    int matchcid;        /*!< Match caller id ? */
00904    const char *cidmatch;      /*!< Caller id to match for this extension */
00905    int priority;        /*!< Priority */
00906    const char *label;      /*!< Label */
00907    struct ast_context *parent;   /*!< The context this extension belongs to  */
00908    const char *app;     /*!< Application to execute */
00909    struct ast_app *cached_app;     /*!< Cached location of application */
00910    void *data;       /*!< Data to use (arguments) */
00911    void (*datad)(void *);     /*!< Data destructor */
00912    struct ast_exten *peer;    /*!< Next higher priority with our extension */
00913    struct ast_hashtab *peer_table;    /*!< Priorities list in hashtab form -- only on the head of the peer list */
00914    struct ast_hashtab *peer_label_table; /*!< labeled priorities in the peers -- only on the head of the peer list */
00915    const char *registrar;     /*!< Registrar */
00916    struct ast_exten *next;    /*!< Extension with a greater ID */
00917    char stuff[0];
00918 };
00919 
00920 /*! \brief ast_include: include= support in extensions.conf */
00921 struct ast_include {
00922    const char *name;
00923    const char *rname;         /*!< Context to include */
00924    const char *registrar;        /*!< Registrar */
00925    int hastime;            /*!< If time construct exists */
00926    struct ast_timing timing;               /*!< time construct */
00927    struct ast_include *next;     /*!< Link them together */
00928    char stuff[0];
00929 };
00930 
00931 /*! \brief ast_sw: Switch statement in extensions.conf */
00932 struct ast_sw {
00933    char *name;
00934    const char *registrar;        /*!< Registrar */
00935    char *data;          /*!< Data load */
00936    int eval;
00937    AST_LIST_ENTRY(ast_sw) list;
00938    char stuff[0];
00939 };
00940 
00941 /*! \brief ast_ignorepat: Ignore patterns in dial plan */
00942 struct ast_ignorepat {
00943    const char *registrar;
00944    struct ast_ignorepat *next;
00945    const char pattern[0];
00946 };
00947 
00948 /*! \brief match_char: forms a syntax tree for quick matching of extension patterns */
00949 struct match_char
00950 {
00951    int is_pattern; /* the pattern started with '_' */
00952    int deleted;    /* if this is set, then... don't return it */
00953    int specificity; /* simply the strlen of x, or 10 for X, 9 for Z, and 8 for N; and '.' and '!' will add 11 ? */
00954    struct match_char *alt_char;
00955    struct match_char *next_char;
00956    struct ast_exten *exten; /* attached to last char of a pattern for exten */
00957    char x[1];       /* the pattern itself-- matches a single char */
00958 };
00959 
00960 struct scoreboard  /* make sure all fields are 0 before calling new_find_extension */
00961 {
00962    int total_specificity;
00963    int total_length;
00964    char last_char;   /* set to ! or . if they are the end of the pattern */
00965    int canmatch;     /* if the string to match was just too short */
00966    struct match_char *node;
00967    struct ast_exten *canmatch_exten;
00968    struct ast_exten *exten;
00969 };
00970 
00971 /*! \brief ast_context: An extension context */
00972 struct ast_context {
00973    ast_rwlock_t lock;         /*!< A lock to prevent multiple threads from clobbering the context */
00974    struct ast_exten *root;       /*!< The root of the list of extensions */
00975    struct ast_hashtab *root_table;            /*!< For exact matches on the extensions in the pattern tree, and for traversals of the pattern_tree  */
00976    struct match_char *pattern_tree;        /*!< A tree to speed up extension pattern matching */
00977    struct ast_context *next;     /*!< Link them together */
00978    struct ast_include *includes;    /*!< Include other contexts */
00979    struct ast_ignorepat *ignorepats;   /*!< Patterns for which to continue playing dialtone */
00980    char *registrar;        /*!< Registrar -- make sure you malloc this, as the registrar may have to survive module unloads */
00981    int refcount;                   /*!< each module that would have created this context should inc/dec this as appropriate */
00982    AST_LIST_HEAD_NOLOCK(, ast_sw) alts;   /*!< Alternative switches */
00983    ast_mutex_t macrolock;        /*!< A lock to implement "exclusive" macros - held whilst a call is executing in the macro */
00984    char name[0];           /*!< Name of the context */
00985 };
00986 
00987 /*! \brief ast_app: A registered application */
00988 struct ast_app {
00989    int (*execute)(struct ast_channel *chan, const char *data);
00990    AST_DECLARE_STRING_FIELDS(
00991       AST_STRING_FIELD(synopsis);     /*!< Synopsis text for 'show applications' */
00992       AST_STRING_FIELD(description);  /*!< Description (help text) for 'show application &lt;name&gt;' */
00993       AST_STRING_FIELD(syntax);       /*!< Syntax text for 'core show applications' */
00994       AST_STRING_FIELD(arguments);    /*!< Arguments description */
00995       AST_STRING_FIELD(seealso);      /*!< See also */
00996    );
00997 #ifdef AST_XML_DOCS
00998    enum ast_doc_src docsrc;      /*!< Where the documentation come from. */
00999 #endif
01000    AST_RWLIST_ENTRY(ast_app) list;     /*!< Next app in list */
01001    struct ast_module *module;    /*!< Module this app belongs to */
01002    char name[0];           /*!< Name of the application */
01003 };
01004 
01005 /*! \brief ast_state_cb: An extension state notify register item */
01006 struct ast_state_cb {
01007    /*! Watcher ID returned when registered. */
01008    int id;
01009    /*! Arbitrary data passed for callbacks. */
01010    void *data;
01011    /*! Flag if this callback is an extended callback containing detailed device status */
01012    int extended;
01013    /*! Callback when state changes. */
01014    ast_state_cb_type change_cb;
01015    /*! Callback when destroyed so any resources given by the registerer can be freed. */
01016    ast_state_cb_destroy_type destroy_cb;
01017    /*! \note Only used by ast_merge_contexts_and_delete */
01018    AST_LIST_ENTRY(ast_state_cb) entry;
01019 };
01020 
01021 /*!
01022  * \brief Structure for dial plan hints
01023  *
01024  * \note Hints are pointers from an extension in the dialplan to
01025  * one or more devices (tech/name)
01026  *
01027  * See \ref AstExtState
01028  */
01029 struct ast_hint {
01030    /*!
01031     * \brief Hint extension
01032     *
01033     * \note
01034     * Will never be NULL while the hint is in the hints container.
01035     */
01036    struct ast_exten *exten;
01037    struct ao2_container *callbacks; /*!< Device state callback container for this extension */
01038 
01039    /*! Dev state variables */
01040    int laststate;       /*!< Last known device state */
01041 
01042    /*! Presence state variables */
01043    int last_presence_state;     /*!< Last known presence state */
01044    char *last_presence_subtype; /*!< Last known presence subtype string */
01045    char *last_presence_message; /*!< Last known presence message string */
01046 
01047    char context_name[AST_MAX_CONTEXT];/*!< Context of destroyed hint extension. */
01048    char exten_name[AST_MAX_EXTENSION];/*!< Extension of destroyed hint extension. */
01049 };
01050 
01051 
01052 #define HINTDEVICE_DATA_LENGTH 16
01053 AST_THREADSTORAGE(hintdevice_data);
01054 
01055 /* --- Hash tables of various objects --------*/
01056 #ifdef LOW_MEMORY
01057 #define HASH_EXTENHINT_SIZE 17
01058 #else
01059 #define HASH_EXTENHINT_SIZE 563
01060 #endif
01061 
01062 
01063 /*! \brief Container for hint devices */
01064 static struct ao2_container *hintdevices;
01065 
01066 /*!
01067  * \brief Structure for dial plan hint devices
01068  * \note hintdevice is one device pointing to a hint.
01069  */
01070 struct ast_hintdevice {
01071    /*!
01072     * \brief Hint this hintdevice belongs to.
01073     * \note Holds a reference to the hint object.
01074     */
01075    struct ast_hint *hint;
01076    /*! Name of the hint device. */
01077    char hintdevice[1];
01078 };
01079 
01080 
01081 /*!
01082  * \note Using the device for hash
01083  */
01084 static int hintdevice_hash_cb(const void *obj, const int flags)
01085 {
01086    const struct ast_hintdevice *ext = obj;
01087 
01088    return ast_str_case_hash(ext->hintdevice);
01089 }
01090 /*!
01091  * \note Devices on hints are not unique so no CMP_STOP is returned
01092  * Dont use ao2_find against hintdevices container cause there always
01093  * could be more than one result.
01094  */
01095 static int hintdevice_cmp_multiple(void *obj, void *arg, int flags)
01096 {
01097    struct ast_hintdevice *ext = obj, *ext2 = arg;
01098 
01099    return !strcasecmp(ext->hintdevice, ext2->hintdevice) ? CMP_MATCH  : 0;
01100 }
01101 
01102 /*
01103  * \details This is used with ao2_callback to remove old devices
01104  * when they are linked to the hint
01105 */
01106 static int hintdevice_remove_cb(void *deviceobj, void *arg, int flags)
01107 {
01108    struct ast_hintdevice *device = deviceobj;
01109    struct ast_hint *hint = arg;
01110 
01111    return (device->hint == hint) ? CMP_MATCH : 0;
01112 }
01113 
01114 static int remove_hintdevice(struct ast_hint *hint)
01115 {
01116    /* iterate through all devices and remove the devices which are linked to this hint */
01117    ao2_t_callback(hintdevices, OBJ_NODATA | OBJ_MULTIPLE | OBJ_UNLINK,
01118       hintdevice_remove_cb, hint,
01119       "callback to remove all devices which are linked to a hint");
01120    return 0;
01121 }
01122 
01123 static char *parse_hint_device(struct ast_str *hint_args);
01124 /*!
01125  * \internal
01126  * \brief Destroy the given hintdevice object.
01127  *
01128  * \param obj Hint device to destroy.
01129  *
01130  * \return Nothing
01131  */
01132 static void hintdevice_destroy(void *obj)
01133 {
01134    struct ast_hintdevice *doomed = obj;
01135 
01136    if (doomed->hint) {
01137       ao2_ref(doomed->hint, -1);
01138       doomed->hint = NULL;
01139    }
01140 }
01141 
01142 /*! \brief add hintdevice structure and link it into the container.
01143  */
01144 static int add_hintdevice(struct ast_hint *hint, const char *devicelist)
01145 {
01146    struct ast_str *str;
01147    char *parse;
01148    char *cur;
01149    struct ast_hintdevice *device;
01150    int devicelength;
01151 
01152    if (!hint || !devicelist) {
01153       /* Trying to add garbage? Don't bother. */
01154       return 0;
01155    }
01156    if (!(str = ast_str_thread_get(&hintdevice_data, 16))) {
01157       return -1;
01158    }
01159    ast_str_set(&str, 0, "%s", devicelist);
01160    parse = ast_str_buffer(str);
01161 
01162    /* Spit on '&' and ',' to handle presence hints as well */
01163    while ((cur = strsep(&parse, "&,"))) {
01164       devicelength = strlen(cur);
01165       if (!devicelength) {
01166          continue;
01167       }
01168       device = ao2_t_alloc(sizeof(*device) + devicelength, hintdevice_destroy,
01169          "allocating a hintdevice structure");
01170       if (!device) {
01171          return -1;
01172       }
01173       strcpy(device->hintdevice, cur);
01174       ao2_ref(hint, +1);
01175       device->hint = hint;
01176       ao2_t_link(hintdevices, device, "Linking device into hintdevice container.");
01177       ao2_t_ref(device, -1, "hintdevice is linked so we can unref");
01178    }
01179 
01180    return 0;
01181 }
01182 
01183 
01184 static const struct cfextension_states {
01185    int extension_state;
01186    const char * const text;
01187 } extension_states[] = {
01188    { AST_EXTENSION_NOT_INUSE,                     "Idle" },
01189    { AST_EXTENSION_INUSE,                         "InUse" },
01190    { AST_EXTENSION_BUSY,                          "Busy" },
01191    { AST_EXTENSION_UNAVAILABLE,                   "Unavailable" },
01192    { AST_EXTENSION_RINGING,                       "Ringing" },
01193    { AST_EXTENSION_INUSE | AST_EXTENSION_RINGING, "InUse&Ringing" },
01194    { AST_EXTENSION_ONHOLD,                        "Hold" },
01195    { AST_EXTENSION_INUSE | AST_EXTENSION_ONHOLD,  "InUse&Hold" }
01196 };
01197 
01198 struct pbx_exception {
01199    AST_DECLARE_STRING_FIELDS(
01200       AST_STRING_FIELD(context); /*!< Context associated with this exception */
01201       AST_STRING_FIELD(exten);   /*!< Exten associated with this exception */
01202       AST_STRING_FIELD(reason);     /*!< The exception reason */
01203    );
01204 
01205    int priority;           /*!< Priority associated with this exception */
01206 };
01207 
01208 static int pbx_builtin_answer(struct ast_channel *, const char *);
01209 static int pbx_builtin_goto(struct ast_channel *, const char *);
01210 static int pbx_builtin_hangup(struct ast_channel *, const char *);
01211 static int pbx_builtin_background(struct ast_channel *, const char *);
01212 static int pbx_builtin_wait(struct ast_channel *, const char *);
01213 static int pbx_builtin_waitexten(struct ast_channel *, const char *);
01214 static int pbx_builtin_incomplete(struct ast_channel *, const char *);
01215 static int pbx_builtin_setamaflags(struct ast_channel *, const char *);
01216 static int pbx_builtin_ringing(struct ast_channel *, const char *);
01217 static int pbx_builtin_proceeding(struct ast_channel *, const char *);
01218 static int pbx_builtin_progress(struct ast_channel *, const char *);
01219 static int pbx_builtin_congestion(struct ast_channel *, const char *);
01220 static int pbx_builtin_busy(struct ast_channel *, const char *);
01221 static int pbx_builtin_noop(struct ast_channel *, const char *);
01222 static int pbx_builtin_gotoif(struct ast_channel *, const char *);
01223 static int pbx_builtin_gotoiftime(struct ast_channel *, const char *);
01224 static int pbx_builtin_execiftime(struct ast_channel *, const char *);
01225 static int pbx_builtin_saynumber(struct ast_channel *, const char *);
01226 static int pbx_builtin_saydigits(struct ast_channel *, const char *);
01227 static int pbx_builtin_saycharacters(struct ast_channel *, const char *);
01228 static int pbx_builtin_saycharacters_case(struct ast_channel *, const char *);
01229 static int pbx_builtin_sayphonetic(struct ast_channel *, const char *);
01230 static int matchcid(const char *cidpattern, const char *callerid);
01231 #ifdef NEED_DEBUG
01232 static void log_match_char_tree(struct match_char *node, char *prefix); /* for use anywhere */
01233 #endif
01234 static int pbx_builtin_importvar(struct ast_channel *, const char *);
01235 static void set_ext_pri(struct ast_channel *c, const char *exten, int pri);
01236 static void new_find_extension(const char *str, struct scoreboard *score,
01237       struct match_char *tree, int length, int spec, const char *callerid,
01238       const char *label, enum ext_match_t action);
01239 static struct match_char *already_in_tree(struct match_char *current, char *pat, int is_pattern);
01240 static struct match_char *add_exten_to_pattern_tree(struct ast_context *con,
01241       struct ast_exten *e1, int findonly);
01242 static void create_match_char_tree(struct ast_context *con);
01243 static struct ast_exten *get_canmatch_exten(struct match_char *node);
01244 static void destroy_pattern_tree(struct match_char *pattern_tree);
01245 static int hashtab_compare_extens(const void *ha_a, const void *ah_b);
01246 static int hashtab_compare_exten_numbers(const void *ah_a, const void *ah_b);
01247 static int hashtab_compare_exten_labels(const void *ah_a, const void *ah_b);
01248 static unsigned int hashtab_hash_extens(const void *obj);
01249 static unsigned int hashtab_hash_priority(const void *obj);
01250 static unsigned int hashtab_hash_labels(const void *obj);
01251 static void __ast_internal_context_destroy( struct ast_context *con);
01252 static int ast_add_extension_nolock(const char *context, int replace, const char *extension,
01253    int priority, const char *label, const char *callerid,
01254    const char *application, void *data, void (*datad)(void *), const char *registrar);
01255 static int ast_add_extension2_lockopt(struct ast_context *con,
01256    int replace, const char *extension, int priority, const char *label, const char *callerid,
01257    const char *application, void *data, void (*datad)(void *),
01258    const char *registrar, int lock_context);
01259 static struct ast_context *find_context_locked(const char *context);
01260 static struct ast_context *find_context(const char *context);
01261 static void get_device_state_causing_channels(struct ao2_container *c);
01262 
01263 /*!
01264  * \internal
01265  * \brief Character array comparison function for qsort.
01266  *
01267  * \param a Left side object.
01268  * \param b Right side object.
01269  *
01270  * \retval <0 if a < b
01271  * \retval =0 if a = b
01272  * \retval >0 if a > b
01273  */
01274 static int compare_char(const void *a, const void *b)
01275 {
01276    const unsigned char *ac = a;
01277    const unsigned char *bc = b;
01278 
01279    return *ac - *bc;
01280 }
01281 
01282 /* labels, contexts are case sensitive  priority numbers are ints */
01283 int ast_hashtab_compare_contexts(const void *ah_a, const void *ah_b)
01284 {
01285    const struct ast_context *ac = ah_a;
01286    const struct ast_context *bc = ah_b;
01287    if (!ac || !bc) /* safety valve, but it might prevent a crash you'd rather have happen */
01288       return 1;
01289    /* assume context names are registered in a string table! */
01290    return strcmp(ac->name, bc->name);
01291 }
01292 
01293 static int hashtab_compare_extens(const void *ah_a, const void *ah_b)
01294 {
01295    const struct ast_exten *ac = ah_a;
01296    const struct ast_exten *bc = ah_b;
01297    int x = strcmp(ac->exten, bc->exten);
01298    if (x) { /* if exten names are diff, then return */
01299       return x;
01300    }
01301 
01302    /* but if they are the same, do the cidmatch values match? */
01303    /* not sure which side may be using ast_ext_matchcid_types, so check both */
01304    if (ac->matchcid == AST_EXT_MATCHCID_ANY || bc->matchcid == AST_EXT_MATCHCID_ANY) {
01305       return 0;
01306    }
01307    if (ac->matchcid == AST_EXT_MATCHCID_OFF && bc->matchcid == AST_EXT_MATCHCID_OFF) {
01308       return 0;
01309    }
01310    if (ac->matchcid != bc->matchcid) {
01311       return 1;
01312    }
01313    /* all other cases already disposed of, match now required on callerid string (cidmatch) */
01314    /* although ast_add_extension2_lockopt() enforces non-zero ptr, caller may not have */
01315    if (ast_strlen_zero(ac->cidmatch) && ast_strlen_zero(bc->cidmatch)) {
01316       return 0;
01317    }
01318    return strcmp(ac->cidmatch, bc->cidmatch);
01319 }
01320 
01321 static int hashtab_compare_exten_numbers(const void *ah_a, const void *ah_b)
01322 {
01323    const struct ast_exten *ac = ah_a;
01324    const struct ast_exten *bc = ah_b;
01325    return ac->priority != bc->priority;
01326 }
01327 
01328 static int hashtab_compare_exten_labels(const void *ah_a, const void *ah_b)
01329 {
01330    const struct ast_exten *ac = ah_a;
01331    const struct ast_exten *bc = ah_b;
01332    return strcmp(S_OR(ac->label, ""), S_OR(bc->label, ""));
01333 }
01334 
01335 unsigned int ast_hashtab_hash_contexts(const void *obj)
01336 {
01337    const struct ast_context *ac = obj;
01338    return ast_hashtab_hash_string(ac->name);
01339 }
01340 
01341 static unsigned int hashtab_hash_extens(const void *obj)
01342 {
01343    const struct ast_exten *ac = obj;
01344    unsigned int x = ast_hashtab_hash_string(ac->exten);
01345    unsigned int y = 0;
01346    if (ac->matchcid == AST_EXT_MATCHCID_ON)
01347       y = ast_hashtab_hash_string(ac->cidmatch);
01348    return x+y;
01349 }
01350 
01351 static unsigned int hashtab_hash_priority(const void *obj)
01352 {
01353    const struct ast_exten *ac = obj;
01354    return ast_hashtab_hash_int(ac->priority);
01355 }
01356 
01357 static unsigned int hashtab_hash_labels(const void *obj)
01358 {
01359    const struct ast_exten *ac = obj;
01360    return ast_hashtab_hash_string(S_OR(ac->label, ""));
01361 }
01362 
01363 
01364 AST_RWLOCK_DEFINE_STATIC(globalslock);
01365 static struct varshead globals = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
01366 
01367 static int autofallthrough = 1;
01368 static int extenpatternmatchnew = 0;
01369 static char *overrideswitch = NULL;
01370 
01371 /*! \brief Subscription for device state change events */
01372 static struct stasis_subscription *device_state_sub;
01373 /*! \brief Subscription for presence state change events */
01374 static struct stasis_subscription *presence_state_sub;
01375 
01376 AST_MUTEX_DEFINE_STATIC(maxcalllock);
01377 static int countcalls;
01378 static int totalcalls;
01379 
01380 /*!
01381  * \brief Registered functions container.
01382  *
01383  * It is sorted by function name.
01384  */
01385 static AST_RWLIST_HEAD_STATIC(acf_root, ast_custom_function);
01386 
01387 /*! \brief Declaration of builtin applications */
01388 static struct pbx_builtin {
01389    char name[AST_MAX_APP];
01390    int (*execute)(struct ast_channel *chan, const char *data);
01391 } builtins[] =
01392 {
01393    /* These applications are built into the PBX core and do not
01394       need separate modules */
01395 
01396    { "Answer",         pbx_builtin_answer },
01397    { "BackGround",     pbx_builtin_background },
01398    { "Busy",           pbx_builtin_busy },
01399    { "Congestion",     pbx_builtin_congestion },
01400    { "ExecIfTime",     pbx_builtin_execiftime },
01401    { "Goto",           pbx_builtin_goto },
01402    { "GotoIf",         pbx_builtin_gotoif },
01403    { "GotoIfTime",     pbx_builtin_gotoiftime },
01404    { "ImportVar",      pbx_builtin_importvar },
01405    { "Hangup",         pbx_builtin_hangup },
01406    { "Incomplete",     pbx_builtin_incomplete },
01407    { "NoOp",           pbx_builtin_noop },
01408    { "Proceeding",     pbx_builtin_proceeding },
01409    { "Progress",       pbx_builtin_progress },
01410    { "RaiseException", pbx_builtin_raise_exception },
01411    { "Ringing",        pbx_builtin_ringing },
01412    { "SayAlpha",       pbx_builtin_saycharacters },
01413    { "SayAlphaCase",   pbx_builtin_saycharacters_case },
01414    { "SayDigits",      pbx_builtin_saydigits },
01415    { "SayNumber",      pbx_builtin_saynumber },
01416    { "SayPhonetic",    pbx_builtin_sayphonetic },
01417    { "Set",            pbx_builtin_setvar },
01418    { "MSet",           pbx_builtin_setvar_multiple },
01419    { "SetAMAFlags",    pbx_builtin_setamaflags },
01420    { "Wait",           pbx_builtin_wait },
01421    { "WaitExten",      pbx_builtin_waitexten }
01422 };
01423 
01424 static struct ast_context *contexts;
01425 static struct ast_hashtab *contexts_table = NULL;
01426 
01427 /*!
01428  * \brief Lock for the ast_context list
01429  * \note
01430  * This lock MUST be recursive, or a deadlock on reload may result.  See
01431  * https://issues.asterisk.org/view.php?id=17643
01432  */
01433 AST_MUTEX_DEFINE_STATIC(conlock);
01434 
01435 /*!
01436  * \brief Lock to hold off restructuring of hints by ast_merge_contexts_and_delete.
01437  */
01438 AST_MUTEX_DEFINE_STATIC(context_merge_lock);
01439 
01440 /*!
01441  * \brief Registered applications container.
01442  *
01443  * It is sorted by application name.
01444  */
01445 static AST_RWLIST_HEAD_STATIC(apps, ast_app);
01446 
01447 static AST_RWLIST_HEAD_STATIC(switches, ast_switch);
01448 
01449 static int stateid = 1;
01450 /*!
01451  * \note When holding this container's lock, do _not_ do
01452  * anything that will cause conlock to be taken, unless you
01453  * _already_ hold it.  The ast_merge_contexts_and_delete function
01454  * will take the locks in conlock/hints order, so any other
01455  * paths that require both locks must also take them in that
01456  * order.
01457  */
01458 static struct ao2_container *hints;
01459 
01460 static struct ao2_container *statecbs;
01461 
01462 #ifdef CONTEXT_DEBUG
01463 
01464 /* these routines are provided for doing run-time checks
01465    on the extension structures, in case you are having
01466    problems, this routine might help you localize where
01467    the problem is occurring. It's kinda like a debug memory
01468    allocator's arena checker... It'll eat up your cpu cycles!
01469    but you'll see, if you call it in the right places,
01470    right where your problems began...
01471 */
01472 
01473 /* you can break on the check_contexts_trouble()
01474 routine in your debugger to stop at the moment
01475 there's a problem */
01476 void check_contexts_trouble(void);
01477 
01478 void check_contexts_trouble(void)
01479 {
01480    int x = 1;
01481    x = 2;
01482 }
01483 
01484 int check_contexts(char *, int);
01485 
01486 int check_contexts(char *file, int line )
01487 {
01488    struct ast_hashtab_iter *t1;
01489    struct ast_context *c1, *c2;
01490    int found = 0;
01491    struct ast_exten *e1, *e2, *e3;
01492    struct ast_exten ex;
01493 
01494    /* try to find inconsistencies */
01495    /* is every context in the context table in the context list and vice-versa ? */
01496 
01497    if (!contexts_table) {
01498       ast_log(LOG_NOTICE,"Called from: %s:%d: No contexts_table!\n", file, line);
01499       usleep(500000);
01500    }
01501 
01502    t1 = ast_hashtab_start_traversal(contexts_table);
01503    while( (c1 = ast_hashtab_next(t1))) {
01504       for(c2=contexts;c2;c2=c2->next) {
01505          if (!strcmp(c1->name, c2->name)) {
01506             found = 1;
01507             break;
01508          }
01509       }
01510       if (!found) {
01511          ast_log(LOG_NOTICE,"Called from: %s:%d: Could not find the %s context in the linked list\n", file, line, c1->name);
01512          check_contexts_trouble();
01513       }
01514    }
01515    ast_hashtab_end_traversal(t1);
01516    for(c2=contexts;c2;c2=c2->next) {
01517       c1 = find_context_locked(c2->name);
01518       if (!c1) {
01519          ast_log(LOG_NOTICE,"Called from: %s:%d: Could not find the %s context in the hashtab\n", file, line, c2->name);
01520          check_contexts_trouble();
01521       } else
01522          ast_unlock_contexts();
01523    }
01524 
01525    /* loop thru all contexts, and verify the exten structure compares to the
01526       hashtab structure */
01527    for(c2=contexts;c2;c2=c2->next) {
01528       c1 = find_context_locked(c2->name);
01529       if (c1) {
01530          ast_unlock_contexts();
01531 
01532          /* is every entry in the root list also in the root_table? */
01533          for(e1 = c1->root; e1; e1=e1->next)
01534          {
01535             char dummy_name[1024];
01536             ex.exten = dummy_name;
01537             ex.matchcid = e1->matchcid;
01538             ex.cidmatch = e1->cidmatch;
01539             ast_copy_string(dummy_name, e1->exten, sizeof(dummy_name));
01540             e2 = ast_hashtab_lookup(c1->root_table, &ex);
01541             if (!e2) {
01542                if (e1->matchcid == AST_EXT_MATCHCID_ON) {
01543                   ast_log(LOG_NOTICE,"Called from: %s:%d: The %s context records the exten %s (CID match: %s) but it is not in its root_table\n", file, line, c2->name, dummy_name, e1->cidmatch );
01544                } else {
01545                   ast_log(LOG_NOTICE,"Called from: %s:%d: The %s context records the exten %s but it is not in its root_table\n", file, line, c2->name, dummy_name );
01546                }
01547                check_contexts_trouble();
01548             }
01549          }
01550 
01551          /* is every entry in the root_table also in the root list? */
01552          if (!c2->root_table) {
01553             if (c2->root) {
01554                ast_log(LOG_NOTICE,"Called from: %s:%d: No c2->root_table for context %s!\n", file, line, c2->name);
01555                usleep(500000);
01556             }
01557          } else {
01558             t1 = ast_hashtab_start_traversal(c2->root_table);
01559             while( (e2 = ast_hashtab_next(t1)) ) {
01560                for(e1=c2->root;e1;e1=e1->next) {
01561                   if (!strcmp(e1->exten, e2->exten)) {
01562                      found = 1;
01563                      break;
01564                   }
01565                }
01566                if (!found) {
01567                   ast_log(LOG_NOTICE,"Called from: %s:%d: The %s context records the exten %s but it is not in its root_table\n", file, line, c2->name, e2->exten);
01568                   check_contexts_trouble();
01569                }
01570 
01571             }
01572             ast_hashtab_end_traversal(t1);
01573          }
01574       }
01575       /* is every priority reflected in the peer_table at the head of the list? */
01576 
01577       /* is every entry in the root list also in the root_table? */
01578       /* are the per-extension peer_tables in the right place? */
01579 
01580       for(e1 = c2->root; e1; e1 = e1->next) {
01581 
01582          for(e2=e1;e2;e2=e2->peer) {
01583             ex.priority = e2->priority;
01584             if (e2 != e1 && e2->peer_table) {
01585                ast_log(LOG_NOTICE,"Called from: %s:%d: The %s context, %s exten, %d priority has a peer_table entry, and shouldn't!\n", file, line, c2->name, e1->exten, e2->priority );
01586                check_contexts_trouble();
01587             }
01588 
01589             if (e2 != e1 && e2->peer_label_table) {
01590                ast_log(LOG_NOTICE,"Called from: %s:%d: The %s context, %s exten, %d priority has a peer_label_table entry, and shouldn't!\n", file, line, c2->name, e1->exten, e2->priority );
01591                check_contexts_trouble();
01592             }
01593 
01594             if (e2 == e1 && !e2->peer_table){
01595                ast_log(LOG_NOTICE,"Called from: %s:%d: The %s context, %s exten, %d priority doesn't have a peer_table!\n", file, line, c2->name, e1->exten, e2->priority );
01596                check_contexts_trouble();
01597             }
01598 
01599             if (e2 == e1 && !e2->peer_label_table) {
01600                ast_log(LOG_NOTICE,"Called from: %s:%d: The %s context, %s exten, %d priority doesn't have a peer_label_table!\n", file, line, c2->name, e1->exten, e2->priority );
01601                check_contexts_trouble();
01602             }
01603 
01604 
01605             e3 = ast_hashtab_lookup(e1->peer_table, &ex);
01606             if (!e3) {
01607                ast_log(LOG_NOTICE,"Called from: %s:%d: The %s context, %s exten, %d priority is not reflected in the peer_table\n", file, line, c2->name, e1->exten, e2->priority );
01608                check_contexts_trouble();
01609             }
01610          }
01611 
01612          if (!e1->peer_table){
01613             ast_log(LOG_NOTICE,"Called from: %s:%d: No e1->peer_table!\n", file, line);
01614             usleep(500000);
01615          }
01616 
01617          /* is every entry in the peer_table also in the peer list? */
01618          t1 = ast_hashtab_start_traversal(e1->peer_table);
01619          while( (e2 = ast_hashtab_next(t1)) ) {
01620             for(e3=e1;e3;e3=e3->peer) {
01621                if (e3->priority == e2->priority) {
01622                   found = 1;
01623                   break;
01624                }
01625             }
01626             if (!found) {
01627                ast_log(LOG_NOTICE,"Called from: %s:%d: The %s context, %s exten, %d priority is not reflected in the peer list\n", file, line, c2->name, e1->exten, e2->priority );
01628                check_contexts_trouble();
01629             }
01630          }
01631          ast_hashtab_end_traversal(t1);
01632       }
01633    }
01634    return 0;
01635 }
01636 #endif
01637 
01638 /*
01639    \note This function is special. It saves the stack so that no matter
01640    how many times it is called, it returns to the same place */
01641 int pbx_exec(struct ast_channel *c, /*!< Channel */
01642         struct ast_app *app,  /*!< Application */
01643         const char *data)     /*!< Data for execution */
01644 {
01645    int res;
01646    struct ast_module_user *u = NULL;
01647    const char *saved_c_appl;
01648    const char *saved_c_data;
01649 
01650    /* save channel values */
01651    saved_c_appl= ast_channel_appl(c);
01652    saved_c_data= ast_channel_data(c);
01653 
01654    ast_channel_lock(c);
01655    ast_channel_appl_set(c, app->name);
01656    ast_channel_data_set(c, data);
01657    ast_channel_publish_snapshot(c);
01658    ast_channel_unlock(c);
01659 
01660    if (app->module)
01661       u = __ast_module_user_add(app->module, c);
01662    res = app->execute(c, S_OR(data, ""));
01663    if (app->module && u)
01664       __ast_module_user_remove(app->module, u);
01665    /* restore channel values */
01666    ast_channel_appl_set(c, saved_c_appl);
01667    ast_channel_data_set(c, saved_c_data);
01668    return res;
01669 }
01670 
01671 static struct ast_app *pbx_findapp_nolock(const char *name)
01672 {
01673    struct ast_app *cur;
01674    int cmp;
01675 
01676    AST_RWLIST_TRAVERSE(&apps, cur, list) {
01677       cmp = strcasecmp(name, cur->name);
01678       if (cmp > 0) {
01679          continue;
01680       }
01681       if (!cmp) {
01682          /* Found it. */
01683          break;
01684       }
01685       /* Not in container. */
01686       cur = NULL;
01687       break;
01688    }
01689 
01690    return cur;
01691 }
01692 
01693 struct ast_app *pbx_findapp(const char *app)
01694 {
01695    struct ast_app *ret;
01696 
01697    AST_RWLIST_RDLOCK(&apps);
01698    ret = pbx_findapp_nolock(app);
01699    AST_RWLIST_UNLOCK(&apps);
01700 
01701    return ret;
01702 }
01703 
01704 static struct ast_switch *pbx_findswitch(const char *sw)
01705 {
01706    struct ast_switch *asw;
01707 
01708    AST_RWLIST_RDLOCK(&switches);
01709    AST_RWLIST_TRAVERSE(&switches, asw, list) {
01710       if (!strcasecmp(asw->name, sw))
01711          break;
01712    }
01713    AST_RWLIST_UNLOCK(&switches);
01714 
01715    return asw;
01716 }
01717 
01718 static inline int include_valid(struct ast_include *i)
01719 {
01720    if (!i->hastime)
01721       return 1;
01722 
01723    return ast_check_timing(&(i->timing));
01724 }
01725 
01726 static void pbx_destroy(struct ast_pbx *p)
01727 {
01728    ast_free(p);
01729 }
01730 
01731 /* form a tree that fully describes all the patterns in a context's extensions
01732  * in this tree, a "node" represents an individual character or character set
01733  * meant to match the corresponding character in a dial string. The tree
01734  * consists of a series of match_char structs linked in a chain
01735  * via the alt_char pointers. More than one pattern can share the same parts of the
01736  * tree as other extensions with the same pattern to that point.
01737  * My first attempt to duplicate the finding of the 'best' pattern was flawed in that
01738  * I misunderstood the general algorithm. I thought that the 'best' pattern
01739  * was the one with lowest total score. This was not true. Thus, if you have
01740  * patterns "1XXXXX" and "X11111", you would be tempted to say that "X11111" is
01741  * the "best" match because it has fewer X's, and is therefore more specific,
01742  * but this is not how the old algorithm works. It sorts matching patterns
01743  * in a similar collating sequence as sorting alphabetic strings, from left to
01744  * right. Thus, "1XXXXX" comes before "X11111", and would be the "better" match,
01745  * because "1" is more specific than "X".
01746  * So, to accomodate this philosophy, I sort the tree branches along the alt_char
01747  * line so they are lowest to highest in specificity numbers. This way, as soon
01748  * as we encounter our first complete match, we automatically have the "best"
01749  * match and can stop the traversal immediately. Same for CANMATCH/MATCHMORE.
01750  * If anyone would like to resurrect the "wrong" pattern trie searching algorithm,
01751  * they are welcome to revert pbx to before 1 Apr 2008.
01752  * As an example, consider these 4 extensions:
01753  * (a) NXXNXXXXXX
01754  * (b) 307754XXXX
01755  * (c) fax
01756  * (d) NXXXXXXXXX
01757  *
01758  * In the above, between (a) and (d), (a) is a more specific pattern than (d), and would win over
01759  * most numbers. For all numbers beginning with 307754, (b) should always win.
01760  *
01761  * These pattern should form a (sorted) tree that looks like this:
01762  *   { "3" }  --next-->  { "0" }  --next--> { "7" } --next--> { "7" } --next--> { "5" } ... blah ... --> { "X" exten_match: (b) }
01763  *      |
01764  *      |alt
01765  *      |
01766  *   { "f" }  --next-->  { "a" }  --next--> { "x"  exten_match: (c) }
01767  *   { "N" }  --next-->  { "X" }  --next--> { "X" } --next--> { "N" } --next--> { "X" } ... blah ... --> { "X" exten_match: (a) }
01768  *      |                                                        |
01769  *      |                                                        |alt
01770  *      |alt                                                     |
01771  *      |                                                     { "X" } --next--> { "X" } ... blah ... --> { "X" exten_match: (d) }
01772  *      |
01773  *     NULL
01774  *
01775  *   In the above, I could easily turn "N" into "23456789", but I think that a quick "if( *z >= '2' && *z <= '9' )" might take
01776  *   fewer CPU cycles than a call to strchr("23456789",*z), where *z is the char to match...
01777  *
01778  *   traversal is pretty simple: one routine merely traverses the alt list, and for each matching char in the pattern,  it calls itself
01779  *   on the corresponding next pointer, incrementing also the pointer of the string to be matched, and passing the total specificity and length.
01780  *   We pass a pointer to a scoreboard down through, also.
01781  *   The scoreboard isn't as necessary to the revised algorithm, but I kept it as a handy way to return the matched extension.
01782  *   The first complete match ends the traversal, which should make this version of the pattern matcher faster
01783  *   the previous. The same goes for "CANMATCH" or "MATCHMORE"; the first such match ends the traversal. In both
01784  *   these cases, the reason we can stop immediately, is because the first pattern match found will be the "best"
01785  *   according to the sort criteria.
01786  *   Hope the limit on stack depth won't be a problem... this routine should
01787  *   be pretty lean as far a stack usage goes. Any non-match terminates the recursion down a branch.
01788  *
01789  *   In the above example, with the number "3077549999" as the pattern, the traversor could match extensions a, b and d.  All are
01790  *   of length 10; they have total specificities of  24580, 10246, and 25090, respectively, not that this matters
01791  *   at all. (b) wins purely because the first character "3" is much more specific (lower specificity) than "N". I have
01792  *   left the specificity totals in the code as an artifact; at some point, I will strip it out.
01793  *
01794  *   Just how much time this algorithm might save over a plain linear traversal over all possible patterns is unknown,
01795  *   because it's a function of how many extensions are stored in a context. With thousands of extensions, the speedup
01796  *   can be very noticeable. The new matching algorithm can run several hundreds of times faster, if not a thousand or
01797  *   more times faster in extreme cases.
01798  *
01799  *   MatchCID patterns are also supported, and stored in the tree just as the extension pattern is. Thus, you
01800  *   can have patterns in your CID field as well.
01801  *
01802  * */
01803 
01804 
01805 static void update_scoreboard(struct scoreboard *board, int length, int spec, struct ast_exten *exten, char last, const char *callerid, int deleted, struct match_char *node)
01806 {
01807    /* if this extension is marked as deleted, then skip this -- if it never shows
01808       on the scoreboard, it will never be found, nor will halt the traversal. */
01809    if (deleted)
01810       return;
01811    board->total_specificity = spec;
01812    board->total_length = length;
01813    board->exten = exten;
01814    board->last_char = last;
01815    board->node = node;
01816 #ifdef NEED_DEBUG_HERE
01817    ast_log(LOG_NOTICE,"Scoreboarding (LONGER) %s, len=%d, score=%d\n", exten->exten, length, spec);
01818 #endif
01819 }
01820 
01821 #ifdef NEED_DEBUG
01822 static void log_match_char_tree(struct match_char *node, char *prefix)
01823 {
01824    char extenstr[40];
01825    struct ast_str *my_prefix = ast_str_alloca(1024);
01826 
01827    extenstr[0] = '\0';
01828 
01829    if (node && node->exten)
01830       snprintf(extenstr, sizeof(extenstr), "(%p)", node->exten);
01831 
01832    if (strlen(node->x) > 1) {
01833       ast_debug(1, "%s[%s]:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y':'N',
01834          node->deleted? 'D':'-', node->specificity, node->exten? "EXTEN:":"",
01835          node->exten ? node->exten->exten : "", extenstr);
01836    } else {
01837       ast_debug(1, "%s%s:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y':'N',
01838          node->deleted? 'D':'-', node->specificity, node->exten? "EXTEN:":"",
01839          node->exten ? node->exten->exten : "", extenstr);
01840    }
01841 
01842    ast_str_set(&my_prefix, 0, "%s+       ", prefix);
01843 
01844    if (node->next_char)
01845       log_match_char_tree(node->next_char, ast_str_buffer(my_prefix));
01846 
01847    if (node->alt_char)
01848       log_match_char_tree(node->alt_char, prefix);
01849 }
01850 #endif
01851 
01852 static void cli_match_char_tree(struct match_char *node, char *prefix, int fd)
01853 {
01854    char extenstr[40];
01855    struct ast_str *my_prefix = ast_str_alloca(1024);
01856 
01857    extenstr[0] = '\0';
01858 
01859    if (node->exten) {
01860       snprintf(extenstr, sizeof(extenstr), "(%p)", node->exten);
01861    }
01862 
01863    if (strlen(node->x) > 1) {
01864       ast_cli(fd, "%s[%s]:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y' : 'N',
01865          node->deleted ? 'D' : '-', node->specificity, node->exten? "EXTEN:" : "",
01866          node->exten ? node->exten->exten : "", extenstr);
01867    } else {
01868       ast_cli(fd, "%s%s:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y' : 'N',
01869          node->deleted ? 'D' : '-', node->specificity, node->exten? "EXTEN:" : "",
01870          node->exten ? node->exten->exten : "", extenstr);
01871    }
01872 
01873    ast_str_set(&my_prefix, 0, "%s+       ", prefix);
01874 
01875    if (node->next_char)
01876       cli_match_char_tree(node->next_char, ast_str_buffer(my_prefix), fd);
01877 
01878    if (node->alt_char)
01879       cli_match_char_tree(node->alt_char, prefix, fd);
01880 }
01881 
01882 static struct ast_exten *get_canmatch_exten(struct match_char *node)
01883 {
01884    /* find the exten at the end of the rope */
01885    struct match_char *node2 = node;
01886 
01887    for (node2 = node; node2; node2 = node2->next_char) {
01888       if (node2->exten) {
01889 #ifdef NEED_DEBUG_HERE
01890          ast_log(LOG_NOTICE,"CanMatch_exten returns exten %s(%p)\n", node2->exten->exten, node2->exten);
01891 #endif
01892          return node2->exten;
01893       }
01894    }
01895 #ifdef NEED_DEBUG_HERE
01896    ast_log(LOG_NOTICE,"CanMatch_exten returns NULL, match_char=%s\n", node->x);
01897 #endif
01898    return 0;
01899 }
01900 
01901 static struct ast_exten *trie_find_next_match(struct match_char *node)
01902 {
01903    struct match_char *m3;
01904    struct match_char *m4;
01905    struct ast_exten *e3;
01906 
01907    if (node && node->x[0] == '.' && !node->x[1]) { /* dot and ! will ALWAYS be next match in a matchmore */
01908       return node->exten;
01909    }
01910 
01911    if (node && node->x[0] == '!' && !node->x[1]) {
01912       return node->exten;
01913    }
01914 
01915    if (!node || !node->next_char) {
01916       return NULL;
01917    }
01918 
01919    m3 = node->next_char;
01920 
01921    if (m3->exten) {
01922       return m3->exten;
01923    }
01924    for (m4 = m3->alt_char; m4; m4 = m4->alt_char) {
01925       if (m4->exten) {
01926          return m4->exten;
01927       }
01928    }
01929    for (m4 = m3; m4; m4 = m4->alt_char) {
01930       e3 = trie_find_next_match(m3);
01931       if (e3) {
01932          return e3;
01933       }
01934    }
01935 
01936    return NULL;
01937 }
01938 
01939 #ifdef DEBUG_THIS
01940 static char *action2str(enum ext_match_t action)
01941 {
01942    switch (action) {
01943    case E_MATCH:
01944       return "MATCH";
01945    case E_CANMATCH:
01946       return "CANMATCH";
01947    case E_MATCHMORE:
01948       return "MATCHMORE";
01949    case E_FINDLABEL:
01950       return "FINDLABEL";
01951    case E_SPAWN:
01952       return "SPAWN";
01953    default:
01954       return "?ACTION?";
01955    }
01956 }
01957 
01958 #endif
01959 
01960 static void new_find_extension(const char *str, struct scoreboard *score, struct match_char *tree, int length, int spec, const char *callerid, const char *label, enum ext_match_t action)
01961 {
01962    struct match_char *p; /* note minimal stack storage requirements */
01963    struct ast_exten pattern = { .label = label };
01964 #ifdef DEBUG_THIS
01965    if (tree)
01966       ast_log(LOG_NOTICE,"new_find_extension called with %s on (sub)tree %s action=%s\n", str, tree->x, action2str(action));
01967    else
01968       ast_log(LOG_NOTICE,"new_find_extension called with %s on (sub)tree NULL action=%s\n", str, action2str(action));
01969 #endif
01970    for (p = tree; p; p = p->alt_char) {
01971       if (p->is_pattern) {
01972          if (p->x[0] == 'N') {
01973             if (p->x[1] == 0 && *str >= '2' && *str <= '9' ) {
01974 #define  NEW_MATCHER_CHK_MATCH          \
01975                if (p->exten && !(*(str + 1))) { /* if a shorter pattern matches along the way, might as well report it */             \
01976                   if (action == E_MATCH || action == E_SPAWN || action == E_FINDLABEL) { /* if in CANMATCH/MATCHMORE, don't let matches get in the way */   \
01977                      update_scoreboard(score, length + 1, spec + p->specificity, p->exten, 0, callerid, p->deleted, p);                 \
01978                      if (!p->deleted) {                                                                                           \
01979                         if (action == E_FINDLABEL) {                                                                             \
01980                            if (ast_hashtab_lookup(score->exten->peer_label_table, &pattern)) {                                  \
01981                               ast_debug(4, "Found label in preferred extension\n");                                            \
01982                               return;                                                                                          \
01983                            }                                                                                                    \
01984                         } else {                                                                                                 \
01985                            ast_debug(4, "returning an exact match-- first found-- %s\n", p->exten->exten);                       \
01986                            return; /* the first match, by definition, will be the best, because of the sorted tree */           \
01987                         }                                                                                                        \
01988                      }                                                                                                            \
01989                   }                                                                                                                \
01990                }
01991 
01992 #define  NEW_MATCHER_RECURSE             \
01993                if (p->next_char && (*(str + 1) || (p->next_char->x[0] == '/' && p->next_char->x[1] == 0)                 \
01994                                              || p->next_char->x[0] == '!')) {                                          \
01995                   if (*(str + 1) || p->next_char->x[0] == '!') {                                                         \
01996                      new_find_extension(str + 1, score, p->next_char, length + 1, spec + p->specificity, callerid, label, action); \
01997                      if (score->exten)  {                                                                             \
01998                           ast_debug(4 ,"returning an exact match-- %s\n", score->exten->exten);                         \
01999                         return; /* the first match is all we need */                                                 \
02000                      }                                                                                    \
02001                   } else {                                                                                             \
02002                      new_find_extension("/", score, p->next_char, length + 1, spec + p->specificity, callerid, label, action);    \
02003                      if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) {      \
02004                           ast_debug(4,"returning a (can/more) match--- %s\n", score->exten ? score->exten->exten :     \
02005                                      "NULL");                                                                        \
02006                         return; /* the first match is all we need */                                                 \
02007                      }                                                                                    \
02008                   }                                                                                                    \
02009                } else if ((p->next_char || action == E_CANMATCH) && !*(str + 1)) {                                                                  \
02010                   score->canmatch = 1;                                                                                 \
02011                   score->canmatch_exten = get_canmatch_exten(p);                                                       \
02012                   if (action == E_CANMATCH || action == E_MATCHMORE) {                                                 \
02013                        ast_debug(4, "returning a canmatch/matchmore--- str=%s\n", str);                                  \
02014                      return;                                                                                          \
02015                   }                                                                                        \
02016                }
02017 
02018                NEW_MATCHER_CHK_MATCH;
02019                NEW_MATCHER_RECURSE;
02020             }
02021          } else if (p->x[0] == 'Z') {
02022             if (p->x[1] == 0 && *str >= '1' && *str <= '9' ) {
02023                NEW_MATCHER_CHK_MATCH;
02024                NEW_MATCHER_RECURSE;
02025             }
02026          } else if (p->x[0] == 'X') {
02027             if (p->x[1] == 0 && *str >= '0' && *str <= '9' ) {
02028                NEW_MATCHER_CHK_MATCH;
02029                NEW_MATCHER_RECURSE;
02030             }
02031          } else if (p->x[0] == '.' && p->x[1] == 0) {
02032             /* how many chars will the . match against? */
02033             int i = 0;
02034             const char *str2 = str;
02035             while (*str2 && *str2 != '/') {
02036                str2++;
02037                i++;
02038             }
02039             if (p->exten && *str2 != '/') {
02040                update_scoreboard(score, length + i, spec + (i * p->specificity), p->exten, '.', callerid, p->deleted, p);
02041                if (score->exten) {
02042                   ast_debug(4,"return because scoreboard has a match with '/'--- %s\n", score->exten->exten);
02043                   return; /* the first match is all we need */
02044                }
02045             }
02046             if (p->next_char && p->next_char->x[0] == '/' && p->next_char->x[1] == 0) {
02047                new_find_extension("/", score, p->next_char, length + i, spec+(p->specificity*i), callerid, label, action);
02048                if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) {
02049                   ast_debug(4, "return because scoreboard has exact match OR CANMATCH/MATCHMORE & canmatch set--- %s\n", score->exten ? score->exten->exten : "NULL");
02050                   return; /* the first match is all we need */
02051                }
02052             }
02053          } else if (p->x[0] == '!' && p->x[1] == 0) {
02054             /* how many chars will the . match against? */
02055             int i = 1;
02056             const char *str2 = str;
02057             while (*str2 && *str2 != '/') {
02058                str2++;
02059                i++;
02060             }
02061             if (p->exten && *str2 != '/') {
02062                update_scoreboard(score, length + 1, spec + (p->specificity * i), p->exten, '!', callerid, p->deleted, p);
02063                if (score->exten) {
02064                   ast_debug(4, "return because scoreboard has a '!' match--- %s\n", score->exten->exten);
02065                   return; /* the first match is all we need */
02066                }
02067             }
02068             if (p->next_char && p->next_char->x[0] == '/' && p->next_char->x[1] == 0) {
02069                new_find_extension("/", score, p->next_char, length + i, spec + (p->specificity * i), callerid, label, action);
02070                if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) {
02071                   ast_debug(4, "return because scoreboard has exact match OR CANMATCH/MATCHMORE & canmatch set with '/' and '!'--- %s\n", score->exten ? score->exten->exten : "NULL");
02072                   return; /* the first match is all we need */
02073                }
02074             }
02075          } else if (p->x[0] == '/' && p->x[1] == 0) {
02076             /* the pattern in the tree includes the cid match! */
02077             if (p->next_char && callerid && *callerid) {
02078                new_find_extension(callerid, score, p->next_char, length + 1, spec, callerid, label, action);
02079                if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) {
02080                   ast_debug(4, "return because scoreboard has exact match OR CANMATCH/MATCHMORE & canmatch set with '/'--- %s\n", score->exten ? score->exten->exten : "NULL");
02081                   return; /* the first match is all we need */
02082                }
02083             }
02084          } else if (strchr(p->x, *str)) {
02085             ast_debug(4, "Nothing strange about this match\n");
02086             NEW_MATCHER_CHK_MATCH;
02087             NEW_MATCHER_RECURSE;
02088          }
02089       } else if (strchr(p->x, *str)) {
02090          ast_debug(4, "Nothing strange about this match\n");
02091          NEW_MATCHER_CHK_MATCH;
02092          NEW_MATCHER_RECURSE;
02093       }
02094    }
02095    ast_debug(4, "return at end of func\n");
02096 }
02097 
02098 /* the algorithm for forming the extension pattern tree is also a bit simple; you
02099  * traverse all the extensions in a context, and for each char of the extension,
02100  * you see if it exists in the tree; if it doesn't, you add it at the appropriate
02101  * spot. What more can I say? At the end of each exten, you cap it off by adding the
02102  * address of the extension involved. Duplicate patterns will be complained about.
02103  *
02104  * Ideally, this would be done for each context after it is created and fully
02105  * filled. It could be done as a finishing step after extensions.conf or .ael is
02106  * loaded, or it could be done when the first search is encountered. It should only
02107  * have to be done once, until the next unload or reload.
02108  *
02109  * I guess forming this pattern tree would be analogous to compiling a regex. Except
02110  * that a regex only handles 1 pattern, really. This trie holds any number
02111  * of patterns. Well, really, it **could** be considered a single pattern,
02112  * where the "|" (or) operator is allowed, I guess, in a way, sort of...
02113  */
02114 
02115 static struct match_char *already_in_tree(struct match_char *current, char *pat, int is_pattern)
02116 {
02117    struct match_char *t;
02118 
02119    if (!current) {
02120       return 0;
02121    }
02122 
02123    for (t = current; t; t = t->alt_char) {
02124       if (is_pattern == t->is_pattern && !strcmp(pat, t->x)) {/* uh, we may want to sort exploded [] contents to make matching easy */
02125          return t;
02126       }
02127    }
02128 
02129    return 0;
02130 }
02131 
02132 /* The first arg is the location of the tree ptr, or the
02133    address of the next_char ptr in the node, so we can mess
02134    with it, if we need to insert at the beginning of the list */
02135 
02136 static void insert_in_next_chars_alt_char_list(struct match_char **parent_ptr, struct match_char *node)
02137 {
02138    struct match_char *curr, *lcurr;
02139 
02140    /* insert node into the tree at "current", so the alt_char list from current is
02141       sorted in increasing value as you go to the leaves */
02142    if (!(*parent_ptr)) {
02143       *parent_ptr = node;
02144       return;
02145    }
02146 
02147    if ((*parent_ptr)->specificity > node->specificity) {
02148       /* insert at head */
02149       node->alt_char = (*parent_ptr);
02150       *parent_ptr = node;
02151       return;
02152    }
02153 
02154    lcurr = *parent_ptr;
02155    for (curr = (*parent_ptr)->alt_char; curr; curr = curr->alt_char) {
02156       if (curr->specificity > node->specificity) {
02157          node->alt_char = curr;
02158          lcurr->alt_char = node;
02159          break;
02160       }
02161       lcurr = curr;
02162    }
02163 
02164    if (!curr) {
02165       lcurr->alt_char = node;
02166    }
02167 
02168 }
02169 
02170 struct pattern_node {
02171    /*! Pattern node specificity */
02172    int specif;
02173    /*! Pattern node match characters. */
02174    char buf[256];
02175 };
02176 
02177 static struct match_char *add_pattern_node(struct ast_context *con, struct match_char *current, const struct pattern_node *pattern, int is_pattern, int already, struct match_char **nextcharptr)
02178 {
02179    struct match_char *m;
02180 
02181    if (!(m = ast_calloc(1, sizeof(*m) + strlen(pattern->buf)))) {
02182       return NULL;
02183    }
02184 
02185    /* strcpy is safe here since we know its size and have allocated
02186     * just enough space for when we allocated m
02187     */
02188    strcpy(m->x, pattern->buf);
02189 
02190    /* the specificity scores are the same as used in the old
02191       pattern matcher. */
02192    m->is_pattern = is_pattern;
02193    if (pattern->specif == 1 && is_pattern && pattern->buf[0] == 'N') {
02194       m->specificity = 0x0832;
02195    } else if (pattern->specif == 1 && is_pattern && pattern->buf[0] == 'Z') {
02196       m->specificity = 0x0931;
02197    } else if (pattern->specif == 1 && is_pattern && pattern->buf[0] == 'X') {
02198       m->specificity = 0x0a30;
02199    } else if (pattern->specif == 1 && is_pattern && pattern->buf[0] == '.') {
02200       m->specificity = 0x18000;
02201    } else if (pattern->specif == 1 && is_pattern && pattern->buf[0] == '!') {
02202       m->specificity = 0x28000;
02203    } else {
02204       m->specificity = pattern->specif;
02205    }
02206 
02207    if (!con->pattern_tree) {
02208       insert_in_next_chars_alt_char_list(&con->pattern_tree, m);
02209    } else {
02210       if (already) { /* switch to the new regime (traversing vs appending)*/
02211          insert_in_next_chars_alt_char_list(nextcharptr, m);
02212       } else {
02213          insert_in_next_chars_alt_char_list(&current->next_char, m);
02214       }
02215    }
02216 
02217    return m;
02218 }
02219 
02220 /*!
02221  * \internal
02222  * \brief Extract the next exten pattern node.
02223  *
02224  * \param node Pattern node to fill.
02225  * \param src Next source character to read.
02226  * \param pattern TRUE if the exten is a pattern.
02227  * \param extenbuf Original exten buffer to use in diagnostic messages.
02228  *
02229  * \retval Ptr to next extenbuf pos to read.
02230  */
02231 static const char *get_pattern_node(struct pattern_node *node, const char *src, int pattern, const char *extenbuf)
02232 {
02233 #define INC_DST_OVERFLOW_CHECK                     \
02234    do {                                   \
02235       if (dst - node->buf < sizeof(node->buf) - 1) {  \
02236          ++dst;                              \
02237       } else {                            \
02238          overflow = 1;                       \
02239       }                                   \
02240    } while (0)
02241 
02242    node->specif = 0;
02243    node->buf[0] = '\0';
02244    while (*src) {
02245       if (*src == '[' && pattern) {
02246          char *dst = node->buf;
02247          const char *src_next;
02248          int length;
02249          int overflow = 0;
02250 
02251          /* get past the '[' */
02252          ++src;
02253          for (;;) {
02254             if (*src == '\\') {
02255                /* Escaped character. */
02256                ++src;
02257                if (*src == '[' || *src == '\\' || *src == '-' || *src == ']') {
02258                   *dst = *src++;
02259                   INC_DST_OVERFLOW_CHECK;
02260                }
02261             } else if (*src == '-') {
02262                unsigned char first;
02263                unsigned char last;
02264 
02265                src_next = src;
02266                first = *(src_next - 1);
02267                last = *++src_next;
02268 
02269                if (last == '\\') {
02270                   /* Escaped character. */
02271                   last = *++src_next;
02272                }
02273 
02274                /* Possible char range. */
02275                if (node->buf[0] && last) {
02276                   /* Expand the char range. */
02277                   while (++first <= last) {
02278                      *dst = first;
02279                      INC_DST_OVERFLOW_CHECK;
02280                   }
02281                   src = src_next + 1;
02282                } else {
02283                   /*
02284                    * There was no left or right char for the range.
02285                    * It is just a '-'.
02286                    */
02287                   *dst = *src++;
02288                   INC_DST_OVERFLOW_CHECK;
02289                }
02290             } else if (*src == '\0') {
02291                ast_log(LOG_WARNING,
02292                   "A matching ']' was not found for '[' in exten pattern '%s'\n",
02293                   extenbuf);
02294                break;
02295             } else if (*src == ']') {
02296                ++src;
02297                break;
02298             } else {
02299                *dst = *src++;
02300                INC_DST_OVERFLOW_CHECK;
02301             }
02302          }
02303          /* null terminate the exploded range */
02304          *dst = '\0';
02305 
02306          if (overflow) {
02307             ast_log(LOG_ERROR,
02308                "Expanded character set too large to deal with in exten pattern '%s'. Ignoring character set.\n",
02309                extenbuf);
02310             node->buf[0] = '\0';
02311             continue;
02312          }
02313 
02314          /* Sort the characters in character set. */
02315          length = strlen(node->buf);
02316          if (!length) {
02317             ast_log(LOG_WARNING, "Empty character set in exten pattern '%s'. Ignoring.\n",
02318                extenbuf);
02319             node->buf[0] = '\0';
02320             continue;
02321          }
02322          qsort(node->buf, length, 1, compare_char);
02323 
02324          /* Remove duplicate characters from character set. */
02325          dst = node->buf;
02326          src_next = node->buf;
02327          while (*src_next++) {
02328             if (*dst != *src_next) {
02329                *++dst = *src_next;
02330             }
02331          }
02332 
02333          length = strlen(node->buf);
02334          length <<= 8;
02335          node->specif = length | (unsigned char) node->buf[0];
02336          break;
02337       } else if (*src == '-') {
02338          /* Skip dashes in all extensions. */
02339          ++src;
02340       } else {
02341          if (*src == '\\') {
02342             /*
02343              * XXX The escape character here does not remove any special
02344              * meaning to characters except the '[', '\\', and '-'
02345              * characters since they are special only in this function.
02346              */
02347             node->buf[0] = *++src;
02348             if (!node->buf[0]) {
02349                break;
02350             }
02351          } else {
02352             node->buf[0] = *src;
02353             if (pattern) {
02354                /* make sure n,x,z patterns are canonicalized to N,X,Z */
02355                if (node->buf[0] == 'n') {
02356                   node->buf[0] = 'N';
02357                } else if (node->buf[0] == 'x') {
02358                   node->buf[0] = 'X';
02359                } else if (node->buf[0] == 'z') {
02360                   node->buf[0] = 'Z';
02361                }
02362             }
02363          }
02364          node->buf[1] = '\0';
02365          node->specif = 1;
02366          ++src;
02367          break;
02368       }
02369    }
02370    return src;
02371 
02372 #undef INC_DST_OVERFLOW_CHECK
02373 }
02374 
02375 static struct match_char *add_exten_to_pattern_tree(struct ast_context *con, struct ast_exten *e1, int findonly)
02376 {
02377    struct match_char *m1 = NULL;
02378    struct match_char *m2 = NULL;
02379    struct match_char **m0;
02380    const char *pos;
02381    int already;
02382    int pattern = 0;
02383    int idx_cur;
02384    int idx_next;
02385    char extenbuf[512];
02386    struct pattern_node pat_node[2];
02387 
02388    if (e1->matchcid) {
02389       if (sizeof(extenbuf) < strlen(e1->exten) + strlen(e1->cidmatch) + 2) {
02390          ast_log(LOG_ERROR,
02391             "The pattern %s/%s is too big to deal with: it will be ignored! Disaster!\n",
02392             e1->exten, e1->cidmatch);
02393          return NULL;
02394       }
02395       sprintf(extenbuf, "%s/%s", e1->exten, e1->cidmatch);/* Safe.  We just checked. */
02396    } else {
02397       ast_copy_string(extenbuf, e1->exten, sizeof(extenbuf));
02398    }
02399 
02400 #ifdef NEED_DEBUG
02401    ast_debug(1, "Adding exten %s to tree\n", extenbuf);
02402 #endif
02403    m1 = con->pattern_tree; /* each pattern starts over at the root of the pattern tree */
02404    m0 = &con->pattern_tree;
02405    already = 1;
02406 
02407    pos = extenbuf;
02408    if (*pos == '_') {
02409       pattern = 1;
02410       ++pos;
02411    }
02412    idx_cur = 0;
02413    pos = get_pattern_node(&pat_node[idx_cur], pos, pattern, extenbuf);
02414    for (; pat_node[idx_cur].buf[0]; idx_cur = idx_next) {
02415       idx_next = (idx_cur + 1) % ARRAY_LEN(pat_node);
02416       pos = get_pattern_node(&pat_node[idx_next], pos, pattern, extenbuf);
02417 
02418       /* See about adding node to tree. */
02419       m2 = NULL;
02420       if (already && (m2 = already_in_tree(m1, pat_node[idx_cur].buf, pattern))
02421          && m2->next_char) {
02422          if (!pat_node[idx_next].buf[0]) {
02423             /*
02424              * This is the end of the pattern, but not the end of the tree.
02425              * Mark this node with the exten... a shorter pattern might win
02426              * if the longer one doesn't match.
02427              */
02428             if (findonly) {
02429                return m2;
02430             }
02431             if (m2->exten) {
02432                ast_log(LOG_WARNING, "Found duplicate exten. Had %s found %s\n",
02433                   m2->deleted ? "(deleted/invalid)" : m2->exten->exten, e1->exten);
02434             }
02435             m2->exten = e1;
02436             m2->deleted = 0;
02437          }
02438          m1 = m2->next_char; /* m1 points to the node to compare against */
02439          m0 = &m2->next_char; /* m0 points to the ptr that points to m1 */
02440       } else { /* not already OR not m2 OR nor m2->next_char */
02441          if (m2) {
02442             if (findonly) {
02443                return m2;
02444             }
02445             m1 = m2; /* while m0 stays the same */
02446          } else {
02447             if (findonly) {
02448                return m1;
02449             }
02450             m1 = add_pattern_node(con, m1, &pat_node[idx_cur], pattern, already, m0);
02451             if (!m1) { /* m1 is the node just added */
02452                return NULL;
02453             }
02454             m0 = &m1->next_char;
02455          }
02456          if (!pat_node[idx_next].buf[0]) {
02457             if (m2 && m2->exten) {
02458                ast_log(LOG_WARNING, "Found duplicate exten. Had %s found %s\n",
02459                   m2->deleted ? "(deleted/invalid)" : m2->exten->exten, e1->exten);
02460             }
02461             m1->deleted = 0;
02462             m1->exten = e1;
02463          }
02464 
02465          /* The 'already' variable is a mini-optimization designed to make it so that we
02466           * don't have to call already_in_tree when we know it will return false.
02467           */
02468          already = 0;
02469       }
02470    }
02471    return m1;
02472 }
02473 
02474 static void create_match_char_tree(struct ast_context *con)
02475 {
02476    struct ast_hashtab_iter *t1;
02477    struct ast_exten *e1;
02478 #ifdef NEED_DEBUG
02479    int biggest_bucket, resizes, numobjs, numbucks;
02480 
02481    ast_debug(1, "Creating Extension Trie for context %s(%p)\n", con->name, con);
02482    ast_hashtab_get_stats(con->root_table, &biggest_bucket, &resizes, &numobjs, &numbucks);
02483    ast_debug(1, "This tree has %d objects in %d bucket lists, longest list=%d objects, and has resized %d times\n",
02484          numobjs, numbucks, biggest_bucket, resizes);
02485 #endif
02486    t1 = ast_hashtab_start_traversal(con->root_table);
02487    while ((e1 = ast_hashtab_next(t1))) {
02488       if (e1->exten) {
02489          add_exten_to_pattern_tree(con, e1, 0);
02490       } else {
02491          ast_log(LOG_ERROR, "Attempt to create extension with no extension name.\n");
02492       }
02493    }
02494    ast_hashtab_end_traversal(t1);
02495 }
02496 
02497 static void destroy_pattern_tree(struct match_char *pattern_tree) /* pattern tree is a simple binary tree, sort of, so the proper way to destroy it is... recursively! */
02498 {
02499    /* destroy all the alternates */
02500    if (pattern_tree->alt_char) {
02501       destroy_pattern_tree(pattern_tree->alt_char);
02502       pattern_tree->alt_char = 0;
02503    }
02504    /* destroy all the nexts */
02505    if (pattern_tree->next_char) {
02506       destroy_pattern_tree(pattern_tree->next_char);
02507       pattern_tree->next_char = 0;
02508    }
02509    pattern_tree->exten = 0; /* never hurts to make sure there's no pointers laying around */
02510    ast_free(pattern_tree);
02511 }
02512 
02513 /*!
02514  * \internal
02515  * \brief Get the length of the exten string.
02516  *
02517  * \param str Exten to get length.
02518  *
02519  * \retval strlen of exten.
02520  */
02521 static int ext_cmp_exten_strlen(const char *str)
02522 {
02523    int len;
02524 
02525    len = 0;
02526    for (;;) {
02527       /* Ignore '-' chars as eye candy fluff. */
02528       while (*str == '-') {
02529          ++str;
02530       }
02531       if (!*str) {
02532          break;
02533       }
02534       ++str;
02535       ++len;
02536    }
02537    return len;
02538 }
02539 
02540 /*!
02541  * \internal
02542  * \brief Partial comparison of non-pattern extens.
02543  *
02544  * \param left Exten to compare.
02545  * \param right Exten to compare.  Also matches if this string ends first.
02546  *
02547  * \retval <0 if left < right
02548  * \retval =0 if left == right
02549  * \retval >0 if left > right
02550  */
02551 static int ext_cmp_exten_partial(const char *left, const char *right)
02552 {
02553    int cmp;
02554 
02555    for (;;) {
02556       /* Ignore '-' chars as eye candy fluff. */
02557       while (*left == '-') {
02558          ++left;
02559       }
02560       while (*right == '-') {
02561          ++right;
02562       }
02563 
02564       if (!*right) {
02565          /*
02566           * Right ended first for partial match or both ended at the same
02567           * time for a match.
02568           */
02569          cmp = 0;
02570          break;
02571       }
02572 
02573       cmp = *left - *right;
02574       if (cmp) {
02575          break;
02576       }
02577       ++left;
02578       ++right;
02579    }
02580    return cmp;
02581 }
02582 
02583 /*!
02584  * \internal
02585  * \brief Comparison of non-pattern extens.
02586  *
02587  * \param left Exten to compare.
02588  * \param right Exten to compare.
02589  *
02590  * \retval <0 if left < right
02591  * \retval =0 if left == right
02592  * \retval >0 if left > right
02593  */
02594 static int ext_cmp_exten(const char *left, const char *right)
02595 {
02596    int cmp;
02597 
02598    for (;;) {
02599       /* Ignore '-' chars as eye candy fluff. */
02600       while (*left == '-') {
02601          ++left;
02602       }
02603       while (*right == '-') {
02604          ++right;
02605       }
02606 
02607       cmp = *left - *right;
02608       if (cmp) {
02609          break;
02610       }
02611       if (!*left) {
02612          /*
02613           * Get here only if both strings ended at the same time.  cmp
02614           * would be non-zero if only one string ended.
02615           */
02616          break;
02617       }
02618       ++left;
02619       ++right;
02620    }
02621    return cmp;
02622 }
02623 
02624 /*
02625  * Special characters used in patterns:
02626  * '_'   underscore is the leading character of a pattern.
02627  *    In other position it is treated as a regular char.
02628  * '-' The '-' is a separator and ignored.  Why?  So patterns like NXX-XXX-XXXX work.
02629  * .  one or more of any character. Only allowed at the end of
02630  *    a pattern.
02631  * !  zero or more of anything. Also impacts the result of CANMATCH
02632  *    and MATCHMORE. Only allowed at the end of a pattern.
02633  *    In the core routine, ! causes a match with a return code of 2.
02634  *    In turn, depending on the search mode: (XXX check if it is implemented)
02635  *    - E_MATCH retuns 1 (does match)
02636  *    - E_MATCHMORE returns 0 (no match)
02637  *    - E_CANMATCH returns 1 (does match)
02638  *
02639  * /  should not appear as it is considered the separator of the CID info.
02640  *    XXX at the moment we may stop on this char.
02641  *
02642  * X Z N match ranges 0-9, 1-9, 2-9 respectively.
02643  * [  denotes the start of a set of character. Everything inside
02644  *    is considered literally. We can have ranges a-d and individual
02645  *    characters. A '[' and '-' can be considered literally if they
02646  *    are just before ']'.
02647  *    XXX currently there is no way to specify ']' in a range, nor \ is
02648  *    considered specially.
02649  *
02650  * When we compare a pattern with a specific extension, all characters in the extension
02651  * itself are considered literally.
02652  * XXX do we want to consider space as a separator as well ?
02653  * XXX do we want to consider the separators in non-patterns as well ?
02654  */
02655 
02656 /*!
02657  * \brief helper functions to sort extension patterns in the desired way,
02658  * so that more specific patterns appear first.
02659  *
02660  * \details
02661  * The function compares individual characters (or sets of), returning
02662  * an int where bits 0-7 are the ASCII code of the first char in the set,
02663  * bits 8-15 are the number of characters in the set, and bits 16-20 are
02664  * for special cases.
02665  * This way more specific patterns (smaller character sets) appear first.
02666  * Wildcards have a special value, so that we can directly compare them to
02667  * sets by subtracting the two values. In particular:
02668  *  0x001xx     one character, character set starting with xx
02669  *  0x0yyxx     yy characters, character set starting with xx
02670  *  0x18000     '.' (one or more of anything)
02671  *  0x28000     '!' (zero or more of anything)
02672  *  0x30000     NUL (end of string)
02673  *  0x40000     error in set.
02674  * The pointer to the string is advanced according to needs.
02675  * NOTES:
02676  *  1. the empty set is ignored.
02677  *  2. given that a full set has always 0 as the first element,
02678  *     we could encode the special cases as 0xffXX where XX
02679  *     is 1, 2, 3, 4 as used above.
02680  */
02681 static int ext_cmp_pattern_pos(const char **p, unsigned char *bitwise)
02682 {
02683 #define BITS_PER  8  /* Number of bits per unit (byte). */
02684    unsigned char c;
02685    unsigned char cmin;
02686    int count;
02687    const char *end;
02688 
02689    do {
02690       /* Get character and advance. (Ignore '-' chars as eye candy fluff.) */
02691       do {
02692          c = *(*p)++;
02693       } while (c == '-');
02694 
02695       /* always return unless we have a set of chars */
02696       switch (c) {
02697       default:
02698          /* ordinary character */
02699          bitwise[c / BITS_PER] = 1 << ((BITS_PER - 1) - (c % BITS_PER));
02700          return 0x0100 | c;
02701 
02702       case 'n':
02703       case 'N':
02704          /* 2..9 */
02705          bitwise[6] = 0x3f;
02706          bitwise[7] = 0xc0;
02707          return 0x0800 | '2';
02708 
02709       case 'x':
02710       case 'X':
02711          /* 0..9 */
02712          bitwise[6] = 0xff;
02713          bitwise[7] = 0xc0;
02714          return 0x0A00 | '0';
02715 
02716       case 'z':
02717       case 'Z':
02718          /* 1..9 */
02719          bitwise[6] = 0x7f;
02720          bitwise[7] = 0xc0;
02721          return 0x0900 | '1';
02722 
02723       case '.':
02724          /* wildcard */
02725          return 0x18000;
02726 
02727       case '!':
02728          /* earlymatch */
02729          return 0x28000;   /* less specific than '.' */
02730 
02731       case '\0':
02732          /* empty string */
02733          *p = NULL;
02734          return 0x30000;
02735 
02736       case '[':
02737          /* char set */
02738          break;
02739       }
02740       /* locate end of set */
02741       end = strchr(*p, ']');
02742 
02743       if (!end) {
02744          ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n");
02745          return 0x40000;   /* XXX make this entry go last... */
02746       }
02747 
02748       count = 0;
02749       cmin = 0xFF;
02750       for (; *p < end; ++*p) {
02751          unsigned char c1; /* first char in range */
02752          unsigned char c2; /* last char in range */
02753 
02754          c1 = (*p)[0];
02755          if (*p + 2 < end && (*p)[1] == '-') { /* this is a range */
02756             c2 = (*p)[2];
02757             *p += 2;    /* skip a total of 3 chars */
02758          } else {        /* individual character */
02759             c2 = c1;
02760          }
02761          if (c1 < cmin) {
02762             cmin = c1;
02763          }
02764          for (; c1 <= c2; ++c1) {
02765             unsigned char mask = 1 << ((BITS_PER - 1) - (c1 % BITS_PER));
02766 
02767             /*
02768              * Note: If two character sets score the same, the one with the
02769              * lowest ASCII values will compare as coming first.  Must fill
02770              * in most significant bits for lower ASCII values to accomplish
02771              * the desired sort order.
02772              */
02773             if (!(bitwise[c1 / BITS_PER] & mask)) {
02774                /* Add the character to the set. */
02775                bitwise[c1 / BITS_PER] |= mask;
02776                count += 0x100;
02777             }
02778          }
02779       }
02780       ++*p;
02781    } while (!count);/* While the char set was empty. */
02782    return count | cmin;
02783 }
02784 
02785 /*!
02786  * \internal
02787  * \brief Comparison of exten patterns.
02788  *
02789  * \param left Pattern to compare.
02790  * \param right Pattern to compare.
02791  *
02792  * \retval <0 if left < right
02793  * \retval =0 if left == right
02794  * \retval >0 if left > right
02795  */
02796 static int ext_cmp_pattern(const char *left, const char *right)
02797 {
02798    int cmp;
02799    int left_pos;
02800    int right_pos;
02801 
02802    for (;;) {
02803       unsigned char left_bitwise[32] = { 0, };
02804       unsigned char right_bitwise[32] = { 0, };
02805 
02806       left_pos = ext_cmp_pattern_pos(&left, left_bitwise);
02807       right_pos = ext_cmp_pattern_pos(&right, right_bitwise);
02808       cmp = left_pos - right_pos;
02809       if (!cmp) {
02810          /*
02811           * Are the character sets different, even though they score the same?
02812           *
02813           * Note: Must swap left and right to get the sense of the
02814           * comparison correct.  Otherwise, we would need to multiply by
02815           * -1 instead.
02816           */
02817          cmp = memcmp(right_bitwise, left_bitwise, ARRAY_LEN(left_bitwise));
02818       }
02819       if (cmp) {
02820          break;
02821       }
02822       if (!left) {
02823          /*
02824           * Get here only if both patterns ended at the same time.  cmp
02825           * would be non-zero if only one pattern ended.
02826           */
02827          break;
02828       }
02829    }
02830    return cmp;
02831 }
02832 
02833 /*!
02834  * \internal
02835  * \brief Comparison of dialplan extens for sorting purposes.
02836  *
02837  * \param left Exten/pattern to compare.
02838  * \param right Exten/pattern to compare.
02839  *
02840  * \retval <0 if left < right
02841  * \retval =0 if left == right
02842  * \retval >0 if left > right
02843  */
02844 static int ext_cmp(const char *left, const char *right)
02845 {
02846    /* Make sure non-pattern extens come first. */
02847    if (left[0] != '_') {
02848       if (right[0] == '_') {
02849          return -1;
02850       }
02851       /* Compare two non-pattern extens. */
02852       return ext_cmp_exten(left, right);
02853    }
02854    if (right[0] != '_') {
02855       return 1;
02856    }
02857 
02858    /*
02859     * OK, we need full pattern sorting routine.
02860     *
02861     * Skip past the underscores
02862     */
02863    return ext_cmp_pattern(left + 1, right + 1);
02864 }
02865 
02866 int ast_extension_cmp(const char *a, const char *b)
02867 {
02868    int cmp;
02869 
02870    cmp = ext_cmp(a, b);
02871    if (cmp < 0) {
02872       return -1;
02873    }
02874    if (cmp > 0) {
02875       return 1;
02876    }
02877    return 0;
02878 }
02879 
02880 /*!
02881  * \internal
02882  * \brief used ast_extension_{match|close}
02883  * mode is as follows:
02884  * E_MATCH     success only on exact match
02885  * E_MATCHMORE success only on partial match (i.e. leftover digits in pattern)
02886  * E_CANMATCH  either of the above.
02887  * \retval 0 on no-match
02888  * \retval 1 on match
02889  * \retval 2 on early match.
02890  */
02891 
02892 static int _extension_match_core(const char *pattern, const char *data, enum ext_match_t mode)
02893 {
02894    mode &= E_MATCH_MASK;   /* only consider the relevant bits */
02895 
02896 #ifdef NEED_DEBUG_HERE
02897    ast_log(LOG_NOTICE,"match core: pat: '%s', dat: '%s', mode=%d\n", pattern, data, (int)mode);
02898 #endif
02899 
02900    if (pattern[0] != '_') { /* not a pattern, try exact or partial match */
02901       int lp = ext_cmp_exten_strlen(pattern);
02902       int ld = ext_cmp_exten_strlen(data);
02903 
02904       if (lp < ld) {    /* pattern too short, cannot match */
02905 #ifdef NEED_DEBUG_HERE
02906          ast_log(LOG_NOTICE,"return (0) - pattern too short, cannot match\n");
02907 #endif
02908          return 0;
02909       }
02910       /* depending on the mode, accept full or partial match or both */
02911       if (mode == E_MATCH) {
02912 #ifdef NEED_DEBUG_HERE
02913          ast_log(LOG_NOTICE,"return (!ext_cmp_exten(%s,%s) when mode== E_MATCH)\n", pattern, data);
02914 #endif
02915          return !ext_cmp_exten(pattern, data); /* 1 on match, 0 on fail */
02916       }
02917       if (ld == 0 || !ext_cmp_exten_partial(pattern, data)) { /* partial or full match */
02918 #ifdef NEED_DEBUG_HERE
02919          ast_log(LOG_NOTICE,"return (mode(%d) == E_MATCHMORE ? lp(%d) > ld(%d) : 1)\n", mode, lp, ld);
02920 #endif
02921          return (mode == E_MATCHMORE) ? lp > ld : 1; /* XXX should consider '!' and '/' ? */
02922       } else {
02923 #ifdef NEED_DEBUG_HERE
02924          ast_log(LOG_NOTICE,"return (0) when ld(%d) > 0 && pattern(%s) != data(%s)\n", ld, pattern, data);
02925 #endif
02926          return 0;
02927       }
02928    }
02929    if (mode == E_MATCH && data[0] == '_') {
02930       /*
02931        * XXX It is bad design that we don't know if we should be
02932        * comparing data and pattern as patterns or comparing data if
02933        * it conforms to pattern when the function is called.  First,
02934        * assume they are both patterns.  If they don't match then try
02935        * to see if data conforms to the given pattern.
02936        *
02937        * note: if this test is left out, then _x. will not match _x. !!!
02938        */
02939 #ifdef NEED_DEBUG_HERE
02940       ast_log(LOG_NOTICE, "Comparing as patterns first. pattern:%s data:%s\n", pattern, data);
02941 #endif
02942       if (!ext_cmp_pattern(pattern + 1, data + 1)) {
02943 #ifdef NEED_DEBUG_HERE
02944          ast_log(LOG_NOTICE,"return (1) - pattern matches pattern\n");
02945 #endif
02946          return 1;
02947       }
02948    }
02949 
02950    ++pattern; /* skip leading _ */
02951    /*
02952     * XXX below we stop at '/' which is a separator for the CID info. However we should
02953     * not store '/' in the pattern at all. When we insure it, we can remove the checks.
02954     */
02955    for (;;) {
02956       const char *end;
02957 
02958       /* Ignore '-' chars as eye candy fluff. */
02959       while (*data == '-') {
02960          ++data;
02961       }
02962       while (*pattern == '-') {
02963          ++pattern;
02964       }
02965       if (!*data || !*pattern || *pattern == '/') {
02966          break;
02967       }
02968 
02969       switch (*pattern) {
02970       case '[':   /* a range */
02971          ++pattern;
02972          end = strchr(pattern, ']'); /* XXX should deal with escapes ? */
02973          if (!end) {
02974             ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n");
02975             return 0;   /* unconditional failure */
02976          }
02977          if (pattern == end) {
02978             /* Ignore empty character sets. */
02979             ++pattern;
02980             continue;
02981          }
02982          for (; pattern < end; ++pattern) {
02983             if (pattern+2 < end && pattern[1] == '-') { /* this is a range */
02984                if (*data >= pattern[0] && *data <= pattern[2])
02985                   break;   /* match found */
02986                else {
02987                   pattern += 2; /* skip a total of 3 chars */
02988                   continue;
02989                }
02990             } else if (*data == pattern[0])
02991                break;   /* match found */
02992          }
02993          if (pattern >= end) {
02994 #ifdef NEED_DEBUG_HERE
02995             ast_log(LOG_NOTICE,"return (0) when pattern>=end\n");
02996 #endif
02997             return 0;
02998          }
02999          pattern = end; /* skip and continue */
03000          break;
03001       case 'n':
03002       case 'N':
03003          if (*data < '2' || *data > '9') {
03004 #ifdef NEED_DEBUG_HERE
03005             ast_log(LOG_NOTICE,"return (0) N is not matched\n");
03006 #endif
03007             return 0;
03008          }
03009          break;
03010       case 'x':
03011       case 'X':
03012          if (*data < '0' || *data > '9') {
03013 #ifdef NEED_DEBUG_HERE
03014             ast_log(LOG_NOTICE,"return (0) X is not matched\n");
03015 #endif
03016             return 0;
03017          }
03018          break;
03019       case 'z':
03020       case 'Z':
03021          if (*data < '1' || *data > '9') {
03022 #ifdef NEED_DEBUG_HERE
03023             ast_log(LOG_NOTICE,"return (0) Z is not matched\n");
03024 #endif
03025             return 0;
03026          }
03027          break;
03028       case '.':   /* Must match, even with more digits */
03029 #ifdef NEED_DEBUG_HERE
03030          ast_log(LOG_NOTICE, "return (1) when '.' is matched\n");
03031 #endif
03032          return 1;
03033       case '!':   /* Early match */
03034 #ifdef NEED_DEBUG_HERE
03035          ast_log(LOG_NOTICE, "return (2) when '!' is matched\n");
03036 #endif
03037          return 2;
03038       default:
03039          if (*data != *pattern) {
03040 #ifdef NEED_DEBUG_HERE
03041             ast_log(LOG_NOTICE, "return (0) when *data(%c) != *pattern(%c)\n", *data, *pattern);
03042 #endif
03043             return 0;
03044          }
03045          break;
03046       }
03047       ++data;
03048       ++pattern;
03049    }
03050    if (*data)        /* data longer than pattern, no match */ {
03051 #ifdef NEED_DEBUG_HERE
03052       ast_log(LOG_NOTICE, "return (0) when data longer than pattern\n");
03053 #endif
03054       return 0;
03055    }
03056 
03057    /*
03058     * match so far, but ran off the end of data.
03059     * Depending on what is next, determine match or not.
03060     */
03061    if (*pattern == '\0' || *pattern == '/') {   /* exact match */
03062 #ifdef NEED_DEBUG_HERE
03063       ast_log(LOG_NOTICE, "at end, return (%d) in 'exact match'\n", (mode==E_MATCHMORE) ? 0 : 1);
03064 #endif
03065       return (mode == E_MATCHMORE) ? 0 : 1;  /* this is a failure for E_MATCHMORE */
03066    } else if (*pattern == '!')   {     /* early match */
03067 #ifdef NEED_DEBUG_HERE
03068       ast_log(LOG_NOTICE, "at end, return (2) when '!' is matched\n");
03069 #endif
03070       return 2;
03071    } else {                /* partial match */
03072 #ifdef NEED_DEBUG_HERE
03073       ast_log(LOG_NOTICE, "at end, return (%d) which deps on E_MATCH\n", (mode == E_MATCH) ? 0 : 1);
03074 #endif
03075       return (mode == E_MATCH) ? 0 : 1;   /* this is a failure for E_MATCH */
03076    }
03077 }
03078 
03079 /*
03080  * Wrapper around _extension_match_core() to do performance measurement
03081  * using the profiling code.
03082  */
03083 static int extension_match_core(const char *pattern, const char *data, enum ext_match_t mode)
03084 {
03085    int i;
03086    static int prof_id = -2;   /* marker for 'unallocated' id */
03087    if (prof_id == -2) {
03088       prof_id = ast_add_profile("ext_match", 0);
03089    }
03090    ast_mark(prof_id, 1);
03091    i = _extension_match_core(ast_strlen_zero(pattern) ? "" : pattern, ast_strlen_zero(data) ? "" : data, mode);
03092    ast_mark(prof_id, 0);
03093    return i;
03094 }
03095 
03096 int ast_extension_match(const char *pattern, const char *data)
03097 {
03098    return extension_match_core(pattern, data, E_MATCH);
03099 }
03100 
03101 int ast_extension_close(const char *pattern, const char *data, int needmore)
03102 {
03103    if (needmore != E_MATCHMORE && needmore != E_CANMATCH)
03104       ast_log(LOG_WARNING, "invalid argument %d\n", needmore);
03105    return extension_match_core(pattern, data, needmore);
03106 }
03107 
03108 struct fake_context /* this struct is purely for matching in the hashtab */
03109 {
03110    ast_rwlock_t lock;
03111    struct ast_exten *root;
03112    struct ast_hashtab *root_table;
03113    struct match_char *pattern_tree;
03114    struct ast_context *next;
03115    struct ast_include *includes;
03116    struct ast_ignorepat *ignorepats;
03117    const char *registrar;
03118    int refcount;
03119    AST_LIST_HEAD_NOLOCK(, ast_sw) alts;
03120    ast_mutex_t macrolock;
03121    char name[256];
03122 };
03123 
03124 struct ast_context *ast_context_find(const char *name)
03125 {
03126    struct ast_context *tmp;
03127    struct fake_context item;
03128 
03129    if (!name) {
03130       return NULL;
03131    }
03132    ast_rdlock_contexts();
03133    if (contexts_table) {
03134       ast_copy_string(item.name, name, sizeof(item.name));
03135       tmp = ast_hashtab_lookup(contexts_table, &item);
03136    } else {
03137       tmp = NULL;
03138       while ((tmp = ast_walk_contexts(tmp))) {
03139          if (!strcasecmp(name, tmp->name)) {
03140             break;
03141          }
03142       }
03143    }
03144    ast_unlock_contexts();
03145    return tmp;
03146 }
03147 
03148 #define STATUS_NO_CONTEXT  1
03149 #define STATUS_NO_EXTENSION   2
03150 #define STATUS_NO_PRIORITY 3
03151 #define STATUS_NO_LABEL    4
03152 #define STATUS_SUCCESS     5
03153 
03154 static int matchcid(const char *cidpattern, const char *callerid)
03155 {
03156    /* If the Caller*ID pattern is empty, then we're matching NO Caller*ID, so
03157       failing to get a number should count as a match, otherwise not */
03158 
03159    if (ast_strlen_zero(callerid)) {
03160       return ast_strlen_zero(cidpattern) ? 1 : 0;
03161    }
03162 
03163    return ast_extension_match(cidpattern, callerid);
03164 }
03165 
03166 struct ast_exten *pbx_find_extension(struct ast_channel *chan,
03167    struct ast_context *bypass, struct pbx_find_info *q,
03168    const char *context, const char *exten, int priority,
03169    const char *label, const char *callerid, enum ext_match_t action)
03170 {
03171    int x, res;
03172    struct ast_context *tmp = NULL;
03173    struct ast_exten *e = NULL, *eroot = NULL;
03174    struct ast_include *i = NULL;
03175    struct ast_sw *sw = NULL;
03176    struct ast_exten pattern = {NULL, };
03177    struct scoreboard score = {0, };
03178    struct ast_str *tmpdata = NULL;
03179 
03180    pattern.label = label;
03181    pattern.priority = priority;
03182 #ifdef NEED_DEBUG_HERE
03183    ast_log(LOG_NOTICE, "Looking for cont/ext/prio/label/action = %s/%s/%d/%s/%d\n", context, exten, priority, label, (int) action);
03184 #endif
03185 
03186    /* Initialize status if appropriate */
03187    if (q->stacklen == 0) {
03188       q->status = STATUS_NO_CONTEXT;
03189       q->swo = NULL;
03190       q->data = NULL;
03191       q->foundcontext = NULL;
03192    } else if (q->stacklen >= AST_PBX_MAX_STACK) {
03193       ast_log(LOG_WARNING, "Maximum PBX stack exceeded\n");
03194       return NULL;
03195    }
03196 
03197    /* Check first to see if we've already been checked */
03198    for (x = 0; x < q->stacklen; x++) {
03199       if (!strcasecmp(q->incstack[x], context))
03200          return NULL;
03201    }
03202 
03203    if (bypass) { /* bypass means we only look there */
03204       tmp = bypass;
03205    } else {      /* look in contexts */
03206       tmp = find_context(context);
03207       if (!tmp) {
03208          return NULL;
03209       }
03210    }
03211 
03212    if (q->status < STATUS_NO_EXTENSION)
03213       q->status = STATUS_NO_EXTENSION;
03214 
03215    /* Do a search for matching extension */
03216 
03217    eroot = NULL;
03218    score.total_specificity = 0;
03219    score.exten = 0;
03220    score.total_length = 0;
03221    if (!tmp->pattern_tree && tmp->root_table) {
03222       create_match_char_tree(tmp);
03223 #ifdef NEED_DEBUG
03224       ast_debug(1, "Tree Created in context %s:\n", context);
03225       log_match_char_tree(tmp->pattern_tree," ");
03226 #endif
03227    }
03228 #ifdef NEED_DEBUG
03229    ast_log(LOG_NOTICE, "The Trie we are searching in:\n");
03230    log_match_char_tree(tmp->pattern_tree, "::  ");
03231 #endif
03232 
03233    do {
03234       if (!ast_strlen_zero(overrideswitch)) {
03235          char *osw = ast_strdupa(overrideswitch), *name;
03236          struct ast_switch *asw;
03237          ast_switch_f *aswf = NULL;
03238          char *datap;
03239          int eval = 0;
03240 
03241          name = strsep(&osw, "/");
03242          asw = pbx_findswitch(name);
03243 
03244          if (!asw) {
03245             ast_log(LOG_WARNING, "No such switch '%s'\n", name);
03246             break;
03247          }
03248 
03249          if (osw && strchr(osw, '$')) {
03250             eval = 1;
03251          }
03252 
03253          if (eval && !(tmpdata = ast_str_thread_get(&switch_data, 512))) {
03254             ast_log(LOG_WARNING, "Can't evaluate overrideswitch?!\n");
03255             break;
03256          } else if (eval) {
03257             /* Substitute variables now */
03258             pbx_substitute_variables_helper(chan, osw, ast_str_buffer(tmpdata), ast_str_size(tmpdata));
03259             datap = ast_str_buffer(tmpdata);
03260          } else {
03261             datap = osw;
03262          }
03263 
03264          /* equivalent of extension_match_core() at the switch level */
03265          if (action == E_CANMATCH)
03266             aswf = asw->canmatch;
03267          else if (action == E_MATCHMORE)
03268             aswf = asw->matchmore;
03269          else /* action == E_MATCH */
03270             aswf = asw->exists;
03271          if (!aswf) {
03272             res = 0;
03273          } else {
03274             if (chan) {
03275                ast_autoservice_start(chan);
03276             }
03277             res = aswf(chan, context, exten, priority, callerid, datap);
03278             if (chan) {
03279                ast_autoservice_stop(chan);
03280             }
03281          }
03282          if (res) {  /* Got a match */
03283             q->swo = asw;
03284             q->data = datap;
03285             q->foundcontext = context;
03286             /* XXX keep status = STATUS_NO_CONTEXT ? */
03287             return NULL;
03288          }
03289       }
03290    } while (0);
03291 
03292    if (extenpatternmatchnew) {
03293       new_find_extension(exten, &score, tmp->pattern_tree, 0, 0, callerid, label, action);
03294       eroot = score.exten;
03295 
03296       if (score.last_char == '!' && action == E_MATCHMORE) {
03297          /* We match an extension ending in '!'.
03298           * The decision in this case is final and is NULL (no match).
03299           */
03300 #ifdef NEED_DEBUG_HERE
03301          ast_log(LOG_NOTICE,"Returning MATCHMORE NULL with exclamation point.\n");
03302 #endif
03303          return NULL;
03304       }
03305 
03306       if (!eroot && (action == E_CANMATCH || action == E_MATCHMORE) && score.canmatch_exten) {
03307          q->status = STATUS_SUCCESS;
03308 #ifdef NEED_DEBUG_HERE
03309          ast_log(LOG_NOTICE,"Returning CANMATCH exten %s\n", score.canmatch_exten->exten);
03310 #endif
03311          return score.canmatch_exten;
03312       }
03313 
03314       if ((action == E_MATCHMORE || action == E_CANMATCH)  && eroot) {
03315          if (score.node) {
03316             struct ast_exten *z = trie_find_next_match(score.node);
03317             if (z) {
03318 #ifdef NEED_DEBUG_HERE
03319                ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten %s\n", z->exten);
03320 #endif
03321             } else {
03322                if (score.canmatch_exten) {
03323 #ifdef NEED_DEBUG_HERE
03324                   ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE canmatchmatch exten %s(%p)\n", score.canmatch_exten->exten, score.canmatch_exten);
03325 #endif
03326                   return score.canmatch_exten;
03327                } else {
03328 #ifdef NEED_DEBUG_HERE
03329                   ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten NULL\n");
03330 #endif
03331                }
03332             }
03333             return z;
03334          }
03335 #ifdef NEED_DEBUG_HERE
03336          ast_log(LOG_NOTICE, "Returning CANMATCH/MATCHMORE NULL (no next_match)\n");
03337 #endif
03338          return NULL;  /* according to the code, complete matches are null matches in MATCHMORE mode */
03339       }
03340 
03341       if (eroot) {
03342          /* found entry, now look for the right priority */
03343          if (q->status < STATUS_NO_PRIORITY)
03344             q->status = STATUS_NO_PRIORITY;
03345          e = NULL;
03346          if (action == E_FINDLABEL && label ) {
03347             if (q->status < STATUS_NO_LABEL)
03348                q->status = STATUS_NO_LABEL;
03349             e = ast_hashtab_lookup(eroot->peer_label_table, &pattern);
03350          } else {
03351             e = ast_hashtab_lookup(eroot->peer_table, &pattern);
03352          }
03353          if (e) { /* found a valid match */
03354             q->status = STATUS_SUCCESS;
03355             q->foundcontext = context;
03356 #ifdef NEED_DEBUG_HERE
03357             ast_log(LOG_NOTICE,"Returning complete match of exten %s\n", e->exten);
03358 #endif
03359             return e;
03360          }
03361       }
03362    } else {   /* the old/current default exten pattern match algorithm */
03363 
03364       /* scan the list trying to match extension and CID */
03365       eroot = NULL;
03366       while ( (eroot = ast_walk_context_extensions(tmp, eroot)) ) {
03367          int match = extension_match_core(eroot->exten, exten, action);
03368          /* 0 on fail, 1 on match, 2 on earlymatch */
03369 
03370          if (!match || (eroot->matchcid && !matchcid(eroot->cidmatch, callerid)))
03371             continue;   /* keep trying */
03372          if (match == 2 && action == E_MATCHMORE) {
03373             /* We match an extension ending in '!'.
03374              * The decision in this case is final and is NULL (no match).
03375              */
03376             return NULL;
03377          }
03378          /* found entry, now look for the right priority */
03379          if (q->status < STATUS_NO_PRIORITY)
03380             q->status = STATUS_NO_PRIORITY;
03381          e = NULL;
03382          if (action == E_FINDLABEL && label ) {
03383             if (q->status < STATUS_NO_LABEL)
03384                q->status = STATUS_NO_LABEL;
03385             e = ast_hashtab_lookup(eroot->peer_label_table, &pattern);
03386          } else {
03387             e = ast_hashtab_lookup(eroot->peer_table, &pattern);
03388          }
03389          if (e) { /* found a valid match */
03390             q->status = STATUS_SUCCESS;
03391             q->foundcontext = context;
03392             return e;
03393          }
03394       }
03395    }
03396 
03397    /* Check alternative switches */
03398    AST_LIST_TRAVERSE(&tmp->alts, sw, list) {
03399       struct ast_switch *asw = pbx_findswitch(sw->name);
03400       ast_switch_f *aswf = NULL;
03401       char *datap;
03402 
03403       if (!asw) {
03404          ast_log(LOG_WARNING, "No such switch '%s'\n", sw->name);
03405          continue;
03406       }
03407 
03408       /* Substitute variables now */
03409       if (sw->eval) {
03410          if (!(tmpdata = ast_str_thread_get(&switch_data, 512))) {
03411             ast_log(LOG_WARNING, "Can't evaluate switch?!\n");
03412             continue;
03413          }
03414          pbx_substitute_variables_helper(chan, sw->data, ast_str_buffer(tmpdata), ast_str_size(tmpdata));
03415       }
03416 
03417       /* equivalent of extension_match_core() at the switch level */
03418       if (action == E_CANMATCH)
03419          aswf = asw->canmatch;
03420       else if (action == E_MATCHMORE)
03421          aswf = asw->matchmore;
03422       else /* action == E_MATCH */
03423          aswf = asw->exists;
03424       datap = sw->eval ? ast_str_buffer(tmpdata) : sw->data;
03425       if (!aswf)
03426          res = 0;
03427       else {
03428          if (chan)
03429             ast_autoservice_start(chan);
03430          res = aswf(chan, context, exten, priority, callerid, datap);
03431          if (chan)
03432             ast_autoservice_stop(chan);
03433       }
03434       if (res) {  /* Got a match */
03435          q->swo = asw;
03436          q->data = datap;
03437          q->foundcontext = context;
03438          /* XXX keep status = STATUS_NO_CONTEXT ? */
03439          return NULL;
03440       }
03441    }
03442    q->incstack[q->stacklen++] = tmp->name;   /* Setup the stack */
03443    /* Now try any includes we have in this context */
03444    for (i = tmp->includes; i; i = i->next) {
03445       if (include_valid(i)) {
03446          if ((e = pbx_find_extension(chan, bypass, q, i->rname, exten, priority, label, callerid, action))) {
03447 #ifdef NEED_DEBUG_HERE
03448             ast_log(LOG_NOTICE,"Returning recursive match of %s\n", e->exten);
03449 #endif
03450             return e;
03451          }
03452          if (q->swo)
03453             return NULL;
03454       }
03455    }
03456    return NULL;
03457 }
03458 
03459 /*!
03460  * \brief extract offset:length from variable name.
03461  * \return 1 if there is a offset:length part, which is
03462  * trimmed off (values go into variables)
03463  */
03464 static int parse_variable_name(char *var, int *offset, int *length, int *isfunc)
03465 {
03466    int parens = 0;
03467 
03468    *offset = 0;
03469    *length = INT_MAX;
03470    *isfunc = 0;
03471    for (; *var; var++) {
03472       if (*var == '(') {
03473          (*isfunc)++;
03474          parens++;
03475       } else if (*var == ')') {
03476          parens--;
03477       } else if (*var == ':' && parens == 0) {
03478          *var++ = '\0';
03479          sscanf(var, "%30d:%30d", offset, length);
03480          return 1; /* offset:length valid */
03481       }
03482    }
03483    return 0;
03484 }
03485 
03486 /*!
03487  *\brief takes a substring. It is ok to call with value == workspace.
03488  * \param value
03489  * \param offset < 0 means start from the end of the string and set the beginning
03490  *   to be that many characters back.
03491  * \param length is the length of the substring, a value less than 0 means to leave
03492  * that many off the end.
03493  * \param workspace
03494  * \param workspace_len
03495  * Always return a copy in workspace.
03496  */
03497 static char *substring(const char *value, int offset, int length, char *workspace, size_t workspace_len)
03498 {
03499    char *ret = workspace;
03500    int lr;  /* length of the input string after the copy */
03501 
03502    ast_copy_string(workspace, value, workspace_len); /* always make a copy */
03503 
03504    lr = strlen(ret); /* compute length after copy, so we never go out of the workspace */
03505 
03506    /* Quick check if no need to do anything */
03507    if (offset == 0 && length >= lr) /* take the whole string */
03508       return ret;
03509 
03510    if (offset < 0)   {  /* translate negative offset into positive ones */
03511       offset = lr + offset;
03512       if (offset < 0) /* If the negative offset was greater than the length of the string, just start at the beginning */
03513          offset = 0;
03514    }
03515 
03516    /* too large offset result in empty string so we know what to return */
03517    if (offset >= lr)
03518       return ret + lr;  /* the final '\0' */
03519 
03520    ret += offset;    /* move to the start position */
03521    if (length >= 0 && length < lr - offset)  /* truncate if necessary */
03522       ret[length] = '\0';
03523    else if (length < 0) {
03524       if (lr > offset - length) /* After we remove from the front and from the rear, is there anything left? */
03525          ret[lr + length - offset] = '\0';
03526       else
03527          ret[0] = '\0';
03528    }
03529 
03530    return ret;
03531 }
03532 
03533 static const char *ast_str_substring(struct ast_str *value, int offset, int length)
03534 {
03535    int lr;  /* length of the input string after the copy */
03536 
03537    lr = ast_str_strlen(value); /* compute length after copy, so we never go out of the workspace */
03538 
03539    /* Quick check if no need to do anything */
03540    if (offset == 0 && length >= lr) /* take the whole string */
03541       return ast_str_buffer(value);
03542 
03543    if (offset < 0)   {  /* translate negative offset into positive ones */
03544       offset = lr + offset;
03545       if (offset < 0) /* If the negative offset was greater than the length of the string, just start at the beginning */
03546          offset = 0;
03547    }
03548 
03549    /* too large offset result in empty string so we know what to return */
03550    if (offset >= lr) {
03551       ast_str_reset(value);
03552       return ast_str_buffer(value);
03553    }
03554 
03555    if (offset > 0) {
03556       /* Go ahead and chop off the beginning */
03557       memmove(ast_str_buffer(value), ast_str_buffer(value) + offset, ast_str_strlen(value) - offset + 1);
03558       lr -= offset;
03559    }
03560 
03561    if (length >= 0 && length < lr) {   /* truncate if necessary */
03562       char *tmp = ast_str_buffer(value);
03563       tmp[length] = '\0';
03564       ast_str_update(value);
03565    } else if (length < 0) {
03566       if (lr > -length) { /* After we remove from the front and from the rear, is there anything left? */
03567          char *tmp = ast_str_buffer(value);
03568          tmp[lr + length] = '\0';
03569          ast_str_update(value);
03570       } else {
03571          ast_str_reset(value);
03572       }
03573    } else {
03574       /* Nothing to do, but update the buffer length */
03575       ast_str_update(value);
03576    }
03577 
03578    return ast_str_buffer(value);
03579 }
03580 
03581 /*! \brief  Support for Asterisk built-in variables in the dialplan
03582 
03583 \note See also
03584    - \ref AstVar  Channel variables
03585    - \ref AstCauses The HANGUPCAUSE variable
03586  */
03587 void pbx_retrieve_variable(struct ast_channel *c, const char *var, char **ret, char *workspace, int workspacelen, struct varshead *headp)
03588 {
03589    struct ast_str *str = ast_str_create(16);
03590    const char *cret;
03591 
03592    cret = ast_str_retrieve_variable(&str, 0, c, headp, var);
03593    ast_copy_string(workspace, ast_str_buffer(str), workspacelen);
03594    *ret = cret ? workspace : NULL;
03595    ast_free(str);
03596 }
03597 
03598 const char *ast_str_retrieve_variable(struct ast_str **str, ssize_t maxlen, struct ast_channel *c, struct varshead *headp, const char *var)
03599 {
03600    const char not_found = '\0';
03601    char *tmpvar;
03602    const char *ret;
03603    const char *s; /* the result */
03604    int offset, length;
03605    int i, need_substring;
03606    struct varshead *places[2] = { headp, &globals };  /* list of places where we may look */
03607    char workspace[20];
03608 
03609    if (c) {
03610       ast_channel_lock(c);
03611       places[0] = ast_channel_varshead(c);
03612    }
03613    /*
03614     * Make a copy of var because parse_variable_name() modifies the string.
03615     * Then if called directly, we might need to run substring() on the result;
03616     * remember this for later in 'need_substring', 'offset' and 'length'
03617     */
03618    tmpvar = ast_strdupa(var); /* parse_variable_name modifies the string */
03619    need_substring = parse_variable_name(tmpvar, &offset, &length, &i /* ignored */);
03620 
03621    /*
03622     * Look first into predefined variables, then into variable lists.
03623     * Variable 's' points to the result, according to the following rules:
03624     * s == &not_found (set at the beginning) means that we did not find a
03625     * matching variable and need to look into more places.
03626     * If s != &not_found, s is a valid result string as follows:
03627     * s = NULL if the variable does not have a value;
03628     * you typically do this when looking for an unset predefined variable.
03629     * s = workspace if the result has been assembled there;
03630     * typically done when the result is built e.g. with an snprintf(),
03631     * so we don't need to do an additional copy.
03632     * s != workspace in case we have a string, that needs to be copied
03633     * (the ast_copy_string is done once for all at the end).
03634     * Typically done when the result is already available in some string.
03635     */
03636    s = &not_found;   /* default value */
03637    if (c) { /* This group requires a valid channel */
03638       /* Names with common parts are looked up a piece at a time using strncmp. */
03639       if (!strncmp(var, "CALL", 4)) {
03640          if (!strncmp(var + 4, "ING", 3)) {
03641             if (!strcmp(var + 7, "PRES")) {        /* CALLINGPRES */
03642                ast_str_set(str, maxlen, "%d",
03643                   ast_party_id_presentation(&ast_channel_caller(c)->id));
03644                s = ast_str_buffer(*str);
03645             } else if (!strcmp(var + 7, "ANI2")) {    /* CALLINGANI2 */
03646                ast_str_set(str, maxlen, "%d", ast_channel_caller(c)->ani2);
03647                s = ast_str_buffer(*str);
03648             } else if (!strcmp(var + 7, "TON")) {     /* CALLINGTON */
03649                ast_str_set(str, maxlen, "%d", ast_channel_caller(c)->id.number.plan);
03650                s = ast_str_buffer(*str);
03651             } else if (!strcmp(var + 7, "TNS")) {     /* CALLINGTNS */
03652                ast_str_set(str, maxlen, "%d", ast_channel_dialed(c)->transit_network_select);
03653                s = ast_str_buffer(*str);
03654             }
03655          }
03656       } else if (!strcmp(var, "HINT")) {
03657          s = ast_str_get_hint(str, maxlen, NULL, 0, c, ast_channel_context(c), ast_channel_exten(c)) ? ast_str_buffer(*str) : NULL;
03658       } else if (!strcmp(var, "HINTNAME")) {
03659          s = ast_str_get_hint(NULL, 0, str, maxlen, c, ast_channel_context(c), ast_channel_exten(c)) ? ast_str_buffer(*str) : NULL;
03660       } else if (!strcmp(var, "EXTEN")) {
03661          s = ast_channel_exten(c);
03662       } else if (!strcmp(var, "CONTEXT")) {
03663          s = ast_channel_context(c);
03664       } else if (!strcmp(var, "PRIORITY")) {
03665          ast_str_set(str, maxlen, "%d", ast_channel_priority(c));
03666          s = ast_str_buffer(*str);
03667       } else if (!strcmp(var, "CHANNEL")) {
03668          s = ast_channel_name(c);
03669       } else if (!strcmp(var, "UNIQUEID")) {
03670          s = ast_channel_uniqueid(c);
03671       } else if (!strcmp(var, "HANGUPCAUSE")) {
03672          ast_str_set(str, maxlen, "%d", ast_channel_hangupcause(c));
03673          s = ast_str_buffer(*str);
03674       }
03675    }
03676    if (s == &not_found) { /* look for more */
03677       if (!strcmp(var, "EPOCH")) {
03678          ast_str_set(str, maxlen, "%d", (int) time(NULL));
03679          s = ast_str_buffer(*str);
03680       } else if (!strcmp(var, "SYSTEMNAME")) {
03681          s = ast_config_AST_SYSTEM_NAME;
03682       } else if (!strcmp(var, "ASTETCDIR")) {
03683          s = ast_config_AST_CONFIG_DIR;
03684       } else if (!strcmp(var, "ASTMODDIR")) {
03685          s = ast_config_AST_MODULE_DIR;
03686       } else if (!strcmp(var, "ASTVARLIBDIR")) {
03687          s = ast_config_AST_VAR_DIR;
03688       } else if (!strcmp(var, "ASTDBDIR")) {
03689          s = ast_config_AST_DB;
03690       } else if (!strcmp(var, "ASTKEYDIR")) {
03691          s = ast_config_AST_KEY_DIR;
03692       } else if (!strcmp(var, "ASTDATADIR")) {
03693          s = ast_config_AST_DATA_DIR;
03694       } else if (!strcmp(var, "ASTAGIDIR")) {
03695          s = ast_config_AST_AGI_DIR;
03696       } else if (!strcmp(var, "ASTSPOOLDIR")) {
03697          s = ast_config_AST_SPOOL_DIR;
03698       } else if (!strcmp(var, "ASTRUNDIR")) {
03699          s = ast_config_AST_RUN_DIR;
03700       } else if (!strcmp(var, "ASTLOGDIR")) {
03701          s = ast_config_AST_LOG_DIR;
03702       } else if (!strcmp(var, "ENTITYID")) {
03703          ast_eid_to_str(workspace, sizeof(workspace), &ast_eid_default);
03704          s = workspace;
03705       }
03706    }
03707    /* if not found, look into chanvars or global vars */
03708    for (i = 0; s == &not_found && i < ARRAY_LEN(places); i++) {
03709       struct ast_var_t *variables;
03710       if (!places[i])
03711          continue;
03712       if (places[i] == &globals)
03713          ast_rwlock_rdlock(&globalslock);
03714       AST_LIST_TRAVERSE(places[i], variables, entries) {
03715          if (!strcmp(ast_var_name(variables), var)) {
03716             s = ast_var_value(variables);
03717             break;
03718          }
03719       }
03720       if (places[i] == &globals)
03721          ast_rwlock_unlock(&globalslock);
03722    }
03723    if (s == &not_found || s == NULL) {
03724       ast_debug(5, "Result of '%s' is NULL\n", var);
03725       ret = NULL;
03726    } else {
03727       ast_debug(5, "Result of '%s' is '%s'\n", var, s);
03728       if (s != ast_str_buffer(*str)) {
03729          ast_str_set(str, maxlen, "%s", s);
03730       }
03731       ret = ast_str_buffer(*str);
03732       if (need_substring) {
03733          ret = ast_str_substring(*str, offset, length);
03734          ast_debug(2, "Final result of '%s' is '%s'\n", var, ret);
03735       }
03736    }
03737 
03738    if (c) {
03739       ast_channel_unlock(c);
03740    }
03741    return ret;
03742 }
03743 
03744 static void exception_store_free(void *data)
03745 {
03746    struct pbx_exception *exception = data;
03747    ast_string_field_free_memory(exception);
03748    ast_free(exception);
03749 }
03750 
03751 static const struct ast_datastore_info exception_store_info = {
03752    .type = "EXCEPTION",
03753    .destroy = exception_store_free,
03754 };
03755 
03756 /*!
03757  * \internal
03758  * \brief Set the PBX to execute the exception extension.
03759  *
03760  * \param chan Channel to raise the exception on.
03761  * \param reason Reason exception is raised.
03762  * \param priority Dialplan priority to set.
03763  *
03764  * \retval 0 on success.
03765  * \retval -1 on error.
03766  */
03767 static int raise_exception(struct ast_channel *chan, const char *reason, int priority)
03768 {
03769    struct ast_datastore *ds = ast_channel_datastore_find(chan, &exception_store_info, NULL);
03770    struct pbx_exception *exception = NULL;
03771 
03772    if (!ds) {
03773       ds = ast_datastore_alloc(&exception_store_info, NULL);
03774       if (!ds)
03775          return -1;
03776       if (!(exception = ast_calloc_with_stringfields(1, struct pbx_exception, 128))) {
03777          ast_datastore_free(ds);
03778          return -1;
03779       }
03780       ds->data = exception;
03781       ast_channel_datastore_add(chan, ds);
03782    } else
03783       exception = ds->data;
03784 
03785    ast_string_field_set(exception, reason, reason);
03786    ast_string_field_set(exception, context, ast_channel_context(chan));
03787    ast_string_field_set(exception, exten, ast_channel_exten(chan));
03788    exception->priority = ast_channel_priority(chan);
03789    set_ext_pri(chan, "e", priority);
03790    return 0;
03791 }
03792 
03793 int pbx_builtin_raise_exception(struct ast_channel *chan, const char *reason)
03794 {
03795    /* Priority will become 1, next time through the AUTOLOOP */
03796    return raise_exception(chan, reason, 0);
03797 }
03798 
03799 static int acf_exception_read(struct ast_channel *chan, const char *name, char *data, char *buf, size_t buflen)
03800 {
03801    struct ast_datastore *ds = ast_channel_datastore_find(chan, &exception_store_info, NULL);
03802    struct pbx_exception *exception = NULL;
03803    if (!ds || !ds->data)
03804       return -1;
03805    exception = ds->data;
03806    if (!strcasecmp(data, "REASON"))
03807       ast_copy_string(buf, exception->reason, buflen);
03808    else if (!strcasecmp(data, "CONTEXT"))
03809       ast_copy_string(buf, exception->context, buflen);
03810    else if (!strncasecmp(data, "EXTEN", 5))
03811       ast_copy_string(buf, exception->exten, buflen);
03812    else if (!strcasecmp(data, "PRIORITY"))
03813       snprintf(buf, buflen, "%d", exception->priority);
03814    else
03815       return -1;
03816    return 0;
03817 }
03818 
03819 static struct ast_custom_function exception_function = {
03820    .name = "EXCEPTION",
03821    .read = acf_exception_read,
03822 };
03823 
03824 static char *handle_show_functions(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
03825 {
03826    struct ast_custom_function *acf;
03827    int count_acf = 0;
03828    int like = 0;
03829 
03830    switch (cmd) {
03831    case CLI_INIT:
03832       e->command = "core show functions [like]";
03833       e->usage =
03834          "Usage: core show functions [like <text>]\n"
03835          "       List builtin functions, optionally only those matching a given string\n";
03836       return NULL;
03837    case CLI_GENERATE:
03838       return NULL;
03839    }
03840 
03841    if (a->argc == 5 && (!strcmp(a->argv[3], "like")) ) {
03842       like = 1;
03843    } else if (a->argc != 3) {
03844       return CLI_SHOWUSAGE;
03845    }
03846 
03847    ast_cli(a->fd, "%s Custom Functions:\n--------------------------------------------------------------------------------\n", like ? "Matching" : "Installed");
03848 
03849    AST_RWLIST_RDLOCK(&acf_root);
03850    AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) {
03851       if (!like || strstr(acf->name, a->argv[4])) {
03852          count_acf++;
03853          ast_cli(a->fd, "%-20.20s  %-35.35s  %s\n",
03854             S_OR(acf->name, ""),
03855             S_OR(acf->syntax, ""),
03856             S_OR(acf->synopsis, ""));
03857       }
03858    }
03859    AST_RWLIST_UNLOCK(&acf_root);
03860 
03861    ast_cli(a->fd, "%d %scustom functions installed.\n", count_acf, like ? "matching " : "");
03862 
03863    return CLI_SUCCESS;
03864 }
03865 
03866 static char *complete_functions(const char *word, int pos, int state)
03867 {
03868    struct ast_custom_function *cur;
03869    char *ret = NULL;
03870    int which = 0;
03871    int wordlen;
03872    int cmp;
03873 
03874    if (pos != 3) {
03875       return NULL;
03876    }
03877 
03878    wordlen = strlen(word);
03879    AST_RWLIST_RDLOCK(&acf_root);
03880    AST_RWLIST_TRAVERSE(&acf_root, cur, acflist) {
03881       /*
03882        * Do a case-insensitive search for convenience in this
03883        * 'complete' function.
03884        *
03885        * We must search the entire container because the functions are
03886        * sorted and normally found case sensitively.
03887        */
03888       cmp = strncasecmp(word, cur->name, wordlen);
03889       if (!cmp) {
03890          /* Found match. */
03891          if (++which <= state) {
03892             /* Not enough matches. */
03893             continue;
03894          }
03895          ret = ast_strdup(cur->name);
03896          break;
03897       }
03898    }
03899    AST_RWLIST_UNLOCK(&acf_root);
03900 
03901    return ret;
03902 }
03903 
03904 static char *handle_show_function(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
03905 {
03906    struct ast_custom_function *acf;
03907    /* Maximum number of characters added by terminal coloring is 22 */
03908    char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40], argtitle[40], seealsotitle[40];
03909    char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL, *seealso = NULL;
03910    char stxtitle[40], *syntax = NULL, *arguments = NULL;
03911    int syntax_size, description_size, synopsis_size, arguments_size, seealso_size;
03912 
03913    switch (cmd) {
03914    case CLI_INIT:
03915       e->command = "core show function";
03916       e->usage =
03917          "Usage: core show function <function>\n"
03918          "       Describe a particular dialplan function.\n";
03919       return NULL;
03920    case CLI_GENERATE:
03921       return complete_functions(a->word, a->pos, a->n);
03922    }
03923 
03924    if (a->argc != 4) {
03925       return CLI_SHOWUSAGE;
03926    }
03927 
03928    if (!(acf = ast_custom_function_find(a->argv[3]))) {
03929       ast_cli(a->fd, "No function by that name registered.\n");
03930       return CLI_FAILURE;
03931    }
03932 
03933    syntax_size = strlen(S_OR(acf->syntax, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
03934    if (!(syntax = ast_malloc(syntax_size))) {
03935       ast_cli(a->fd, "Memory allocation failure!\n");
03936       return CLI_FAILURE;
03937    }
03938 
03939    snprintf(info, sizeof(info), "\n  -= Info about function '%s' =- \n\n", acf->name);
03940    term_color(infotitle, info, COLOR_MAGENTA, 0, sizeof(infotitle));
03941    term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40);
03942    term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40);
03943    term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, 40);
03944    term_color(argtitle, "[Arguments]\n", COLOR_MAGENTA, 0, 40);
03945    term_color(seealsotitle, "[See Also]\n", COLOR_MAGENTA, 0, 40);
03946    term_color(syntax, S_OR(acf->syntax, "Not available"), COLOR_CYAN, 0, syntax_size);
03947 #ifdef AST_XML_DOCS
03948    if (acf->docsrc == AST_XML_DOC) {
03949       arguments = ast_xmldoc_printable(S_OR(acf->arguments, "Not available"), 1);
03950       synopsis = ast_xmldoc_printable(S_OR(acf->synopsis, "Not available"), 1);
03951       description = ast_xmldoc_printable(S_OR(acf->desc, "Not available"), 1);
03952       seealso = ast_xmldoc_printable(S_OR(acf->seealso, "Not available"), 1);
03953    } else
03954 #endif
03955    {
03956       synopsis_size = strlen(S_OR(acf->synopsis, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
03957       synopsis = ast_malloc(synopsis_size);
03958 
03959       description_size = strlen(S_OR(acf->desc, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
03960       description = ast_malloc(description_size);
03961 
03962       arguments_size = strlen(S_OR(acf->arguments, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
03963       arguments = ast_malloc(arguments_size);
03964 
03965       seealso_size = strlen(S_OR(acf->seealso, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
03966       seealso = ast_malloc(seealso_size);
03967 
03968       /* check allocated memory. */
03969       if (!synopsis || !description || !arguments || !seealso) {
03970          ast_free(synopsis);
03971          ast_free(description);
03972          ast_free(arguments);
03973          ast_free(seealso);
03974          ast_free(syntax);
03975          return CLI_FAILURE;
03976       }
03977 
03978       term_color(arguments, S_OR(acf->arguments, "Not available"), COLOR_CYAN, 0, arguments_size);
03979       term_color(synopsis, S_OR(acf->synopsis, "Not available"), COLOR_CYAN, 0, synopsis_size);
03980       term_color(description, S_OR(acf->desc, "Not available"), COLOR_CYAN, 0, description_size);
03981       term_color(seealso, S_OR(acf->seealso, "Not available"), COLOR_CYAN, 0, seealso_size);
03982    }
03983 
03984    ast_cli(a->fd, "%s%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n",
03985          infotitle, syntitle, synopsis, destitle, description,
03986          stxtitle, syntax, argtitle, arguments, seealsotitle, seealso);
03987 
03988    ast_free(arguments);
03989    ast_free(synopsis);
03990    ast_free(description);
03991    ast_free(seealso);
03992    ast_free(syntax);
03993 
03994    return CLI_SUCCESS;
03995 }
03996 
03997 static struct ast_custom_function *ast_custom_function_find_nolock(const char *name)
03998 {
03999    struct ast_custom_function *cur;
04000    int cmp;
04001 
04002    AST_RWLIST_TRAVERSE(&acf_root, cur, acflist) {
04003       cmp = strcmp(name, cur->name);
04004       if (cmp > 0) {
04005          continue;
04006       }
04007       if (!cmp) {
04008          /* Found it. */
04009          break;
04010       }
04011       /* Not in container. */
04012       cur = NULL;
04013       break;
04014    }
04015 
04016    return cur;
04017 }
04018 
04019 struct ast_custom_function *ast_custom_function_find(const char *name)
04020 {
04021    struct ast_custom_function *acf;
04022 
04023    AST_RWLIST_RDLOCK(&acf_root);
04024    acf = ast_custom_function_find_nolock(name);
04025    AST_RWLIST_UNLOCK(&acf_root);
04026 
04027    return acf;
04028 }
04029 
04030 int ast_custom_function_unregister(struct ast_custom_function *acf)
04031 {
04032    struct ast_custom_function *cur;
04033 
04034    if (!acf) {
04035       return -1;
04036    }
04037 
04038    AST_RWLIST_WRLOCK(&acf_root);
04039    if ((cur = AST_RWLIST_REMOVE(&acf_root, acf, acflist))) {
04040 #ifdef AST_XML_DOCS
04041       if (cur->docsrc == AST_XML_DOC) {
04042          ast_string_field_free_memory(acf);
04043       }
04044 #endif
04045       ast_verb(2, "Unregistered custom function %s\n", cur->name);
04046    }
04047    AST_RWLIST_UNLOCK(&acf_root);
04048 
04049    return cur ? 0 : -1;
04050 }
04051 
04052 /*!
04053  * \brief Returns true if given custom function escalates privileges on read.
04054  *
04055  * \param acf Custom function to query.
04056  * \return True (non-zero) if reads escalate privileges.
04057  * \return False (zero) if reads just read.
04058  */
04059 static int read_escalates(const struct ast_custom_function *acf) {
04060    return acf->read_escalates;
04061 }
04062 
04063 /*!
04064  * \brief Returns true if given custom function escalates privileges on write.
04065  *
04066  * \param acf Custom function to query.
04067  * \return True (non-zero) if writes escalate privileges.
04068  * \return False (zero) if writes just write.
04069  */
04070 static int write_escalates(const struct ast_custom_function *acf) {
04071    return acf->write_escalates;
04072 }
04073 
04074 /*! \internal
04075  *  \brief Retrieve the XML documentation of a specified ast_custom_function,
04076  *         and populate ast_custom_function string fields.
04077  *  \param acf ast_custom_function structure with empty 'desc' and 'synopsis'
04078  *             but with a function 'name'.
04079  *  \retval -1 On error.
04080  *  \retval 0 On succes.
04081  */
04082 static int acf_retrieve_docs(struct ast_custom_function *acf)
04083 {
04084 #ifdef AST_XML_DOCS
04085    char *tmpxml;
04086 
04087    /* Let's try to find it in the Documentation XML */
04088    if (!ast_strlen_zero(acf->desc) || !ast_strlen_zero(acf->synopsis)) {
04089       return 0;
04090    }
04091 
04092    if (ast_string_field_init(acf, 128)) {
04093       return -1;
04094    }
04095 
04096    /* load synopsis */
04097    tmpxml = ast_xmldoc_build_synopsis("function", acf->name, ast_module_name(acf->mod));
04098    ast_string_field_set(acf, synopsis, tmpxml);
04099    ast_free(tmpxml);
04100 
04101    /* load description */
04102    tmpxml = ast_xmldoc_build_description("function", acf->name, ast_module_name(acf->mod));
04103    ast_string_field_set(acf, desc, tmpxml);
04104    ast_free(tmpxml);
04105 
04106    /* load syntax */
04107    tmpxml = ast_xmldoc_build_syntax("function", acf->name, ast_module_name(acf->mod));
04108    ast_string_field_set(acf, syntax, tmpxml);
04109    ast_free(tmpxml);
04110 
04111    /* load arguments */
04112    tmpxml = ast_xmldoc_build_arguments("function", acf->name, ast_module_name(acf->mod));
04113    ast_string_field_set(acf, arguments, tmpxml);
04114    ast_free(tmpxml);
04115 
04116    /* load seealso */
04117    tmpxml = ast_xmldoc_build_seealso("function", acf->name, ast_module_name(acf->mod));
04118    ast_string_field_set(acf, seealso, tmpxml);
04119    ast_free(tmpxml);
04120 
04121    acf->docsrc = AST_XML_DOC;
04122 #endif
04123 
04124    return 0;
04125 }
04126 
04127 int __ast_custom_function_register(struct ast_custom_function *acf, struct ast_module *mod)
04128 {
04129    struct ast_custom_function *cur;
04130 
04131    if (!acf) {
04132       return -1;
04133    }
04134 
04135    acf->mod = mod;
04136 #ifdef AST_XML_DOCS
04137    acf->docsrc = AST_STATIC_DOC;
04138 #endif
04139 
04140    if (acf_retrieve_docs(acf)) {
04141       return -1;
04142    }
04143 
04144    AST_RWLIST_WRLOCK(&acf_root);
04145 
04146    cur = ast_custom_function_find_nolock(acf->name);
04147    if (cur) {
04148       ast_log(LOG_ERROR, "Function %s already registered.\n", acf->name);
04149       AST_RWLIST_UNLOCK(&acf_root);
04150       return -1;
04151    }
04152 
04153    /* Store in alphabetical order */
04154    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&acf_root, cur, acflist) {
04155       if (strcmp(acf->name, cur->name) < 0) {
04156          AST_RWLIST_INSERT_BEFORE_CURRENT(acf, acflist);
04157          break;
04158       }
04159    }
04160    AST_RWLIST_TRAVERSE_SAFE_END;
04161    if (!cur) {
04162       AST_RWLIST_INSERT_TAIL(&acf_root, acf, acflist);
04163    }
04164 
04165    AST_RWLIST_UNLOCK(&acf_root);
04166 
04167    ast_verb(2, "Registered custom function '" COLORIZE_FMT "'\n", COLORIZE(COLOR_BRCYAN, 0, acf->name));
04168 
04169    return 0;
04170 }
04171 
04172 int __ast_custom_function_register_escalating(struct ast_custom_function *acf, enum ast_custom_function_escalation escalation, struct ast_module *mod)
04173 {
04174    int res;
04175 
04176    res = __ast_custom_function_register(acf, mod);
04177    if (res != 0) {
04178       return -1;
04179    }
04180 
04181    switch (escalation) {
04182    case AST_CFE_NONE:
04183       break;
04184    case AST_CFE_READ:
04185       acf->read_escalates = 1;
04186       break;
04187    case AST_CFE_WRITE:
04188       acf->write_escalates = 1;
04189       break;
04190    case AST_CFE_BOTH:
04191       acf->read_escalates = 1;
04192       acf->write_escalates = 1;
04193       break;
04194    }
04195 
04196    return 0;
04197 }
04198 
04199 /*! \brief return a pointer to the arguments of the function,
04200  * and terminates the function name with '\\0'
04201  */
04202 static char *func_args(char *function)
04203 {
04204    char *args = strchr(function, '(');
04205 
04206    if (!args) {
04207       ast_log(LOG_WARNING, "Function '%s' doesn't contain parentheses.  Assuming null argument.\n", function);
04208    } else {
04209       char *p;
04210       *args++ = '\0';
04211       if ((p = strrchr(args, ')'))) {
04212          *p = '\0';
04213       } else {
04214          ast_log(LOG_WARNING, "Can't find trailing parenthesis for function '%s(%s'?\n", function, args);
04215       }
04216    }
04217    return args;
04218 }
04219 
04220 void pbx_live_dangerously(int new_live_dangerously)
04221 {
04222    if (new_live_dangerously && !live_dangerously) {
04223       ast_log(LOG_WARNING, "Privilege escalation protection disabled!\n"
04224          "See https://wiki.asterisk.org/wiki/x/1gKfAQ for more details.\n");
04225    }
04226 
04227    if (!new_live_dangerously && live_dangerously) {
04228       ast_log(LOG_NOTICE, "Privilege escalation protection enabled.\n");
04229    }
04230    live_dangerously = new_live_dangerously;
04231 }
04232 
04233 int ast_thread_inhibit_escalations(void)
04234 {
04235    int *thread_inhibit_escalations;
04236 
04237    thread_inhibit_escalations = ast_threadstorage_get(
04238       &thread_inhibit_escalations_tl, sizeof(*thread_inhibit_escalations));
04239 
04240    if (thread_inhibit_escalations == NULL) {
04241       ast_log(LOG_ERROR, "Error inhibiting privilege escalations for current thread\n");
04242       return -1;
04243    }
04244 
04245    *thread_inhibit_escalations = 1;
04246    return 0;
04247 }
04248 
04249 /*!
04250  * \brief Indicates whether the current thread inhibits the execution of
04251  * dangerous functions.
04252  *
04253  * \return True (non-zero) if dangerous function execution is inhibited.
04254  * \return False (zero) if dangerous function execution is allowed.
04255  */
04256 static int thread_inhibits_escalations(void)
04257 {
04258    int *thread_inhibit_escalations;
04259 
04260    thread_inhibit_escalations = ast_threadstorage_get(
04261       &thread_inhibit_escalations_tl, sizeof(*thread_inhibit_escalations));
04262 
04263    if (thread_inhibit_escalations == NULL) {
04264       ast_log(LOG_ERROR, "Error checking thread's ability to run dangerous functions\n");
04265       /* On error, assume that we are inhibiting */
04266       return 1;
04267    }
04268 
04269    return *thread_inhibit_escalations;
04270 }
04271 
04272 /*!
04273  * \brief Determines whether execution of a custom function's read function
04274  * is allowed.
04275  *
04276  * \param acfptr Custom function to check
04277  * \return True (non-zero) if reading is allowed.
04278  * \return False (zero) if reading is not allowed.
04279  */
04280 static int is_read_allowed(struct ast_custom_function *acfptr)
04281 {
04282    if (!acfptr) {
04283       return 1;
04284    }
04285 
04286    if (!read_escalates(acfptr)) {
04287       return 1;
04288    }
04289 
04290    if (!thread_inhibits_escalations()) {
04291       return 1;
04292    }
04293 
04294    if (live_dangerously) {
04295       /* Global setting overrides the thread's preference */
04296       ast_debug(2, "Reading %s from a dangerous context\n",
04297          acfptr->name);
04298       return 1;
04299    }
04300 
04301    /* We have no reason to allow this function to execute */
04302    return 0;
04303 }
04304 
04305 /*!
04306  * \brief Determines whether execution of a custom function's write function
04307  * is allowed.
04308  *
04309  * \param acfptr Custom function to check
04310  * \return True (non-zero) if writing is allowed.
04311  * \return False (zero) if writing is not allowed.
04312  */
04313 static int is_write_allowed(struct ast_custom_function *acfptr)
04314 {
04315    if (!acfptr) {
04316       return 1;
04317    }
04318 
04319    if (!write_escalates(acfptr)) {
04320       return 1;
04321    }
04322 
04323    if (!thread_inhibits_escalations()) {
04324       return 1;
04325    }
04326 
04327    if (live_dangerously) {
04328       /* Global setting overrides the thread's preference */
04329       ast_debug(2, "Writing %s from a dangerous context\n",
04330          acfptr->name);
04331       return 1;
04332    }
04333 
04334    /* We have no reason to allow this function to execute */
04335    return 0;
04336 }
04337 
04338 int ast_func_read(struct ast_channel *chan, const char *function, char *workspace, size_t len)
04339 {
04340    char *copy = ast_strdupa(function);
04341    char *args = func_args(copy);
04342    struct ast_custom_function *acfptr = ast_custom_function_find(copy);
04343    int res;
04344    struct ast_module_user *u = NULL;
04345 
04346    if (acfptr == NULL) {
04347       ast_log(LOG_ERROR, "Function %s not registered\n", copy);
04348    } else if (!acfptr->read && !acfptr->read2) {
04349       ast_log(LOG_ERROR, "Function %s cannot be read\n", copy);
04350    } else if (!is_read_allowed(acfptr)) {
04351       ast_log(LOG_ERROR, "Dangerous function %s read blocked\n", copy);
04352    } else if (acfptr->read) {
04353       if (acfptr->mod) {
04354          u = __ast_module_user_add(acfptr->mod, chan);
04355       }
04356       res = acfptr->read(chan, copy, args, workspace, len);
04357       if (acfptr->mod && u) {
04358          __ast_module_user_remove(acfptr->mod, u);
04359       }
04360       return res;
04361    } else {
04362       struct ast_str *str = ast_str_create(16);
04363       if (acfptr->mod) {
04364          u = __ast_module_user_add(acfptr->mod, chan);
04365       }
04366       res = acfptr->read2(chan, copy, args, &str, 0);
04367       if (acfptr->mod && u) {
04368          __ast_module_user_remove(acfptr->mod, u);
04369       }
04370       ast_copy_string(workspace, ast_str_buffer(str), len > ast_str_size(str) ? ast_str_size(str) : len);
04371       ast_free(str);
04372       return res;
04373    }
04374    return -1;
04375 }
04376 
04377 int ast_func_read2(struct ast_channel *chan, const char *function, struct ast_str **str, ssize_t maxlen)
04378 {
04379    char *copy = ast_strdupa(function);
04380    char *args = func_args(copy);
04381    struct ast_custom_function *acfptr = ast_custom_function_find(copy);
04382    int res;
04383    struct ast_module_user *u = NULL;
04384 
04385    if (acfptr == NULL) {
04386       ast_log(LOG_ERROR, "Function %s not registered\n", copy);
04387    } else if (!acfptr->read && !acfptr->read2) {
04388       ast_log(LOG_ERROR, "Function %s cannot be read\n", copy);
04389    } else if (!is_read_allowed(acfptr)) {
04390       ast_log(LOG_ERROR, "Dangerous function %s read blocked\n", copy);
04391    } else {
04392       if (acfptr->mod) {
04393          u = __ast_module_user_add(acfptr->mod, chan);
04394       }
04395       ast_str_reset(*str);
04396       if (acfptr->read2) {
04397          /* ast_str enabled */
04398          res = acfptr->read2(chan, copy, args, str, maxlen);
04399       } else {
04400          /* Legacy function pointer, allocate buffer for result */
04401          int maxsize = ast_str_size(*str);
04402          if (maxlen > -1) {
04403             if (maxlen == 0) {
04404                if (acfptr->read_max) {
04405                   maxsize = acfptr->read_max;
04406                } else {
04407                   maxsize = VAR_BUF_SIZE;
04408                }
04409             } else {
04410                maxsize = maxlen;
04411             }
04412             ast_str_make_space(str, maxsize);
04413          }
04414          res = acfptr->read(chan, copy, args, ast_str_buffer(*str), maxsize);
04415       }
04416       if (acfptr->mod && u) {
04417          __ast_module_user_remove(acfptr->mod, u);
04418       }
04419       return res;
04420    }
04421    return -1;
04422 }
04423 
04424 int ast_func_write(struct ast_channel *chan, const char *function, const char *value)
04425 {
04426    char *copy = ast_strdupa(function);
04427    char *args = func_args(copy);
04428    struct ast_custom_function *acfptr = ast_custom_function_find(copy);
04429 
04430    if (acfptr == NULL) {
04431       ast_log(LOG_ERROR, "Function %s not registered\n", copy);
04432    } else if (!acfptr->write) {
04433       ast_log(LOG_ERROR, "Function %s cannot be written to\n", copy);
04434    } else if (!is_write_allowed(acfptr)) {
04435       ast_log(LOG_ERROR, "Dangerous function %s write blocked\n", copy);
04436    } else {
04437       int res;
04438       struct ast_module_user *u = NULL;
04439       if (acfptr->mod)
04440          u = __ast_module_user_add(acfptr->mod, chan);
04441       res = acfptr->write(chan, copy, args, value);
04442       if (acfptr->mod && u)
04443          __ast_module_user_remove(acfptr->mod, u);
04444       return res;
04445    }
04446 
04447    return -1;
04448 }
04449 
04450 void ast_str_substitute_variables_full(struct ast_str **buf, ssize_t maxlen, struct ast_channel *c, struct varshead *headp, const char *templ, size_t *used)
04451 {
04452    /* Substitutes variables into buf, based on string templ */
04453    char *cp4 = NULL;
04454    const char *whereweare;
04455    int orig_size = 0;
04456    int offset, offset2, isfunction;
04457    const char *nextvar, *nextexp, *nextthing;
04458    const char *vars, *vare;
04459    char *finalvars;
04460    int pos, brackets, needsub, len;
04461    struct ast_str *substr1 = ast_str_create(16), *substr2 = NULL, *substr3 = ast_str_create(16);
04462 
04463    ast_str_reset(*buf);
04464    whereweare = templ;
04465    while (!ast_strlen_zero(whereweare)) {
04466       /* reset our buffer */
04467       ast_str_reset(substr3);
04468 
04469       /* Assume we're copying the whole remaining string */
04470       pos = strlen(whereweare);
04471       nextvar = NULL;
04472       nextexp = NULL;
04473       nextthing = strchr(whereweare, '$');
04474       if (nextthing) {
04475          switch (nextthing[1]) {
04476          case '{':
04477             nextvar = nextthing;
04478             pos = nextvar - whereweare;
04479             break;
04480          case '[':
04481             nextexp = nextthing;
04482             pos = nextexp - whereweare;
04483             break;
04484          default:
04485             pos = 1;
04486          }
04487       }
04488 
04489       if (pos) {
04490          /* Copy that many bytes */
04491          ast_str_append_substr(buf, maxlen, whereweare, pos);
04492 
04493          templ += pos;
04494          whereweare += pos;
04495       }
04496 
04497       if (nextvar) {
04498          /* We have a variable.  Find the start and end, and determine
04499             if we are going to have to recursively call ourselves on the
04500             contents */
04501          vars = vare = nextvar + 2;
04502          brackets = 1;
04503          needsub = 0;
04504 
04505          /* Find the end of it */
04506          while (brackets && *vare) {
04507             if ((vare[0] == '$') && (vare[1] == '{')) {
04508                needsub++;
04509             } else if (vare[0] == '{') {
04510                brackets++;
04511             } else if (vare[0] == '}') {
04512                brackets--;
04513             } else if ((vare[0] == '$') && (vare[1] == '['))
04514                needsub++;
04515             vare++;
04516          }
04517          if (brackets)
04518             ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n");
04519          len = vare - vars - 1;
04520 
04521          /* Skip totally over variable string */
04522          whereweare += (len + 3);
04523 
04524          /* Store variable name (and truncate) */
04525          ast_str_set_substr(&substr1, 0, vars, len);
04526          ast_debug(5, "Evaluating '%s' (from '%s' len %d)\n", ast_str_buffer(substr1), vars, len);
04527 
04528          /* Substitute if necessary */
04529          if (needsub) {
04530             size_t my_used;
04531 
04532             if (!substr2) {
04533                substr2 = ast_str_create(16);
04534             }
04535             ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), &my_used);
04536             finalvars = ast_str_buffer(substr2);
04537          } else {
04538             finalvars = ast_str_buffer(substr1);
04539          }
04540 
04541          parse_variable_name(finalvars, &offset, &offset2, &isfunction);
04542          if (isfunction) {
04543             /* Evaluate function */
04544             if (c || !headp) {
04545                cp4 = ast_func_read2(c, finalvars, &substr3, 0) ? NULL : ast_str_buffer(substr3);
04546             } else {
04547                struct varshead old;
04548                struct ast_channel *bogus = ast_dummy_channel_alloc();
04549                if (bogus) {
04550                   memcpy(&old, ast_channel_varshead(bogus), sizeof(old));
04551                   memcpy(ast_channel_varshead(bogus), headp, sizeof(*ast_channel_varshead(bogus)));
04552                   cp4 = ast_func_read2(c, finalvars, &substr3, 0) ? NULL : ast_str_buffer(substr3);
04553                   /* Don't deallocate the varshead that was passed in */
04554                   memcpy(ast_channel_varshead(bogus), &old, sizeof(*ast_channel_varshead(bogus)));
04555                   ast_channel_unref(bogus);
04556                } else {
04557                   ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution.  Function results may be blank.\n");
04558                }
04559             }
04560             ast_debug(2, "Function %s result is '%s'\n", finalvars, cp4 ? cp4 : "(null)");
04561          } else {
04562             /* Retrieve variable value */
04563             ast_str_retrieve_variable(&substr3, 0, c, headp, finalvars);
04564             cp4 = ast_str_buffer(substr3);
04565          }
04566          if (cp4) {
04567             ast_str_substring(substr3, offset, offset2);
04568             ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3));
04569          }
04570       } else if (nextexp) {
04571          /* We have an expression.  Find the start and end, and determine
04572             if we are going to have to recursively call ourselves on the
04573             contents */
04574          vars = vare = nextexp + 2;
04575          brackets = 1;
04576          needsub = 0;
04577 
04578          /* Find the end of it */
04579          while (brackets && *vare) {
04580             if ((vare[0] == '$') && (vare[1] == '[')) {
04581                needsub++;
04582                brackets++;
04583                vare++;
04584             } else if (vare[0] == '[') {
04585                brackets++;
04586             } else if (vare[0] == ']') {
04587                brackets--;
04588             } else if ((vare[0] == '$') && (vare[1] == '{')) {
04589                needsub++;
04590                vare++;
04591             }
04592             vare++;
04593          }
04594          if (brackets)
04595             ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n");
04596          len = vare - vars - 1;
04597 
04598          /* Skip totally over expression */
04599          whereweare += (len + 3);
04600 
04601          /* Store variable name (and truncate) */
04602          ast_str_set_substr(&substr1, 0, vars, len);
04603 
04604          /* Substitute if necessary */
04605          if (needsub) {
04606             size_t my_used;
04607 
04608             if (!substr2) {
04609                substr2 = ast_str_create(16);
04610             }
04611             ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), &my_used);
04612             finalvars = ast_str_buffer(substr2);
04613          } else {
04614             finalvars = ast_str_buffer(substr1);
04615          }
04616 
04617          if (ast_str_expr(&substr3, 0, c, finalvars)) {
04618             ast_debug(2, "Expression result is '%s'\n", ast_str_buffer(substr3));
04619          }
04620          ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3));
04621       }
04622    }
04623    *used = ast_str_strlen(*buf) - orig_size;
04624    ast_free(substr1);
04625    ast_free(substr2);
04626    ast_free(substr3);
04627 }
04628 
04629 void ast_str_substitute_variables(struct ast_str **buf, ssize_t maxlen, struct ast_channel *chan, const char *templ)
04630 {
04631    size_t used;
04632    ast_str_substitute_variables_full(buf, maxlen, chan, NULL, templ, &used);
04633 }
04634 
04635 void ast_str_substitute_variables_varshead(struct ast_str **buf, ssize_t maxlen, struct varshead *headp, const char *templ)
04636 {
04637    size_t used;
04638    ast_str_substitute_variables_full(buf, maxlen, NULL, headp, templ, &used);
04639 }
04640 
04641 void pbx_substitute_variables_helper_full(struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int count, size_t *used)
04642 {
04643    /* Substitutes variables into cp2, based on string cp1, cp2 NO LONGER NEEDS TO BE ZEROED OUT!!!!  */
04644    char *cp4 = NULL;
04645    const char *whereweare, *orig_cp2 = cp2;
04646    int length, offset, offset2, isfunction;
04647    char *workspace = NULL;
04648    char *ltmp = NULL, *var = NULL;
04649    char *nextvar, *nextexp, *nextthing;
04650    char *vars, *vare;
04651    int pos, brackets, needsub, len;
04652 
04653    *cp2 = 0; /* just in case nothing ends up there */
04654    whereweare = cp1;
04655    while (!ast_strlen_zero(whereweare) && count) {
04656       /* Assume we're copying the whole remaining string */
04657       pos = strlen(whereweare);
04658       nextvar = NULL;
04659       nextexp = NULL;
04660       nextthing = strchr(whereweare, '$');
04661       if (nextthing) {
04662          switch (nextthing[1]) {
04663          case '{':
04664             nextvar = nextthing;
04665             pos = nextvar - whereweare;
04666             break;
04667          case '[':
04668             nextexp = nextthing;
04669             pos = nextexp - whereweare;
04670             break;
04671          default:
04672             pos = 1;
04673          }
04674       }
04675 
04676       if (pos) {
04677          /* Can't copy more than 'count' bytes */
04678          if (pos > count)
04679             pos = count;
04680 
04681          /* Copy that many bytes */
04682          memcpy(cp2, whereweare, pos);
04683 
04684          count -= pos;
04685          cp2 += pos;
04686          whereweare += pos;
04687          *cp2 = 0;
04688       }
04689 
04690       if (nextvar) {
04691          /* We have a variable.  Find the start and end, and determine
04692             if we are going to have to recursively call ourselves on the
04693             contents */
04694          vars = vare = nextvar + 2;
04695          brackets = 1;
04696          needsub = 0;
04697 
04698          /* Find the end of it */
04699          while (brackets && *vare) {
04700             if ((vare[0] == '$') && (vare[1] == '{')) {
04701                needsub++;
04702             } else if (vare[0] == '{') {
04703                brackets++;
04704             } else if (vare[0] == '}') {
04705                brackets--;
04706             } else if ((vare[0] == '$') && (vare[1] == '['))
04707                needsub++;
04708             vare++;
04709          }
04710          if (brackets)
04711             ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n");
04712          len = vare - vars - 1;
04713 
04714          /* Skip totally over variable string */
04715          whereweare += (len + 3);
04716 
04717          if (!var)
04718             var = ast_alloca(VAR_BUF_SIZE);
04719 
04720          /* Store variable name (and truncate) */
04721          ast_copy_string(var, vars, len + 1);
04722 
04723          /* Substitute if necessary */
04724          if (needsub) {
04725             size_t my_used;
04726 
04727             if (!ltmp) {
04728                ltmp = ast_alloca(VAR_BUF_SIZE);
04729             }
04730             pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &my_used);
04731             vars = ltmp;
04732          } else {
04733             vars = var;
04734          }
04735 
04736          if (!workspace)
04737             workspace = ast_alloca(VAR_BUF_SIZE);
04738 
04739          workspace[0] = '\0';
04740 
04741          parse_variable_name(vars, &offset, &offset2, &isfunction);
04742          if (isfunction) {
04743             /* Evaluate function */
04744             if (c || !headp)
04745                cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace;
04746             else {
04747                struct varshead old;
04748                struct ast_channel *c = ast_dummy_channel_alloc();
04749                if (c) {
04750                   memcpy(&old, ast_channel_varshead(c), sizeof(old));
04751                   memcpy(ast_channel_varshead(c), headp, sizeof(*ast_channel_varshead(c)));
04752                   cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace;
04753                   /* Don't deallocate the varshead that was passed in */
04754                   memcpy(ast_channel_varshead(c), &old, sizeof(*ast_channel_varshead(c)));
04755                   c = ast_channel_unref(c);
04756                } else {
04757                   ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution.  Function results may be blank.\n");
04758                }
04759             }
04760             ast_debug(2, "Function %s result is '%s'\n", vars, cp4 ? cp4 : "(null)");
04761          } else {
04762             /* Retrieve variable value */
04763             pbx_retrieve_variable(c, vars, &cp4, workspace, VAR_BUF_SIZE, headp);
04764          }
04765          if (cp4) {
04766             cp4 = substring(cp4, offset, offset2, workspace, VAR_BUF_SIZE);
04767 
04768             length = strlen(cp4);
04769             if (length > count)
04770                length = count;
04771             memcpy(cp2, cp4, length);
04772             count -= length;
04773             cp2 += length;
04774             *cp2 = 0;
04775          }
04776       } else if (nextexp) {
04777          /* We have an expression.  Find the start and end, and determine
04778             if we are going to have to recursively call ourselves on the
04779             contents */
04780          vars = vare = nextexp + 2;
04781          brackets = 1;
04782          needsub = 0;
04783 
04784          /* Find the end of it */
04785          while (brackets && *vare) {
04786             if ((vare[0] == '$') && (vare[1] == '[')) {
04787                needsub++;
04788                brackets++;
04789                vare++;
04790             } else if (vare[0] == '[') {
04791                brackets++;
04792             } else if (vare[0] == ']') {
04793                brackets--;
04794             } else if ((vare[0] == '$') && (vare[1] == '{')) {
04795                needsub++;
04796                vare++;
04797             }
04798             vare++;
04799          }
04800          if (brackets)
04801             ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n");
04802          len = vare - vars - 1;
04803 
04804          /* Skip totally over expression */
04805          whereweare += (len + 3);
04806 
04807          if (!var)
04808             var = ast_alloca(VAR_BUF_SIZE);
04809 
04810          /* Store variable name (and truncate) */
04811          ast_copy_string(var, vars, len + 1);
04812 
04813          /* Substitute if necessary */
04814          if (needsub) {
04815             size_t my_used;
04816 
04817             if (!ltmp) {
04818                ltmp = ast_alloca(VAR_BUF_SIZE);
04819             }
04820             pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &my_used);
04821             vars = ltmp;
04822          } else {
04823             vars = var;
04824          }
04825 
04826          length = ast_expr(vars, cp2, count, c);
04827 
04828          if (length) {
04829             ast_debug(1, "Expression result is '%s'\n", cp2);
04830             count -= length;
04831             cp2 += length;
04832             *cp2 = 0;
04833          }
04834       }
04835    }
04836    *used = cp2 - orig_cp2;
04837 }
04838 
04839 void pbx_substitute_variables_helper(struct ast_channel *c, const char *cp1, char *cp2, int count)
04840 {
04841    size_t used;
04842    pbx_substitute_variables_helper_full(c, (c) ? ast_channel_varshead(c) : NULL, cp1, cp2, count, &used);
04843 }
04844 
04845 void pbx_substitute_variables_varshead(struct varshead *headp, const char *cp1, char *cp2, int count)
04846 {
04847    size_t used;
04848    pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count, &used);
04849 }
04850 
04851 /*!
04852  * \brief The return value depends on the action:
04853  *
04854  * E_MATCH, E_CANMATCH, E_MATCHMORE require a real match,
04855  * and return 0 on failure, -1 on match;
04856  * E_FINDLABEL maps the label to a priority, and returns
04857  * the priority on success, ... XXX
04858  * E_SPAWN, spawn an application,
04859  *
04860  * \retval 0 on success.
04861  * \retval  -1 on failure.
04862  *
04863  * \note The channel is auto-serviced in this function, because doing an extension
04864  * match may block for a long time.  For example, if the lookup has to use a network
04865  * dialplan switch, such as DUNDi or IAX2, it may take a while.  However, the channel
04866  * auto-service code will queue up any important signalling frames to be processed
04867  * after this is done.
04868  */
04869 static int pbx_extension_helper(struct ast_channel *c, struct ast_context *con,
04870   const char *context, const char *exten, int priority,
04871   const char *label, const char *callerid, enum ext_match_t action, int *found, int combined_find_spawn)
04872 {
04873    struct ast_exten *e;
04874    struct ast_app *app;
04875    char *substitute = NULL;
04876    int res;
04877    struct pbx_find_info q = { .stacklen = 0 }; /* the rest is reset in pbx_find_extension */
04878    char passdata[EXT_DATA_SIZE];
04879    int matching_action = (action == E_MATCH || action == E_CANMATCH || action == E_MATCHMORE);
04880 
04881    ast_rdlock_contexts();
04882    if (found)
04883       *found = 0;
04884 
04885    e = pbx_find_extension(c, con, &q, context, exten, priority, label, callerid, action);
04886    if (e) {
04887       if (found)
04888          *found = 1;
04889       if (matching_action) {
04890          ast_unlock_contexts();
04891          return -1;  /* success, we found it */
04892       } else if (action == E_FINDLABEL) { /* map the label to a priority */
04893          res = e->priority;
04894          ast_unlock_contexts();
04895          return res; /* the priority we were looking for */
04896       } else { /* spawn */
04897          if (!e->cached_app)
04898             e->cached_app = pbx_findapp(e->app);
04899          app = e->cached_app;
04900          if (ast_strlen_zero(e->data)) {
04901             *passdata = '\0';
04902          } else {
04903             const char *tmp;
04904             if ((!(tmp = strchr(e->data, '$'))) || (!strstr(tmp, "${") && !strstr(tmp, "$["))) {
04905                /* no variables to substitute, copy on through */
04906                ast_copy_string(passdata, e->data, sizeof(passdata));
04907             } else {
04908                /* save e->data on stack for later processing after lock released */
04909                substitute = ast_strdupa(e->data);
04910             }
04911          }
04912          ast_unlock_contexts();
04913          if (!app) {
04914             ast_log(LOG_WARNING, "No application '%s' for extension (%s, %s, %d)\n", e->app, context, exten, priority);
04915             return -1;
04916          }
04917          if (ast_channel_context(c) != context)
04918             ast_channel_context_set(c, context);
04919          if (ast_channel_exten(c) != exten)
04920             ast_channel_exten_set(c, exten);
04921          ast_channel_priority_set(c, priority);
04922          if (substitute) {
04923             pbx_substitute_variables_helper(c, substitute, passdata, sizeof(passdata)-1);
04924          }
04925          ast_debug(1, "Launching '%s'\n", app->name);
04926          if (VERBOSITY_ATLEAST(3)) {
04927             ast_verb(3, "Executing [%s@%s:%d] " COLORIZE_FMT "(\"" COLORIZE_FMT "\", \"" COLORIZE_FMT "\") %s\n",
04928                exten, context, priority,
04929                COLORIZE(COLOR_BRCYAN, 0, app->name),
04930                COLORIZE(COLOR_BRMAGENTA, 0, ast_channel_name(c)),
04931                COLORIZE(COLOR_BRMAGENTA, 0, passdata),
04932                "in new stack");
04933          }
04934          return pbx_exec(c, app, passdata);  /* 0 on success, -1 on failure */
04935       }
04936    } else if (q.swo) {  /* not found here, but in another switch */
04937       if (found)
04938          *found = 1;
04939       ast_unlock_contexts();
04940       if (matching_action) {
04941          return -1;
04942       } else {
04943          if (!q.swo->exec) {
04944             ast_log(LOG_WARNING, "No execution engine for switch %s\n", q.swo->name);
04945             res = -1;
04946          }
04947          return q.swo->exec(c, q.foundcontext ? q.foundcontext : context, exten, priority, callerid, q.data);
04948       }
04949    } else { /* not found anywhere, see what happened */
04950       ast_unlock_contexts();
04951       /* Using S_OR here because Solaris doesn't like NULL being passed to ast_log */
04952       switch (q.status) {
04953       case STATUS_NO_CONTEXT:
04954          if (!matching_action && !combined_find_spawn)
04955             ast_log(LOG_NOTICE, "Cannot find extension context '%s'\n", S_OR(context, ""));
04956          break;
04957       case STATUS_NO_EXTENSION:
04958          if (!matching_action && !combined_find_spawn)
04959             ast_log(LOG_NOTICE, "Cannot find extension '%s' in context '%s'\n", exten, S_OR(context, ""));
04960          break;
04961       case STATUS_NO_PRIORITY:
04962          if (!matching_action && !combined_find_spawn)
04963             ast_log(LOG_NOTICE, "No such priority %d in extension '%s' in context '%s'\n", priority, exten, S_OR(context, ""));
04964          break;
04965       case STATUS_NO_LABEL:
04966          if (context && !combined_find_spawn)
04967             ast_log(LOG_NOTICE, "No such label '%s' in extension '%s' in context '%s'\n", label, exten, S_OR(context, ""));
04968          break;
04969       default:
04970          ast_debug(1, "Shouldn't happen!\n");
04971       }
04972 
04973       return (matching_action) ? 0 : -1;
04974    }
04975 }
04976 
04977 /*! \brief Find hint for given extension in context */
04978 static struct ast_exten *ast_hint_extension_nolock(struct ast_channel *c, const char *context, const char *exten)
04979 {
04980    struct pbx_find_info q = { .stacklen = 0 }; /* the rest is set in pbx_find_context */
04981    return pbx_find_extension(c, NULL, &q, context, exten, PRIORITY_HINT, NULL, "", E_MATCH);
04982 }
04983 
04984 static struct ast_exten *ast_hint_extension(struct ast_channel *c, const char *context, const char *exten)
04985 {
04986    struct ast_exten *e;
04987    ast_rdlock_contexts();
04988    e = ast_hint_extension_nolock(c, context, exten);
04989    ast_unlock_contexts();
04990    return e;
04991 }
04992 
04993 enum ast_extension_states ast_devstate_to_extenstate(enum ast_device_state devstate)
04994 {
04995    switch (devstate) {
04996    case AST_DEVICE_ONHOLD:
04997       return AST_EXTENSION_ONHOLD;
04998    case AST_DEVICE_BUSY:
04999       return AST_EXTENSION_BUSY;
05000    case AST_DEVICE_UNKNOWN:
05001       return AST_EXTENSION_NOT_INUSE;
05002    case AST_DEVICE_UNAVAILABLE:
05003    case AST_DEVICE_INVALID:
05004       return AST_EXTENSION_UNAVAILABLE;
05005    case AST_DEVICE_RINGINUSE:
05006       return (AST_EXTENSION_INUSE | AST_EXTENSION_RINGING);
05007    case AST_DEVICE_RINGING:
05008       return AST_EXTENSION_RINGING;
05009    case AST_DEVICE_INUSE:
05010       return AST_EXTENSION_INUSE;
05011    case AST_DEVICE_NOT_INUSE:
05012       return AST_EXTENSION_NOT_INUSE;
05013    case AST_DEVICE_TOTAL: /* not a device state, included for completeness */
05014       break;
05015    }
05016 
05017    return AST_EXTENSION_NOT_INUSE;
05018 }
05019 
05020 /*!
05021  * \internal
05022  * \brief Parse out the presence portion of the hint string
05023  */
05024 static char *parse_hint_presence(struct ast_str *hint_args)
05025 {
05026    char *copy = ast_strdupa(ast_str_buffer(hint_args));
05027    char *tmp = "";
05028 
05029    if ((tmp = strrchr(copy, ','))) {
05030       *tmp = '\0';
05031       tmp++;
05032    } else {
05033       return NULL;
05034    }
05035    ast_str_set(&hint_args, 0, "%s", tmp);
05036    return ast_str_buffer(hint_args);
05037 }
05038 
05039 /*!
05040  * \internal
05041  * \brief Parse out the device portion of the hint string
05042  */
05043 static char *parse_hint_device(struct ast_str *hint_args)
05044 {
05045    char *copy = ast_strdupa(ast_str_buffer(hint_args));
05046    char *tmp;
05047 
05048    if ((tmp = strrchr(copy, ','))) {
05049       *tmp = '\0';
05050    }
05051 
05052    ast_str_set(&hint_args, 0, "%s", copy);
05053    return ast_str_buffer(hint_args);
05054 }
05055 
05056 static void device_state_info_dt(void *obj)
05057 {
05058    struct ast_device_state_info *info = obj;
05059 
05060    ao2_cleanup(info->causing_channel);
05061 }
05062 
05063 static struct ao2_container *alloc_device_state_info(void)
05064 {
05065    return ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_NOLOCK, 1, NULL, NULL);
05066 }
05067 
05068 static int ast_extension_state3(struct ast_str *hint_app, struct ao2_container *device_state_info)
05069 {
05070    char *cur;
05071    char *rest;
05072    struct ast_devstate_aggregate agg;
05073 
05074    /* One or more devices separated with a & character */
05075    rest = parse_hint_device(hint_app);
05076 
05077    ast_devstate_aggregate_init(&agg);
05078    while ((cur = strsep(&rest, "&"))) {
05079       enum ast_device_state state = ast_device_state(cur);
05080 
05081       ast_devstate_aggregate_add(&agg, state);
05082       if (device_state_info) {
05083          struct ast_device_state_info *obj;
05084 
05085          obj = ao2_alloc_options(sizeof(*obj) + strlen(cur), device_state_info_dt, AO2_ALLOC_OPT_LOCK_NOLOCK);
05086          /* if failed we cannot add this device */
05087          if (obj) {
05088             obj->device_state = state;
05089             strcpy(obj->device_name, cur);
05090             ao2_link(device_state_info, obj);
05091             ao2_ref(obj, -1);
05092          }
05093       }
05094    }
05095 
05096    return ast_devstate_to_extenstate(ast_devstate_aggregate_result(&agg));
05097 }
05098 
05099 /*! \brief Check state of extension by using hints */
05100 static int ast_extension_state2(struct ast_exten *e, struct ao2_container *device_state_info)
05101 {
05102    struct ast_str *hint_app = ast_str_thread_get(&extensionstate_buf, 32);
05103 
05104    if (!e || !hint_app) {
05105       return -1;
05106    }
05107 
05108    ast_str_set(&hint_app, 0, "%s", ast_get_extension_app(e));
05109    return ast_extension_state3(hint_app, device_state_info);
05110 }
05111 
05112 /*! \brief Return extension_state as string */
05113 const char *ast_extension_state2str(int extension_state)
05114 {
05115    int i;
05116 
05117    for (i = 0; (i < ARRAY_LEN(extension_states)); i++) {
05118       if (extension_states[i].extension_state == extension_state)
05119          return extension_states[i].text;
05120    }
05121    return "Unknown";
05122 }
05123 
05124 /*!
05125  * \internal
05126  * \brief Check extension state for an extension by using hint
05127  */
05128 static int internal_extension_state_extended(struct ast_channel *c, const char *context, const char *exten,
05129    struct ao2_container *device_state_info)
05130 {
05131    struct ast_exten *e;
05132 
05133    if (!(e = ast_hint_extension(c, context, exten))) {  /* Do we have a hint for this extension ? */
05134       return -1;                   /* No hint, return -1 */
05135    }
05136 
05137    if (e->exten[0] == '_') {
05138       /* Create this hint on-the-fly */
05139       ast_add_extension(e->parent->name, 0, exten, e->priority, e->label,
05140          e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr,
05141          e->registrar);
05142       if (!(e = ast_hint_extension(c, context, exten))) {
05143          /* Improbable, but not impossible */
05144          return -1;
05145       }
05146    }
05147 
05148    return ast_extension_state2(e, device_state_info);  /* Check all devices in the hint */
05149 }
05150 
05151 /*! \brief Check extension state for an extension by using hint */
05152 int ast_extension_state(struct ast_channel *c, const char *context, const char *exten)
05153 {
05154    return internal_extension_state_extended(c, context, exten, NULL);
05155 }
05156 
05157 /*! \brief Check extended extension state for an extension by using hint */
05158 int ast_extension_state_extended(struct ast_channel *c, const char *context, const char *exten,
05159    struct ao2_container **device_state_info)
05160 {
05161    struct ao2_container *container = NULL;
05162    int ret;
05163 
05164    if (device_state_info) {
05165       container = alloc_device_state_info();
05166    }
05167 
05168    ret = internal_extension_state_extended(c, context, exten, container);
05169    if (ret < 0 && container) {
05170       ao2_ref(container, -1);
05171       container = NULL;
05172    }
05173 
05174    if (device_state_info) {
05175       get_device_state_causing_channels(container);
05176       *device_state_info = container;
05177    }
05178 
05179    return ret;
05180 }
05181 
05182 static int extension_presence_state_helper(struct ast_exten *e, char **subtype, char **message)
05183 {
05184    struct ast_str *hint_app = ast_str_thread_get(&extensionstate_buf, 32);
05185    char *presence_provider;
05186    const char *app;
05187 
05188    if (!e || !hint_app) {
05189       return -1;
05190    }
05191 
05192    app = ast_get_extension_app(e);
05193    if (ast_strlen_zero(app)) {
05194       return -1;
05195    }
05196 
05197    ast_str_set(&hint_app, 0, "%s", app);
05198    presence_provider = parse_hint_presence(hint_app);
05199 
05200    if (ast_strlen_zero(presence_provider)) {
05201       /* No presence string in the hint */
05202       return 0;
05203    }
05204 
05205    return ast_presence_state(presence_provider, subtype, message);
05206 }
05207 
05208 int ast_hint_presence_state(struct ast_channel *c, const char *context, const char *exten, char **subtype, char **message)
05209 {
05210    struct ast_exten *e;
05211 
05212    if (!(e = ast_hint_extension(c, context, exten))) {  /* Do we have a hint for this extension ? */
05213       return -1;                   /* No hint, return -1 */
05214    }
05215 
05216    if (e->exten[0] == '_') {
05217       /* Create this hint on-the-fly */
05218       ast_add_extension(e->parent->name, 0, exten, e->priority, e->label,
05219          e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr,
05220          e->registrar);
05221       if (!(e = ast_hint_extension(c, context, exten))) {
05222          /* Improbable, but not impossible */
05223          return -1;
05224       }
05225    }
05226 
05227    return extension_presence_state_helper(e, subtype, message);
05228 }
05229 
05230 static int execute_state_callback(ast_state_cb_type cb,
05231    const char *context,
05232    const char *exten,
05233    void *data,
05234    enum ast_state_cb_update_reason reason,
05235    struct ast_hint *hint,
05236    struct ao2_container *device_state_info)
05237 {
05238    int res = 0;
05239    struct ast_state_cb_info info = { 0, };
05240 
05241    info.reason = reason;
05242 
05243    /* Copy over current hint data */
05244    if (hint) {
05245       ao2_lock(hint);
05246       info.exten_state = hint->laststate;
05247       info.device_state_info = device_state_info;
05248       info.presence_state = hint->last_presence_state;
05249       if (!(ast_strlen_zero(hint->last_presence_subtype))) {
05250          info.presence_subtype = ast_strdupa(hint->last_presence_subtype);
05251       } else {
05252          info.presence_subtype = "";
05253       }
05254       if (!(ast_strlen_zero(hint->last_presence_message))) {
05255          info.presence_message = ast_strdupa(hint->last_presence_message);
05256       } else {
05257          info.presence_message = "";
05258       }
05259       ao2_unlock(hint);
05260    } else {
05261       info.exten_state = AST_EXTENSION_REMOVED;
05262    }
05263 
05264    /* NOTE: The casts will not be needed for v10 and later */
05265    res = cb((char *) context, (char *) exten, &info, data);
05266 
05267    return res;
05268 }
05269 
05270 /*!
05271  * /internal
05272  * /brief Identify a channel for every device which is supposedly responsible for the device state.
05273  *
05274  * Especially when the device is ringing, the oldest ringing channel is chosen.
05275  * For all other cases the first encountered channel in the specific state is chosen.
05276  */
05277 static void get_device_state_causing_channels(struct ao2_container *c)
05278 {
05279    struct ao2_iterator iter;
05280    struct ast_device_state_info *info;
05281    struct ast_channel *chan;
05282 
05283    if (!c || !ao2_container_count(c)) {
05284       return;
05285    }
05286    iter = ao2_iterator_init(c, 0);
05287    for (; (info = ao2_iterator_next(&iter)); ao2_ref(info, -1)) {
05288       enum ast_channel_state search_state = 0; /* prevent false uninit warning */
05289       char match[AST_CHANNEL_NAME];
05290       struct ast_channel_iterator *chan_iter;
05291       struct timeval chantime = {0, }; /* prevent false uninit warning */
05292 
05293       switch (info->device_state) {
05294       case AST_DEVICE_RINGING:
05295       case AST_DEVICE_RINGINUSE:
05296          /* find ringing channel */
05297          search_state = AST_STATE_RINGING;
05298          break;
05299       case AST_DEVICE_BUSY:
05300          /* find busy channel */
05301          search_state = AST_STATE_BUSY;
05302          break;
05303       case AST_DEVICE_ONHOLD:
05304       case AST_DEVICE_INUSE:
05305          /* find up channel */
05306          search_state = AST_STATE_UP;
05307          break;
05308       case AST_DEVICE_UNKNOWN:
05309       case AST_DEVICE_NOT_INUSE:
05310       case AST_DEVICE_INVALID:
05311       case AST_DEVICE_UNAVAILABLE:
05312       case AST_DEVICE_TOTAL /* not a state */:
05313          /* no channels are of interest */
05314          continue;
05315       }
05316 
05317       /* iterate over all channels of the device */
05318            snprintf(match, sizeof(match), "%s-", info->device_name);
05319       chan_iter = ast_channel_iterator_by_name_new(match, strlen(match));
05320       for (; (chan = ast_channel_iterator_next(chan_iter)); ast_channel_unref(chan)) {
05321          ast_channel_lock(chan);
05322          /* this channel's state doesn't match */
05323          if (search_state != ast_channel_state(chan)) {
05324             ast_channel_unlock(chan);
05325             continue;
05326          }
05327          /* any non-ringing channel will fit */
05328          if (search_state != AST_STATE_RINGING) {
05329             ast_channel_unlock(chan);
05330             info->causing_channel = chan; /* is kept ref'd! */
05331             break;
05332          }
05333          /* but we need the oldest ringing channel of the device to match with undirected pickup */
05334          if (!info->causing_channel) {
05335             chantime = ast_channel_creationtime(chan);
05336             ast_channel_ref(chan); /* must ref it! */
05337             info->causing_channel = chan;
05338          } else if (ast_tvcmp(ast_channel_creationtime(chan), chantime) < 0) {
05339             chantime = ast_channel_creationtime(chan);
05340             ast_channel_unref(info->causing_channel);
05341             ast_channel_ref(chan); /* must ref it! */
05342             info->causing_channel = chan;
05343          }
05344          ast_channel_unlock(chan);
05345       }
05346       ast_channel_iterator_destroy(chan_iter);
05347    }
05348    ao2_iterator_destroy(&iter);
05349 }
05350 
05351 static void device_state_cb(void *unused, struct stasis_subscription *sub, struct stasis_message *msg)
05352 {
05353    struct ast_device_state_message *dev_state;
05354    struct ast_hint *hint;
05355    struct ast_str *hint_app;
05356    struct ast_hintdevice *device;
05357    struct ast_hintdevice *cmpdevice;
05358    struct ao2_iterator *dev_iter;
05359    struct ao2_iterator cb_iter;
05360    char context_name[AST_MAX_CONTEXT];
05361    char exten_name[AST_MAX_EXTENSION];
05362 
05363    if (ast_device_state_message_type() != stasis_message_type(msg)) {
05364       return;
05365    }
05366 
05367    dev_state = stasis_message_data(msg);
05368    if (dev_state->eid) {
05369       /* ignore non-aggregate states */
05370       return;
05371    }
05372 
05373    if (ao2_container_count(hintdevices) == 0) {
05374       /* There are no hints monitoring devices. */
05375       return;
05376    }
05377 
05378    hint_app = ast_str_create(1024);
05379    if (!hint_app) {
05380       return;
05381    }
05382 
05383    cmpdevice = ast_alloca(sizeof(*cmpdevice) + strlen(dev_state->device));
05384    strcpy(cmpdevice->hintdevice, dev_state->device);
05385 
05386    ast_mutex_lock(&context_merge_lock);/* Hold off ast_merge_contexts_and_delete */
05387    dev_iter = ao2_t_callback(hintdevices,
05388       OBJ_POINTER | OBJ_MULTIPLE,
05389       hintdevice_cmp_multiple,
05390       cmpdevice,
05391       "find devices in container");
05392    if (!dev_iter) {
05393       ast_mutex_unlock(&context_merge_lock);
05394       ast_free(hint_app);
05395       return;
05396    }
05397 
05398    for (; (device = ao2_iterator_next(dev_iter)); ao2_t_ref(device, -1, "Next device")) {
05399       struct ast_state_cb *state_cb;
05400       int state;
05401       int same_state;
05402       struct ao2_container *device_state_info;
05403       int first_extended_cb_call = 1;
05404 
05405       if (!device->hint) {
05406          /* Should never happen. */
05407          continue;
05408       }
05409       hint = device->hint;
05410 
05411       ao2_lock(hint);
05412       if (!hint->exten) {
05413          /* The extension has already been destroyed */
05414          ao2_unlock(hint);
05415          continue;
05416       }
05417 
05418       /*
05419        * Save off strings in case the hint extension gets destroyed
05420        * while we are notifying the watchers.
05421        */
05422       ast_copy_string(context_name,
05423          ast_get_context_name(ast_get_extension_context(hint->exten)),
05424          sizeof(context_name));
05425       ast_copy_string(exten_name, ast_get_extension_name(hint->exten),
05426          sizeof(exten_name));
05427       ast_str_set(&hint_app, 0, "%s", ast_get_extension_app(hint->exten));
05428       ao2_unlock(hint);
05429 
05430       /*
05431        * Get device state for this hint.
05432        *
05433        * NOTE: We cannot hold any locks while determining the hint
05434        * device state or notifying the watchers without causing a
05435        * deadlock.  (conlock, hints, and hint)
05436        */
05437       /* Make a container so state3 can fill it if we wish.
05438        * If that failed we simply do not provide the extended state info.
05439        */
05440       device_state_info = alloc_device_state_info();
05441       state = ast_extension_state3(hint_app, device_state_info);
05442       if ((same_state = state == hint->laststate) && (~state & AST_EXTENSION_RINGING)) {
05443          ao2_cleanup(device_state_info);
05444          continue;
05445       }
05446 
05447       /* Device state changed since last check - notify the watchers. */
05448       hint->laststate = state;   /* record we saw the change */
05449 
05450       /* For general callbacks */
05451       cb_iter = ao2_iterator_init(statecbs, 0);
05452       for (; !same_state && (state_cb = ao2_iterator_next(&cb_iter)); ao2_ref(state_cb, -1)) {
05453          execute_state_callback(state_cb->change_cb,
05454             context_name,
05455             exten_name,
05456             state_cb->data,
05457             AST_HINT_UPDATE_DEVICE,
05458             hint,
05459             NULL);
05460       }
05461       ao2_iterator_destroy(&cb_iter);
05462 
05463       /* For extension callbacks */
05464       /* extended callbacks are called when the state changed or when AST_STATE_RINGING is
05465        * included. Normal callbacks are only called when the state changed.
05466        */
05467       cb_iter = ao2_iterator_init(hint->callbacks, 0);
05468       for (; (state_cb = ao2_iterator_next(&cb_iter)); ao2_ref(state_cb, -1)) {
05469          if (state_cb->extended && first_extended_cb_call) {
05470             /* Fill detailed device_state_info now that we know it is used by extd. callback */
05471             first_extended_cb_call = 0;
05472             get_device_state_causing_channels(device_state_info);
05473          }
05474          if (state_cb->extended || !same_state) {
05475             execute_state_callback(state_cb->change_cb,
05476                context_name,
05477                exten_name,
05478                state_cb->data,
05479                AST_HINT_UPDATE_DEVICE,
05480                hint,
05481                state_cb->extended ? device_state_info : NULL);
05482          }
05483       }
05484       ao2_iterator_destroy(&cb_iter);
05485 
05486       ao2_cleanup(device_state_info);
05487    }
05488    ast_mutex_unlock(&context_merge_lock);
05489 
05490    ao2_iterator_destroy(dev_iter);
05491    ast_free(hint_app);
05492    return;
05493 }
05494 
05495 /*!
05496  * \internal
05497  * \brief Destroy the given state callback object.
05498  *
05499  * \param doomed State callback to destroy.
05500  *
05501  * \return Nothing
05502  */
05503 static void destroy_state_cb(void *doomed)
05504 {
05505    struct ast_state_cb *state_cb = doomed;
05506 
05507    if (state_cb->destroy_cb) {
05508       state_cb->destroy_cb(state_cb->id, state_cb->data);
05509    }
05510 }
05511 
05512 /*!
05513  * \internal
05514  * \brief Add watcher for extension states with destructor
05515  */
05516 static int extension_state_add_destroy(const char *context, const char *exten,
05517    ast_state_cb_type change_cb, ast_state_cb_destroy_type destroy_cb, void *data, int extended)
05518 {
05519    struct ast_hint *hint;
05520    struct ast_state_cb *state_cb;
05521    struct ast_exten *e;
05522    int id;
05523 
05524    /* If there's no context and extension:  add callback to statecbs list */
05525    if (!context && !exten) {
05526       /* Prevent multiple adds from adding the same change_cb at the same time. */
05527       ao2_lock(statecbs);
05528 
05529       /* Remove any existing change_cb. */
05530       ao2_find(statecbs, change_cb, OBJ_UNLINK | OBJ_NODATA);
05531 
05532       /* Now insert the change_cb */
05533       if (!(state_cb = ao2_alloc(sizeof(*state_cb), destroy_state_cb))) {
05534          ao2_unlock(statecbs);
05535          return -1;
05536       }
05537       state_cb->id = 0;
05538       state_cb->change_cb = change_cb;
05539       state_cb->destroy_cb = destroy_cb;
05540       state_cb->data = data;
05541       state_cb->extended = extended;
05542       ao2_link(statecbs, state_cb);
05543 
05544       ao2_ref(state_cb, -1);
05545       ao2_unlock(statecbs);
05546       return 0;
05547    }
05548 
05549    if (!context || !exten)
05550       return -1;
05551 
05552    /* This callback type is for only one hint, so get the hint */
05553    e = ast_hint_extension(NULL, context, exten);
05554    if (!e) {
05555       return -1;
05556    }
05557 
05558    /* If this is a pattern, dynamically create a new extension for this
05559     * particular match.  Note that this will only happen once for each
05560     * individual extension, because the pattern will no longer match first.
05561     */
05562    if (e->exten[0] == '_') {
05563       ast_add_extension(e->parent->name, 0, exten, e->priority, e->label,
05564          e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr,
05565          e->registrar);
05566       e = ast_hint_extension(NULL, context, exten);
05567       if (!e || e->exten[0] == '_') {
05568          return -1;
05569       }
05570    }
05571 
05572    /* Find the hint in the hints container */
05573    ao2_lock(hints);/* Locked to hold off ast_merge_contexts_and_delete */
05574    hint = ao2_find(hints, e, 0);
05575    if (!hint) {
05576       ao2_unlock(hints);
05577       return -1;
05578    }
05579 
05580    /* Now insert the callback in the callback list  */
05581    if (!(state_cb = ao2_alloc(sizeof(*state_cb), destroy_state_cb))) {
05582       ao2_ref(hint, -1);
05583       ao2_unlock(hints);
05584       return -1;
05585    }
05586    do {
05587       id = stateid++;      /* Unique ID for this callback */
05588       /* Do not allow id to ever be -1 or 0. */
05589    } while (id == -1 || id == 0);
05590    state_cb->id = id;
05591    state_cb->change_cb = change_cb; /* Pointer to callback routine */
05592    state_cb->destroy_cb = destroy_cb;
05593    state_cb->data = data;     /* Data for the callback */
05594    state_cb->extended = extended;
05595    ao2_link(hint->callbacks, state_cb);
05596 
05597    ao2_ref(state_cb, -1);
05598    ao2_ref(hint, -1);
05599    ao2_unlock(hints);
05600 
05601    return id;
05602 }
05603 
05604 /*! \brief Add watcher for extension states with destructor */
05605 int ast_extension_state_add_destroy(const char *context, const char *exten,
05606    ast_state_cb_type change_cb, ast_state_cb_destroy_type destroy_cb, void *data)
05607 {
05608    return extension_state_add_destroy(context, exten, change_cb, destroy_cb, data, 0);
05609 }
05610 
05611 /*! \brief Add watcher for extension states */
05612 int ast_extension_state_add(const char *context, const char *exten,
05613    ast_state_cb_type change_cb, void *data)
05614 {
05615    return extension_state_add_destroy(context, exten, change_cb, NULL, data, 0);
05616 }
05617 
05618 /*! \brief Add watcher for extended extension states with destructor */
05619 int ast_extension_state_add_destroy_extended(const char *context, const char *exten,
05620    ast_state_cb_type change_cb, ast_state_cb_destroy_type destroy_cb, void *data)
05621 {
05622    return extension_state_add_destroy(context, exten, change_cb, destroy_cb, data, 1);
05623 }
05624 
05625 /*! \brief Add watcher for extended extension states */
05626 int ast_extension_state_add_extended(const char *context, const char *exten,
05627    ast_state_cb_type change_cb, void *data)
05628 {
05629    return extension_state_add_destroy(context, exten, change_cb, NULL, data, 1);
05630 }
05631 
05632 /*! \brief Find Hint by callback id */
05633 static int find_hint_by_cb_id(void *obj, void *arg, int flags)
05634 {
05635    struct ast_state_cb *state_cb;
05636    const struct ast_hint *hint = obj;
05637    int *id = arg;
05638 
05639    if ((state_cb = ao2_find(hint->callbacks, id, 0))) {
05640       ao2_ref(state_cb, -1);
05641       return CMP_MATCH | CMP_STOP;
05642    }
05643 
05644    return 0;
05645 }
05646 
05647 /*! \brief  ast_extension_state_del: Remove a watcher from the callback list */
05648 int ast_extension_state_del(int id, ast_state_cb_type change_cb)
05649 {
05650    struct ast_state_cb *p_cur;
05651    int ret = -1;
05652 
05653    if (!id) {  /* id == 0 is a callback without extension */
05654       if (!change_cb) {
05655          return ret;
05656       }
05657       p_cur = ao2_find(statecbs, change_cb, OBJ_UNLINK);
05658       if (p_cur) {
05659          ret = 0;
05660          ao2_ref(p_cur, -1);
05661       }
05662    } else { /* callback with extension, find the callback based on ID */
05663       struct ast_hint *hint;
05664 
05665       ao2_lock(hints);/* Locked to hold off ast_merge_contexts_and_delete */
05666       hint = ao2_callback(hints, 0, find_hint_by_cb_id, &id);
05667       if (hint) {
05668          p_cur = ao2_find(hint->callbacks, &id, OBJ_UNLINK);
05669          if (p_cur) {
05670             ret = 0;
05671             ao2_ref(p_cur, -1);
05672          }
05673          ao2_ref(hint, -1);
05674       }
05675       ao2_unlock(hints);
05676    }
05677 
05678    return ret;
05679 }
05680 
05681 static int hint_id_cmp(void *obj, void *arg, int flags)
05682 {
05683    const struct ast_state_cb *cb = obj;
05684    int *id = arg;
05685 
05686    return (cb->id == *id) ? CMP_MATCH | CMP_STOP : 0;
05687 }
05688 
05689 /*!
05690  * \internal
05691  * \brief Destroy the given hint object.
05692  *
05693  * \param obj Hint to destroy.
05694  *
05695  * \return Nothing
05696  */
05697 static void destroy_hint(void *obj)
05698 {
05699    struct ast_hint *hint = obj;
05700 
05701    if (hint->callbacks) {
05702       struct ast_state_cb *state_cb;
05703       const char *context_name;
05704       const char *exten_name;
05705 
05706       if (hint->exten) {
05707          context_name = ast_get_context_name(ast_get_extension_context(hint->exten));
05708          exten_name = ast_get_extension_name(hint->exten);
05709          hint->exten = NULL;
05710       } else {
05711          /* The extension has already been destroyed */
05712          context_name = hint->context_name;
05713          exten_name = hint->exten_name;
05714       }
05715       hint->laststate = AST_EXTENSION_DEACTIVATED;
05716       while ((state_cb = ao2_callback(hint->callbacks, OBJ_UNLINK, NULL, NULL))) {
05717          /* Notify with -1 and remove all callbacks */
05718          execute_state_callback(state_cb->change_cb,
05719             context_name,
05720             exten_name,
05721             state_cb->data,
05722             AST_HINT_UPDATE_DEVICE,
05723             hint,
05724             NULL);
05725          ao2_ref(state_cb, -1);
05726       }
05727       ao2_ref(hint->callbacks, -1);
05728    }
05729    ast_free(hint->last_presence_subtype);
05730    ast_free(hint->last_presence_message);
05731 }
05732 
05733 /*! \brief Remove hint from extension */
05734 static int ast_remove_hint(struct ast_exten *e)
05735 {
05736    /* Cleanup the Notifys if hint is removed */
05737    struct ast_hint *hint;
05738 
05739    if (!e) {
05740       return -1;
05741    }
05742 
05743    hint = ao2_find(hints, e, OBJ_UNLINK);
05744    if (!hint) {
05745       return -1;
05746    }
05747 
05748    remove_hintdevice(hint);
05749 
05750    /*
05751     * The extension is being destroyed so we must save some
05752     * information to notify that the extension is deactivated.
05753     */
05754    ao2_lock(hint);
05755    ast_copy_string(hint->context_name,
05756       ast_get_context_name(ast_get_extension_context(hint->exten)),
05757       sizeof(hint->context_name));
05758    ast_copy_string(hint->exten_name, ast_get_extension_name(hint->exten),
05759       sizeof(hint->exten_name));
05760    hint->exten = NULL;
05761    ao2_unlock(hint);
05762 
05763    ao2_ref(hint, -1);
05764 
05765    return 0;
05766 }
05767 
05768 /*! \brief Add hint to hint list, check initial extension state */
05769 static int ast_add_hint(struct ast_exten *e)
05770 {
05771    struct ast_hint *hint_new;
05772    struct ast_hint *hint_found;
05773    char *message = NULL;
05774    char *subtype = NULL;
05775    int presence_state;
05776 
05777    if (!e) {
05778       return -1;
05779    }
05780 
05781    /*
05782     * We must create the hint we wish to add before determining if
05783     * it is already in the hints container to avoid possible
05784     * deadlock when getting the current extension state.
05785     */
05786    hint_new = ao2_alloc(sizeof(*hint_new), destroy_hint);
05787    if (!hint_new) {
05788       return -1;
05789    }
05790 
05791    /* Initialize new hint. */
05792    hint_new->callbacks = ao2_container_alloc(1, NULL, hint_id_cmp);
05793    if (!hint_new->callbacks) {
05794       ao2_ref(hint_new, -1);
05795       return -1;
05796    }
05797    hint_new->exten = e;
05798    if (strstr(e->app, "${") && e->exten[0] == '_') {
05799       /* The hint is dynamic and hasn't been evaluted yet */
05800       hint_new->laststate = AST_DEVICE_INVALID;
05801       hint_new->last_presence_state = AST_PRESENCE_INVALID;
05802    } else {
05803       hint_new->laststate = ast_extension_state2(e, NULL);
05804       if ((presence_state = extension_presence_state_helper(e, &subtype, &message)) > 0) {
05805          hint_new->last_presence_state = presence_state;
05806          hint_new->last_presence_subtype = subtype;
05807          hint_new->last_presence_message = message;
05808          message = subtype = NULL;
05809       }
05810    }
05811 
05812    /* Prevent multiple add hints from adding the same hint at the same time. */
05813    ao2_lock(hints);
05814 
05815    /* Search if hint exists, do nothing */
05816    hint_found = ao2_find(hints, e, 0);
05817    if (hint_found) {
05818       ao2_ref(hint_found, -1);
05819       ao2_unlock(hints);
05820       ao2_ref(hint_new, -1);
05821       ast_debug(2, "HINTS: Not re-adding existing hint %s: %s\n",
05822          ast_get_extension_name(e), ast_get_extension_app(e));
05823       return -1;
05824    }
05825 
05826    /* Add new hint to the hints container */
05827    ast_debug(2, "HINTS: Adding hint %s: %s\n",
05828       ast_get_extension_name(e), ast_get_extension_app(e));
05829    ao2_link(hints, hint_new);
05830    if (add_hintdevice(hint_new, ast_get_extension_app(e))) {
05831       ast_log(LOG_WARNING, "Could not add devices for hint: %s@%s.\n",
05832          ast_get_extension_name(e),
05833          ast_get_context_name(ast_get_extension_context(e)));
05834    }
05835 
05836    /* if not dynamic */
05837    if (!(strstr(e->app, "${") && e->exten[0] == '_')) {
05838       struct ast_state_cb *state_cb;
05839       struct ao2_iterator cb_iter;
05840 
05841       /* For general callbacks */
05842       cb_iter = ao2_iterator_init(statecbs, 0);
05843       for (; (state_cb = ao2_iterator_next(&cb_iter)); ao2_ref(state_cb, -1)) {
05844          execute_state_callback(state_cb->change_cb,
05845                ast_get_context_name(ast_get_extension_context(e)),
05846                ast_get_extension_name(e),
05847                state_cb->data,
05848                AST_HINT_UPDATE_DEVICE,
05849                hint_new,
05850                NULL);
05851       }
05852       ao2_iterator_destroy(&cb_iter);
05853    }
05854    ao2_unlock(hints);
05855    ao2_ref(hint_new, -1);
05856 
05857    return 0;
05858 }
05859 
05860 /*! \brief Change hint for an extension */
05861 static int ast_change_hint(struct ast_exten *oe, struct ast_exten *ne)
05862 {
05863    struct ast_hint *hint;
05864 
05865    if (!oe || !ne) {
05866       return -1;
05867    }
05868 
05869    ao2_lock(hints);/* Locked to hold off others while we move the hint around. */
05870 
05871    /*
05872     * Unlink the hint from the hints container as the extension
05873     * name (which is the hash value) could change.
05874     */
05875    hint = ao2_find(hints, oe, OBJ_UNLINK);
05876    if (!hint) {
05877       ao2_unlock(hints);
05878       return -1;
05879    }
05880 
05881    remove_hintdevice(hint);
05882 
05883    /* Update the hint and put it back in the hints container. */
05884    ao2_lock(hint);
05885    hint->exten = ne;
05886    ao2_unlock(hint);
05887    ao2_link(hints, hint);
05888    if (add_hintdevice(hint, ast_get_extension_app(ne))) {
05889       ast_log(LOG_WARNING, "Could not add devices for hint: %s@%s.\n",
05890          ast_get_extension_name(ne),
05891          ast_get_context_name(ast_get_extension_context(ne)));
05892    }
05893 
05894    ao2_unlock(hints);
05895    ao2_ref(hint, -1);
05896 
05897    return 0;
05898 }
05899 
05900 
05901 /*! \brief Get hint for channel */
05902 int ast_get_hint(char *hint, int hintsize, char *name, int namesize, struct ast_channel *c, const char *context, const char *exten)
05903 {
05904    struct ast_exten *e = ast_hint_extension(c, context, exten);
05905 
05906    if (e) {
05907       if (hint)
05908          ast_copy_string(hint, ast_get_extension_app(e), hintsize);
05909       if (name) {
05910          const char *tmp = ast_get_extension_app_data(e);
05911          if (tmp)
05912             ast_copy_string(name, tmp, namesize);
05913       }
05914       return -1;
05915    }
05916    return 0;
05917 }
05918 
05919 /*! \brief Get hint for channel */
05920 int ast_str_get_hint(struct ast_str **hint, ssize_t hintsize, struct ast_str **name, ssize_t namesize, struct ast_channel *c, const char *context, const char *exten)
05921 {
05922    struct ast_exten *e = ast_hint_extension(c, context, exten);
05923 
05924    if (!e) {
05925       return 0;
05926    }
05927 
05928    if (hint) {
05929       ast_str_set(hint, hintsize, "%s", ast_get_extension_app(e));
05930    }
05931    if (name) {
05932       const char *tmp = ast_get_extension_app_data(e);
05933       if (tmp) {
05934          ast_str_set(name, namesize, "%s", tmp);
05935       }
05936    }
05937    return -1;
05938 }
05939 
05940 int ast_exists_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
05941 {
05942    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCH, 0, 0);
05943 }
05944 
05945 int ast_findlabel_extension(struct ast_channel *c, const char *context, const char *exten, const char *label, const char *callerid)
05946 {
05947    return pbx_extension_helper(c, NULL, context, exten, 0, label, callerid, E_FINDLABEL, 0, 0);
05948 }
05949 
05950 int ast_findlabel_extension2(struct ast_channel *c, struct ast_context *con, const char *exten, const char *label, const char *callerid)
05951 {
05952    return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, E_FINDLABEL, 0, 0);
05953 }
05954 
05955 int ast_canmatch_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
05956 {
05957    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_CANMATCH, 0, 0);
05958 }
05959 
05960 int ast_matchmore_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
05961 {
05962    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCHMORE, 0, 0);
05963 }
05964 
05965 int ast_spawn_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid, int *found, int combined_find_spawn)
05966 {
05967    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_SPAWN, found, combined_find_spawn);
05968 }
05969 
05970 void ast_pbx_h_exten_run(struct ast_channel *chan, const char *context)
05971 {
05972    int autoloopflag;
05973    int found;
05974    int spawn_error;
05975 
05976    ast_channel_lock(chan);
05977 
05978    /*
05979     * Make sure that the channel is marked as hungup since we are
05980     * going to run the h exten on it.
05981     */
05982    ast_softhangup_nolock(chan, AST_SOFTHANGUP_HANGUP_EXEC);
05983 
05984    /* Set h exten location */
05985    if (context != ast_channel_context(chan)) {
05986       ast_channel_context_set(chan, context);
05987    }
05988    ast_channel_exten_set(chan, "h");
05989    ast_channel_priority_set(chan, 1);
05990 
05991    /* Save autoloop flag */
05992    autoloopflag = ast_test_flag(ast_channel_flags(chan), AST_FLAG_IN_AUTOLOOP);
05993    ast_set_flag(ast_channel_flags(chan), AST_FLAG_IN_AUTOLOOP);
05994    ast_channel_unlock(chan);
05995 
05996    for (;;) {
05997       spawn_error = ast_spawn_extension(chan, ast_channel_context(chan),
05998          ast_channel_exten(chan), ast_channel_priority(chan),
05999          S_COR(ast_channel_caller(chan)->id.number.valid,
06000             ast_channel_caller(chan)->id.number.str, NULL), &found, 1);
06001 
06002       ast_channel_lock(chan);
06003       if (spawn_error) {
06004          /* The code after the loop needs the channel locked. */
06005          break;
06006       }
06007       ast_channel_priority_set(chan, ast_channel_priority(chan) + 1);
06008       ast_channel_unlock(chan);
06009    }
06010    if (found && spawn_error) {
06011       /* Something bad happened, or a hangup has been requested. */
06012       ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n",
06013          ast_channel_context(chan), ast_channel_exten(chan),
06014          ast_channel_priority(chan), ast_channel_name(chan));
06015       ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n",
06016          ast_channel_context(chan), ast_channel_exten(chan),
06017          ast_channel_priority(chan), ast_channel_name(chan));
06018    }
06019 
06020    /* An "h" exten has been run, so indicate that one has been run. */
06021    ast_set_flag(ast_channel_flags(chan), AST_FLAG_BRIDGE_HANGUP_RUN);
06022 
06023    /* Restore autoloop flag */
06024    ast_set2_flag(ast_channel_flags(chan), autoloopflag, AST_FLAG_IN_AUTOLOOP);
06025    ast_channel_unlock(chan);
06026 }
06027 
06028 /*!
06029  * \internal
06030  * \brief Publish a hangup handler related message to \ref stasis
06031  */
06032 static void publish_hangup_handler_message(const char *action, struct ast_channel *chan, const char *handler)
06033 {
06034    RAII_VAR(struct ast_json *, blob, NULL, ast_json_unref);
06035 
06036    blob = ast_json_pack("{s: s, s: s}",
06037          "type", action,
06038          "handler", S_OR(handler, ""));
06039    if (!blob) {
06040       return;
06041    }
06042 
06043    ast_channel_publish_blob(chan, ast_channel_hangup_handler_type(), blob);
06044 }
06045 
06046 int ast_pbx_hangup_handler_run(struct ast_channel *chan)
06047 {
06048    struct ast_hangup_handler_list *handlers;
06049    struct ast_hangup_handler *h_handler;
06050 
06051    ast_channel_lock(chan);
06052    handlers = ast_channel_hangup_handlers(chan);
06053    if (AST_LIST_EMPTY(handlers)) {
06054       ast_channel_unlock(chan);
06055       return 0;
06056    }
06057 
06058    /*
06059     * Make sure that the channel is marked as hungup since we are
06060     * going to run the hangup handlers on it.
06061     */
06062    ast_softhangup_nolock(chan, AST_SOFTHANGUP_HANGUP_EXEC);
06063 
06064    for (;;) {
06065       handlers = ast_channel_hangup_handlers(chan);
06066       h_handler = AST_LIST_REMOVE_HEAD(handlers, node);
06067       if (!h_handler) {
06068          break;
06069       }
06070 
06071       publish_hangup_handler_message("run", chan, h_handler->args);
06072       ast_channel_unlock(chan);
06073 
06074       ast_app_exec_sub(NULL, chan, h_handler->args, 1);
06075       ast_free(h_handler);
06076 
06077       ast_channel_lock(chan);
06078    }
06079    ast_channel_unlock(chan);
06080    return 1;
06081 }
06082 
06083 void ast_pbx_hangup_handler_init(struct ast_channel *chan)
06084 {
06085    struct ast_hangup_handler_list *handlers;
06086 
06087    handlers = ast_channel_hangup_handlers(chan);
06088    AST_LIST_HEAD_INIT_NOLOCK(handlers);
06089 }
06090 
06091 void ast_pbx_hangup_handler_destroy(struct ast_channel *chan)
06092 {
06093    struct ast_hangup_handler_list *handlers;
06094    struct ast_hangup_handler *h_handler;
06095 
06096    ast_channel_lock(chan);
06097 
06098    /* Get rid of each of the hangup handlers on the channel */
06099    handlers = ast_channel_hangup_handlers(chan);
06100    while ((h_handler = AST_LIST_REMOVE_HEAD(handlers, node))) {
06101       ast_free(h_handler);
06102    }
06103 
06104    ast_channel_unlock(chan);
06105 }
06106 
06107 int ast_pbx_hangup_handler_pop(struct ast_channel *chan)
06108 {
06109    struct ast_hangup_handler_list *handlers;
06110    struct ast_hangup_handler *h_handler;
06111 
06112    ast_channel_lock(chan);
06113    handlers = ast_channel_hangup_handlers(chan);
06114    h_handler = AST_LIST_REMOVE_HEAD(handlers, node);
06115    if (h_handler) {
06116       publish_hangup_handler_message("pop", chan, h_handler->args);
06117    }
06118    ast_channel_unlock(chan);
06119    if (h_handler) {
06120       ast_free(h_handler);
06121       return 1;
06122    }
06123    return 0;
06124 }
06125 
06126 void ast_pbx_hangup_handler_push(struct ast_channel *chan, const char *handler)
06127 {
06128    struct ast_hangup_handler_list *handlers;
06129    struct ast_hangup_handler *h_handler;
06130    const char *expanded_handler;
06131 
06132    if (ast_strlen_zero(handler)) {
06133       return;
06134    }
06135 
06136    expanded_handler = ast_app_expand_sub_args(chan, handler);
06137    if (!expanded_handler) {
06138       return;
06139    }
06140    h_handler = ast_malloc(sizeof(*h_handler) + 1 + strlen(expanded_handler));
06141    if (!h_handler) {
06142       ast_free((char *) expanded_handler);
06143       return;
06144    }
06145    strcpy(h_handler->args, expanded_handler);/* Safe */
06146    ast_free((char *) expanded_handler);
06147 
06148    ast_channel_lock(chan);
06149 
06150    handlers = ast_channel_hangup_handlers(chan);
06151    AST_LIST_INSERT_HEAD(handlers, h_handler, node);
06152    publish_hangup_handler_message("push", chan, h_handler->args);
06153    ast_channel_unlock(chan);
06154 }
06155 
06156 #define HANDLER_FORMAT  "%-30s %s\n"
06157 
06158 /*!
06159  * \internal
06160  * \brief CLI output the hangup handler headers.
06161  * \since 11.0
06162  *
06163  * \param fd CLI file descriptor to use.
06164  *
06165  * \return Nothing
06166  */
06167 static void ast_pbx_hangup_handler_headers(int fd)
06168 {
06169    ast_cli(fd, HANDLER_FORMAT, "Channel", "Handler");
06170 }
06171 
06172 /*!
06173  * \internal
06174  * \brief CLI output the channel hangup handlers.
06175  * \since 11.0
06176  *
06177  * \param fd CLI file descriptor to use.
06178  * \param chan Channel to show hangup handlers.
06179  *
06180  * \return Nothing
06181  */
06182 static void ast_pbx_hangup_handler_show(int fd, struct ast_channel *chan)
06183 {
06184    struct ast_hangup_handler_list *handlers;
06185    struct ast_hangup_handler *h_handler;
06186    int first = 1;
06187 
06188    ast_channel_lock(chan);
06189    handlers = ast_channel_hangup_handlers(chan);
06190    AST_LIST_TRAVERSE(handlers, h_handler, node) {
06191       ast_cli(fd, HANDLER_FORMAT, first ? ast_channel_name(chan) : "", h_handler->args);
06192       first = 0;
06193    }
06194    ast_channel_unlock(chan);
06195 }
06196 
06197 /*
06198  * \brief 'show hanguphandlers <channel>' CLI command implementation function...
06199  */
06200 static char *handle_show_hangup_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
06201 {
06202    struct ast_channel *chan;
06203 
06204    switch (cmd) {
06205    case CLI_INIT:
06206       e->command = "core show hanguphandlers";
06207       e->usage =
06208          "Usage: core show hanguphandlers <channel>\n"
06209          "       Show hangup handlers of a specified channel.\n";
06210       return NULL;
06211    case CLI_GENERATE:
06212       return ast_complete_channels(a->line, a->word, a->pos, a->n, e->args);
06213    }
06214 
06215    if (a->argc < 4) {
06216       return CLI_SHOWUSAGE;
06217    }
06218 
06219    chan = ast_channel_get_by_name(a->argv[3]);
06220    if (!chan) {
06221       ast_cli(a->fd, "Channel does not exist.\n");
06222       return CLI_FAILURE;
06223    }
06224 
06225    ast_pbx_hangup_handler_headers(a->fd);
06226    ast_pbx_hangup_handler_show(a->fd, chan);
06227 
06228    ast_channel_unref(chan);
06229 
06230    return CLI_SUCCESS;
06231 }
06232 
06233 /*
06234  * \brief 'show hanguphandlers all' CLI command implementation function...
06235  */
06236 static char *handle_show_hangup_all(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
06237 {
06238    struct ast_channel_iterator *iter;
06239    struct ast_channel *chan;
06240 
06241    switch (cmd) {
06242    case CLI_INIT:
06243       e->command = "core show hanguphandlers all";
06244       e->usage =
06245          "Usage: core show hanguphandlers all\n"
06246          "       Show hangup handlers for all channels.\n";
06247       return NULL;
06248    case CLI_GENERATE:
06249       return ast_complete_channels(a->line, a->word, a->pos, a->n, e->args);
06250    }
06251 
06252    if (a->argc < 4) {
06253       return CLI_SHOWUSAGE;
06254    }
06255 
06256    iter = ast_channel_iterator_all_new();
06257    if (!iter) {
06258       return CLI_FAILURE;
06259    }
06260 
06261    ast_pbx_hangup_handler_headers(a->fd);
06262    for (; (chan = ast_channel_iterator_next(iter)); ast_channel_unref(chan)) {
06263       ast_pbx_hangup_handler_show(a->fd, chan);
06264    }
06265    ast_channel_iterator_destroy(iter);
06266 
06267    return CLI_SUCCESS;
06268 }
06269 
06270 /*! helper function to set extension and priority */
06271 static void set_ext_pri(struct ast_channel *c, const char *exten, int pri)
06272 {
06273    ast_channel_lock(c);
06274    ast_channel_exten_set(c, exten);
06275    ast_channel_priority_set(c, pri);
06276    ast_channel_unlock(c);
06277 }
06278 
06279 /*!
06280  * \brief collect digits from the channel into the buffer.
06281  * \param c, buf, buflen, pos
06282  * \param waittime is in milliseconds
06283  * \retval 0 on timeout or done.
06284  * \retval -1 on error.
06285 */
06286 static int collect_digits(struct ast_channel *c, int waittime, char *buf, int buflen, int pos)
06287 {
06288    int digit;
06289 
06290    buf[pos] = '\0';  /* make sure it is properly terminated */
06291    while (ast_matchmore_extension(c, ast_channel_context(c), buf, 1,
06292       S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
06293       /* As long as we're willing to wait, and as long as it's not defined,
06294          keep reading digits until we can't possibly get a right answer anymore.  */
06295       digit = ast_waitfordigit(c, waittime);
06296       if (ast_channel_softhangup_internal_flag(c) & AST_SOFTHANGUP_ASYNCGOTO) {
06297          ast_channel_clear_softhangup(c, AST_SOFTHANGUP_ASYNCGOTO);
06298       } else {
06299          if (!digit) /* No entry */
06300             break;
06301          if (digit < 0) /* Error, maybe a  hangup */
06302             return -1;
06303          if (pos < buflen - 1) { /* XXX maybe error otherwise ? */
06304             buf[pos++] = digit;
06305             buf[pos] = '\0';
06306          }
06307          waittime = ast_channel_pbx(c)->dtimeoutms;
06308       }
06309    }
06310    return 0;
06311 }
06312 
06313 static enum ast_pbx_result __ast_pbx_run(struct ast_channel *c,
06314       struct ast_pbx_args *args)
06315 {
06316    int found = 0; /* set if we find at least one match */
06317    int res = 0;
06318    int autoloopflag;
06319    int error = 0;    /* set an error conditions */
06320    struct ast_pbx *pbx;
06321    ast_callid callid;
06322 
06323    /* A little initial setup here */
06324    if (ast_channel_pbx(c)) {
06325       ast_log(LOG_WARNING, "%s already has PBX structure??\n", ast_channel_name(c));
06326       /* XXX and now what ? */
06327       ast_free(ast_channel_pbx(c));
06328    }
06329    if (!(pbx = ast_calloc(1, sizeof(*pbx)))) {
06330       return AST_PBX_FAILED;
06331    }
06332 
06333    callid = ast_read_threadstorage_callid();
06334    /* If the thread isn't already associated with a callid, we should create that association. */
06335    if (!callid) {
06336       /* Associate new PBX thread with the channel call id if it is availble.
06337        * If not, create a new one instead.
06338        */
06339       callid = ast_channel_callid(c);
06340       if (!callid) {
06341          callid = ast_create_callid();
06342          if (callid) {
06343             ast_channel_lock(c);
06344             ast_channel_callid_set(c, callid);
06345             ast_channel_unlock(c);
06346          }
06347       }
06348       ast_callid_threadassoc_add(callid);
06349       callid = 0;
06350    }
06351 
06352    ast_channel_pbx_set(c, pbx);
06353    /* Set reasonable defaults */
06354    ast_channel_pbx(c)->rtimeoutms = 10000;
06355    ast_channel_pbx(c)->dtimeoutms = 5000;
06356 
06357    autoloopflag = ast_test_flag(ast_channel_flags(c), AST_FLAG_IN_AUTOLOOP);  /* save value to restore at the end */
06358    ast_set_flag(ast_channel_flags(c), AST_FLAG_IN_AUTOLOOP);
06359 
06360    if (ast_strlen_zero(ast_channel_exten(c))) {
06361       /* If not successful fall back to 's' - but only if there is no given exten  */
06362       ast_verb(2, "Starting %s at %s,%s,%d failed so falling back to exten 's'\n", ast_channel_name(c), ast_channel_context(c), ast_channel_exten(c), ast_channel_priority(c));
06363       /* XXX the original code used the existing priority in the call to
06364        * ast_exists_extension(), and reset it to 1 afterwards.
06365        * I believe the correct thing is to set it to 1 immediately.
06366       */
06367       set_ext_pri(c, "s", 1);
06368    }
06369 
06370    for (;;) {
06371       char dst_exten[256]; /* buffer to accumulate digits */
06372       int pos = 0;      /* XXX should check bounds */
06373       int digit = 0;
06374       int invalid = 0;
06375       int timeout = 0;
06376 
06377       /* No digits pressed yet */
06378       dst_exten[pos] = '\0';
06379 
06380       /* loop on priorities in this context/exten */
06381       while (!(res = ast_spawn_extension(c, ast_channel_context(c), ast_channel_exten(c), ast_channel_priority(c),
06382          S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL),
06383          &found, 1))) {
06384 
06385          if (!ast_check_hangup(c)) {
06386             ast_channel_priority_set(c, ast_channel_priority(c) + 1);
06387             continue;
06388          }
06389 
06390          /* Check softhangup flags. */
06391          if (ast_channel_softhangup_internal_flag(c) & AST_SOFTHANGUP_ASYNCGOTO) {
06392             ast_channel_clear_softhangup(c, AST_SOFTHANGUP_ASYNCGOTO);
06393             continue;
06394          }
06395          if (ast_channel_softhangup_internal_flag(c) & AST_SOFTHANGUP_TIMEOUT) {
06396             if (ast_exists_extension(c, ast_channel_context(c), "T", 1,
06397                S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
06398                set_ext_pri(c, "T", 1);
06399                /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
06400                memset(ast_channel_whentohangup(c), 0, sizeof(*ast_channel_whentohangup(c)));
06401                ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT);
06402                continue;
06403             } else if (ast_exists_extension(c, ast_channel_context(c), "e", 1,
06404                S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
06405                raise_exception(c, "ABSOLUTETIMEOUT", 1);
06406                /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
06407                memset(ast_channel_whentohangup(c), 0, sizeof(*ast_channel_whentohangup(c)));
06408                ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT);
06409                continue;
06410             }
06411 
06412             /* Call timed out with no special extension to jump to. */
06413             error = 1;
06414             break;
06415          }
06416          ast_debug(1, "Extension %s, priority %d returned normally even though call was hung up\n",
06417             ast_channel_exten(c), ast_channel_priority(c));
06418          error = 1;
06419          break;
06420       } /* end while  - from here on we can use 'break' to go out */
06421       if (found && res) {
06422          /* Something bad happened, or a hangup has been requested. */
06423          if (strchr("0123456789ABCDEF*#", res)) {
06424             ast_debug(1, "Oooh, got something to jump out with ('%c')!\n", res);
06425             pos = 0;
06426             dst_exten[pos++] = digit = res;
06427             dst_exten[pos] = '\0';
06428          } else if (res == AST_PBX_INCOMPLETE) {
06429             ast_debug(1, "Spawn extension (%s,%s,%d) exited INCOMPLETE on '%s'\n", ast_channel_context(c), ast_channel_exten(c), ast_channel_priority(c), ast_channel_name(c));
06430             ast_verb(2, "Spawn extension (%s, %s, %d) exited INCOMPLETE on '%s'\n", ast_channel_context(c), ast_channel_exten(c), ast_channel_priority(c), ast_channel_name(c));
06431 
06432             /* Don't cycle on incomplete - this will happen if the only extension that matches is our "incomplete" extension */
06433             if (!ast_matchmore_extension(c, ast_channel_context(c), ast_channel_exten(c), 1,
06434                S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
06435                invalid = 1;
06436             } else {
06437                ast_copy_string(dst_exten, ast_channel_exten(c), sizeof(dst_exten));
06438                digit = 1;
06439                pos = strlen(dst_exten);
06440             }
06441          } else {
06442             ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", ast_channel_context(c), ast_channel_exten(c), ast_channel_priority(c), ast_channel_name(c));
06443             ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", ast_channel_context(c), ast_channel_exten(c), ast_channel_priority(c), ast_channel_name(c));
06444 
06445             if ((res == AST_PBX_ERROR)
06446                && ast_exists_extension(c, ast_channel_context(c), "e", 1,
06447                   S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
06448                /* if we are already on the 'e' exten, don't jump to it again */
06449                if (!strcmp(ast_channel_exten(c), "e")) {
06450                   ast_verb(2, "Spawn extension (%s, %s, %d) exited ERROR while already on 'e' exten on '%s'\n", ast_channel_context(c), ast_channel_exten(c), ast_channel_priority(c), ast_channel_name(c));
06451                   error = 1;
06452                } else {
06453                   raise_exception(c, "ERROR", 1);
06454                   continue;
06455                }
06456             }
06457 
06458             if (ast_channel_softhangup_internal_flag(c) & AST_SOFTHANGUP_ASYNCGOTO) {
06459                ast_channel_clear_softhangup(c, AST_SOFTHANGUP_ASYNCGOTO);
06460                continue;
06461             }
06462             if (ast_channel_softhangup_internal_flag(c) & AST_SOFTHANGUP_TIMEOUT) {
06463                if (ast_exists_extension(c, ast_channel_context(c), "T", 1,
06464                   S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
06465                   set_ext_pri(c, "T", 1);
06466                   /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
06467                   memset(ast_channel_whentohangup(c), 0, sizeof(*ast_channel_whentohangup(c)));
06468                   ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT);
06469                   continue;
06470                } else if (ast_exists_extension(c, ast_channel_context(c), "e", 1,
06471                   S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
06472                   raise_exception(c, "ABSOLUTETIMEOUT", 1);
06473                   /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
06474                   memset(ast_channel_whentohangup(c), 0, sizeof(*ast_channel_whentohangup(c)));
06475                   ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT);
06476                   continue;
06477                }
06478                /* Call timed out with no special extension to jump to. */
06479             }
06480             error = 1;
06481             break;
06482          }
06483       }
06484       if (error)
06485          break;
06486 
06487       /*!\note
06488        * We get here on a failure of some kind:  non-existing extension or
06489        * hangup.  We have options, here.  We can either catch the failure
06490        * and continue, or we can drop out entirely. */
06491 
06492       if (invalid
06493          || (ast_strlen_zero(dst_exten) &&
06494             !ast_exists_extension(c, ast_channel_context(c), ast_channel_exten(c), 1,
06495             S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL)))) {
06496          /*!\note
06497           * If there is no match at priority 1, it is not a valid extension anymore.
06498           * Try to continue at "i" (for invalid) or "e" (for exception) or exit if
06499           * neither exist.
06500           */
06501          if (ast_exists_extension(c, ast_channel_context(c), "i", 1,
06502             S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
06503             ast_verb(3, "Channel '%s' sent to invalid extension: context,exten,priority=%s,%s,%d\n",
06504                ast_channel_name(c), ast_channel_context(c), ast_channel_exten(c), ast_channel_priority(c));
06505             pbx_builtin_setvar_helper(c, "INVALID_EXTEN", ast_channel_exten(c));
06506             set_ext_pri(c, "i", 1);
06507          } else if (ast_exists_extension(c, ast_channel_context(c), "e", 1,
06508             S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
06509             raise_exception(c, "INVALID", 1);
06510          } else {
06511             ast_log(LOG_WARNING, "Channel '%s' sent to invalid extension but no invalid handler: context,exten,priority=%s,%s,%d\n",
06512                ast_channel_name(c), ast_channel_context(c), ast_channel_exten(c), ast_channel_priority(c));
06513             error = 1; /* we know what to do with it */
06514             break;
06515          }
06516       } else if (ast_channel_softhangup_internal_flag(c) & AST_SOFTHANGUP_TIMEOUT) {
06517          /* If we get this far with AST_SOFTHANGUP_TIMEOUT, then we know that the "T" extension is next. */
06518          ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT);
06519       } else { /* keypress received, get more digits for a full extension */
06520          int waittime = 0;
06521          if (digit)
06522             waittime = ast_channel_pbx(c)->dtimeoutms;
06523          else if (!autofallthrough)
06524             waittime = ast_channel_pbx(c)->rtimeoutms;
06525          if (!waittime) {
06526             const char *status = pbx_builtin_getvar_helper(c, "DIALSTATUS");
06527             if (!status)
06528                status = "UNKNOWN";
06529             ast_verb(3, "Auto fallthrough, channel '%s' status is '%s'\n", ast_channel_name(c), status);
06530             if (!strcasecmp(status, "CONGESTION"))
06531                res = pbx_builtin_congestion(c, "10");
06532             else if (!strcasecmp(status, "CHANUNAVAIL"))
06533                res = pbx_builtin_congestion(c, "10");
06534             else if (!strcasecmp(status, "BUSY"))
06535                res = pbx_builtin_busy(c, "10");
06536             error = 1; /* XXX disable message */
06537             break;   /* exit from the 'for' loop */
06538          }
06539 
06540          if (collect_digits(c, waittime, dst_exten, sizeof(dst_exten), pos))
06541             break;
06542          if (res == AST_PBX_INCOMPLETE && ast_strlen_zero(&dst_exten[pos]))
06543             timeout = 1;
06544          if (!timeout
06545             && ast_exists_extension(c, ast_channel_context(c), dst_exten, 1,
06546                S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) { /* Prepare the next cycle */
06547             set_ext_pri(c, dst_exten, 1);
06548          } else {
06549             /* No such extension */
06550             if (!timeout && !ast_strlen_zero(dst_exten)) {
06551                /* An invalid extension */
06552                if (ast_exists_extension(c, ast_channel_context(c), "i", 1,
06553                   S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
06554                   ast_verb(3, "Invalid extension '%s' in context '%s' on %s\n", dst_exten, ast_channel_context(c), ast_channel_name(c));
06555                   pbx_builtin_setvar_helper(c, "INVALID_EXTEN", dst_exten);
06556                   set_ext_pri(c, "i", 1);
06557                } else if (ast_exists_extension(c, ast_channel_context(c), "e", 1,
06558                   S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
06559                   raise_exception(c, "INVALID", 1);
06560                } else {
06561                   ast_log(LOG_WARNING,
06562                      "Invalid extension '%s', but no rule 'i' or 'e' in context '%s'\n",
06563                      dst_exten, ast_channel_context(c));
06564                   found = 1; /* XXX disable message */
06565                   break;
06566                }
06567             } else {
06568                /* A simple timeout */
06569                if (ast_exists_extension(c, ast_channel_context(c), "t", 1,
06570                   S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
06571                   ast_verb(3, "Timeout on %s\n", ast_channel_name(c));
06572                   set_ext_pri(c, "t", 1);
06573                } else if (ast_exists_extension(c, ast_channel_context(c), "e", 1,
06574                   S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
06575                   raise_exception(c, "RESPONSETIMEOUT", 1);
06576                } else {
06577                   ast_log(LOG_WARNING,
06578                      "Timeout, but no rule 't' or 'e' in context '%s'\n",
06579                      ast_channel_context(c));
06580                   found = 1; /* XXX disable message */
06581                   break;
06582                }
06583             }
06584          }
06585       }
06586    }
06587 
06588    if (!found && !error) {
06589       ast_log(LOG_WARNING, "Don't know what to do with '%s'\n", ast_channel_name(c));
06590    }
06591 
06592    if (!args || !args->no_hangup_chan) {
06593       ast_softhangup(c, AST_SOFTHANGUP_APPUNLOAD);
06594       if (!ast_test_flag(ast_channel_flags(c), AST_FLAG_BRIDGE_HANGUP_RUN)
06595          && ast_exists_extension(c, ast_channel_context(c), "h", 1,
06596             S_COR(ast_channel_caller(c)->id.number.valid,
06597                ast_channel_caller(c)->id.number.str, NULL))) {
06598          ast_pbx_h_exten_run(c, ast_channel_context(c));
06599       }
06600       ast_pbx_hangup_handler_run(c);
06601    }
06602 
06603    ast_set2_flag(ast_channel_flags(c), autoloopflag, AST_FLAG_IN_AUTOLOOP);
06604    ast_clear_flag(ast_channel_flags(c), AST_FLAG_BRIDGE_HANGUP_RUN); /* from one round to the next, make sure this gets cleared */
06605    pbx_destroy(ast_channel_pbx(c));
06606    ast_channel_pbx_set(c, NULL);
06607 
06608    if (!args || !args->no_hangup_chan) {
06609       ast_hangup(c);
06610    }
06611 
06612    return AST_PBX_SUCCESS;
06613 }
06614 
06615 /*!
06616  * \brief Increase call count for channel
06617  * \retval 0 on success
06618  * \retval non-zero if a configured limit (maxcalls, maxload, minmemfree) was reached
06619 */
06620 static int increase_call_count(const struct ast_channel *c)
06621 {
06622    int failed = 0;
06623    double curloadavg;
06624 #if defined(HAVE_SYSINFO)
06625    long curfreemem;
06626    struct sysinfo sys_info;
06627 #endif
06628 
06629    ast_mutex_lock(&maxcalllock);
06630    if (ast_option_maxcalls) {
06631       if (countcalls >= ast_option_maxcalls) {
06632          ast_log(LOG_WARNING, "Maximum call limit of %d calls exceeded by '%s'!\n", ast_option_maxcalls, ast_channel_name(c));
06633          failed = -1;
06634       }
06635    }
06636    if (ast_option_maxload) {
06637       getloadavg(&curloadavg, 1);
06638       if (curloadavg >= ast_option_maxload) {
06639          ast_log(LOG_WARNING, "Maximum loadavg limit of %f load exceeded by '%s' (currently %f)!\n", ast_option_maxload, ast_channel_name(c), curloadavg);
06640          failed = -1;
06641       }
06642    }
06643 #if defined(HAVE_SYSINFO)
06644    if (option_minmemfree) {
06645       if (!sysinfo(&sys_info)) {
06646          /* make sure that the free system memory is above the configured low watermark
06647           * convert the amount of freeram from mem_units to MB */
06648          curfreemem = sys_info.freeram * sys_info.mem_unit;
06649          curfreemem /= 1024 * 1024;
06650          if (curfreemem < option_minmemfree) {
06651             ast_log(LOG_WARNING, "Available system memory (~%ldMB) is below the configured low watermark (%ldMB)\n", curfreemem, option_minmemfree);
06652             failed = -1;
06653          }
06654       }
06655    }
06656 #endif
06657 
06658    if (!failed) {
06659       countcalls++;
06660       totalcalls++;
06661    }
06662    ast_mutex_unlock(&maxcalllock);
06663 
06664    return failed;
06665 }
06666 
06667 static void decrease_call_count(void)
06668 {
06669    ast_mutex_lock(&maxcalllock);
06670    if (countcalls > 0)
06671       countcalls--;
06672    ast_mutex_unlock(&maxcalllock);
06673 }
06674 
06675 static void destroy_exten(struct ast_exten *e)
06676 {
06677    if (e->priority == PRIORITY_HINT)
06678       ast_remove_hint(e);
06679 
06680    if (e->peer_table)
06681       ast_hashtab_destroy(e->peer_table,0);
06682    if (e->peer_label_table)
06683       ast_hashtab_destroy(e->peer_label_table, 0);
06684    if (e->datad)
06685       e->datad(e->data);
06686    ast_free(e);
06687 }
06688 
06689 static void *pbx_thread(void *data)
06690 {
06691    /* Oh joyeous kernel, we're a new thread, with nothing to do but
06692       answer this channel and get it going.
06693    */
06694    /* NOTE:
06695       The launcher of this function _MUST_ increment 'countcalls'
06696       before invoking the function; it will be decremented when the
06697       PBX has finished running on the channel
06698     */
06699    struct ast_channel *c = data;
06700 
06701    __ast_pbx_run(c, NULL);
06702    decrease_call_count();
06703 
06704    pthread_exit(NULL);
06705 
06706    return NULL;
06707 }
06708 
06709 enum ast_pbx_result ast_pbx_start(struct ast_channel *c)
06710 {
06711    pthread_t t;
06712 
06713    if (!c) {
06714       ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n");
06715       return AST_PBX_FAILED;
06716    }
06717 
06718    if (!ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) {
06719       ast_log(LOG_WARNING, "PBX requires Asterisk to be fully booted\n");
06720       return AST_PBX_FAILED;
06721    }
06722 
06723    if (increase_call_count(c))
06724       return AST_PBX_CALL_LIMIT;
06725 
06726    /* Start a new thread, and get something handling this channel. */
06727    if (ast_pthread_create_detached(&t, NULL, pbx_thread, c)) {
06728       ast_log(LOG_WARNING, "Failed to create new channel thread\n");
06729       decrease_call_count();
06730       return AST_PBX_FAILED;
06731    }
06732 
06733    return AST_PBX_SUCCESS;
06734 }
06735 
06736 enum ast_pbx_result ast_pbx_run_args(struct ast_channel *c, struct ast_pbx_args *args)
06737 {
06738    enum ast_pbx_result res = AST_PBX_SUCCESS;
06739 
06740    if (!ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) {
06741       ast_log(LOG_WARNING, "PBX requires Asterisk to be fully booted\n");
06742       return AST_PBX_FAILED;
06743    }
06744 
06745    if (increase_call_count(c)) {
06746       return AST_PBX_CALL_LIMIT;
06747    }
06748 
06749    res = __ast_pbx_run(c, args);
06750 
06751    decrease_call_count();
06752 
06753    return res;
06754 }
06755 
06756 enum ast_pbx_result ast_pbx_run(struct ast_channel *c)
06757 {
06758    return ast_pbx_run_args(c, NULL);
06759 }
06760 
06761 int ast_active_calls(void)
06762 {
06763    return countcalls;
06764 }
06765 
06766 int ast_processed_calls(void)
06767 {
06768    return totalcalls;
06769 }
06770 
06771 int pbx_set_autofallthrough(int newval)
06772 {
06773    int oldval = autofallthrough;
06774    autofallthrough = newval;
06775    return oldval;
06776 }
06777 
06778 int pbx_set_extenpatternmatchnew(int newval)
06779 {
06780    int oldval = extenpatternmatchnew;
06781    extenpatternmatchnew = newval;
06782    return oldval;
06783 }
06784 
06785 void pbx_set_overrideswitch(const char *newval)
06786 {
06787    if (overrideswitch) {
06788       ast_free(overrideswitch);
06789    }
06790    if (!ast_strlen_zero(newval)) {
06791       overrideswitch = ast_strdup(newval);
06792    } else {
06793       overrideswitch = NULL;
06794    }
06795 }
06796 
06797 /*!
06798  * \brief lookup for a context with a given name,
06799  * \retval found context or NULL if not found.
06800  */
06801 static struct ast_context *find_context(const char *context)
06802 {
06803    struct fake_context item;
06804 
06805    ast_copy_string(item.name, context, sizeof(item.name));
06806 
06807    return ast_hashtab_lookup(contexts_table, &item);
06808 }
06809 
06810 /*!
06811  * \brief lookup for a context with a given name,
06812  * \retval with conlock held if found.
06813  * \retval NULL if not found.
06814  */
06815 static struct ast_context *find_context_locked(const char *context)
06816 {
06817    struct ast_context *c;
06818    struct fake_context item;
06819 
06820    ast_copy_string(item.name, context, sizeof(item.name));
06821 
06822    ast_rdlock_contexts();
06823    c = ast_hashtab_lookup(contexts_table, &item);
06824    if (!c) {
06825       ast_unlock_contexts();
06826    }
06827 
06828    return c;
06829 }
06830 
06831 /*!
06832  * \brief Remove included contexts.
06833  * This function locks contexts list by &conlist, search for the right context
06834  * structure, leave context list locked and call ast_context_remove_include2
06835  * which removes include, unlock contexts list and return ...
06836  */
06837 int ast_context_remove_include(const char *context, const char *include, const char *registrar)
06838 {
06839    int ret = -1;
06840    struct ast_context *c;
06841 
06842    c = find_context_locked(context);
06843    if (c) {
06844       /* found, remove include from this context ... */
06845       ret = ast_context_remove_include2(c, include, registrar);
06846       ast_unlock_contexts();
06847    }
06848    return ret;
06849 }
06850 
06851 /*!
06852  * \brief Locks context, remove included contexts, unlocks context.
06853  * When we call this function, &conlock lock must be locked, because when
06854  * we giving *con argument, some process can remove/change this context
06855  * and after that there can be segfault.
06856  *
06857  * \retval 0 on success.
06858  * \retval -1 on failure.
06859  */
06860 int ast_context_remove_include2(struct ast_context *con, const char *include, const char *registrar)
06861 {
06862    struct ast_include *i, *pi = NULL;
06863    int ret = -1;
06864 
06865    ast_wrlock_context(con);
06866 
06867    /* find our include */
06868    for (i = con->includes; i; pi = i, i = i->next) {
06869       if (!strcmp(i->name, include) &&
06870             (!registrar || !strcmp(i->registrar, registrar))) {
06871          /* remove from list */
06872          ast_verb(3, "Removing inclusion of context '%s' in context '%s; registrar=%s'\n", include, ast_get_context_name(con), registrar);
06873          if (pi)
06874             pi->next = i->next;
06875          else
06876             con->includes = i->next;
06877          /* free include and return */
06878          ast_destroy_timing(&(i->timing));
06879          ast_free(i);
06880          ret = 0;
06881          break;
06882       }
06883    }
06884 
06885    ast_unlock_context(con);
06886 
06887    return ret;
06888 }
06889 
06890 /*!
06891  * \note This function locks contexts list by &conlist, search for the rigt context
06892  * structure, leave context list locked and call ast_context_remove_switch2
06893  * which removes switch, unlock contexts list and return ...
06894  */
06895 int ast_context_remove_switch(const char *context, const char *sw, const char *data, const char *registrar)
06896 {
06897    int ret = -1; /* default error return */
06898    struct ast_context *c;
06899 
06900    c = find_context_locked(context);
06901    if (c) {
06902       /* remove switch from this context ... */
06903       ret = ast_context_remove_switch2(c, sw, data, registrar);
06904       ast_unlock_contexts();
06905    }
06906    return ret;
06907 }
06908 
06909 /*!
06910  * \brief This function locks given context, removes switch, unlock context and
06911  * return.
06912  * \note When we call this function, &conlock lock must be locked, because when
06913  * we giving *con argument, some process can remove/change this context
06914  * and after that there can be segfault.
06915  *
06916  */
06917 int ast_context_remove_switch2(struct ast_context *con, const char *sw, const char *data, const char *registrar)
06918 {
06919    struct ast_sw *i;
06920    int ret = -1;
06921 
06922    ast_wrlock_context(con);
06923 
06924    /* walk switches */
06925    AST_LIST_TRAVERSE_SAFE_BEGIN(&con->alts, i, list) {
06926       if (!strcmp(i->name, sw) && !strcmp(i->data, data) &&
06927          (!registrar || !strcmp(i->registrar, registrar))) {
06928          /* found, remove from list */
06929          ast_verb(3, "Removing switch '%s' from context '%s; registrar=%s'\n", sw, ast_get_context_name(con), registrar);
06930          AST_LIST_REMOVE_CURRENT(list);
06931          ast_free(i); /* free switch and return */
06932          ret = 0;
06933          break;
06934       }
06935    }
06936    AST_LIST_TRAVERSE_SAFE_END;
06937 
06938    ast_unlock_context(con);
06939 
06940    return ret;
06941 }
06942 
06943 /*! \note This function will lock conlock. */
06944 int ast_context_remove_extension(const char *context, const char *extension, int priority, const char *registrar)
06945 {
06946    return ast_context_remove_extension_callerid(context, extension, priority, NULL, AST_EXT_MATCHCID_ANY, registrar);
06947 }
06948 
06949 int ast_context_remove_extension_callerid(const char *context, const char *extension, int priority, const char *callerid, int matchcallerid, const char *registrar)
06950 {
06951    int ret = -1; /* default error return */
06952    struct ast_context *c;
06953 
06954    c = find_context_locked(context);
06955    if (c) { /* ... remove extension ... */
06956       ret = ast_context_remove_extension_callerid2(c, extension, priority, callerid,
06957          matchcallerid, registrar, 0);
06958       ast_unlock_contexts</