Sat Apr 26 2014 22:01:38

Asterisk developer's documentation


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: 408786 $")
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/cel.h"
00054 #include "asterisk/config.h"
00055 #include "asterisk/term.h"
00056 #include "asterisk/time.h"
00057 #include "asterisk/manager.h"
00058 #include "asterisk/ast_expr.h"
00059 #include "asterisk/linkedlists.h"
00060 #define  SAY_STUBS   /* generate declarations and stubs for say methods */
00061 #include "asterisk/say.h"
00062 #include "asterisk/utils.h"
00063 #include "asterisk/causes.h"
00064 #include "asterisk/musiconhold.h"
00065 #include "asterisk/app.h"
00066 #include "asterisk/devicestate.h"
00067 #include "asterisk/presencestate.h"
00068 #include "asterisk/event.h"
00069 #include "asterisk/hashtab.h"
00070 #include "asterisk/module.h"
00071 #include "asterisk/indications.h"
00072 #include "asterisk/taskprocessor.h"
00073 #include "asterisk/xmldoc.h"
00074 #include "asterisk/astobj2.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          <parameter name="nocdr">
00108             <para>Asterisk will send an answer signal to the calling phone, but will not
00109             set the disposition or answer time in the CDR for this call.</para>
00110          </parameter>
00111       </syntax>
00112       <description>
00113          <para>If the call has not been answered, this application will
00114          answer it. Otherwise, it has no effect on the call.</para>
00115       </description>
00116       <see-also>
00117          <ref type="application">Hangup</ref>
00118       </see-also>
00119    </application>
00120    <application name="BackGround" language="en_US">
00121       <synopsis>
00122          Play an audio file while waiting for digits of an extension to go to.
00123       </synopsis>
00124       <syntax>
00125          <parameter name="filenames" required="true" argsep="&amp;">
00126             <argument name="filename1" required="true" />
00127             <argument name="filename2" multiple="true" />
00128          </parameter>
00129          <parameter name="options">
00130             <optionlist>
00131                <option name="s">
00132                   <para>Causes the playback of the message to be skipped
00133                   if the channel is not in the <literal>up</literal> state (i.e. it
00134                   hasn't been answered yet). If this happens, the
00135                   application will return immediately.</para>
00136                </option>
00137                <option name="n">
00138                   <para>Don't answer the channel before playing the files.</para>
00139                </option>
00140                <option name="m">
00141                   <para>Only break if a digit hit matches a one digit
00142                   extension in the destination context.</para>
00143                </option>
00144             </optionlist>
00145          </parameter>
00146          <parameter name="langoverride">
00147             <para>Explicitly specifies which language to attempt to use for the requested sound files.</para>
00148          </parameter>
00149          <parameter name="context">
00150             <para>This is the dialplan context that this application will use when exiting
00151             to a dialed extension.</para>
00152          </parameter>
00153       </syntax>
00154       <description>
00155          <para>This application will play the given list of files <emphasis>(do not put extension)</emphasis>
00156          while waiting for an extension to be dialed by the calling channel. To continue waiting
00157          for digits after this application has finished playing files, the <literal>WaitExten</literal>
00158          application should be used.</para>
00159          <para>If one of the requested sound files does not exist, call processing will be terminated.</para>
00160          <para>This application sets the following channel variable upon completion:</para>
00161          <variablelist>
00162             <variable name="BACKGROUNDSTATUS">
00163                <para>The status of the background attempt as a text string.</para>
00164                <value name="SUCCESS" />
00165                <value name="FAILED" />
00166             </variable>
00167          </variablelist>
00168       </description>
00169       <see-also>
00170          <ref type="application">ControlPlayback</ref>
00171          <ref type="application">WaitExten</ref>
00172          <ref type="application">BackgroundDetect</ref>
00173          <ref type="function">TIMEOUT</ref>
00174       </see-also>
00175    </application>
00176    <application name="Busy" language="en_US">
00177       <synopsis>
00178          Indicate the Busy condition.
00179       </synopsis>
00180       <syntax>
00181          <parameter name="timeout">
00182             <para>If specified, the calling channel will be hung up after the specified number of seconds.
00183             Otherwise, this application will wait until the calling channel hangs up.</para>
00184          </parameter>
00185       </syntax>
00186       <description>
00187          <para>This application will indicate the busy condition to the calling channel.</para>
00188       </description>
00189       <see-also>
00190          <ref type="application">Congestion</ref>
00191          <ref type="application">Progress</ref>
00192          <ref type="application">Playtones</ref>
00193          <ref type="application">Hangup</ref>
00194       </see-also>
00195    </application>
00196    <application name="Congestion" language="en_US">
00197       <synopsis>
00198          Indicate the Congestion condition.
00199       </synopsis>
00200       <syntax>
00201          <parameter name="timeout">
00202             <para>If specified, the calling channel will be hung up after the specified number of seconds.
00203             Otherwise, this application will wait until the calling channel hangs up.</para>
00204          </parameter>
00205       </syntax>
00206       <description>
00207          <para>This application will indicate the congestion condition to the calling channel.</para>
00208       </description>
00209       <see-also>
00210          <ref type="application">Busy</ref>
00211          <ref type="application">Progress</ref>
00212          <ref type="application">Playtones</ref>
00213          <ref type="application">Hangup</ref>
00214       </see-also>
00215    </application>
00216    <application name="ExecIfTime" language="en_US">
00217       <synopsis>
00218          Conditional application execution based on the current time.
00219       </synopsis>
00220       <syntax argsep="?">
00221          <parameter name="day_condition" required="true">
00222             <argument name="times" required="true" />
00223             <argument name="weekdays" required="true" />
00224             <argument name="mdays" required="true" />
00225             <argument name="months" required="true" />
00226             <argument name="timezone" required="false" />
00227          </parameter>
00228          <parameter name="appname" required="true" hasparams="optional">
00229             <argument name="appargs" required="true" />
00230          </parameter>
00231       </syntax>
00232       <description>
00233          <para>This application will execute the specified dialplan application, with optional
00234          arguments, if the current time matches the given time specification.</para>
00235       </description>
00236       <see-also>
00237          <ref type="application">Exec</ref>
00238          <ref type="application">ExecIf</ref>
00239          <ref type="application">TryExec</ref>
00240          <ref type="application">GotoIfTime</ref>
00241       </see-also>
00242    </application>
00243    <application name="Goto" language="en_US">
00244       <synopsis>
00245          Jump to a particular priority, extension, or context.
00246       </synopsis>
00247       <syntax>
00248          <parameter name="context" />
00249          <parameter name="extensions" />
00250          <parameter name="priority" required="true" />
00251       </syntax>
00252       <description>
00253          <para>This application will set the current context, extension, and priority in the channel structure.
00254          After it completes, the pbx engine will continue dialplan execution at the specified location.
00255          If no specific <replaceable>extension</replaceable>, or <replaceable>extension</replaceable> and
00256          <replaceable>context</replaceable>, are specified, then this application will
00257          just set the specified <replaceable>priority</replaceable> of the current extension.</para>
00258          <para>At least a <replaceable>priority</replaceable> is required as an argument, or the goto will
00259          return a <literal>-1</literal>,  and the channel and call will be terminated.</para>
00260          <para>If the location that is put into the channel information is bogus, and asterisk cannot
00261          find that location in the dialplan, then the execution engine will try to find and execute the code in
00262          the <literal>i</literal> (invalid) extension in the current context. If that does not exist, it will try to execute the
00263          <literal>h</literal> extension. If neither the <literal>h</literal> nor <literal>i</literal> extensions
00264          have been defined, the channel is hung up, and the execution of instructions on the channel is terminated.
00265          What this means is that, for example, you specify a context that does not exist, then
00266          it will not be possible to find the <literal>h</literal> or <literal>i</literal> extensions,
00267          and the call will terminate!</para>
00268       </description>
00269       <see-also>
00270          <ref type="application">GotoIf</ref>
00271          <ref type="application">GotoIfTime</ref>
00272          <ref type="application">Gosub</ref>
00273          <ref type="application">Macro</ref>
00274       </see-also>
00275    </application>
00276    <application name="GotoIf" language="en_US">
00277       <synopsis>
00278          Conditional goto.
00279       </synopsis>
00280       <syntax argsep="?">
00281          <parameter name="condition" required="true" />
00282          <parameter name="destination" required="true" argsep=":">
00283             <argument name="labeliftrue">
00284                <para>Continue at <replaceable>labeliftrue</replaceable> if the condition is true.
00285                Takes the form similar to Goto() of [[context,]extension,]priority.</para>
00286             </argument>
00287             <argument name="labeliffalse">
00288                <para>Continue at <replaceable>labeliffalse</replaceable> if the condition is false.
00289                Takes the form similar to Goto() of [[context,]extension,]priority.</para>
00290             </argument>
00291          </parameter>
00292       </syntax>
00293       <description>
00294          <para>This application will set the current context, extension, and priority in the channel structure
00295          based on the evaluation of the given condition. After this application completes, the
00296          pbx engine will continue dialplan execution at the specified location in the dialplan.
00297          The labels are specified with the same syntax as used within the Goto application.
00298          If the label chosen by the condition is omitted, no jump is performed, and the execution passes to the
00299          next instruction. If the target location is bogus, and does not exist, the execution engine will try
00300          to find and execute the code in the <literal>i</literal> (invalid) extension in the current context.
00301          If that does not exist, it will try to execute the <literal>h</literal> extension.
00302          If neither the <literal>h</literal> nor <literal>i</literal> extensions have been defined,
00303          the channel is hung up, and the execution of instructions on the channel is terminated.
00304          Remember that this command can set the current context, and if the context specified
00305          does not exist, then it will not be able to find any 'h' or 'i' extensions there, and
00306          the channel and call will both be terminated!.</para>
00307       </description>
00308       <see-also>
00309          <ref type="application">Goto</ref>
00310          <ref type="application">GotoIfTime</ref>
00311          <ref type="application">GosubIf</ref>
00312          <ref type="application">MacroIf</ref>
00313       </see-also>
00314    </application>
00315    <application name="GotoIfTime" language="en_US">
00316       <synopsis>
00317          Conditional Goto based on the current time.
00318       </synopsis>
00319       <syntax argsep="?">
00320          <parameter name="condition" required="true">
00321             <argument name="times" required="true" />
00322             <argument name="weekdays" required="true" />
00323             <argument name="mdays" required="true" />
00324             <argument name="months" required="true" />
00325             <argument name="timezone" required="false" />
00326          </parameter>
00327          <parameter name="destination" required="true" argsep=":">
00328             <argument name="labeliftrue">
00329                <para>Continue at <replaceable>labeliftrue</replaceable> if the condition is true.
00330                Takes the form similar to Goto() of [[context,]extension,]priority.</para>
00331             </argument>
00332             <argument name="labeliffalse">
00333                <para>Continue at <replaceable>labeliffalse</replaceable> if the condition is false.
00334                Takes the form similar to Goto() of [[context,]extension,]priority.</para>
00335             </argument>
00336          </parameter>
00337       </syntax>
00338       <description>
00339          <para>This application will set the context, extension, and priority in the channel structure
00340          based on the evaluation of the given time specification. After this application completes,
00341          the pbx engine will continue dialplan execution at the specified location in the dialplan.
00342          If the current time is within the given time specification, the channel will continue at
00343          <replaceable>labeliftrue</replaceable>. Otherwise the channel will continue at <replaceable>labeliffalse</replaceable>.
00344          If the label chosen by the condition is omitted, no jump is performed, and execution passes to the next
00345          instruction. If the target jump location is bogus, the same actions would be taken as for <literal>Goto</literal>.
00346          Further information on the time specification can be found in examples
00347          illustrating how to do time-based context includes in the dialplan.</para>
00348       </description>
00349       <see-also>
00350          <ref type="application">GotoIf</ref>
00351          <ref type="application">Goto</ref>
00352          <ref type="function">IFTIME</ref>
00353          <ref type="function">TESTTIME</ref>
00354       </see-also>
00355    </application>
00356    <application name="ImportVar" language="en_US">
00357       <synopsis>
00358          Import a variable from a channel into a new variable.
00359       </synopsis>
00360       <syntax argsep="=">
00361          <parameter name="newvar" required="true" />
00362          <parameter name="vardata" required="true">
00363             <argument name="channelname" required="true" />
00364             <argument name="variable" required="true" />
00365          </parameter>
00366       </syntax>
00367       <description>
00368          <para>This application imports a <replaceable>variable</replaceable> from the specified
00369          <replaceable>channel</replaceable> (as opposed to the current one) and stores it as a variable
00370          (<replaceable>newvar</replaceable>) in the current channel (the channel that is calling this
00371          application). Variables created by this application have the same inheritance properties as those
00372          created with the <literal>Set</literal> application.</para>
00373       </description>
00374       <see-also>
00375          <ref type="application">Set</ref>
00376       </see-also>
00377    </application>
00378    <application name="Hangup" language="en_US">
00379       <synopsis>
00380          Hang up the calling channel.
00381       </synopsis>
00382       <syntax>
00383          <parameter name="causecode">
00384             <para>If a <replaceable>causecode</replaceable> is given the channel's
00385             hangup cause will be set to the given value.</para>
00386          </parameter>
00387       </syntax>
00388       <description>
00389          <para>This application will hang up the calling channel.</para>
00390       </description>
00391       <see-also>
00392          <ref type="application">Answer</ref>
00393          <ref type="application">Busy</ref>
00394          <ref type="application">Congestion</ref>
00395       </see-also>
00396    </application>
00397    <application name="Incomplete" language="en_US">
00398       <synopsis>
00399          Returns AST_PBX_INCOMPLETE value.
00400       </synopsis>
00401       <syntax>
00402          <parameter name="n">
00403             <para>If specified, then Incomplete will not attempt to answer the channel first.</para>
00404             <note><para>Most channel types need to be in Answer state in order to receive DTMF.</para></note>
00405          </parameter>
00406       </syntax>
00407       <description>
00408          <para>Signals the PBX routines that the previous matched extension is incomplete
00409          and that further input should be allowed before matching can be considered
00410          to be complete.  Can be used within a pattern match when certain criteria warrants
00411          a longer match.</para>
00412       </description>
00413    </application>
00414    <application name="NoOp" language="en_US">
00415       <synopsis>
00416          Do Nothing (No Operation).
00417       </synopsis>
00418       <syntax>
00419          <parameter name="text">
00420             <para>Any text provided can be viewed at the Asterisk CLI.</para>
00421          </parameter>
00422       </syntax>
00423       <description>
00424          <para>This application does nothing. However, it is useful for debugging purposes.</para>
00425          <para>This method can be used to see the evaluations of variables or functions without having any effect.</para>
00426       </description>
00427       <see-also>
00428          <ref type="application">Verbose</ref>
00429          <ref type="application">Log</ref>
00430       </see-also>
00431    </application>
00432    <application name="Proceeding" language="en_US">
00433       <synopsis>
00434          Indicate proceeding.
00435       </synopsis>
00436       <syntax />
00437       <description>
00438          <para>This application will request that a proceeding message be provided to the calling channel.</para>
00439       </description>
00440    </application>
00441    <application name="Progress" language="en_US">
00442       <synopsis>
00443          Indicate progress.
00444       </synopsis>
00445       <syntax />
00446       <description>
00447          <para>This application will request that in-band progress information be provided to the calling channel.</para>
00448       </description>
00449       <see-also>
00450          <ref type="application">Busy</ref>
00451          <ref type="application">Congestion</ref>
00452          <ref type="application">Ringing</ref>
00453          <ref type="application">Playtones</ref>
00454       </see-also>
00455    </application>
00456    <application name="RaiseException" language="en_US">
00457       <synopsis>
00458          Handle an exceptional condition.
00459       </synopsis>
00460       <syntax>
00461          <parameter name="reason" required="true" />
00462       </syntax>
00463       <description>
00464          <para>This application will jump to the <literal>e</literal> extension in the current context, setting the
00465          dialplan function EXCEPTION(). If the <literal>e</literal> extension does not exist, the call will hangup.</para>
00466       </description>
00467       <see-also>
00468          <ref type="function">Exception</ref>
00469       </see-also>
00470    </application>
00471    <application name="ResetCDR" language="en_US">
00472       <synopsis>
00473          Resets the Call Data Record.
00474       </synopsis>
00475       <syntax>
00476          <parameter name="options">
00477             <optionlist>
00478                <option name="w">
00479                   <para>Store the current CDR record before resetting it.</para>
00480                </option>
00481                <option name="a">
00482                   <para>Store any stacked records.</para>
00483                </option>
00484                <option name="v">
00485                   <para>Save CDR variables.</para>
00486                </option>
00487                <option name="e">
00488                   <para>Enable CDR only (negate effects of NoCDR).</para>
00489                </option>
00490             </optionlist>
00491          </parameter>
00492       </syntax>
00493       <description>
00494          <para>This application causes the Call Data Record to be reset.</para>
00495       </description>
00496       <see-also>
00497          <ref type="application">ForkCDR</ref>
00498          <ref type="application">NoCDR</ref>
00499       </see-also>
00500    </application>
00501    <application name="Ringing" language="en_US">
00502       <synopsis>
00503          Indicate ringing tone.
00504       </synopsis>
00505       <syntax />
00506       <description>
00507          <para>This application will request that the channel indicate a ringing tone to the user.</para>
00508       </description>
00509       <see-also>
00510          <ref type="application">Busy</ref>
00511          <ref type="application">Congestion</ref>
00512          <ref type="application">Progress</ref>
00513          <ref type="application">Playtones</ref>
00514       </see-also>
00515    </application>
00516    <application name="SayAlpha" language="en_US">
00517       <synopsis>
00518          Say Alpha.
00519       </synopsis>
00520       <syntax>
00521          <parameter name="string" required="true" />
00522       </syntax>
00523       <description>
00524          <para>This application will play the sounds that correspond to the letters of the
00525          given <replaceable>string</replaceable>.</para>
00526       </description>
00527       <see-also>
00528          <ref type="application">SayDigits</ref>
00529          <ref type="application">SayNumber</ref>
00530          <ref type="application">SayPhonetic</ref>
00531          <ref type="function">CHANNEL</ref>
00532       </see-also>
00533    </application>
00534    <application name="SayDigits" language="en_US">
00535       <synopsis>
00536          Say Digits.
00537       </synopsis>
00538       <syntax>
00539          <parameter name="digits" required="true" />
00540       </syntax>
00541       <description>
00542          <para>This application will play the sounds that correspond to the digits of
00543          the given number. This will use the language that is currently set for the channel.</para>
00544       </description>
00545       <see-also>
00546          <ref type="application">SayAlpha</ref>
00547          <ref type="application">SayNumber</ref>
00548          <ref type="application">SayPhonetic</ref>
00549          <ref type="function">CHANNEL</ref>
00550       </see-also>
00551    </application>
00552    <application name="SayNumber" language="en_US">
00553       <synopsis>
00554          Say Number.
00555       </synopsis>
00556       <syntax>
00557          <parameter name="digits" required="true" />
00558          <parameter name="gender" />
00559       </syntax>
00560       <description>
00561          <para>This application will play the sounds that correspond to the given <replaceable>digits</replaceable>.
00562          Optionally, a <replaceable>gender</replaceable> may be specified. This will use the language that is currently
00563          set for the channel. See the CHANNEL() function for more information on setting the language for the channel.</para>
00564       </description>
00565       <see-also>
00566          <ref type="application">SayAlpha</ref>
00567          <ref type="application">SayDigits</ref>
00568          <ref type="application">SayPhonetic</ref>
00569          <ref type="function">CHANNEL</ref>
00570       </see-also>
00571    </application>
00572    <application name="SayPhonetic" language="en_US">
00573       <synopsis>
00574          Say Phonetic.
00575       </synopsis>
00576       <syntax>
00577          <parameter name="string" required="true" />
00578       </syntax>
00579       <description>
00580          <para>This application will play the sounds from the phonetic alphabet that correspond to the
00581          letters in the given <replaceable>string</replaceable>.</para>
00582       </description>
00583       <see-also>
00584          <ref type="application">SayAlpha</ref>
00585          <ref type="application">SayDigits</ref>
00586          <ref type="application">SayNumber</ref>
00587       </see-also>
00588    </application>
00589    <application name="Set" language="en_US">
00590       <synopsis>
00591          Set channel variable or function value.
00592       </synopsis>
00593       <syntax argsep="=">
00594          <parameter name="name" required="true" />
00595          <parameter name="value" required="true" />
00596       </syntax>
00597       <description>
00598          <para>This function can be used to set the value of channel variables or dialplan functions.
00599          When setting variables, if the variable name is prefixed with <literal>_</literal>,
00600          the variable will be inherited into channels created from the current channel.
00601          If the variable name is prefixed with <literal>__</literal>, the variable will be
00602          inherited into channels created from the current channel and all children channels.</para>
00603          <note><para>If (and only if), in <filename>/etc/asterisk/asterisk.conf</filename>, you have
00604          a <literal>[compat]</literal> category, and you have <literal>app_set = 1.4</literal> under that, then
00605          the behavior of this app changes, and strips surrounding quotes from the right hand side as
00606          it did previously in 1.4.
00607          The advantages of not stripping out quoting, and not caring about the separator characters (comma and vertical bar)
00608          were sufficient to make these changes in 1.6. Confusion about how many backslashes would be needed to properly
00609          protect separators and quotes in various database access strings has been greatly
00610          reduced by these changes.</para></note>
00611       </description>
00612       <see-also>
00613          <ref type="application">MSet</ref>
00614          <ref type="function">GLOBAL</ref>
00615          <ref type="function">SET</ref>
00616          <ref type="function">ENV</ref>
00617       </see-also>
00618    </application>
00619    <application name="MSet" language="en_US">
00620       <synopsis>
00621          Set channel variable(s) or function value(s).
00622       </synopsis>
00623       <syntax>
00624          <parameter name="set1" required="true" argsep="=">
00625             <argument name="name1" required="true" />
00626             <argument name="value1" required="true" />
00627          </parameter>
00628          <parameter name="set2" multiple="true" argsep="=">
00629             <argument name="name2" required="true" />
00630             <argument name="value2" required="true" />
00631          </parameter>
00632       </syntax>
00633       <description>
00634          <para>This function can be used to set the value of channel variables or dialplan functions.
00635          When setting variables, if the variable name is prefixed with <literal>_</literal>,
00636          the variable will be inherited into channels created from the current channel
00637          If the variable name is prefixed with <literal>__</literal>, the variable will be
00638          inherited into channels created from the current channel and all children channels.
00639          MSet behaves in a similar fashion to the way Set worked in 1.2/1.4 and is thus
00640          prone to doing things that you may not expect. For example, it strips surrounding
00641          double-quotes from the right-hand side (value). If you need to put a separator
00642          character (comma or vert-bar), you will need to escape them by inserting a backslash
00643          before them. Avoid its use if possible.</para>
00644       </description>
00645       <see-also>
00646          <ref type="application">Set</ref>
00647       </see-also>
00648    </application>
00649    <application name="SetAMAFlags" language="en_US">
00650       <synopsis>
00651          Set the AMA Flags.
00652       </synopsis>
00653       <syntax>
00654          <parameter name="flag" />
00655       </syntax>
00656       <description>
00657          <para>This application will set the channel's AMA Flags for billing purposes.</para>
00658       </description>
00659       <see-also>
00660          <ref type="function">CDR</ref>
00661       </see-also>
00662    </application>
00663    <application name="Wait" language="en_US">
00664       <synopsis>
00665          Waits for some time.
00666       </synopsis>
00667       <syntax>
00668          <parameter name="seconds" required="true">
00669             <para>Can be passed with fractions of a second. For example, <literal>1.5</literal> will ask the
00670             application to wait for 1.5 seconds.</para>
00671          </parameter>
00672       </syntax>
00673       <description>
00674          <para>This application waits for a specified number of <replaceable>seconds</replaceable>.</para>
00675       </description>
00676    </application>
00677    <application name="WaitExten" language="en_US">
00678       <synopsis>
00679          Waits for an extension to be entered.
00680       </synopsis>
00681       <syntax>
00682          <parameter name="seconds">
00683             <para>Can be passed with fractions of a second. For example, <literal>1.5</literal> will ask the
00684             application to wait for 1.5 seconds.</para>
00685          </parameter>
00686          <parameter name="options">
00687             <optionlist>
00688                <option name="m">
00689                   <para>Provide music on hold to the caller while waiting for an extension.</para>
00690                   <argument name="x">
00691                      <para>Specify the class for music on hold. <emphasis>CHANNEL(musicclass) will
00692                      be used instead if set</emphasis></para>
00693                   </argument>
00694                </option>
00695             </optionlist>
00696          </parameter>
00697       </syntax>
00698       <description>
00699          <para>This application waits for the user to enter a new extension for a specified number
00700          of <replaceable>seconds</replaceable>.</para>
00701          <xi:include xpointer="xpointer(/docs/application[@name='Macro']/description/warning[2])" />
00702       </description>
00703       <see-also>
00704          <ref type="application">Background</ref>
00705          <ref type="function">TIMEOUT</ref>
00706       </see-also>
00707    </application>
00708    <function name="EXCEPTION" language="en_US">
00709       <synopsis>
00710          Retrieve the details of the current dialplan exception.
00711       </synopsis>
00712       <syntax>
00713          <parameter name="field" required="true">
00714             <para>The following fields are available for retrieval:</para>
00715             <enumlist>
00716                <enum name="reason">
00717                   <para>INVALID, ERROR, RESPONSETIMEOUT, ABSOLUTETIMEOUT, or custom
00718                   value set by the RaiseException() application</para>
00719                </enum>
00720                <enum name="context">
00721                   <para>The context executing when the exception occurred.</para>
00722                </enum>
00723                <enum name="exten">
00724                   <para>The extension executing when the exception occurred.</para>
00725                </enum>
00726                <enum name="priority">
00727                   <para>The numeric priority executing when the exception occurred.</para>
00728                </enum>
00729             </enumlist>
00730          </parameter>
00731       </syntax>
00732       <description>
00733          <para>Retrieve the details (specified <replaceable>field</replaceable>) of the current dialplan exception.</para>
00734       </description>
00735       <see-also>
00736          <ref type="application">RaiseException</ref>
00737       </see-also>
00738    </function>
00739    <function name="TESTTIME" language="en_US">
00740       <synopsis>
00741          Sets a time to be used with the channel to test logical conditions.
00742       </synopsis>
00743       <syntax>
00744          <parameter name="date" required="true" argsep=" ">
00745             <para>Date in ISO 8601 format</para>
00746          </parameter>
00747          <parameter name="time" required="true" argsep=" ">
00748             <para>Time in HH:MM:SS format (24-hour time)</para>
00749          </parameter>
00750          <parameter name="zone" required="false">
00751             <para>Timezone name</para>
00752          </parameter>
00753       </syntax>
00754       <description>
00755          <para>To test dialplan timing conditions at times other than the current time, use
00756          this function to set an alternate date and time.  For example, you may wish to evaluate
00757          whether a location will correctly identify to callers that the area is closed on Christmas
00758          Day, when Christmas would otherwise fall on a day when the office is normally open.</para>
00759       </description>
00760       <see-also>
00761          <ref type="application">GotoIfTime</ref>
00762       </see-also>
00763    </function>
00764    <manager name="ShowDialPlan" language="en_US">
00765       <synopsis>
00766          Show dialplan contexts and extensions
00767       </synopsis>
00768       <syntax>
00769          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00770          <parameter name="Extension">
00771             <para>Show a specific extension.</para>
00772          </parameter>
00773          <parameter name="Context">
00774             <para>Show a specific context.</para>
00775          </parameter>
00776       </syntax>
00777       <description>
00778          <para>Show dialplan contexts and extensions. Be aware that showing the full dialplan
00779          may take a lot of capacity.</para>
00780       </description>
00781    </manager>
00782  ***/
00783 
00784 #ifdef LOW_MEMORY
00785 #define EXT_DATA_SIZE 256
00786 #else
00787 #define EXT_DATA_SIZE 8192
00788 #endif
00789 
00790 #define SWITCH_DATA_LENGTH 256
00791 
00792 #define VAR_BUF_SIZE 4096
00793 
00794 #define  VAR_NORMAL     1
00795 #define  VAR_SOFTTRAN   2
00796 #define  VAR_HARDTRAN   3
00797 
00798 #define BACKGROUND_SKIP    (1 << 0)
00799 #define BACKGROUND_NOANSWER   (1 << 1)
00800 #define BACKGROUND_MATCHEXTEN (1 << 2)
00801 #define BACKGROUND_PLAYBACK   (1 << 3)
00802 
00803 AST_APP_OPTIONS(background_opts, {
00804    AST_APP_OPTION('s', BACKGROUND_SKIP),
00805    AST_APP_OPTION('n', BACKGROUND_NOANSWER),
00806    AST_APP_OPTION('m', BACKGROUND_MATCHEXTEN),
00807    AST_APP_OPTION('p', BACKGROUND_PLAYBACK),
00808 });
00809 
00810 #define WAITEXTEN_MOH      (1 << 0)
00811 #define WAITEXTEN_DIALTONE (1 << 1)
00812 
00813 AST_APP_OPTIONS(waitexten_opts, {
00814    AST_APP_OPTION_ARG('m', WAITEXTEN_MOH, 0),
00815    AST_APP_OPTION_ARG('d', WAITEXTEN_DIALTONE, 0),
00816 });
00817 
00818 struct ast_context;
00819 struct ast_app;
00820 
00821 static struct ast_taskprocessor *extension_state_tps;
00822 
00823 AST_THREADSTORAGE(switch_data);
00824 AST_THREADSTORAGE(extensionstate_buf);
00825 /*!
00826  * \brief A thread local indicating whether the current thread can run
00827  * 'dangerous' dialplan functions.
00828  */
00829 AST_THREADSTORAGE(thread_inhibit_escalations_tl);
00830 
00831 /*!
00832  * \brief Set to true (non-zero) to globally allow all dangerous dialplan
00833  * functions to run.
00834  */
00835 static int live_dangerously;
00836 
00837 /*!
00838    \brief ast_exten: An extension
00839    The dialplan is saved as a linked list with each context
00840    having it's own linked list of extensions - one item per
00841    priority.
00842 */
00843 struct ast_exten {
00844    char *exten;         /*!< Extension name */
00845    int matchcid;        /*!< Match caller id ? */
00846    const char *cidmatch;      /*!< Caller id to match for this extension */
00847    int priority;        /*!< Priority */
00848    const char *label;      /*!< Label */
00849    struct ast_context *parent;   /*!< The context this extension belongs to  */
00850    const char *app;     /*!< Application to execute */
00851    struct ast_app *cached_app;     /*!< Cached location of application */
00852    void *data;       /*!< Data to use (arguments) */
00853    void (*datad)(void *);     /*!< Data destructor */
00854    struct ast_exten *peer;    /*!< Next higher priority with our extension */
00855    struct ast_hashtab *peer_table;    /*!< Priorities list in hashtab form -- only on the head of the peer list */
00856    struct ast_hashtab *peer_label_table; /*!< labeled priorities in the peers -- only on the head of the peer list */
00857    const char *registrar;     /*!< Registrar */
00858    struct ast_exten *next;    /*!< Extension with a greater ID */
00859    char stuff[0];
00860 };
00861 
00862 /*! \brief ast_include: include= support in extensions.conf */
00863 struct ast_include {
00864    const char *name;
00865    const char *rname;         /*!< Context to include */
00866    const char *registrar;        /*!< Registrar */
00867    int hastime;            /*!< If time construct exists */
00868    struct ast_timing timing;               /*!< time construct */
00869    struct ast_include *next;     /*!< Link them together */
00870    char stuff[0];
00871 };
00872 
00873 /*! \brief ast_sw: Switch statement in extensions.conf */
00874 struct ast_sw {
00875    char *name;
00876    const char *registrar;        /*!< Registrar */
00877    char *data;          /*!< Data load */
00878    int eval;
00879    AST_LIST_ENTRY(ast_sw) list;
00880    char stuff[0];
00881 };
00882 
00883 /*! \brief ast_ignorepat: Ignore patterns in dial plan */
00884 struct ast_ignorepat {
00885    const char *registrar;
00886    struct ast_ignorepat *next;
00887    const char pattern[0];
00888 };
00889 
00890 /*! \brief match_char: forms a syntax tree for quick matching of extension patterns */
00891 struct match_char
00892 {
00893    int is_pattern; /* the pattern started with '_' */
00894    int deleted;    /* if this is set, then... don't return it */
00895    int specificity; /* simply the strlen of x, or 10 for X, 9 for Z, and 8 for N; and '.' and '!' will add 11 ? */
00896    struct match_char *alt_char;
00897    struct match_char *next_char;
00898    struct ast_exten *exten; /* attached to last char of a pattern for exten */
00899    char x[1];       /* the pattern itself-- matches a single char */
00900 };
00901 
00902 struct scoreboard  /* make sure all fields are 0 before calling new_find_extension */
00903 {
00904    int total_specificity;
00905    int total_length;
00906    char last_char;   /* set to ! or . if they are the end of the pattern */
00907    int canmatch;     /* if the string to match was just too short */
00908    struct match_char *node;
00909    struct ast_exten *canmatch_exten;
00910    struct ast_exten *exten;
00911 };
00912 
00913 /*! \brief ast_context: An extension context */
00914 struct ast_context {
00915    ast_rwlock_t lock;         /*!< A lock to prevent multiple threads from clobbering the context */
00916    struct ast_exten *root;       /*!< The root of the list of extensions */
00917    struct ast_hashtab *root_table;            /*!< For exact matches on the extensions in the pattern tree, and for traversals of the pattern_tree  */
00918    struct match_char *pattern_tree;        /*!< A tree to speed up extension pattern matching */
00919    struct ast_context *next;     /*!< Link them together */
00920    struct ast_include *includes;    /*!< Include other contexts */
00921    struct ast_ignorepat *ignorepats;   /*!< Patterns for which to continue playing dialtone */
00922    char *registrar;        /*!< Registrar -- make sure you malloc this, as the registrar may have to survive module unloads */
00923    int refcount;                   /*!< each module that would have created this context should inc/dec this as appropriate */
00924    AST_LIST_HEAD_NOLOCK(, ast_sw) alts;   /*!< Alternative switches */
00925    ast_mutex_t macrolock;        /*!< A lock to implement "exclusive" macros - held whilst a call is executing in the macro */
00926    char name[0];           /*!< Name of the context */
00927 };
00928 
00929 /*! \brief ast_app: A registered application */
00930 struct ast_app {
00931    int (*execute)(struct ast_channel *chan, const char *data);
00932    AST_DECLARE_STRING_FIELDS(
00933       AST_STRING_FIELD(synopsis);     /*!< Synopsis text for 'show applications' */
00934       AST_STRING_FIELD(description);  /*!< Description (help text) for 'show application &lt;name&gt;' */
00935       AST_STRING_FIELD(syntax);       /*!< Syntax text for 'core show applications' */
00936       AST_STRING_FIELD(arguments);    /*!< Arguments description */
00937       AST_STRING_FIELD(seealso);      /*!< See also */
00938    );
00939 #ifdef AST_XML_DOCS
00940    enum ast_doc_src docsrc;      /*!< Where the documentation come from. */
00941 #endif
00942    AST_RWLIST_ENTRY(ast_app) list;     /*!< Next app in list */
00943    struct ast_module *module;    /*!< Module this app belongs to */
00944    char name[0];           /*!< Name of the application */
00945 };
00946 
00947 /*! \brief ast_state_cb: An extension state notify register item */
00948 struct ast_state_cb {
00949    /*! Watcher ID returned when registered. */
00950    int id;
00951    /*! Arbitrary data passed for callbacks. */
00952    void *data;
00953    /*! Flag if this callback is an extended callback containing detailed device status */
00954    int extended;
00955    /*! Callback when state changes. */
00956    ast_state_cb_type change_cb;
00957    /*! Callback when destroyed so any resources given by the registerer can be freed. */
00958    ast_state_cb_destroy_type destroy_cb;
00959    /*! \note Only used by ast_merge_contexts_and_delete */
00960    AST_LIST_ENTRY(ast_state_cb) entry;
00961 };
00962 
00963 /*!
00964  * \brief Structure for dial plan hints
00965  *
00966  * \note Hints are pointers from an extension in the dialplan to
00967  * one or more devices (tech/name)
00968  *
00969  * See \ref AstExtState
00970  */
00971 struct ast_hint {
00972    /*!
00973     * \brief Hint extension
00974     *
00975     * \note
00976     * Will never be NULL while the hint is in the hints container.
00977     */
00978    struct ast_exten *exten;
00979    struct ao2_container *callbacks; /*!< Device state callback container for this extension */
00980 
00981    /*! Dev state variables */
00982    int laststate;       /*!< Last known device state */
00983 
00984    /*! Presence state variables */
00985    int last_presence_state;     /*!< Last known presence state */
00986    char *last_presence_subtype; /*!< Last known presence subtype string */
00987    char *last_presence_message; /*!< Last known presence message string */
00988 
00989    char context_name[AST_MAX_CONTEXT];/*!< Context of destroyed hint extension. */
00990    char exten_name[AST_MAX_EXTENSION];/*!< Extension of destroyed hint extension. */
00991 };
00992 
00993 
00994 #define HINTDEVICE_DATA_LENGTH 16
00995 AST_THREADSTORAGE(hintdevice_data);
00996 
00997 /* --- Hash tables of various objects --------*/
00998 #ifdef LOW_MEMORY
00999 #define HASH_EXTENHINT_SIZE 17
01000 #else
01001 #define HASH_EXTENHINT_SIZE 563
01002 #endif
01003 
01004 
01005 /*! \brief Container for hint devices */
01006 static struct ao2_container *hintdevices;
01007 
01008 /*!
01009  * \brief Structure for dial plan hint devices
01010  * \note hintdevice is one device pointing to a hint.
01011  */
01012 struct ast_hintdevice {
01013    /*!
01014     * \brief Hint this hintdevice belongs to.
01015     * \note Holds a reference to the hint object.
01016     */
01017    struct ast_hint *hint;
01018    /*! Name of the hint device. */
01019    char hintdevice[1];
01020 };
01021 
01022 
01023 /*!
01024  * \note Using the device for hash
01025  */
01026 static int hintdevice_hash_cb(const void *obj, const int flags)
01027 {
01028    const struct ast_hintdevice *ext = obj;
01029 
01030    return ast_str_case_hash(ext->hintdevice);
01031 }
01032 /*!
01033  * \note Devices on hints are not unique so no CMP_STOP is returned
01034  * Dont use ao2_find against hintdevices container cause there always
01035  * could be more than one result.
01036  */
01037 static int hintdevice_cmp_multiple(void *obj, void *arg, int flags)
01038 {
01039    struct ast_hintdevice *ext = obj, *ext2 = arg;
01040 
01041    return !strcasecmp(ext->hintdevice, ext2->hintdevice) ? CMP_MATCH  : 0;
01042 }
01043 
01044 /*
01045  * \details This is used with ao2_callback to remove old devices
01046  * when they are linked to the hint
01047 */
01048 static int hintdevice_remove_cb(void *deviceobj, void *arg, int flags)
01049 {
01050    struct ast_hintdevice *device = deviceobj;
01051    struct ast_hint *hint = arg;
01052 
01053    return (device->hint == hint) ? CMP_MATCH : 0;
01054 }
01055 
01056 static int remove_hintdevice(struct ast_hint *hint)
01057 {
01058    /* iterate through all devices and remove the devices which are linked to this hint */
01059    ao2_t_callback(hintdevices, OBJ_NODATA | OBJ_MULTIPLE | OBJ_UNLINK,
01060       hintdevice_remove_cb, hint,
01061       "callback to remove all devices which are linked to a hint");
01062    return 0;
01063 }
01064 
01065 static char *parse_hint_device(struct ast_str *hint_args);
01066 /*!
01067  * \internal
01068  * \brief Destroy the given hintdevice object.
01069  *
01070  * \param obj Hint device to destroy.
01071  *
01072  * \return Nothing
01073  */
01074 static void hintdevice_destroy(void *obj)
01075 {
01076    struct ast_hintdevice *doomed = obj;
01077 
01078    if (doomed->hint) {
01079       ao2_ref(doomed->hint, -1);
01080       doomed->hint = NULL;
01081    }
01082 }
01083 
01084 /*! \brief add hintdevice structure and link it into the container.
01085  */
01086 static int add_hintdevice(struct ast_hint *hint, const char *devicelist)
01087 {
01088    struct ast_str *str;
01089    char *parse;
01090    char *cur;
01091    struct ast_hintdevice *device;
01092    int devicelength;
01093 
01094    if (!hint || !devicelist) {
01095       /* Trying to add garbage? Don't bother. */
01096       return 0;
01097    }
01098    if (!(str = ast_str_thread_get(&hintdevice_data, 16))) {
01099       return -1;
01100    }
01101    ast_str_set(&str, 0, "%s", devicelist);
01102    parse = parse_hint_device(str);
01103 
01104    while ((cur = strsep(&parse, "&"))) {
01105       devicelength = strlen(cur);
01106       device = ao2_t_alloc(sizeof(*device) + devicelength, hintdevice_destroy,
01107          "allocating a hintdevice structure");
01108       if (!device) {
01109          return -1;
01110       }
01111       strcpy(device->hintdevice, cur);
01112       ao2_ref(hint, +1);
01113       device->hint = hint;
01114       ao2_t_link(hintdevices, device, "Linking device into hintdevice container.");
01115       ao2_t_ref(device, -1, "hintdevice is linked so we can unref");
01116    }
01117 
01118    return 0;
01119 }
01120 
01121 
01122 static const struct cfextension_states {
01123    int extension_state;
01124    const char * const text;
01125 } extension_states[] = {
01126    { AST_EXTENSION_NOT_INUSE,                     "Idle" },
01127    { AST_EXTENSION_INUSE,                         "InUse" },
01128    { AST_EXTENSION_BUSY,                          "Busy" },
01129    { AST_EXTENSION_UNAVAILABLE,                   "Unavailable" },
01130    { AST_EXTENSION_RINGING,                       "Ringing" },
01131    { AST_EXTENSION_INUSE | AST_EXTENSION_RINGING, "InUse&Ringing" },
01132    { AST_EXTENSION_ONHOLD,                        "Hold" },
01133    { AST_EXTENSION_INUSE | AST_EXTENSION_ONHOLD,  "InUse&Hold" }
01134 };
01135 
01136 struct presencechange {
01137    char *provider;
01138    int state;
01139    char *subtype;
01140    char *message;
01141 };
01142 
01143 struct statechange {
01144    AST_LIST_ENTRY(statechange) entry;
01145    char dev[0];
01146 };
01147 
01148 struct pbx_exception {
01149    AST_DECLARE_STRING_FIELDS(
01150       AST_STRING_FIELD(context); /*!< Context associated with this exception */
01151       AST_STRING_FIELD(exten);   /*!< Exten associated with this exception */
01152       AST_STRING_FIELD(reason);     /*!< The exception reason */
01153    );
01154 
01155    int priority;           /*!< Priority associated with this exception */
01156 };
01157 
01158 static int pbx_builtin_answer(struct ast_channel *, const char *);
01159 static int pbx_builtin_goto(struct ast_channel *, const char *);
01160 static int pbx_builtin_hangup(struct ast_channel *, const char *);
01161 static int pbx_builtin_background(struct ast_channel *, const char *);
01162 static int pbx_builtin_wait(struct ast_channel *, const char *);
01163 static int pbx_builtin_waitexten(struct ast_channel *, const char *);
01164 static int pbx_builtin_incomplete(struct ast_channel *, const char *);
01165 static int pbx_builtin_resetcdr(struct ast_channel *, const char *);
01166 static int pbx_builtin_setamaflags(struct ast_channel *, const char *);
01167 static int pbx_builtin_ringing(struct ast_channel *, const char *);
01168 static int pbx_builtin_proceeding(struct ast_channel *, const char *);
01169 static int pbx_builtin_progress(struct ast_channel *, const char *);
01170 static int pbx_builtin_congestion(struct ast_channel *, const char *);
01171 static int pbx_builtin_busy(struct ast_channel *, const char *);
01172 static int pbx_builtin_noop(struct ast_channel *, const char *);
01173 static int pbx_builtin_gotoif(struct ast_channel *, const char *);
01174 static int pbx_builtin_gotoiftime(struct ast_channel *, const char *);
01175 static int pbx_builtin_execiftime(struct ast_channel *, const char *);
01176 static int pbx_builtin_saynumber(struct ast_channel *, const char *);
01177 static int pbx_builtin_saydigits(struct ast_channel *, const char *);
01178 static int pbx_builtin_saycharacters(struct ast_channel *, const char *);
01179 static int pbx_builtin_sayphonetic(struct ast_channel *, const char *);
01180 static int matchcid(const char *cidpattern, const char *callerid);
01181 #ifdef NEED_DEBUG
01182 static void log_match_char_tree(struct match_char *node, char *prefix); /* for use anywhere */
01183 #endif
01184 static int pbx_builtin_importvar(struct ast_channel *, const char *);
01185 static void set_ext_pri(struct ast_channel *c, const char *exten, int pri);
01186 static void new_find_extension(const char *str, struct scoreboard *score,
01187       struct match_char *tree, int length, int spec, const char *callerid,
01188       const char *label, enum ext_match_t action);
01189 static struct match_char *already_in_tree(struct match_char *current, char *pat, int is_pattern);
01190 static struct match_char *add_exten_to_pattern_tree(struct ast_context *con,
01191       struct ast_exten *e1, int findonly);
01192 static void create_match_char_tree(struct ast_context *con);
01193 static struct ast_exten *get_canmatch_exten(struct match_char *node);
01194 static void destroy_pattern_tree(struct match_char *pattern_tree);
01195 static int hashtab_compare_extens(const void *ha_a, const void *ah_b);
01196 static int hashtab_compare_exten_numbers(const void *ah_a, const void *ah_b);
01197 static int hashtab_compare_exten_labels(const void *ah_a, const void *ah_b);
01198 static unsigned int hashtab_hash_extens(const void *obj);
01199 static unsigned int hashtab_hash_priority(const void *obj);
01200 static unsigned int hashtab_hash_labels(const void *obj);
01201 static void __ast_internal_context_destroy( struct ast_context *con);
01202 static int ast_add_extension_nolock(const char *context, int replace, const char *extension,
01203    int priority, const char *label, const char *callerid,
01204    const char *application, void *data, void (*datad)(void *), const char *registrar);
01205 static int ast_add_extension2_lockopt(struct ast_context *con,
01206    int replace, const char *extension, int priority, const char *label, const char *callerid,
01207    const char *application, void *data, void (*datad)(void *),
01208    const char *registrar, int lock_context);
01209 static struct ast_context *find_context_locked(const char *context);
01210 static struct ast_context *find_context(const char *context);
01211 static void get_device_state_causing_channels(struct ao2_container *c);
01212 
01213 /*!
01214  * \internal
01215  * \brief Character array comparison function for qsort.
01216  *
01217  * \param a Left side object.
01218  * \param b Right side object.
01219  *
01220  * \retval <0 if a < b
01221  * \retval =0 if a = b
01222  * \retval >0 if a > b
01223  */
01224 static int compare_char(const void *a, const void *b)
01225 {
01226    const unsigned char *ac = a;
01227    const unsigned char *bc = b;
01228 
01229    return *ac - *bc;
01230 }
01231 
01232 /* labels, contexts are case sensitive  priority numbers are ints */
01233 int ast_hashtab_compare_contexts(const void *ah_a, const void *ah_b)
01234 {
01235    const struct ast_context *ac = ah_a;
01236    const struct ast_context *bc = ah_b;
01237    if (!ac || !bc) /* safety valve, but it might prevent a crash you'd rather have happen */
01238       return 1;
01239    /* assume context names are registered in a string table! */
01240    return strcmp(ac->name, bc->name);
01241 }
01242 
01243 static int hashtab_compare_extens(const void *ah_a, const void *ah_b)
01244 {
01245    const struct ast_exten *ac = ah_a;
01246    const struct ast_exten *bc = ah_b;
01247    int x = strcmp(ac->exten, bc->exten);
01248    if (x) { /* if exten names are diff, then return */
01249       return x;
01250    }
01251 
01252    /* but if they are the same, do the cidmatch values match? */
01253    /* not sure which side may be using ast_ext_matchcid_types, so check both */
01254    if (ac->matchcid == AST_EXT_MATCHCID_ANY || bc->matchcid == AST_EXT_MATCHCID_ANY) {
01255       return 0;
01256    }
01257    if (ac->matchcid == AST_EXT_MATCHCID_OFF && bc->matchcid == AST_EXT_MATCHCID_OFF) {
01258       return 0;
01259    }
01260    if (ac->matchcid != bc->matchcid) {
01261       return 1;
01262    }
01263    /* all other cases already disposed of, match now required on callerid string (cidmatch) */
01264    /* although ast_add_extension2_lockopt() enforces non-zero ptr, caller may not have */
01265    if (ast_strlen_zero(ac->cidmatch) && ast_strlen_zero(bc->cidmatch)) {
01266       return 0;
01267    }
01268    return strcmp(ac->cidmatch, bc->cidmatch);
01269 }
01270 
01271 static int hashtab_compare_exten_numbers(const void *ah_a, const void *ah_b)
01272 {
01273    const struct ast_exten *ac = ah_a;
01274    const struct ast_exten *bc = ah_b;
01275    return ac->priority != bc->priority;
01276 }
01277 
01278 static int hashtab_compare_exten_labels(const void *ah_a, const void *ah_b)
01279 {
01280    const struct ast_exten *ac = ah_a;
01281    const struct ast_exten *bc = ah_b;
01282    return strcmp(S_OR(ac->label, ""), S_OR(bc->label, ""));
01283 }
01284 
01285 unsigned int ast_hashtab_hash_contexts(const void *obj)
01286 {
01287    const struct ast_context *ac = obj;
01288    return ast_hashtab_hash_string(ac->name);
01289 }
01290 
01291 static unsigned int hashtab_hash_extens(const void *obj)
01292 {
01293    const struct ast_exten *ac = obj;
01294    unsigned int x = ast_hashtab_hash_string(ac->exten);
01295    unsigned int y = 0;
01296    if (ac->matchcid == AST_EXT_MATCHCID_ON)
01297       y = ast_hashtab_hash_string(ac->cidmatch);
01298    return x+y;
01299 }
01300 
01301 static unsigned int hashtab_hash_priority(const void *obj)
01302 {
01303    const struct ast_exten *ac = obj;
01304    return ast_hashtab_hash_int(ac->priority);
01305 }
01306 
01307 static unsigned int hashtab_hash_labels(const void *obj)
01308 {
01309    const struct ast_exten *ac = obj;
01310    return ast_hashtab_hash_string(S_OR(ac->label, ""));
01311 }
01312 
01313 
01314 AST_RWLOCK_DEFINE_STATIC(globalslock);
01315 static struct varshead globals = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
01316 
01317 static int autofallthrough = 1;
01318 static int extenpatternmatchnew = 0;
01319 static char *overrideswitch = NULL;
01320 
01321 /*! \brief Subscription for device state change events */
01322 static struct ast_event_sub *device_state_sub;
01323 /*! \brief Subscription for presence state change events */
01324 static struct ast_event_sub *presence_state_sub;
01325 
01326 AST_MUTEX_DEFINE_STATIC(maxcalllock);
01327 static int countcalls;
01328 static int totalcalls;
01329 
01330 static AST_RWLIST_HEAD_STATIC(acf_root, ast_custom_function);
01331 
01332 /*!
01333  * \brief Extra information for an \ref ast_custom_function holding privilege
01334  * escalation information. Kept in a separate structure for ABI compatibility.
01335  */
01336 struct ast_custom_escalating_function {
01337    AST_RWLIST_ENTRY(ast_custom_escalating_function) list;
01338    const struct ast_custom_function *acf;
01339    unsigned int read_escalates:1;
01340    unsigned int write_escalates:1;
01341 };
01342 
01343 static AST_RWLIST_HEAD_STATIC(escalation_root, ast_custom_escalating_function);
01344 
01345 /*! \brief Declaration of builtin applications */
01346 static struct pbx_builtin {
01347    char name[AST_MAX_APP];
01348    int (*execute)(struct ast_channel *chan, const char *data);
01349 } builtins[] =
01350 {
01351    /* These applications are built into the PBX core and do not
01352       need separate modules */
01353 
01354    { "Answer",         pbx_builtin_answer },
01355    { "BackGround",     pbx_builtin_background },
01356    { "Busy",           pbx_builtin_busy },
01357    { "Congestion",     pbx_builtin_congestion },
01358    { "ExecIfTime",     pbx_builtin_execiftime },
01359    { "Goto",           pbx_builtin_goto },
01360    { "GotoIf",         pbx_builtin_gotoif },
01361    { "GotoIfTime",     pbx_builtin_gotoiftime },
01362    { "ImportVar",      pbx_builtin_importvar },
01363    { "Hangup",         pbx_builtin_hangup },
01364    { "Incomplete",     pbx_builtin_incomplete },
01365    { "NoOp",           pbx_builtin_noop },
01366    { "Proceeding",     pbx_builtin_proceeding },
01367    { "Progress",       pbx_builtin_progress },
01368    { "RaiseException", pbx_builtin_raise_exception },
01369    { "ResetCDR",       pbx_builtin_resetcdr },
01370    { "Ringing",        pbx_builtin_ringing },
01371    { "SayAlpha",       pbx_builtin_saycharacters },
01372    { "SayDigits",      pbx_builtin_saydigits },
01373    { "SayNumber",      pbx_builtin_saynumber },
01374    { "SayPhonetic",    pbx_builtin_sayphonetic },
01375    { "Set",            pbx_builtin_setvar },
01376    { "MSet",           pbx_builtin_setvar_multiple },
01377    { "SetAMAFlags",    pbx_builtin_setamaflags },
01378    { "Wait",           pbx_builtin_wait },
01379    { "WaitExten",      pbx_builtin_waitexten }
01380 };
01381 
01382 static struct ast_context *contexts;
01383 static struct ast_hashtab *contexts_table = NULL;
01384 
01385 /*!
01386  * \brief Lock for the ast_context list
01387  * \note
01388  * This lock MUST be recursive, or a deadlock on reload may result.  See
01389  * https://issues.asterisk.org/view.php?id=17643
01390  */
01391 AST_MUTEX_DEFINE_STATIC(conlock);
01392 
01393 /*!
01394  * \brief Lock to hold off restructuring of hints by ast_merge_contexts_and_delete.
01395  */
01396 AST_MUTEX_DEFINE_STATIC(context_merge_lock);
01397 
01398 static AST_RWLIST_HEAD_STATIC(apps, ast_app);
01399 
01400 static AST_RWLIST_HEAD_STATIC(switches, ast_switch);
01401 
01402 static int stateid = 1;
01403 /*!
01404  * \note When holding this container's lock, do _not_ do
01405  * anything that will cause conlock to be taken, unless you
01406  * _already_ hold it.  The ast_merge_contexts_and_delete function
01407  * will take the locks in conlock/hints order, so any other
01408  * paths that require both locks must also take them in that
01409  * order.
01410  */
01411 static struct ao2_container *hints;
01412 
01413 static struct ao2_container *statecbs;
01414 
01415 #ifdef CONTEXT_DEBUG
01416 
01417 /* these routines are provided for doing run-time checks
01418    on the extension structures, in case you are having
01419    problems, this routine might help you localize where
01420    the problem is occurring. It's kinda like a debug memory
01421    allocator's arena checker... It'll eat up your cpu cycles!
01422    but you'll see, if you call it in the right places,
01423    right where your problems began...
01424 */
01425 
01426 /* you can break on the check_contexts_trouble()
01427 routine in your debugger to stop at the moment
01428 there's a problem */
01429 void check_contexts_trouble(void);
01430 
01431 void check_contexts_trouble(void)
01432 {
01433    int x = 1;
01434    x = 2;
01435 }
01436 
01437 int check_contexts(char *, int);
01438 
01439 int check_contexts(char *file, int line )
01440 {
01441    struct ast_hashtab_iter *t1;
01442    struct ast_context *c1, *c2;
01443    int found = 0;
01444    struct ast_exten *e1, *e2, *e3;
01445    struct ast_exten ex;
01446 
01447    /* try to find inconsistencies */
01448    /* is every context in the context table in the context list and vice-versa ? */
01449 
01450    if (!contexts_table) {
01451       ast_log(LOG_NOTICE,"Called from: %s:%d: No contexts_table!\n", file, line);
01452       usleep(500000);
01453    }
01454 
01455    t1 = ast_hashtab_start_traversal(contexts_table);
01456    while( (c1 = ast_hashtab_next(t1))) {
01457       for(c2=contexts;c2;c2=c2->next) {
01458          if (!strcmp(c1->name, c2->name)) {
01459             found = 1;
01460             break;
01461          }
01462       }
01463       if (!found) {
01464          ast_log(LOG_NOTICE,"Called from: %s:%d: Could not find the %s context in the linked list\n", file, line, c1->name);
01465          check_contexts_trouble();
01466       }
01467    }
01468    ast_hashtab_end_traversal(t1);
01469    for(c2=contexts;c2;c2=c2->next) {
01470       c1 = find_context_locked(c2->name);
01471       if (!c1) {
01472          ast_log(LOG_NOTICE,"Called from: %s:%d: Could not find the %s context in the hashtab\n", file, line, c2->name);
01473          check_contexts_trouble();
01474       } else
01475          ast_unlock_contexts();
01476    }
01477 
01478    /* loop thru all contexts, and verify the exten structure compares to the
01479       hashtab structure */
01480    for(c2=contexts;c2;c2=c2->next) {
01481       c1 = find_context_locked(c2->name);
01482       if (c1) {
01483          ast_unlock_contexts();
01484 
01485          /* is every entry in the root list also in the root_table? */
01486          for(e1 = c1->root; e1; e1=e1->next)
01487          {
01488             char dummy_name[1024];
01489             ex.exten = dummy_name;
01490             ex.matchcid = e1->matchcid;
01491             ex.cidmatch = e1->cidmatch;
01492             ast_copy_string(dummy_name, e1->exten, sizeof(dummy_name));
01493             e2 = ast_hashtab_lookup(c1->root_table, &ex);
01494             if (!e2) {
01495                if (e1->matchcid == AST_EXT_MATCHCID_ON) {
01496                   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 );
01497                } else {
01498                   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 );
01499                }
01500                check_contexts_trouble();
01501             }
01502          }
01503 
01504          /* is every entry in the root_table also in the root list? */
01505          if (!c2->root_table) {
01506             if (c2->root) {
01507                ast_log(LOG_NOTICE,"Called from: %s:%d: No c2->root_table for context %s!\n", file, line, c2->name);
01508                usleep(500000);
01509             }
01510          } else {
01511             t1 = ast_hashtab_start_traversal(c2->root_table);
01512             while( (e2 = ast_hashtab_next(t1)) ) {
01513                for(e1=c2->root;e1;e1=e1->next) {
01514                   if (!strcmp(e1->exten, e2->exten)) {
01515                      found = 1;
01516                      break;
01517                   }
01518                }
01519                if (!found) {
01520                   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);
01521                   check_contexts_trouble();
01522                }
01523 
01524             }
01525             ast_hashtab_end_traversal(t1);
01526          }
01527       }
01528       /* is every priority reflected in the peer_table at the head of the list? */
01529 
01530       /* is every entry in the root list also in the root_table? */
01531       /* are the per-extension peer_tables in the right place? */
01532 
01533       for(e1 = c2->root; e1; e1 = e1->next) {
01534 
01535          for(e2=e1;e2;e2=e2->peer) {
01536             ex.priority = e2->priority;
01537             if (e2 != e1 && e2->peer_table) {
01538                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 );
01539                check_contexts_trouble();
01540             }
01541 
01542             if (e2 != e1 && e2->peer_label_table) {
01543                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 );
01544                check_contexts_trouble();
01545             }
01546 
01547             if (e2 == e1 && !e2->peer_table){
01548                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 );
01549                check_contexts_trouble();
01550             }
01551 
01552             if (e2 == e1 && !e2->peer_label_table) {
01553                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 );
01554                check_contexts_trouble();
01555             }
01556 
01557 
01558             e3 = ast_hashtab_lookup(e1->peer_table, &ex);
01559             if (!e3) {
01560                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 );
01561                check_contexts_trouble();
01562             }
01563          }
01564 
01565          if (!e1->peer_table){
01566             ast_log(LOG_NOTICE,"Called from: %s:%d: No e1->peer_table!\n", file, line);
01567             usleep(500000);
01568          }
01569 
01570          /* is every entry in the peer_table also in the peer list? */
01571          t1 = ast_hashtab_start_traversal(e1->peer_table);
01572          while( (e2 = ast_hashtab_next(t1)) ) {
01573             for(e3=e1;e3;e3=e3->peer) {
01574                if (e3->priority == e2->priority) {
01575                   found = 1;
01576                   break;
01577                }
01578             }
01579             if (!found) {
01580                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 );
01581                check_contexts_trouble();
01582             }
01583          }
01584          ast_hashtab_end_traversal(t1);
01585       }
01586    }
01587    return 0;
01588 }
01589 #endif
01590 
01591 /*
01592    \note This function is special. It saves the stack so that no matter
01593    how many times it is called, it returns to the same place */
01594 int pbx_exec(struct ast_channel *c, /*!< Channel */
01595         struct ast_app *app,  /*!< Application */
01596         const char *data)     /*!< Data for execution */
01597 {
01598    int res;
01599    struct ast_module_user *u = NULL;
01600    const char *saved_c_appl;
01601    const char *saved_c_data;
01602 
01603    if (ast_channel_cdr(c) && !ast_check_hangup(c))
01604       ast_cdr_setapp(ast_channel_cdr(c), app->name, data);
01605 
01606    /* save channel values */
01607    saved_c_appl= ast_channel_appl(c);
01608    saved_c_data= ast_channel_data(c);
01609 
01610    ast_channel_appl_set(c, app->name);
01611    ast_channel_data_set(c, data);
01612    ast_cel_report_event(c, AST_CEL_APP_START, NULL, NULL, NULL);
01613 
01614    if (app->module)
01615       u = __ast_module_user_add(app->module, c);
01616    if (strcasecmp(app->name, "system") && !ast_strlen_zero(data) &&
01617          strchr(data, '|') && !strchr(data, ',') && !ast_opt_dont_warn) {
01618       ast_log(LOG_WARNING, "The application delimiter is now the comma, not "
01619          "the pipe.  Did you forget to convert your dialplan?  (%s(%s))\n",
01620          app->name, (char *) data);
01621    }
01622    res = app->execute(c, S_OR(data, ""));
01623    if (app->module && u)
01624       __ast_module_user_remove(app->module, u);
01625    ast_cel_report_event(c, AST_CEL_APP_END, NULL, NULL, NULL);
01626    /* restore channel values */
01627    ast_channel_appl_set(c, saved_c_appl);
01628    ast_channel_data_set(c, saved_c_data);
01629    return res;
01630 }
01631 
01632 /*! \brief Find application handle in linked list
01633  */
01634 struct ast_app *pbx_findapp(const char *app)
01635 {
01636    struct ast_app *tmp;
01637 
01638    AST_RWLIST_RDLOCK(&apps);
01639    AST_RWLIST_TRAVERSE(&apps, tmp, list) {
01640       if (!strcasecmp(tmp->name, app))
01641          break;
01642    }
01643    AST_RWLIST_UNLOCK(&apps);
01644 
01645    return tmp;
01646 }
01647 
01648 static struct ast_switch *pbx_findswitch(const char *sw)
01649 {
01650    struct ast_switch *asw;
01651 
01652    AST_RWLIST_RDLOCK(&switches);
01653    AST_RWLIST_TRAVERSE(&switches, asw, list) {
01654       if (!strcasecmp(asw->name, sw))
01655          break;
01656    }
01657    AST_RWLIST_UNLOCK(&switches);
01658 
01659    return asw;
01660 }
01661 
01662 static inline int include_valid(struct ast_include *i)
01663 {
01664    if (!i->hastime)
01665       return 1;
01666 
01667    return ast_check_timing(&(i->timing));
01668 }
01669 
01670 static void pbx_destroy(struct ast_pbx *p)
01671 {
01672    ast_free(p);
01673 }
01674 
01675 /* form a tree that fully describes all the patterns in a context's extensions
01676  * in this tree, a "node" represents an individual character or character set
01677  * meant to match the corresponding character in a dial string. The tree
01678  * consists of a series of match_char structs linked in a chain
01679  * via the alt_char pointers. More than one pattern can share the same parts of the
01680  * tree as other extensions with the same pattern to that point.
01681  * My first attempt to duplicate the finding of the 'best' pattern was flawed in that
01682  * I misunderstood the general algorithm. I thought that the 'best' pattern
01683  * was the one with lowest total score. This was not true. Thus, if you have
01684  * patterns "1XXXXX" and "X11111", you would be tempted to say that "X11111" is
01685  * the "best" match because it has fewer X's, and is therefore more specific,
01686  * but this is not how the old algorithm works. It sorts matching patterns
01687  * in a similar collating sequence as sorting alphabetic strings, from left to
01688  * right. Thus, "1XXXXX" comes before "X11111", and would be the "better" match,
01689  * because "1" is more specific than "X".
01690  * So, to accomodate this philosophy, I sort the tree branches along the alt_char
01691  * line so they are lowest to highest in specificity numbers. This way, as soon
01692  * as we encounter our first complete match, we automatically have the "best"
01693  * match and can stop the traversal immediately. Same for CANMATCH/MATCHMORE.
01694  * If anyone would like to resurrect the "wrong" pattern trie searching algorithm,
01695  * they are welcome to revert pbx to before 1 Apr 2008.
01696  * As an example, consider these 4 extensions:
01697  * (a) NXXNXXXXXX
01698  * (b) 307754XXXX
01699  * (c) fax
01700  * (d) NXXXXXXXXX
01701  *
01702  * In the above, between (a) and (d), (a) is a more specific pattern than (d), and would win over
01703  * most numbers. For all numbers beginning with 307754, (b) should always win.
01704  *
01705  * These pattern should form a (sorted) tree that looks like this:
01706  *   { "3" }  --next-->  { "0" }  --next--> { "7" } --next--> { "7" } --next--> { "5" } ... blah ... --> { "X" exten_match: (b) }
01707  *      |
01708  *      |alt
01709  *      |
01710  *   { "f" }  --next-->  { "a" }  --next--> { "x"  exten_match: (c) }
01711  *   { "N" }  --next-->  { "X" }  --next--> { "X" } --next--> { "N" } --next--> { "X" } ... blah ... --> { "X" exten_match: (a) }
01712  *      |                                                        |
01713  *      |                                                        |alt
01714  *      |alt                                                     |
01715  *      |                                                     { "X" } --next--> { "X" } ... blah ... --> { "X" exten_match: (d) }
01716  *      |
01717  *     NULL
01718  *
01719  *   In the above, I could easily turn "N" into "23456789", but I think that a quick "if( *z >= '2' && *z <= '9' )" might take
01720  *   fewer CPU cycles than a call to strchr("23456789",*z), where *z is the char to match...
01721  *
01722  *   traversal is pretty simple: one routine merely traverses the alt list, and for each matching char in the pattern,  it calls itself
01723  *   on the corresponding next pointer, incrementing also the pointer of the string to be matched, and passing the total specificity and length.
01724  *   We pass a pointer to a scoreboard down through, also.
01725  *   The scoreboard isn't as necessary to the revised algorithm, but I kept it as a handy way to return the matched extension.
01726  *   The first complete match ends the traversal, which should make this version of the pattern matcher faster
01727  *   the previous. The same goes for "CANMATCH" or "MATCHMORE"; the first such match ends the traversal. In both
01728  *   these cases, the reason we can stop immediately, is because the first pattern match found will be the "best"
01729  *   according to the sort criteria.
01730  *   Hope the limit on stack depth won't be a problem... this routine should
01731  *   be pretty lean as far a stack usage goes. Any non-match terminates the recursion down a branch.
01732  *
01733  *   In the above example, with the number "3077549999" as the pattern, the traversor could match extensions a, b and d.  All are
01734  *   of length 10; they have total specificities of  24580, 10246, and 25090, respectively, not that this matters
01735  *   at all. (b) wins purely because the first character "3" is much more specific (lower specificity) than "N". I have
01736  *   left the specificity totals in the code as an artifact; at some point, I will strip it out.
01737  *
01738  *   Just how much time this algorithm might save over a plain linear traversal over all possible patterns is unknown,
01739  *   because it's a function of how many extensions are stored in a context. With thousands of extensions, the speedup
01740  *   can be very noticeable. The new matching algorithm can run several hundreds of times faster, if not a thousand or
01741  *   more times faster in extreme cases.
01742  *
01743  *   MatchCID patterns are also supported, and stored in the tree just as the extension pattern is. Thus, you
01744  *   can have patterns in your CID field as well.
01745  *
01746  * */
01747 
01748 
01749 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)
01750 {
01751    /* if this extension is marked as deleted, then skip this -- if it never shows
01752       on the scoreboard, it will never be found, nor will halt the traversal. */
01753    if (deleted)
01754       return;
01755    board->total_specificity = spec;
01756    board->total_length = length;
01757    board->exten = exten;
01758    board->last_char = last;
01759    board->node = node;
01760 #ifdef NEED_DEBUG_HERE
01761    ast_log(LOG_NOTICE,"Scoreboarding (LONGER) %s, len=%d, score=%d\n", exten->exten, length, spec);
01762 #endif
01763 }
01764 
01765 #ifdef NEED_DEBUG
01766 static void log_match_char_tree(struct match_char *node, char *prefix)
01767 {
01768    char extenstr[40];
01769    struct ast_str *my_prefix = ast_str_alloca(1024);
01770 
01771    extenstr[0] = '\0';
01772 
01773    if (node && node->exten)
01774       snprintf(extenstr, sizeof(extenstr), "(%p)", node->exten);
01775 
01776    if (strlen(node->x) > 1) {
01777       ast_debug(1, "%s[%s]:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y':'N',
01778          node->deleted? 'D':'-', node->specificity, node->exten? "EXTEN:":"",
01779          node->exten ? node->exten->exten : "", extenstr);
01780    } else {
01781       ast_debug(1, "%s%s:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y':'N',
01782          node->deleted? 'D':'-', node->specificity, node->exten? "EXTEN:":"",
01783          node->exten ? node->exten->exten : "", extenstr);
01784    }
01785 
01786    ast_str_set(&my_prefix, 0, "%s+       ", prefix);
01787 
01788    if (node->next_char)
01789       log_match_char_tree(node->next_char, ast_str_buffer(my_prefix));
01790 
01791    if (node->alt_char)
01792       log_match_char_tree(node->alt_char, prefix);
01793 }
01794 #endif
01795 
01796 static void cli_match_char_tree(struct match_char *node, char *prefix, int fd)
01797 {
01798    char extenstr[40];
01799    struct ast_str *my_prefix = ast_str_alloca(1024);
01800 
01801    extenstr[0] = '\0';
01802 
01803    if (node->exten) {
01804       snprintf(extenstr, sizeof(extenstr), "(%p)", node->exten);
01805    }
01806 
01807    if (strlen(node->x) > 1) {
01808       ast_cli(fd, "%s[%s]:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y' : 'N',
01809          node->deleted ? 'D' : '-', node->specificity, node->exten? "EXTEN:" : "",
01810          node->exten ? node->exten->exten : "", extenstr);
01811    } else {
01812       ast_cli(fd, "%s%s:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y' : 'N',
01813          node->deleted ? 'D' : '-', node->specificity, node->exten? "EXTEN:" : "",
01814          node->exten ? node->exten->exten : "", extenstr);
01815    }
01816 
01817    ast_str_set(&my_prefix, 0, "%s+       ", prefix);
01818 
01819    if (node->next_char)
01820       cli_match_char_tree(node->next_char, ast_str_buffer(my_prefix), fd);
01821 
01822    if (node->alt_char)
01823       cli_match_char_tree(node->alt_char, prefix, fd);
01824 }
01825 
01826 static struct ast_exten *get_canmatch_exten(struct match_char *node)
01827 {
01828    /* find the exten at the end of the rope */
01829    struct match_char *node2 = node;
01830 
01831    for (node2 = node; node2; node2 = node2->next_char) {
01832       if (node2->exten) {
01833 #ifdef NEED_DEBUG_HERE
01834          ast_log(LOG_NOTICE,"CanMatch_exten returns exten %s(%p)\n", node2->exten->exten, node2->exten);
01835 #endif
01836          return node2->exten;
01837       }
01838    }
01839 #ifdef NEED_DEBUG_HERE
01840    ast_log(LOG_NOTICE,"CanMatch_exten returns NULL, match_char=%s\n", node->x);
01841 #endif
01842    return 0;
01843 }
01844 
01845 static struct ast_exten *trie_find_next_match(struct match_char *node)
01846 {
01847    struct match_char *m3;
01848    struct match_char *m4;
01849    struct ast_exten *e3;
01850 
01851    if (node && node->x[0] == '.' && !node->x[1]) { /* dot and ! will ALWAYS be next match in a matchmore */
01852       return node->exten;
01853    }
01854 
01855    if (node && node->x[0] == '!' && !node->x[1]) {
01856       return node->exten;
01857    }
01858 
01859    if (!node || !node->next_char) {
01860       return NULL;
01861    }
01862 
01863    m3 = node->next_char;
01864 
01865    if (m3->exten) {
01866       return m3->exten;
01867    }
01868    for (m4 = m3->alt_char; m4; m4 = m4->alt_char) {
01869       if (m4->exten) {
01870          return m4->exten;
01871       }
01872    }
01873    for (m4 = m3; m4; m4 = m4->alt_char) {
01874       e3 = trie_find_next_match(m3);
01875       if (e3) {
01876          return e3;
01877       }
01878    }
01879 
01880    return NULL;
01881 }
01882 
01883 #ifdef DEBUG_THIS
01884 static char *action2str(enum ext_match_t action)
01885 {
01886    switch (action) {
01887    case E_MATCH:
01888       return "MATCH";
01889    case E_CANMATCH:
01890       return "CANMATCH";
01891    case E_MATCHMORE:
01892       return "MATCHMORE";
01893    case E_FINDLABEL:
01894       return "FINDLABEL";
01895    case E_SPAWN:
01896       return "SPAWN";
01897    default:
01898       return "?ACTION?";
01899    }
01900 }
01901 
01902 #endif
01903 
01904 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)
01905 {
01906    struct match_char *p; /* note minimal stack storage requirements */
01907    struct ast_exten pattern = { .label = label };
01908 #ifdef DEBUG_THIS
01909    if (tree)
01910       ast_log(LOG_NOTICE,"new_find_extension called with %s on (sub)tree %s action=%s\n", str, tree->x, action2str(action));
01911    else
01912       ast_log(LOG_NOTICE,"new_find_extension called with %s on (sub)tree NULL action=%s\n", str, action2str(action));
01913 #endif
01914    for (p = tree; p; p = p->alt_char) {
01915       if (p->is_pattern) {
01916          if (p->x[0] == 'N') {
01917             if (p->x[1] == 0 && *str >= '2' && *str <= '9' ) {
01918 #define  NEW_MATCHER_CHK_MATCH          \
01919                if (p->exten && !(*(str + 1))) { /* if a shorter pattern matches along the way, might as well report it */             \
01920                   if (action == E_MATCH || action == E_SPAWN || action == E_FINDLABEL) { /* if in CANMATCH/MATCHMORE, don't let matches get in the way */   \
01921                      update_scoreboard(score, length + 1, spec + p->specificity, p->exten, 0, callerid, p->deleted, p);                 \
01922                      if (!p->deleted) {                                                                                           \
01923                         if (action == E_FINDLABEL) {                                                                             \
01924                            if (ast_hashtab_lookup(score->exten->peer_label_table, &pattern)) {                                  \
01925                               ast_debug(4, "Found label in preferred extension\n");                                            \
01926                               return;                                                                                          \
01927                            }                                                                                                    \
01928                         } else {                                                                                                 \
01929                            ast_debug(4, "returning an exact match-- first found-- %s\n", p->exten->exten);                       \
01930                            return; /* the first match, by definition, will be the best, because of the sorted tree */           \
01931                         }                                                                                                        \
01932                      }                                                                                                            \
01933                   }                                                                                                                \
01934                }
01935 
01936 #define  NEW_MATCHER_RECURSE             \
01937                if (p->next_char && (*(str + 1) || (p->next_char->x[0] == '/' && p->next_char->x[1] == 0)                 \
01938                                              || p->next_char->x[0] == '!')) {                                          \
01939                   if (*(str + 1) || p->next_char->x[0] == '!') {                                                         \
01940                      new_find_extension(str + 1, score, p->next_char, length + 1, spec + p->specificity, callerid, label, action); \
01941                      if (score->exten)  {                                                                             \
01942                           ast_debug(4 ,"returning an exact match-- %s\n", score->exten->exten);                         \
01943                         return; /* the first match is all we need */                                                 \
01944                      }                                                                                    \
01945                   } else {                                                                                             \
01946                      new_find_extension("/", score, p->next_char, length + 1, spec + p->specificity, callerid, label, action);    \
01947                      if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) {      \
01948                           ast_debug(4,"returning a (can/more) match--- %s\n", score->exten ? score->exten->exten :     \
01949                                      "NULL");                                                                        \
01950                         return; /* the first match is all we need */                                                 \
01951                      }                                                                                    \
01952                   }                                                                                                    \
01953                } else if ((p->next_char || action == E_CANMATCH) && !*(str + 1)) {                                                                  \
01954                   score->canmatch = 1;                                                                                 \
01955                   score->canmatch_exten = get_canmatch_exten(p);                                                       \
01956                   if (action == E_CANMATCH || action == E_MATCHMORE) {                                                 \
01957                        ast_debug(4, "returning a canmatch/matchmore--- str=%s\n", str);                                  \
01958                      return;                                                                                          \
01959                   }                                                                                        \
01960                }
01961 
01962                NEW_MATCHER_CHK_MATCH;
01963                NEW_MATCHER_RECURSE;
01964             }
01965          } else if (p->x[0] == 'Z') {
01966             if (p->x[1] == 0 && *str >= '1' && *str <= '9' ) {
01967                NEW_MATCHER_CHK_MATCH;
01968                NEW_MATCHER_RECURSE;
01969             }
01970          } else if (p->x[0] == 'X') {
01971             if (p->x[1] == 0 && *str >= '0' && *str <= '9' ) {
01972                NEW_MATCHER_CHK_MATCH;
01973                NEW_MATCHER_RECURSE;
01974             }
01975          } else if (p->x[0] == '.' && p->x[1] == 0) {
01976             /* how many chars will the . match against? */
01977             int i = 0;
01978             const char *str2 = str;
01979             while (*str2 && *str2 != '/') {
01980                str2++;
01981                i++;
01982             }
01983             if (p->exten && *str2 != '/') {
01984                update_scoreboard(score, length + i, spec + (i * p->specificity), p->exten, '.', callerid, p->deleted, p);
01985                if (score->exten) {
01986                   ast_debug(4,"return because scoreboard has a match with '/'--- %s\n", score->exten->exten);
01987                   return; /* the first match is all we need */
01988                }
01989             }
01990             if (p->next_char && p->next_char->x[0] == '/' && p->next_char->x[1] == 0) {
01991                new_find_extension("/", score, p->next_char, length + i, spec+(p->specificity*i), callerid, label, action);
01992                if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) {
01993                   ast_debug(4, "return because scoreboard has exact match OR CANMATCH/MATCHMORE & canmatch set--- %s\n", score->exten ? score->exten->exten : "NULL");
01994                   return; /* the first match is all we need */
01995                }
01996             }
01997          } else if (p->x[0] == '!' && p->x[1] == 0) {
01998             /* how many chars will the . match against? */
01999             int i = 1;
02000             const char *str2 = str;
02001             while (*str2 && *str2 != '/') {
02002                str2++;
02003                i++;
02004             }
02005             if (p->exten && *str2 != '/') {
02006                update_scoreboard(score, length + 1, spec + (p->specificity * i), p->exten, '!', callerid, p->deleted, p);
02007                if (score->exten) {
02008                   ast_debug(4, "return because scoreboard has a '!' match--- %s\n", score->exten->exten);
02009                   return; /* the first match is all we need */
02010                }
02011             }
02012             if (p->next_char && p->next_char->x[0] == '/' && p->next_char->x[1] == 0) {
02013                new_find_extension("/", score, p->next_char, length + i, spec + (p->specificity * i), callerid, label, action);
02014                if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) {
02015                   ast_debug(4, "return because scoreboard has exact match OR CANMATCH/MATCHMORE & canmatch set with '/' and '!'--- %s\n", score->exten ? score->exten->exten : "NULL");
02016                   return; /* the first match is all we need */
02017                }
02018             }
02019          } else if (p->x[0] == '/' && p->x[1] == 0) {
02020             /* the pattern in the tree includes the cid match! */
02021             if (p->next_char && callerid && *callerid) {
02022                new_find_extension(callerid, score, p->next_char, length + 1, spec, callerid, label, action);
02023                if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) {
02024                   ast_debug(4, "return because scoreboard has exact match OR CANMATCH/MATCHMORE & canmatch set with '/'--- %s\n", score->exten ? score->exten->exten : "NULL");
02025                   return; /* the first match is all we need */
02026                }
02027             }
02028          } else if (strchr(p->x, *str)) {
02029             ast_debug(4, "Nothing strange about this match\n");
02030             NEW_MATCHER_CHK_MATCH;
02031             NEW_MATCHER_RECURSE;
02032          }
02033       } else if (strchr(p->x, *str)) {
02034          ast_debug(4, "Nothing strange about this match\n");
02035          NEW_MATCHER_CHK_MATCH;
02036          NEW_MATCHER_RECURSE;
02037       }
02038    }
02039    ast_debug(4, "return at end of func\n");
02040 }
02041 
02042 /* the algorithm for forming the extension pattern tree is also a bit simple; you
02043  * traverse all the extensions in a context, and for each char of the extension,
02044  * you see if it exists in the tree; if it doesn't, you add it at the appropriate
02045  * spot. What more can I say? At the end of each exten, you cap it off by adding the
02046  * address of the extension involved. Duplicate patterns will be complained about.
02047  *
02048  * Ideally, this would be done for each context after it is created and fully
02049  * filled. It could be done as a finishing step after extensions.conf or .ael is
02050  * loaded, or it could be done when the first search is encountered. It should only
02051  * have to be done once, until the next unload or reload.
02052  *
02053  * I guess forming this pattern tree would be analogous to compiling a regex. Except
02054  * that a regex only handles 1 pattern, really. This trie holds any number
02055  * of patterns. Well, really, it **could** be considered a single pattern,
02056  * where the "|" (or) operator is allowed, I guess, in a way, sort of...
02057  */
02058 
02059 static struct match_char *already_in_tree(struct match_char *current, char *pat, int is_pattern)
02060 {
02061    struct match_char *t;
02062 
02063    if (!current) {
02064       return 0;
02065    }
02066 
02067    for (t = current; t; t = t->alt_char) {
02068       if (is_pattern == t->is_pattern && !strcmp(pat, t->x)) {/* uh, we may want to sort exploded [] contents to make matching easy */
02069          return t;
02070       }
02071    }
02072 
02073    return 0;
02074 }
02075 
02076 /* The first arg is the location of the tree ptr, or the
02077    address of the next_char ptr in the node, so we can mess
02078    with it, if we need to insert at the beginning of the list */
02079 
02080 static void insert_in_next_chars_alt_char_list(struct match_char **parent_ptr, struct match_char *node)
02081 {
02082    struct match_char *curr, *lcurr;
02083 
02084    /* insert node into the tree at "current", so the alt_char list from current is
02085       sorted in increasing value as you go to the leaves */
02086    if (!(*parent_ptr)) {
02087       *parent_ptr = node;
02088       return;
02089    }
02090 
02091    if ((*parent_ptr)->specificity > node->specificity) {
02092       /* insert at head */
02093       node->alt_char = (*parent_ptr);
02094       *parent_ptr = node;
02095       return;
02096    }
02097 
02098    lcurr = *parent_ptr;
02099    for (curr = (*parent_ptr)->alt_char; curr; curr = curr->alt_char) {
02100       if (curr->specificity > node->specificity) {
02101          node->alt_char = curr;
02102          lcurr->alt_char = node;
02103          break;
02104       }
02105       lcurr = curr;
02106    }
02107 
02108    if (!curr) {
02109       lcurr->alt_char = node;
02110    }
02111 
02112 }
02113 
02114 struct pattern_node {
02115    /*! Pattern node specificity */
02116    int specif;
02117    /*! Pattern node match characters. */
02118    char buf[256];
02119 };
02120 
02121 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)
02122 {
02123    struct match_char *m;
02124 
02125    if (!(m = ast_calloc(1, sizeof(*m) + strlen(pattern->buf)))) {
02126       return NULL;
02127    }
02128 
02129    /* strcpy is safe here since we know its size and have allocated
02130     * just enough space for when we allocated m
02131     */
02132    strcpy(m->x, pattern->buf);
02133 
02134    /* the specificity scores are the same as used in the old
02135       pattern matcher. */
02136    m->is_pattern = is_pattern;
02137    if (pattern->specif == 1 && is_pattern && pattern->buf[0] == 'N') {
02138       m->specificity = 0x0832;
02139    } else if (pattern->specif == 1 && is_pattern && pattern->buf[0] == 'Z') {
02140       m->specificity = 0x0931;
02141    } else if (pattern->specif == 1 && is_pattern && pattern->buf[0] == 'X') {
02142       m->specificity = 0x0a30;
02143    } else if (pattern->specif == 1 && is_pattern && pattern->buf[0] == '.') {
02144       m->specificity = 0x18000;
02145    } else if (pattern->specif == 1 && is_pattern && pattern->buf[0] == '!') {
02146       m->specificity = 0x28000;
02147    } else {
02148       m->specificity = pattern->specif;
02149    }
02150 
02151    if (!con->pattern_tree) {
02152       insert_in_next_chars_alt_char_list(&con->pattern_tree, m);
02153    } else {
02154       if (already) { /* switch to the new regime (traversing vs appending)*/
02155          insert_in_next_chars_alt_char_list(nextcharptr, m);
02156       } else {
02157          insert_in_next_chars_alt_char_list(&current->next_char, m);
02158       }
02159    }
02160 
02161    return m;
02162 }
02163 
02164 /*!
02165  * \internal
02166  * \brief Extract the next exten pattern node.
02167  *
02168  * \param node Pattern node to fill.
02169  * \param src Next source character to read.
02170  * \param pattern TRUE if the exten is a pattern.
02171  * \param extenbuf Original exten buffer to use in diagnostic messages.
02172  *
02173  * \retval Ptr to next extenbuf pos to read.
02174  */
02175 static const char *get_pattern_node(struct pattern_node *node, const char *src, int pattern, const char *extenbuf)
02176 {
02177 #define INC_DST_OVERFLOW_CHECK                     \
02178    do {                                   \
02179       if (dst - node->buf < sizeof(node->buf) - 1) {  \
02180          ++dst;                              \
02181       } else {                            \
02182          overflow = 1;                       \
02183       }                                   \
02184    } while (0)
02185 
02186    node->specif = 0;
02187    node->buf[0] = '\0';
02188    while (*src) {
02189       if (*src == '[' && pattern) {
02190          char *dst = node->buf;
02191          const char *src_next;
02192          int length;
02193          int overflow = 0;
02194 
02195          /* get past the '[' */
02196          ++src;
02197          for (;;) {
02198             if (*src == '\\') {
02199                /* Escaped character. */
02200                ++src;
02201                if (*src == '[' || *src == '\\' || *src == '-' || *src == ']') {
02202                   *dst = *src++;
02203                   INC_DST_OVERFLOW_CHECK;
02204                }
02205             } else if (*src == '-') {
02206                unsigned char first;
02207                unsigned char last;
02208 
02209                src_next = src;
02210                first = *(src_next - 1);
02211                last = *++src_next;
02212 
02213                if (last == '\\') {
02214                   /* Escaped character. */
02215                   last = *++src_next;
02216                }
02217 
02218                /* Possible char range. */
02219                if (node->buf[0] && last) {
02220                   /* Expand the char range. */
02221                   while (++first <= last) {
02222                      *dst = first;
02223                      INC_DST_OVERFLOW_CHECK;
02224                   }
02225                   src = src_next + 1;
02226                } else {
02227                   /*
02228                    * There was no left or right char for the range.
02229                    * It is just a '-'.
02230                    */
02231                   *dst = *src++;
02232                   INC_DST_OVERFLOW_CHECK;
02233                }
02234             } else if (*src == '\0') {
02235                ast_log(LOG_WARNING,
02236                   "A matching ']' was not found for '[' in exten pattern '%s'\n",
02237                   extenbuf);
02238                break;
02239             } else if (*src == ']') {
02240                ++src;
02241                break;
02242             } else {
02243                *dst = *src++;
02244                INC_DST_OVERFLOW_CHECK;
02245             }
02246          }
02247          /* null terminate the exploded range */
02248          *dst = '\0';
02249 
02250          if (overflow) {
02251             ast_log(LOG_ERROR,
02252                "Expanded character set too large to deal with in exten pattern '%s'. Ignoring character set.\n",
02253                extenbuf);
02254             node->buf[0] = '\0';
02255             continue;
02256          }
02257 
02258          /* Sort the characters in character set. */
02259          length = strlen(node->buf);
02260          if (!length) {
02261             ast_log(LOG_WARNING, "Empty character set in exten pattern '%s'. Ignoring.\n",
02262                extenbuf);
02263             node->buf[0] = '\0';
02264             continue;
02265          }
02266          qsort(node->buf, length, 1, compare_char);
02267 
02268          /* Remove duplicate characters from character set. */
02269          dst = node->buf;
02270          src_next = node->buf;
02271          while (*src_next++) {
02272             if (*dst != *src_next) {
02273                *++dst = *src_next;
02274             }
02275          }
02276 
02277          length = strlen(node->buf);
02278          length <<= 8;
02279          node->specif = length | (unsigned char) node->buf[0];
02280          break;
02281       } else if (*src == '-') {
02282          /* Skip dashes in all extensions. */
02283          ++src;
02284       } else {
02285          if (*src == '\\') {
02286             /*
02287              * XXX The escape character here does not remove any special
02288              * meaning to characters except the '[', '\\', and '-'
02289              * characters since they are special only in this function.
02290              */
02291             node->buf[0] = *++src;
02292             if (!node->buf[0]) {
02293                break;
02294             }
02295          } else {
02296             node->buf[0] = *src;
02297             if (pattern) {
02298                /* make sure n,x,z patterns are canonicalized to N,X,Z */
02299                if (node->buf[0] == 'n') {
02300                   node->buf[0] = 'N';
02301                } else if (node->buf[0] == 'x') {
02302                   node->buf[0] = 'X';
02303                } else if (node->buf[0] == 'z') {
02304                   node->buf[0] = 'Z';
02305                }
02306             }
02307          }
02308          node->buf[1] = '\0';
02309          node->specif = 1;
02310          ++src;
02311          break;
02312       }
02313    }
02314    return src;
02315 
02316 #undef INC_DST_OVERFLOW_CHECK
02317 }
02318 
02319 static struct match_char *add_exten_to_pattern_tree(struct ast_context *con, struct ast_exten *e1, int findonly)
02320 {
02321    struct match_char *m1 = NULL;
02322    struct match_char *m2 = NULL;
02323    struct match_char **m0;
02324    const char *pos;
02325    int already;
02326    int pattern = 0;
02327    int idx_cur;
02328    int idx_next;
02329    char extenbuf[512];
02330    struct pattern_node pat_node[2];
02331 
02332    if (e1->matchcid) {
02333       if (sizeof(extenbuf) < strlen(e1->exten) + strlen(e1->cidmatch) + 2) {
02334          ast_log(LOG_ERROR,
02335             "The pattern %s/%s is too big to deal with: it will be ignored! Disaster!\n",
02336             e1->exten, e1->cidmatch);
02337          return NULL;
02338       }
02339       sprintf(extenbuf, "%s/%s", e1->exten, e1->cidmatch);/* Safe.  We just checked. */
02340    } else {
02341       ast_copy_string(extenbuf, e1->exten, sizeof(extenbuf));
02342    }
02343 
02344 #ifdef NEED_DEBUG
02345    ast_debug(1, "Adding exten %s to tree\n", extenbuf);
02346 #endif
02347    m1 = con->pattern_tree; /* each pattern starts over at the root of the pattern tree */
02348    m0 = &con->pattern_tree;
02349    already = 1;
02350 
02351    pos = extenbuf;
02352    if (*pos == '_') {
02353       pattern = 1;
02354       ++pos;
02355    }
02356    idx_cur = 0;
02357    pos = get_pattern_node(&pat_node[idx_cur], pos, pattern, extenbuf);
02358    for (; pat_node[idx_cur].buf[0]; idx_cur = idx_next) {
02359       idx_next = (idx_cur + 1) % ARRAY_LEN(pat_node);
02360       pos = get_pattern_node(&pat_node[idx_next], pos, pattern, extenbuf);
02361 
02362       /* See about adding node to tree. */
02363       m2 = NULL;
02364       if (already && (m2 = already_in_tree(m1, pat_node[idx_cur].buf, pattern))
02365          && m2->next_char) {
02366          if (!pat_node[idx_next].buf[0]) {
02367             /*
02368              * This is the end of the pattern, but not the end of the tree.
02369              * Mark this node with the exten... a shorter pattern might win
02370              * if the longer one doesn't match.
02371              */
02372             if (findonly) {
02373                return m2;
02374             }
02375             if (m2->exten) {
02376                ast_log(LOG_WARNING, "Found duplicate exten. Had %s found %s\n",
02377                   m2->deleted ? "(deleted/invalid)" : m2->exten->exten, e1->exten);
02378             }
02379             m2->exten = e1;
02380             m2->deleted = 0;
02381          }
02382          m1 = m2->next_char; /* m1 points to the node to compare against */
02383          m0 = &m2->next_char; /* m0 points to the ptr that points to m1 */
02384       } else { /* not already OR not m2 OR nor m2->next_char */
02385          if (m2) {
02386             if (findonly) {
02387                return m2;
02388             }
02389             m1 = m2; /* while m0 stays the same */
02390          } else {
02391             if (findonly) {
02392                return m1;
02393             }
02394             m1 = add_pattern_node(con, m1, &pat_node[idx_cur], pattern, already, m0);
02395             if (!m1) { /* m1 is the node just added */
02396                return NULL;
02397             }
02398             m0 = &m1->next_char;
02399          }
02400          if (!pat_node[idx_next].buf[0]) {
02401             if (m2 && m2->exten) {
02402                ast_log(LOG_WARNING, "Found duplicate exten. Had %s found %s\n",
02403                   m2->deleted ? "(deleted/invalid)" : m2->exten->exten, e1->exten);
02404             }
02405             m1->deleted = 0;
02406             m1->exten = e1;
02407          }
02408 
02409          /* The 'already' variable is a mini-optimization designed to make it so that we
02410           * don't have to call already_in_tree when we know it will return false.
02411           */
02412          already = 0;
02413       }
02414    }
02415    return m1;
02416 }
02417 
02418 static void create_match_char_tree(struct ast_context *con)
02419 {
02420    struct ast_hashtab_iter *t1;
02421    struct ast_exten *e1;
02422 #ifdef NEED_DEBUG
02423    int biggest_bucket, resizes, numobjs, numbucks;
02424 
02425    ast_debug(1, "Creating Extension Trie for context %s(%p)\n", con->name, con);
02426    ast_hashtab_get_stats(con->root_table, &biggest_bucket, &resizes, &numobjs, &numbucks);
02427    ast_debug(1, "This tree has %d objects in %d bucket lists, longest list=%d objects, and has resized %d times\n",
02428          numobjs, numbucks, biggest_bucket, resizes);
02429 #endif
02430    t1 = ast_hashtab_start_traversal(con->root_table);
02431    while ((e1 = ast_hashtab_next(t1))) {
02432       if (e1->exten) {
02433          add_exten_to_pattern_tree(con, e1, 0);
02434       } else {
02435          ast_log(LOG_ERROR, "Attempt to create extension with no extension name.\n");
02436       }
02437    }
02438    ast_hashtab_end_traversal(t1);
02439 }
02440 
02441 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! */
02442 {
02443    /* destroy all the alternates */
02444    if (pattern_tree->alt_char) {
02445       destroy_pattern_tree(pattern_tree->alt_char);
02446       pattern_tree->alt_char = 0;
02447    }
02448    /* destroy all the nexts */
02449    if (pattern_tree->next_char) {
02450       destroy_pattern_tree(pattern_tree->next_char);
02451       pattern_tree->next_char = 0;
02452    }
02453    pattern_tree->exten = 0; /* never hurts to make sure there's no pointers laying around */
02454    ast_free(pattern_tree);
02455 }
02456 
02457 /*!
02458  * \internal
02459  * \brief Get the length of the exten string.
02460  *
02461  * \param str Exten to get length.
02462  *
02463  * \retval strlen of exten.
02464  */
02465 static int ext_cmp_exten_strlen(const char *str)
02466 {
02467    int len;
02468 
02469    len = 0;
02470    for (;;) {
02471       /* Ignore '-' chars as eye candy fluff. */
02472       while (*str == '-') {
02473          ++str;
02474       }
02475       if (!*str) {
02476          break;
02477       }
02478       ++str;
02479       ++len;
02480    }
02481    return len;
02482 }
02483 
02484 /*!
02485  * \internal
02486  * \brief Partial comparison of non-pattern extens.
02487  *
02488  * \param left Exten to compare.
02489  * \param right Exten to compare.  Also matches if this string ends first.
02490  *
02491  * \retval <0 if left < right
02492  * \retval =0 if left == right
02493  * \retval >0 if left > right
02494  */
02495 static int ext_cmp_exten_partial(const char *left, const char *right)
02496 {
02497    int cmp;
02498 
02499    for (;;) {
02500       /* Ignore '-' chars as eye candy fluff. */
02501       while (*left == '-') {
02502          ++left;
02503       }
02504       while (*right == '-') {
02505          ++right;
02506       }
02507 
02508       if (!*right) {
02509          /*
02510           * Right ended first for partial match or both ended at the same
02511           * time for a match.
02512           */
02513          cmp = 0;
02514          break;
02515       }
02516 
02517       cmp = *left - *right;
02518       if (cmp) {
02519          break;
02520       }
02521       ++left;
02522       ++right;
02523    }
02524    return cmp;
02525 }
02526 
02527 /*!
02528  * \internal
02529  * \brief Comparison of non-pattern extens.
02530  *
02531  * \param left Exten to compare.
02532  * \param right Exten to compare.
02533  *
02534  * \retval <0 if left < right
02535  * \retval =0 if left == right
02536  * \retval >0 if left > right
02537  */
02538 static int ext_cmp_exten(const char *left, const char *right)
02539 {
02540    int cmp;
02541 
02542    for (;;) {
02543       /* Ignore '-' chars as eye candy fluff. */
02544       while (*left == '-') {
02545          ++left;
02546       }
02547       while (*right == '-') {
02548          ++right;
02549       }
02550 
02551       cmp = *left - *right;
02552       if (cmp) {
02553          break;
02554       }
02555       if (!*left) {
02556          /*
02557           * Get here only if both strings ended at the same time.  cmp
02558           * would be non-zero if only one string ended.
02559           */
02560          break;
02561       }
02562       ++left;
02563       ++right;
02564    }
02565    return cmp;
02566 }
02567 
02568 /*
02569  * Special characters used in patterns:
02570  * '_'   underscore is the leading character of a pattern.
02571  *    In other position it is treated as a regular char.
02572  * '-' The '-' is a separator and ignored.  Why?  So patterns like NXX-XXX-XXXX work.
02573  * .  one or more of any character. Only allowed at the end of
02574  *    a pattern.
02575  * !  zero or more of anything. Also impacts the result of CANMATCH
02576  *    and MATCHMORE. Only allowed at the end of a pattern.
02577  *    In the core routine, ! causes a match with a return code of 2.
02578  *    In turn, depending on the search mode: (XXX check if it is implemented)
02579  *    - E_MATCH retuns 1 (does match)
02580  *    - E_MATCHMORE returns 0 (no match)
02581  *    - E_CANMATCH returns 1 (does match)
02582  *
02583  * /  should not appear as it is considered the separator of the CID info.
02584  *    XXX at the moment we may stop on this char.
02585  *
02586  * X Z N match ranges 0-9, 1-9, 2-9 respectively.
02587  * [  denotes the start of a set of character. Everything inside
02588  *    is considered literally. We can have ranges a-d and individual
02589  *    characters. A '[' and '-' can be considered literally if they
02590  *    are just before ']'.
02591  *    XXX currently there is no way to specify ']' in a range, nor \ is
02592  *    considered specially.
02593  *
02594  * When we compare a pattern with a specific extension, all characters in the extension
02595  * itself are considered literally.
02596  * XXX do we want to consider space as a separator as well ?
02597  * XXX do we want to consider the separators in non-patterns as well ?
02598  */
02599 
02600 /*!
02601  * \brief helper functions to sort extension patterns in the desired way,
02602  * so that more specific patterns appear first.
02603  *
02604  * \details
02605  * The function compares individual characters (or sets of), returning
02606  * an int where bits 0-7 are the ASCII code of the first char in the set,
02607  * bits 8-15 are the number of characters in the set, and bits 16-20 are
02608  * for special cases.
02609  * This way more specific patterns (smaller character sets) appear first.
02610  * Wildcards have a special value, so that we can directly compare them to
02611  * sets by subtracting the two values. In particular:
02612  *  0x001xx     one character, character set starting with xx
02613  *  0x0yyxx     yy characters, character set starting with xx
02614  *  0x18000     '.' (one or more of anything)
02615  *  0x28000     '!' (zero or more of anything)
02616  *  0x30000     NUL (end of string)
02617  *  0x40000     error in set.
02618  * The pointer to the string is advanced according to needs.
02619  * NOTES:
02620  *  1. the empty set is ignored.
02621  *  2. given that a full set has always 0 as the first element,
02622  *     we could encode the special cases as 0xffXX where XX
02623  *     is 1, 2, 3, 4 as used above.
02624  */
02625 static int ext_cmp_pattern_pos(const char **p, unsigned char *bitwise)
02626 {
02627 #define BITS_PER  8  /* Number of bits per unit (byte). */
02628    unsigned char c;
02629    unsigned char cmin;
02630    int count;
02631    const char *end;
02632 
02633    do {
02634       /* Get character and advance. (Ignore '-' chars as eye candy fluff.) */
02635       do {
02636          c = *(*p)++;
02637       } while (c == '-');
02638 
02639       /* always return unless we have a set of chars */
02640       switch (c) {
02641       default:
02642          /* ordinary character */
02643          bitwise[c / BITS_PER] = 1 << ((BITS_PER - 1) - (c % BITS_PER));
02644          return 0x0100 | c;
02645 
02646       case 'n':
02647       case 'N':
02648          /* 2..9 */
02649          bitwise[6] = 0x3f;
02650          bitwise[7] = 0xc0;
02651          return 0x0800 | '2';
02652 
02653       case 'x':
02654       case 'X':
02655          /* 0..9 */
02656          bitwise[6] = 0xff;
02657          bitwise[7] = 0xc0;
02658          return 0x0A00 | '0';
02659 
02660       case 'z':
02661       case 'Z':
02662          /* 1..9 */
02663          bitwise[6] = 0x7f;
02664          bitwise[7] = 0xc0;
02665          return 0x0900 | '1';
02666 
02667       case '.':
02668          /* wildcard */
02669          return 0x18000;
02670 
02671       case '!':
02672          /* earlymatch */
02673          return 0x28000;   /* less specific than '.' */
02674 
02675       case '\0':
02676          /* empty string */
02677          *p = NULL;
02678          return 0x30000;
02679 
02680       case '[':
02681          /* char set */
02682          break;
02683       }
02684       /* locate end of set */
02685       end = strchr(*p, ']');
02686 
02687       if (!end) {
02688          ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n");
02689          return 0x40000;   /* XXX make this entry go last... */
02690       }
02691 
02692       count = 0;
02693       cmin = 0xFF;
02694       for (; *p < end; ++*p) {
02695          unsigned char c1; /* first char in range */
02696          unsigned char c2; /* last char in range */
02697 
02698          c1 = (*p)[0];
02699          if (*p + 2 < end && (*p)[1] == '-') { /* this is a range */
02700             c2 = (*p)[2];
02701             *p += 2;    /* skip a total of 3 chars */
02702          } else {        /* individual character */
02703             c2 = c1;
02704          }
02705          if (c1 < cmin) {
02706             cmin = c1;
02707          }
02708          for (; c1 <= c2; ++c1) {
02709             unsigned char mask = 1 << ((BITS_PER - 1) - (c1 % BITS_PER));
02710 
02711             /*
02712              * Note: If two character sets score the same, the one with the
02713              * lowest ASCII values will compare as coming first.  Must fill
02714              * in most significant bits for lower ASCII values to accomplish
02715              * the desired sort order.
02716              */
02717             if (!(bitwise[c1 / BITS_PER] & mask)) {
02718                /* Add the character to the set. */
02719                bitwise[c1 / BITS_PER] |= mask;
02720                count += 0x100;
02721             }
02722          }
02723       }
02724       ++*p;
02725    } while (!count);/* While the char set was empty. */
02726    return count | cmin;
02727 }
02728 
02729 /*!
02730  * \internal
02731  * \brief Comparison of exten patterns.
02732  *
02733  * \param left Pattern to compare.
02734  * \param right Pattern to compare.
02735  *
02736  * \retval <0 if left < right
02737  * \retval =0 if left == right
02738  * \retval >0 if left > right
02739  */
02740 static int ext_cmp_pattern(const char *left, const char *right)
02741 {
02742    int cmp;
02743    int left_pos;
02744    int right_pos;
02745 
02746    for (;;) {
02747       unsigned char left_bitwise[32] = { 0, };
02748       unsigned char right_bitwise[32] = { 0, };
02749 
02750       left_pos = ext_cmp_pattern_pos(&left, left_bitwise);
02751       right_pos = ext_cmp_pattern_pos(&right, right_bitwise);
02752       cmp = left_pos - right_pos;
02753       if (!cmp) {
02754          /*
02755           * Are the character sets different, even though they score the same?
02756           *
02757           * Note: Must swap left and right to get the sense of the
02758           * comparison correct.  Otherwise, we would need to multiply by
02759           * -1 instead.
02760           */
02761          cmp = memcmp(right_bitwise, left_bitwise, ARRAY_LEN(left_bitwise));
02762       }
02763       if (cmp) {
02764          break;
02765       }
02766       if (!left) {
02767          /*
02768           * Get here only if both patterns ended at the same time.  cmp
02769           * would be non-zero if only one pattern ended.
02770           */
02771          break;
02772       }
02773    }
02774    return cmp;
02775 }
02776 
02777 /*!
02778  * \internal
02779  * \brief Comparison of dialplan extens for sorting purposes.
02780  *
02781  * \param left Exten/pattern to compare.
02782  * \param right Exten/pattern to compare.
02783  *
02784  * \retval <0 if left < right
02785  * \retval =0 if left == right
02786  * \retval >0 if left > right
02787  */
02788 static int ext_cmp(const char *left, const char *right)
02789 {
02790    /* Make sure non-pattern extens come first. */
02791    if (left[0] != '_') {
02792       if (right[0] == '_') {
02793          return -1;
02794       }
02795       /* Compare two non-pattern extens. */
02796       return ext_cmp_exten(left, right);
02797    }
02798    if (right[0] != '_') {
02799       return 1;
02800    }
02801 
02802    /*
02803     * OK, we need full pattern sorting routine.
02804     *
02805     * Skip past the underscores
02806     */
02807    return ext_cmp_pattern(left + 1, right + 1);
02808 }
02809 
02810 int ast_extension_cmp(const char *a, const char *b)
02811 {
02812    int cmp;
02813 
02814    cmp = ext_cmp(a, b);
02815    if (cmp < 0) {
02816       return -1;
02817    }
02818    if (cmp > 0) {
02819       return 1;
02820    }
02821    return 0;
02822 }
02823 
02824 /*!
02825  * \internal
02826  * \brief used ast_extension_{match|close}
02827  * mode is as follows:
02828  * E_MATCH     success only on exact match
02829  * E_MATCHMORE success only on partial match (i.e. leftover digits in pattern)
02830  * E_CANMATCH  either of the above.
02831  * \retval 0 on no-match
02832  * \retval 1 on match
02833  * \retval 2 on early match.
02834  */
02835 
02836 static int _extension_match_core(const char *pattern, const char *data, enum ext_match_t mode)
02837 {
02838    mode &= E_MATCH_MASK;   /* only consider the relevant bits */
02839 
02840 #ifdef NEED_DEBUG_HERE
02841    ast_log(LOG_NOTICE,"match core: pat: '%s', dat: '%s', mode=%d\n", pattern, data, (int)mode);
02842 #endif
02843 
02844    if (pattern[0] != '_') { /* not a pattern, try exact or partial match */
02845       int lp = ext_cmp_exten_strlen(pattern);
02846       int ld = ext_cmp_exten_strlen(data);
02847 
02848       if (lp < ld) {    /* pattern too short, cannot match */
02849 #ifdef NEED_DEBUG_HERE
02850          ast_log(LOG_NOTICE,"return (0) - pattern too short, cannot match\n");
02851 #endif
02852          return 0;
02853       }
02854       /* depending on the mode, accept full or partial match or both */
02855       if (mode == E_MATCH) {
02856 #ifdef NEED_DEBUG_HERE
02857          ast_log(LOG_NOTICE,"return (!ext_cmp_exten(%s,%s) when mode== E_MATCH)\n", pattern, data);
02858 #endif
02859          return !ext_cmp_exten(pattern, data); /* 1 on match, 0 on fail */
02860       }
02861       if (ld == 0 || !ext_cmp_exten_partial(pattern, data)) { /* partial or full match */
02862 #ifdef NEED_DEBUG_HERE
02863          ast_log(LOG_NOTICE,"return (mode(%d) == E_MATCHMORE ? lp(%d) > ld(%d) : 1)\n", mode, lp, ld);
02864 #endif
02865          return (mode == E_MATCHMORE) ? lp > ld : 1; /* XXX should consider '!' and '/' ? */
02866       } else {
02867 #ifdef NEED_DEBUG_HERE
02868          ast_log(LOG_NOTICE,"return (0) when ld(%d) > 0 && pattern(%s) != data(%s)\n", ld, pattern, data);
02869 #endif
02870          return 0;
02871       }
02872    }
02873    if (mode == E_MATCH && data[0] == '_') {
02874       /*
02875        * XXX It is bad design that we don't know if we should be
02876        * comparing data and pattern as patterns or comparing data if
02877        * it conforms to pattern when the function is called.  First,
02878        * assume they are both patterns.  If they don't match then try
02879        * to see if data conforms to the given pattern.
02880        *
02881        * note: if this test is left out, then _x. will not match _x. !!!
02882        */
02883 #ifdef NEED_DEBUG_HERE
02884       ast_log(LOG_NOTICE, "Comparing as patterns first. pattern:%s data:%s\n", pattern, data);
02885 #endif
02886       if (!ext_cmp_pattern(pattern + 1, data + 1)) {
02887 #ifdef NEED_DEBUG_HERE
02888          ast_log(LOG_NOTICE,"return (1) - pattern matches pattern\n");
02889 #endif
02890          return 1;
02891       }
02892    }
02893 
02894    ++pattern; /* skip leading _ */
02895    /*
02896     * XXX below we stop at '/' which is a separator for the CID info. However we should
02897     * not store '/' in the pattern at all. When we insure it, we can remove the checks.
02898     */
02899    for (;;) {
02900       const char *end;
02901 
02902       /* Ignore '-' chars as eye candy fluff. */
02903       while (*data == '-') {
02904          ++data;
02905       }
02906       while (*pattern == '-') {
02907          ++pattern;
02908       }
02909       if (!*data || !*pattern || *pattern == '/') {
02910          break;
02911       }
02912 
02913       switch (*pattern) {
02914       case '[':   /* a range */
02915          ++pattern;
02916          end = strchr(pattern, ']'); /* XXX should deal with escapes ? */
02917          if (!end) {
02918             ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n");
02919             return 0;   /* unconditional failure */
02920          }
02921          if (pattern == end) {
02922             /* Ignore empty character sets. */
02923             ++pattern;
02924             continue;
02925          }
02926          for (; pattern < end; ++pattern) {
02927             if (pattern+2 < end && pattern[1] == '-') { /* this is a range */
02928                if (*data >= pattern[0] && *data <= pattern[2])
02929                   break;   /* match found */
02930                else {
02931                   pattern += 2; /* skip a total of 3 chars */
02932                   continue;
02933                }
02934             } else if (*data == pattern[0])
02935                break;   /* match found */
02936          }
02937          if (pattern >= end) {
02938 #ifdef NEED_DEBUG_HERE
02939             ast_log(LOG_NOTICE,"return (0) when pattern>=end\n");
02940 #endif
02941             return 0;
02942          }
02943          pattern = end; /* skip and continue */
02944          break;
02945       case 'n':
02946       case 'N':
02947          if (*data < '2' || *data > '9') {
02948 #ifdef NEED_DEBUG_HERE
02949             ast_log(LOG_NOTICE,"return (0) N is not matched\n");
02950 #endif
02951             return 0;
02952          }
02953          break;
02954       case 'x':
02955       case 'X':
02956          if (*data < '0' || *data > '9') {
02957 #ifdef NEED_DEBUG_HERE
02958             ast_log(LOG_NOTICE,"return (0) X is not matched\n");
02959 #endif
02960             return 0;
02961          }
02962          break;
02963       case 'z':
02964       case 'Z':
02965          if (*data < '1' || *data > '9') {
02966 #ifdef NEED_DEBUG_HERE
02967             ast_log(LOG_NOTICE,"return (0) Z is not matched\n");
02968 #endif
02969             return 0;
02970          }
02971          break;
02972       case '.':   /* Must match, even with more digits */
02973 #ifdef NEED_DEBUG_HERE
02974          ast_log(LOG_NOTICE, "return (1) when '.' is matched\n");
02975 #endif
02976          return 1;
02977       case '!':   /* Early match */
02978 #ifdef NEED_DEBUG_HERE
02979          ast_log(LOG_NOTICE, "return (2) when '!' is matched\n");
02980 #endif
02981          return 2;
02982       default:
02983          if (*data != *pattern) {
02984 #ifdef NEED_DEBUG_HERE
02985             ast_log(LOG_NOTICE, "return (0) when *data(%c) != *pattern(%c)\n", *data, *pattern);
02986 #endif
02987             return 0;
02988          }
02989          break;
02990       }
02991       ++data;
02992       ++pattern;
02993    }
02994    if (*data)        /* data longer than pattern, no match */ {
02995 #ifdef NEED_DEBUG_HERE
02996       ast_log(LOG_NOTICE, "return (0) when data longer than pattern\n");
02997 #endif
02998       return 0;
02999    }
03000 
03001    /*
03002     * match so far, but ran off the end of data.
03003     * Depending on what is next, determine match or not.
03004     */
03005    if (*pattern == '\0' || *pattern == '/') {   /* exact match */
03006 #ifdef NEED_DEBUG_HERE
03007       ast_log(LOG_NOTICE, "at end, return (%d) in 'exact match'\n", (mode==E_MATCHMORE) ? 0 : 1);
03008 #endif
03009       return (mode == E_MATCHMORE) ? 0 : 1;  /* this is a failure for E_MATCHMORE */
03010    } else if (*pattern == '!')   {     /* early match */
03011 #ifdef NEED_DEBUG_HERE
03012       ast_log(LOG_NOTICE, "at end, return (2) when '!' is matched\n");
03013 #endif
03014       return 2;
03015    } else {                /* partial match */
03016 #ifdef NEED_DEBUG_HERE
03017       ast_log(LOG_NOTICE, "at end, return (%d) which deps on E_MATCH\n", (mode == E_MATCH) ? 0 : 1);
03018 #endif
03019       return (mode == E_MATCH) ? 0 : 1;   /* this is a failure for E_MATCH */
03020    }
03021 }
03022 
03023 /*
03024  * Wrapper around _extension_match_core() to do performance measurement
03025  * using the profiling code.
03026  */
03027 static int extension_match_core(const char *pattern, const char *data, enum ext_match_t mode)
03028 {
03029    int i;
03030    static int prof_id = -2;   /* marker for 'unallocated' id */
03031    if (prof_id == -2) {
03032       prof_id = ast_add_profile("ext_match", 0);
03033    }
03034    ast_mark(prof_id, 1);
03035    i = _extension_match_core(ast_strlen_zero(pattern) ? "" : pattern, ast_strlen_zero(data) ? "" : data, mode);
03036    ast_mark(prof_id, 0);
03037    return i;
03038 }
03039 
03040 int ast_extension_match(const char *pattern, const char *data)
03041 {
03042    return extension_match_core(pattern, data, E_MATCH);
03043 }
03044 
03045 int ast_extension_close(const char *pattern, const char *data, int needmore)
03046 {
03047    if (needmore != E_MATCHMORE && needmore != E_CANMATCH)
03048       ast_log(LOG_WARNING, "invalid argument %d\n", needmore);
03049    return extension_match_core(pattern, data, needmore);
03050 }
03051 
03052 struct fake_context /* this struct is purely for matching in the hashtab */
03053 {
03054    ast_rwlock_t lock;
03055    struct ast_exten *root;
03056    struct ast_hashtab *root_table;
03057    struct match_char *pattern_tree;
03058    struct ast_context *next;
03059    struct ast_include *includes;
03060    struct ast_ignorepat *ignorepats;
03061    const char *registrar;
03062    int refcount;
03063    AST_LIST_HEAD_NOLOCK(, ast_sw) alts;
03064    ast_mutex_t macrolock;
03065    char name[256];
03066 };
03067 
03068 struct ast_context *ast_context_find(const char *name)
03069 {
03070    struct ast_context *tmp;
03071    struct fake_context item;
03072 
03073    if (!name) {
03074       return NULL;
03075    }
03076    ast_rdlock_contexts();
03077    if (contexts_table) {
03078       ast_copy_string(item.name, name, sizeof(item.name));
03079       tmp = ast_hashtab_lookup(contexts_table, &item);
03080    } else {
03081       tmp = NULL;
03082       while ((tmp = ast_walk_contexts(tmp))) {
03083          if (!strcasecmp(name, tmp->name)) {
03084             break;
03085          }
03086       }
03087    }
03088    ast_unlock_contexts();
03089    return tmp;
03090 }
03091 
03092 #define STATUS_NO_CONTEXT  1
03093 #define STATUS_NO_EXTENSION   2
03094 #define STATUS_NO_PRIORITY 3
03095 #define STATUS_NO_LABEL    4
03096 #define STATUS_SUCCESS     5
03097 
03098 static int matchcid(const char *cidpattern, const char *callerid)
03099 {
03100    /* If the Caller*ID pattern is empty, then we're matching NO Caller*ID, so
03101       failing to get a number should count as a match, otherwise not */
03102 
03103    if (ast_strlen_zero(callerid)) {
03104       return ast_strlen_zero(cidpattern) ? 1 : 0;
03105    }
03106 
03107    return ast_extension_match(cidpattern, callerid);
03108 }
03109 
03110 struct ast_exten *pbx_find_extension(struct ast_channel *chan,
03111    struct ast_context *bypass, struct pbx_find_info *q,
03112    const char *context, const char *exten, int priority,
03113    const char *label, const char *callerid, enum ext_match_t action)
03114 {
03115    int x, res;
03116    struct ast_context *tmp = NULL;
03117    struct ast_exten *e = NULL, *eroot = NULL;
03118    struct ast_include *i = NULL;
03119    struct ast_sw *sw = NULL;
03120    struct ast_exten pattern = {NULL, };
03121    struct scoreboard score = {0, };
03122    struct ast_str *tmpdata = NULL;
03123 
03124    pattern.label = label;
03125    pattern.priority = priority;
03126 #ifdef NEED_DEBUG_HERE
03127    ast_log(LOG_NOTICE, "Looking for cont/ext/prio/label/action = %s/%s/%d/%s/%d\n", context, exten, priority, label, (int) action);
03128 #endif
03129 
03130    /* Initialize status if appropriate */
03131    if (q->stacklen == 0) {
03132       q->status = STATUS_NO_CONTEXT;
03133       q->swo = NULL;
03134       q->data = NULL;
03135       q->foundcontext = NULL;
03136    } else if (q->stacklen >= AST_PBX_MAX_STACK) {
03137       ast_log(LOG_WARNING, "Maximum PBX stack exceeded\n");
03138       return NULL;
03139    }
03140 
03141    /* Check first to see if we've already been checked */
03142    for (x = 0; x < q->stacklen; x++) {
03143       if (!strcasecmp(q->incstack[x], context))
03144          return NULL;
03145    }
03146 
03147    if (bypass) { /* bypass means we only look there */
03148       tmp = bypass;
03149    } else {      /* look in contexts */
03150       tmp = find_context(context);
03151       if (!tmp) {
03152          return NULL;
03153       }
03154    }
03155 
03156    if (q->status < STATUS_NO_EXTENSION)
03157       q->status = STATUS_NO_EXTENSION;
03158 
03159    /* Do a search for matching extension */
03160 
03161    eroot = NULL;
03162    score.total_specificity = 0;
03163    score.exten = 0;
03164    score.total_length = 0;
03165    if (!tmp->pattern_tree && tmp->root_table) {
03166       create_match_char_tree(tmp);
03167 #ifdef NEED_DEBUG
03168       ast_debug(1, "Tree Created in context %s:\n", context);
03169       log_match_char_tree(tmp->pattern_tree," ");
03170 #endif
03171    }
03172 #ifdef NEED_DEBUG
03173    ast_log(LOG_NOTICE, "The Trie we are searching in:\n");
03174    log_match_char_tree(tmp->pattern_tree, "::  ");
03175 #endif
03176 
03177    do {
03178       if (!ast_strlen_zero(overrideswitch)) {
03179          char *osw = ast_strdupa(overrideswitch), *name;
03180          struct ast_switch *asw;
03181          ast_switch_f *aswf = NULL;
03182          char *datap;
03183          int eval = 0;
03184 
03185          name = strsep(&osw, "/");
03186          asw = pbx_findswitch(name);
03187 
03188          if (!asw) {
03189             ast_log(LOG_WARNING, "No such switch '%s'\n", name);
03190             break;
03191          }
03192 
03193          if (osw && strchr(osw, '$')) {
03194             eval = 1;
03195          }
03196 
03197          if (eval && !(tmpdata = ast_str_thread_get(&switch_data, 512))) {
03198             ast_log(LOG_WARNING, "Can't evaluate overrideswitch?!\n");
03199             break;
03200          } else if (eval) {
03201             /* Substitute variables now */
03202             pbx_substitute_variables_helper(chan, osw, ast_str_buffer(tmpdata), ast_str_size(tmpdata));
03203             datap = ast_str_buffer(tmpdata);
03204          } else {
03205             datap = osw;
03206          }
03207 
03208          /* equivalent of extension_match_core() at the switch level */
03209          if (action == E_CANMATCH)
03210             aswf = asw->canmatch;
03211          else if (action == E_MATCHMORE)
03212             aswf = asw->matchmore;
03213          else /* action == E_MATCH */
03214             aswf = asw->exists;
03215          if (!aswf) {
03216             res = 0;
03217          } else {
03218             if (chan) {
03219                ast_autoservice_start(chan);
03220             }
03221             res = aswf(chan, context, exten, priority, callerid, datap);
03222             if (chan) {
03223                ast_autoservice_stop(chan);
03224             }
03225          }
03226          if (res) {  /* Got a match */
03227             q->swo = asw;
03228             q->data = datap;
03229             q->foundcontext = context;
03230             /* XXX keep status = STATUS_NO_CONTEXT ? */
03231             return NULL;
03232          }
03233       }
03234    } while (0);
03235 
03236    if (extenpatternmatchnew) {
03237       new_find_extension(exten, &score, tmp->pattern_tree, 0, 0, callerid, label, action);
03238       eroot = score.exten;
03239 
03240       if (score.last_char == '!' && action == E_MATCHMORE) {
03241          /* We match an extension ending in '!'.
03242           * The decision in this case is final and is NULL (no match).
03243           */
03244 #ifdef NEED_DEBUG_HERE
03245          ast_log(LOG_NOTICE,"Returning MATCHMORE NULL with exclamation point.\n");
03246 #endif
03247          return NULL;
03248       }
03249 
03250       if (!eroot && (action == E_CANMATCH || action == E_MATCHMORE) && score.canmatch_exten) {
03251          q->status = STATUS_SUCCESS;
03252 #ifdef NEED_DEBUG_HERE
03253          ast_log(LOG_NOTICE,"Returning CANMATCH exten %s\n", score.canmatch_exten->exten);
03254 #endif
03255          return score.canmatch_exten;
03256       }
03257 
03258       if ((action == E_MATCHMORE || action == E_CANMATCH)  && eroot) {
03259          if (score.node) {
03260             struct ast_exten *z = trie_find_next_match(score.node);
03261             if (z) {
03262 #ifdef NEED_DEBUG_HERE
03263                ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten %s\n", z->exten);
03264 #endif
03265             } else {
03266                if (score.canmatch_exten) {
03267 #ifdef NEED_DEBUG_HERE
03268                   ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE canmatchmatch exten %s(%p)\n", score.canmatch_exten->exten, score.canmatch_exten);
03269 #endif
03270                   return score.canmatch_exten;
03271                } else {
03272 #ifdef NEED_DEBUG_HERE
03273                   ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten NULL\n");
03274 #endif
03275                }
03276             }
03277             return z;
03278          }
03279 #ifdef NEED_DEBUG_HERE
03280          ast_log(LOG_NOTICE, "Returning CANMATCH/MATCHMORE NULL (no next_match)\n");
03281 #endif
03282          return NULL;  /* according to the code, complete matches are null matches in MATCHMORE mode */
03283       }
03284 
03285       if (eroot) {
03286          /* found entry, now look for the right priority */
03287          if (q->status < STATUS_NO_PRIORITY)
03288             q->status = STATUS_NO_PRIORITY;
03289          e = NULL;
03290          if (action == E_FINDLABEL && label ) {
03291             if (q->status < STATUS_NO_LABEL)
03292                q->status = STATUS_NO_LABEL;
03293             e = ast_hashtab_lookup(eroot->peer_label_table, &pattern);
03294          } else {
03295             e = ast_hashtab_lookup(eroot->peer_table, &pattern);
03296          }
03297          if (e) { /* found a valid match */
03298             q->status = STATUS_SUCCESS;
03299             q->foundcontext = context;
03300 #ifdef NEED_DEBUG_HERE
03301             ast_log(LOG_NOTICE,"Returning complete match of exten %s\n", e->exten);
03302 #endif
03303             return e;
03304          }
03305       }
03306    } else {   /* the old/current default exten pattern match algorithm */
03307 
03308       /* scan the list trying to match extension and CID */
03309       eroot = NULL;
03310       while ( (eroot = ast_walk_context_extensions(tmp, eroot)) ) {
03311          int match = extension_match_core(eroot->exten, exten, action);
03312          /* 0 on fail, 1 on match, 2 on earlymatch */
03313 
03314          if (!match || (eroot->matchcid && !matchcid(eroot->cidmatch, callerid)))
03315             continue;   /* keep trying */
03316          if (match == 2 && action == E_MATCHMORE) {
03317             /* We match an extension ending in '!'.
03318              * The decision in this case is final and is NULL (no match).
03319              */
03320             return NULL;
03321          }
03322          /* found entry, now look for the right priority */
03323          if (q->status < STATUS_NO_PRIORITY)
03324             q->status = STATUS_NO_PRIORITY;
03325          e = NULL;
03326          if (action == E_FINDLABEL && label ) {
03327             if (q->status < STATUS_NO_LABEL)
03328                q->status = STATUS_NO_LABEL;
03329             e = ast_hashtab_lookup(eroot->peer_label_table, &pattern);
03330          } else {
03331             e = ast_hashtab_lookup(eroot->peer_table, &pattern);
03332          }
03333          if (e) { /* found a valid match */
03334             q->status = STATUS_SUCCESS;
03335             q->foundcontext = context;
03336             return e;
03337          }
03338       }
03339    }
03340 
03341    /* Check alternative switches */
03342    AST_LIST_TRAVERSE(&tmp->alts, sw, list) {
03343       struct ast_switch *asw = pbx_findswitch(sw->name);
03344       ast_switch_f *aswf = NULL;
03345       char *datap;
03346 
03347       if (!asw) {
03348          ast_log(LOG_WARNING, "No such switch '%s'\n", sw->name);
03349          continue;
03350       }
03351 
03352       /* Substitute variables now */
03353       if (sw->eval) {
03354          if (!(tmpdata = ast_str_thread_get(&switch_data, 512))) {
03355             ast_log(LOG_WARNING, "Can't evaluate switch?!\n");
03356             continue;
03357          }
03358          pbx_substitute_variables_helper(chan, sw->data, ast_str_buffer(tmpdata), ast_str_size(tmpdata));
03359       }
03360 
03361       /* equivalent of extension_match_core() at the switch level */
03362       if (action == E_CANMATCH)
03363          aswf = asw->canmatch;
03364       else if (action == E_MATCHMORE)
03365          aswf = asw->matchmore;
03366       else /* action == E_MATCH */
03367          aswf = asw->exists;
03368       datap = sw->eval ? ast_str_buffer(tmpdata) : sw->data;
03369       if (!aswf)
03370          res = 0;
03371       else {
03372          if (chan)
03373             ast_autoservice_start(chan);
03374          res = aswf(chan, context, exten, priority, callerid, datap);
03375          if (chan)
03376             ast_autoservice_stop(chan);
03377       }
03378       if (res) {  /* Got a match */
03379          q->swo = asw;
03380          q->data = datap;
03381          q->foundcontext = context;
03382          /* XXX keep status = STATUS_NO_CONTEXT ? */
03383          return NULL;
03384       }
03385    }
03386    q->incstack[q->stacklen++] = tmp->name;   /* Setup the stack */
03387    /* Now try any includes we have in this context */
03388    for (i = tmp->includes; i; i = i->next) {
03389       if (include_valid(i)) {
03390          if ((e = pbx_find_extension(chan, bypass, q, i->rname, exten, priority, label, callerid, action))) {
03391 #ifdef NEED_DEBUG_HERE
03392             ast_log(LOG_NOTICE,"Returning recursive match of %s\n", e->exten);
03393 #endif
03394             return e;
03395          }
03396          if (q->swo)
03397             return NULL;
03398       }
03399    }
03400    return NULL;
03401 }
03402 
03403 /*!
03404  * \brief extract offset:length from variable name.
03405  * \return 1 if there is a offset:length part, which is
03406  * trimmed off (values go into variables)
03407  */
03408 static int parse_variable_name(char *var, int *offset, int *length, int *isfunc)
03409 {
03410    int parens = 0;
03411 
03412    *offset = 0;
03413    *length = INT_MAX;
03414    *isfunc = 0;
03415    for (; *var; var++) {
03416       if (*var == '(') {
03417          (*isfunc)++;
03418          parens++;
03419       } else if (*var == ')') {
03420          parens--;
03421       } else if (*var == ':' && parens == 0) {
03422          *var++ = '\0';
03423          sscanf(var, "%30d:%30d", offset, length);
03424          return 1; /* offset:length valid */
03425       }
03426    }
03427    return 0;
03428 }
03429 
03430 /*!
03431  *\brief takes a substring. It is ok to call with value == workspace.
03432  * \param value
03433  * \param offset < 0 means start from the end of the string and set the beginning
03434  *   to be that many characters back.
03435  * \param length is the length of the substring, a value less than 0 means to leave
03436  * that many off the end.
03437  * \param workspace
03438  * \param workspace_len
03439  * Always return a copy in workspace.
03440  */
03441 static char *substring(const char *value, int offset, int length, char *workspace, size_t workspace_len)
03442 {
03443    char *ret = workspace;
03444    int lr;  /* length of the input string after the copy */
03445 
03446    ast_copy_string(workspace, value, workspace_len); /* always make a copy */
03447 
03448    lr = strlen(ret); /* compute length after copy, so we never go out of the workspace */
03449 
03450    /* Quick check if no need to do anything */
03451    if (offset == 0 && length >= lr) /* take the whole string */
03452       return ret;
03453 
03454    if (offset < 0)   {  /* translate negative offset into positive ones */
03455       offset = lr + offset;
03456       if (offset < 0) /* If the negative offset was greater than the length of the string, just start at the beginning */
03457          offset = 0;
03458    }
03459 
03460    /* too large offset result in empty string so we know what to return */
03461    if (offset >= lr)
03462       return ret + lr;  /* the final '\0' */
03463 
03464    ret += offset;    /* move to the start position */
03465    if (length >= 0 && length < lr - offset)  /* truncate if necessary */
03466       ret[length] = '\0';
03467    else if (length < 0) {
03468       if (lr > offset - length) /* After we remove from the front and from the rear, is there anything left? */
03469          ret[lr + length - offset] = '\0';
03470       else
03471          ret[0] = '\0';
03472    }
03473 
03474    return ret;
03475 }
03476 
03477 static const char *ast_str_substring(struct ast_str *value, int offset, int length)
03478 {
03479    int lr;  /* length of the input string after the copy */
03480 
03481    lr = ast_str_strlen(value); /* compute length after copy, so we never go out of the workspace */
03482 
03483    /* Quick check if no need to do anything */
03484    if (offset == 0 && length >= lr) /* take the whole string */
03485       return ast_str_buffer(value);
03486 
03487    if (offset < 0)   {  /* translate negative offset into positive ones */
03488       offset = lr + offset;
03489       if (offset < 0) /* If the negative offset was greater than the length of the string, just start at the beginning */
03490          offset = 0;
03491    }
03492 
03493    /* too large offset result in empty string so we know what to return */
03494    if (offset >= lr) {
03495       ast_str_reset(value);
03496       return ast_str_buffer(value);
03497    }
03498 
03499    if (offset > 0) {
03500       /* Go ahead and chop off the beginning */
03501       memmove(ast_str_buffer(value), ast_str_buffer(value) + offset, ast_str_strlen(value) - offset + 1);
03502       lr -= offset;
03503    }
03504 
03505    if (length >= 0 && length < lr) {   /* truncate if necessary */
03506       char *tmp = ast_str_buffer(value);
03507       tmp[length] = '\0';
03508       ast_str_update(value);
03509    } else if (length < 0) {
03510       if (lr > -length) { /* After we remove from the front and from the rear, is there anything left? */
03511          char *tmp = ast_str_buffer(value);
03512          tmp[lr + length] = '\0';
03513          ast_str_update(value);
03514       } else {
03515          ast_str_reset(value);
03516       }
03517    } else {
03518       /* Nothing to do, but update the buffer length */
03519       ast_str_update(value);
03520    }
03521 
03522    return ast_str_buffer(value);
03523 }
03524 
03525 /*! \brief  Support for Asterisk built-in variables in the dialplan
03526 
03527 \note See also
03528    - \ref AstVar  Channel variables
03529    - \ref AstCauses The HANGUPCAUSE variable
03530  */
03531 void pbx_retrieve_variable(struct ast_channel *c, const char *var, char **ret, char *workspace, int workspacelen, struct varshead *headp)
03532 {
03533    struct ast_str *str = ast_str_create(16);
03534    const char *cret;
03535 
03536    cret = ast_str_retrieve_variable(&str, 0, c, headp, var);
03537    ast_copy_string(workspace, ast_str_buffer(str), workspacelen);
03538    *ret = cret ? workspace : NULL;
03539    ast_free(str);
03540 }
03541 
03542 const char *ast_str_retrieve_variable(struct ast_str **str, ssize_t maxlen, struct ast_channel *c, struct varshead *headp, const char *var)
03543 {
03544    const char not_found = '\0';
03545    char *tmpvar;
03546    const char *ret;
03547    const char *s; /* the result */
03548    int offset, length;
03549    int i, need_substring;
03550    struct varshead *places[2] = { headp, &globals };  /* list of places where we may look */
03551    char workspace[20];
03552 
03553    if (c) {
03554       ast_channel_lock(c);
03555       places[0] = ast_channel_varshead(c);
03556    }
03557    /*
03558     * Make a copy of var because parse_variable_name() modifies the string.
03559     * Then if called directly, we might need to run substring() on the result;
03560     * remember this for later in 'need_substring', 'offset' and 'length'
03561     */
03562    tmpvar = ast_strdupa(var); /* parse_variable_name modifies the string */
03563    need_substring = parse_variable_name(tmpvar, &offset, &length, &i /* ignored */);
03564 
03565    /*
03566     * Look first into predefined variables, then into variable lists.
03567     * Variable 's' points to the result, according to the following rules:
03568     * s == &not_found (set at the beginning) means that we did not find a
03569     * matching variable and need to look into more places.
03570     * If s != &not_found, s is a valid result string as follows:
03571     * s = NULL if the variable does not have a value;
03572     * you typically do this when looking for an unset predefined variable.
03573     * s = workspace if the result has been assembled there;
03574     * typically done when the result is built e.g. with an snprintf(),
03575     * so we don't need to do an additional copy.
03576     * s != workspace in case we have a string, that needs to be copied
03577     * (the ast_copy_string is done once for all at the end).
03578     * Typically done when the result is already available in some string.
03579     */
03580    s = &not_found;   /* default value */
03581    if (c) { /* This group requires a valid channel */
03582       /* Names with common parts are looked up a piece at a time using strncmp. */
03583       if (!strncmp(var, "CALL", 4)) {
03584          if (!strncmp(var + 4, "ING", 3)) {
03585             if (!strcmp(var + 7, "PRES")) {        /* CALLINGPRES */
03586                ast_str_set(str, maxlen, "%d",
03587                   ast_party_id_presentation(&ast_channel_caller(c)->id));
03588                s = ast_str_buffer(*str);
03589             } else if (!strcmp(var + 7, "ANI2")) {    /* CALLINGANI2 */
03590                ast_str_set(str, maxlen, "%d", ast_channel_caller(c)->ani2);
03591                s = ast_str_buffer(*str);
03592             } else if (!strcmp(var + 7, "TON")) {     /* CALLINGTON */
03593                ast_str_set(str, maxlen, "%d", ast_channel_caller(c)->id.number.plan);
03594                s = ast_str_buffer(*str);
03595             } else if (!strcmp(var + 7, "TNS")) {     /* CALLINGTNS */
03596                ast_str_set(str, maxlen, "%d", ast_channel_dialed(c)->transit_network_select);
03597                s = ast_str_buffer(*str);
03598             }
03599          }
03600       } else if (!strcmp(var, "HINT")) {
03601          s = ast_str_get_hint(str, maxlen, NULL, 0, c, ast_channel_context(c), ast_channel_exten(c)) ? ast_str_buffer(*str) : NULL;
03602       } else if (!strcmp(var, "HINTNAME")) {
03603          s = ast_str_get_hint(NULL, 0, str, maxlen, c, ast_channel_context(c), ast_channel_exten(c)) ? ast_str_buffer(*str) : NULL;
03604       } else if (!strcmp(var, "EXTEN")) {
03605          s = ast_channel_exten(c);
03606       } else if (!strcmp(var, "CONTEXT")) {
03607          s = ast_channel_context(c);
03608       } else if (!strcmp(var, "PRIORITY")) {
03609          ast_str_set(str, maxlen, "%d", ast_channel_priority(c));
03610          s = ast_str_buffer(*str);
03611       } else if (!strcmp(var, "CHANNEL")) {
03612          s = ast_channel_name(c);
03613       } else if (!strcmp(var, "UNIQUEID")) {
03614          s = ast_channel_uniqueid(c);
03615       } else if (!strcmp(var, "HANGUPCAUSE")) {
03616          ast_str_set(str, maxlen, "%d", ast_channel_hangupcause(c));
03617          s = ast_str_buffer(*str);
03618       }
03619    }
03620    if (s == &not_found) { /* look for more */
03621       if (!strcmp(var, "EPOCH")) {
03622          ast_str_set(str, maxlen, "%u", (int) time(NULL));
03623          s = ast_str_buffer(*str);
03624       } else if (!strcmp(var, "SYSTEMNAME")) {
03625          s = ast_config_AST_SYSTEM_NAME;
03626       } else if (!strcmp(var, "ASTETCDIR")) {
03627          s = ast_config_AST_CONFIG_DIR;
03628       } else if (!strcmp(var, "ASTMODDIR")) {
03629          s = ast_config_AST_MODULE_DIR;
03630       } else if (!strcmp(var, "ASTVARLIBDIR")) {
03631          s = ast_config_AST_VAR_DIR;
03632       } else if (!strcmp(var, "ASTDBDIR")) {
03633          s = ast_config_AST_DB;
03634       } else if (!strcmp(var, "ASTKEYDIR")) {
03635          s = ast_config_AST_KEY_DIR;
03636       } else if (!strcmp(var, "ASTDATADIR")) {
03637          s = ast_config_AST_DATA_DIR;
03638       } else if (!strcmp(var, "ASTAGIDIR")) {
03639          s = ast_config_AST_AGI_DIR;
03640       } else if (!strcmp(var, "ASTSPOOLDIR")) {
03641          s = ast_config_AST_SPOOL_DIR;
03642       } else if (!strcmp(var, "ASTRUNDIR")) {
03643          s = ast_config_AST_RUN_DIR;
03644       } else if (!strcmp(var, "ASTLOGDIR")) {
03645          s = ast_config_AST_LOG_DIR;
03646       } else if (!strcmp(var, "ENTITYID")) {
03647          ast_eid_to_str(workspace, sizeof(workspace), &ast_eid_default);
03648          s = workspace;
03649       }
03650    }
03651    /* if not found, look into chanvars or global vars */
03652    for (i = 0; s == &not_found && i < ARRAY_LEN(places); i++) {
03653       struct ast_var_t *variables;
03654       if (!places[i])
03655          continue;
03656       if (places[i] == &globals)
03657          ast_rwlock_rdlock(&globalslock);
03658       AST_LIST_TRAVERSE(places[i], variables, entries) {
03659          if (!strcasecmp(ast_var_name(variables), var)) {
03660             s = ast_var_value(variables);
03661             break;
03662          }
03663       }
03664       if (places[i] == &globals)
03665          ast_rwlock_unlock(&globalslock);
03666    }
03667    if (s == &not_found || s == NULL) {
03668       ast_debug(5, "Result of '%s' is NULL\n", var);
03669       ret = NULL;
03670    } else {
03671       ast_debug(5, "Result of '%s' is '%s'\n", var, s);
03672       if (s != ast_str_buffer(*str)) {
03673          ast_str_set(str, maxlen, "%s", s);
03674       }
03675       ret = ast_str_buffer(*str);
03676       if (need_substring) {
03677          ret = ast_str_substring(*str, offset, length);
03678          ast_debug(2, "Final result of '%s' is '%s'\n", var, ret);
03679       }
03680    }
03681 
03682    if (c) {
03683       ast_channel_unlock(c);
03684    }
03685    return ret;
03686 }
03687 
03688 static void exception_store_free(void *data)
03689 {
03690    struct pbx_exception *exception = data;
03691    ast_string_field_free_memory(exception);
03692    ast_free(exception);
03693 }
03694 
03695 static const struct ast_datastore_info exception_store_info = {
03696    .type = "EXCEPTION",
03697    .destroy = exception_store_free,
03698 };
03699 
03700 /*!
03701  * \internal
03702  * \brief Set the PBX to execute the exception extension.
03703  *
03704  * \param chan Channel to raise the exception on.
03705  * \param reason Reason exception is raised.
03706  * \param priority Dialplan priority to set.
03707  *
03708  * \retval 0 on success.
03709  * \retval -1 on error.
03710  */
03711 static int raise_exception(struct ast_channel *chan, const char *reason, int priority)
03712 {
03713    struct ast_datastore *ds = ast_channel_datastore_find(chan, &exception_store_info, NULL);
03714    struct pbx_exception *exception = NULL;
03715 
03716    if (!ds) {
03717       ds = ast_datastore_alloc(&exception_store_info, NULL);
03718       if (!ds)
03719          return -1;
03720       if (!(exception = ast_calloc_with_stringfields(1, struct pbx_exception, 128))) {
03721          ast_datastore_free(ds);
03722          return -1;
03723       }
03724       ds->data = exception;
03725       ast_channel_datastore_add(chan, ds);
03726    } else
03727       exception = ds->data;
03728 
03729    ast_string_field_set(exception, reason, reason);
03730    ast_string_field_set(exception, context, ast_channel_context(chan));
03731    ast_string_field_set(exception, exten, ast_channel_exten(chan));
03732    exception->priority = ast_channel_priority(chan);
03733    set_ext_pri(chan, "e", priority);
03734    return 0;
03735 }
03736 
03737 int pbx_builtin_raise_exception(struct ast_channel *chan, const char *reason)
03738 {
03739    /* Priority will become 1, next time through the AUTOLOOP */
03740    return raise_exception(chan, reason, 0);
03741 }
03742 
03743 static int acf_exception_read(struct ast_channel *chan, const char *name, char *data, char *buf, size_t buflen)
03744 {
03745    struct ast_datastore *ds = ast_channel_datastore_find(chan, &exception_store_info, NULL);
03746    struct pbx_exception *exception = NULL;
03747    if (!ds || !ds->data)
03748       return -1;
03749    exception = ds->data;
03750    if (!strcasecmp(data, "REASON"))
03751       ast_copy_string(buf, exception->reason, buflen);
03752    else if (!strcasecmp(data, "CONTEXT"))
03753       ast_copy_string(buf, exception->context, buflen);
03754    else if (!strncasecmp(data, "EXTEN", 5))
03755       ast_copy_string(buf, exception->exten, buflen);
03756    else if (!strcasecmp(data, "PRIORITY"))
03757       snprintf(buf, buflen, "%d", exception->priority);
03758    else
03759       return -1;
03760    return 0;
03761 }
03762 
03763 static struct ast_custom_function exception_function = {
03764    .name = "EXCEPTION",
03765    .read = acf_exception_read,
03766 };
03767 
03768 static char *handle_show_functions(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
03769 {
03770    struct ast_custom_function *acf;
03771    int count_acf = 0;
03772    int like = 0;
03773 
03774    switch (cmd) {
03775    case CLI_INIT:
03776       e->command = "core show functions [like]";
03777       e->usage =
03778          "Usage: core show functions [like <text>]\n"
03779          "       List builtin functions, optionally only those matching a given string\n";
03780       return NULL;
03781    case CLI_GENERATE:
03782       return NULL;
03783    }
03784 
03785    if (a->argc == 5 && (!strcmp(a->argv[3], "like")) ) {
03786       like = 1;
03787    } else if (a->argc != 3) {
03788       return CLI_SHOWUSAGE;
03789    }
03790 
03791    ast_cli(a->fd, "%s Custom Functions:\n--------------------------------------------------------------------------------\n", like ? "Matching" : "Installed");
03792 
03793    AST_RWLIST_RDLOCK(&acf_root);
03794    AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) {
03795       if (!like || strstr(acf->name, a->argv[4])) {
03796          count_acf++;
03797          ast_cli(a->fd, "%-20.20s  %-35.35s  %s\n",
03798             S_OR(acf->name, ""),
03799             S_OR(acf->syntax, ""),
03800             S_OR(acf->synopsis, ""));
03801       }
03802    }
03803    AST_RWLIST_UNLOCK(&acf_root);
03804 
03805    ast_cli(a->fd, "%d %scustom functions installed.\n", count_acf, like ? "matching " : "");
03806 
03807    return CLI_SUCCESS;
03808 }
03809 
03810 static char *handle_show_function(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
03811 {
03812    struct ast_custom_function *acf;
03813    /* Maximum number of characters added by terminal coloring is 22 */
03814    char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40], argtitle[40], seealsotitle[40];
03815    char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL, *seealso = NULL;
03816    char stxtitle[40], *syntax = NULL, *arguments = NULL;
03817    int syntax_size, description_size, synopsis_size, arguments_size, seealso_size;
03818    char *ret = NULL;
03819    int which = 0;
03820    int wordlen;
03821 
03822    switch (cmd) {
03823    case CLI_INIT:
03824       e->command = "core show function";
03825       e->usage =
03826          "Usage: core show function <function>\n"
03827          "       Describe a particular dialplan function.\n";
03828       return NULL;
03829    case CLI_GENERATE:
03830       wordlen = strlen(a->word);
03831       /* case-insensitive for convenience in this 'complete' function */
03832       AST_RWLIST_RDLOCK(&acf_root);
03833       AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) {
03834          if (!strncasecmp(a->word, acf->name, wordlen) && ++which > a->n) {
03835             ret = ast_strdup(acf->name);
03836             break;
03837          }
03838       }
03839       AST_RWLIST_UNLOCK(&acf_root);
03840 
03841       return ret;
03842    }
03843 
03844    if (a->argc < 4) {
03845       return CLI_SHOWUSAGE;
03846    }
03847 
03848    if (!(acf = ast_custom_function_find(a->argv[3]))) {
03849       ast_cli(a->fd, "No function by that name registered.\n");
03850       return CLI_FAILURE;
03851    }
03852 
03853    syntax_size = strlen(S_OR(acf->syntax, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
03854    if (!(syntax = ast_malloc(syntax_size))) {
03855       ast_cli(a->fd, "Memory allocation failure!\n");
03856       return CLI_FAILURE;
03857    }
03858 
03859    snprintf(info, sizeof(info), "\n  -= Info about function '%s' =- \n\n", acf->name);
03860    term_color(infotitle, info, COLOR_MAGENTA, 0, sizeof(infotitle));
03861    term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40);
03862    term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40);
03863    term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, 40);
03864    term_color(argtitle, "[Arguments]\n", COLOR_MAGENTA, 0, 40);
03865    term_color(seealsotitle, "[See Also]\n", COLOR_MAGENTA, 0, 40);
03866    term_color(syntax, S_OR(acf->syntax, "Not available"), COLOR_CYAN, 0, syntax_size);
03867 #ifdef AST_XML_DOCS
03868    if (acf->docsrc == AST_XML_DOC) {
03869       arguments = ast_xmldoc_printable(S_OR(acf->arguments, "Not available"), 1);
03870       synopsis = ast_xmldoc_printable(S_OR(acf->synopsis, "Not available"), 1);
03871       description = ast_xmldoc_printable(S_OR(acf->desc, "Not available"), 1);
03872       seealso = ast_xmldoc_printable(S_OR(acf->seealso, "Not available"), 1);
03873    } else
03874 #endif
03875    {
03876       synopsis_size = strlen(S_OR(acf->synopsis, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
03877       synopsis = ast_malloc(synopsis_size);
03878 
03879       description_size = strlen(S_OR(acf->desc, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
03880       description = ast_malloc(description_size);
03881 
03882       arguments_size = strlen(S_OR(acf->arguments, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
03883       arguments = ast_malloc(arguments_size);
03884 
03885       seealso_size = strlen(S_OR(acf->seealso, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
03886       seealso = ast_malloc(seealso_size);
03887 
03888       /* check allocated memory. */
03889       if (!synopsis || !description || !arguments || !seealso) {
03890          ast_free(synopsis);
03891          ast_free(description);
03892          ast_free(arguments);
03893          ast_free(seealso);
03894          ast_free(syntax);
03895          return CLI_FAILURE;
03896       }
03897 
03898       term_color(arguments, S_OR(acf->arguments, "Not available"), COLOR_CYAN, 0, arguments_size);
03899       term_color(synopsis, S_OR(acf->synopsis, "Not available"), COLOR_CYAN, 0, synopsis_size);
03900       term_color(description, S_OR(acf->desc, "Not available"), COLOR_CYAN, 0, description_size);
03901       term_color(seealso, S_OR(acf->seealso, "Not available"), COLOR_CYAN, 0, seealso_size);
03902    }
03903 
03904    ast_cli(a->fd, "%s%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n",
03905          infotitle, syntitle, synopsis, destitle, description,
03906          stxtitle, syntax, argtitle, arguments, seealsotitle, seealso);
03907 
03908    ast_free(arguments);
03909    ast_free(synopsis);
03910    ast_free(description);
03911    ast_free(seealso);
03912    ast_free(syntax);
03913 
03914    return CLI_SUCCESS;
03915 }
03916 
03917 struct ast_custom_function *ast_custom_function_find(const char *name)
03918 {
03919    struct ast_custom_function *acf = NULL;
03920 
03921    AST_RWLIST_RDLOCK(&acf_root);
03922    AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) {
03923       if (!strcmp(name, acf->name))
03924          break;
03925    }
03926    AST_RWLIST_UNLOCK(&acf_root);
03927 
03928    return acf;
03929 }
03930 
03931 int ast_custom_function_unregister(struct ast_custom_function *acf)
03932 {
03933    struct ast_custom_function *cur;
03934    struct ast_custom_escalating_function *cur_escalation;
03935 
03936    if (!acf) {
03937       return -1;
03938    }
03939 
03940    AST_RWLIST_WRLOCK(&acf_root);
03941    if ((cur = AST_RWLIST_REMOVE(&acf_root, acf, acflist))) {
03942 #ifdef AST_XML_DOCS
03943       if (cur->docsrc == AST_XML_DOC) {
03944          ast_string_field_free_memory(acf);
03945       }
03946 #endif
03947       ast_verb(2, "Unregistered custom function %s\n", cur->name);
03948    }
03949    AST_RWLIST_UNLOCK(&acf_root);
03950 
03951    /* Remove from the escalation list */
03952    AST_RWLIST_WRLOCK(&escalation_root);
03953    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&escalation_root, cur_escalation, list) {
03954       if (cur_escalation->acf == acf) {
03955          AST_RWLIST_REMOVE_CURRENT(list);
03956          ast_free(cur_escalation);
03957          break;
03958       }
03959    }
03960    AST_RWLIST_TRAVERSE_SAFE_END;
03961    AST_RWLIST_UNLOCK(&escalation_root);
03962 
03963    return cur ? 0 : -1;
03964 }
03965 
03966 /*!
03967  * \brief Returns true if given custom function escalates privileges on read.
03968  *
03969  * \param acf Custom function to query.
03970  * \return True (non-zero) if reads escalate privileges.
03971  * \return False (zero) if reads just read.
03972  */
03973 static int read_escalates(const struct ast_custom_function *acf) {
03974    int res = 0;
03975    struct ast_custom_escalating_function *cur_escalation;
03976 
03977    AST_RWLIST_RDLOCK(&escalation_root);
03978    AST_RWLIST_TRAVERSE(&escalation_root, cur_escalation, list) {
03979       if (cur_escalation->acf == acf) {
03980          res = cur_escalation->read_escalates;
03981          break;
03982       }
03983    }
03984    AST_RWLIST_UNLOCK(&escalation_root);
03985    return res;
03986 }
03987 
03988 /*!
03989  * \brief Returns true if given custom function escalates privileges on write.
03990  *
03991  * \param acf Custom function to query.
03992  * \return True (non-zero) if writes escalate privileges.
03993  * \return False (zero) if writes just write.
03994  */
03995 static int write_escalates(const struct ast_custom_function *acf) {
03996    int res = 0;
03997    struct ast_custom_escalating_function *cur_escalation;
03998 
03999    AST_RWLIST_RDLOCK(&escalation_root);
04000    AST_RWLIST_TRAVERSE(&escalation_root, cur_escalation, list) {
04001       if (cur_escalation->acf == acf) {
04002          res = cur_escalation->write_escalates;
04003          break;
04004       }
04005    }
04006    AST_RWLIST_UNLOCK(&escalation_root);
04007    return res;
04008 }
04009 
04010 /*! \internal
04011  *  \brief Retrieve the XML documentation of a specified ast_custom_function,
04012  *         and populate ast_custom_function string fields.
04013  *  \param acf ast_custom_function structure with empty 'desc' and 'synopsis'
04014  *             but with a function 'name'.
04015  *  \retval -1 On error.
04016  *  \retval 0 On succes.
04017  */
04018 static int acf_retrieve_docs(struct ast_custom_function *acf)
04019 {
04020 #ifdef AST_XML_DOCS
04021    char *tmpxml;
04022 
04023    /* Let's try to find it in the Documentation XML */
04024    if (!ast_strlen_zero(acf->desc) || !ast_strlen_zero(acf->synopsis)) {
04025       return 0;
04026    }
04027 
04028    if (ast_string_field_init(acf, 128)) {
04029       return -1;
04030    }
04031 
04032    /* load synopsis */
04033    tmpxml = ast_xmldoc_build_synopsis("function", acf->name, ast_module_name(acf->mod));
04034    ast_string_field_set(acf, synopsis, tmpxml);
04035    ast_free(tmpxml);
04036 
04037    /* load description */
04038    tmpxml = ast_xmldoc_build_description("function", acf->name, ast_module_name(acf->mod));
04039    ast_string_field_set(acf, desc, tmpxml);
04040    ast_free(tmpxml);
04041 
04042    /* load syntax */
04043    tmpxml = ast_xmldoc_build_syntax("function", acf->name, ast_module_name(acf->mod));
04044    ast_string_field_set(acf, syntax, tmpxml);
04045    ast_free(tmpxml);
04046 
04047    /* load arguments */
04048    tmpxml = ast_xmldoc_build_arguments("function", acf->name, ast_module_name(acf->mod));
04049    ast_string_field_set(acf, arguments, tmpxml);
04050    ast_free(tmpxml);
04051 
04052    /* load seealso */
04053    tmpxml = ast_xmldoc_build_seealso("function", acf->name, ast_module_name(acf->mod));
04054    ast_string_field_set(acf, seealso, tmpxml);
04055    ast_free(tmpxml);
04056 
04057    acf->docsrc = AST_XML_DOC;
04058 #endif
04059 
04060    return 0;
04061 }
04062 
04063 int __ast_custom_function_register(struct ast_custom_function *acf, struct ast_module *mod)
04064 {
04065    struct ast_custom_function *cur;
04066    char tmps[80];
04067 
04068    if (!acf) {
04069       return -1;
04070    }
04071 
04072    acf->mod = mod;
04073 #ifdef AST_XML_DOCS
04074    acf->docsrc = AST_STATIC_DOC;
04075 #endif
04076 
04077    if (acf_retrieve_docs(acf)) {
04078       return -1;
04079    }
04080 
04081    AST_RWLIST_WRLOCK(&acf_root);
04082 
04083    AST_RWLIST_TRAVERSE(&acf_root, cur, acflist) {
04084       if (!strcmp(acf->name, cur->name)) {
04085          ast_log(LOG_ERROR, "Function %s already registered.\n", acf->name);
04086          AST_RWLIST_UNLOCK(&acf_root);
04087          return -1;
04088       }
04089    }
04090 
04091    /* Store in alphabetical order */
04092    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&acf_root, cur, acflist) {
04093       if (strcasecmp(acf->name, cur->name) < 0) {
04094          AST_RWLIST_INSERT_BEFORE_CURRENT(acf, acflist);
04095          break;
04096       }
04097    }
04098    AST_RWLIST_TRAVERSE_SAFE_END;
04099 
04100    if (!cur) {
04101       AST_RWLIST_INSERT_TAIL(&acf_root, acf, acflist);
04102    }
04103 
04104    AST_RWLIST_UNLOCK(&acf_root);
04105 
04106    ast_verb(2, "Registered custom function '%s'\n", term_color(tmps, acf->name, COLOR_BRCYAN, 0, sizeof(tmps)));
04107 
04108    return 0;
04109 }
04110 
04111 int __ast_custom_function_register_escalating(struct ast_custom_function *acf, enum ast_custom_function_escalation escalation, struct ast_module *mod)
04112 {
04113    struct ast_custom_escalating_function *acf_escalation = NULL;
04114    int res;
04115 
04116    res = __ast_custom_function_register(acf, mod);
04117    if (res != 0) {
04118       return -1;
04119    }
04120 
04121    if (escalation == AST_CFE_NONE) {
04122       /* No escalations; no need to do anything else */
04123       return 0;
04124    }
04125 
04126    acf_escalation = ast_calloc(1, sizeof(*acf_escalation));
04127    if (!acf_escalation) {
04128       ast_custom_function_unregister(acf);
04129       return -1;
04130    }
04131 
04132    acf_escalation->acf = acf;
04133    switch (escalation) {
04134    case AST_CFE_NONE:
04135       break;
04136    case AST_CFE_READ:
04137       acf_escalation->read_escalates = 1;
04138       break;
04139    case AST_CFE_WRITE:
04140       acf_escalation->write_escalates = 1;
04141       break;
04142    case AST_CFE_BOTH:
04143       acf_escalation->read_escalates = 1;
04144       acf_escalation->write_escalates = 1;
04145       break;
04146    }
04147 
04148    AST_RWLIST_WRLOCK(&escalation_root);
04149    AST_RWLIST_INSERT_TAIL(&escalation_root, acf_escalation, list);
04150    AST_RWLIST_UNLOCK(&escalation_root);
04151 
04152    return 0;
04153 }
04154 
04155 /*! \brief return a pointer to the arguments of the function,
04156  * and terminates the function name with '\\0'
04157  */
04158 static char *func_args(char *function)
04159 {
04160    char *args = strchr(function, '(');
04161 
04162    if (!args) {
04163       ast_log(LOG_WARNING, "Function '%s' doesn't contain parentheses.  Assuming null argument.\n", function);
04164    } else {
04165       char *p;
04166       *args++ = '\0';
04167       if ((p = strrchr(args, ')'))) {
04168          *p = '\0';
04169       } else {
04170          ast_log(LOG_WARNING, "Can't find trailing parenthesis for function '%s(%s'?\n", function, args);
04171       }
04172    }
04173    return args;
04174 }
04175 
04176 void pbx_live_dangerously(int new_live_dangerously)
04177 {
04178    if (new_live_dangerously && !live_dangerously) {
04179       ast_log(LOG_WARNING, "Privilege escalation protection disabled!\n"
04180          "See https://wiki.asterisk.org/wiki/x/1gKfAQ for more details.\n");
04181    }
04182 
04183    if (!new_live_dangerously && live_dangerously) {
04184       ast_log(LOG_NOTICE, "Privilege escalation protection enabled.\n");
04185    }
04186    live_dangerously = new_live_dangerously;
04187 }
04188 
04189 int ast_thread_inhibit_escalations(void)
04190 {
04191    int *thread_inhibit_escalations;
04192 
04193    thread_inhibit_escalations = ast_threadstorage_get(
04194       &thread_inhibit_escalations_tl, sizeof(*thread_inhibit_escalations));
04195 
04196    if (thread_inhibit_escalations == NULL) {
04197       ast_log(LOG_ERROR, "Error inhibiting privilege escalations for current thread\n");
04198       return -1;
04199    }
04200 
04201    *thread_inhibit_escalations = 1;
04202    return 0;
04203 }
04204 
04205 /*!
04206  * \brief Indicates whether the current thread inhibits the execution of
04207  * dangerous functions.
04208  *
04209  * \return True (non-zero) if dangerous function execution is inhibited.
04210  * \return False (zero) if dangerous function execution is allowed.
04211  */
04212 static int thread_inhibits_escalations(void)
04213 {
04214    int *thread_inhibit_escalations;
04215 
04216    thread_inhibit_escalations = ast_threadstorage_get(
04217       &thread_inhibit_escalations_tl, sizeof(*thread_inhibit_escalations));
04218 
04219    if (thread_inhibit_escalations == NULL) {
04220       ast_log(LOG_ERROR, "Error checking thread's ability to run dangerous functions\n");
04221       /* On error, assume that we are inhibiting */
04222       return 1;
04223    }
04224 
04225    return *thread_inhibit_escalations;
04226 }
04227 
04228 /*!
04229  * \brief Determines whether execution of a custom function's read function
04230  * is allowed.
04231  *
04232  * \param acfptr Custom function to check
04233  * \return True (non-zero) if reading is allowed.
04234  * \return False (zero) if reading is not allowed.
04235  */
04236 static int is_read_allowed(struct ast_custom_function *acfptr)
04237 {
04238    if (!acfptr) {
04239       return 1;
04240    }
04241 
04242    if (!read_escalates(acfptr)) {
04243       return 1;
04244    }
04245 
04246    if (!thread_inhibits_escalations()) {
04247       return 1;
04248    }
04249 
04250    if (live_dangerously) {
04251       /* Global setting overrides the thread's preference */
04252       ast_debug(2, "Reading %s from a dangerous context\n",
04253          acfptr->name);
04254       return 1;
04255    }
04256 
04257    /* We have no reason to allow this function to execute */
04258    return 0;
04259 }
04260 
04261 /*!
04262  * \brief Determines whether execution of a custom function's write function
04263  * is allowed.
04264  *
04265  * \param acfptr Custom function to check
04266  * \return True (non-zero) if writing is allowed.
04267  * \return False (zero) if writing is not allowed.
04268  */
04269 static int is_write_allowed(struct ast_custom_function *acfptr)
04270 {
04271    if (!acfptr) {
04272       return 1;
04273    }
04274 
04275    if (!write_escalates(acfptr)) {
04276       return 1;
04277    }
04278 
04279    if (!thread_inhibits_escalations()) {
04280       return 1;
04281    }
04282 
04283    if (live_dangerously) {
04284       /* Global setting overrides the thread's preference */
04285       ast_debug(2, "Writing %s from a dangerous context\n",
04286          acfptr->name);
04287       return 1;
04288    }
04289 
04290    /* We have no reason to allow this function to execute */
04291    return 0;
04292 }
04293 
04294 int ast_func_read(struct ast_channel *chan, const char *function, char *workspace, size_t len)
04295 {
04296    char *copy = ast_strdupa(function);
04297    char *args = func_args(copy);
04298    struct ast_custom_function *acfptr = ast_custom_function_find(copy);
04299    int res;
04300    struct ast_module_user *u = NULL;
04301 
04302    if (acfptr == NULL) {
04303       ast_log(LOG_ERROR, "Function %s not registered\n", copy);
04304    } else if (!acfptr->read && !acfptr->read2) {
04305       ast_log(LOG_ERROR, "Function %s cannot be read\n", copy);
04306    } else if (!is_read_allowed(acfptr)) {
04307       ast_log(LOG_ERROR, "Dangerous function %s read blocked\n", copy);
04308    } else if (acfptr->read) {
04309       if (acfptr->mod) {
04310          u = __ast_module_user_add(acfptr->mod, chan);
04311       }
04312       res = acfptr->read(chan, copy, args, workspace, len);
04313       if (acfptr->mod && u) {
04314          __ast_module_user_remove(acfptr->mod, u);
04315       }
04316       return res;
04317    } else {
04318       struct ast_str *str = ast_str_create(16);
04319       if (acfptr->mod) {
04320          u = __ast_module_user_add(acfptr->mod, chan);
04321       }
04322       res = acfptr->read2(chan, copy, args, &str, 0);
04323       if (acfptr->mod && u) {
04324          __ast_module_user_remove(acfptr->mod, u);
04325       }
04326       ast_copy_string(workspace, ast_str_buffer(str), len > ast_str_size(str) ? ast_str_size(str) : len);
04327       ast_free(str);
04328       return res;
04329    }
04330    return -1;
04331 }
04332 
04333 int ast_func_read2(struct ast_channel *chan, const char *function, struct ast_str **str, ssize_t maxlen)
04334 {
04335    char *copy = ast_strdupa(function);
04336    char *args = func_args(copy);
04337    struct ast_custom_function *acfptr = ast_custom_function_find(copy);
04338    int res;
04339    struct ast_module_user *u = NULL;
04340 
04341    if (acfptr == NULL) {
04342       ast_log(LOG_ERROR, "Function %s not registered\n", copy);
04343    } else if (!acfptr->read && !acfptr->read2) {
04344       ast_log(LOG_ERROR, "Function %s cannot be read\n", copy);
04345    } else if (!is_read_allowed(acfptr)) {
04346       ast_log(LOG_ERROR, "Dangerous function %s read blocked\n", copy);
04347    } else {
04348       if (acfptr->mod) {
04349          u = __ast_module_user_add(acfptr->mod, chan);
04350       }
04351       ast_str_reset(*str);
04352       if (acfptr->read2) {
04353          /* ast_str enabled */
04354          res = acfptr->read2(chan, copy, args, str, maxlen);
04355       } else {
04356          /* Legacy function pointer, allocate buffer for result */
04357          int maxsize = ast_str_size(*str);
04358          if (maxlen > -1) {
04359             if (maxlen == 0) {
04360                if (acfptr->read_max) {
04361                   maxsize = acfptr->read_max;
04362                } else {
04363                   maxsize = VAR_BUF_SIZE;
04364                }
04365             } else {
04366                maxsize = maxlen;
04367             }
04368             ast_str_make_space(str, maxsize);
04369          }
04370          res = acfptr->read(chan, copy, args, ast_str_buffer(*str), maxsize);
04371       }
04372       if (acfptr->mod && u) {
04373          __ast_module_user_remove(acfptr->mod, u);
04374       }
04375       return res;
04376    }
04377    return -1;
04378 }
04379 
04380 int ast_func_write(struct ast_channel *chan, const char *function, const char *value)
04381 {
04382    char *copy = ast_strdupa(function);
04383    char *args = func_args(copy);
04384    struct ast_custom_function *acfptr = ast_custom_function_find(copy);
04385 
04386    if (acfptr == NULL) {
04387       ast_log(LOG_ERROR, "Function %s not registered\n", copy);
04388    } else if (!acfptr->write) {
04389       ast_log(LOG_ERROR, "Function %s cannot be written to\n", copy);
04390    } else if (!is_write_allowed(acfptr)) {
04391       ast_log(LOG_ERROR, "Dangerous function %s write blocked\n", copy);
04392    } else {
04393       int res;
04394       struct ast_module_user *u = NULL;
04395       if (acfptr->mod)
04396          u = __ast_module_user_add(acfptr->mod, chan);
04397       res = acfptr->write(chan, copy, args, value);
04398       if (acfptr->mod && u)
04399          __ast_module_user_remove(acfptr->mod, u);
04400       return res;
04401    }
04402 
04403    return -1;
04404 }
04405 
04406 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)
04407 {
04408    /* Substitutes variables into buf, based on string templ */
04409    char *cp4 = NULL;
04410    const char *whereweare;
04411    int orig_size = 0;
04412    int offset, offset2, isfunction;
04413    const char *nextvar, *nextexp, *nextthing;
04414    const char *vars, *vare;
04415    char *finalvars;
04416    int pos, brackets, needsub, len;
04417    struct ast_str *substr1 = ast_str_create(16), *substr2 = NULL, *substr3 = ast_str_create(16);
04418 
04419    ast_str_reset(*buf);
04420    whereweare = templ;
04421    while (!ast_strlen_zero(whereweare)) {
04422       /* reset our buffer */
04423       ast_str_reset(substr3);
04424 
04425       /* Assume we're copying the whole remaining string */
04426       pos = strlen(whereweare);
04427       nextvar = NULL;
04428       nextexp = NULL;
04429       nextthing = strchr(whereweare, '$');
04430       if (nextthing) {
04431          switch (nextthing[1]) {
04432          case '{':
04433             nextvar = nextthing;
04434             pos = nextvar - whereweare;
04435             break;
04436          case '[':
04437             nextexp = nextthing;
04438             pos = nextexp - whereweare;
04439             break;
04440          default:
04441             pos = 1;
04442          }
04443       }
04444 
04445       if (pos) {
04446          /* Copy that many bytes */
04447          ast_str_append_substr(buf, maxlen, whereweare, pos);
04448 
04449          templ += pos;
04450          whereweare += pos;
04451       }
04452 
04453       if (nextvar) {
04454          /* We have a variable.  Find the start and end, and determine
04455             if we are going to have to recursively call ourselves on the
04456             contents */
04457          vars = vare = nextvar + 2;
04458          brackets = 1;
04459          needsub = 0;
04460 
04461          /* Find the end of it */
04462          while (brackets && *vare) {
04463             if ((vare[0] == '$') && (vare[1] == '{')) {
04464                needsub++;
04465             } else if (vare[0] == '{') {
04466                brackets++;
04467             } else if (vare[0] == '}') {
04468                brackets--;
04469             } else if ((vare[0] == '$') && (vare[1] == '['))
04470                needsub++;
04471             vare++;
04472          }
04473          if (brackets)
04474             ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n");
04475          len = vare - vars - 1;
04476 
04477          /* Skip totally over variable string */
04478          whereweare += (len + 3);
04479 
04480          /* Store variable name (and truncate) */
04481          ast_str_set_substr(&substr1, 0, vars, len);
04482          ast_debug(5, "Evaluating '%s' (from '%s' len %d)\n", ast_str_buffer(substr1), vars, len);
04483 
04484          /* Substitute if necessary */
04485          if (needsub) {
04486             size_t used;
04487             if (!substr2) {
04488                substr2 = ast_str_create(16);
04489             }
04490 
04491             ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), &used);
04492             finalvars = ast_str_buffer(substr2);
04493          } else {
04494             finalvars = ast_str_buffer(substr1);
04495          }
04496 
04497          parse_variable_name(finalvars, &offset, &offset2, &isfunction);
04498          if (isfunction) {
04499             /* Evaluate function */
04500             if (c || !headp) {
04501                cp4 = ast_func_read2(c, finalvars, &substr3, 0) ? NULL : ast_str_buffer(substr3);
04502             } else {
04503                struct varshead old;
04504                struct ast_channel *bogus = ast_dummy_channel_alloc();
04505                if (bogus) {
04506                   memcpy(&old, ast_channel_varshead(bogus), sizeof(old));
04507                   memcpy(ast_channel_varshead(bogus), headp, sizeof(*ast_channel_varshead(bogus)));
04508                   cp4 = ast_func_read2(c, finalvars, &substr3, 0) ? NULL : ast_str_buffer(substr3);
04509                   /* Don't deallocate the varshead that was passed in */
04510                   memcpy(ast_channel_varshead(bogus), &old, sizeof(*ast_channel_varshead(bogus)));
04511                   ast_channel_unref(bogus);
04512                } else {
04513                   ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution.  Function results may be blank.\n");
04514                }
04515             }
04516             ast_debug(2, "Function %s result is '%s'\n", finalvars, cp4 ? cp4 : "(null)");
04517          } else {
04518             /* Retrieve variable value */
04519             ast_str_retrieve_variable(&substr3, 0, c, headp, finalvars);
04520             cp4 = ast_str_buffer(substr3);
04521          }
04522          if (cp4) {
04523             ast_str_substring(substr3, offset, offset2);
04524             ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3));
04525          }
04526       } else if (nextexp) {
04527          /* We have an expression.  Find the start and end, and determine
04528             if we are going to have to recursively call ourselves on the
04529             contents */
04530          vars = vare = nextexp + 2;
04531          brackets = 1;
04532          needsub = 0;
04533 
04534          /* Find the end of it */
04535          while (brackets && *vare) {
04536             if ((vare[0] == '$') && (vare[1] == '[')) {
04537                needsub++;
04538                brackets++;
04539                vare++;
04540             } else if (vare[0] == '[') {
04541                brackets++;
04542             } else if (vare[0] == ']') {
04543                brackets--;
04544             } else if ((vare[0] == '$') && (vare[1] == '{')) {
04545                needsub++;
04546                vare++;
04547             }
04548             vare++;
04549          }
04550          if (brackets)
04551             ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n");
04552          len = vare - vars - 1;
04553 
04554          /* Skip totally over expression */
04555          whereweare += (len + 3);
04556 
04557          /* Store variable name (and truncate) */
04558          ast_str_set_substr(&substr1, 0, vars, len);
04559 
04560          /* Substitute if necessary */
04561          if (needsub) {
04562             size_t used;
04563             if (!substr2) {
04564                substr2 = ast_str_create(16);
04565             }
04566 
04567             ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), &used);
04568             finalvars = ast_str_buffer(substr2);
04569          } else {
04570             finalvars = ast_str_buffer(substr1);
04571          }
04572 
04573          if (ast_str_expr(&substr3, 0, c, finalvars)) {
04574             ast_debug(2, "Expression result is '%s'\n", ast_str_buffer(substr3));
04575          }
04576          ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3));
04577       }
04578    }
04579    *used = ast_str_strlen(*buf) - orig_size;
04580    ast_free(substr1);
04581    ast_free(substr2);
04582    ast_free(substr3);
04583 }
04584 
04585 void ast_str_substitute_variables(struct ast_str **buf, ssize_t maxlen, struct ast_channel *chan, const char *templ)
04586 {
04587    size_t used;
04588    ast_str_substitute_variables_full(buf, maxlen, chan, NULL, templ, &used);
04589 }
04590 
04591 void ast_str_substitute_variables_varshead(struct ast_str **buf, ssize_t maxlen, struct varshead *headp, const char *templ)
04592 {
04593    size_t used;
04594    ast_str_substitute_variables_full(buf, maxlen, NULL, headp, templ, &used);
04595 }
04596 
04597 void pbx_substitute_variables_helper_full(struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int count, size_t *used)
04598 {
04599    /* Substitutes variables into cp2, based on string cp1, cp2 NO LONGER NEEDS TO BE ZEROED OUT!!!!  */
04600    char *cp4 = NULL;
04601    const char *whereweare, *orig_cp2 = cp2;
04602    int length, offset, offset2, isfunction;
04603    char *workspace = NULL;
04604    char *ltmp = NULL, *var = NULL;
04605    char *nextvar, *nextexp, *nextthing;
04606    char *vars, *vare;
04607    int pos, brackets, needsub, len;
04608 
04609    *cp2 = 0; /* just in case nothing ends up there */
04610    whereweare = cp1;
04611    while (!ast_strlen_zero(whereweare) && count) {
04612       /* Assume we're copying the whole remaining string */
04613       pos = strlen(whereweare);
04614       nextvar = NULL;
04615       nextexp = NULL;
04616       nextthing = strchr(whereweare, '$');
04617       if (nextthing) {
04618          switch (nextthing[1]) {
04619          case '{':
04620             nextvar = nextthing;
04621             pos = nextvar - whereweare;
04622             break;
04623          case '[':
04624             nextexp = nextthing;
04625             pos = nextexp - whereweare;
04626             break;
04627          default:
04628             pos = 1;
04629          }
04630       }
04631 
04632       if (pos) {
04633          /* Can't copy more than 'count' bytes */
04634          if (pos > count)
04635             pos = count;
04636 
04637          /* Copy that many bytes */
04638          memcpy(cp2, whereweare, pos);
04639 
04640          count -= pos;
04641          cp2 += pos;
04642          whereweare += pos;
04643          *cp2 = 0;
04644       }
04645 
04646       if (nextvar) {
04647          /* We have a variable.  Find the start and end, and determine
04648             if we are going to have to recursively call ourselves on the
04649             contents */
04650          vars = vare = nextvar + 2;
04651          brackets = 1;
04652          needsub = 0;
04653 
04654          /* Find the end of it */
04655          while (brackets && *vare) {
04656             if ((vare[0] == '$') && (vare[1] == '{')) {
04657                needsub++;
04658             } else if (vare[0] == '{') {
04659                brackets++;
04660             } else if (vare[0] == '}') {
04661                brackets--;
04662             } else if ((vare[0] == '$') && (vare[1] == '['))
04663                needsub++;
04664             vare++;
04665          }
04666          if (brackets)
04667             ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n");
04668          len = vare - vars - 1;
04669 
04670          /* Skip totally over variable string */
04671          whereweare += (len + 3);
04672 
04673          if (!var)
04674             var = ast_alloca(VAR_BUF_SIZE);
04675 
04676          /* Store variable name (and truncate) */
04677          ast_copy_string(var, vars, len + 1);
04678 
04679          /* Substitute if necessary */
04680          if (needsub) {
04681             size_t used;
04682             if (!ltmp)
04683                ltmp = ast_alloca(VAR_BUF_SIZE);
04684 
04685             pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &used);
04686             vars = ltmp;
04687          } else {
04688             vars = var;
04689          }
04690 
04691          if (!workspace)
04692             workspace = ast_alloca(VAR_BUF_SIZE);
04693 
04694          workspace[0] = '\0';
04695 
04696          parse_variable_name(vars, &offset, &offset2, &isfunction);
04697          if (isfunction) {
04698             /* Evaluate function */
04699             if (c || !headp)
04700                cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace;
04701             else {
04702                struct varshead old;
04703                struct ast_channel *c = ast_dummy_channel_alloc();
04704                if (c) {
04705                   memcpy(&old, ast_channel_varshead(c), sizeof(old));
04706                   memcpy(ast_channel_varshead(c), headp, sizeof(*ast_channel_varshead(c)));
04707                   cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace;
04708                   /* Don't deallocate the varshead that was passed in */
04709                   memcpy(ast_channel_varshead(c), &old, sizeof(*ast_channel_varshead(c)));
04710                   c = ast_channel_unref(c);
04711                } else {
04712                   ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution.  Function results may be blank.\n");
04713                }
04714             }
04715             ast_debug(2, "Function %s result is '%s'\n", vars, cp4 ? cp4 : "(null)");
04716          } else {
04717             /* Retrieve variable value */
04718             pbx_retrieve_variable(c, vars, &cp4, workspace, VAR_BUF_SIZE, headp);
04719          }
04720          if (cp4) {
04721             cp4 = substring(cp4, offset, offset2, workspace, VAR_BUF_SIZE);
04722 
04723             length = strlen(cp4);
04724             if (length > count)
04725                length = count;
04726             memcpy(cp2, cp4, length);
04727             count -= length;
04728             cp2 += length;
04729             *cp2 = 0;
04730          }
04731       } else if (nextexp) {
04732          /* We have an expression.  Find the start and end, and determine
04733             if we are going to have to recursively call ourselves on the
04734             contents */
04735          vars = vare = nextexp + 2;
04736          brackets = 1;
04737          needsub = 0;
04738 
04739          /* Find the end of it */
04740          while (brackets && *vare) {
04741             if ((vare[0] == '$') && (vare[1] == '[')) {
04742                needsub++;
04743                brackets++;
04744                vare++;
04745             } else if (vare[0] == '[') {
04746                brackets++;
04747             } else if (vare[0] == ']') {
04748                brackets--;
04749             } else if ((vare[0] == '$') && (vare[1] == '{')) {
04750                needsub++;
04751                vare++;
04752             }
04753             vare++;
04754          }
04755          if (brackets)
04756             ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n");
04757          len = vare - vars - 1;
04758 
04759          /* Skip totally over expression */
04760          whereweare += (len + 3);
04761 
04762          if (!var)
04763             var = ast_alloca(VAR_BUF_SIZE);
04764 
04765          /* Store variable name (and truncate) */
04766          ast_copy_string(var, vars, len + 1);
04767 
04768          /* Substitute if necessary */
04769          if (needsub) {
04770             size_t used;
04771             if (!ltmp)
04772                ltmp = ast_alloca(VAR_BUF_SIZE);
04773 
04774             pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &used);
04775             vars = ltmp;
04776          } else {
04777             vars = var;
04778          }
04779 
04780          length = ast_expr(vars, cp2, count, c);
04781 
04782          if (length) {
04783             ast_debug(1, "Expression result is '%s'\n", cp2);
04784             count -= length;
04785             cp2 += length;
04786             *cp2 = 0;
04787          }
04788       }
04789    }
04790    *used = cp2 - orig_cp2;
04791 }
04792 
04793 void pbx_substitute_variables_helper(struct ast_channel *c, const char *cp1, char *cp2, int count)
04794 {
04795    size_t used;
04796    pbx_substitute_variables_helper_full(c, (c) ? ast_channel_varshead(c) : NULL, cp1, cp2, count, &used);
04797 }
04798 
04799 void pbx_substitute_variables_varshead(struct varshead *headp, const char *cp1, char *cp2, int count)
04800 {
04801    size_t used;
04802    pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count, &used);
04803 }
04804 
04805 /*!
04806  * \brief The return value depends on the action:
04807  *
04808  * E_MATCH, E_CANMATCH, E_MATCHMORE require a real match,
04809  * and return 0 on failure, -1 on match;
04810  * E_FINDLABEL maps the label to a priority, and returns
04811  * the priority on success, ... XXX
04812  * E_SPAWN, spawn an application,
04813  *
04814  * \retval 0 on success.
04815  * \retval  -1 on failure.
04816  *
04817  * \note The channel is auto-serviced in this function, because doing an extension
04818  * match may block for a long time.  For example, if the lookup has to use a network
04819  * dialplan switch, such as DUNDi or IAX2, it may take a while.  However, the channel
04820  * auto-service code will queue up any important signalling frames to be processed
04821  * after this is done.
04822  */
04823 static int pbx_extension_helper(struct ast_channel *c, struct ast_context *con,
04824   const char *context, const char *exten, int priority,
04825   const char *label, const char *callerid, enum ext_match_t action, int *found, int combined_find_spawn)
04826 {
04827    struct ast_exten *e;
04828    struct ast_app *app;
04829    char *substitute = NULL;
04830    int res;
04831    struct pbx_find_info q = { .stacklen = 0 }; /* the rest is reset in pbx_find_extension */
04832    char passdata[EXT_DATA_SIZE];
04833 
04834    int matching_action = (action == E_MATCH || action == E_CANMATCH || action == E_MATCHMORE);
04835 
04836    ast_rdlock_contexts();
04837    if (found)
04838       *found = 0;
04839 
04840    e = pbx_find_extension(c, con, &q, context, exten, priority, label, callerid, action);
04841    if (e) {
04842       if (found)
04843          *found = 1;
04844       if (matching_action) {
04845          ast_unlock_contexts();
04846          return -1;  /* success, we found it */
04847       } else if (action == E_FINDLABEL) { /* map the label to a priority */
04848          res = e->priority;
04849          ast_unlock_contexts();
04850          return res; /* the priority we were looking for */
04851       } else { /* spawn */
04852          if (!e->cached_app)
04853             e->cached_app = pbx_findapp(e->app);
04854          app = e->cached_app;
04855          if (ast_strlen_zero(e->data)) {
04856             *passdata = '\0';
04857          } else {
04858             const char *tmp;
04859             if ((!(tmp = strchr(e->data, '$'))) || (!strstr(tmp, "${") && !strstr(tmp, "$["))) {
04860                /* no variables to substitute, copy on through */
04861                ast_copy_string(passdata, e->data, sizeof(passdata));
04862             } else {
04863                /* save e->data on stack for later processing after lock released */
04864                substitute = ast_strdupa(e->data);
04865             }
04866          }
04867          ast_unlock_contexts();
04868          if (!app) {
04869             ast_log(LOG_WARNING, "No application '%s' for extension (%s, %s, %d)\n", e->app, context, exten, priority);
04870             return -1;
04871          }
04872          if (ast_channel_context(c) != context)
04873             ast_channel_context_set(c, context);
04874          if (ast_channel_exten(c) != exten)
04875             ast_channel_exten_set(c, exten);
04876          ast_channel_priority_set(c, priority);
04877          if (substitute) {
04878             pbx_substitute_variables_helper(c, substitute, passdata, sizeof(passdata)-1);
04879          }
04880 #ifdef CHANNEL_TRACE
04881          ast_channel_trace_update(c);
04882 #endif
04883          ast_debug(1, "Launching '%s'\n", app->name);
04884          if (VERBOSITY_ATLEAST(3)) {
04885             char tmp[80], tmp2[80], tmp3[EXT_DATA_SIZE];
04886             ast_verb(3, "Executing [%s@%s:%d] %s(\"%s\", \"%s\") %s\n",
04887                exten, context, priority,
04888                term_color(tmp, app->name, COLOR_BRCYAN, 0, sizeof(tmp)),
04889                term_color(tmp2, ast_channel_name(c), COLOR_BRMAGENTA, 0, sizeof(tmp2)),
04890                term_color(tmp3, passdata, COLOR_BRMAGENTA, 0, sizeof(tmp3)),
04891                "in new stack");
04892          }
04893          /*** DOCUMENTATION
04894             <managerEventInstance>
04895                <synopsis>Raised when a channel enters a new context, extension, priority.</synopsis>
04896                <syntax>
04897                   <parameter name="Application">
04898                      <para>The application about to be executed.</para>
04899                   </parameter>
04900                   <parameter name="AppData">
04901                      <para>The data to be passed to the application.</para>
04902                   </parameter>
04903                </syntax>
04904             </managerEventInstance>
04905          ***/
04906          manager_event(EVENT_FLAG_DIALPLAN, "Newexten",
04907                "Channel: %s\r\n"
04908                "Context: %s\r\n"
04909                "Extension: %s\r\n"
04910                "Priority: %d\r\n"
04911                "Application: %s\r\n"
04912                "AppData: %s\r\n"
04913                "Uniqueid: %s\r\n",
04914                ast_channel_name(c), ast_channel_context(c), ast_channel_exten(c), ast_channel_priority(c), app->name, passdata, ast_channel_uniqueid(c));
04915          return pbx_exec(c, app, passdata);  /* 0 on success, -1 on failure */
04916       }
04917    } else if (q.swo) {  /* not found here, but in another switch */
04918       if (found)
04919          *found = 1;
04920       ast_unlock_contexts();
04921       if (matching_action) {
04922          return -1;
04923       } else {
04924          if (!q.swo->exec) {
04925             ast_log(LOG_WARNING, "No execution engine for switch %s\n", q.swo->name);
04926             res = -1;
04927          }
04928          return q.swo->exec(c, q.foundcontext ? q.foundcontext : context, exten, priority, callerid, q.data);
04929       }
04930    } else { /* not found anywhere, see what happened */
04931       ast_unlock_contexts();
04932       /* Using S_OR here because Solaris doesn't like NULL being passed to ast_log */
04933       switch (q.status) {
04934       case STATUS_NO_CONTEXT:
04935          if (!matching_action && !combined_find_spawn)
04936             ast_log(LOG_NOTICE, "Cannot find extension context '%s'\n", S_OR(context, ""));
04937          break;
04938       case STATUS_NO_EXTENSION:
04939          if (!matching_action && !combined_find_spawn)
04940             ast_log(LOG_NOTICE, "Cannot find extension '%s' in context '%s'\n", exten, S_OR(context, ""));
04941          break;
04942       case STATUS_NO_PRIORITY:
04943          if (!matching_action && !combined_find_spawn)
04944             ast_log(LOG_NOTICE, "No such priority %d in extension '%s' in context '%s'\n", priority, exten, S_OR(context, ""));
04945          break;
04946       case STATUS_NO_LABEL:
04947          if (context && !combined_find_spawn)
04948             ast_log(LOG_NOTICE, "No such label '%s' in extension '%s' in context '%s'\n", label, exten, S_OR(context, ""));
04949          break;
04950       default:
04951          ast_debug(1, "Shouldn't happen!\n");
04952       }
04953 
04954       return (matching_action) ? 0 : -1;
04955    }
04956 }
04957 
04958 /*! \brief Find hint for given extension in context */
04959 static struct ast_exten *ast_hint_extension_nolock(struct ast_channel *c, const char *context, const char *exten)
04960 {
04961    struct pbx_find_info q = { .stacklen = 0 }; /* the rest is set in pbx_find_context */
04962    return pbx_find_extension(c, NULL, &q, context, exten, PRIORITY_HINT, NULL, "", E_MATCH);
04963 }
04964 
04965 static struct ast_exten *ast_hint_extension(struct ast_channel *c, const char *context, const char *exten)
04966 {
04967    struct ast_exten *e;
04968    ast_rdlock_contexts();
04969    e = ast_hint_extension_nolock(c, context, exten);
04970    ast_unlock_contexts();
04971    return e;
04972 }
04973 
04974 enum ast_extension_states ast_devstate_to_extenstate(enum ast_device_state devstate)
04975 {
04976    switch (devstate) {
04977    case AST_DEVICE_ONHOLD:
04978       return AST_EXTENSION_ONHOLD;
04979    case AST_DEVICE_BUSY:
04980       return AST_EXTENSION_BUSY;
04981    case AST_DEVICE_UNKNOWN:
04982       return AST_EXTENSION_NOT_INUSE;
04983    case AST_DEVICE_UNAVAILABLE:
04984    case AST_DEVICE_INVALID:
04985       return AST_EXTENSION_UNAVAILABLE;
04986    case AST_DEVICE_RINGINUSE:
04987       return (AST_EXTENSION_INUSE | AST_EXTENSION_RINGING);
04988    case AST_DEVICE_RINGING:
04989       return AST_EXTENSION_RINGING;
04990    case AST_DEVICE_INUSE:
04991       return AST_EXTENSION_INUSE;
04992    case AST_DEVICE_NOT_INUSE:
04993       return AST_EXTENSION_NOT_INUSE;
04994    case AST_DEVICE_TOTAL: /* not a device state, included for completeness */
04995       break;
04996    }
04997 
04998    return AST_EXTENSION_NOT_INUSE;
04999 }
05000 
05001 /*!
05002  * \internal
05003  * \brief Parse out the presence portion of the hint string
05004  */
05005 static char *parse_hint_presence(struct ast_str *hint_args)
05006 {
05007    char *copy = ast_strdupa(ast_str_buffer(hint_args));
05008    char *tmp = "";
05009 
05010    if ((tmp = strrchr(copy, ','))) {
05011       *tmp = '\0';
05012       tmp++;
05013    } else {
05014       return NULL;
05015    }
05016    ast_str_set(&hint_args, 0, "%s", tmp);
05017    return ast_str_buffer(hint_args);
05018 }
05019 
05020 /*!
05021  * \internal
05022  * \brief Parse out the device portion of the hint string
05023  */
05024 static char *parse_hint_device(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    }
05032 
05033    ast_str_set(&hint_args, 0, "%s", copy);
05034    return ast_str_buffer(hint_args);
05035 }
05036 
05037 static void device_state_info_dt(void *obj)
05038 {
05039    struct ast_device_state_info *info = obj;
05040 
05041    ao2_cleanup(info->causing_channel);
05042 }
05043 
05044 static struct ao2_container *alloc_device_state_info(void)
05045 {
05046    return ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_NOLOCK, 1, NULL, NULL);
05047 }
05048 
05049 static int ast_extension_state3(struct ast_str *hint_app, struct ao2_container *device_state_info)
05050 {
05051    char *cur;
05052    char *rest;
05053    struct ast_devstate_aggregate agg;
05054 
05055    /* One or more devices separated with a & character */
05056    rest = parse_hint_device(hint_app);
05057 
05058    ast_devstate_aggregate_init(&agg);
05059    while ((cur = strsep(&rest, "&"))) {
05060       enum ast_device_state state = ast_device_state(cur);
05061 
05062       ast_devstate_aggregate_add(&agg, state);
05063       if (device_state_info) {
05064          struct ast_device_state_info *obj;
05065 
05066          obj = ao2_alloc_options(sizeof(*obj) + strlen(cur), device_state_info_dt, AO2_ALLOC_OPT_LOCK_NOLOCK);
05067          /* if failed we cannot add this device */
05068          if (obj) {
05069             obj->device_state = state;
05070             strcpy(obj->device_name, cur);
05071             ao2_link(device_state_info, obj);
05072             ao2_ref(obj, -1);
05073          }
05074       }
05075    }
05076 
05077    return ast_devstate_to_extenstate(ast_devstate_aggregate_result(&agg));
05078 }
05079 
05080 /*! \brief Check state of extension by using hints */
05081 static int ast_extension_state2(struct ast_exten *e, struct ao2_container *device_state_info)
05082 {
05083    struct ast_str *hint_app = ast_str_thread_get(&extensionstate_buf, 32);
05084 
05085    if (!e || !hint_app) {
05086       return -1;
05087    }
05088 
05089    ast_str_set(&hint_app, 0, "%s", ast_get_extension_app(e));
05090    return ast_extension_state3(hint_app, device_state_info);
05091 }
05092 
05093 /*! \brief Return extension_state as string */
05094 const char *ast_extension_state2str(int extension_state)
05095 {
05096    int i;
05097 
05098    for (i = 0; (i < ARRAY_LEN(extension_states)); i++) {
05099       if (extension_states[i].extension_state == extension_state)
05100          return extension_states[i].text;
05101    }
05102    return "Unknown";
05103 }
05104 
05105 /*! \internal \brief Check extension state for an extension by using hint */
05106 static int internal_extension_state_extended(struct ast_channel *c, const char *context, const char *exten,
05107    struct ao2_container *device_state_info)
05108 {
05109    struct ast_exten *e;
05110 
05111    if (!(e = ast_hint_extension(c, context, exten))) {  /* Do we have a hint for this extension ? */
05112       return -1;                   /* No hint, return -1 */
05113    }
05114 
05115    if (e->exten[0] == '_') {
05116       /* Create this hint on-the-fly */
05117       ast_add_extension(e->parent->name, 0, exten, e->priority, e->label,
05118          e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr,
05119          e->registrar);
05120       if (!(e = ast_hint_extension(c, context, exten))) {
05121          /* Improbable, but not impossible */
05122          return -1;
05123       }
05124    }
05125 
05126    return ast_extension_state2(e, device_state_info);  /* Check all devices in the hint */
05127 }
05128 
05129 /*! \brief Check extension state for an extension by using hint */
05130 int ast_extension_state(struct ast_channel *c, const char *context, const char *exten)
05131 {
05132    return internal_extension_state_extended(c, context, exten, NULL);
05133 }
05134 
05135 /*! \brief Check extended extension state for an extension by using hint */
05136 int ast_extension_state_extended(struct ast_channel *c, const char *context, const char *exten,
05137    struct ao2_container **device_state_info)
05138 {
05139    struct ao2_container *container = NULL;
05140    int ret;
05141 
05142    if (device_state_info) {
05143       container = alloc_device_state_info();
05144    }
05145 
05146    ret = internal_extension_state_extended(c, context, exten, container);
05147    if (ret < 0 && container) {
05148       ao2_ref(container, -1);
05149       container = NULL;
05150    }
05151 
05152    if (device_state_info) {
05153       get_device_state_causing_channels(container);
05154       *device_state_info = container;
05155    }
05156 
05157    return ret;
05158 }
05159 
05160 static int extension_presence_state_helper(struct ast_exten *e, char **subtype, char **message)
05161 {
05162    struct ast_str *hint_app = ast_str_thread_get(&extensionstate_buf, 32);
05163    char *presence_provider;
05164    const char *app;
05165 
05166    if (!e || !hint_app) {
05167       return -1;
05168    }
05169 
05170    app = ast_get_extension_app(e);
05171    if (ast_strlen_zero(app)) {
05172       return -1;
05173    }
05174 
05175    ast_str_set(&hint_app, 0, "%s", app);
05176    presence_provider = parse_hint_presence(hint_app);
05177 
05178    if (ast_strlen_zero(presence_provider)) {
05179       /* No presence string in the hint */
05180       return 0;
05181    }
05182 
05183    return ast_presence_state(presence_provider, subtype, message);
05184 }
05185 
05186 int ast_hint_presence_state(struct ast_channel *c, const char *context, const char *exten, char **subtype, char **message)
05187 {
05188    struct ast_exten *e;
05189 
05190    if (!(e = ast_hint_extension(c, context, exten))) {  /* Do we have a hint for this extension ? */
05191       return -1;                   /* No hint, return -1 */
05192    }
05193 
05194    if (e->exten[0] == '_') {
05195       /* Create this hint on-the-fly */
05196       ast_add_extension(e->parent->name, 0, exten, e->priority, e->label,
05197          e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr,
05198          e->registrar);
05199       if (!(e = ast_hint_extension(c, context, exten))) {
05200          /* Improbable, but not impossible */
05201          return -1;
05202       }
05203    }
05204 
05205    return extension_presence_state_helper(e, subtype, message);
05206 }
05207 
05208 static int execute_state_callback(ast_state_cb_type cb,
05209    const char *context,
05210    const char *exten,
05211    void *data,
05212    enum ast_state_cb_update_reason reason,
05213    struct ast_hint *hint,
05214    struct ao2_container *device_state_info)
05215 {
05216    int res = 0;
05217    struct ast_state_cb_info info = { 0, };
05218 
05219    info.reason = reason;
05220 
05221    /* Copy over current hint data */
05222    if (hint) {
05223       ao2_lock(hint);
05224       info.exten_state = hint->laststate;
05225       info.device_state_info = device_state_info;
05226       info.presence_state = hint->last_presence_state;
05227       if (!(ast_strlen_zero(hint->last_presence_subtype))) {
05228          info.presence_subtype = ast_strdupa(hint->last_presence_subtype);
05229       } else {
05230          info.presence_subtype = "";
05231       }
05232       if (!(ast_strlen_zero(hint->last_presence_message))) {
05233          info.presence_message = ast_strdupa(hint->last_presence_message);
05234       } else {
05235          info.presence_message = "";
05236       }
05237       ao2_unlock(hint);
05238    } else {
05239       info.exten_state = AST_EXTENSION_REMOVED;
05240    }
05241 
05242    /* NOTE: The casts will not be needed for v10 and later */
05243    res = cb((char *) context, (char *) exten, &info, data);
05244 
05245    return res;
05246 }
05247 
05248 static int handle_presencechange(void *datap)
05249 {
05250    struct ast_hint *hint;
05251    struct ast_str *hint_app = NULL;
05252    struct presencechange *pc = datap;
05253    struct ao2_iterator i;
05254    struct ao2_iterator cb_iter;
05255    char context_name[AST_MAX_CONTEXT];
05256    char exten_name[AST_MAX_EXTENSION];
05257    int res = -1;
05258 
05259    hint_app = ast_str_create(1024);
05260    if (!hint_app) {
05261       goto presencechange_cleanup;
05262    }
05263 
05264    ast_mutex_lock(&context_merge_lock);/* Hold off ast_merge_contexts_and_delete */
05265    i = ao2_iterator_init(hints, 0);
05266    for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) {
05267       struct ast_state_cb *state_cb;
05268       const char *app;
05269       char *parse;
05270 
05271       ao2_lock(hint);
05272 
05273       if (!hint->exten) {
05274          /* The extension has already been destroyed */
05275          ao2_unlock(hint);
05276          continue;
05277       }
05278 
05279       /* Does this hint monitor the device that changed state? */
05280       app = ast_get_extension_app(hint->exten);
05281       if (ast_strlen_zero(app)) {
05282          /* The hint does not monitor presence at all. */
05283          ao2_unlock(hint);
05284          continue;
05285       }
05286 
05287       ast_str_set(&hint_app, 0, "%s", app);
05288       parse = parse_hint_presence(hint_app);
05289       if (ast_strlen_zero(parse)) {
05290          ao2_unlock(hint);
05291          continue;
05292       }
05293       if (strcasecmp(parse, pc->provider)) {
05294          /* The hint does not monitor the presence provider. */
05295          ao2_unlock(hint);
05296          continue;
05297       }
05298 
05299       /*
05300        * Save off strings in case the hint extension gets destroyed
05301        * while we are notifying the watchers.
05302        */
05303       ast_copy_string(context_name,
05304          ast_get_context_name(ast_get_extension_context(hint->exten)),
05305          sizeof(context_name));
05306       ast_copy_string(exten_name, ast_get_extension_name(hint->exten),
05307          sizeof(exten_name));
05308       ast_str_set(&hint_app, 0, "%s", ast_get_extension_app(hint->exten));
05309 
05310       /* Check to see if update is necessary */
05311       if ((hint->last_presence_state == pc->state) &&
05312          ((hint->last_presence_subtype && pc->subtype && !strcmp(hint->last_presence_subtype, pc->subtype)) || (!hint->last_presence_subtype && !pc->subtype)) &&
05313          ((hint->last_presence_message && pc->message && !strcmp(hint->last_presence_message, pc->message)) || (!hint->last_presence_message && !pc->message))) {
05314 
05315          /* this update is the same as the last, do nothing */
05316          ao2_unlock(hint);
05317          continue;
05318       }
05319 
05320       /* update new values */
05321       ast_free(hint->last_presence_subtype);
05322       ast_free(hint->last_presence_message);
05323       hint->last_presence_state = pc->state;
05324       hint->last_presence_subtype = pc->subtype ? ast_strdup(pc->subtype) : NULL;
05325       hint->last_presence_message = pc->message ? ast_strdup(pc->message) : NULL;
05326 
05327       ao2_unlock(hint);
05328 
05329       /* For general callbacks */
05330       cb_iter = ao2_iterator_init(statecbs, 0);
05331       for (; (state_cb = ao2_iterator_next(&cb_iter)); ao2_ref(state_cb, -1)) {
05332          execute_state_callback(state_cb->change_cb,
05333             context_name,
05334             exten_name,
05335             state_cb->data,
05336             AST_HINT_UPDATE_PRESENCE,
05337             hint,
05338             NULL);
05339       }
05340       ao2_iterator_destroy(&cb_iter);
05341 
05342       /* For extension callbacks */
05343       cb_iter = ao2_iterator_init(hint->callbacks, 0);
05344       for (; (state_cb = ao2_iterator_next(&cb_iter)); ao2_ref(state_cb, -1)) {
05345          execute_state_callback(state_cb->change_cb,
05346             context_name,
05347             exten_name,
05348             state_cb->data,
05349             AST_HINT_UPDATE_PRESENCE,
05350             hint,
05351             NULL);
05352       }
05353       ao2_iterator_destroy(&cb_iter);
05354    }
05355    ao2_iterator_destroy(&i);
05356    ast_mutex_unlock(&context_merge_lock);
05357 
05358    res = 0;
05359 
05360 presencechange_cleanup:
05361    ast_free(hint_app);
05362    ao2_ref(pc, -1);
05363 
05364    return res;
05365 }
05366 
05367 /*!
05368  * /internal
05369  * /brief Identify a channel for every device which is supposedly responsible for the device state.
05370  *
05371  * Especially when the device is ringing, the oldest ringing channel is chosen.
05372  * For all other cases the first encountered channel in the specific state is chosen.
05373  */
05374 static void get_device_state_causing_channels(struct ao2_container *c)
05375 {
05376    struct ao2_iterator iter;
05377    struct ast_device_state_info *info;
05378    struct ast_channel *chan;
05379 
05380    if (!c || !ao2_container_count(c)) {
05381       return;
05382    }
05383    iter = ao2_iterator_init(c, 0);
05384    for (; (info = ao2_iterator_next(&iter)); ao2_ref(info, -1)) {
05385       enum ast_channel_state search_state = 0; /* prevent false uninit warning */
05386       char match[AST_CHANNEL_NAME];
05387       struct ast_channel_iterator *chan_iter;
05388       struct timeval chantime = {0, }; /* prevent false uninit warning */
05389 
05390       switch (info->device_state) {
05391       case AST_DEVICE_RINGING:
05392       case AST_DEVICE_RINGINUSE:
05393          /* find ringing channel */
05394          search_state = AST_STATE_RINGING;
05395          break;
05396       case AST_DEVICE_BUSY:
05397          /* find busy channel */
05398          search_state = AST_STATE_BUSY;
05399          break;
05400       case AST_DEVICE_ONHOLD:
05401       case AST_DEVICE_INUSE:
05402          /* find up channel */
05403          search_state = AST_STATE_UP;
05404          break;
05405       case AST_DEVICE_UNKNOWN:
05406       case AST_DEVICE_NOT_INUSE:
05407       case AST_DEVICE_INVALID:
05408       case AST_DEVICE_UNAVAILABLE:
05409       case AST_DEVICE_TOTAL /* not a state */:
05410          /* no channels are of interest */
05411          continue;
05412       }
05413 
05414       /* iterate over all channels of the device */
05415            snprintf(match, sizeof(match), "%s-", info->device_name);
05416       chan_iter = ast_channel_iterator_by_name_new(match, strlen(match));
05417       for (; (chan = ast_channel_iterator_next(chan_iter)); ast_channel_unref(chan)) {
05418          ast_channel_lock(chan);
05419          /* this channel's state doesn't match */
05420          if (search_state != ast_channel_state(chan)) {
05421             ast_channel_unlock(chan);
05422             continue;
05423          }
05424          /* any non-ringing channel will fit */
05425          if (search_state != AST_STATE_RINGING) {
05426             ast_channel_unlock(chan);
05427             info->causing_channel = chan; /* is kept ref'd! */
05428             break;
05429          }
05430          /* but we need the oldest ringing channel of the device to match with undirected pickup */
05431          if (!info->causing_channel) {
05432             chantime = ast_channel_creationtime(chan);
05433             ast_channel_ref(chan); /* must ref it! */
05434             info->causing_channel = chan;
05435          } else if (ast_tvcmp(ast_channel_creationtime(chan), chantime) < 0) {
05436             chantime = ast_channel_creationtime(chan);
05437             ast_channel_unref(info->causing_channel);
05438             ast_channel_ref(chan); /* must ref it! */
05439             info->causing_channel = chan;
05440          }
05441          ast_channel_unlock(chan);
05442       }
05443       ast_channel_iterator_destroy(chan_iter);
05444    }
05445    ao2_iterator_destroy(&iter);
05446 }
05447 
05448 static int handle_statechange(void *datap)
05449 {
05450    struct ast_hint *hint;
05451    struct ast_str *hint_app;
05452    struct ast_hintdevice *device;
05453    struct ast_hintdevice *cmpdevice;
05454    struct statechange *sc = datap;
05455    struct ao2_iterator *dev_iter;
05456    struct ao2_iterator cb_iter;
05457    char context_name[AST_MAX_CONTEXT];
05458    char exten_name[AST_MAX_EXTENSION];
05459 
05460    if (ao2_container_count(hintdevices) == 0) {
05461       /* There are no hints monitoring devices. */
05462       ast_free(sc);
05463       return 0;
05464    }
05465 
05466    hint_app = ast_str_create(1024);
05467    if (!hint_app) {
05468       ast_free(sc);
05469       return -1;
05470    }
05471 
05472    cmpdevice = ast_alloca(sizeof(*cmpdevice) + strlen(sc->dev));
05473    strcpy(cmpdevice->hintdevice, sc->dev);
05474 
05475    ast_mutex_lock(&context_merge_lock);/* Hold off ast_merge_contexts_and_delete */
05476    dev_iter = ao2_t_callback(hintdevices,
05477       OBJ_POINTER | OBJ_MULTIPLE,
05478       hintdevice_cmp_multiple,
05479       cmpdevice,
05480       "find devices in container");
05481    if (!dev_iter) {
05482       ast_mutex_unlock(&context_merge_lock);
05483       ast_free(hint_app);
05484       ast_free(sc);
05485       return -1;
05486    }
05487 
05488    for (; (device = ao2_iterator_next(dev_iter)); ao2_t_ref(device, -1, "Next device")) {
05489       struct ast_state_cb *state_cb;
05490       int state;
05491       int same_state;
05492       struct ao2_container *device_state_info;
05493       int first_extended_cb_call = 1;
05494 
05495       if (!device->hint) {
05496          /* Should never happen. */
05497          continue;
05498       }
05499       hint = device->hint;
05500 
05501       ao2_lock(hint);
05502       if (!hint->exten) {
05503          /* The extension has already been destroyed */
05504          ao2_unlock(hint);
05505          continue;
05506       }
05507 
05508       /*
05509        * Save off strings in case the hint extension gets destroyed
05510        * while we are notifying the watchers.
05511        */
05512       ast_copy_string(context_name,
05513          ast_get_context_name(ast_get_extension_context(hint->exten)),
05514          sizeof(context_name));
05515       ast_copy_string(exten_name, ast_get_extension_name(hint->exten),
05516          sizeof(exten_name));
05517       ast_str_set(&hint_app, 0, "%s", ast_get_extension_app(hint->exten));
05518       ao2_unlock(hint);
05519 
05520       /*
05521        * Get device state for this hint.
05522        *
05523        * NOTE: We cannot hold any locks while determining the hint
05524        * device state or notifying the watchers without causing a
05525        * deadlock.  (conlock, hints, and hint)
05526        */
05527       /* Make a container so state3 can fill it if we wish.
05528        * If that failed we simply do not provide the extended state info.
05529        */
05530       device_state_info = alloc_device_state_info();
05531       state = ast_extension_state3(hint_app, device_state_info);
05532       if ((same_state = state == hint->laststate) && (~state & AST_EXTENSION_RINGING)) {
05533          ao2_cleanup(device_state_info);
05534          continue;
05535       }
05536 
05537       /* Device state changed since last check - notify the watchers. */
05538       hint->laststate = state;   /* record we saw the change */
05539 
05540       /* For general callbacks */
05541       cb_iter = ao2_iterator_init(statecbs, 0);
05542       for (; !same_state && (state_cb = ao2_iterator_next(&cb_iter)); ao2_ref(state_cb, -1)) {
05543          execute_state_callback(state_cb->change_cb,
05544             context_name,
05545             exten_name,
05546             state_cb->data,
05547             AST_HINT_UPDATE_DEVICE,
05548             hint,
05549             NULL);
05550       }
05551       ao2_iterator_destroy(&cb_iter);
05552 
05553       /* For extension callbacks */
05554       /* extended callbacks are called when the state changed or when AST_EVENT_RINGING is
05555        * included. Normal callbacks are only called when the state changed.
05556        */
05557       cb_iter = ao2_iterator_init(hint->callbacks, 0);
05558       for (; (state_cb = ao2_iterator_next(&cb_iter)); ao2_ref(state_cb, -1)) {
05559          if (state_cb->extended && first_extended_cb_call) {
05560             /* Fill detailed device_state_info now that we know it is used by extd. callback */
05561             first_extended_cb_call = 0;
05562             get_device_state_causing_channels(device_state_info);
05563          }
05564          if (state_cb->extended || !same_state) {
05565             execute_state_callback(state_cb->change_cb,
05566                context_name,
05567                exten_name,
05568                state_cb->data,
05569                AST_HINT_UPDATE_DEVICE,
05570                hint,
05571                state_cb->extended ? device_state_info : NULL);
05572          }
05573       }
05574       ao2_iterator_destroy(&cb_iter);
05575 
05576       ao2_cleanup(device_state_info);
05577    }
05578    ast_mutex_unlock(&context_merge_lock);
05579 
05580    ao2_iterator_destroy(dev_iter);
05581    ast_free(hint_app);
05582    ast_free(sc);
05583    return 0;
05584 }
05585 
05586 /*!
05587  * \internal
05588  * \brief Destroy the given state callback object.
05589  *
05590  * \param doomed State callback to destroy.
05591  *
05592  * \return Nothing
05593  */
05594 static void destroy_state_cb(void *doomed)
05595 {
05596    struct ast_state_cb *state_cb = doomed;
05597 
05598    if (state_cb->destroy_cb) {
05599       state_cb->destroy_cb(state_cb->id, state_cb->data);
05600    }
05601 }
05602 
05603 /*! \internal \brief Add watcher for extension states with destructor */
05604 static int extension_state_add_destroy(const char *context, const char *exten,
05605    ast_state_cb_type change_cb, ast_state_cb_destroy_type destroy_cb, void *data, int extended)
05606 {
05607    struct ast_hint *hint;
05608    struct ast_state_cb *state_cb;
05609    struct ast_exten *e;
05610    int id;
05611 
05612    /* If there's no context and extension:  add callback to statecbs list */
05613    if (!context && !exten) {
05614       /* Prevent multiple adds from adding the same change_cb at the same time. */
05615       ao2_lock(statecbs);
05616 
05617       /* Remove any existing change_cb. */
05618       ao2_find(statecbs, change_cb, OBJ_UNLINK | OBJ_NODATA);
05619 
05620       /* Now insert the change_cb */
05621       if (!(state_cb = ao2_alloc(sizeof(*state_cb), destroy_state_cb))) {
05622          ao2_unlock(statecbs);
05623          return -1;
05624       }
05625       state_cb->id = 0;
05626       state_cb->change_cb = change_cb;
05627       state_cb->destroy_cb = destroy_cb;
05628       state_cb->data = data;
05629       state_cb->extended = extended;
05630       ao2_link(statecbs, state_cb);
05631 
05632       ao2_ref(state_cb, -1);
05633       ao2_unlock(statecbs);
05634       return 0;
05635    }
05636 
05637    if (!context || !exten)
05638       return -1;
05639 
05640    /* This callback type is for only one hint, so get the hint */
05641    e = ast_hint_extension(NULL, context, exten);
05642    if (!e) {
05643       return -1;
05644    }
05645 
05646    /* If this is a pattern, dynamically create a new extension for this
05647     * particular match.  Note that this will only happen once for each
05648     * individual extension, because the pattern will no longer match first.
05649     */
05650    if (e->exten[0] == '_') {
05651       ast_add_extension(e->parent->name, 0, exten, e->priority, e->label,
05652          e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr,
05653          e->registrar);
05654       e = ast_hint_extension(NULL, context, exten);
05655       if (!e || e->exten[0] == '_') {
05656          return -1;
05657       }
05658    }
05659 
05660    /* Find the hint in the hints container */
05661    ao2_lock(hints);/* Locked to hold off ast_merge_contexts_and_delete */
05662    hint = ao2_find(hints, e, 0);
05663    if (!hint) {
05664       ao2_unlock(hints);
05665       return -1;
05666    }
05667 
05668    /* Now insert the callback in the callback list  */
05669    if (!(state_cb = ao2_alloc(sizeof(*state_cb), destroy_state_cb))) {
05670       ao2_ref(hint, -1);
05671       ao2_unlock(hints);
05672       return -1;
05673    }
05674    do {
05675       id = stateid++;      /* Unique ID for this callback */
05676       /* Do not allow id to ever be -1 or 0. */
05677    } while (id == -1 || id == 0);
05678    state_cb->id = id;
05679    state_cb->change_cb = change_cb; /* Pointer to callback routine */
05680    state_cb->destroy_cb = destroy_cb;
05681    state_cb->data = data;     /* Data for the callback */
05682    state_cb->extended = extended;
05683    ao2_link(hint->callbacks, state_cb);
05684 
05685    ao2_ref(state_cb, -1);
05686    ao2_ref(hint, -1);
05687    ao2_unlock(hints);
05688 
05689    return id;
05690 }
05691 
05692 /*! \brief Add watcher for extension states with destructor */
05693 int ast_extension_state_add_destroy(const char *context, const char *exten,
05694    ast_state_cb_type change_cb, ast_state_cb_destroy_type destroy_cb, void *data)
05695 {
05696    return extension_state_add_destroy(context, exten, change_cb, destroy_cb, data, 0);
05697 }
05698 
05699 /*! \brief Add watcher for extension states */
05700 int ast_extension_state_add(const char *context, const char *exten,
05701    ast_state_cb_type change_cb, void *data)
05702 {
05703    return extension_state_add_destroy(context, exten, change_cb, NULL, data, 0);
05704 }
05705 
05706 /*! \brief Add watcher for extended extension states with destructor */
05707 int ast_extension_state_add_destroy_extended(const char *context, const char *exten,
05708    ast_state_cb_type change_cb, ast_state_cb_destroy_type destroy_cb, void *data)
05709 {
05710    return extension_state_add_destroy(context, exten, change_cb, destroy_cb, data, 1);
05711 }
05712 
05713 /*! \brief Add watcher for extended extension states */
05714 int ast_extension_state_add_extended(const char *context, const char *exten,
05715    ast_state_cb_type change_cb, void *data)
05716 {
05717    return extension_state_add_destroy(context, exten, change_cb, NULL, data, 1);
05718 }
05719 
05720 /*! \brief Find Hint by callback id */
05721 static int find_hint_by_cb_id(void *obj, void *arg, int flags)
05722 {
05723    struct ast_state_cb *state_cb;
05724    const struct ast_hint *hint = obj;
05725    int *id = arg;
05726 
05727    if ((state_cb = ao2_find(hint->callbacks, id, 0))) {
05728       ao2_ref(state_cb, -1);
05729       return CMP_MATCH | CMP_STOP;
05730    }
05731 
05732    return 0;
05733 }
05734 
05735 /*! \brief  ast_extension_state_del: Remove a watcher from the callback list */
05736 int ast_extension_state_del(int id, ast_state_cb_type change_cb)
05737 {
05738    struct ast_state_cb *p_cur;
05739    int ret = -1;
05740 
05741    if (!id) {  /* id == 0 is a callback without extension */
05742       if (!change_cb) {
05743          return ret;
05744       }
05745       p_cur = ao2_find(statecbs, change_cb, OBJ_UNLINK);
05746       if (p_cur) {
05747          ret = 0;
05748          ao2_ref(p_cur, -1);
05749       }
05750    } else { /* callback with extension, find the callback based on ID */
05751       struct ast_hint *hint;
05752 
05753       ao2_lock(hints);/* Locked to hold off ast_merge_contexts_and_delete */
05754       hint = ao2_callback(hints, 0, find_hint_by_cb_id, &id);
05755       if (hint) {
05756          p_cur = ao2_find(hint->callbacks, &id, OBJ_UNLINK);
05757          if (p_cur) {
05758             ret = 0;
05759             ao2_ref(p_cur, -1);
05760          }
05761          ao2_ref(hint, -1);
05762       }
05763       ao2_unlock(hints);
05764    }
05765 
05766    return ret;
05767 }
05768 
05769 static int hint_id_cmp(void *obj, void *arg, int flags)
05770 {
05771    const struct ast_state_cb *cb = obj;
05772    int *id = arg;
05773 
05774    return (cb->id == *id) ? CMP_MATCH | CMP_STOP : 0;
05775 }
05776 
05777 /*!
05778  * \internal
05779  * \brief Destroy the given hint object.
05780  *
05781  * \param obj Hint to destroy.
05782  *
05783  * \return Nothing
05784  */
05785 static void destroy_hint(void *obj)
05786 {
05787    struct ast_hint *hint = obj;
05788 
05789    if (hint->callbacks) {
05790       struct ast_state_cb *state_cb;
05791       const char *context_name;
05792       const char *exten_name;
05793 
05794       if (hint->exten) {
05795          context_name = ast_get_context_name(ast_get_extension_context(hint->exten));
05796          exten_name = ast_get_extension_name(hint->exten);
05797          hint->exten = NULL;
05798       } else {
05799          /* The extension has already been destroyed */
05800          context_name = hint->context_name;
05801          exten_name = hint->exten_name;
05802       }
05803       hint->laststate = AST_EXTENSION_DEACTIVATED;
05804       while ((state_cb = ao2_callback(hint->callbacks, OBJ_UNLINK, NULL, NULL))) {
05805          /* Notify with -1 and remove all callbacks */
05806          execute_state_callback(state_cb->change_cb,
05807             context_name,
05808             exten_name,
05809             state_cb->data,
05810             AST_HINT_UPDATE_DEVICE,
05811             hint,
05812             NULL);
05813          ao2_ref(state_cb, -1);
05814       }
05815       ao2_ref(hint->callbacks, -1);
05816    }
05817    ast_free(hint->last_presence_subtype);
05818    ast_free(hint->last_presence_message);
05819 }
05820 
05821 /*! \brief Remove hint from extension */
05822 static int ast_remove_hint(struct ast_exten *e)
05823 {
05824    /* Cleanup the Notifys if hint is removed */
05825    struct ast_hint *hint;
05826 
05827    if (!e) {
05828       return -1;
05829    }
05830 
05831    hint = ao2_find(hints, e, OBJ_UNLINK);
05832    if (!hint) {
05833       return -1;
05834    }
05835 
05836    remove_hintdevice(hint);
05837 
05838    /*
05839     * The extension is being destroyed so we must save some
05840     * information to notify that the extension is deactivated.
05841     */
05842    ao2_lock(hint);
05843    ast_copy_string(hint->context_name,
05844       ast_get_context_name(ast_get_extension_context(hint->exten)),
05845       sizeof(hint->context_name));
05846    ast_copy_string(hint->exten_name, ast_get_extension_name(hint->exten),
05847       sizeof(hint->exten_name));
05848    hint->exten = NULL;
05849    ao2_unlock(hint);
05850 
05851    ao2_ref(hint, -1);
05852 
05853    return 0;
05854 }
05855 
05856 /*! \brief Add hint to hint list, check initial extension state */
05857 static int ast_add_hint(struct ast_exten *e)
05858 {
05859    struct ast_hint *hint_new;
05860    struct ast_hint *hint_found;
05861    char *message = NULL;
05862    char *subtype = NULL;
05863    int presence_state;
05864 
05865    if (!e) {
05866       return -1;
05867    }
05868 
05869    /*
05870     * We must create the hint we wish to add before determining if
05871     * it is already in the hints container to avoid possible
05872     * deadlock when getting the current extension state.
05873     */
05874    hint_new = ao2_alloc(sizeof(*hint_new), destroy_hint);
05875    if (!hint_new) {
05876       return -1;
05877    }
05878 
05879    /* Initialize new hint. */
05880    hint_new->callbacks = ao2_container_alloc(1, NULL, hint_id_cmp);
05881    if (!hint_new->callbacks) {
05882       ao2_ref(hint_new, -1);
05883       return -1;
05884    }
05885    hint_new->exten = e;
05886    hint_new->laststate = ast_extension_state2(e, NULL);
05887    if ((presence_state = extension_presence_state_helper(e, &subtype, &message)) > 0) {
05888       hint_new->last_presence_state = presence_state;
05889       hint_new->last_presence_subtype = subtype;
05890       hint_new->last_presence_message = message;
05891       message = subtype = NULL;
05892    }
05893 
05894    /* Prevent multiple add hints from adding the same hint at the same time. */
05895    ao2_lock(hints);
05896 
05897    /* Search if hint exists, do nothing */
05898    hint_found = ao2_find(hints, e, 0);
05899    if (hint_found) {
05900       ao2_ref(hint_found, -1);
05901       ao2_unlock(hints);
05902       ao2_ref(hint_new, -1);
05903       ast_debug(2, "HINTS: Not re-adding existing hint %s: %s\n",
05904          ast_get_extension_name(e), ast_get_extension_app(e));
05905       return -1;
05906    }
05907 
05908    /* Add new hint to the hints container */
05909    ast_debug(2, "HINTS: Adding hint %s: %s\n",
05910       ast_get_extension_name(e), ast_get_extension_app(e));
05911    ao2_link(hints, hint_new);
05912    if (add_hintdevice(hint_new, ast_get_extension_app(e))) {
05913       ast_log(LOG_WARNING, "Could not add devices for hint: %s@%s.\n",
05914          ast_get_extension_name(e),
05915          ast_get_context_name(ast_get_extension_context(e)));
05916    }
05917 
05918    ao2_unlock(hints);
05919    ao2_ref(hint_new, -1);
05920 
05921    return 0;
05922 }
05923 
05924 /*! \brief Change hint for an extension */
05925 static int ast_change_hint(struct ast_exten *oe, struct ast_exten *ne)
05926 {
05927    struct ast_hint *hint;
05928 
05929    if (!oe || !ne) {
05930       return -1;
05931    }
05932 
05933    ao2_lock(hints);/* Locked to hold off others while we move the hint around. */
05934 
05935    /*
05936     * Unlink the hint from the hints container as the extension
05937     * name (which is the hash value) could change.
05938     */
05939    hint = ao2_find(hints, oe, OBJ_UNLINK);
05940    if (!hint) {
05941       ao2_unlock(hints);
05942       return -1;
05943    }
05944 
05945    remove_hintdevice(hint);
05946 
05947    /* Update the hint and put it back in the hints container. */
05948    ao2_lock(hint);
05949    hint->exten = ne;
05950    ao2_unlock(hint);
05951    ao2_link(hints, hint);
05952    if (add_hintdevice(hint, ast_get_extension_app(ne))) {
05953       ast_log(LOG_WARNING, "Could not add devices for hint: %s@%s.\n",
05954          ast_get_extension_name(ne),
05955          ast_get_context_name(ast_get_extension_context(ne)));
05956    }
05957 
05958    ao2_unlock(hints);
05959    ao2_ref(hint, -1);
05960 
05961    return 0;
05962 }
05963 
05964 
05965 /*! \brief Get hint for channel */
05966 int ast_get_hint(char *hint, int hintsize, char *name, int namesize, struct ast_channel *c, const char *context, const char *exten)
05967 {
05968    struct ast_exten *e = ast_hint_extension(c, context, exten);
05969 
05970    if (e) {
05971       if (hint)
05972          ast_copy_string(hint, ast_get_extension_app(e), hintsize);
05973       if (name) {
05974          const char *tmp = ast_get_extension_app_data(e);
05975          if (tmp)
05976             ast_copy_string(name, tmp, namesize);
05977       }
05978       return -1;
05979    }
05980    return 0;
05981 }
05982 
05983 /*! \brief Get hint for channel */
05984 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)
05985 {
05986    struct ast_exten *e = ast_hint_extension(c, context, exten);
05987 
05988    if (!e) {
05989       return 0;
05990    }
05991 
05992    if (hint) {
05993       ast_str_set(hint, hintsize, "%s", ast_get_extension_app(e));
05994    }
05995    if (name) {
05996       const char *tmp = ast_get_extension_app_data(e);
05997       if (tmp) {
05998          ast_str_set(name, namesize, "%s", tmp);
05999       }
06000    }
06001    return -1;
06002 }
06003 
06004 int ast_exists_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
06005 {
06006    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCH, 0, 0);
06007 }
06008 
06009 int ast_findlabel_extension(struct ast_channel *c, const char *context, const char *exten, const char *label, const char *callerid)
06010 {
06011    return pbx_extension_helper(c, NULL, context, exten, 0, label, callerid, E_FINDLABEL, 0, 0);
06012 }
06013 
06014 int ast_findlabel_extension2(struct ast_channel *c, struct ast_context *con, const char *exten, const char *label, const char *callerid)
06015 {
06016    return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, E_FINDLABEL, 0, 0);
06017 }
06018 
06019 int ast_canmatch_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
06020 {
06021    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_CANMATCH, 0, 0);
06022 }
06023 
06024 int ast_matchmore_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
06025 {
06026    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCHMORE, 0, 0);
06027 }
06028 
06029 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)
06030 {
06031    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_SPAWN, found, combined_find_spawn);
06032 }
06033 
06034 void ast_pbx_h_exten_run(struct ast_channel *chan, const char *context)
06035 {
06036    int autoloopflag;
06037    int found;
06038    int spawn_error;
06039 
06040    ast_channel_lock(chan);
06041 
06042    if (ast_channel_cdr(chan) && ast_opt_end_cdr_before_h_exten) {
06043       ast_cdr_end(ast_channel_cdr(chan));
06044    }
06045 
06046    /* Set h exten location */
06047    if (context != ast_channel_context(chan)) {
06048       ast_channel_context_set(chan, context);
06049    }
06050    ast_channel_exten_set(chan, "h");
06051    ast_channel_priority_set(chan, 1);
06052 
06053    /*
06054     * Make sure that the channel is marked as hungup since we are
06055     * going to run the h exten on it.
06056     */
06057    ast_softhangup_nolock(chan, AST_SOFTHANGUP_APPUNLOAD);
06058 
06059    /* Save autoloop flag */
06060    autoloopflag = ast_test_flag(ast_channel_flags(chan), AST_FLAG_IN_AUTOLOOP);
06061    ast_set_flag(ast_channel_flags(chan), AST_FLAG_IN_AUTOLOOP);
06062    ast_channel_unlock(chan);
06063 
06064    for (;;) {
06065       spawn_error = ast_spawn_extension(chan, ast_channel_context(chan),
06066          ast_channel_exten(chan), ast_channel_priority(chan),
06067          S_COR(ast_channel_caller(chan)->id.number.valid,
06068             ast_channel_caller(chan)->id.number.str, NULL), &found, 1);
06069 
06070       ast_channel_lock(chan);
06071       if (spawn_error) {
06072          /* The code after the loop needs the channel locked. */
06073          break;
06074       }
06075       ast_channel_priority_set(chan, ast_channel_priority(chan) + 1);
06076       ast_channel_unlock(chan);
06077    }
06078    if (found && spawn_error) {
06079       /* Something bad happened, or a hangup has been requested. */
06080       ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n",
06081          ast_channel_context(chan), ast_channel_exten(chan),
06082          ast_channel_priority(chan), ast_channel_name(chan));
06083       ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n",
06084          ast_channel_context(chan), ast_channel_exten(chan),
06085          ast_channel_priority(chan), ast_channel_name(chan));
06086    }
06087 
06088    /* An "h" exten has been run, so indicate that one has been run. */
06089    ast_set_flag(ast_channel_flags(chan), AST_FLAG_BRIDGE_HANGUP_RUN);
06090 
06091    /* Restore autoloop flag */
06092    ast_set2_flag(ast_channel_flags(chan), autoloopflag, AST_FLAG_IN_AUTOLOOP);
06093    ast_channel_unlock(chan);
06094 }
06095 
06096 int ast_pbx_hangup_handler_run(struct ast_channel *chan)
06097 {
06098    struct ast_hangup_handler_list *handlers;
06099    struct ast_hangup_handler *h_handler;
06100 
06101    ast_channel_lock(chan);
06102    handlers = ast_channel_hangup_handlers(chan);
06103    if (AST_LIST_EMPTY(handlers)) {
06104       ast_channel_unlock(chan);
06105       return 0;
06106    }
06107 
06108    if (ast_channel_cdr(chan) && ast_opt_end_cdr_before_h_exten) {
06109       ast_cdr_end(ast_channel_cdr(chan));
06110    }
06111 
06112    /*
06113     * Make sure that the channel is marked as hungup since we are
06114     * going to run the hangup handlers on it.
06115     */
06116    ast_softhangup_nolock(chan, AST_SOFTHANGUP_APPUNLOAD);
06117 
06118    for (;;) {
06119       handlers = ast_channel_hangup_handlers(chan);
06120       h_handler = AST_LIST_REMOVE_HEAD(handlers, node);
06121       if (!h_handler) {
06122          break;
06123       }
06124 
06125       /*** DOCUMENTATION
06126          <managerEventInstance>
06127             <synopsis>Raised when a hangup handler is about to be called.</synopsis>
06128             <syntax>
06129                <parameter name="Handler">
06130                   <para>Hangup handler parameter string passed to the Gosub application.</para>
06131                </parameter>
06132             </syntax>
06133          </managerEventInstance>
06134       ***/
06135       manager_event(EVENT_FLAG_DIALPLAN, "HangupHandlerRun",
06136          "Channel: %s\r\n"
06137          "Uniqueid: %s\r\n"
06138          "Handler: %s\r\n",
06139          ast_channel_name(chan),
06140          ast_channel_uniqueid(chan),
06141          h_handler->args);
06142       ast_channel_unlock(chan);
06143 
06144       ast_app_exec_sub(NULL, chan, h_handler->args, 1);
06145       ast_free(h_handler);
06146 
06147       ast_channel_lock(chan);
06148    }
06149    ast_channel_unlock(chan);
06150    return 1;
06151 }
06152 
06153 void ast_pbx_hangup_handler_init(struct ast_channel *chan)
06154 {
06155    struct ast_hangup_handler_list *handlers;
06156 
06157    handlers = ast_channel_hangup_handlers(chan);
06158    AST_LIST_HEAD_INIT_NOLOCK(handlers);
06159 }
06160 
06161 void ast_pbx_hangup_handler_destroy(struct ast_channel *chan)
06162 {
06163    struct ast_hangup_handler_list *handlers;
06164    struct ast_hangup_handler *h_handler;
06165 
06166    ast_channel_lock(chan);
06167 
06168    /* Get rid of each of the hangup handlers on the channel */
06169    handlers = ast_channel_hangup_handlers(chan);
06170    while ((h_handler = AST_LIST_REMOVE_HEAD(handlers, node))) {
06171       ast_free(h_handler);
06172    }
06173 
06174    ast_channel_unlock(chan);
06175 }
06176 
06177 int ast_pbx_hangup_handler_pop(struct ast_channel *chan)
06178 {
06179    struct ast_hangup_handler_list *handlers;
06180    struct ast_hangup_handler *h_handler;
06181 
06182    ast_channel_lock(chan);
06183    handlers = ast_channel_hangup_handlers(chan);
06184    h_handler = AST_LIST_REMOVE_HEAD(handlers, node);
06185    if (h_handler) {
06186       /*** DOCUMENTATION
06187          <managerEventInstance>
06188             <synopsis>
06189                Raised when a hangup handler is removed from the handler
06190                stack by the CHANNEL() function.
06191             </synopsis>
06192             <syntax>
06193                <parameter name="Handler">
06194                   <para>Hangup handler parameter string passed to the Gosub application.</para>
06195                </parameter>
06196             </syntax>
06197             <see-also>
06198                <ref type="managerEvent">HangupHandlerPush</ref>
06199                <ref type="function">CHANNEL</ref>
06200             </see-also>
06201          </managerEventInstance>
06202       ***/
06203       manager_event(EVENT_FLAG_DIALPLAN, "HangupHandlerPop",
06204          "Channel: %s\r\n"
06205          "Uniqueid: %s\r\n"
06206          "Handler: %s\r\n",
06207          ast_channel_name(chan),
06208          ast_channel_uniqueid(chan),
06209          h_handler->args);
06210    }
06211    ast_channel_unlock(chan);
06212    if (h_handler) {
06213       ast_free(h_handler);
06214       return 1;
06215    }
06216    return 0;
06217 }
06218 
06219 void ast_pbx_hangup_handler_push(struct ast_channel *chan, const char *handler)
06220 {
06221    struct ast_hangup_handler_list *handlers;
06222    struct ast_hangup_handler *h_handler;
06223    const char *expanded_handler;
06224 
06225    if (ast_strlen_zero(handler)) {
06226       return;
06227    }
06228 
06229    expanded_handler = ast_app_expand_sub_args(chan, handler);
06230    if (!expanded_handler) {
06231       return;
06232    }
06233    h_handler = ast_malloc(sizeof(*h_handler) + 1 + strlen(expanded_handler));
06234    if (!h_handler) {
06235       ast_free((char *) expanded_handler);
06236       return;
06237    }
06238    strcpy(h_handler->args, expanded_handler);/* Safe */
06239    ast_free((char *) expanded_handler);
06240 
06241    ast_channel_lock(chan);
06242 
06243    handlers = ast_channel_hangup_handlers(chan);
06244    AST_LIST_INSERT_HEAD(handlers, h_handler, node);
06245 
06246    /*** DOCUMENTATION
06247       <managerEventInstance>
06248          <synopsis>
06249             Raised when a hangup handler is added to the handler
06250             stack by the CHANNEL() function.
06251          </synopsis>
06252          <syntax>
06253             <parameter name="Handler">
06254                <para>Hangup handler parameter string passed to the Gosub application.</para>
06255             </parameter>
06256          </syntax>
06257          <see-also>
06258             <ref type="managerEvent">HangupHandlerPop</ref>
06259             <ref type="function">CHANNEL</ref>
06260          </see-also>
06261       </managerEventInstance>
06262    ***/
06263    manager_event(EVENT_FLAG_DIALPLAN, "HangupHandlerPush",
06264       "Channel: %s\r\n"
06265       "Uniqueid: %s\r\n"
06266       "Handler: %s\r\n",
06267       ast_channel_name(chan),
06268       ast_channel_uniqueid(chan),
06269       h_handler->args);
06270 
06271    ast_channel_unlock(chan);
06272 }
06273 
06274 #define HANDLER_FORMAT  "%-30s %s\n"
06275 
06276 /*!
06277  * \internal
06278  * \brief CLI output the hangup handler headers.
06279  * \since 11.0
06280  *
06281  * \param fd CLI file descriptor to use.
06282  *
06283  * \return Nothing
06284  */
06285 static void ast_pbx_hangup_handler_headers(int fd)
06286 {
06287    ast_cli(fd, HANDLER_FORMAT, "Channel", "Handler");
06288 }
06289 
06290 /*!
06291  * \internal
06292  * \brief CLI output the channel hangup handlers.
06293  * \since 11.0
06294  *
06295  * \param fd CLI file descriptor to use.
06296  * \param chan Channel to show hangup handlers.
06297  *
06298  * \return Nothing
06299  */
06300 static void ast_pbx_hangup_handler_show(int fd, struct ast_channel *chan)
06301 {
06302    struct ast_hangup_handler_list *handlers;
06303    struct ast_hangup_handler *h_handler;
06304    int first = 1;
06305 
06306    ast_channel_lock(chan);
06307    handlers = ast_channel_hangup_handlers(chan);
06308    AST_LIST_TRAVERSE(handlers, h_handler, node) {
06309       ast_cli(fd, HANDLER_FORMAT, first ? ast_channel_name(chan) : "", h_handler->args);
06310       first = 0;
06311    }
06312    ast_channel_unlock(chan);
06313 }
06314 
06315 /*
06316  * \brief 'show hanguphandlers <channel>' CLI command implementation function...
06317  */
06318 static char *handle_show_hangup_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
06319 {
06320    struct ast_channel *chan;
06321 
06322    switch (cmd) {
06323    case CLI_INIT:
06324       e->command = "core show hanguphandlers";
06325       e->usage =
06326          "Usage: core show hanguphandlers <channel>\n"
06327          "       Show hangup handlers of a specified channel.\n";
06328       return NULL;
06329    case CLI_GENERATE:
06330       return ast_complete_channels(a->line, a->word, a->pos, a->n, e->args);
06331    }
06332 
06333    if (a->argc < 4) {
06334       return CLI_SHOWUSAGE;
06335    }
06336 
06337    chan = ast_channel_get_by_name(a->argv[3]);
06338    if (!chan) {
06339       ast_cli(a->fd, "Channel does not exist.\n");
06340       return CLI_FAILURE;
06341    }
06342 
06343    ast_pbx_hangup_handler_headers(a->fd);
06344    ast_pbx_hangup_handler_show(a->fd, chan);
06345 
06346    ast_channel_unref(chan);
06347 
06348    return CLI_SUCCESS;
06349 }
06350 
06351 /*
06352  * \brief 'show hanguphandlers all' CLI command implementation function...
06353  */
06354 static char *handle_show_hangup_all(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
06355 {
06356    struct ast_channel_iterator *iter;
06357    struct ast_channel *chan;
06358 
06359    switch (cmd) {
06360    case CLI_INIT:
06361       e->command = "core show hanguphandlers all";
06362       e->usage =
06363          "Usage: core show hanguphandlers all\n"
06364          "       Show hangup handlers for all channels.\n";
06365       return NULL;
06366    case CLI_GENERATE:
06367       return ast_complete_channels(a->line, a->word, a->pos, a->n, e->args);
06368    }
06369 
06370    if (a->argc < 4) {
06371       return CLI_SHOWUSAGE;
06372    }
06373 
06374    iter = ast_channel_iterator_all_new();
06375    if (!iter) {
06376       return CLI_FAILURE;
06377    }
06378 
06379    ast_pbx_hangup_handler_headers(a->fd);
06380    for (; (chan = ast_channel_iterator_next(iter)); ast_channel_unref(chan)) {
06381       ast_pbx_hangup_handler_show(a->fd, chan);
06382    }
06383    ast_channel_iterator_destroy(iter);
06384 
06385    return CLI_SUCCESS;
06386 }
06387 
06388 /*! helper function to set extension and priority */
06389 static void set_ext_pri(struct ast_channel *c, const char *exten, int pri)
06390 {
06391    ast_channel_lock(c);
06392    ast_channel_exten_set(c, exten);
06393    ast_channel_priority_set(c, pri);
06394    ast_channel_unlock(c);
06395 }
06396 
06397 /*!
06398  * \brief collect digits from the channel into the buffer.
06399  * \param c, buf, buflen, pos
06400  * \param waittime is in milliseconds
06401  * \retval 0 on timeout or done.
06402  * \retval -1 on error.
06403 */
06404 static int collect_digits(struct ast_channel *c, int waittime, char *buf, int buflen, int pos)
06405 {
06406    int digit;
06407 
06408    buf[pos] = '\0';  /* make sure it is properly terminated */
06409    while (ast_matchmore_extension(c, ast_channel_context(c), buf, 1,
06410       S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
06411       /* As long as we're willing to wait, and as long as it's not defined,
06412          keep reading digits until we can't possibly get a right answer anymore.  */
06413       digit = ast_waitfordigit(c, waittime);
06414       if (ast_channel_softhangup_internal_flag(c) & AST_SOFTHANGUP_ASYNCGOTO) {
06415          ast_channel_clear_softhangup(c, AST_SOFTHANGUP_ASYNCGOTO);
06416       } else {
06417          if (!digit) /* No entry */
06418             break;
06419          if (digit < 0) /* Error, maybe a  hangup */
06420             return -1;
06421          if (pos < buflen - 1) { /* XXX maybe error otherwise ? */
06422             buf[pos++] = digit;
06423             buf[pos] = '\0';
06424          }
06425          waittime = ast_channel_pbx(c)->dtimeoutms;
06426       }
06427    }
06428    return 0;
06429 }
06430 
06431 static enum ast_pbx_result __ast_pbx_run(struct ast_channel *c,
06432       struct ast_pbx_args *args)
06433 {
06434    int found = 0; /* set if we find at least one match */
06435    int res = 0;
06436    int autoloopflag;
06437    int error = 0;    /* set an error conditions */
06438    struct ast_pbx *pbx;
06439    struct ast_callid *callid;
06440 
06441    /* A little initial setup here */
06442    if (ast_channel_pbx(c)) {
06443       ast_log(LOG_WARNING, "%s already has PBX structure??\n", ast_channel_name(c));
06444       /* XXX and now what ? */
06445       ast_free(ast_channel_pbx(c));
06446    }
06447    if (!(pbx = ast_calloc(1, sizeof(*pbx)))) {
06448       return -1;
06449    }
06450 
06451    callid = ast_read_threadstorage_callid();
06452    /* If the thread isn't already associated with a callid, we should create that association. */
06453    if (!callid) {
06454       /* Associate new PBX thread with the channel call id if it is availble.
06455        * If not, create a new one instead.
06456        */
06457       callid = ast_channel_callid(c);
06458       if (!callid) {
06459          callid = ast_create_callid();
06460          if (callid) {
06461             ast_channel_callid_set(c, callid);
06462          }
06463       }
06464       ast_callid_threadassoc_add(callid);
06465       callid = ast_callid_unref(callid);
06466    } else {
06467       /* Nothing to do here, The thread is already bound to a callid.  Let's just get rid of the reference. */
06468       ast_callid_unref(callid);
06469    }
06470 
06471    ast_channel_pbx_set(c, pbx);
06472    /* Set reasonable defaults */
06473    ast_channel_pbx(c)->rtimeoutms = 10000;
06474    ast_channel_pbx(c)->dtimeoutms = 5000;
06475 
06476    autoloopflag = ast_test_flag(ast_channel_flags(c), AST_FLAG_IN_AUTOLOOP);  /* save value to restore at the end */
06477    ast_set_flag(ast_channel_flags(c), AST_FLAG_IN_AUTOLOOP);
06478 
06479    if (ast_strlen_zero(ast_channel_exten(c))) {
06480       /* If not successful fall back to 's' - but only if there is no given exten  */
06481       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));
06482       /* XXX the original code used the existing priority in the call to
06483        * ast_exists_extension(), and reset it to 1 afterwards.
06484        * I believe the correct thing is to set it to 1 immediately.
06485       */
06486       set_ext_pri(c, "s", 1);
06487    }
06488 
06489    ast_channel_lock(c);
06490    if (ast_channel_cdr(c)) {
06491       /* allow CDR variables that have been collected after channel was created to be visible during call */
06492       ast_cdr_update(c);
06493    }
06494    ast_channel_unlock(c);
06495    for (;;) {
06496       char dst_exten[256]; /* buffer to accumulate digits */
06497       int pos = 0;      /* XXX should check bounds */
06498       int digit = 0;
06499       int invalid = 0;
06500       int timeout = 0;
06501 
06502       /* No digits pressed yet */
06503       dst_exten[pos] = '\0';
06504 
06505       /* loop on priorities in this context/exten */
06506       while (!(res = ast_spawn_extension(c, ast_channel_context(c), ast_channel_exten(c), ast_channel_priority(c),
06507          S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL),
06508          &found, 1))) {
06509          if (!ast_check_hangup(c)) {
06510             ast_channel_priority_set(c, ast_channel_priority(c) + 1);
06511             continue;
06512          }
06513 
06514          /* Check softhangup flags. */
06515          if (ast_channel_softhangup_internal_flag(c) & AST_SOFTHANGUP_ASYNCGOTO) {
06516             ast_channel_clear_softhangup(c, AST_SOFTHANGUP_ASYNCGOTO);
06517             continue;
06518          }
06519          if (ast_channel_softhangup_internal_flag(c) & AST_SOFTHANGUP_TIMEOUT) {
06520             if (ast_exists_extension(c, ast_channel_context(c), "T", 1,
06521                S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
06522                set_ext_pri(c, "T", 1);
06523                /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
06524                memset(ast_channel_whentohangup(c), 0, sizeof(*ast_channel_whentohangup(c)));
06525                ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT);
06526                continue;
06527             } else if (ast_exists_extension(c, ast_channel_context(c), "e", 1,
06528                S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
06529                raise_exception(c, "ABSOLUTETIMEOUT", 1);
06530                /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
06531                memset(ast_channel_whentohangup(c), 0, sizeof(*ast_channel_whentohangup(c)));
06532                ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT);
06533                continue;
06534             }
06535 
06536             /* Call timed out with no special extension to jump to. */
06537             error = 1;
06538             break;
06539          }
06540          ast_debug(1, "Extension %s, priority %d returned normally even though call was hung up\n",
06541             ast_channel_exten(c), ast_channel_priority(c));
06542          error = 1;
06543          break;
06544       } /* end while  - from here on we can use 'break' to go out */
06545       if (found && res) {
06546          /* Something bad happened, or a hangup has been requested. */
06547          if (strchr("0123456789ABCDEF*#", res)) {
06548             ast_debug(1, "Oooh, got something to jump out with ('%c')!\n", res);
06549             pos = 0;
06550             dst_exten[pos++] = digit = res;
06551             dst_exten[pos] = '\0';
06552          } else if (res == AST_PBX_INCOMPLETE) {
06553             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));
06554             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));
06555 
06556             /* Don't cycle on incomplete - this will happen if the only extension that matches is our "incomplete" extension */
06557             if (!ast_matchmore_extension(c, ast_channel_context(c), ast_channel_exten(c), 1,
06558                S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
06559                invalid = 1;
06560             } else {
06561                ast_copy_string(dst_exten, ast_channel_exten(c), sizeof(dst_exten));
06562                digit = 1;
06563                pos = strlen(dst_exten);
06564             }
06565          } else {
06566             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));
06567             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));
06568 
06569             if ((res == AST_PBX_ERROR)
06570                && ast_exists_extension(c, ast_channel_context(c), "e", 1,
06571                   S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
06572                /* if we are already on the 'e' exten, don't jump to it again */
06573                if (!strcmp(ast_channel_exten(c), "e")) {
06574                   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));
06575                   error = 1;
06576                } else {
06577                   raise_exception(c, "ERROR", 1);
06578                   continue;
06579                }
06580             }
06581 
06582             if (ast_channel_softhangup_internal_flag(c) & AST_SOFTHANGUP_ASYNCGOTO) {
06583                ast_channel_clear_softhangup(c, AST_SOFTHANGUP_ASYNCGOTO);
06584                continue;
06585             }
06586             if (ast_channel_softhangup_internal_flag(c) & AST_SOFTHANGUP_TIMEOUT) {
06587                if (ast_exists_extension(c, ast_channel_context(c), "T", 1,
06588                   S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
06589                   set_ext_pri(c, "T", 1);
06590                   /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
06591                   memset(ast_channel_whentohangup(c), 0, sizeof(*ast_channel_whentohangup(c)));
06592                   ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT);
06593                   continue;
06594                } else if (ast_exists_extension(c, ast_channel_context(c), "e", 1,
06595                   S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
06596                   raise_exception(c, "ABSOLUTETIMEOUT", 1);
06597                   /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
06598                   memset(ast_channel_whentohangup(c), 0, sizeof(*ast_channel_whentohangup(c)));
06599                   ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT);
06600                   continue;
06601                }
06602                /* Call timed out with no special extension to jump to. */
06603             }
06604             ast_channel_lock(c);
06605             if (ast_channel_cdr(c)) {
06606                ast_cdr_update(c);
06607             }
06608             ast_channel_unlock(c);
06609             error = 1;
06610             break;
06611          }
06612       }
06613       if (error)
06614          break;
06615 
06616       /*!\note
06617        * We get here on a failure of some kind:  non-existing extension or
06618        * hangup.  We have options, here.  We can either catch the failure
06619        * and continue, or we can drop out entirely. */
06620 
06621       if (invalid
06622          || (ast_strlen_zero(dst_exten) &&
06623             !ast_exists_extension(c, ast_channel_context(c), ast_channel_exten(c), 1,
06624             S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL)))) {
06625          /*!\note
06626           * If there is no match at priority 1, it is not a valid extension anymore.
06627           * Try to continue at "i" (for invalid) or "e" (for exception) or exit if
06628           * neither exist.
06629           */
06630          if (ast_exists_extension(c, ast_channel_context(c), "i", 1,
06631             S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
06632             ast_verb(3, "Channel '%s' sent to invalid extension: context,exten,priority=%s,%s,%d\n",
06633                ast_channel_name(c), ast_channel_context(c), ast_channel_exten(c), ast_channel_priority(c));
06634             pbx_builtin_setvar_helper(c, "INVALID_EXTEN", ast_channel_exten(c));
06635             set_ext_pri(c, "i", 1);
06636          } else if (ast_exists_extension(c, ast_channel_context(c), "e", 1,
06637             S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
06638             raise_exception(c, "INVALID", 1);
06639          } else {
06640             ast_log(LOG_WARNING, "Channel '%s' sent to invalid extension but no invalid handler: context,exten,priority=%s,%s,%d\n",
06641                ast_channel_name(c), ast_channel_context(c), ast_channel_exten(c), ast_channel_priority(c));
06642             error = 1; /* we know what to do with it */
06643             break;
06644          }
06645       } else if (ast_channel_softhangup_internal_flag(c) & AST_SOFTHANGUP_TIMEOUT) {
06646          /* If we get this far with AST_SOFTHANGUP_TIMEOUT, then we know that the "T" extension is next. */
06647          ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT);
06648       } else { /* keypress received, get more digits for a full extension */
06649          int waittime = 0;
06650          if (digit)
06651             waittime = ast_channel_pbx(c)->dtimeoutms;
06652          else if (!autofallthrough)
06653             waittime = ast_channel_pbx(c)->rtimeoutms;
06654          if (!waittime) {
06655             const char *status = pbx_builtin_getvar_helper(c, "DIALSTATUS");
06656             if (!status)
06657                status = "UNKNOWN";
06658             ast_verb(3, "Auto fallthrough, channel '%s' status is '%s'\n", ast_channel_name(c), status);
06659             if (!strcasecmp(status, "CONGESTION"))
06660                res = pbx_builtin_congestion(c, "10");
06661             else if (!strcasecmp(status, "CHANUNAVAIL"))
06662                res = pbx_builtin_congestion(c, "10");
06663             else if (!strcasecmp(status, "BUSY"))
06664                res = pbx_builtin_busy(c, "10");
06665             error = 1; /* XXX disable message */
06666             break;   /* exit from the 'for' loop */
06667          }
06668 
06669          if (collect_digits(c, waittime, dst_exten, sizeof(dst_exten), pos))
06670             break;
06671          if (res == AST_PBX_INCOMPLETE && ast_strlen_zero(&dst_exten[pos]))
06672             timeout = 1;
06673          if (!timeout
06674             && ast_exists_extension(c, ast_channel_context(c), dst_exten, 1,
06675                S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) { /* Prepare the next cycle */
06676             set_ext_pri(c, dst_exten, 1);
06677          } else {
06678             /* No such extension */
06679             if (!timeout && !ast_strlen_zero(dst_exten)) {
06680                /* An invalid extension */
06681                if (ast_exists_extension(c, ast_channel_context(c), "i", 1,
06682                   S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
06683                   ast_verb(3, "Invalid extension '%s' in context '%s' on %s\n", dst_exten, ast_channel_context(c), ast_channel_name(c));
06684                   pbx_builtin_setvar_helper(c, "INVALID_EXTEN", dst_exten);
06685                   set_ext_pri(c, "i", 1);
06686                } else if (ast_exists_extension(c, ast_channel_context(c), "e", 1,
06687                   S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
06688                   raise_exception(c, "INVALID", 1);
06689                } else {
06690                   ast_log(LOG_WARNING,
06691                      "Invalid extension '%s', but no rule 'i' or 'e' in context '%s'\n",
06692                      dst_exten, ast_channel_context(c));
06693                   found = 1; /* XXX disable message */
06694                   break;
06695                }
06696             } else {
06697                /* A simple timeout */
06698                if (ast_exists_extension(c, ast_channel_context(c), "t", 1,
06699                   S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
06700                   ast_verb(3, "Timeout on %s\n", ast_channel_name(c));
06701                   set_ext_pri(c, "t", 1);
06702                } else if (ast_exists_extension(c, ast_channel_context(c), "e", 1,
06703                   S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
06704                   raise_exception(c, "RESPONSETIMEOUT", 1);
06705                } else {
06706                   ast_log(LOG_WARNING,
06707                      "Timeout, but no rule 't' or 'e' in context '%s'\n",
06708                      ast_channel_context(c));
06709                   found = 1; /* XXX disable message */
06710                   break;
06711                }
06712             }
06713          }
06714          ast_channel_lock(c);
06715          if (ast_channel_cdr(c)) {
06716             ast_verb(2, "CDR updated on %s\n",ast_channel_name(c));
06717             ast_cdr_update(c);
06718          }
06719          ast_channel_unlock(c);
06720       }
06721    }
06722 
06723    if (!found && !error) {
06724       ast_log(LOG_WARNING, "Don't know what to do with '%s'\n", ast_channel_name(c));
06725    }
06726 
06727    if (!args || !args->no_hangup_chan) {
06728       ast_softhangup(c, AST_SOFTHANGUP_APPUNLOAD);
06729       if (!ast_test_flag(ast_channel_flags(c), AST_FLAG_BRIDGE_HANGUP_RUN)
06730          && ast_exists_extension(c, ast_channel_context(c), "h", 1,
06731             S_COR(ast_channel_caller(c)->id.number.valid,
06732                ast_channel_caller(c)->id.number.str, NULL))) {
06733          ast_pbx_h_exten_run(c, ast_channel_context(c));
06734       }
06735       ast_pbx_hangup_handler_run(c);
06736    }
06737 
06738    ast_set2_flag(ast_channel_flags(c), autoloopflag, AST_FLAG_IN_AUTOLOOP);
06739    ast_clear_flag(ast_channel_flags(c), AST_FLAG_BRIDGE_HANGUP_RUN); /* from one round to the next, make sure this gets cleared */
06740    pbx_destroy(ast_channel_pbx(c));
06741    ast_channel_pbx_set(c, NULL);
06742 
06743    if (!args || !args->no_hangup_chan) {
06744       ast_hangup(c);
06745    }
06746 
06747    return 0;
06748 }
06749 
06750 /*!
06751  * \brief Increase call count for channel
06752  * \retval 0 on success
06753  * \retval non-zero if a configured limit (maxcalls, maxload, minmemfree) was reached
06754 */
06755 static int increase_call_count(const struct ast_channel *c)
06756 {
06757    int failed = 0;
06758    double curloadavg;
06759 #if defined(HAVE_SYSINFO)
06760    long curfreemem;
06761    struct sysinfo sys_info;
06762 #endif
06763 
06764    ast_mutex_lock(&maxcalllock);
06765    if (option_maxcalls) {
06766       if (countcalls >= option_maxcalls) {
06767          ast_log(LOG_WARNING, "Maximum call limit of %d calls exceeded by '%s'!\n", option_maxcalls, ast_channel_name(c));
06768          failed = -1;
06769       }
06770    }
06771    if (option_maxload) {
06772       getloadavg(&curloadavg, 1);
06773       if (curloadavg >= option_maxload) {
06774          ast_log(LOG_WARNING, "Maximum loadavg limit of %f load exceeded by '%s' (currently %f)!\n", option_maxload, ast_channel_name(c), curloadavg);
06775          failed = -1;
06776       }
06777    }
06778 #if defined(HAVE_SYSINFO)
06779    if (option_minmemfree) {
06780       if (!sysinfo(&sys_info)) {
06781          /* make sure that the free system memory is above the configured low watermark
06782           * convert the amount of freeram from mem_units to MB */
06783          curfreemem = sys_info.freeram * sys_info.mem_unit;
06784          curfreemem /= 1024 * 1024;
06785          if (curfreemem < option_minmemfree) {
06786             ast_log(LOG_WARNING, "Available system memory (~%ldMB) is below the configured low watermark (%ldMB)\n", curfreemem, option_minmemfree);
06787             failed = -1;
06788          }
06789       }
06790    }
06791 #endif
06792 
06793    if (!failed) {
06794       countcalls++;
06795       totalcalls++;
06796    }
06797    ast_mutex_unlock(&maxcalllock);
06798 
06799    return failed;
06800 }
06801 
06802 static void decrease_call_count(void)
06803 {
06804    ast_mutex_lock(&maxcalllock);
06805    if (countcalls > 0)
06806       countcalls--;
06807    ast_mutex_unlock(&maxcalllock);
06808 }
06809 
06810 static void destroy_exten(struct ast_exten *e)
06811 {
06812    if (e->priority == PRIORITY_HINT)
06813       ast_remove_hint(e);
06814 
06815    if (e->peer_table)
06816       ast_hashtab_destroy(e->peer_table,0);
06817    if (e->peer_label_table)
06818       ast_hashtab_destroy(e->peer_label_table, 0);
06819    if (e->datad)
06820       e->datad(e->data);
06821    ast_free(e);
06822 }
06823 
06824 static void *pbx_thread(void *data)
06825 {
06826    /* Oh joyeous kernel, we're a new thread, with nothing to do but
06827       answer this channel and get it going.
06828    */
06829    /* NOTE:
06830       The launcher of this function _MUST_ increment 'countcalls'
06831       before invoking the function; it will be decremented when the
06832       PBX has finished running on the channel
06833     */
06834    struct ast_channel *c = data;
06835 
06836    __ast_pbx_run(c, NULL);
06837    decrease_call_count();
06838 
06839    pthread_exit(NULL);
06840 
06841    return NULL;
06842 }
06843 
06844 enum ast_pbx_result ast_pbx_start(struct ast_channel *c)
06845 {
06846    pthread_t t;
06847 
06848    if (!c) {
06849       ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n");
06850       return AST_PBX_FAILED;
06851    }
06852 
06853    if (!ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) {
06854       ast_log(LOG_WARNING, "PBX requires Asterisk to be fully booted\n");
06855       return AST_PBX_FAILED;
06856    }
06857 
06858    if (increase_call_count(c))
06859       return AST_PBX_CALL_LIMIT;
06860 
06861    /* Start a new thread, and get something handling this channel. */
06862    if (ast_pthread_create_detached(&t, NULL, pbx_thread, c)) {
06863       ast_log(LOG_WARNING, "Failed to create new channel thread\n");
06864       decrease_call_count();
06865       return AST_PBX_FAILED;
06866    }
06867 
06868    return AST_PBX_SUCCESS;
06869 }
06870 
06871 enum ast_pbx_result ast_pbx_run_args(struct ast_channel *c, struct ast_pbx_args *args)
06872 {
06873    enum ast_pbx_result res = AST_PBX_SUCCESS;
06874 
06875    if (!ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) {
06876       ast_log(LOG_WARNING, "PBX requires Asterisk to be fully booted\n");
06877       return AST_PBX_FAILED;
06878    }
06879 
06880    if (increase_call_count(c)) {
06881       return AST_PBX_CALL_LIMIT;
06882    }
06883 
06884    res = __ast_pbx_run(c, args);
06885 
06886    decrease_call_count();
06887 
06888    return res;
06889 }
06890 
06891 enum ast_pbx_result ast_pbx_run(struct ast_channel *c)
06892 {
06893    return ast_pbx_run_args(c, NULL);
06894 }
06895 
06896 int ast_active_calls(void)
06897 {
06898    return countcalls;
06899 }
06900 
06901 int ast_processed_calls(void)
06902 {
06903    return totalcalls;
06904 }
06905 
06906 int pbx_set_autofallthrough(int newval)
06907 {
06908    int oldval = autofallthrough;
06909    autofallthrough = newval;
06910    return oldval;
06911 }
06912 
06913 int pbx_set_extenpatternmatchnew(int newval)
06914 {
06915    int oldval = extenpatternmatchnew;
06916    extenpatternmatchnew = newval;
06917    return oldval;
06918 }
06919 
06920 void pbx_set_overrideswitch(const char *newval)
06921 {
06922    if (overrideswitch) {
06923       ast_free(overrideswitch);
06924    }
06925    if (!ast_strlen_zero(newval)) {
06926       overrideswitch = ast_strdup(newval);
06927    } else {
06928       overrideswitch = NULL;
06929    }
06930 }
06931 
06932 /*!
06933  * \brief lookup for a context with a given name,
06934  * \retval found context or NULL if not found.
06935  */
06936 static struct ast_context *find_context(const char *context)
06937 {
06938    struct fake_context item;
06939 
06940    ast_copy_string(item.name, context, sizeof(item.name));
06941 
06942    return ast_hashtab_lookup(contexts_table, &item);
06943 }
06944 
06945 /*!
06946  * \brief lookup for a context with a given name,
06947  * \retval with conlock held if found.
06948  * \retval NULL if not found.
06949  */
06950 static struct ast_context *find_context_locked(const char *context)
06951 {
06952    struct ast_context *c;
06953    struct fake_context item;
06954 
06955    ast_copy_string(item.name, context, sizeof(item.name));
06956 
06957    ast_rdlock_contexts();
06958    c = ast_hashtab_lookup(contexts_table, &item);
06959    if (!c) {
06960       ast_unlock_contexts();
06961    }
06962 
06963    return c;
06964 }
06965 
06966 /*!
06967  * \brief Remove included contexts.
06968  * This function locks contexts list by &conlist, search for the right context
06969  * structure, leave context list locked and call ast_context_remove_include2
06970  * which removes include, unlock contexts list and return ...
06971  */
06972 int ast_context_remove_include(const char *context, const char *include, const char *registrar)
06973 {
06974    int ret = -1;
06975    struct ast_context *c;
06976 
06977    c = find_context_locked(context);
06978    if (c) {
06979       /* found, remove include from this context ... */
06980       ret = ast_context_remove_include2(c, include, registrar);
06981       ast_unlock_contexts();
06982    }
06983    return ret;
06984 }
06985 
06986 /*!
06987  * \brief Locks context, remove included contexts, unlocks context.
06988  * When we call this function, &conlock lock must be locked, because when
06989  * we giving *con argument, some process can remove/change this context
06990  * and after that there can be segfault.
06991  *
06992  * \retval 0 on success.
06993  * \retval -1 on failure.
06994  */
06995 int ast_context_remove_include2(struct ast_context *con, const char *include, const char *registrar)
06996 {
06997    struct ast_include *i, *pi = NULL;
06998    int ret = -1;
06999 
07000    ast_wrlock_context(con);
07001 
07002    /* find our include */
07003    for (i = con->includes; i; pi = i, i = i->next) {
07004       if (!strcmp(i->name, include) &&
07005             (!registrar || !strcmp(i->registrar, registrar))) {
07006          /* remove from list */
07007          ast_verb(3, "Removing inclusion of context '%s' in context '%s; registrar=%s'\n", include, ast_get_context_name(con), registrar);
07008          if (pi)
07009             pi->next = i->next;
07010          else
07011             con->includes = i->next;
07012          /* free include and return */
07013          ast_destroy_timing(&(i->timing));
07014          ast_free(i);
07015          ret = 0;
07016          break;
07017       }
07018    }
07019 
07020    ast_unlock_context(con);
07021 
07022    return ret;
07023 }
07024 
07025 /*!
07026  * \note This function locks contexts list by &conlist, search for the rigt context
07027  * structure, leave context list locked and call ast_context_remove_switch2
07028  * which removes switch, unlock contexts list and return ...
07029  */
07030 int ast_context_remove_switch(const char *context, const char *sw, const char *data, const char *registrar)
07031 {
07032    int ret = -1; /* default error return */
07033    struct ast_context *c;
07034 
07035    c = find_context_locked(context);
07036    if (c) {
07037       /* remove switch from this context ... */
07038       ret = ast_context_remove_switch2(c, sw, data, registrar);
07039       ast_unlock_contexts();
07040    }
07041    return ret;
07042 }
07043 
07044 /*!
07045  * \brief This function locks given context, removes switch, unlock context and
07046  * return.
07047  * \note When we call this function, &conlock lock must be locked, because when
07048  * we giving *con argument, some process can remove/change this context
07049  * and after that there can be segfault.
07050  *
07051  */
07052 int ast_context_remove_switch2(struct ast_context *con, const char *sw, const char *data, const char *registrar)
07053 {
07054    struct ast_sw *i;
07055    int ret = -1;
07056 
07057    ast_wrlock_context(con);
07058 
07059    /* walk switches */
07060    AST_LIST_TRAVERSE_SAFE_BEGIN(&con->alts, i, list) {
07061       if (!strcmp(i->name, sw) && !strcmp(i->data, data) &&
07062          (!registrar || !strcmp(i->registrar, registrar))) {
07063          /* found, remove from list */
07064          ast_verb(3, "Removing switch '%s' from context '%s; registrar=%s'\n", sw, ast_get_context_name(con), registrar);
07065          AST_LIST_REMOVE_CURRENT(list);
07066          ast_free(i); /* free switch and return */
07067          ret = 0;
07068          break;
07069       }
07070    }
07071    AST_LIST_TRAVERSE_SAFE_END;
07072 
07073    ast_unlock_context(con);
07074 
07075    return ret;
07076 }
07077 
07078 /*! \note This function will lock conlock. */
07079 int ast_context_remove_extension(const char *context, const char *extension, int priority, const char *registrar)
07080 {
07081    return ast_context_remove_extension_callerid(context, extension, priority, NULL, AST_EXT_MATCHCID_ANY, registrar);
07082 }
07083 
07084 int ast_context_remove_extension_callerid(const char *context, const char *extension, int priority, const char *callerid, int matchcallerid, const char *registrar)
07085 {
07086    int ret = -1; /* default error return */
07087    struct ast_context *c;
07088 
07089    c = find_context_locked(context);
07090    if (c) { /* ... remove extension ... */
07091       ret = ast_context_remove_extension_callerid2(c, extension, priority, callerid,
07092          matchcallerid, registrar, 0);
07093       ast_unlock_contexts();
07094    }
07095 
07096    return ret;
07097 }
07098 
07099 /*!
07100  * \brief This functionc locks given context, search for the right extension and
07101  * fires out all peer in this extensions with given priority. If priority
07102  * is set to 0, all peers are removed. After that, unlock context and
07103  * return.
07104  * \note When do you want to call this function, make sure that &conlock is locked,
07105  * because some process can handle with your *con context before you lock
07106  * it.
07107  *
07108  */
07109 int ast_context_remove_extension2(struct ast_context *con, const char *extension, int priority, const char *registrar, int already_locked)
07110 {
07111    return ast_context_remove_extension_callerid2(con, extension, priority, NULL, AST_EXT_MATCHCID_ANY, registrar, already_locked);
07112 }
07113 
07114 int ast_context_remove_extension_callerid2(struct ast_context *con, const char *extension, int priority, const char *callerid, int matchcallerid, const char *registrar, int already_locked)
07115 {
07116    struct ast_exten *exten, *prev_exten = NULL;
07117    struct ast_exten *peer;
07118    struct ast_exten ex, *exten2, *exten3;
07119    char dummy_name[1024];
07120    struct ast_exten *previous_peer = NULL;
07121    struct ast_exten *next_peer = NULL;
07122    int found = 0;
07123 
07124    if (!already_locked)
07125       ast_wrlock_context(con);
07126 
07127 #ifdef NEED_DEBUG
07128    ast_verb(3,"Removing %s/%s/%d%s%s from trees, registrar=%s\n", con->name, extension, priority, matchcallerid ? "/" : "", matchcallerid ? callerid : "", registrar);
07129 #endif
07130 #ifdef CONTEXT_DEBUG
07131    check_contexts(__FILE__, __LINE__);
07132 #endif
07133    /* find this particular extension */
07134    ex.exten = dummy_name;
07135    ex.matchcid = matchcallerid;
07136    ex.cidmatch = callerid;
07137    ast_copy_string(dummy_name, extension, sizeof(dummy_name));
07138    exten = ast_hashtab_lookup(con->root_table, &ex);
07139    if (exten) {
07140       if (priority == 0) {
07141          exten2 = ast_hashtab_remove_this_object(con->root_table, exten);
07142          if (!exten2)
07143             ast_log(LOG_ERROR,"Trying to delete the exten %s from context %s, but could not remove from the root_table\n", extension, con->name);
07144          if (con->pattern_tree) {
07145             struct match_char *x = add_exten_to_pattern_tree(con, exten, 1);
07146 
07147             if (x->exten) { /* this test for safety purposes */
07148                x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */
07149                x->exten = 0; /* get rid of what will become a bad pointer */
07150             } else {
07151                ast_log(LOG_WARNING,"Trying to delete an exten from a context, but the pattern tree node returned isn't a full extension\n");
07152             }
07153          }
07154       } else {
07155          ex.priority = priority;
07156          exten2 = ast_hashtab_lookup(exten->peer_table, &ex);
07157          if (exten2) {
07158             if (exten2->label) { /* if this exten has a label, remove that, too */
07159                exten3 = ast_hashtab_remove_this_object(exten->peer_label_table,exten2);
07160                if (!exten3)
07161                   ast_log(LOG_ERROR,"Did not remove this priority label (%d/%s) from the peer_label_table of context %s, extension %s!\n", priority, exten2->label, con->name, exten2->exten);
07162             }
07163 
07164             exten3 = ast_hashtab_remove_this_object(exten->peer_table, exten2);
07165             if (!exten3)
07166                ast_log(LOG_ERROR,"Did not remove this priority (%d) from the peer_table of context %s, extension %s!\n", priority, con->name, exten2->exten);
07167             if (exten2 == exten && exten2->peer) {
07168                exten2 = ast_hashtab_remove_this_object(con->root_table, exten);
07169                ast_hashtab_insert_immediate(con->root_table, exten2->peer);
07170             }
07171             if (ast_hashtab_size(exten->peer_table) == 0) {
07172                /* well, if the last priority of an exten is to be removed,
07173                   then, the extension is removed, too! */
07174                exten3 = ast_hashtab_remove_this_object(con->root_table, exten);
07175                if (!exten3)
07176                   ast_log(LOG_ERROR,"Did not remove this exten (%s) from the context root_table (%s) (priority %d)\n", exten->exten, con->name, priority);
07177                if (con->pattern_tree) {
07178                   struct match_char *x = add_exten_to_pattern_tree(con, exten, 1);
07179                   if (x->exten) { /* this test for safety purposes */
07180                      x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */
07181                      x->exten = 0; /* get rid of what will become a bad pointer */
07182                   }
07183                }
07184             }
07185          } else {
07186             ast_log(LOG_ERROR,"Could not find priority %d of exten %s in context %s!\n",
07187                   priority, exten->exten, con->name);
07188          }
07189       }
07190    } else {
07191       /* hmmm? this exten is not in this pattern tree? */
07192       ast_log(LOG_WARNING,"Cannot find extension %s in root_table in context %s\n",
07193             extension, con->name);
07194    }
07195 #ifdef NEED_DEBUG
07196    if (con->pattern_tree) {
07197       ast_log(LOG_NOTICE,"match char tree after exten removal:\n");
07198       log_match_char_tree(con->pattern_tree, " ");
07199    }
07200 #endif
07201 
07202    /* scan the extension list to find first matching extension-registrar */
07203    for (exten = con->root; exten; prev_exten = exten, exten = exten->next) {
07204       if (!strcmp(exten->exten, extension) &&
07205          (!registrar || !strcmp(exten->registrar, registrar)) &&
07206          (!matchcallerid || (!ast_strlen_zero(callerid) && !ast_strlen_zero(exten->cidmatch) && !strcmp(exten->cidmatch, callerid)) || (ast_strlen_zero(callerid) && ast_strlen_zero(exten->cidmatch))))
07207          break;
07208    }
07209    if (!exten) {
07210       /* we can't find right extension */
07211       if (!already_locked)
07212          ast_unlock_context(con);
07213       return -1;
07214    }
07215 
07216    /* scan the priority list to remove extension with exten->priority == priority */
07217    for (peer = exten, next_peer = exten->peer ? exten->peer : exten->next;
07218        peer && !strcmp(peer->exten, extension) &&
07219          (!callerid || (!matchcallerid && !peer->matchcid) || (matchcallerid && peer->matchcid && !strcmp(peer->cidmatch, callerid))) ;
07220          peer = next_peer, next_peer = next_peer ? (next_peer->peer ? next_peer->peer : next_peer->next) : NULL) {
07221 
07222       if ((priority == 0 || peer->priority == priority) &&
07223             (!registrar || !strcmp(peer->registrar, registrar) )) {
07224          found = 1;
07225 
07226          /* we are first priority extension? */
07227          if (!previous_peer) {
07228             /*
07229              * We are first in the priority chain, so must update the extension chain.
07230              * The next node is either the next priority or the next extension
07231              */
07232             struct ast_exten *next_node = peer->peer ? peer->peer : peer->next;
07233             if (peer->peer) {
07234                /* move the peer_table and peer_label_table down to the next peer, if
07235                   it is there */
07236                peer->peer->peer_table = peer->peer_table;
07237                peer->peer->peer_label_table = peer->peer_label_table;
07238                peer->peer_table = NULL;
07239                peer->peer_label_table = NULL;
07240             }
07241             if (!prev_exten) {   /* change the root... */
07242                con->root = next_node;
07243             } else {
07244                prev_exten->next = next_node; /* unlink */
07245             }
07246             if (peer->peer)   { /* update the new head of the pri list */
07247                peer->peer->next = peer->next;
07248             }
07249          } else { /* easy, we are not first priority in extension */
07250             previous_peer->peer = peer->peer;
07251          }
07252 
07253 
07254          /* now, free whole priority extension */
07255          destroy_exten(peer);
07256       } else {
07257          previous_peer = peer;
07258       }
07259    }
07260    if (!already_locked)
07261       ast_unlock_context(con);
07262    return found ? 0 : -1;
07263 }
07264 
07265 
07266 /*!
07267  * \note This function locks contexts list by &conlist, searches for the right context
07268  * structure, and locks the macrolock mutex in that context.
07269  * macrolock is used to limit a macro to be executed by one call at a time.
07270  */
07271 int ast_context_lockmacro(const char *context)
07272 {
07273    struct ast_context *c;
07274    int ret = -1;
07275 
07276    c = find_context_locked(context);
07277    if (c) {
07278       ast_unlock_contexts();
07279 
07280       /* if we found context, lock macrolock */
07281       ret = ast_mutex_lock(&c->macrolock);
07282    }
07283 
07284    return ret;
07285 }
07286 
07287 /*!
07288  * \note This function locks contexts list by &conlist, searches for the right context
07289  * structure, and unlocks the macrolock mutex in that context.
07290  * macrolock is used to limit a macro to be executed by one call at a time.
07291  */
07292 int ast_context_unlockmacro(const char *context)
07293 {
07294    struct ast_context *c;
07295    int ret = -1;
07296 
07297    c = find_context_locked(context);
07298    if (c) {
07299       ast_unlock_contexts();
07300 
07301       /* if we found context, unlock macrolock */
07302       ret = ast_mutex_unlock(&c->macrolock);
07303    }
07304 
07305    return ret;
07306 }
07307 
07308 /*! \brief Dynamically register a new dial plan application */
07309 int ast_register_application2(const char *app, int (*execute)(struct ast_channel *, const char *), const char *synopsis, const char *description, void *mod)
07310 {
07311    struct ast_app *tmp, *cur = NULL;
07312    char tmps[80];
07313    int length, res;
07314 #ifdef AST_XML_DOCS
07315    char *tmpxml;
07316 #endif
07317 
07318    AST_RWLIST_WRLOCK(&apps);
07319    AST_RWLIST_TRAVERSE(&apps, tmp, list) {
07320       if (!(res = strcasecmp(app, tmp->name))) {
07321          ast_log(LOG_WARNING, "Already have an application '%s'\n", app);
07322          AST_RWLIST_UNLOCK(&apps);
07323          return -1;
07324       } else if (res < 0)
07325          break;
07326    }
07327 
07328    length = sizeof(*tmp) + strlen(app) + 1;
07329 
07330    if (!(tmp = ast_calloc(1, length))) {
07331       AST_RWLIST_UNLOCK(&apps);
07332       return -1;
07333    }
07334 
07335    if (ast_string_field_init(tmp, 128)) {
07336       AST_RWLIST_UNLOCK(&apps);
07337       ast_free(tmp);
07338       return -1;
07339    }
07340 
07341    strcpy(tmp->name, app);
07342    tmp->execute = execute;
07343    tmp->module = mod;
07344 
07345 #ifdef AST_XML_DOCS
07346    /* Try to lookup the docs in our XML documentation database */
07347    if (ast_strlen_zero(synopsis) && ast_strlen_zero(description)) {
07348       /* load synopsis */
07349       tmpxml = ast_xmldoc_build_synopsis("application", app, ast_module_name(tmp->module));
07350       ast_string_field_set(tmp, synopsis, tmpxml);
07351       ast_free(tmpxml);
07352 
07353       /* load description */
07354       tmpxml = ast_xmldoc_build_description("application", app, ast_module_name(tmp->module));
07355       ast_string_field_set(tmp, description, tmpxml);
07356       ast_free(tmpxml);
07357 
07358       /* load syntax */
07359       tmpxml = ast_xmldoc_build_syntax("application", app, ast_module_name(tmp->module));
07360       ast_string_field_set(tmp, syntax, tmpxml);
07361       ast_free(tmpxml);
07362 
07363       /* load arguments */
07364       tmpxml = ast_xmldoc_build_arguments("application", app, ast_module_name(tmp->module));
07365       ast_string_field_set(tmp, arguments, tmpxml);
07366       ast_free(tmpxml);
07367 
07368       /* load seealso */
07369       tmpxml = ast_xmldoc_build_seealso("application", app, ast_module_name(tmp->module));
07370       ast_string_field_set(tmp, seealso, tmpxml);
07371       ast_free(tmpxml);
07372       tmp->docsrc = AST_XML_DOC;
07373    } else {
07374 #endif
07375       ast_string_field_set(tmp, synopsis, synopsis);
07376       ast_string_field_set(tmp, description, description);
07377 #ifdef AST_XML_DOCS
07378       tmp->docsrc = AST_STATIC_DOC;
07379    }
07380 #endif
07381 
07382    /* Store in alphabetical order */
07383    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&apps, cur, list) {
07384       if (strcasecmp(tmp->name, cur->name) < 0) {
07385          AST_RWLIST_INSERT_BEFORE_CURRENT(tmp, list);
07386          break;
07387       }
07388    }
07389    AST_RWLIST_TRAVERSE_SAFE_END;
07390    if (!cur)
07391       AST_RWLIST_INSERT_TAIL(&apps, tmp, list);
07392 
07393    ast_verb(2, "Registered application '%s'\n", term_color(tmps, tmp->name, COLOR_BRCYAN, 0, sizeof(tmps)));
07394 
07395    AST_RWLIST_UNLOCK(&apps);
07396 
07397    return 0;
07398 }
07399 
07400 /*
07401  * Append to the list. We don't have a tail pointer because we need
07402  * to scan the list anyways to check for duplicates during insertion.
07403  */
07404 int ast_register_switch(struct ast_switch *sw)
07405 {
07406    struct ast_switch *tmp;
07407 
07408    AST_RWLIST_WRLOCK(&switches);
07409    AST_RWLIST_TRAVERSE(&switches, tmp, list) {
07410       if (!strcasecmp(tmp->name, sw->name)) {
07411          AST_RWLIST_UNLOCK(&switches);
07412          ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name);
07413          return -1;
07414       }
07415    }
07416    AST_RWLIST_INSERT_TAIL(&switches, sw, list);
07417    AST_RWLIST_UNLOCK(&switches);
07418 
07419    return 0;
07420 }
07421 
07422 void ast_unregister_switch(struct ast_switch *sw)
07423 {
07424    AST_RWLIST_WRLOCK(&switches);
07425    AST_RWLIST_REMOVE(&switches, sw, list);
07426    AST_RWLIST_UNLOCK(&switches);
07427 }
07428 
07429 /*
07430  * Help for CLI commands ...
07431  */
07432 
07433 static void print_app_docs(struct ast_app *aa, int fd)
07434 {
07435    /* Maximum number of characters added by terminal coloring is 22 */
07436    char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40], stxtitle[40], argtitle[40];
07437    char seealsotitle[40];
07438    char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL, *syntax = NULL, *arguments = NULL;
07439    char *seealso = NULL;
07440    int syntax_size, synopsis_size, description_size, arguments_size, seealso_size;
07441 
07442    snprintf(info, sizeof(info), "\n  -= Info about application '%s' =- \n\n", aa->name);
07443    term_color(infotitle, info, COLOR_MAGENTA, 0, sizeof(infotitle));
07444 
07445    term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40);
07446    term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40);
07447    term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, 40);
07448    term_color(argtitle, "[Arguments]\n", COLOR_MAGENTA, 0, 40);
07449    term_color(seealsotitle, "[See Also]\n", COLOR_MAGENTA, 0, 40);
07450 
07451 #ifdef AST_XML_DOCS
07452    if (aa->docsrc == AST_XML_DOC) {
07453       description = ast_xmldoc_printable(S_OR(aa->description, "Not available"), 1);
07454       arguments = ast_xmldoc_printable(S_OR(aa->arguments, "Not available"), 1);
07455       synopsis = ast_xmldoc_printable(S_OR(aa->synopsis, "Not available"), 1);
07456       seealso = ast_xmldoc_printable(S_OR(aa->seealso, "Not available"), 1);
07457 
07458       if (!synopsis || !description || !arguments || !seealso) {
07459          goto return_cleanup;
07460       }
07461    } else
07462 #endif
07463    {
07464       synopsis_size = strlen(S_OR(aa->synopsis, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
07465       synopsis = ast_malloc(synopsis_size);
07466 
07467       description_size = strlen(S_OR(aa->description, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
07468       description = ast_malloc(description_size);
07469 
07470       arguments_size = strlen(S_OR(aa->arguments, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
07471       arguments = ast_malloc(arguments_size);
07472 
07473       seealso_size = strlen(S_OR(aa->seealso, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
07474       seealso = ast_malloc(seealso_size);
07475 
07476       if (!synopsis || !description || !arguments || !seealso) {
07477          goto return_cleanup;
07478       }
07479 
07480       term_color(synopsis, S_OR(aa->synopsis, "Not available"), COLOR_CYAN, 0, synopsis_size);
07481       term_color(description, S_OR(aa->description, "Not available"),   COLOR_CYAN, 0, description_size);
07482       term_color(arguments, S_OR(aa->arguments, "Not available"), COLOR_CYAN, 0, arguments_size);
07483       term_color(seealso, S_OR(aa->seealso, "Not available"), COLOR_CYAN, 0, seealso_size);
07484    }
07485 
07486    /* Handle the syntax the same for both XML and raw docs */
07487    syntax_size = strlen(S_OR(aa->syntax, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
07488    if (!(syntax = ast_malloc(syntax_size))) {
07489       goto return_cleanup;
07490    }
07491    term_color(syntax, S_OR(aa->syntax, "Not available"), COLOR_CYAN, 0, syntax_size);
07492 
07493    ast_cli(fd, "%s%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n",
07494          infotitle, syntitle, synopsis, destitle, description,
07495          stxtitle, syntax, argtitle, arguments, seealsotitle, seealso);
07496 
07497 return_cleanup:
07498    ast_free(description);
07499    ast_free(arguments);
07500    ast_free(synopsis);
07501    ast_free(seealso);
07502    ast_free(syntax);
07503 }
07504 
07505 /*
07506  * \brief 'show application' CLI command implementation function...
07507  */
07508 static char *handle_show_application(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
07509 {
07510    struct ast_app *aa;
07511    int app, no_registered_app = 1;
07512 
07513    switch (cmd) {
07514    case CLI_INIT:
07515       e->command = "core show application";
07516       e->usage =
07517          "Usage: core show application <application> [<application> [<application> [...]]]\n"
07518          "       Describes a particular application.\n";
07519       return NULL;
07520    case CLI_GENERATE:
07521       /*
07522        * There is a possibility to show informations about more than one
07523        * application at one time. You can type 'show application Dial Echo' and
07524        * you will see informations about these two applications ...
07525        */
07526       return ast_complete_applications(a->line, a->word, a->n);
07527    }
07528 
07529    if (a->argc < 4) {
07530       return CLI_SHOWUSAGE;
07531    }
07532 
07533    AST_RWLIST_RDLOCK(&apps);
07534    AST_RWLIST_TRAVERSE(&apps, aa, list) {
07535       /* Check for each app that was supplied as an argument */
07536       for (app = 3; app < a->argc; app++) {
07537          if (strcasecmp(aa->name, a->argv[app])) {
07538             continue;
07539          }
07540 
07541          /* We found it! */
07542          no_registered_app = 0;
07543 
07544          print_app_docs(aa, a->fd);
07545       }
07546    }
07547    AST_RWLIST_UNLOCK(&apps);
07548 
07549    /* we found at least one app? no? */
07550    if (no_registered_app) {
07551       ast_cli(a->fd, "Your application(s) is (are) not registered\n");
07552       return CLI_FAILURE;
07553    }
07554 
07555    return CLI_SUCCESS;
07556 }
07557 
07558 /*! \brief  handle_show_hints: CLI support for listing registered dial plan hints */
07559 static char *handle_show_hints(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
07560 {
07561    struct ast_hint *hint;
07562    int num = 0;
07563    int watchers;
07564    struct ao2_iterator i;
07565 
07566    switch (cmd) {
07567    case CLI_INIT:
07568       e->command = "core show hints";
07569       e->usage =
07570          "Usage: core show hints\n"
07571          "       List registered hints\n";
07572       return NULL;
07573    case CLI_GENERATE:
07574       return NULL;
07575    }
07576 
07577    if (ao2_container_count(hints) == 0) {
07578       ast_cli(a->fd, "There are no registered dialplan hints\n");
07579       return CLI_SUCCESS;
07580    }
07581    /* ... we have hints ... */
07582    ast_cli(a->fd, "\n    -= Registered Asterisk Dial Plan Hints =-\n");
07583 
07584    i = ao2_iterator_init(hints, 0);
07585    for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) {
07586       ao2_lock(hint);
07587       if (!hint->exten) {
07588          /* The extension has already been destroyed */
07589          ao2_unlock(hint);
07590          continue;
07591       }
07592       watchers = ao2_container_count(hint->callbacks);
07593       ast_cli(a->fd, "   %20s@%-20.20s: %-20.20s  State:%-15.15s Watchers %2d\n",
07594          ast_get_extension_name(hint->exten),
07595          ast_get_context_name(ast_get_extension_context(hint->exten)),
07596          ast_get_extension_app(hint->exten),
07597          ast_extension_state2str(hint->laststate), watchers);
07598       ao2_unlock(hint);
07599       num++;
07600    }
07601    ao2_iterator_destroy(&i);
07602 
07603    ast_cli(a->fd, "----------------\n");
07604    ast_cli(a->fd, "- %d hints registered\n", num);
07605    return CLI_SUCCESS;
07606 }
07607 
07608 /*! \brief autocomplete for CLI command 'core show hint' */
07609 static char *complete_core_show_hint(const char *line, const char *word, int pos, int state)
07610 {
07611    struct ast_hint *hint;
07612    char *ret = NULL;
07613    int which = 0;
07614    int wordlen;
07615    struct ao2_iterator i;
07616 
07617    if (pos != 3)
07618       return NULL;
07619 
07620    wordlen = strlen(word);
07621 
07622    /* walk through all hints */
07623    i = ao2_iterator_init(hints, 0);
07624    for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) {
07625       ao2_lock(hint);
07626       if (!hint->exten) {
07627          /* The extension has already been destroyed */
07628          ao2_unlock(hint);
07629          continue;
07630       }
07631       if (!strncasecmp(word, ast_get_extension_name(hint->exten), wordlen) && ++which > state) {
07632          ret = ast_strdup(ast_get_extension_name(hint->exten));
07633          ao2_unlock(hint);
07634          ao2_ref(hint, -1);
07635          break;
07636       }
07637       ao2_unlock(hint);
07638    }
07639    ao2_iterator_destroy(&i);
07640 
07641    return ret;
07642 }
07643 
07644 /*! \brief  handle_show_hint: CLI support for listing registered dial plan hint */
07645 static char *handle_show_hint(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
07646 {
07647    struct ast_hint *hint;
07648    int watchers;
07649    int num = 0, extenlen;
07650    struct ao2_iterator i;
07651 
07652    switch (cmd) {
07653    case CLI_INIT:
07654       e->command = "core show hint";
07655       e->usage =
07656          "Usage: core show hint <exten>\n"
07657          "       List registered hint\n";
07658       return NULL;
07659    case CLI_GENERATE:
07660       return complete_core_show_hint(a->line, a->word, a->pos, a->n);
07661    }
07662 
07663    if (a->argc < 4)
07664       return CLI_SHOWUSAGE;
07665 
07666    if (ao2_container_count(hints) == 0) {
07667       ast_cli(a->fd, "There are no registered dialplan hints\n");
07668       return CLI_SUCCESS;
07669    }
07670 
07671    extenlen = strlen(a->argv[3]);
07672    i = ao2_iterator_init(hints, 0);
07673    for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) {
07674       ao2_lock(hint);
07675       if (!hint->exten) {
07676          /* The extension has already been destroyed */
07677          ao2_unlock(hint);
07678          continue;
07679       }
07680       if (!strncasecmp(ast_get_extension_name(hint->exten), a->argv[3], extenlen)) {
07681          watchers = ao2_container_count(hint->callbacks);
07682          ast_cli(a->fd, "   %20s@%-20.20s: %-20.20s  State:%-15.15s Watchers %2d\n",
07683             ast_get_extension_name(hint->exten),
07684             ast_get_context_name(ast_get_extension_context(hint->exten)),
07685             ast_get_extension_app(hint->exten),
07686             ast_extension_state2str(hint->laststate), watchers);
07687          num++;
07688       }
07689       ao2_unlock(hint);
07690    }
07691    ao2_iterator_destroy(&i);
07692    if (!num)
07693       ast_cli(a->fd, "No hints matching extension %s\n", a->argv[3]);
07694    else
07695       ast_cli(a->fd, "%d hint%s matching extension %s\n", num, (num!=1 ? "s":""), a->argv[3]);
07696    return CLI_SUCCESS;
07697 }
07698 
07699 
07700 /*! \brief  handle_show_switches: CLI support for listing registered dial plan switches */
07701 static char *handle_show_switches(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
07702 {
07703    struct ast_switch *sw;
07704 
07705    switch (cmd) {
07706    case CLI_INIT:
07707       e->command = "core show switches";
07708       e->usage =
07709          "Usage: core show switches\n"
07710          "       List registered switches\n";
07711       return NULL;
07712    case CLI_GENERATE:
07713       return NULL;
07714    }
07715 
07716    AST_RWLIST_RDLOCK(&switches);
07717 
07718    if (AST_RWLIST_EMPTY(&switches)) {
07719       AST_RWLIST_UNLOCK(&switches);
07720       ast_cli(a->fd, "There are no registered alternative switches\n");
07721       return CLI_SUCCESS;
07722    }
07723 
07724    ast_cli(a->fd, "\n    -= Registered Asterisk Alternative Switches =-\n");
07725    AST_RWLIST_TRAVERSE(&switches, sw, list)
07726       ast_cli(a->fd, "%s: %s\n", sw->name, sw->description);
07727 
07728    AST_RWLIST_UNLOCK(&switches);
07729 
07730    return CLI_SUCCESS;
07731 }
07732 
07733 static char *handle_show_applications(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
07734 {
07735    struct ast_app *aa;
07736    int like = 0, describing = 0;
07737    int total_match = 0;    /* Number of matches in like clause */
07738    int total_apps = 0;     /* Number of apps registered */
07739    static const char * const choices[] = { "like", "describing", NULL };
07740 
07741    switch (cmd) {
07742    case CLI_INIT:
07743       e->command = "core show applications [like|describing]";
07744       e->usage =
07745          "Usage: core show applications [{like|describing} <text>]\n"
07746          "       List applications which are currently available.\n"
07747          "       If 'like', <text> will be a substring of the app name\n"
07748          "       If 'describing', <text> will be a substring of the description\n";
07749       return NULL;
07750    case CLI_GENERATE:
07751       return (a->pos != 3) ? NULL : ast_cli_complete(a->word, choices, a->n);
07752    }
07753 
07754    AST_RWLIST_RDLOCK(&apps);
07755 
07756    if (AST_RWLIST_EMPTY(&apps)) {
07757       ast_cli(a->fd, "There are no registered applications\n");
07758       AST_RWLIST_UNLOCK(&apps);
07759       return CLI_SUCCESS;
07760    }
07761 
07762    /* core list applications like <keyword> */
07763    if ((a->argc == 5) && (!strcmp(a->argv[3], "like"))) {
07764       like = 1;
07765    } else if ((a->argc > 4) && (!strcmp(a->argv[3], "describing"))) {
07766       describing = 1;
07767    }
07768 
07769    /* core list applications describing <keyword1> [<keyword2>] [...] */
07770    if ((!like) && (!describing)) {
07771       ast_cli(a->fd, "    -= Registered Asterisk Applications =-\n");
07772    } else {
07773       ast_cli(a->fd, "    -= Matching Asterisk Applications =-\n");
07774    }
07775 
07776    AST_RWLIST_TRAVERSE(&apps, aa, list) {
07777       int printapp = 0;
07778       total_apps++;
07779       if (like) {
07780          if (strcasestr(aa->name, a->argv[4])) {
07781             printapp = 1;
07782             total_match++;
07783          }
07784       } else if (describing) {
07785          if (aa->description) {
07786             /* Match all words on command line */
07787             int i;
07788             printapp = 1;
07789             for (i = 4; i < a->argc; i++) {
07790                if (!strcasestr(aa->description, a->argv[i])) {
07791                   printapp = 0;
07792                } else {
07793                   total_match++;
07794                }
07795             }
07796          }
07797       } else {
07798          printapp = 1;
07799       }
07800 
07801       if (printapp) {
07802          ast_cli(a->fd,"  %20s: %s\n", aa->name, aa->synopsis ? aa->synopsis : "<Synopsis not available>");
07803       }
07804    }
07805    if ((!like) && (!describing)) {
07806       ast_cli(a->fd, "    -= %d Applications Registered =-\n",total_apps);
07807    } else {
07808       ast_cli(a->fd, "    -= %d Applications Matching =-\n",total_match);
07809    }
07810 
07811    AST_RWLIST_UNLOCK(&apps);
07812 
07813    return CLI_SUCCESS;
07814 }
07815 
07816 /*
07817  * 'show dialplan' CLI command implementation functions ...
07818  */
07819 static char *complete_show_dialplan_context(const char *line, const char *word, int pos,
07820    int state)
07821 {
07822    struct ast_context *c = NULL;
07823    char *ret = NULL;
07824    int which = 0;
07825    int wordlen;
07826 
07827    /* we are do completion of [exten@]context on second position only */
07828    if (pos != 2)
07829       return NULL;
07830 
07831    ast_rdlock_contexts();
07832 
07833    wordlen = strlen(word);
07834 
07835    /* walk through all contexts and return the n-th match */
07836    while ( (c = ast_walk_contexts(c)) ) {
07837       if (!strncasecmp(word, ast_get_context_name(c), wordlen) && ++which > state) {
07838          ret = ast_strdup(ast_get_context_name(c));
07839          break;
07840       }
07841    }
07842 
07843    ast_unlock_contexts();
07844 
07845    return ret;
07846 }
07847 
07848 /*! \brief Counters for the show dialplan manager command */
07849 struct dialplan_counters {
07850    int total_items;
07851    int total_context;
07852    int total_exten;
07853    int total_prio;
07854    int context_existence;
07855    int extension_existence;
07856 };
07857 
07858 /*! \brief helper function to print an extension */
07859 static void print_ext(struct ast_exten *e, char * buf, int buflen)
07860 {
07861    int prio = ast_get_extension_priority(e);
07862    if (prio == PRIORITY_HINT) {
07863       snprintf(buf, buflen, "hint: %s",
07864          ast_get_extension_app(e));
07865    } else {
07866       snprintf(buf, buflen, "%d. %s(%s)",
07867          prio, ast_get_extension_app(e),
07868          (!ast_strlen_zero(ast_get_extension_app_data(e)) ? (char *)ast_get_extension_app_data(e) : ""));
07869    }
07870 }
07871 
07872 /* XXX not verified */
07873 static int show_dialplan_helper(int fd, const char *context, const char *exten, struct dialplan_counters *dpc, struct ast_include *rinclude, int includecount, const char *includes[])
07874 {
07875    struct ast_context *c = NULL;
07876    int res = 0, old_total_exten = dpc->total_exten;
07877 
07878    ast_rdlock_contexts();
07879 
07880    /* walk all contexts ... */
07881    while ( (c = ast_walk_contexts(c)) ) {
07882       struct ast_exten *e;
07883       struct ast_include *i;
07884       struct ast_ignorepat *ip;
07885       char buf[256], buf2[256];
07886       int context_info_printed = 0;
07887 
07888       if (context && strcmp(ast_get_context_name(c), context))
07889          continue;   /* skip this one, name doesn't match */
07890 
07891       dpc->context_existence = 1;
07892 
07893       ast_rdlock_context(c);
07894 
07895       /* are we looking for exten too? if yes, we print context
07896        * only if we find our extension.
07897        * Otherwise print context even if empty ?
07898        * XXX i am not sure how the rinclude is handled.
07899        * I think it ought to go inside.
07900        */
07901       if (!exten) {
07902          dpc->total_context++;
07903          ast_cli(fd, "[ Context '%s' created by '%s' ]\n",
07904             ast_get_context_name(c), ast_get_context_registrar(c));
07905          context_info_printed = 1;
07906       }
07907 
07908       /* walk extensions ... */
07909       e = NULL;
07910       while ( (e = ast_walk_context_extensions(c, e)) ) {
07911          struct ast_exten *p;
07912 
07913          if (exten && !ast_extension_match(ast_get_extension_name(e), exten))
07914             continue;   /* skip, extension match failed */
07915 
07916          dpc->extension_existence = 1;
07917 
07918          /* may we print context info? */
07919          if (!context_info_printed) {
07920             dpc->total_context++;
07921             if (rinclude) { /* TODO Print more info about rinclude */
07922                ast_cli(fd, "[ Included context '%s' created by '%s' ]\n",
07923                   ast_get_context_name(c), ast_get_context_registrar(c));
07924             } else {
07925                ast_cli(fd, "[ Context '%s' created by '%s' ]\n",
07926                   ast_get_context_name(c), ast_get_context_registrar(c));
07927             }
07928             context_info_printed = 1;
07929          }
07930          dpc->total_prio++;
07931 
07932          /* write extension name and first peer */
07933          if (e->matchcid == AST_EXT_MATCHCID_ON)
07934             snprintf(buf, sizeof(buf), "'%s' (CID match '%s') => ", ast_get_extension_name(e), e->cidmatch);
07935          else
07936             snprintf(buf, sizeof(buf), "'%s' =>", ast_get_extension_name(e));
07937 
07938          print_ext(e, buf2, sizeof(buf2));
07939 
07940          ast_cli(fd, "  %-17s %-45s [%s]\n", buf, buf2,
07941             ast_get_extension_registrar(e));
07942 
07943          dpc->total_exten++;
07944          /* walk next extension peers */
07945          p = e;   /* skip the first one, we already got it */
07946          while ( (p = ast_walk_extension_priorities(e, p)) ) {
07947             const char *el = ast_get_extension_label(p);
07948             dpc->total_prio++;
07949             if (el)
07950                snprintf(buf, sizeof(buf), "   [%s]", el);
07951             else
07952                buf[0] = '\0';
07953             print_ext(p, buf2, sizeof(buf2));
07954 
07955             ast_cli(fd,"  %-17s %-45s [%s]\n", buf, buf2,
07956                ast_get_extension_registrar(p));
07957          }
07958       }
07959 
07960       /* walk included and write info ... */
07961       i = NULL;
07962       while ( (i = ast_walk_context_includes(c, i)) ) {
07963          snprintf(buf, sizeof(buf), "'%s'", ast_get_include_name(i));
07964          if (exten) {
07965             /* Check all includes for the requested extension */
07966             if (includecount >= AST_PBX_MAX_STACK) {
07967                ast_log(LOG_WARNING, "Maximum include depth exceeded!\n");
07968             } else {
07969                int dupe = 0;
07970                int x;
07971                for (x = 0; x < includecount; x++) {
07972                   if (!strcasecmp(includes[x], ast_get_include_name(i))) {
07973                      dupe++;
07974                      break;
07975                   }
07976                }
07977                if (!dupe) {
07978                   includes[includecount] = ast_get_include_name(i);
07979                   show_dialplan_helper(fd, ast_get_include_name(i), exten, dpc, i, includecount + 1, includes);
07980                } else {
07981                   ast_log(LOG_WARNING, "Avoiding circular include of %s within %s\n", ast_get_include_name(i), context);
07982                }
07983             }
07984          } else {
07985             ast_cli(fd, "  Include =>        %-45s [%s]\n",
07986                buf, ast_get_include_registrar(i));
07987          }
07988       }
07989 
07990       /* walk ignore patterns and write info ... */
07991       ip = NULL;
07992       while ( (ip = ast_walk_context_ignorepats(c, ip)) ) {
07993          const char *ipname = ast_get_ignorepat_name(ip);
07994          char ignorepat[AST_MAX_EXTENSION];
07995          snprintf(buf, sizeof(buf), "'%s'", ipname);
07996          snprintf(ignorepat, sizeof(ignorepat), "_%s.", ipname);
07997          if (!exten || ast_extension_match(ignorepat, exten)) {
07998             ast_cli(fd, "  Ignore pattern => %-45s [%s]\n",
07999                buf, ast_get_ignorepat_registrar(ip));
08000          }
08001       }
08002       if (!rinclude) {
08003          struct ast_sw *sw = NULL;
08004          while ( (sw = ast_walk_context_switches(c, sw)) ) {
08005             snprintf(buf, sizeof(buf), "'%s/%s'",
08006                ast_get_switch_name(sw),
08007                ast_get_switch_data(sw));
08008             ast_cli(fd, "  Alt. Switch =>    %-45s [%s]\n",
08009                buf, ast_get_switch_registrar(sw));
08010          }
08011       }
08012 
08013       ast_unlock_context(c);
08014 
08015       /* if we print something in context, make an empty line */
08016       if (context_info_printed)
08017          ast_cli(fd, "\n");
08018    }
08019    ast_unlock_contexts();
08020 
08021    return (dpc->total_exten == old_total_exten) ? -1 : res;
08022 }
08023 
08024 static int show_debug_helper(int fd, const char *context, const char *exten, struct dialplan_counters *dpc, struct ast_include *rinclude, int includecount, const char *includes[])
08025 {
08026    struct ast_context *c = NULL;
08027    int res = 0, old_total_exten = dpc->total_exten;
08028 
08029    ast_cli(fd,"\n     In-mem exten Trie for Fast Extension Pattern Matching:\n\n");
08030 
08031    ast_cli(fd,"\n           Explanation: Node Contents Format = <char(s) to match>:<pattern?>:<specif>:[matched extension]\n");
08032    ast_cli(fd,    "                        Where <char(s) to match> is a set of chars, any one of which should match the current character\n");
08033    ast_cli(fd,    "                              <pattern?>: Y if this a pattern match (eg. _XZN[5-7]), N otherwise\n");
08034    ast_cli(fd,    "                              <specif>: an assigned 'exactness' number for this matching char. The lower the number, the more exact the match\n");
08035    ast_cli(fd,    "                              [matched exten]: If all chars matched to this point, which extension this matches. In form: EXTEN:<exten string>\n");
08036    ast_cli(fd,    "                        In general, you match a trie node to a string character, from left to right. All possible matching chars\n");
08037    ast_cli(fd,    "                        are in a string vertically, separated by an unbroken string of '+' characters.\n\n");
08038    ast_rdlock_contexts();
08039 
08040    /* walk all contexts ... */
08041    while ( (c = ast_walk_contexts(c)) ) {
08042       int context_info_printed = 0;
08043 
08044       if (context && strcmp(ast_get_context_name(c), context))
08045          continue;   /* skip this one, name doesn't match */
08046 
08047       dpc->context_existence = 1;
08048 
08049       if (!c->pattern_tree) {
08050          /* Ignore check_return warning from Coverity for ast_exists_extension below */
08051          ast_exists_extension(NULL, c->name, "s", 1, ""); /* do this to force the trie to built, if it is not already */
08052       }
08053 
08054       ast_rdlock_context(c);
08055 
08056       dpc->total_context++;
08057       ast_cli(fd, "[ Context '%s' created by '%s' ]\n",
08058          ast_get_context_name(c), ast_get_context_registrar(c));
08059       context_info_printed = 1;
08060 
08061       if (c->pattern_tree)
08062       {
08063          cli_match_char_tree(c->pattern_tree, " ", fd);
08064       } else {
08065          ast_cli(fd,"\n     No Pattern Trie present. Perhaps the context is empty...or there is trouble...\n\n");
08066       }
08067 
08068       ast_unlock_context(c);
08069 
08070       /* if we print something in context, make an empty line */
08071       if (context_info_printed)
08072          ast_cli(fd, "\n");
08073    }
08074    ast_unlock_contexts();
08075 
08076    return (dpc->total_exten == old_total_exten) ? -1 : res;
08077 }
08078 
08079 static char *handle_show_dialplan(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
08080 {
08081    char *exten = NULL, *context = NULL;
08082    /* Variables used for different counters */
08083    struct dialplan_counters counters;
08084    const char *incstack[AST_PBX_MAX_STACK];
08085 
08086    switch (cmd) {
08087    case CLI_INIT:
08088       e->command = "dialplan show";
08089       e->usage =
08090          "Usage: dialplan show [[exten@]context]\n"
08091          "       Show dialplan\n";
08092       return NULL;
08093    case CLI_GENERATE:
08094       return complete_show_dialplan_context(a->line, a->word, a->pos, a->n);
08095    }
08096 
08097    memset(&counters, 0, sizeof(counters));
08098 
08099    if (a->argc != 2 && a->argc != 3)
08100       return CLI_SHOWUSAGE;
08101 
08102    /* we obtain [exten@]context? if yes, split them ... */
08103    if (a->argc == 3) {
08104       if (strchr(a->argv[2], '@')) {   /* split into exten & context */
08105          context = ast_strdupa(a->argv[2]);
08106          exten = strsep(&context, "@");
08107          /* change empty strings to NULL */
08108          if (ast_strlen_zero(exten))
08109             exten = NULL;
08110       } else { /* no '@' char, only context given */
08111          context = ast_strdupa(a->argv[2]);
08112       }
08113       if (ast_strlen_zero(context))
08114          context = NULL;
08115    }
08116    /* else Show complete dial plan, context and exten are NULL */
08117    show_dialplan_helper(a->fd, context, exten, &counters, NULL, 0, incstack);
08118 
08119    /* check for input failure and throw some error messages */
08120    if (context && !counters.context_existence) {
08121       ast_cli(a->fd, "There is no existence of '%s' context\n", context);
08122       return CLI_FAILURE;
08123    }
08124 
08125    if (exten && !counters.extension_existence) {
08126       if (context)
08127          ast_cli(a->fd, "There is no existence of %s@%s extension\n",
08128             exten, context);
08129       else
08130          ast_cli(a->fd,
08131             "There is no existence of '%s' extension in all contexts\n",
08132             exten);
08133       return CLI_FAILURE;
08134    }
08135 
08136    ast_cli(a->fd,"-= %d %s (%d %s) in %d %s. =-\n",
08137             counters.total_exten, counters.total_exten == 1 ? "extension" : "extensions",
08138             counters.total_prio, counters.total_prio == 1 ? "priority" : "priorities",
08139             counters.total_context, counters.total_context == 1 ? "context" : "contexts");
08140 
08141    /* everything ok */
08142    return CLI_SUCCESS;
08143 }
08144 
08145 /*! \brief Send ack once */
08146 static char *handle_debug_dialplan(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
08147 {
08148    char *exten = NULL, *context = NULL;
08149    /* Variables used for different counters */
08150    struct dialplan_counters counters;
08151    const char *incstack[AST_PBX_MAX_STACK];
08152 
08153    switch (cmd) {
08154    case CLI_INIT:
08155       e->command = "dialplan debug";
08156       e->usage =
08157          "Usage: dialplan debug [context]\n"
08158          "       Show dialplan context Trie(s). Usually only useful to folks debugging the deep internals of the fast pattern matcher\n";
08159       return NULL;
08160    case CLI_GENERATE:
08161       return complete_show_dialplan_context(a->line, a->word, a->pos, a->n);
08162    }
08163 
08164    memset(&counters, 0, sizeof(counters));
08165 
08166    if (a->argc != 2 && a->argc != 3)
08167       return CLI_SHOWUSAGE;
08168 
08169    /* we obtain [exten@]context? if yes, split them ... */
08170    /* note: we ignore the exten totally here .... */
08171    if (a->argc == 3) {
08172       if (strchr(a->argv[2], '@')) {   /* split into exten & context */
08173          context = ast_strdupa(a->argv[2]);
08174          exten = strsep(&context, "@");
08175          /* change empty strings to NULL */
08176          if (ast_strlen_zero(exten))
08177             exten = NULL;
08178       } else { /* no '@' char, only context given */
08179          context = ast_strdupa(a->argv[2]);
08180       }
08181       if (ast_strlen_zero(context))
08182          context = NULL;
08183    }
08184    /* else Show complete dial plan, context and exten are NULL */
08185    show_debug_helper(a->fd, context, exten, &counters, NULL, 0, incstack);
08186 
08187    /* check for input failure and throw some error messages */
08188    if (context && !counters.context_existence) {
08189       ast_cli(a->fd, "There is no existence of '%s' context\n", context);
08190       return CLI_FAILURE;
08191    }
08192 
08193 
08194    ast_cli(a->fd,"-= %d %s. =-\n",
08195          counters.total_context, counters.total_context == 1 ? "context" : "contexts");
08196 
08197    /* everything ok */
08198    return CLI_SUCCESS;
08199 }
08200 
08201 /*! \brief Send ack once */
08202 static void manager_dpsendack(struct mansession *s, const struct message *m)
08203 {
08204    astman_send_listack(s, m, "DialPlan list will follow", "start");
08205 }
08206 
08207 /*! \brief Show dialplan extensions
08208  * XXX this function is similar but not exactly the same as the CLI's
08209  * show dialplan. Must check whether the difference is intentional or not.
08210  */
08211 static int manager_show_dialplan_helper(struct mansession *s, const struct message *m,
08212                const char *actionidtext, const char *context,
08213                const char *exten, struct dialplan_counters *dpc,
08214                struct ast_include *rinclude)
08215 {
08216    struct ast_context *c;
08217    int res = 0, old_total_exten = dpc->total_exten;
08218 
08219    if (ast_strlen_zero(exten))
08220       exten = NULL;
08221    if (ast_strlen_zero(context))
08222       context = NULL;
08223 
08224    ast_debug(3, "manager_show_dialplan: Context: -%s- Extension: -%s-\n", context, exten);
08225 
08226    /* try to lock contexts */
08227    if (ast_rdlock_contexts()) {
08228       astman_send_error(s, m, "Failed to lock contexts");
08229       ast_log(LOG_WARNING, "Failed to lock contexts list for manager: listdialplan\n");
08230       return -1;
08231    }
08232 
08233    c = NULL;      /* walk all contexts ... */
08234    while ( (c = ast_walk_contexts(c)) ) {
08235       struct ast_exten *e;
08236       struct ast_include *i;
08237       struct ast_ignorepat *ip;
08238 
08239       if (context && strcmp(ast_get_context_name(c), context) != 0)
08240          continue;   /* not the name we want */
08241 
08242       dpc->context_existence = 1;
08243       dpc->total_context++;
08244 
08245       ast_debug(3, "manager_show_dialplan: Found Context: %s \n", ast_get_context_name(c));
08246 
08247       if (ast_rdlock_context(c)) {  /* failed to lock */
08248          ast_debug(3, "manager_show_dialplan: Failed to lock context\n");
08249          continue;
08250       }
08251 
08252       /* XXX note- an empty context is not printed */
08253       e = NULL;      /* walk extensions in context  */
08254       while ( (e = ast_walk_context_extensions(c, e)) ) {
08255          struct ast_exten *p;
08256 
08257          /* looking for extension? is this our extension? */
08258          if (exten && !ast_extension_match(ast_get_extension_name(e), exten)) {
08259             /* not the one we are looking for, continue */
08260             ast_debug(3, "manager_show_dialplan: Skipping extension %s\n", ast_get_extension_name(e));
08261             continue;
08262          }
08263          ast_debug(3, "manager_show_dialplan: Found Extension: %s \n", ast_get_extension_name(e));
08264 
08265          dpc->extension_existence = 1;
08266 
08267          dpc->total_exten++;
08268 
08269          p = NULL;      /* walk next extension peers */
08270          while ( (p = ast_walk_extension_priorities(e, p)) ) {
08271             int prio = ast_get_extension_priority(p);
08272 
08273             dpc->total_prio++;
08274             if (!dpc->total_items++)
08275                manager_dpsendack(s, m);
08276             astman_append(s, "Event: ListDialplan\r\n%s", actionidtext);
08277             astman_append(s, "Context: %s\r\nExtension: %s\r\n", ast_get_context_name(c), ast_get_extension_name(e) );
08278 
08279             /* XXX maybe make this conditional, if p != e ? */
08280             if (ast_get_extension_label(p))
08281                astman_append(s, "ExtensionLabel: %s\r\n", ast_get_extension_label(p));
08282 
08283             if (prio == PRIORITY_HINT) {
08284                astman_append(s, "Priority: hint\r\nApplication: %s\r\n", ast_get_extension_app(p));
08285             } else {
08286                astman_append(s, "Priority: %d\r\nApplication: %s\r\nAppData: %s\r\n", prio, ast_get_extension_app(p), (char *) ast_get_extension_app_data(p));
08287             }
08288             astman_append(s, "Registrar: %s\r\n\r\n", ast_get_extension_registrar(e));
08289          }
08290       }
08291 
08292       i = NULL;      /* walk included and write info ... */
08293       while ( (i = ast_walk_context_includes(c, i)) ) {
08294          if (exten) {
08295             /* Check all includes for the requested extension */
08296             manager_show_dialplan_helper(s, m, actionidtext, ast_get_include_name(i), exten, dpc, i);
08297          } else {
08298             if (!dpc->total_items++)
08299                manager_dpsendack(s, m);
08300             astman_append(s, "Event: ListDialplan\r\n%s", actionidtext);
08301             astman_append(s, "Context: %s\r\nIncludeContext: %s\r\nRegistrar: %s\r\n", ast_get_context_name(c), ast_get_include_name(i), ast_get_include_registrar(i));
08302             astman_append(s, "\r\n");
08303             ast_debug(3, "manager_show_dialplan: Found Included context: %s \n", ast_get_include_name(i));
08304          }
08305       }
08306 
08307       ip = NULL;  /* walk ignore patterns and write info ... */
08308       while ( (ip = ast_walk_context_ignorepats(c, ip)) ) {
08309          const char *ipname = ast_get_ignorepat_name(ip);
08310          char ignorepat[AST_MAX_EXTENSION];
08311 
08312          snprintf(ignorepat, sizeof(ignorepat), "_%s.", ipname);
08313          if (!exten || ast_extension_match(ignorepat, exten)) {
08314             if (!dpc->total_items++)
08315                manager_dpsendack(s, m);
08316             astman_append(s, "Event: ListDialplan\r\n%s", actionidtext);
08317             astman_append(s, "Context: %s\r\nIgnorePattern: %s\r\nRegistrar: %s\r\n", ast_get_context_name(c), ipname, ast_get_ignorepat_registrar(ip));
08318             astman_append(s, "\r\n");
08319          }
08320       }
08321       if (!rinclude) {
08322          struct ast_sw *sw = NULL;
08323          while ( (sw = ast_walk_context_switches(c, sw)) ) {
08324             if (!dpc->total_items++)
08325                manager_dpsendack(s, m);
08326             astman_append(s, "Event: ListDialplan\r\n%s", actionidtext);
08327             astman_append(s, "Context: %s\r\nSwitch: %s/%s\r\nRegistrar: %s\r\n", ast_get_context_name(c), ast_get_switch_name(sw), ast_get_switch_data(sw), ast_get_switch_registrar(sw));
08328             astman_append(s, "\r\n");
08329             ast_debug(3, "manager_show_dialplan: Found Switch : %s \n", ast_get_switch_name(sw));
08330          }
08331       }
08332 
08333       ast_unlock_context(c);
08334    }
08335    ast_unlock_contexts();
08336 
08337    if (dpc->total_exten == old_total_exten) {
08338       ast_debug(3, "manager_show_dialplan: Found nothing new\n");
08339       /* Nothing new under the sun */
08340       return -1;
08341    } else {
08342       return res;
08343    }
08344 }
08345 
08346 /*! \brief  Manager listing of dial plan */
08347 static int manager_show_dialplan(struct mansession *s, const struct message *m)
08348 {
08349    const char *exten, *context;
08350    const char *id = astman_get_header(m, "ActionID");
08351    char idtext[256];
08352 
08353    /* Variables used for different counters */
08354    struct dialplan_counters counters;
08355 
08356    if (!ast_strlen_zero(id))
08357       snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id);
08358    else
08359       idtext[0] = '\0';
08360 
08361    memset(&counters, 0, sizeof(counters));
08362 
08363    exten = astman_get_header(m, "Extension");
08364    context = astman_get_header(m, "Context");
08365 
08366    manager_show_dialplan_helper(s, m, idtext, context, exten, &counters, NULL);
08367 
08368    if (!ast_strlen_zero(context) && !counters.context_existence) {
08369       char errorbuf[BUFSIZ];
08370 
08371       snprintf(errorbuf, sizeof(errorbuf), "Did not find context %s", context);
08372       astman_send_error(s, m, errorbuf);
08373       return 0;
08374    }
08375    if (!ast_strlen_zero(exten) && !counters.extension_existence) {
08376       char errorbuf[BUFSIZ];
08377 
08378       if (!ast_strlen_zero(context))
08379          snprintf(errorbuf, sizeof(errorbuf), "Did not find extension %s@%s", exten, context);
08380       else
08381          snprintf(errorbuf, sizeof(errorbuf), "Did not find extension %s in any context", exten);
08382       astman_send_error(s, m, errorbuf);
08383       return 0;
08384    }
08385 
08386    if (!counters.total_items) {
08387       manager_dpsendack(s, m);
08388    }
08389 
08390    astman_append(s, "Event: ShowDialPlanComplete\r\n"
08391       "EventList: Complete\r\n"
08392       "ListItems: %d\r\n"
08393       "ListExtensions: %d\r\n"
08394       "ListPriorities: %d\r\n"
08395       "ListContexts: %d\r\n"
08396       "%s"
08397       "\r\n", counters.total_items, counters.total_exten, counters.total_prio, counters.total_context, idtext);
08398 
08399    /* everything ok */
08400    return 0;
08401 }
08402 
08403 /*! \brief CLI support for listing global variables in a parseable way */
08404 static char *handle_show_globals(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
08405 {
08406    int i = 0;
08407    struct ast_var_t *newvariable;
08408 
08409    switch (cmd) {
08410    case CLI_INIT:
08411       e->command = "dialplan show globals";
08412       e->usage =
08413          "Usage: dialplan show globals\n"
08414          "       List current global dialplan variables and their values\n";
08415       return NULL;
08416    case CLI_GENERATE:
08417       return NULL;
08418    }
08419 
08420    ast_rwlock_rdlock(&globalslock);
08421    AST_LIST_TRAVERSE (&globals, newvariable, entries) {
08422       i++;
08423       ast_cli(a->fd, "   %s=%s\n", ast_var_name(newvariable), ast_var_value(newvariable));
08424    }
08425    ast_rwlock_unlock(&globalslock);
08426    ast_cli(a->fd, "\n    -- %d variable(s)\n", i);
08427 
08428    return CLI_SUCCESS;
08429 }
08430 
08431 #ifdef AST_DEVMODE
08432 static char *handle_show_device2extenstate(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
08433 {
08434    struct ast_devstate_aggregate agg;
08435    int i, j, exten, combined;
08436 
08437    switch (cmd) {
08438    case CLI_INIT:
08439       e->command = "core show device2extenstate";
08440       e->usage =
08441          "Usage: core show device2extenstate\n"
08442          "       Lists device state to extension state combinations.\n";
08443    case CLI_GENERATE:
08444       return NULL;
08445    }
08446    for (i = 0; i < AST_DEVICE_TOTAL; i++) {
08447       for (j = 0; j < AST_DEVICE_TOTAL; j++) {
08448          ast_devstate_aggregate_init(&agg);
08449          ast_devstate_aggregate_add(&agg, i);
08450          ast_devstate_aggregate_add(&agg, j);
08451          combined = ast_devstate_aggregate_result(&agg);
08452          exten = ast_devstate_to_extenstate(combined);
08453          ast_cli(a->fd, "\n Exten:%14s  CombinedDevice:%12s  Dev1:%12s  Dev2:%12s", ast_extension_state2str(exten), ast_devstate_str(combined), ast_devstate_str(j), ast_devstate_str(i));
08454       }
08455    }
08456    ast_cli(a->fd, "\n");
08457    return CLI_SUCCESS;
08458 }
08459 #endif
08460 
08461 /*! \brief CLI support for listing chanvar's variables in a parseable way */
08462 static char *handle_show_chanvar(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
08463 {
08464    struct ast_channel *chan = NULL;
08465    struct ast_str *vars = ast_str_alloca(BUFSIZ * 4); /* XXX large because we might have lots of channel vars */
08466 
08467    switch (cmd) {
08468    case CLI_INIT:
08469       e->command = "dialplan show chanvar";
08470       e->usage =
08471          "Usage: dialplan show chanvar <channel>\n"
08472          "       List current channel variables and their values\n";
08473       return NULL;
08474    case CLI_GENERATE:
08475       return ast_complete_channels(a->line, a->word, a->pos, a->n, 3);
08476    }
08477 
08478    if (a->argc != e->args + 1)
08479       return CLI_SHOWUSAGE;
08480 
08481    if (!(chan = ast_channel_get_by_name(a->argv[e->args]))) {
08482       ast_cli(a->fd, "Channel '%s' not found\n", a->argv[e->args]);
08483       return CLI_FAILURE;
08484    }
08485 
08486    pbx_builtin_serialize_variables(chan, &vars);
08487 
08488    if (ast_str_strlen(vars)) {
08489       ast_cli(a->fd, "\nVariables for channel %s:\n%s\n", a->argv[e->args], ast_str_buffer(vars));
08490    }
08491 
08492    chan = ast_channel_unref(chan);
08493 
08494    return CLI_SUCCESS;
08495 }
08496 
08497 static char *handle_set_global(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
08498 {
08499    switch (cmd) {
08500    case CLI_INIT:
08501       e->command = "dialplan set global";
08502       e->usage =
08503          "Usage: dialplan set global <name> <value>\n"
08504          "       Set global dialplan variable <name> to <value>\n";
08505       return NULL;
08506    case CLI_GENERATE:
08507       return NULL;
08508    }
08509 
08510    if (a->argc != e->args + 2)
08511       return CLI_SHOWUSAGE;
08512 
08513    pbx_builtin_setvar_helper(NULL, a->argv[3], a->argv[4]);
08514    ast_cli(a->fd, "\n    -- Global variable '%s' set to '%s'\n", a->argv[3], a->argv[4]);
08515 
08516    return CLI_SUCCESS;
08517 }
08518 
08519 static char *handle_set_chanvar(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
08520 {
08521    struct ast_channel *chan;
08522    const char *chan_name, *var_name, *var_value;
08523 
08524    switch (cmd) {
08525    case CLI_INIT:
08526       e->command = "dialplan set chanvar";
08527       e->usage =
08528          "Usage: dialplan set chanvar <channel> <varname> <value>\n"
08529          "       Set channel variable <varname> to <value>\n";
08530       return NULL;
08531    case CLI_GENERATE:
08532       return ast_complete_channels(a->line, a->word, a->pos, a->n, 3);
08533    }
08534 
08535    if (a->argc != e->args + 3)
08536       return CLI_SHOWUSAGE;
08537 
08538    chan_name = a->argv[e->args];
08539    var_name = a->argv[e->args + 1];
08540    var_value = a->argv[e->args + 2];
08541 
08542    if (!(chan = ast_channel_get_by_name(chan_name))) {
08543       ast_cli(a->fd, "Channel '%s' not found\n", chan_name);
08544       return CLI_FAILURE;
08545    }
08546 
08547    pbx_builtin_setvar_helper(chan, var_name, var_value);
08548 
08549    chan = ast_channel_unref(chan);
08550 
08551    ast_cli(a->fd, "\n    -- Channel variable '%s' set to '%s' for '%s'\n",  var_name, var_value, chan_name);
08552 
08553    return CLI_SUCCESS;
08554 }
08555 
08556 static char *handle_set_extenpatternmatchnew(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
08557 {
08558    int oldval = 0;
08559 
08560    switch (cmd) {
08561    case CLI_INIT:
08562       e->command = "dialplan set extenpatternmatchnew true";
08563       e->usage =
08564          "Usage: dialplan set extenpatternmatchnew true|false\n"
08565          "       Use the NEW extension pattern matching algorithm, true or false.\n";
08566       return NULL;
08567    case CLI_GENERATE:
08568       return NULL;
08569    }
08570 
08571    if (a->argc != 4)
08572       return CLI_SHOWUSAGE;
08573 
08574    oldval =  pbx_set_extenpatternmatchnew(1);
08575 
08576    if (oldval)
08577       ast_cli(a->fd, "\n    -- Still using the NEW pattern match algorithm for extension names in the dialplan.\n");
08578    else
08579       ast_cli(a->fd, "\n    -- Switched to using the NEW pattern match algorithm for extension names in the dialplan.\n");
08580 
08581    return CLI_SUCCESS;
08582 }
08583 
08584 static char *handle_unset_extenpatternmatchnew(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
08585 {
08586    int oldval = 0;
08587 
08588    switch (cmd) {
08589    case CLI_INIT:
08590       e->command = "dialplan set extenpatternmatchnew false";
08591       e->usage =
08592          "Usage: dialplan set extenpatternmatchnew true|false\n"
08593          "       Use the NEW extension pattern matching algorithm, true or false.\n";
08594       return NULL;
08595    case CLI_GENERATE:
08596       return NULL;
08597    }
08598 
08599    if (a->argc != 4)
08600       return CLI_SHOWUSAGE;
08601 
08602    oldval =  pbx_set_extenpatternmatchnew(0);
08603 
08604    if (!oldval)
08605       ast_cli(a->fd, "\n    -- Still using the OLD pattern match algorithm for extension names in the dialplan.\n");
08606    else
08607       ast_cli(a->fd, "\n    -- Switched to using the OLD pattern match algorithm for extension names in the dialplan.\n");
08608 
08609    return CLI_SUCCESS;
08610 }
08611 
08612 /*
08613  * CLI entries for upper commands ...
08614  */
08615 static struct ast_cli_entry pbx_cli[] = {
08616    AST_CLI_DEFINE(handle_show_applications, "Shows registered dialplan applications"),
08617    AST_CLI_DEFINE(handle_show_functions, "Shows registered dialplan functions"),
08618    AST_CLI_DEFINE(handle_show_switches, "Show alternative switches"),
08619    AST_CLI_DEFINE(handle_show_hints, "Show dialplan hints"),
08620    AST_CLI_DEFINE(handle_show_hint, "Show dialplan hint"),
08621    AST_CLI_DEFINE(handle_show_globals, "Show global dialplan variables"),
08622 #ifdef AST_DEVMODE
08623    AST_CLI_DEFINE(handle_show_device2extenstate, "Show expected exten state from multiple device states"),
08624 #endif
08625    AST_CLI_DEFINE(handle_show_chanvar, "Show channel variables"),
08626    AST_CLI_DEFINE(handle_show_function, "Describe a specific dialplan function"),
08627    AST_CLI_DEFINE(handle_show_hangup_all, "Show hangup handlers of all channels"),
08628    AST_CLI_DEFINE(handle_show_hangup_channel, "Show hangup handlers of a specified channel"),
08629    AST_CLI_DEFINE(handle_show_application, "Describe a specific dialplan application"),
08630    AST_CLI_DEFINE(handle_set_global, "Set global dialplan variable"),
08631    AST_CLI_DEFINE(handle_set_chanvar, "Set a channel variable"),
08632    AST_CLI_DEFINE(handle_show_dialplan, "Show dialplan"),
08633    AST_CLI_DEFINE(handle_debug_dialplan, "Show fast extension pattern matching data structures"),
08634    AST_CLI_DEFINE(handle_unset_extenpatternmatchnew, "Use the Old extension pattern matching algorithm."),
08635    AST_CLI_DEFINE(handle_set_extenpatternmatchnew, "Use the New extension pattern matching algorithm."),
08636 };
08637 
08638 static void unreference_cached_app(struct ast_app *app)
08639 {
08640    struct ast_context *context = NULL;
08641    struct ast_exten *eroot = NULL, *e = NULL;
08642 
08643    ast_rdlock_contexts();
08644    while ((context = ast_walk_contexts(context))) {
08645       while ((eroot = ast_walk_context_extensions(context, eroot))) {
08646          while ((e = ast_walk_extension_priorities(eroot, e))) {
08647             if (e->cached_app == app)
08648                e->cached_app = NULL;
08649          }
08650       }
08651    }
08652    ast_unlock_contexts();
08653 
08654    return;
08655 }
08656 
08657 int ast_unregister_application(const char *app)
08658 {
08659    struct ast_app *tmp;
08660 
08661    AST_RWLIST_WRLOCK(&apps);
08662    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&apps, tmp, list) {
08663       if (!strcasecmp(app, tmp->name)) {
08664          unreference_cached_app(tmp);
08665          AST_RWLIST_REMOVE_CURRENT(list);
08666          ast_verb(2, "Unregistered application '%s'\n", tmp->name);
08667          ast_string_field_free_memory(tmp);
08668          ast_free(tmp);
08669          break;
08670       }
08671    }
08672    AST_RWLIST_TRAVERSE_SAFE_END;
08673    AST_RWLIST_UNLOCK(&apps);
08674 
08675    return tmp ? 0 : -1;
08676 }
08677 
08678 struct ast_context *ast_context_find_or_create(struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *name, const char *registrar)
08679 {
08680    struct ast_context *tmp, **local_contexts;
08681    struct fake_context search;
08682    int length = sizeof(struct ast_context) + strlen(name) + 1;
08683 
08684    if (!contexts_table) {
08685       /* Protect creation of contexts_table from reentrancy. */
08686       ast_wrlock_contexts();
08687       if (!contexts_table) {
08688          contexts_table = ast_hashtab_create(17,
08689             ast_hashtab_compare_contexts,
08690             ast_hashtab_resize_java,
08691             ast_hashtab_newsize_java,
08692             ast_hashtab_hash_contexts,
08693             0);
08694       }
08695       ast_unlock_contexts();
08696    }
08697 
08698    ast_copy_string(search.name, name, sizeof(search.name));
08699    if (!extcontexts) {
08700       ast_rdlock_contexts();
08701       local_contexts = &contexts;
08702       tmp = ast_hashtab_lookup(contexts_table, &search);
08703       ast_unlock_contexts();
08704       if (tmp) {
08705          tmp->refcount++;
08706          return tmp;
08707       }
08708    } else { /* local contexts just in a linked list; search there for the new context; slow, linear search, but not frequent */
08709       local_contexts = extcontexts;
08710       tmp = ast_hashtab_lookup(exttable, &search);
08711       if (tmp) {
08712          tmp->refcount++;
08713          return tmp;
08714       }
08715    }
08716 
08717    if ((tmp = ast_calloc(1, length))) {
08718       ast_rwlock_init(&tmp->lock);
08719       ast_mutex_init(&tmp->macrolock);
08720       strcpy(tmp->name, name);
08721       tmp->root = NULL;
08722       tmp->root_table = NULL;
08723       tmp->registrar = ast_strdup(registrar);
08724       tmp->includes = NULL;
08725       tmp->ignorepats = NULL;
08726       tmp->refcount = 1;
08727    } else {
08728       ast_log(LOG_ERROR, "Danger! We failed to allocate a context for %s!\n", name);
08729       return NULL;
08730    }
08731 
08732    if (!extcontexts) {
08733       ast_wrlock_contexts();
08734       tmp->next = *local_contexts;
08735       *local_contexts = tmp;
08736       ast_hashtab_insert_safe(contexts_table, tmp); /*put this context into the tree */
08737       ast_unlock_contexts();
08738       ast_debug(1, "Registered context '%s'(%p) in table %p registrar: %s\n", tmp->name, tmp, contexts_table, registrar);
08739       ast_verb(3, "Registered extension context '%s'; registrar: %s\n", tmp->name, registrar);
08740    } else {
08741       tmp->next = *local_contexts;
08742       if (exttable)
08743          ast_hashtab_insert_immediate(exttable, tmp); /*put this context into the tree */
08744 
08745       *local_contexts = tmp;
08746       ast_debug(1, "Registered context '%s'(%p) in local table %p; registrar: %s\n", tmp->name, tmp, exttable, registrar);
08747       ast_verb(3, "Registered extension context '%s'; registrar: %s\n", tmp->name, registrar);
08748    }
08749    return tmp;
08750 }
08751 
08752 void __ast_context_destroy(struct ast_context *list, struct ast_hashtab *contexttab, struct ast_context *con, const char *registrar);
08753 
08754 struct store_hint {
08755    char *context;
08756    char *exten;
08757    AST_LIST_HEAD_NOLOCK(, ast_state_cb) callbacks;
08758    int laststate;
08759    int last_presence_state;
08760    char *last_presence_subtype;
08761    char *last_presence_message;
08762 
08763    AST_LIST_ENTRY(store_hint) list;
08764    char data[1];
08765 };
08766 
08767 AST_LIST_HEAD_NOLOCK(store_hints, store_hint);
08768 
08769 static void context_merge_incls_swits_igps_other_registrars(struct ast_context *new, struct ast_context *old, const char *registrar)
08770 {
08771    struct ast_include *i;
08772    struct ast_ignorepat *ip;
08773    struct ast_sw *sw;
08774 
08775    ast_verb(3, "merging incls/swits/igpats from old(%s) to new(%s) context, registrar = %s\n", ast_get_context_name(old), ast_get_context_name(new), registrar);
08776    /* copy in the includes, switches, and ignorepats */
08777    /* walk through includes */
08778    for (i = NULL; (i = ast_walk_context_includes(old, i)) ; ) {
08779       if (strcmp(ast_get_include_registrar(i), registrar) == 0)
08780          continue; /* not mine */
08781       ast_context_add_include2(new, ast_get_include_name(i), ast_get_include_registrar(i));
08782    }
08783 
08784    /* walk through switches */
08785    for (sw = NULL; (sw = ast_walk_context_switches(old, sw)) ; ) {
08786       if (strcmp(ast_get_switch_registrar(sw), registrar) == 0)
08787          continue; /* not mine */
08788       ast_context_add_switch2(new, ast_get_switch_name(sw), ast_get_switch_data(sw), ast_get_switch_eval(sw), ast_get_switch_registrar(sw));
08789    }
08790 
08791    /* walk thru ignorepats ... */
08792    for (ip = NULL; (ip = ast_walk_context_ignorepats(old, ip)); ) {
08793       if (strcmp(ast_get_ignorepat_registrar(ip), registrar) == 0)
08794          continue; /* not mine */
08795       ast_context_add_ignorepat2(new, ast_get_ignorepat_name(ip), ast_get_ignorepat_registrar(ip));
08796    }
08797 }
08798 
08799 
08800 /* the purpose of this routine is to duplicate a context, with all its substructure,
08801    except for any extens that have a matching registrar */
08802 static void context_merge(struct ast_context **extcontexts, struct ast_hashtab *exttable, struct ast_context *context, const char *registrar)
08803 {
08804    struct ast_context *new = ast_hashtab_lookup(exttable, context); /* is there a match in the new set? */
08805    struct ast_exten *exten_item, *prio_item, *new_exten_item, *new_prio_item;
08806    struct ast_hashtab_iter *exten_iter;
08807    struct ast_hashtab_iter *prio_iter;
08808    int insert_count = 0;
08809    int first = 1;
08810 
08811    /* We'll traverse all the extensions/prios, and see which are not registrar'd with
08812       the current registrar, and copy them to the new context. If the new context does not
08813       exist, we'll create it "on demand". If no items are in this context to copy, then we'll
08814       only create the empty matching context if the old one meets the criteria */
08815 
08816    if (context->root_table) {
08817       exten_iter = ast_hashtab_start_traversal(context->root_table);
08818       while ((exten_item=ast_hashtab_next(exten_iter))) {
08819          if (new) {
08820             new_exten_item = ast_hashtab_lookup(new->root_table, exten_item);
08821          } else {
08822             new_exten_item = NULL;
08823          }
08824          prio_iter = ast_hashtab_start_traversal(exten_item->peer_table);
08825          while ((prio_item=ast_hashtab_next(prio_iter))) {
08826             int res1;
08827             char *dupdstr;
08828 
08829             if (new_exten_item) {
08830                new_prio_item = ast_hashtab_lookup(new_exten_item->peer_table, prio_item);
08831             } else {
08832                new_prio_item = NULL;
08833             }
08834             if (strcmp(prio_item->registrar,registrar) == 0) {
08835                continue;
08836             }
08837             /* make sure the new context exists, so we have somewhere to stick this exten/prio */
08838             if (!new) {
08839                new = ast_context_find_or_create(extcontexts, exttable, context->name, prio_item->registrar); /* a new context created via priority from a different context in the old dialplan, gets its registrar from the prio's registrar */
08840             }
08841 
08842             /* copy in the includes, switches, and ignorepats */
08843             if (first) { /* but, only need to do this once */
08844                context_merge_incls_swits_igps_other_registrars(new, context, registrar);
08845                first = 0;
08846             }
08847 
08848             if (!new) {
08849                ast_log(LOG_ERROR,"Could not allocate a new context for %s in merge_and_delete! Danger!\n", context->name);
08850                ast_hashtab_end_traversal(prio_iter);
08851                ast_hashtab_end_traversal(exten_iter);
08852                return; /* no sense continuing. */
08853             }
08854             /* we will not replace existing entries in the new context with stuff from the old context.
08855                but, if this is because of some sort of registrar conflict, we ought to say something... */
08856 
08857             dupdstr = ast_strdup(prio_item->data);
08858 
08859             res1 = ast_add_extension2(new, 0, prio_item->exten, prio_item->priority, prio_item->label,
08860                                 prio_item->matchcid ? prio_item->cidmatch : NULL, prio_item->app, dupdstr, prio_item->datad, prio_item->registrar);
08861             if (!res1 && new_exten_item && new_prio_item){
08862                ast_verb(3,"Dropping old dialplan item %s/%s/%d [%s(%s)] (registrar=%s) due to conflict with new dialplan\n",
08863                      context->name, prio_item->exten, prio_item->priority, prio_item->app, (char*)prio_item->data, prio_item->registrar);
08864             } else {
08865                /* we do NOT pass the priority data from the old to the new -- we pass a copy of it, so no changes to the current dialplan take place,
08866                 and no double frees take place, either! */
08867                insert_count++;
08868             }
08869          }
08870          ast_hashtab_end_traversal(prio_iter);
08871       }
08872       ast_hashtab_end_traversal(exten_iter);
08873    }
08874 
08875    if (!insert_count && !new && (strcmp(context->registrar, registrar) != 0 ||
08876         (strcmp(context->registrar, registrar) == 0 && context->refcount > 1))) {
08877       /* we could have given it the registrar of the other module who incremented the refcount,
08878          but that's not available, so we give it the registrar we know about */
08879       new = ast_context_find_or_create(extcontexts, exttable, context->name, context->registrar);
08880 
08881       /* copy in the includes, switches, and ignorepats */
08882       context_merge_incls_swits_igps_other_registrars(new, context, registrar);
08883    }
08884 }
08885 
08886 
08887 /* XXX this does not check that multiple contexts are merged */
08888 void ast_merge_contexts_and_delete(struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *registrar)
08889 {
08890    double ft;
08891    struct ast_context *tmp;
08892    struct ast_context *oldcontextslist;
08893    struct ast_hashtab *oldtable;
08894    struct store_hints hints_stored = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
08895    struct store_hints hints_removed = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
08896    struct store_hint *saved_hint;
08897    struct ast_hint *hint;
08898    struct ast_exten *exten;
08899    int length;
08900    struct ast_state_cb *thiscb;
08901    struct ast_hashtab_iter *iter;
08902    struct ao2_iterator i;
08903    struct timeval begintime;
08904    struct timeval writelocktime;
08905    struct timeval endlocktime;
08906    struct timeval enddeltime;
08907 
08908    /*
08909     * It is very important that this function hold the hints
08910     * container lock _and_ the conlock during its operation; not
08911     * only do we need to ensure that the list of contexts and
08912     * extensions does not change, but also that no hint callbacks
08913     * (watchers) are added or removed during the merge/delete
08914     * process
08915     *
08916     * In addition, the locks _must_ be taken in this order, because
08917     * there are already other code paths that use this order
08918     */
08919 
08920    begintime = ast_tvnow();
08921    ast_mutex_lock(&context_merge_lock);/* Serialize ast_merge_contexts_and_delete */
08922    ast_wrlock_contexts();
08923 
08924    if (!contexts_table) {
08925       /* Well, that's odd. There are no contexts. */
08926       contexts_table = exttable;
08927       contexts = *extcontexts;
08928       ast_unlock_contexts();
08929       ast_mutex_unlock(&context_merge_lock);
08930       return;
08931    }
08932 
08933    iter = ast_hashtab_start_traversal(contexts_table);
08934    while ((tmp = ast_hashtab_next(iter))) {
08935       context_merge(extcontexts, exttable, tmp, registrar);
08936    }
08937    ast_hashtab_end_traversal(iter);
08938 
08939    ao2_lock(hints);
08940    writelocktime = ast_tvnow();
08941 
08942    /* preserve all watchers for hints */
08943    i = ao2_iterator_init(hints, AO2_ITERATOR_DONTLOCK);
08944    for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) {
08945       if (ao2_container_count(hint->callbacks)) {
08946          ao2_lock(hint);
08947          if (!hint->exten) {
08948             /* The extension has already been destroyed. (Should never happen here) */
08949             ao2_unlock(hint);
08950             continue;
08951          }
08952 
08953          length = strlen(hint->exten->exten) + strlen(hint->exten->parent->name) + 2
08954             + sizeof(*saved_hint);
08955          if (!(saved_hint = ast_calloc(1, length))) {
08956             ao2_unlock(hint);
08957             continue;
08958          }
08959 
08960          /* This removes all the callbacks from the hint into saved_hint. */
08961          while ((thiscb = ao2_callback(hint->callbacks, OBJ_UNLINK, NULL, NULL))) {
08962             AST_LIST_INSERT_TAIL(&saved_hint->callbacks, thiscb, entry);
08963             /*
08964              * We intentionally do not unref thiscb to account for the
08965              * non-ao2 reference in saved_hint->callbacks
08966              */
08967          }
08968 
08969          saved_hint->laststate = hint->laststate;
08970          saved_hint->context = saved_hint->data;
08971          strcpy(saved_hint->data, hint->exten->parent->name);
08972          saved_hint->exten = saved_hint->data + strlen(saved_hint->context) + 1;
08973          strcpy(saved_hint->exten, hint->exten->exten);
08974          if (hint->last_presence_subtype) {
08975             saved_hint->last_presence_subtype = ast_strdup(hint->last_presence_subtype);
08976          }
08977          if (hint->last_presence_message) {
08978             saved_hint->last_presence_message = ast_strdup(hint->last_presence_message);
08979          }
08980          saved_hint->last_presence_state = hint->last_presence_state;
08981          ao2_unlock(hint);
08982          AST_LIST_INSERT_HEAD(&hints_stored, saved_hint, list);
08983       }
08984    }
08985    ao2_iterator_destroy(&i);
08986 
08987    /* save the old table and list */
08988    oldtable = contexts_table;
08989    oldcontextslist = contexts;
08990 
08991    /* move in the new table and list */
08992    contexts_table = exttable;
08993    contexts = *extcontexts;
08994 
08995    /*
08996     * Restore the watchers for hints that can be found; notify
08997     * those that cannot be restored.
08998     */
08999    while ((saved_hint = AST_LIST_REMOVE_HEAD(&hints_stored, list))) {
09000       struct pbx_find_info q = { .stacklen = 0 };
09001 
09002       exten = pbx_find_extension(NULL, NULL, &q, saved_hint->context, saved_hint->exten,
09003          PRIORITY_HINT, NULL, "", E_MATCH);
09004       /*
09005        * If this is a pattern, dynamically create a new extension for this
09006        * particular match.  Note that this will only happen once for each
09007        * individual extension, because the pattern will no longer match first.
09008        */
09009       if (exten && exten->exten[0] == '_') {
09010          ast_add_extension_nolock(exten->parent->name, 0, saved_hint->exten,
09011             PRIORITY_HINT, NULL, 0, exten->app, ast_strdup(exten->data), ast_free_ptr,
09012             exten->registrar);
09013          /* rwlocks are not recursive locks */
09014          exten = ast_hint_extension_nolock(NULL, saved_hint->context,
09015             saved_hint->exten);
09016       }
09017 
09018       /* Find the hint in the hints container */
09019       hint = exten ? ao2_find(hints, exten, 0) : NULL;
09020       if (!hint) {
09021          /*
09022           * Notify watchers of this removed hint later when we aren't
09023           * encumberd by so many locks.
09024           */
09025          AST_LIST_INSERT_HEAD(&hints_removed, saved_hint, list);
09026       } else {
09027          ao2_lock(hint);
09028          while ((thiscb = AST_LIST_REMOVE_HEAD(&saved_hint->callbacks, entry))) {
09029             ao2_link(hint->callbacks, thiscb);
09030             /* Ref that we added when putting into saved_hint->callbacks */
09031             ao2_ref(thiscb, -1);
09032          }
09033          hint->laststate = saved_hint->laststate;
09034          hint->last_presence_state = saved_hint->last_presence_state;
09035          hint->last_presence_subtype = saved_hint->last_presence_subtype;
09036          hint->last_presence_message = saved_hint->last_presence_message;
09037          ao2_unlock(hint);
09038          ao2_ref(hint, -1);
09039          /*
09040           * The free of saved_hint->last_presence_subtype and
09041           * saved_hint->last_presence_message is not necessary here.
09042           */
09043          ast_free(saved_hint);
09044       }
09045    }
09046 
09047    ao2_unlock(hints);
09048    ast_unlock_contexts();
09049 
09050    /*
09051     * Notify watchers of all removed hints with the same lock
09052     * environment as handle_statechange().
09053     */
09054    while ((saved_hint = AST_LIST_REMOVE_HEAD(&hints_removed, list))) {
09055       /* this hint has been removed, notify the watchers */
09056       while ((thiscb = AST_LIST_REMOVE_HEAD(&saved_hint->callbacks, entry))) {
09057          execute_state_callback(thiscb->change_cb,
09058             saved_hint->context,
09059             saved_hint->exten,
09060             thiscb->data,
09061             AST_HINT_UPDATE_DEVICE,
09062             NULL,
09063             NULL);
09064          /* Ref that we added when putting into saved_hint->callbacks */
09065          ao2_ref(thiscb, -1);
09066       }
09067       ast_free(saved_hint->last_presence_subtype);
09068       ast_free(saved_hint->last_presence_message);
09069       ast_free(saved_hint);
09070    }
09071 
09072    ast_mutex_unlock(&context_merge_lock);
09073    endlocktime = ast_tvnow();
09074 
09075    /*
09076     * The old list and hashtab no longer are relevant, delete them
09077     * while the rest of asterisk is now freely using the new stuff
09078     * instead.
09079     */
09080 
09081    ast_hashtab_destroy(oldtable, NULL);
09082 
09083    for (tmp = oldcontextslist; tmp; ) {
09084       struct ast_context *next;  /* next starting point */
09085 
09086       next = tmp->next;
09087       __ast_internal_context_destroy(tmp);
09088       tmp = next;
09089    }
09090    enddeltime = ast_tvnow();
09091 
09092    ft = ast_tvdiff_us(writelocktime, begintime);
09093    ft /= 1000000.0;
09094    ast_verb(3,"Time to scan old dialplan and merge leftovers back into the new: %8.6f sec\n", ft);
09095 
09096    ft = ast_tvdiff_us(endlocktime, writelocktime);
09097    ft /= 1000000.0;
09098    ast_verb(3,"Time to restore hints and swap in new dialplan: %8.6f sec\n", ft);
09099 
09100    ft = ast_tvdiff_us(enddeltime, endlocktime);
09101    ft /= 1000000.0;
09102    ast_verb(3,"Time to delete the old dialplan: %8.6f sec\n", ft);
09103 
09104    ft = ast_tvdiff_us(enddeltime, begintime);
09105    ft /= 1000000.0;
09106    ast_verb(3,"Total time merge_contexts_delete: %8.6f sec\n", ft);
09107 }
09108 
09109 /*
09110  * errno values
09111  *  EBUSY  - can't lock
09112  *  ENOENT - no existence of context
09113  */
09114 int ast_context_add_include(const char *context, const char *include, const char *registrar)
09115 {
09116    int ret = -1;
09117    struct ast_context *c;
09118 
09119    c = find_context_locked(context);
09120    if (c) {
09121       ret = ast_context_add_include2(c, include, registrar);
09122       ast_unlock_contexts();
09123    }
09124    return ret;
09125 }
09126 
09127 /*! \brief Helper for get_range.
09128  * return the index of the matching entry, starting from 1.
09129  * If names is not supplied, try numeric values.
09130  */
09131 static int lookup_name(const char *s, const char * const names[], int max)
09132 {
09133    int i;
09134 
09135    if (names && *s > '9') {
09136       for (i = 0; names[i]; i++) {
09137          if (!strcasecmp(s, names[i])) {
09138             return i;
09139          }
09140       }
09141    }
09142 
09143    /* Allow months and weekdays to be specified as numbers, as well */
09144    if (sscanf(s, "%2d", &i) == 1 && i >= 1 && i <= max) {
09145       /* What the array offset would have been: "1" would be at offset 0 */
09146       return i - 1;
09147    }
09148    return -1; /* error return */
09149 }
09150 
09151 /*! \brief helper function to return a range up to max (7, 12, 31 respectively).
09152  * names, if supplied, is an array of names that should be mapped to numbers.
09153  */
09154 static unsigned get_range(char *src, int max, const char * const names[], const char *msg)
09155 {
09156    int start, end; /* start and ending position */
09157    unsigned int mask = 0;
09158    char *part;
09159 
09160    /* Check for whole range */
09161    if (ast_strlen_zero(src) || !strcmp(src, "*")) {
09162       return (1 << max) - 1;
09163    }
09164 
09165    while ((part = strsep(&src, "&"))) {
09166       /* Get start and ending position */
09167       char *endpart = strchr(part, '-');
09168       if (endpart) {
09169          *endpart++ = '\0';
09170       }
09171       /* Find the start */
09172       if ((start = lookup_name(part, names, max)) < 0) {
09173          ast_log(LOG_WARNING, "Invalid %s '%s', skipping element\n", msg, part);
09174          continue;
09175       }
09176       if (endpart) { /* find end of range */
09177          if ((end = lookup_name(endpart, names, max)) < 0) {
09178             ast_log(LOG_WARNING, "Invalid end %s '%s', skipping element\n", msg, endpart);
09179             continue;
09180          }
09181       } else {
09182          end = start;
09183       }
09184       /* Fill the mask. Remember that ranges are cyclic */
09185       mask |= (1 << end);   /* initialize with last element */
09186       while (start != end) {
09187          mask |= (1 << start);
09188          if (++start >= max) {
09189             start = 0;
09190          }
09191       }
09192    }
09193    return mask;
09194 }
09195 
09196 /*! \brief store a bitmask of valid times, one bit each 1 minute */
09197 static void get_timerange(struct ast_timing *i, char *times)
09198 {
09199    char *endpart, *part;
09200    int x;
09201    int st_h, st_m;
09202    int endh, endm;
09203    int minute_start, minute_end;
09204 
09205    /* start disabling all times, fill the fields with 0's, as they may contain garbage */
09206    memset(i->minmask, 0, sizeof(i->minmask));
09207 
09208    /* 1-minute per bit */
09209    /* Star is all times */
09210    if (ast_strlen_zero(times) || !strcmp(times, "*")) {
09211       /* 48, because each hour takes 2 integers; 30 bits each */
09212       for (x = 0; x < 48; x++) {
09213          i->minmask[x] = 0x3fffffff; /* 30 bits */
09214       }
09215       return;
09216    }
09217    /* Otherwise expect a range */
09218    while ((part = strsep(&times, "&"))) {
09219       if (!(endpart = strchr(part, '-'))) {
09220          if (sscanf(part, "%2d:%2d", &st_h, &st_m) != 2 || st_h < 0 || st_h > 23 || st_m < 0 || st_m > 59) {
09221             ast_log(LOG_WARNING, "%s isn't a valid time.\n", part);
09222             continue;
09223          }
09224          i->minmask[st_h * 2 + (st_m >= 30 ? 1 : 0)] |= (1 << (st_m % 30));
09225          continue;
09226       }
09227       *endpart++ = '\0';
09228       /* why skip non digits? Mostly to skip spaces */
09229       while (*endpart && !isdigit(*endpart)) {
09230          endpart++;
09231       }
09232       if (!*endpart) {
09233          ast_log(LOG_WARNING, "Invalid time range starting with '%s-'.\n", part);
09234          continue;
09235       }
09236       if (sscanf(part, "%2d:%2d", &st_h, &st_m) != 2 || st_h < 0 || st_h > 23 || st_m < 0 || st_m > 59) {
09237          ast_log(LOG_WARNING, "'%s' isn't a valid start time.\n", part);
09238          continue;
09239       }
09240       if (sscanf(endpart, "%2d:%2d", &endh, &endm) != 2 || endh < 0 || endh > 23 || endm < 0 || endm > 59) {
09241          ast_log(LOG_WARNING, "'%s' isn't a valid end time.\n", endpart);
09242          continue;
09243       }
09244       minute_start = st_h * 60 + st_m;
09245       minute_end = endh * 60 + endm;
09246       /* Go through the time and enable each appropriate bit */
09247       for (x = minute_start; x != minute_end; x = (x + 1) % (24 * 60)) {
09248          i->minmask[x / 30] |= (1 << (x % 30));
09249       }
09250       /* Do the last one */
09251       i->minmask[x / 30] |= (1 << (x % 30));
09252    }
09253    /* All done */
09254    return;
09255 }
09256 
09257 static const char * const days[] =
09258 {
09259    "sun",
09260    "mon",
09261    "tue",
09262    "wed",
09263    "thu",
09264    "fri",
09265    "sat",
09266    NULL,
09267 };
09268 
09269 static const char * const months[] =
09270 {
09271    "jan",
09272    "feb",
09273    "mar",
09274    "apr",
09275    "may",
09276    "jun",
09277    "jul",
09278    "aug",
09279    "sep",
09280    "oct",
09281    "nov",
09282    "dec",
09283    NULL,
09284 };
09285 
09286 int ast_build_timing(struct ast_timing *i, const char *info_in)
09287 {
09288    char *info;
09289    int j, num_fields, last_sep = -1;
09290 
09291    i->timezone = NULL;
09292 
09293    /* Check for empty just in case */
09294    if (ast_strlen_zero(info_in)) {
09295       return 0;
09296    }
09297 
09298    /* make a copy just in case we were passed a static string */
09299    info = ast_strdupa(info_in);
09300 
09301    /* count the number of fields in the timespec */
09302    for (j = 0, num_fields = 1; info[j] != '\0'; j++) {
09303       if (info[j] == ',') {
09304          last_sep = j;
09305          num_fields++;
09306       }
09307    }
09308 
09309    /* save the timezone, if it is specified */
09310    if (num_fields == 5) {
09311       i->timezone = ast_strdup(info + last_sep + 1);
09312    }
09313 
09314    /* Assume everything except time */
09315    i->monthmask = 0xfff;   /* 12 bits */
09316    i->daymask = 0x7fffffffU; /* 31 bits */
09317    i->dowmask = 0x7f; /* 7 bits */
09318    /* on each call, use strsep() to move info to the next argument */
09319    get_timerange(i, strsep(&info, "|,"));
09320    if (info)
09321       i->dowmask = get_range(strsep(&info, "|,"), 7, days, "day of week");
09322    if (info)
09323       i->daymask = get_range(strsep(&info, "|,"), 31, NULL, "day");
09324    if (info)
09325       i->monthmask = get_range(strsep(&info, "|,"), 12, months, "month");
09326    return 1;
09327 }
09328 
09329 int ast_check_timing(const struct ast_timing *i)
09330 {
09331    return ast_check_timing2(i, ast_tvnow());
09332 }
09333 
09334 int ast_check_timing2(const struct ast_timing *i, const struct timeval tv)
09335 {
09336    struct ast_tm tm;
09337 
09338    ast_localtime(&tv, &tm, i->timezone);
09339 
09340    /* If it's not the right month, return */
09341    if (!(i->monthmask & (1 << tm.tm_mon)))
09342       return 0;
09343 
09344    /* If it's not that time of the month.... */
09345    /* Warning, tm_mday has range 1..31! */
09346    if (!(i->daymask & (1 << (tm.tm_mday-1))))
09347       return 0;
09348 
09349    /* If it's not the right day of the week */
09350    if (!(i->dowmask & (1 << tm.tm_wday)))
09351       return 0;
09352 
09353    /* Sanity check the hour just to be safe */
09354    if ((tm.tm_hour < 0) || (tm.tm_hour > 23)) {
09355       ast_log(LOG_WARNING, "Insane time...\n");
09356       return 0;
09357    }
09358 
09359    /* Now the tough part, we calculate if it fits
09360       in the right time based on min/hour */
09361    if (!(i->minmask[tm.tm_hour * 2 + (tm.tm_min >= 30 ? 1 : 0)] & (1 << (tm.tm_min >= 30 ? tm.tm_min - 30 : tm.tm_min))))
09362       return 0;
09363 
09364    /* If we got this far, then we're good */
09365    return 1;
09366 }
09367 
09368 int ast_destroy_timing(struct ast_timing *i)
09369 {
09370    if (i->timezone) {
09371       ast_free(i->timezone);
09372       i->timezone = NULL;
09373    }
09374    return 0;
09375 }
09376 /*
09377  * errno values
09378  *  ENOMEM - out of memory
09379  *  EBUSY  - can't lock
09380  *  EEXIST - already included
09381  *  EINVAL - there is no existence of context for inclusion
09382  */
09383 int ast_context_add_include2(struct ast_context *con, const char *value,
09384    const char *registrar)
09385 {
09386    struct ast_include *new_include;
09387    char *c;
09388    struct ast_include *i, *il = NULL; /* include, include_last */
09389    int length;
09390    char *p;
09391 
09392    length = sizeof(struct ast_include);
09393    length += 2 * (strlen(value) + 1);
09394 
09395    /* allocate new include structure ... */
09396    if (!(new_include = ast_calloc(1, length)))
09397       return -1;
09398    /* Fill in this structure. Use 'p' for assignments, as the fields
09399     * in the structure are 'const char *'
09400     */
09401    p = new_include->stuff;
09402    new_include->name = p;
09403    strcpy(p, value);
09404    p += strlen(value) + 1;
09405    new_include->rname = p;
09406    strcpy(p, value);
09407    /* Strip off timing info, and process if it is there */
09408    if ( (c = strchr(p, ',')) ) {
09409       *c++ = '\0';
09410       new_include->hastime = ast_build_timing(&(new_include->timing), c);
09411    }
09412    new_include->next      = NULL;
09413    new_include->registrar = registrar;
09414 
09415    ast_wrlock_context(con);
09416 
09417    /* ... go to last include and check if context is already included too... */
09418    for (i = con->includes; i; i = i->next) {
09419       if (!strcasecmp(i->name, new_include->name)) {
09420          ast_destroy_timing(&(new_include->timing));
09421          ast_free(new_include);
09422          ast_unlock_context(con);
09423          errno = EEXIST;
09424          return -1;
09425       }
09426       il = i;
09427    }
09428 
09429    /* ... include new context into context list, unlock, return */
09430    if (il)
09431       il->next = new_include;
09432    else
09433       con->includes = new_include;
09434    ast_verb(3, "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con));
09435 
09436    ast_unlock_context(con);
09437 
09438    return 0;
09439 }
09440 
09441 /*
09442  * errno values
09443  *  EBUSY  - can't lock
09444  *  ENOENT - no existence of context
09445  */
09446 int ast_context_add_switch(const char *context, const char *sw, const char *data, int eval, const char *registrar)
09447 {
09448    int ret = -1;
09449    struct ast_context *c;
09450 
09451    c = find_context_locked(context);
09452    if (c) { /* found, add switch to this context */
09453       ret = ast_context_add_switch2(c, sw, data, eval, registrar);
09454       ast_unlock_contexts();
09455    }
09456    return ret;
09457 }
09458 
09459 /*
09460  * errno values
09461  *  ENOMEM - out of memory
09462  *  EBUSY  - can't lock
09463  *  EEXIST - already included
09464  *  EINVAL - there is no existence of context for inclusion
09465  */
09466 int ast_context_add_switch2(struct ast_context *con, const char *value,
09467    const char *data, int eval, const char *registrar)
09468 {
09469    struct ast_sw *new_sw;
09470    struct ast_sw *i;
09471    int length;
09472    char *p;
09473 
09474    length = sizeof(struct ast_sw);
09475    length += strlen(value) + 1;
09476    if (data)
09477       length += strlen(data);
09478    length++;
09479 
09480    /* allocate new sw structure ... */
09481    if (!(new_sw = ast_calloc(1, length)))
09482       return -1;
09483    /* ... fill in this structure ... */
09484    p = new_sw->stuff;
09485    new_sw->name = p;
09486    strcpy(new_sw->name, value);
09487    p += strlen(value) + 1;
09488    new_sw->data = p;
09489    if (data) {
09490       strcpy(new_sw->data, data);
09491       p += strlen(data) + 1;
09492    } else {
09493       strcpy(new_sw->data, "");
09494       p++;
09495    }
09496    new_sw->eval     = eval;
09497    new_sw->registrar = registrar;
09498 
09499    /* ... try to lock this context ... */
09500    ast_wrlock_context(con);
09501 
09502    /* ... go to last sw and check if context is already swd too... */
09503    AST_LIST_TRAVERSE(&con->alts, i, list) {
09504       if (!strcasecmp(i->name, new_sw->name) && !strcasecmp(i->data, new_sw->data)) {
09505          ast_free(new_sw);
09506          ast_unlock_context(con);
09507          errno = EEXIST;
09508          return -1;
09509       }
09510    }
09511 
09512    /* ... sw new context into context list, unlock, return */
09513    AST_LIST_INSERT_TAIL(&con->alts, new_sw, list);
09514 
09515    ast_verb(3, "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con));
09516 
09517    ast_unlock_context(con);
09518 
09519    return 0;
09520 }
09521 
09522 /*
09523  * EBUSY  - can't lock
09524  * ENOENT - there is not context existence
09525  */
09526 int ast_context_remove_ignorepat(const char *context, const char *ignorepat, const char *registrar)
09527 {
09528    int ret = -1;
09529    struct ast_context *c;
09530 
09531    c = find_context_locked(context);
09532    if (c) {
09533       ret = ast_context_remove_ignorepat2(c, ignorepat, registrar);
09534       ast_unlock_contexts();
09535    }
09536    return ret;
09537 }
09538 
09539 int ast_context_remove_ignorepat2(struct ast_context *con, const char *ignorepat, const char *registrar)
09540 {
09541    struct ast_ignorepat *ip, *ipl = NULL;
09542 
09543    ast_wrlock_context(con);
09544 
09545    for (ip = con->ignorepats; ip; ip = ip->next) {
09546       if (!strcmp(ip->pattern, ignorepat) &&
09547          (!registrar || (registrar == ip->registrar))) {
09548          if (ipl) {
09549             ipl->next = ip->next;
09550             ast_free(ip);
09551          } else {
09552             con->ignorepats = ip->next;
09553             ast_free(ip);
09554          }
09555          ast_unlock_context(con);
09556          return 0;
09557       }
09558       ipl = ip;
09559    }
09560 
09561    ast_unlock_context(con);
09562    errno = EINVAL;
09563    return -1;
09564 }
09565 
09566 /*
09567  * EBUSY - can't lock
09568  * ENOENT - there is no existence of context
09569  */
09570 int ast_context_add_ignorepat(const char *context, const char *value, const char *registrar)
09571 {
09572    int ret = -1;
09573    struct ast_context *c;
09574 
09575    c = find_context_locked(context);
09576    if (c) {
09577       ret = ast_context_add_ignorepat2(c, value, registrar);
09578       ast_unlock_contexts();
09579    }
09580    return ret;
09581 }
09582 
09583 int ast_context_add_ignorepat2(struct ast_context *con, const char *value, const char *registrar)
09584 {
09585    struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL;
09586    int length;
09587    char *pattern;
09588    length = sizeof(struct ast_ignorepat);
09589    length += strlen(value) + 1;
09590    if (!(ignorepat = ast_calloc(1, length)))
09591       return -1;
09592    /* The cast to char * is because we need to write the initial value.
09593     * The field is not supposed to be modified otherwise.  Also, gcc 4.2
09594     * sees the cast as dereferencing a type-punned pointer and warns about
09595     * it.  This is the workaround (we're telling gcc, yes, that's really
09596     * what we wanted to do).
09597     */
09598    pattern = (char *) ignorepat->pattern;
09599    strcpy(pattern, value);
09600    ignorepat->next = NULL;
09601    ignorepat->registrar = registrar;
09602    ast_wrlock_context(con);
09603    for (ignorepatc = con->ignorepats; ignorepatc; ignorepatc = ignorepatc->next) {
09604       ignorepatl = ignorepatc;
09605       if (!strcasecmp(ignorepatc->pattern, value)) {
09606          /* Already there */
09607          ast_unlock_context(con);
09608          ast_free(ignorepat);
09609          errno = EEXIST;
09610          return -1;
09611       }
09612    }
09613    if (ignorepatl)
09614       ignorepatl->next = ignorepat;
09615    else
09616       con->ignorepats = ignorepat;
09617    ast_unlock_context(con);
09618    return 0;
09619 
09620 }
09621 
09622 int ast_ignore_pattern(const char *context, const char *pattern)
09623 {
09624    struct ast_context *con = ast_context_find(context);
09625 
09626    if (con) {
09627       struct ast_ignorepat *pat;
09628 
09629       for (pat = con->ignorepats; pat; pat = pat->next) {
09630          if (ast_extension_match(pat->pattern, pattern))
09631             return 1;
09632       }
09633    }
09634 
09635    return 0;
09636 }
09637 
09638 /*
09639  * ast_add_extension_nolock -- use only in situations where the conlock is already held
09640  * ENOENT  - no existence of context
09641  *
09642  */
09643 static int ast_add_extension_nolock(const char *context, int replace, const char *extension,
09644    int priority, const char *label, const char *callerid,
09645    const char *application, void *data, void (*datad)(void *), const char *registrar)
09646 {
09647    int ret = -1;
09648    struct ast_context *c;
09649 
09650    c = find_context(context);
09651    if (c) {
09652       ret = ast_add_extension2_lockopt(c, replace, extension, priority, label, callerid,
09653          application, data, datad, registrar, 1);
09654    }
09655 
09656    return ret;
09657 }
09658 /*
09659  * EBUSY   - can't lock
09660  * ENOENT  - no existence of context
09661  *
09662  */
09663 int ast_add_extension(const char *context, int replace, const char *extension,
09664    int priority, const char *label, const char *callerid,
09665    const char *application, void *data, void (*datad)(void *), const char *registrar)
09666 {
09667    int ret = -1;
09668    struct ast_context *c;
09669 
09670    c = find_context_locked(context);
09671    if (c) {
09672       ret = ast_add_extension2(c, replace, extension, priority, label, callerid,
09673          application, data, datad, registrar);
09674       ast_unlock_contexts();
09675    }
09676 
09677    return ret;
09678 }
09679 
09680 int ast_explicit_goto(struct ast_channel *chan, const char *context, const char *exten, int priority)
09681 {
09682    if (!chan)
09683       return -1;
09684 
09685    ast_channel_lock(chan);
09686 
09687    if (!ast_strlen_zero(context))
09688       ast_channel_context_set(chan, context);
09689    if (!ast_strlen_zero(exten))
09690       ast_channel_exten_set(chan, exten);
09691    if (priority > -1) {
09692       /* see flag description in channel.h for explanation */
09693       if (ast_test_flag(ast_channel_flags(chan), AST_FLAG_IN_AUTOLOOP)) {
09694          --priority;
09695       }
09696       ast_channel_priority_set(chan, priority);
09697    }
09698 
09699    ast_channel_unlock(chan);
09700 
09701    return 0;
09702 }
09703 
09704 int ast_async_goto(struct ast_channel *chan, const char *context, const char *exten, int priority)
09705 {
09706    int res = 0;
09707    struct ast_channel *tmpchan;
09708    struct {
09709       char *accountcode;
09710       char *exten;
09711       char *context;
09712       char *linkedid;
09713       char *name;
09714       struct ast_cdr *cdr;
09715       int amaflags;
09716       int state;
09717       struct ast_format readformat;
09718       struct ast_format writeformat;
09719    } tmpvars = { 0, };
09720 
09721    ast_channel_lock(chan);
09722    if (ast_channel_pbx(chan)) { /* This channel is currently in the PBX */
09723       ast_explicit_goto(chan, context, exten, priority + 1);
09724       ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO);
09725       ast_channel_unlock(chan);
09726       return res;
09727    }
09728 
09729    /* In order to do it when the channel doesn't really exist within
09730     * the PBX, we have to make a new channel, masquerade, and start the PBX
09731     * at the new location */
09732    tmpvars.accountcode = ast_strdupa(ast_channel_accountcode(chan));
09733    tmpvars.exten = ast_strdupa(ast_channel_exten(chan));
09734    tmpvars.context = ast_strdupa(ast_channel_context(chan));
09735    tmpvars.linkedid = ast_strdupa(ast_channel_linkedid(chan));
09736    tmpvars.name = ast_strdupa(ast_channel_name(chan));
09737    tmpvars.amaflags = ast_channel_amaflags(chan);
09738    tmpvars.state = ast_channel_state(chan);
09739    ast_format_copy(&tmpvars.writeformat, ast_channel_writeformat(chan));
09740    ast_format_copy(&tmpvars.readformat, ast_channel_readformat(chan));
09741    tmpvars.cdr = ast_channel_cdr(chan) ? ast_cdr_dup(ast_channel_cdr(chan)) : NULL;
09742 
09743    ast_channel_unlock(chan);
09744 
09745    /* Do not hold any channel locks while calling channel_alloc() since the function
09746     * locks the channel container when linking the new channel in. */
09747    if (!(tmpchan = ast_channel_alloc(0, tmpvars.state, 0, 0, tmpvars.accountcode, tmpvars.exten, tmpvars.context, tmpvars.linkedid, tmpvars.amaflags, "AsyncGoto/%s", tmpvars.name))) {
09748       ast_cdr_discard(tmpvars.cdr);
09749       return -1;
09750    }
09751 
09752    /* copy the cdr info over */
09753    if (tmpvars.cdr) {
09754       ast_cdr_discard(ast_channel_cdr(tmpchan));
09755       ast_channel_cdr_set(tmpchan, tmpvars.cdr);
09756       tmpvars.cdr = NULL;
09757    }
09758 
09759    /* Make formats okay */
09760    ast_format_copy(ast_channel_readformat(tmpchan), &tmpvars.readformat);
09761    ast_format_copy(ast_channel_writeformat(tmpchan), &tmpvars.writeformat);
09762 
09763    /* Setup proper location. Never hold another channel lock while calling this function. */
09764    ast_explicit_goto(tmpchan, S_OR(context, tmpvars.context), S_OR(exten, tmpvars.exten), priority);
09765 
09766    /* Masquerade into tmp channel */
09767    if (ast_channel_masquerade(tmpchan, chan)) {
09768       /* Failed to set up the masquerade.  It's probably chan_local
09769        * in the middle of optimizing itself out.  Sad. :( */
09770       ast_hangup(tmpchan);
09771       tmpchan = NULL;
09772       res = -1;
09773    } else {
09774       ast_do_masquerade(tmpchan);
09775       /* Start the PBX going on our stolen channel */
09776       if (ast_pbx_start(tmpchan)) {
09777          ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(tmpchan));
09778          ast_hangup(tmpchan);
09779          res = -1;
09780       }
09781    }
09782 
09783    return res;
09784 }
09785 
09786 int ast_async_goto_by_name(const char *channame, const char *context, const char *exten, int priority)
09787 {
09788    struct ast_channel *chan;
09789    int res = -1;
09790 
09791    if ((chan = ast_channel_get_by_name(channame))) {
09792       res = ast_async_goto(chan, context, exten, priority);
09793       chan = ast_channel_unref(chan);
09794    }
09795 
09796    return res;
09797 }
09798 
09799 /*! \brief copy a string skipping whitespace */
09800 static int ext_strncpy(char *dst, const char *src, int len)
09801 {
09802    int count = 0;
09803    int insquares = 0;
09804 
09805    while (*src && (count < len - 1)) {
09806       if (*src == '[') {
09807          insquares = 1;
09808       } else if (*src == ']') {
09809          insquares = 0;
09810       } else if (*src == ' ' && !insquares) {
09811          src++;
09812          continue;
09813       }
09814       *dst = *src;
09815       dst++;
09816       src++;
09817       count++;
09818    }
09819    *dst = '\0';
09820 
09821    return count;
09822 }
09823 
09824 /*!
09825  * \brief add the extension in the priority chain.
09826  * \retval 0 on success.
09827  * \retval -1 on failure.
09828 */
09829 static int add_priority(struct ast_context *con, struct ast_exten *tmp,
09830    struct ast_exten *el, struct ast_exten *e, int replace)
09831 {
09832    struct ast_exten *ep;
09833    struct ast_exten *eh=e;
09834    int repeated_label = 0; /* Track if this label is a repeat, assume no. */
09835 
09836    for (ep = NULL; e ; ep = e, e = e->peer) {
09837       if (e->label && tmp->label && e->priority != tmp->priority && !strcmp(e->label, tmp->label)) {
09838          if (strcmp(e->exten, tmp->exten)) {
09839             ast_log(LOG_WARNING,
09840                "Extension '%s' priority %d in '%s', label '%s' already in use at aliased extension '%s' priority %d\n",
09841                tmp->exten, tmp->priority, con->name, tmp->label, e->exten, e->priority);
09842          } else {
09843             ast_log(LOG_WARNING,
09844                "Extension '%s' priority %d in '%s', label '%s' already in use at priority %d\n",
09845                tmp->exten, tmp->priority, con->name, tmp->label, e->priority);
09846          }
09847          repeated_label = 1;
09848       }
09849       if (e->priority >= tmp->priority) {
09850          break;
09851       }
09852    }
09853 
09854    if (repeated_label) {   /* Discard the label since it's a repeat. */
09855       tmp->label = NULL;
09856    }
09857 
09858    if (!e) {   /* go at the end, and ep is surely set because the list is not empty */
09859       ast_hashtab_insert_safe(eh->peer_table, tmp);
09860 
09861       if (tmp->label) {
09862          ast_hashtab_insert_safe(eh->peer_label_table, tmp);
09863       }
09864       ep->peer = tmp;
09865       return 0;   /* success */
09866    }
09867    if (e->priority == tmp->priority) {
09868       /* Can't have something exactly the same.  Is this a
09869          replacement?  If so, replace, otherwise, bonk. */
09870       if (!replace) {
09871          if (strcmp(e->exten, tmp->exten)) {
09872             ast_log(LOG_WARNING,
09873                "Unable to register extension '%s' priority %d in '%s', already in use by aliased extension '%s'\n",
09874                tmp->exten, tmp->priority, con->name, e->exten);
09875          } else {
09876             ast_log(LOG_WARNING,
09877                "Unable to register extension '%s' priority %d in '%s', already in use\n",
09878                tmp->exten, tmp->priority, con->name);
09879          }
09880          if (tmp->datad) {
09881             tmp->datad(tmp->data);
09882             /* if you free this, null it out */
09883             tmp->data = NULL;
09884          }
09885 
09886          ast_free(tmp);
09887          return -1;
09888       }
09889       /* we are replacing e, so copy the link fields and then update
09890        * whoever pointed to e to point to us
09891        */
09892       tmp->next = e->next; /* not meaningful if we are not first in the peer list */
09893       tmp->peer = e->peer; /* always meaningful */
09894       if (ep)  {     /* We're in the peer list, just insert ourselves */
09895          ast_hashtab_remove_object_via_lookup(eh->peer_table,e);
09896 
09897          if (e->label) {
09898             ast_hashtab_remove_object_via_lookup(eh->peer_label_table,e);
09899          }
09900 
09901          ast_hashtab_insert_safe(eh->peer_table,tmp);
09902          if (tmp->label) {
09903             ast_hashtab_insert_safe(eh->peer_label_table,tmp);
09904          }
09905 
09906          ep->peer = tmp;
09907       } else if (el) {     /* We're the first extension. Take over e's functions */
09908          struct match_char *x = add_exten_to_pattern_tree(con, e, 1);
09909          tmp->peer_table = e->peer_table;
09910          tmp->peer_label_table = e->peer_label_table;
09911          ast_hashtab_remove_object_via_lookup(tmp->peer_table,e);
09912          ast_hashtab_insert_safe(tmp->peer_table,tmp);
09913          if (e->label) {
09914             ast_hashtab_remove_object_via_lookup(tmp->peer_label_table, e);
09915          }
09916          if (tmp->label) {
09917             ast_hashtab_insert_safe(tmp->peer_label_table, tmp);
09918          }
09919 
09920          ast_hashtab_remove_object_via_lookup(con->root_table, e);
09921          ast_hashtab_insert_safe(con->root_table, tmp);
09922          el->next = tmp;
09923          /* The pattern trie points to this exten; replace the pointer,
09924             and all will be well */
09925          if (x) { /* if the trie isn't formed yet, don't sweat this */
09926             if (x->exten) { /* this test for safety purposes */
09927                x->exten = tmp; /* replace what would become a bad pointer */
09928             } else {
09929                ast_log(LOG_ERROR,"Trying to delete an exten from a context, but the pattern tree node returned isn't an extension\n");
09930             }
09931          }
09932       } else {       /* We're the very first extension.  */
09933          struct match_char *x = add_exten_to_pattern_tree(con, e, 1);
09934          ast_hashtab_remove_object_via_lookup(con->root_table, e);
09935          ast_hashtab_insert_safe(con->root_table, tmp);
09936          tmp->peer_table = e->peer_table;
09937          tmp->peer_label_table = e->peer_label_table;
09938          ast_hashtab_remove_object_via_lookup(tmp->peer_table, e);
09939          ast_hashtab_insert_safe(tmp->peer_table, tmp);
09940          if (e->label) {
09941             ast_hashtab_remove_object_via_lookup(tmp->peer_label_table, e);
09942          }
09943          if (tmp->label) {
09944             ast_hashtab_insert_safe(tmp->peer_label_table, tmp);
09945          }
09946 
09947          ast_hashtab_remove_object_via_lookup(con->root_table, e);
09948          ast_hashtab_insert_safe(con->root_table, tmp);
09949          con->root = tmp;
09950          /* The pattern trie points to this exten; replace the pointer,
09951             and all will be well */
09952          if (x) { /* if the trie isn't formed yet; no problem */
09953             if (x->exten) { /* this test for safety purposes */
09954                x->exten = tmp; /* replace what would become a bad pointer */
09955             } else {
09956                ast_log(LOG_ERROR,"Trying to delete an exten from a context, but the pattern tree node returned isn't an extension\n");
09957             }
09958          }
09959       }
09960       if (tmp->priority == PRIORITY_HINT)
09961          ast_change_hint(e,tmp);
09962       /* Destroy the old one */
09963       if (e->datad)
09964          e->datad(e->data);
09965       ast_free(e);
09966    } else { /* Slip ourselves in just before e */
09967       tmp->peer = e;
09968       tmp->next = e->next; /* extension chain, or NULL if e is not the first extension */
09969       if (ep) {         /* Easy enough, we're just in the peer list */
09970          if (tmp->label) {
09971             ast_hashtab_insert_safe(eh->peer_label_table, tmp);
09972          }
09973          ast_hashtab_insert_safe(eh->peer_table, tmp);
09974          ep->peer = tmp;
09975       } else {       /* we are the first in some peer list, so link in the ext list */
09976          tmp->peer_table = e->peer_table;
09977          tmp->peer_label_table = e->peer_label_table;
09978          e->peer_table = 0;
09979          e->peer_label_table = 0;
09980          ast_hashtab_insert_safe(tmp->peer_table, tmp);
09981          if (tmp->label) {
09982             ast_hashtab_insert_safe(tmp->peer_label_table, tmp);
09983          }
09984          ast_hashtab_remove_object_via_lookup(con->root_table, e);
09985          ast_hashtab_insert_safe(con->root_table, tmp);
09986          if (el)
09987             el->next = tmp;   /* in the middle... */
09988          else
09989             con->root = tmp; /* ... or at the head */
09990          e->next = NULL;   /* e is no more at the head, so e->next must be reset */
09991       }
09992       /* And immediately return success. */
09993       if (tmp->priority == PRIORITY_HINT) {
09994          ast_add_hint(tmp);
09995       }
09996    }
09997    return 0;
09998 }
09999 
10000 /*! \brief
10001  * Main interface to add extensions to the list for out context.
10002  *
10003  * We sort extensions in order of matching preference, so that we can
10004  * stop the search as soon as we find a suitable match.
10005  * This ordering also takes care of wildcards such as '.' (meaning
10006  * "one or more of any character") and '!' (which is 'earlymatch',
10007  * meaning "zero or more of any character" but also impacts the
10008  * return value from CANMATCH and EARLYMATCH.
10009  *
10010  * The extension match rules defined in the devmeeting 2006.05.05 are
10011  * quite simple: WE SELECT THE LONGEST MATCH.
10012  * In detail, "longest" means the number of matched characters in
10013  * the extension. In case of ties (e.g. _XXX and 333) in the length
10014  * of a pattern, we give priority to entries with the smallest cardinality
10015  * (e.g, [5-9] comes before [2-8] before the former has only 5 elements,
10016  * while the latter has 7, etc.
10017  * In case of same cardinality, the first element in the range counts.
10018  * If we still have a tie, any final '!' will make this as a possibly
10019  * less specific pattern.
10020  *
10021  * EBUSY - can't lock
10022  * EEXIST - extension with the same priority exist and no replace is set
10023  *
10024  */
10025 int ast_add_extension2(struct ast_context *con,
10026    int replace, const char *extension, int priority, const char *label, const char *callerid,
10027    const char *application, void *data, void (*datad)(void *),
10028    const char *registrar)
10029 {
10030    return ast_add_extension2_lockopt(con, replace, extension, priority, label, callerid,
10031       application, data, datad, registrar, 1);
10032 }
10033 
10034 /*!
10035  * \brief Same as ast_add_extension2() but controls the context locking.
10036  *
10037  * \details
10038  * Does all the work of ast_add_extension2, but adds an arg to
10039  * determine if context locking should be done.
10040  */
10041 static int ast_add_extension2_lockopt(struct ast_context *con,
10042    int replace, const char *extension, int priority, const char *label, const char *callerid,
10043    const char *application, void *data, void (*datad)(void *),
10044    const char *registrar, int lock_context)
10045 {
10046    /*
10047     * Sort extensions (or patterns) according to the rules indicated above.
10048     * These are implemented by the function ext_cmp()).
10049     * All priorities for the same ext/pattern/cid are kept in a list,
10050     * using the 'peer' field  as a link field..
10051     */
10052    struct ast_exten *tmp, *tmp2, *e, *el = NULL;
10053    int res;
10054    int length;
10055    char *p;
10056    char expand_buf[VAR_BUF_SIZE];
10057    struct ast_exten dummy_exten = {0};
10058    char dummy_name[1024];
10059 
10060    if (ast_strlen_zero(extension)) {
10061       ast_log(LOG_ERROR,"You have to be kidding-- add exten '' to context %s? Figure out a name and call me back. Action ignored.\n",
10062             con->name);
10063       return -1;
10064    }
10065 
10066    /* If we are adding a hint evalulate in variables and global variables */
10067    if (priority == PRIORITY_HINT && strstr(application, "${") && extension[0] != '_') {
10068       struct ast_channel *c = ast_dummy_channel_alloc();
10069 
10070       if (c) {
10071          ast_channel_exten_set(c, extension);
10072          ast_channel_context_set(c, con->name);
10073       }
10074       pbx_substitute_variables_helper(c, application, expand_buf, sizeof(expand_buf));
10075       application = expand_buf;
10076       if (c) {
10077          ast_channel_unref(c);
10078       }
10079    }
10080 
10081    length = sizeof(struct ast_exten);
10082    length += strlen(extension) + 1;
10083    length += strlen(application) + 1;
10084    if (label)
10085       length += strlen(label) + 1;
10086    if (callerid)
10087       length += strlen(callerid) + 1;
10088    else
10089       length ++;  /* just the '\0' */
10090 
10091    /* Be optimistic:  Build the extension structure first */
10092    if (!(tmp = ast_calloc(1, length)))
10093       return -1;
10094 
10095    if (ast_strlen_zero(label)) /* let's turn empty labels to a null ptr */
10096       label = 0;
10097 
10098    /* use p as dst in assignments, as the fields are const char * */
10099    p = tmp->stuff;
10100    if (label) {
10101       tmp->label = p;
10102       strcpy(p, label);
10103       p += strlen(label) + 1;
10104    }
10105    tmp->exten = p;
10106    p += ext_strncpy(p, extension, strlen(extension) + 1) + 1;
10107    tmp->priority = priority;
10108    tmp->cidmatch = p;   /* but use p for assignments below */
10109 
10110    /* Blank callerid and NULL callerid are two SEPARATE things.  Do NOT confuse the two!!! */
10111    if (callerid) {
10112       p += ext_strncpy(p, callerid, strlen(callerid) + 1) + 1;
10113       tmp->matchcid = AST_EXT_MATCHCID_ON;
10114    } else {
10115       *p++ = '\0';
10116       tmp->matchcid = AST_EXT_MATCHCID_OFF;
10117    }
10118    tmp->app = p;
10119    strcpy(p, application);
10120    tmp->parent = con;
10121    tmp->data = data;
10122    tmp->datad = datad;
10123    tmp->registrar = registrar;
10124 
10125    if (lock_context) {
10126       ast_wrlock_context(con);
10127    }
10128 
10129    if (con->pattern_tree) { /* usually, on initial load, the pattern_tree isn't formed until the first find_exten; so if we are adding
10130                         an extension, and the trie exists, then we need to incrementally add this pattern to it. */
10131       ast_copy_string(dummy_name, extension, sizeof(dummy_name));
10132       dummy_exten.exten = dummy_name;
10133       dummy_exten.matchcid = AST_EXT_MATCHCID_OFF;
10134       dummy_exten.cidmatch = 0;
10135       tmp2 = ast_hashtab_lookup(con->root_table, &dummy_exten);
10136       if (!tmp2) {
10137          /* hmmm, not in the trie; */
10138          add_exten_to_pattern_tree(con, tmp, 0);
10139          ast_hashtab_insert_safe(con->root_table, tmp); /* for the sake of completeness */
10140       }
10141    }
10142    res = 0; /* some compilers will think it is uninitialized otherwise */
10143    for (e = con->root; e; el = e, e = e->next) {   /* scan the extension list */
10144       res = ext_cmp(e->exten, tmp->exten);
10145       if (res == 0) { /* extension match, now look at cidmatch */
10146          if (e->matchcid == AST_EXT_MATCHCID_OFF && tmp->matchcid == AST_EXT_MATCHCID_OFF)
10147             res = 0;
10148          else if (tmp->matchcid == AST_EXT_MATCHCID_ON && e->matchcid == AST_EXT_MATCHCID_OFF)
10149             res = 1;
10150          else if (e->matchcid == AST_EXT_MATCHCID_ON && tmp->matchcid == AST_EXT_MATCHCID_OFF)
10151             res = -1;
10152          else
10153             res = ext_cmp(e->cidmatch, tmp->cidmatch);
10154       }
10155       if (res >= 0)
10156          break;
10157    }
10158    if (e && res == 0) { /* exact match, insert in the priority chain */
10159       res = add_priority(con, tmp, el, e, replace);
10160       if (lock_context) {
10161          ast_unlock_context(con);
10162       }
10163       if (res < 0) {
10164          errno = EEXIST;   /* XXX do we care ? */
10165          return 0; /* XXX should we return -1 maybe ? */
10166       }
10167    } else {
10168       /*
10169        * not an exact match, this is the first entry with this pattern,
10170        * so insert in the main list right before 'e' (if any)
10171        */
10172       tmp->next = e;
10173       if (el) {  /* there is another exten already in this context */
10174          el->next = tmp;
10175          tmp->peer_table = ast_hashtab_create(13,
10176                      hashtab_compare_exten_numbers,
10177                      ast_hashtab_resize_java,
10178                      ast_hashtab_newsize_java,
10179                      hashtab_hash_priority,
10180                      0);
10181          tmp->peer_label_table = ast_hashtab_create(7,
10182                         hashtab_compare_exten_labels,
10183                         ast_hashtab_resize_java,
10184                         ast_hashtab_newsize_java,
10185                         hashtab_hash_labels,
10186                         0);
10187          if (label) {
10188             ast_hashtab_insert_safe(tmp->peer_label_table, tmp);
10189          }
10190          ast_hashtab_insert_safe(tmp->peer_table, tmp);
10191       } else {  /* this is the first exten in this context */
10192          if (!con->root_table)
10193             con->root_table = ast_hashtab_create(27,
10194                                        hashtab_compare_extens,
10195                                        ast_hashtab_resize_java,
10196                                        ast_hashtab_newsize_java,
10197                                        hashtab_hash_extens,
10198                                        0);
10199          con->root = tmp;
10200          con->root->peer_table = ast_hashtab_create(13,
10201                         hashtab_compare_exten_numbers,
10202                         ast_hashtab_resize_java,
10203                         ast_hashtab_newsize_java,
10204                         hashtab_hash_priority,
10205                         0);
10206          con->root->peer_label_table = ast_hashtab_create(7,
10207                            hashtab_compare_exten_labels,
10208                            ast_hashtab_resize_java,
10209                            ast_hashtab_newsize_java,
10210                            hashtab_hash_labels,
10211                            0);
10212          if (label) {
10213             ast_hashtab_insert_safe(con->root->peer_label_table, tmp);
10214          }
10215          ast_hashtab_insert_safe(con->root->peer_table, tmp);
10216 
10217       }
10218       ast_hashtab_insert_safe(con->root_table, tmp);
10219       if (lock_context) {
10220          ast_unlock_context(con);
10221       }
10222       if (tmp->priority == PRIORITY_HINT) {
10223          ast_add_hint(tmp);
10224       }
10225    }
10226    if (option_debug) {
10227       if (tmp->matchcid == AST_EXT_MATCHCID_ON) {
10228          ast_debug(1, "Added extension '%s' priority %d (CID match '%s') to %s (%p)\n",
10229                  tmp->exten, tmp->priority, tmp->cidmatch, con->name, con);
10230       } else {
10231          ast_debug(1, "Added extension '%s' priority %d to %s (%p)\n",
10232                  tmp->exten, tmp->priority, con->name, con);
10233       }
10234    }
10235 
10236    if (tmp->matchcid == AST_EXT_MATCHCID_ON) {
10237       ast_verb(3, "Added extension '%s' priority %d (CID match '%s') to %s\n",
10238              tmp->exten, tmp->priority, tmp->cidmatch, con->name);
10239    } else {
10240       ast_verb(3, "Added extension '%s' priority %d to %s\n",
10241              tmp->exten, tmp->priority, con->name);
10242    }
10243 
10244    return 0;
10245 }
10246 
10247 struct async_stat {
10248    pthread_t p;
10249    struct ast_channel *chan;
10250    char context[AST_MAX_CONTEXT];
10251    char exten[AST_MAX_EXTENSION];
10252    int priority;
10253    int timeout;
10254    char app[AST_MAX_EXTENSION];
10255    char appdata[1024];
10256    int early_media;        /* Connect the bridge if early media arrives, don't wait for answer */
10257 };
10258 
10259 static void *async_wait(void *data)
10260 {
10261    struct async_stat *as = data;
10262    struct ast_channel *chan = as->chan;
10263    int timeout = as->timeout;
10264    int res;
10265    struct ast_frame *f;
10266    struct ast_app *app;
10267    int have_early_media = 0;
10268    struct timeval start = ast_tvnow();
10269    int ms;
10270 
10271    if (chan) {
10272       struct ast_callid *callid = ast_channel_callid(chan);
10273       if (callid) {
10274          ast_callid_threadassoc_add(callid);
10275          ast_callid_unref(callid);
10276       }
10277    }
10278 
10279    while ((ms = ast_remaining_ms(start, timeout)) &&
10280          ast_channel_state(chan) != AST_STATE_UP) {
10281       res = ast_waitfor(chan, ms);
10282       if (res < 1)
10283          break;
10284 
10285       f = ast_read(chan);
10286       if (!f)
10287          break;
10288       if (f->frametype == AST_FRAME_CONTROL) {
10289          if ((f->subclass.integer == AST_CONTROL_BUSY)  ||
10290              (f->subclass.integer == AST_CONTROL_CONGESTION) ) {
10291             ast_frfree(f);
10292             break;
10293          }
10294          if (as->early_media && f->subclass.integer == AST_CONTROL_PROGRESS) {
10295             have_early_media = 1;
10296             ast_frfree(f);
10297             break;
10298          }
10299       }
10300       ast_frfree(f);
10301    }
10302    if (ast_channel_state(chan) == AST_STATE_UP || have_early_media) {
10303       if (have_early_media) {
10304          ast_debug(2, "Activating pbx since we have early media \n");
10305       }
10306       if (!ast_strlen_zero(as->app)) {
10307          app = pbx_findapp(as->app);
10308          if (app) {
10309             ast_verb(3, "Launching %s(%s) on %s\n", as->app, as->appdata, ast_channel_name(chan));
10310             pbx_exec(chan, app, as->appdata);
10311          } else
10312             ast_log(LOG_WARNING, "No such application '%s'\n", as->app);
10313       } else {
10314          if (!ast_strlen_zero(as->context))
10315             ast_channel_context_set(chan, as->context);
10316          if (!ast_strlen_zero(as->exten))
10317             ast_channel_exten_set(chan, as->exten);
10318          if (as->priority > 0)
10319             ast_channel_priority_set(chan, as->priority);
10320          /* Run the PBX */
10321          if (ast_pbx_run(chan)) {
10322             ast_log(LOG_ERROR, "Failed to start PBX on %s\n", ast_channel_name(chan));
10323          } else {
10324             /* PBX will have taken care of this */
10325             chan = NULL;
10326          }
10327       }
10328    }
10329    ast_free(as);
10330    if (chan)
10331       ast_hangup(chan);
10332    return NULL;
10333 }
10334 
10335 /*!
10336  * \brief Function to post an empty cdr after a spool call fails.
10337  * \note This function posts an empty cdr for a failed spool call
10338 */
10339 static int ast_pbx_outgoing_cdr_failed(void)
10340 {
10341    /* allocate a channel */
10342    struct ast_channel *chan = ast_dummy_channel_alloc();
10343 
10344    if (!chan)
10345       return -1;  /* failure */
10346 
10347    ast_channel_cdr_set(chan, ast_cdr_alloc());
10348    if (!ast_channel_cdr(chan)) {
10349       /* allocation of the cdr failed */
10350       chan = ast_channel_unref(chan);   /* free the channel */
10351       return -1;                /* return failure */
10352    }
10353 
10354    /* allocation of the cdr was successful */
10355    ast_cdr_init(ast_channel_cdr(chan), chan);  /* initialize our channel's cdr */
10356    ast_cdr_start(ast_channel_cdr(chan));       /* record the start and stop time */
10357    ast_cdr_end(ast_channel_cdr(chan));
10358    ast_cdr_failed(ast_channel_cdr(chan));      /* set the status to failed */
10359    ast_cdr_detach(ast_channel_cdr(chan));      /* post and free the record */
10360    ast_channel_cdr_set(chan, NULL);
10361    chan = ast_channel_unref(chan);         /* free the channel */
10362 
10363    return 0;  /* success */
10364 }
10365 
10366 int ast_pbx_outgoing_exten(const char *type, struct ast_format_cap *cap, const char *addr, int timeout, const char *context, const char *exten, int priority, int *reason, int synchronous, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **channel, int early_media)
10367 {
10368    struct ast_channel *chan;
10369    struct async_stat *as;
10370    struct ast_callid *callid;
10371    int callid_created = 0;
10372    int res = -1, cdr_res = -1;
10373    struct outgoing_helper oh;
10374 
10375    oh.connect_on_early_media = early_media;
10376 
10377    callid_created = ast_callid_threadstorage_auto(&callid);
10378 
10379    if (synchronous) {
10380       oh.context = context;
10381       oh.exten = exten;
10382       oh.priority = priority;
10383       oh.cid_num = cid_num;
10384       oh.cid_name = cid_name;
10385       oh.account = account;
10386       oh.vars = vars;
10387       oh.parent_channel = NULL;
10388 
10389       chan = __ast_request_and_dial(type, cap, NULL, addr, timeout, reason, cid_num, cid_name, &oh);
10390       if (channel) {
10391          *channel = chan;
10392          if (chan)
10393             ast_channel_lock(chan);
10394       }
10395       if (chan) {
10396          /* Bind the callid to the channel if it doesn't already have one on creation */
10397          struct ast_callid *channel_callid = ast_channel_callid(chan);
10398          if (channel_callid) {
10399             ast_callid_unref(channel_callid);
10400          } else {
10401             if (callid) {
10402                ast_channel_callid_set(chan, callid);
10403             }
10404          }
10405 
10406          if (ast_channel_state(chan) == AST_STATE_UP || (early_media && *reason == AST_CONTROL_PROGRESS)) {
10407                res = 0;
10408             ast_verb(4, "Channel %s %s\n", ast_channel_name(chan), ast_channel_state(chan) == AST_STATE_UP ? "was answered" : "got early media");
10409 
10410             if (synchronous > 1) {
10411                if (channel)
10412                   ast_channel_unlock(chan);
10413                if (ast_pbx_run(chan)) {
10414                   ast_log(LOG_ERROR, "Unable to run PBX on %s\n", ast_channel_name(chan));
10415                   if (channel)
10416                      *channel = NULL;
10417                   ast_hangup(chan);
10418                   chan = NULL;
10419                   res = -1;
10420                }
10421             } else {
10422                if (ast_pbx_start(chan)) {
10423                   ast_log(LOG_ERROR, "Unable to start PBX on %s\n", ast_channel_name(chan));
10424                   if (channel) {
10425                      *channel = NULL;
10426                      ast_channel_unlock(chan);
10427                   }
10428                   ast_hangup(chan);
10429                   res = -1;
10430                }
10431                chan = NULL;
10432             }
10433          } else {
10434             ast_verb(4, "Channel %s was never answered.\n", ast_channel_name(chan));
10435 
10436             if (ast_channel_cdr(chan)) { /* update the cdr */
10437                /* here we update the status of the call, which sould be busy.
10438                 * if that fails then we set the status to failed */
10439                if (ast_cdr_disposition(ast_channel_cdr(chan), ast_channel_hangupcause(chan)))
10440                   ast_cdr_failed(ast_channel_cdr(chan));
10441             }
10442 
10443             if (channel) {
10444                *channel = NULL;
10445                ast_channel_unlock(chan);
10446             }
10447             ast_hangup(chan);
10448             chan = NULL;
10449          }
10450       }
10451 
10452       if (res < 0) { /* the call failed for some reason */
10453          if (*reason == 0) { /* if the call failed (not busy or no answer)
10454                         * update the cdr with the failed message */
10455             cdr_res = ast_pbx_outgoing_cdr_failed();
10456             if (cdr_res != 0) {
10457                res = cdr_res;
10458                goto outgoing_exten_cleanup;
10459             }
10460          }
10461 
10462          /* create a fake channel and execute the "failed" extension (if it exists) within the requested context */
10463          /* check if "failed" exists */
10464          if (ast_exists_extension(chan, context, "failed", 1, NULL)) {
10465             chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", NULL, 0, "OutgoingSpoolFailed");
10466             if (chan) {
10467                char failed_reason[4] = "";
10468                if (!ast_strlen_zero(context))
10469                   ast_channel_context_set(chan, context);
10470                set_ext_pri(chan, "failed", 1);
10471                ast_set_variables(chan, vars);
10472                snprintf(failed_reason, sizeof(failed_reason), "%d", *reason);
10473                pbx_builtin_setvar_helper(chan, "REASON", failed_reason);
10474                if (account)
10475                   ast_cdr_setaccount(chan, account);
10476                if (ast_pbx_run(chan)) {
10477                   ast_log(LOG_ERROR, "Unable to run PBX on %s\n", ast_channel_name(chan));
10478                   ast_hangup(chan);
10479                }
10480                chan = NULL;
10481             }
10482          }
10483       }
10484    } else {
10485       struct ast_callid *channel_callid;
10486       if (!(as = ast_calloc(1, sizeof(*as)))) {
10487          res = -1;
10488          goto outgoing_exten_cleanup;
10489       }
10490       chan = ast_request_and_dial(type, cap, NULL, addr, timeout, reason, cid_num, cid_name);
10491       if (channel) {
10492          *channel = chan;
10493          if (chan)
10494             ast_channel_lock(chan);
10495       }
10496       if (!chan) {
10497          ast_free(as);
10498          res = -1;
10499          goto outgoing_exten_cleanup;
10500       }
10501 
10502       /* Bind the newly created callid to the channel if it doesn't already have one on creation. */
10503       channel_callid = ast_channel_callid(chan);
10504       if (channel_callid) {
10505          ast_callid_unref(channel_callid);
10506       } else {
10507          if (callid) {
10508             ast_channel_callid_set(chan, callid);
10509          }
10510       }
10511 
10512       as->chan = chan;
10513       ast_copy_string(as->context, context, sizeof(as->context));
10514       set_ext_pri(as->chan,  exten, priority);
10515       as->timeout = timeout;
10516       ast_set_variables(chan, vars);
10517       if (account)
10518          ast_cdr_setaccount(chan, account);
10519       if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) {
10520          ast_log(LOG_WARNING, "Failed to start async wait\n");
10521          ast_free(as);
10522          if (channel) {
10523             *channel = NULL;
10524             ast_channel_unlock(chan);
10525          }
10526          ast_hangup(chan);
10527          res = -1;
10528          goto outgoing_exten_cleanup;
10529       }
10530       res = 0;
10531    }
10532 
10533 outgoing_exten_cleanup:
10534    ast_callid_threadstorage_auto_clean(callid, callid_created);
10535    ast_variables_destroy(vars);
10536    return res;
10537 }
10538 
10539 struct app_tmp {
10540    struct ast_channel *chan;
10541    pthread_t t;
10542    AST_DECLARE_STRING_FIELDS (
10543       AST_STRING_FIELD(app);
10544       AST_STRING_FIELD(data);
10545    );
10546 };
10547 
10548 /*! \brief run the application and free the descriptor once done */
10549 static void *ast_pbx_run_app(void *data)
10550 {
10551    struct app_tmp *tmp = data;
10552    struct ast_app *app;
10553    app = pbx_findapp(tmp->app);
10554    if (app) {
10555       ast_verb(4, "Launching %s(%s) on %s\n", tmp->app, tmp->data, ast_channel_name(tmp->chan));
10556       pbx_exec(tmp->chan, app, tmp->data);
10557    } else
10558       ast_log(LOG_WARNING, "No such application '%s'\n", tmp->app);
10559    ast_hangup(tmp->chan);
10560    ast_string_field_free_memory(tmp);
10561    ast_free(tmp);
10562    return NULL;
10563 }
10564 
10565 int ast_pbx_outgoing_app(const char *type, struct ast_format_cap *cap, const char *addr, int timeout, const char *app, const char *appdata, int *reason, int synchronous, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel)
10566 {
10567    struct ast_channel *chan;
10568    struct app_tmp *tmp;
10569    struct ast_callid *callid;
10570    int callid_created;
10571    int res = -1, cdr_res = -1;
10572    struct outgoing_helper oh;
10573 
10574    /* Start by checking for a callid in threadstorage, and if none is found, bind one. */
10575    callid_created = ast_callid_threadstorage_auto(&callid);
10576 
10577    memset(&oh, 0, sizeof(oh));
10578    oh.vars = vars;
10579    oh.account = account;
10580 
10581    if (locked_channel)
10582       *locked_channel = NULL;
10583    if (ast_strlen_zero(app)) {
10584       res = -1;
10585       goto outgoing_app_cleanup;
10586    }
10587    if (synchronous) {
10588       chan = __ast_request_and_dial(type, cap, NULL, addr, timeout, reason, cid_num, cid_name, &oh);
10589       if (chan) {
10590          /* Bind the newly created callid to the channel if it doesn't already have one on creation */
10591          struct ast_callid *channel_callid = ast_channel_callid(chan);
10592          if (channel_callid) {
10593             ast_callid_unref(channel_callid);
10594          } else {
10595             if (callid) {
10596                ast_channel_callid_set(chan, callid);
10597             }
10598          }
10599 
10600          ast_set_variables(chan, vars);
10601          if (account)
10602             ast_cdr_setaccount(chan, account);
10603          if (ast_channel_state(chan) == AST_STATE_UP) {
10604             res = 0;
10605             ast_verb(4, "Channel %s was answered.\n", ast_channel_name(chan));
10606             tmp = ast_calloc(1, sizeof(*tmp));
10607             if (!tmp || ast_string_field_init(tmp, 252)) {
10608                if (tmp) {
10609                   ast_free(tmp);
10610                }
10611                res = -1;
10612             } else {
10613                ast_string_field_set(tmp, app, app);
10614                ast_string_field_set(tmp, data, appdata);
10615                tmp->chan = chan;
10616                if (synchronous > 1) {
10617                   if (locked_channel)
10618                      ast_channel_unlock(chan);
10619                   ast_pbx_run_app(tmp);
10620                } else {
10621                   if (locked_channel)
10622                      ast_channel_lock(chan);
10623                   if (ast_pthread_create_detached(&tmp->t, NULL, ast_pbx_run_app, tmp)) {
10624                      ast_log(LOG_WARNING, "Unable to spawn execute thread on %s: %s\n", ast_channel_name(chan), strerror(errno));
10625                      ast_string_field_free_memory(tmp);
10626                      ast_free(tmp);
10627                      if (locked_channel)
10628                         ast_channel_unlock(chan);
10629                      ast_hangup(chan);
10630                      res = -1;
10631                   } else {
10632                      if (locked_channel)
10633                         *locked_channel = chan;
10634                   }
10635                }
10636             }
10637          } else {
10638             ast_verb(4, "Channel %s was never answered.\n", ast_channel_name(chan));
10639             if (ast_channel_cdr(chan)) { /* update the cdr */
10640                /* here we update the status of the call, which sould be busy.
10641                 * if that fails then we set the status to failed */
10642                if (ast_cdr_disposition(ast_channel_cdr(chan), ast_channel_hangupcause(chan)))
10643                   ast_cdr_failed(ast_channel_cdr(chan));
10644             }
10645             ast_hangup(chan);
10646          }
10647       }
10648 
10649       if (res < 0) { /* the call failed for some reason */
10650          if (*reason == 0) { /* if the call failed (not busy or no answer)
10651                         * update the cdr with the failed message */
10652             cdr_res = ast_pbx_outgoing_cdr_failed();
10653             if (cdr_res != 0) {
10654                res = cdr_res;
10655                goto outgoing_app_cleanup;
10656             }
10657          }
10658       }
10659 
10660    } else {
10661       struct async_stat *as;
10662       struct ast_callid *channel_callid;
10663       if (!(as = ast_calloc(1, sizeof(*as)))) {
10664          res = -1;
10665          goto outgoing_app_cleanup;
10666       }
10667       chan = __ast_request_and_dial(type, cap, NULL, addr, timeout, reason, cid_num, cid_name, &oh);
10668       if (!chan) {
10669          ast_free(as);
10670          res = -1;
10671          goto outgoing_app_cleanup;
10672       }
10673 
10674       /* Bind the newly created callid to the channel if it doesn't already have one on creation. */
10675       channel_callid = ast_channel_callid(chan);
10676       if (channel_callid) {
10677          ast_callid_unref(channel_callid);
10678       } else {
10679          if (callid) {
10680             ast_channel_callid_set(chan, callid);
10681          }
10682       }
10683 
10684       as->chan = chan;
10685       ast_copy_string(as->app, app, sizeof(as->app));
10686       if (appdata)
10687          ast_copy_string(as->appdata,  appdata, sizeof(as->appdata));
10688       as->timeout = timeout;
10689       ast_set_variables(chan, vars);
10690       if (account)
10691          ast_cdr_setaccount(chan, account);
10692       /* Start a new thread, and get something handling this channel. */
10693       if (locked_channel)
10694          ast_channel_lock(chan);
10695       if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) {
10696          ast_log(LOG_WARNING, "Failed to start async wait\n");
10697          ast_free(as);
10698          if (locked_channel)
10699             ast_channel_unlock(chan);
10700          ast_hangup(chan);
10701          res = -1;
10702          goto outgoing_app_cleanup;
10703       } else {
10704          if (locked_channel)
10705             *locked_channel = chan;
10706       }
10707       res = 0;
10708    }
10709 
10710 outgoing_app_cleanup:
10711    ast_callid_threadstorage_auto_clean(callid, callid_created);
10712    ast_variables_destroy(vars);
10713    return res;
10714 }
10715 
10716 /* this is the guts of destroying a context --
10717    freeing up the structure, traversing and destroying the
10718    extensions, switches, ignorepats, includes, etc. etc. */
10719 
10720 static void __ast_internal_context_destroy( struct ast_context *con)
10721 {
10722    struct ast_include *tmpi;
10723    struct ast_sw *sw;
10724    struct ast_exten *e, *el, *en;
10725    struct ast_ignorepat *ipi;
10726    struct ast_context *tmp = con;
10727 
10728    for (tmpi = tmp->includes; tmpi; ) { /* Free includes */
10729       struct ast_include *tmpil = tmpi;
10730       tmpi = tmpi->next;
10731       ast_free(tmpil);
10732    }
10733    for (ipi = tmp->ignorepats; ipi; ) { /* Free ignorepats */
10734       struct ast_ignorepat *ipl = ipi;
10735       ipi = ipi->next;
10736       ast_free(ipl);
10737    }
10738    if (tmp->registrar)
10739       ast_free(tmp->registrar);
10740 
10741    /* destroy the hash tabs */
10742    if (tmp->root_table) {
10743       ast_hashtab_destroy(tmp->root_table, 0);
10744    }
10745    /* and destroy the pattern tree */
10746    if (tmp->pattern_tree)
10747       destroy_pattern_tree(tmp->pattern_tree);
10748 
10749    while ((sw = AST_LIST_REMOVE_HEAD(&tmp->alts, list)))
10750       ast_free(sw);
10751    for (e = tmp->root; e;) {
10752       for (en = e->peer; en;) {
10753          el = en;
10754          en = en->peer;
10755          destroy_exten(el);
10756       }
10757       el = e;
10758       e = e->next;
10759       destroy_exten(el);
10760    }
10761    tmp->root = NULL;
10762    ast_rwlock_destroy(&tmp->lock);
10763    ast_mutex_destroy(&tmp->macrolock);
10764    ast_free(tmp);
10765 }
10766 
10767 
10768 void __ast_context_destroy(struct ast_context *list, struct ast_hashtab *contexttab, struct ast_context *con, const char *registrar)
10769 {
10770    struct ast_context *tmp, *tmpl=NULL;
10771    struct ast_exten *exten_item, *prio_item;
10772 
10773    for (tmp = list; tmp; ) {
10774       struct ast_context *next = NULL; /* next starting point */
10775          /* The following code used to skip forward to the next
10776             context with matching registrar, but this didn't
10777             make sense; individual priorities registrar'd to
10778             the matching registrar could occur in any context! */
10779       ast_debug(1, "Investigate ctx %s %s\n", tmp->name, tmp->registrar);
10780       if (con) {
10781          for (; tmp; tmpl = tmp, tmp = tmp->next) { /* skip to the matching context */
10782             ast_debug(1, "check ctx %s %s\n", tmp->name, tmp->registrar);
10783             if ( !strcasecmp(tmp->name, con->name) ) {
10784                break;   /* found it */
10785             }
10786          }
10787       }
10788 
10789       if (!tmp)   /* not found, we are done */
10790          break;
10791       ast_wrlock_context(tmp);
10792 
10793       if (registrar) {
10794          /* then search thru and remove any extens that match registrar. */
10795          struct ast_hashtab_iter *exten_iter;
10796          struct ast_hashtab_iter *prio_iter;
10797          struct ast_ignorepat *ip, *ipl = NULL, *ipn = NULL;
10798          struct ast_include *i, *pi = NULL, *ni = NULL;
10799          struct ast_sw *sw = NULL;
10800 
10801          /* remove any ignorepats whose registrar matches */
10802          for (ip = tmp->ignorepats; ip; ip = ipn) {
10803             ipn = ip->next;
10804             if (!strcmp(ip->registrar, registrar)) {
10805                if (ipl) {
10806                   ipl->next = ip->next;
10807                   ast_free(ip);
10808                   continue; /* don't change ipl */
10809                } else {
10810                   tmp->ignorepats = ip->next;
10811                   ast_free(ip);
10812                   continue; /* don't change ipl */
10813                }
10814             }
10815             ipl = ip;
10816          }
10817          /* remove any includes whose registrar matches */
10818          for (i = tmp->includes; i; i = ni) {
10819             ni = i->next;
10820             if (strcmp(i->registrar, registrar) == 0) {
10821                /* remove from list */
10822                if (pi) {
10823                   pi->next = i->next;
10824                   /* free include */
10825                   ast_free(i);
10826                   continue; /* don't change pi */
10827                } else {
10828                   tmp->includes = i->next;
10829                   /* free include */
10830                   ast_free(i);
10831                   continue; /* don't change pi */
10832                }
10833             }
10834             pi = i;
10835          }
10836          /* remove any switches whose registrar matches */
10837          AST_LIST_TRAVERSE_SAFE_BEGIN(&tmp->alts, sw, list) {
10838             if (strcmp(sw->registrar,registrar) == 0) {
10839                AST_LIST_REMOVE_CURRENT(list);
10840                ast_free(sw);
10841             }
10842          }
10843          AST_LIST_TRAVERSE_SAFE_END;
10844 
10845          if (tmp->root_table) { /* it is entirely possible that the context is EMPTY */
10846             exten_iter = ast_hashtab_start_traversal(tmp->root_table);
10847             while ((exten_item=ast_hashtab_next(exten_iter))) {
10848                int end_traversal = 1;
10849                prio_iter = ast_hashtab_start_traversal(exten_item->peer_table);
10850                while ((prio_item=ast_hashtab_next(prio_iter))) {
10851                   char extension[AST_MAX_EXTENSION];
10852                   char cidmatch[AST_MAX_EXTENSION];
10853                   if (!prio_item->registrar || strcmp(prio_item->registrar, registrar) != 0) {
10854                      continue;
10855                   }
10856                   ast_verb(3, "Remove %s/%s/%d, registrar=%s; con=%s(%p); con->root=%p\n",
10857                          tmp->name, prio_item->exten, prio_item->priority, registrar, con? con->name : "<nil>", con, con? con->root_table: NULL);
10858                   ast_copy_string(extension, prio_item->exten, sizeof(extension));
10859                   if (prio_item->cidmatch) {
10860                      ast_copy_string(cidmatch, prio_item->cidmatch, sizeof(cidmatch));
10861                   }
10862                   end_traversal &= ast_context_remove_extension_callerid2(tmp, extension, prio_item->priority, cidmatch, prio_item->matchcid, NULL, 1);
10863                }
10864                /* Explanation:
10865                 * ast_context_remove_extension_callerid2 will destroy the extension that it comes across. This
10866                 * destruction includes destroying the exten's peer_table, which we are currently traversing. If
10867                 * ast_context_remove_extension_callerid2 ever should return '0' then this means we have destroyed
10868                 * the hashtable which we are traversing, and thus calling ast_hashtab_end_traversal will result
10869                 * in reading invalid memory. Thus, if we detect that we destroyed the hashtable, then we will simply
10870                 * free the iterator
10871                 */
10872                if (end_traversal) {
10873                   ast_hashtab_end_traversal(prio_iter);
10874                } else {
10875                   ast_free(prio_iter);
10876                }
10877             }
10878             ast_hashtab_end_traversal(exten_iter);
10879          }
10880 
10881          /* delete the context if it's registrar matches, is empty, has refcount of 1, */
10882          /* it's not empty, if it has includes, ignorepats, or switches that are registered from
10883             another registrar. It's not empty if there are any extensions */
10884          if (strcmp(tmp->registrar, registrar) == 0 && tmp->refcount < 2 && !tmp->root && !tmp->ignorepats && !tmp->includes && AST_LIST_EMPTY(&tmp->alts)) {
10885             ast_debug(1, "delete ctx %s %s\n", tmp->name, tmp->registrar);
10886             ast_hashtab_remove_this_object(contexttab, tmp);
10887 
10888             next = tmp->next;
10889             if (tmpl)
10890                tmpl->next = next;
10891             else
10892                contexts = next;
10893             /* Okay, now we're safe to let it go -- in a sense, we were
10894                ready to let it go as soon as we locked it. */
10895             ast_unlock_context(tmp);
10896             __ast_internal_context_destroy(tmp);
10897          } else {
10898             ast_debug(1,"Couldn't delete ctx %s/%s; refc=%d; tmp.root=%p\n", tmp->name, tmp->registrar,
10899                     tmp->refcount, tmp->root);
10900             ast_unlock_context(tmp);
10901             next = tmp->next;
10902             tmpl = tmp;
10903          }
10904       } else if (con) {
10905          ast_verb(3, "Deleting context %s registrar=%s\n", tmp->name, tmp->registrar);
10906          ast_debug(1, "delete ctx %s %s\n", tmp->name, tmp->registrar);
10907          ast_hashtab_remove_this_object(contexttab, tmp);
10908 
10909          next = tmp->next;
10910          if (tmpl)
10911             tmpl->next = next;
10912          else
10913             contexts = next;
10914          /* Okay, now we're safe to let it go -- in a sense, we were
10915             ready to let it go as soon as we locked it. */
10916          ast_unlock_context(tmp);
10917          __ast_internal_context_destroy(tmp);
10918       }
10919 
10920       /* if we have a specific match, we are done, otherwise continue */
10921       tmp = con ? NULL : next;
10922    }
10923 }
10924 
10925 void ast_context_destroy(struct ast_context *con, const char *registrar)
10926 {
10927    ast_wrlock_contexts();
10928    __ast_context_destroy(contexts, contexts_table, con,registrar);
10929    ast_unlock_contexts();
10930 }
10931 
10932 static void wait_for_hangup(struct ast_channel *chan, const void *data)
10933 {
10934    int res;
10935    struct ast_frame *f;
10936    double waitsec;
10937    int waittime;
10938 
10939    if (ast_strlen_zero(data) || (sscanf(data, "%30lg", &waitsec) != 1) || (waitsec < 0))
10940       waitsec = -1;
10941    if (waitsec > -1) {
10942       waittime = waitsec * 1000.0;
10943       ast_safe_sleep(chan, waittime);
10944    } else do {
10945       res = ast_waitfor(chan, -1);
10946       if (res < 0)
10947          return;
10948       f = ast_read(chan);
10949       if (f)
10950          ast_frfree(f);
10951    } while(f);
10952 }
10953 
10954 /*!
10955  * \ingroup applications
10956  */
10957 static int pbx_builtin_proceeding(struct ast_channel *chan, const char *data)
10958 {
10959    ast_indicate(chan, AST_CONTROL_PROCEEDING);
10960    return 0;
10961 }
10962 
10963 /*!
10964  * \ingroup applications
10965  */
10966 static int pbx_builtin_progress(struct ast_channel *chan, const char *data)
10967 {
10968    ast_indicate(chan, AST_CONTROL_PROGRESS);
10969    return 0;
10970 }
10971 
10972 /*!
10973  * \ingroup applications
10974  */
10975 static int pbx_builtin_ringing(struct ast_channel *chan, const char *data)
10976 {
10977    ast_indicate(chan, AST_CONTROL_RINGING);
10978    return 0;
10979 }
10980 
10981 /*!
10982  * \ingroup applications
10983  */
10984 static int pbx_builtin_busy(struct ast_channel *chan, const char *data)
10985 {
10986    ast_indicate(chan, AST_CONTROL_BUSY);
10987    /* Don't change state of an UP channel, just indicate
10988       busy in audio */
10989    if (ast_channel_state(chan) != AST_STATE_UP) {
10990       ast_setstate(chan, AST_STATE_BUSY);
10991       ast_cdr_busy(ast_channel_cdr(chan));
10992    }
10993    wait_for_hangup(chan, data);
10994    return -1;
10995 }
10996 
10997 /*!
10998  * \ingroup applications
10999  */
11000 static int pbx_builtin_congestion(struct ast_channel *chan, const char *data)
11001 {
11002    ast_indicate(chan, AST_CONTROL_CONGESTION);
11003    /* Don't change state of an UP channel, just indicate
11004       congestion in audio */
11005    if (ast_channel_state(chan) != AST_STATE_UP) {
11006       ast_setstate(chan, AST_STATE_BUSY);
11007       ast_cdr_congestion(ast_channel_cdr(chan));
11008    }
11009    wait_for_hangup(chan, data);
11010    return -1;
11011 }
11012 
11013 /*!
11014  * \ingroup applications
11015  */
11016 static int pbx_builtin_answer(struct ast_channel *chan, const char *data)
11017 {
11018    int delay = 0;
11019    int answer_cdr = 1;
11020    char *parse;
11021    AST_DECLARE_APP_ARGS(args,
11022       AST_APP_ARG(delay);
11023       AST_APP_ARG(answer_cdr);
11024    );
11025 
11026    if (ast_strlen_zero(data)) {
11027       return __ast_answer(chan, 0, 1);
11028    }
11029 
11030    parse = ast_strdupa(data);
11031 
11032    AST_STANDARD_APP_ARGS(args, parse);
11033 
11034    if (!ast_strlen_zero(args.delay) && (ast_channel_state(chan) != AST_STATE_UP))
11035       delay = atoi(data);
11036 
11037    if (delay < 0) {
11038       delay = 0;
11039    }
11040 
11041    if (!ast_strlen_zero(args.answer_cdr) && !strcasecmp(args.answer_cdr, "nocdr")) {
11042       answer_cdr = 0;
11043    }
11044 
11045    return __ast_answer(chan, delay, answer_cdr);
11046 }
11047 
11048 static int pbx_builtin_incomplete(struct ast_channel *chan, const char *data)
11049 {
11050    const char *options = data;
11051    int answer = 1;
11052 
11053    /* Some channels can receive DTMF in unanswered state; some cannot */
11054    if (!ast_strlen_zero(options) && strchr(options, 'n')) {
11055       answer = 0;
11056    }
11057 
11058    /* If the channel is hungup, stop waiting */
11059    if (ast_check_hangup(chan)) {
11060       return -1;
11061    } else if (ast_channel_state(chan) != AST_STATE_UP && answer) {
11062       __ast_answer(chan, 0, 1);
11063    }
11064 
11065    ast_indicate(chan, AST_CONTROL_INCOMPLETE);
11066 
11067    return AST_PBX_INCOMPLETE;
11068 }
11069 
11070 AST_APP_OPTIONS(resetcdr_opts, {
11071    AST_APP_OPTION('w', AST_CDR_FLAG_POSTED),
11072    AST_APP_OPTION('a', AST_CDR_FLAG_LOCKED),
11073    AST_APP_OPTION('v', AST_CDR_FLAG_KEEP_VARS),
11074    AST_APP_OPTION('e', AST_CDR_FLAG_POST_ENABLE),
11075 });
11076 
11077 /*!
11078  * \ingroup applications
11079  */
11080 static int pbx_builtin_resetcdr(struct ast_channel *chan, const char *data)
11081 {
11082    char *args;
11083    struct ast_flags flags = { 0 };
11084 
11085    if (!ast_strlen_zero(data)) {
11086       args = ast_strdupa(data);
11087       ast_app_parse_options(resetcdr_opts, &flags, NULL, args);
11088    }
11089 
11090    ast_cdr_reset(ast_channel_cdr(chan), &flags);
11091 
11092    return 0;
11093 }
11094 
11095 /*!
11096  * \ingroup applications
11097  */
11098 static int pbx_builtin_setamaflags(struct ast_channel *chan, const char *data)
11099 {
11100    /* Copy the AMA Flags as specified */
11101    ast_channel_lock(chan);
11102    ast_cdr_setamaflags(chan, data ? data : "");
11103    ast_channel_unlock(chan);
11104    return 0;
11105 }
11106 
11107 /*!
11108  * \ingroup applications
11109  */
11110 static int pbx_builtin_hangup(struct ast_channel *chan, const char *data)
11111 {
11112    int cause;
11113 
11114    ast_set_hangupsource(chan, "dialplan/builtin", 0);
11115 
11116    if (!ast_strlen_zero(data)) {
11117       cause = ast_str2cause(data);
11118       if (cause <= 0) {
11119          if (sscanf(data, "%30d", &cause) != 1 || cause <= 0) {
11120             ast_log(LOG_WARNING, "Invalid cause given to Hangup(): \"%s\"\n", data);
11121             cause = 0;
11122          }
11123       }
11124    } else {
11125       cause = 0;
11126    }
11127 
11128    ast_channel_lock(chan);
11129    if (cause <= 0) {
11130       cause = ast_channel_hangupcause(chan);
11131       if (cause <= 0) {
11132          cause = AST_CAUSE_NORMAL_CLEARING;
11133       }
11134    }
11135    ast_channel_hangupcause_set(chan, cause);
11136    ast_softhangup_nolock(chan, AST_SOFTHANGUP_EXPLICIT);
11137    ast_channel_unlock(chan);
11138 
11139    return -1;
11140 }
11141 
11142 /*!
11143  * \ingroup functions
11144  */
11145 static int testtime_write(struct ast_channel *chan, const char *cmd, char *var, const char *value)
11146 {
11147    struct ast_tm tm;
11148    struct timeval tv;
11149    char *remainder, result[30], timezone[80];
11150 
11151    /* Turn off testing? */
11152    if (!pbx_checkcondition(value)) {
11153       pbx_builtin_setvar_helper(chan, "TESTTIME", NULL);
11154       return 0;
11155    }
11156 
11157    /* Parse specified time */
11158    if (!(remainder = ast_strptime(value, "%Y/%m/%d %H:%M:%S", &tm))) {
11159       return -1;
11160    }
11161    sscanf(remainder, "%79s", timezone);
11162    tv = ast_mktime(&tm, S_OR(timezone, NULL));
11163 
11164    snprintf(result, sizeof(result), "%ld", (long) tv.tv_sec);
11165    pbx_builtin_setvar_helper(chan, "__TESTTIME", result);
11166    return 0;
11167 }
11168 
11169 static struct ast_custom_function testtime_function = {
11170    .name = "TESTTIME",
11171    .write = testtime_write,
11172 };
11173 
11174 /*!
11175  * \ingroup applications
11176  */
11177 static int pbx_builtin_gotoiftime(struct ast_channel *chan, const char *data)
11178 {
11179    char *s, *ts, *branch1, *branch2, *branch;
11180    struct ast_timing timing;
11181    const char *ctime;
11182    struct timeval tv = ast_tvnow();
11183    long timesecs;
11184 
11185    if (!chan) {
11186       ast_log(LOG_WARNING, "GotoIfTime requires a channel on which to operate\n");
11187       return -1;
11188    }
11189 
11190    if (ast_strlen_zero(data)) {
11191       ast_log(LOG_WARNING, "GotoIfTime requires an argument:\n  <time range>,<days of week>,<days of month>,<months>[,<timezone>]?'labeliftrue':'labeliffalse'\n");
11192       return -1;
11193    }
11194 
11195    ts = s = ast_strdupa(data);
11196 
11197    ast_channel_lock(chan);
11198    if ((ctime = pbx_builtin_getvar_helper(chan, "TESTTIME")) && sscanf(ctime, "%ld", &timesecs) == 1) {
11199       tv.tv_sec = timesecs;
11200    } else if (ctime) {
11201       ast_log(LOG_WARNING, "Using current time to evaluate\n");
11202       /* Reset when unparseable */
11203       pbx_builtin_setvar_helper(chan, "TESTTIME", NULL);
11204    }
11205    ast_channel_unlock(chan);
11206 
11207    /* Separate the Goto path */
11208    strsep(&ts, "?");
11209    branch1 = strsep(&ts,":");
11210    branch2 = strsep(&ts,"");
11211 
11212    /* struct ast_include include contained garbage here, fixed by zeroing it on get_timerange */
11213    if (ast_build_timing(&timing, s) && ast_check_timing2(&timing, tv)) {
11214       branch = branch1;
11215    } else {
11216       branch = branch2;
11217    }
11218    ast_destroy_timing(&timing);
11219 
11220    if (ast_strlen_zero(branch)) {
11221       ast_debug(1, "Not taking any branch\n");
11222       return 0;
11223    }
11224 
11225    return pbx_builtin_goto(chan, branch);
11226 }
11227 
11228 /*!
11229  * \ingroup applications
11230  */
11231 static int pbx_builtin_execiftime(struct ast_channel *chan, const char *data)
11232 {
11233    char *s, *appname;
11234    struct ast_timing timing;
11235    struct ast_app *app;
11236    static const char * const usage = "ExecIfTime requires an argument:\n  <time range>,<days of week>,<days of month>,<months>[,<timezone>]?<appname>[(<appargs>)]";
11237 
11238    if (ast_strlen_zero(data)) {
11239       ast_log(LOG_WARNING, "%s\n", usage);
11240       return -1;
11241    }
11242 
11243    appname = ast_strdupa(data);
11244 
11245    s = strsep(&appname, "?"); /* Separate the timerange and application name/data */
11246    if (!appname) {   /* missing application */
11247       ast_log(LOG_WARNING, "%s\n", usage);
11248       return -1;
11249    }
11250 
11251    if (!ast_build_timing(&timing, s)) {
11252       ast_log(LOG_WARNING, "Invalid Time Spec: %s\nCorrect usage: %s\n", s, usage);
11253       ast_destroy_timing(&timing);
11254       return -1;
11255    }
11256 
11257    if (!ast_check_timing(&timing))  { /* outside the valid time window, just return */
11258       ast_destroy_timing(&timing);
11259       return 0;
11260    }
11261    ast_destroy_timing(&timing);
11262 
11263    /* now split appname(appargs) */
11264    if ((s = strchr(appname, '('))) {
11265       char *e;
11266       *s++ = '\0';
11267       if ((e = strrchr(s, ')')))
11268          *e = '\0';
11269       else
11270          ast_log(LOG_WARNING, "Failed to find closing parenthesis\n");
11271    }
11272 
11273 
11274    if ((app = pbx_findapp(appname))) {
11275       return pbx_exec(chan, app, S_OR(s, ""));
11276    } else {
11277       ast_log(LOG_WARNING, "Cannot locate application %s\n", appname);
11278       return -1;
11279    }
11280 }
11281 
11282 /*!
11283  * \ingroup applications
11284  */
11285 static int pbx_builtin_wait(struct ast_channel *chan, const char *data)
11286 {
11287    int ms;
11288 
11289    /* Wait for "n" seconds */
11290    if (!ast_app_parse_timelen(data, &ms, TIMELEN_SECONDS) && ms > 0) {
11291       return ast_safe_sleep(chan, ms);
11292    }
11293    return 0;
11294 }
11295 
11296 /*!
11297  * \ingroup applications
11298  */
11299 static int pbx_builtin_waitexten(struct ast_channel *chan, const char *data)
11300 {
11301    int ms, res;
11302    struct ast_flags flags = {0};
11303    char *opts[1] = { NULL };
11304    char *parse;
11305    AST_DECLARE_APP_ARGS(args,
11306       AST_APP_ARG(timeout);
11307       AST_APP_ARG(options);
11308    );
11309 
11310    if (!ast_strlen_zero(data)) {
11311       parse = ast_strdupa(data);
11312       AST_STANDARD_APP_ARGS(args, parse);
11313    } else
11314       memset(&args, 0, sizeof(args));
11315 
11316    if (args.options)
11317       ast_app_parse_options(waitexten_opts, &flags, opts, args.options);
11318 
11319    if (ast_test_flag(&flags, WAITEXTEN_MOH) && !opts[0] ) {
11320       ast_log(LOG_WARNING, "The 'm' option has been specified for WaitExten without a class.\n");
11321    } else if (ast_test_flag(&flags, WAITEXTEN_MOH)) {
11322       ast_indicate_data(chan, AST_CONTROL_HOLD, S_OR(opts[0], NULL),
11323          !ast_strlen_zero(opts[0]) ? strlen(opts[0]) + 1 : 0);
11324    } else if (ast_test_flag(&flags, WAITEXTEN_DIALTONE)) {
11325       struct ast_tone_zone_sound *ts = ast_get_indication_tone(ast_channel_zone(chan), "dial");
11326       if (ts) {
11327          ast_playtones_start(chan, 0, ts->data, 0);
11328          ts = ast_tone_zone_sound_unref(ts);
11329       } else {
11330          ast_tonepair_start(chan, 350, 440, 0, 0);
11331       }
11332    }
11333    /* Wait for "n" seconds */
11334    if (!ast_app_parse_timelen(args.timeout, &ms, TIMELEN_SECONDS) && ms > 0) {
11335       /* Yay! */
11336    } else if (ast_channel_pbx(chan)) {
11337       ms = ast_channel_pbx(chan)->rtimeoutms;
11338    } else {
11339       ms = 10000;
11340    }
11341 
11342    res = ast_waitfordigit(chan, ms);
11343    if (!res) {
11344       if (ast_check_hangup(chan)) {
11345          /* Call is hungup for some reason. */
11346          res = -1;
11347       } else if (ast_exists_extension(chan, ast_channel_context(chan), ast_channel_exten(chan), ast_channel_priority(chan) + 1,
11348          S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
11349          ast_verb(3, "Timeout on %s, continuing...\n", ast_channel_name(chan));
11350       } else if (ast_exists_extension(chan, ast_channel_context(chan), "t", 1,
11351          S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
11352          ast_verb(3, "Timeout on %s, going to 't'\n", ast_channel_name(chan));
11353          set_ext_pri(chan, "t", 0); /* 0 will become 1, next time through the loop */
11354       } else if (ast_exists_extension(chan, ast_channel_context(chan), "e", 1,
11355          S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
11356          raise_exception(chan, "RESPONSETIMEOUT", 0); /* 0 will become 1, next time through the loop */
11357       } else {
11358          ast_log(LOG_WARNING, "Timeout but no rule 't' or 'e' in context '%s'\n",
11359             ast_channel_context(chan));
11360          res = -1;
11361       }
11362    }
11363 
11364    if (ast_test_flag(&flags, WAITEXTEN_MOH))
11365       ast_indicate(chan, AST_CONTROL_UNHOLD);
11366    else if (ast_test_flag(&flags, WAITEXTEN_DIALTONE))
11367       ast_playtones_stop(chan);
11368 
11369    return res;
11370 }
11371 
11372 /*!
11373  * \ingroup applications
11374  */
11375 static int pbx_builtin_background(struct ast_channel *chan, const char *data)
11376 {
11377    int res = 0;
11378    int mres = 0;
11379    struct ast_flags flags = {0};
11380    char *parse, exten[2] = "";
11381    AST_DECLARE_APP_ARGS(args,
11382       AST_APP_ARG(filename);
11383       AST_APP_ARG(options);
11384       AST_APP_ARG(lang);
11385       AST_APP_ARG(context);
11386    );
11387 
11388    if (ast_strlen_zero(data)) {
11389       ast_log(LOG_WARNING, "Background requires an argument (filename)\n");
11390       return -1;
11391    }
11392 
11393    parse = ast_strdupa(data);
11394 
11395    AST_STANDARD_APP_ARGS(args, parse);
11396 
11397    if (ast_strlen_zero(args.lang))
11398       args.lang = (char *)ast_channel_language(chan); /* XXX this is const */
11399 
11400    if (ast_strlen_zero(args.context)) {
11401       const char *context;
11402       ast_channel_lock(chan);
11403       if ((context = pbx_builtin_getvar_helper(chan, "MACRO_CONTEXT"))) {
11404          args.context = ast_strdupa(context);
11405       } else {
11406          args.context = ast_strdupa(ast_channel_context(chan));
11407       }
11408       ast_channel_unlock(chan);
11409    }
11410 
11411    if (args.options) {
11412       if (!strcasecmp(args.options, "skip"))
11413          flags.flags = BACKGROUND_SKIP;
11414       else if (!strcasecmp(args.options, "noanswer"))
11415          flags.flags = BACKGROUND_NOANSWER;
11416       else
11417          ast_app_parse_options(background_opts, &flags, NULL, args.options);
11418    }
11419 
11420    /* Answer if need be */
11421    if (ast_channel_state(chan) != AST_STATE_UP) {
11422       if (ast_test_flag(&flags, BACKGROUND_SKIP)) {
11423          goto done;
11424       } else if (!ast_test_flag(&flags, BACKGROUND_NOANSWER)) {
11425          res = ast_answer(chan);
11426       }
11427    }
11428 
11429    if (!res) {
11430       char *back = ast_strip(args.filename);
11431       char *front;
11432 
11433       ast_stopstream(chan);      /* Stop anything playing */
11434       /* Stream the list of files */
11435       while (!res && (front = strsep(&back, "&")) ) {
11436          if ( (res = ast_streamfile(chan, front, args.lang)) ) {
11437             ast_log(LOG_WARNING, "ast_streamfile failed on %s for %s\n", ast_channel_name(chan), (char*)data);
11438             res = 0;
11439             mres = 1;
11440             break;
11441          }
11442          if (ast_test_flag(&flags, BACKGROUND_PLAYBACK)) {
11443             res = ast_waitstream(chan, "");
11444          } else if (ast_test_flag(&flags, BACKGROUND_MATCHEXTEN)) {
11445             res = ast_waitstream_exten(chan, args.context);
11446          } else {
11447             res = ast_waitstream(chan, AST_DIGIT_ANY);
11448          }
11449          ast_stopstream(chan);
11450       }
11451    }
11452 
11453    /*
11454     * If the single digit DTMF is an extension in the specified context, then
11455     * go there and signal no DTMF.  Otherwise, we should exit with that DTMF.
11456     * If we're in Macro, we'll exit and seek that DTMF as the beginning of an
11457     * extension in the Macro's calling context.  If we're not in Macro, then
11458     * we'll simply seek that extension in the calling context.  Previously,
11459     * someone complained about the behavior as it related to the interior of a
11460     * Gosub routine, and the fix (#14011) inadvertently broke FreePBX
11461     * (#14940).  This change should fix both of these situations, but with the
11462     * possible incompatibility that if a single digit extension does not exist
11463     * (but a longer extension COULD have matched), it would have previously
11464     * gone immediately to the "i" extension, but will now need to wait for a
11465     * timeout.
11466     *
11467     * Later, we had to add a flag to disable this workaround, because AGI
11468     * users can EXEC Background and reasonably expect that the DTMF code will
11469     * be returned (see #16434).
11470     */
11471    if (!ast_test_flag(ast_channel_flags(chan), AST_FLAG_DISABLE_WORKAROUNDS)
11472       && (exten[0] = res)
11473       && ast_canmatch_extension(chan, args.context, exten, 1,
11474          S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))
11475       && !ast_matchmore_extension(chan, args.context, exten, 1,
11476          S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
11477       char buf[2] = { 0, };
11478       snprintf(buf, sizeof(buf), "%c", res);
11479       ast_channel_exten_set(chan, buf);
11480       ast_channel_context_set(chan, args.context);
11481       ast_channel_priority_set(chan, 0);
11482       res = 0;
11483    }
11484 done:
11485    pbx_builtin_setvar_helper(chan, "BACKGROUNDSTATUS", mres ? "FAILED" : "SUCCESS");
11486    return res;
11487 }
11488 
11489 /*! Goto
11490  * \ingroup applications
11491  */
11492 static int pbx_builtin_goto(struct ast_channel *chan, const char *data)
11493 {
11494    int res = ast_parseable_goto(chan, data);
11495    if (!res)
11496       ast_verb(3, "Goto (%s,%s,%d)\n", ast_channel_context(chan), ast_channel_exten(chan), ast_channel_priority(chan) + 1);
11497    return res;
11498 }
11499 
11500 
11501 int pbx_builtin_serialize_variables(struct ast_channel *chan, struct ast_str **buf)
11502 {
11503    struct ast_var_t *variables;
11504    const char *var, *val;
11505    int total = 0;
11506 
11507    if (!chan)
11508       return 0;
11509 
11510    ast_str_reset(*buf);
11511 
11512    ast_channel_lock(chan);
11513 
11514    AST_LIST_TRAVERSE(ast_channel_varshead(chan), variables, entries) {
11515       if ((var = ast_var_name(variables)) && (val = ast_var_value(variables))
11516          /* && !ast_strlen_zero(var) && !ast_strlen_zero(val) */
11517          ) {
11518          if (ast_str_append(buf, 0, "%s=%s\n", var, val) < 0) {
11519             ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n");
11520             break;
11521          } else
11522             total++;
11523       } else
11524          break;
11525    }
11526 
11527    ast_channel_unlock(chan);
11528 
11529    return total;
11530 }
11531 
11532 const char *pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
11533 {
11534    struct ast_var_t *variables;
11535    const char *ret = NULL;
11536    int i;
11537    struct varshead *places[2] = { NULL, &globals };
11538 
11539    if (!name)
11540       return NULL;
11541 
11542    if (chan) {
11543       ast_channel_lock(chan);
11544       places[0] = ast_channel_varshead(chan);
11545    }
11546 
11547    for (i = 0; i < 2; i++) {
11548       if (!places[i])
11549          continue;
11550       if (places[i] == &globals)
11551          ast_rwlock_rdlock(&globalslock);
11552       AST_LIST_TRAVERSE(places[i], variables, entries) {
11553          if (!strcmp(name, ast_var_name(variables))) {
11554             ret = ast_var_value(variables);
11555             break;
11556          }
11557       }
11558       if (places[i] == &globals)
11559          ast_rwlock_unlock(&globalslock);
11560       if (ret)
11561          break;
11562    }
11563 
11564    if (chan)
11565       ast_channel_unlock(chan);
11566 
11567    return ret;
11568 }
11569 
11570 void pbx_builtin_pushvar_helper(struct ast_channel *chan, const char *name, const char *value)
11571 {
11572    struct ast_var_t *newvariable;
11573    struct varshead *headp;
11574 
11575    if (name[strlen(name)-1] == ')') {
11576       char *function = ast_strdupa(name);
11577 
11578       ast_log(LOG_WARNING, "Cannot push a value onto a function\n");
11579       ast_func_write(chan, function, value);
11580       return;
11581    }
11582 
11583    if (chan) {
11584       ast_channel_lock(chan);
11585       headp = ast_channel_varshead(chan);
11586    } else {
11587       ast_rwlock_wrlock(&globalslock);
11588       headp = &globals;
11589    }
11590 
11591    if (value && (newvariable = ast_var_assign(name, value))) {
11592       if (headp == &globals)
11593          ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value);
11594       AST_LIST_INSERT_HEAD(headp, newvariable, entries);
11595    }
11596 
11597    if (chan)
11598       ast_channel_unlock(chan);
11599    else
11600       ast_rwlock_unlock(&globalslock);
11601 }
11602 
11603 int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
11604 {
11605    struct ast_var_t *newvariable;
11606    struct varshead *headp;
11607    const char *nametail = name;
11608 
11609    if (name[strlen(name) - 1] == ')') {
11610       char *function = ast_strdupa(name);
11611 
11612       return ast_func_write(chan, function, value);
11613    }
11614 
11615    if (chan) {
11616       ast_channel_lock(chan);
11617       headp = ast_channel_varshead(chan);
11618    } else {
11619       ast_rwlock_wrlock(&globalslock);
11620       headp = &globals;
11621    }
11622 
11623    /* For comparison purposes, we have to strip leading underscores */
11624    if (*nametail == '_') {
11625       nametail++;
11626       if (*nametail == '_')
11627          nametail++;
11628    }
11629 
11630    AST_LIST_TRAVERSE_SAFE_BEGIN(headp, newvariable, entries) {
11631       if (strcmp(ast_var_name(newvariable), nametail) == 0) {
11632          /* there is already such a variable, delete it */
11633          AST_LIST_REMOVE_CURRENT(entries);
11634          ast_var_delete(newvariable);
11635          break;
11636       }
11637    }
11638    AST_LIST_TRAVERSE_SAFE_END;
11639 
11640    if (value && (newvariable = ast_var_assign(name, value))) {
11641       if (headp == &globals)
11642          ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value);
11643       AST_LIST_INSERT_HEAD(headp, newvariable, entries);
11644       /*** DOCUMENTATION
11645          <managerEventInstance>
11646             <synopsis>Raised when a variable is set to a particular value.</synopsis>
11647          </managerEventInstance>
11648       ***/
11649       manager_event(EVENT_FLAG_DIALPLAN, "VarSet",
11650          "Channel: %s\r\n"
11651          "Variable: %s\r\n"
11652          "Value: %s\r\n"
11653          "Uniqueid: %s\r\n",
11654          chan ? ast_channel_name(chan) : "none", name, value,
11655          chan ? ast_channel_uniqueid(chan) : "none");
11656    }
11657 
11658    if (chan)
11659       ast_channel_unlock(chan);
11660    else
11661       ast_rwlock_unlock(&globalslock);
11662    return 0;
11663 }
11664 
11665 int pbx_builtin_setvar(struct ast_channel *chan, const char *data)
11666 {
11667    char *name, *value, *mydata;
11668 
11669    if (ast_compat_app_set) {
11670       return pbx_builtin_setvar_multiple(chan, data);
11671    }
11672 
11673    if (ast_strlen_zero(data)) {
11674       ast_log(LOG_WARNING, "Set requires one variable name/value pair.\n");
11675       return 0;
11676    }
11677 
11678    mydata = ast_strdupa(data);
11679    name = strsep(&mydata, "=");
11680    value = mydata;
11681    if (!value) {
11682       ast_log(LOG_WARNING, "Set requires an '=' to be a valid assignment.\n");
11683       return 0;
11684    }
11685 
11686    if (strchr(name, ' ')) {
11687       ast_log(LOG_WARNING, "Please avoid unnecessary spaces on variables as it may lead to unexpected results ('%s' set to '%s').\n", name, mydata);
11688    }
11689 
11690    pbx_builtin_setvar_helper(chan, name, value);
11691 
11692    return 0;
11693 }
11694 
11695 int pbx_builtin_setvar_multiple(struct ast_channel *chan, const char *vdata)
11696 {
11697    char *data;
11698    int x;
11699    AST_DECLARE_APP_ARGS(args,
11700       AST_APP_ARG(pair)[24];
11701    );
11702    AST_DECLARE_APP_ARGS(pair,
11703       AST_APP_ARG(name);
11704       AST_APP_ARG(value);
11705    );
11706 
11707    if (ast_strlen_zero(vdata)) {
11708       ast_log(LOG_WARNING, "MSet requires at least one variable name/value pair.\n");
11709       return 0;
11710    }
11711 
11712    data = ast_strdupa(vdata);
11713    AST_STANDARD_APP_ARGS(args, data);
11714 
11715    for (x = 0; x < args.argc; x++) {
11716       AST_NONSTANDARD_APP_ARGS(pair, args.pair[x], '=');
11717       if (pair.argc == 2) {
11718          pbx_builtin_setvar_helper(chan, pair.name, pair.value);
11719          if (strchr(pair.name, ' '))
11720             ast_log(LOG_WARNING, "Please avoid unnecessary spaces on variables as it may lead to unexpected results ('%s' set to '%s').\n", pair.name, pair.value);
11721       } else if (!chan) {
11722          ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '='\n", pair.name);
11723       } else {
11724          ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '=' (in %s@%s:%d\n", pair.name, ast_channel_exten(chan), ast_channel_context(chan), ast_channel_priority(chan));
11725       }
11726    }
11727 
11728    return 0;
11729 }
11730 
11731 int pbx_builtin_importvar(struct ast_channel *chan, const char *data)
11732 {
11733    char *name;
11734    char *value;
11735    char *channel;
11736    char tmp[VAR_BUF_SIZE];
11737    static int deprecation_warning = 0;
11738 
11739    if (ast_strlen_zero(data)) {
11740       ast_log(LOG_WARNING, "Ignoring, since there is no variable to set\n");
11741       return 0;
11742    }
11743    tmp[0] = 0;
11744    if (!deprecation_warning) {
11745       ast_log(LOG_WARNING, "ImportVar is deprecated.  Please use Set(varname=${IMPORT(channel,variable)}) instead.\n");
11746       deprecation_warning = 1;
11747    }
11748 
11749    value = ast_strdupa(data);
11750    name = strsep(&value,"=");
11751    channel = strsep(&value,",");
11752    if (channel && value && name) { /*! \todo XXX should do !ast_strlen_zero(..) of the args ? */
11753       struct ast_channel *chan2 = ast_channel_get_by_name(channel);
11754       if (chan2) {
11755          char *s = ast_alloca(strlen(value) + 4);
11756          sprintf(s, "${%s}", value);
11757          pbx_substitute_variables_helper(chan2, s, tmp, sizeof(tmp) - 1);
11758          chan2 = ast_channel_unref(chan2);
11759       }
11760       pbx_builtin_setvar_helper(chan, name, tmp);
11761    }
11762 
11763    return(0);
11764 }
11765 
11766 static int pbx_builtin_noop(struct ast_channel *chan, const char *data)
11767 {
11768    return 0;
11769 }
11770 
11771 void pbx_builtin_clear_globals(void)
11772 {
11773    struct ast_var_t *vardata;
11774 
11775    ast_rwlock_wrlock(&globalslock);
11776    while ((vardata = AST_LIST_REMOVE_HEAD(&globals, entries)))
11777       ast_var_delete(vardata);
11778    ast_rwlock_unlock(&globalslock);
11779 }
11780 
11781 int pbx_checkcondition(const char *condition)
11782 {
11783    int res;
11784    if (ast_strlen_zero(condition)) {                /* NULL or empty strings are false */
11785       return 0;
11786    } else if (sscanf(condition, "%30d", &res) == 1) { /* Numbers are evaluated for truth */
11787       return res;
11788    } else {                                         /* Strings are true */
11789       return 1;
11790    }
11791 }
11792 
11793 static int pbx_builtin_gotoif(struct ast_channel *chan, const char *data)
11794 {
11795    char *condition, *branch1, *branch2, *branch;
11796    char *stringp;
11797 
11798    if (ast_strlen_zero(data)) {
11799       ast_log(LOG_WARNING, "Ignoring, since there is no variable to check\n");
11800       return 0;
11801    }
11802 
11803    stringp = ast_strdupa(data);
11804    condition = strsep(&stringp,"?");
11805    branch1 = strsep(&stringp,":");
11806    branch2 = strsep(&stringp,"");
11807    branch = pbx_checkcondition(condition) ? branch1 : branch2;
11808 
11809    if (ast_strlen_zero(branch)) {
11810       ast_debug(1, "Not taking any branch\n");
11811       return 0;
11812    }
11813 
11814    return pbx_builtin_goto(chan, branch);
11815 }
11816 
11817 static int pbx_builtin_saynumber(struct ast_channel *chan, const char *data)
11818 {
11819    char tmp[256];
11820    char *number = tmp;
11821    char *options;
11822 
11823    if (ast_strlen_zero(data)) {
11824       ast_log(LOG_WARNING, "SayNumber requires an argument (number)\n");
11825       return -1;
11826    }
11827    ast_copy_string(tmp, data, sizeof(tmp));
11828    strsep(&number, ",");
11829    options = strsep(&number, ",");
11830    if (options) {
11831       if ( strcasecmp(options, "f") && strcasecmp(options, "m") &&
11832          strcasecmp(options, "c") && strcasecmp(options, "n") ) {
11833          ast_log(LOG_WARNING, "SayNumber gender option is either 'f', 'm', 'c' or 'n'\n");
11834          return -1;
11835       }
11836    }
11837 
11838    if (ast_say_number(chan, atoi(tmp), "", ast_channel_language(chan), options)) {
11839       ast_log(LOG_WARNING, "We were unable to say the number %s, is it too large?\n", tmp);
11840    }
11841 
11842    return 0;
11843 }
11844 
11845 static int pbx_builtin_saydigits(struct ast_channel *chan, const char *data)
11846 {
11847    int res = 0;
11848 
11849    if (data)
11850       res = ast_say_digit_str(chan, data, "", ast_channel_language(chan));
11851    return res;
11852 }
11853 
11854 static int pbx_builtin_saycharacters(struct ast_channel *chan, const char *data)
11855 {
11856    int res = 0;
11857 
11858    if (data)
11859       res = ast_say_character_str(chan, data, "", ast_channel_language(chan));
11860    return res;
11861 }
11862 
11863 static int pbx_builtin_sayphonetic(struct ast_channel *chan, const char *data)
11864 {
11865    int res = 0;
11866 
11867    if (data)
11868       res = ast_say_phonetic_str(chan, data, "", ast_channel_language(chan));
11869    return res;
11870 }
11871 
11872 static void presencechange_destroy(void *data)
11873 {
11874    struct presencechange *pc = data;
11875    ast_free(pc->provider);
11876    ast_free(pc->subtype);
11877    ast_free(pc->message);
11878 }
11879 
11880 static void presence_state_cb(const struct ast_event *event, void *unused)
11881 {
11882    struct presencechange *pc;
11883    const char *tmp;
11884 
11885    if (!(pc = ao2_alloc(sizeof(*pc), presencechange_destroy))) {
11886       return;
11887    }
11888 
11889    tmp = ast_event_get_ie_str(event, AST_EVENT_IE_PRESENCE_PROVIDER);
11890    if (ast_strlen_zero(tmp)) {
11891       ast_log(LOG_ERROR, "Received invalid event that had no presence provider IE\n");
11892       ao2_ref(pc, -1);
11893       return;
11894    }
11895    pc->provider = ast_strdup(tmp);
11896 
11897    pc->state = ast_event_get_ie_uint(event, AST_EVENT_IE_PRESENCE_STATE);
11898    if (pc->state < 0) {
11899       ao2_ref(pc, -1);
11900       return;
11901    }
11902 
11903    if ((tmp = ast_event_get_ie_str(event, AST_EVENT_IE_PRESENCE_SUBTYPE))) {
11904       pc->subtype = ast_strdup(tmp);
11905    }
11906 
11907    if ((tmp = ast_event_get_ie_str(event, AST_EVENT_IE_PRESENCE_MESSAGE))) {
11908       pc->message = ast_strdup(tmp);
11909    }
11910 
11911    /* The task processor thread is taking our reference to the presencechange object. */
11912    if (ast_taskprocessor_push(extension_state_tps, handle_presencechange, pc) < 0) {
11913       ao2_ref(pc, -1);
11914    }
11915 }
11916 
11917 static void device_state_cb(const struct ast_event *event, void *unused)
11918 {
11919    const char *device;
11920    struct statechange *sc;
11921 
11922    device = ast_event_get_ie_str(event, AST_EVENT_IE_DEVICE);
11923    if (ast_strlen_zero(device)) {
11924       ast_log(LOG_ERROR, "Received invalid event that had no device IE\n");
11925       return;
11926    }
11927 
11928    if (!(sc = ast_calloc(1, sizeof(*sc) + strlen(device) + 1)))
11929       return;
11930    strcpy(sc->dev, device);
11931    if (ast_taskprocessor_push(extension_state_tps, handle_statechange, sc) < 0) {
11932       ast_free(sc);
11933    }
11934 }
11935 
11936 /*!
11937  * \internal
11938  * \brief Implements the hints data provider.
11939  */
11940 static int hints_data_provider_get(const struct ast_data_search *search,
11941    struct ast_data *data_root)
11942 {
11943    struct ast_data *data_hint;
11944    struct ast_hint *hint;
11945    int watchers;
11946    struct ao2_iterator i;
11947 
11948    if (ao2_container_count(hints) == 0) {
11949       return 0;
11950    }
11951 
11952    i = ao2_iterator_init(hints, 0);
11953    for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) {
11954       watchers = ao2_container_count(hint->callbacks);
11955       data_hint = ast_data_add_node(data_root, "hint");
11956       if (!data_hint) {
11957          continue;
11958       }
11959       ast_data_add_str(data_hint, "extension", ast_get_extension_name(hint->exten));
11960       ast_data_add_str(data_hint, "context", ast_get_context_name(ast_get_extension_context(hint->exten)));
11961       ast_data_add_str(data_hint, "application", ast_get_extension_app(hint->exten));
11962       ast_data_add_str(data_hint, "state", ast_extension_state2str(hint->laststate));
11963       ast_data_add_str(data_hint, "presence_state", ast_presence_state2str(hint->last_presence_state));
11964       ast_data_add_str(data_hint, "presence_subtype", S_OR(hint->last_presence_subtype, ""));
11965       ast_data_add_str(data_hint, "presence_subtype", S_OR(hint->last_presence_message, ""));
11966       ast_data_add_int(data_hint, "watchers", watchers);
11967 
11968       if (!ast_data_search_match(search, data_hint)) {
11969          ast_data_remove_node(data_root, data_hint);
11970       }
11971    }
11972    ao2_iterator_destroy(&i);
11973 
11974    return 0;
11975 }
11976 
11977 static const struct ast_data_handler hints_data_provider = {
11978    .version = AST_DATA_HANDLER_VERSION,
11979    .get = hints_data_provider_get
11980 };
11981 
11982 static const struct ast_data_entry pbx_data_providers[] = {
11983    AST_DATA_ENTRY("asterisk/core/hints", &hints_data_provider),
11984 };
11985 
11986 /*! \internal \brief Clean up resources on Asterisk shutdown.
11987  * \note Cleans up resources allocated in load_pbx */
11988 static void unload_pbx(void)
11989 {
11990    int x;
11991 
11992    if (presence_state_sub) {
11993       presence_state_sub = ast_event_unsubscribe(presence_state_sub);
11994    }
11995    if (device_state_sub) {
11996       device_state_sub = ast_event_unsubscribe(device_state_sub);
11997    }
11998 
11999    /* Unregister builtin applications */
12000    for (x = 0; x < ARRAY_LEN(builtins); x++) {
12001       ast_unregister_application(builtins[x].name);
12002    }
12003    ast_manager_unregister("ShowDialPlan");
12004    ast_cli_unregister_multiple(pbx_cli, ARRAY_LEN(pbx_cli));
12005    ast_custom_function_unregister(&exception_function);
12006    ast_custom_function_unregister(&testtime_function);
12007    ast_data_unregister(NULL);
12008    if (extension_state_tps) {
12009       extension_state_tps = ast_taskprocessor_unreference(extension_state_tps);
12010    }
12011 }
12012 
12013 int load_pbx(void)
12014 {
12015    int x;
12016 
12017    ast_register_atexit(unload_pbx);
12018 
12019    /* Initialize the PBX */
12020    ast_verb(1, "Asterisk PBX Core Initializing\n");
12021    if (!(extension_state_tps = ast_taskprocessor_get("pbx-core", 0))) {
12022       ast_log(LOG_WARNING, "failed to create pbx-core taskprocessor\n");
12023    }
12024 
12025    ast_verb(1, "Registering builtin applications:\n");
12026    ast_cli_register_multiple(pbx_cli, ARRAY_LEN(pbx_cli));
12027    ast_data_register_multiple_core(pbx_data_providers, ARRAY_LEN(pbx_data_providers));
12028    __ast_custom_function_register(&exception_function, NULL);
12029    __ast_custom_function_register(&testtime_function, NULL);
12030 
12031    /* Register builtin applications */
12032    for (x = 0; x < ARRAY_LEN(builtins); x++) {
12033       ast_verb(1, "[%s]\n", builtins[x].name);
12034       if (ast_register_application2(builtins[x].name, builtins[x].execute, NULL, NULL, NULL)) {
12035          ast_log(LOG_ERROR, "Unable to register builtin application '%s'\n", builtins[x].name);
12036          return -1;
12037       }
12038    }
12039 
12040    /* Register manager application */
12041    ast_manager_register_xml_core("ShowDialPlan", EVENT_FLAG_CONFIG | EVENT_FLAG_REPORTING, manager_show_dialplan);
12042 
12043    if (!(device_state_sub = ast_event_subscribe(AST_EVENT_DEVICE_STATE, device_state_cb, "pbx Device State Change", NULL,
12044          AST_EVENT_IE_END))) {
12045       return -1;
12046    }
12047 
12048    if (!(presence_state_sub = ast_event_subscribe(AST_EVENT_PRESENCE_STATE, presence_state_cb, "pbx Presence State Change", NULL,
12049          AST_EVENT_IE_END))) {
12050       return -1;
12051    }
12052 
12053    return 0;
12054 }
12055 
12056 /*
12057  * Lock context list functions ...
12058  */
12059 int ast_wrlock_contexts(void)
12060 {
12061    return ast_mutex_lock(&conlock);
12062 }
12063 
12064 int ast_rdlock_contexts(void)
12065 {
12066    return ast_mutex_lock(&conlock);
12067 }
12068 
12069 int ast_unlock_contexts(void)
12070 {
12071    return ast_mutex_unlock(&conlock);
12072 }
12073 
12074 /*
12075  * Lock context ...
12076  */
12077 int ast_wrlock_context(struct ast_context *con)
12078 {
12079    return ast_rwlock_wrlock(&con->lock);
12080 }
12081 
12082 int ast_rdlock_context(struct ast_context *con)
12083 {
12084    return ast_rwlock_rdlock(&con->lock);
12085 }
12086 
12087 int ast_unlock_context(struct ast_context *con)
12088 {
12089    return ast_rwlock_unlock(&con->lock);
12090 }
12091 
12092 /*
12093  * Name functions ...
12094  */
12095 const char *ast_get_context_name(struct ast_context *con)
12096 {
12097    return con ? con->name : NULL;
12098 }
12099 
12100 struct ast_context *ast_get_extension_context(struct ast_exten *exten)
12101 {
12102    return exten ? exten->parent : NULL;
12103 }
12104 
12105 const char *ast_get_extension_name(struct ast_exten *exten)
12106 {
12107    return exten ? exten->exten : NULL;
12108 }
12109 
12110 const char *ast_get_extension_label(struct ast_exten *exten)
12111 {
12112    return exten ? exten->label : NULL;
12113 }
12114 
12115 const char *ast_get_include_name(struct ast_include *inc)
12116 {
12117    return inc ? inc->name : NULL;
12118 }
12119 
12120 const char *ast_get_ignorepat_name(struct ast_ignorepat *ip)
12121 {
12122    return ip ? ip->pattern : NULL;
12123 }
12124 
12125 int ast_get_extension_priority(struct ast_exten *exten)
12126 {
12127    return exten ? exten->priority : -1;
12128 }
12129 
12130 /*
12131  * Registrar info functions ...
12132  */
12133 const char *ast_get_context_registrar(struct ast_context *c)
12134 {
12135    return c ? c->registrar : NULL;
12136 }
12137 
12138 const char *ast_get_extension_registrar(struct ast_exten *e)
12139 {
12140    return e ? e->registrar : NULL;
12141 }
12142 
12143 const char *ast_get_include_registrar(struct ast_include *i)
12144 {
12145    return i ? i->registrar : NULL;
12146 }
12147 
12148 const char *ast_get_ignorepat_registrar(struct ast_ignorepat *ip)
12149 {
12150    return ip ? ip->registrar : NULL;
12151 }
12152 
12153 int ast_get_extension_matchcid(struct ast_exten *e)
12154 {
12155    return e ? e->matchcid : 0;
12156 }
12157 
12158 const char *ast_get_extension_cidmatch(struct ast_exten *e)
12159 {
12160    return e ? e->cidmatch : NULL;
12161 }
12162 
12163 const char *ast_get_extension_app(struct ast_exten *e)
12164 {
12165    return e ? e->app : NULL;
12166 }
12167 
12168 void *ast_get_extension_app_data(struct ast_exten *e)
12169 {
12170    return e ? e->data : NULL;
12171 }
12172 
12173 const char *ast_get_switch_name(struct ast_sw *sw)
12174 {
12175    return sw ? sw->name : NULL;
12176 }
12177 
12178 const char *ast_get_switch_data(struct ast_sw *sw)
12179 {
12180    return sw ? sw->data : NULL;
12181 }
12182 
12183 int ast_get_switch_eval(struct ast_sw *sw)
12184 {
12185    return sw->eval;
12186 }
12187 
12188 const char *ast_get_switch_registrar(struct ast_sw *sw)
12189 {
12190    return sw ? sw->registrar : NULL;
12191 }
12192 
12193 /*
12194  * Walking functions ...
12195  */
12196 struct ast_context *ast_walk_contexts(struct ast_context *con)
12197 {
12198    return con ? con->next : contexts;
12199 }
12200 
12201 struct ast_exten *ast_walk_context_extensions(struct ast_context *con,
12202    struct ast_exten *exten)
12203 {
12204    if (!exten)
12205       return con ? con->root : NULL;
12206    else
12207       return exten->next;
12208 }
12209 
12210 struct ast_sw *ast_walk_context_switches(struct ast_context *con,
12211    struct ast_sw *sw)
12212 {
12213    if (!sw)
12214       return con ? AST_LIST_FIRST(&con->alts) : NULL;
12215    else
12216       return AST_LIST_NEXT(sw, list);
12217 }
12218 
12219 struct ast_exten *ast_walk_extension_priorities(struct ast_exten *exten,
12220    struct ast_exten *priority)
12221 {
12222    return priority ? priority->peer : exten;
12223 }
12224 
12225 struct ast_include *ast_walk_context_includes(struct ast_context *con,
12226    struct ast_include *inc)
12227 {
12228    if (!inc)
12229       return con ? con->includes : NULL;
12230    else
12231       return inc->next;
12232 }
12233 
12234 struct ast_ignorepat *ast_walk_context_ignorepats(struct ast_context *con,
12235    struct ast_ignorepat *ip)
12236 {
12237    if (!ip)
12238       return con ? con->ignorepats : NULL;
12239    else
12240       return ip->next;
12241 }
12242 
12243 int ast_context_verify_includes(struct ast_context *con)
12244 {
12245    struct ast_include *inc = NULL;
12246    int res = 0;
12247 
12248    while ( (inc = ast_walk_context_includes(con, inc)) ) {
12249       if (ast_context_find(inc->rname))
12250          continue;
12251 
12252       res = -1;
12253       ast_log(LOG_WARNING, "Context '%s' tries to include nonexistent context '%s'\n",
12254          ast_get_context_name(con), inc->rname);
12255       break;
12256    }
12257 
12258    return res;
12259 }
12260 
12261 
12262 static int __ast_goto_if_exists(struct ast_channel *chan, const char *context, const char *exten, int priority, int async)
12263 {
12264    int (*goto_func)(struct ast_channel *chan, const char *context, const char *exten, int priority);
12265 
12266    if (!chan)
12267       return -2;
12268 
12269    if (context == NULL)
12270       context = ast_channel_context(chan);
12271    if (exten == NULL)
12272       exten = ast_channel_exten(chan);
12273 
12274    goto_func = (async) ? ast_async_goto : ast_explicit_goto;
12275    if (ast_exists_extension(chan, context, exten, priority,
12276       S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL)))
12277       return goto_func(chan, context, exten, priority);
12278    else {
12279       return AST_PBX_GOTO_FAILED;
12280    }
12281 }
12282 
12283 int ast_goto_if_exists(struct ast_channel *chan, const char* context, const char *exten, int priority)
12284 {
12285    return __ast_goto_if_exists(chan, context, exten, priority, 0);
12286 }
12287 
12288 int ast_async_goto_if_exists(struct ast_channel *chan, const char * context, const char *exten, int priority)
12289 {
12290    return __ast_goto_if_exists(chan, context, exten, priority, 1);
12291 }
12292 
12293 static int pbx_parseable_goto(struct ast_channel *chan, const char *goto_string, int async)
12294 {
12295    char *exten, *pri, *context;
12296    char *stringp;
12297    int ipri;
12298    int mode = 0;
12299 
12300    if (ast_strlen_zero(goto_string)) {
12301       ast_log(LOG_WARNING, "Goto requires an argument ([[context,]extension,]priority)\n");
12302       return -1;
12303    }
12304    stringp = ast_strdupa(goto_string);
12305    context = strsep(&stringp, ","); /* guaranteed non-null */
12306    exten = strsep(&stringp, ",");
12307    pri = strsep(&stringp, ",");
12308    if (!exten) {  /* Only a priority in this one */
12309       pri = context;
12310       exten = NULL;
12311       context = NULL;
12312    } else if (!pri) {   /* Only an extension and priority in this one */
12313       pri = exten;
12314       exten = context;
12315       context = NULL;
12316    }
12317    if (*pri == '+') {
12318       mode = 1;
12319       pri++;
12320    } else if (*pri == '-') {
12321       mode = -1;
12322       pri++;
12323    }
12324    if (sscanf(pri, "%30d", &ipri) != 1) {
12325       ipri = ast_findlabel_extension(chan, context ? context : ast_channel_context(chan),
12326          exten ? exten : ast_channel_exten(chan), pri,
12327          S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL));
12328       if (ipri < 1) {
12329          ast_log(LOG_WARNING, "Priority '%s' must be a number > 0, or valid label\n", pri);
12330          return -1;
12331       } else
12332          mode = 0;
12333    }
12334    /* At this point we have a priority and maybe an extension and a context */
12335 
12336    if (mode)
12337       ipri = ast_channel_priority(chan) + (ipri * mode);
12338 
12339    if (async)
12340       ast_async_goto(chan, context, exten, ipri);
12341    else
12342       ast_explicit_goto(chan, context, exten, ipri);
12343 
12344    return 0;
12345 
12346 }
12347 
12348 int ast_parseable_goto(struct ast_channel *chan, const char *goto_string)
12349 {
12350    return pbx_parseable_goto(chan, goto_string, 0);
12351 }
12352 
12353 int ast_async_parseable_goto(struct ast_channel *chan, const char *goto_string)
12354 {
12355    return pbx_parseable_goto(chan, goto_string, 1);
12356 }
12357 
12358 char *ast_complete_applications(const char *line, const char *word, int state)
12359 {
12360    struct ast_app *app = NULL;
12361    int which = 0;
12362    char *ret = NULL;
12363    size_t wordlen = strlen(word);
12364 
12365    AST_RWLIST_RDLOCK(&apps);
12366    AST_RWLIST_TRAVERSE(&apps, app, list) {
12367       if (!strncasecmp(word, app->name, wordlen) && ++which > state) {
12368          ret = ast_strdup(app->name);
12369          break;
12370       }
12371    }
12372    AST_RWLIST_UNLOCK(&apps);
12373 
12374    return ret;
12375 }
12376 
12377 static int hint_hash(const void *obj, const int flags)
12378 {
12379    const struct ast_hint *hint = obj;
12380    const char *exten_name;
12381    int res;
12382 
12383    exten_name = ast_get_extension_name(hint->exten);
12384    if (ast_strlen_zero(exten_name)) {
12385       /*
12386        * If the exten or extension name isn't set, return 0 so that
12387        * the ao2_find() search will start in the first bucket.
12388        */
12389       res = 0;
12390    } else {
12391       res = ast_str_case_hash(exten_name);
12392    }
12393 
12394    return res;
12395 }
12396 
12397 static int hint_cmp(void *obj, void *arg, int flags)
12398 {
12399    const struct ast_hint *hint = obj;
12400    const struct ast_exten *exten = arg;
12401 
12402    return (hint->exten == exten) ? CMP_MATCH | CMP_STOP : 0;
12403 }
12404 
12405 static int statecbs_cmp(void *obj, void *arg, int flags)
12406 {
12407    const struct ast_state_cb *state_cb = obj;
12408    ast_state_cb_type change_cb = arg;
12409 
12410    return (state_cb->change_cb == change_cb) ? CMP_MATCH | CMP_STOP : 0;
12411 }
12412 
12413 /*!
12414  * \internal
12415  * \brief Clean up resources on Asterisk shutdown
12416  */
12417 static void pbx_shutdown(void)
12418 {
12419    if (hints) {
12420       ao2_ref(hints, -1);
12421       hints = NULL;
12422    }
12423    if (hintdevices) {
12424       ao2_ref(hintdevices, -1);
12425       hintdevices = NULL;
12426    }
12427    if (statecbs) {
12428       ao2_ref(statecbs, -1);
12429       statecbs = NULL;
12430    }
12431    if (contexts_table) {
12432       ast_hashtab_destroy(contexts_table, NULL);
12433    }
12434    pbx_builtin_clear_globals();
12435 }
12436 
12437 int ast_pbx_init(void)
12438 {
12439    hints = ao2_container_alloc(HASH_EXTENHINT_SIZE, hint_hash, hint_cmp);
12440    hintdevices = ao2_container_alloc(HASH_EXTENHINT_SIZE, hintdevice_hash_cb, hintdevice_cmp_multiple);
12441    statecbs = ao2_container_alloc(1, NULL, statecbs_cmp);
12442 
12443    ast_register_atexit(pbx_shutdown);
12444 
12445    return (hints && hintdevices && statecbs) ? 0 : -1;
12446 }