Sat Jul 12 2014 17:18:34

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: 415999 $")
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, "%d", (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    if (strstr(e->app, "${") && e->exten[0] == '_') {
05887       /* The hint is dynamic and hasn't been evaluted yet */
05888       hint_new->laststate = AST_DEVICE_INVALID;
05889       hint_new->last_presence_state = AST_PRESENCE_INVALID;
05890    } else {
05891       hint_new->laststate = ast_extension_state2(e, NULL);
05892       if ((presence_state = extension_presence_state_helper(e, &subtype, &message)) > 0) {
05893          hint_new->last_presence_state = presence_state;
05894          hint_new->last_presence_subtype = subtype;
05895          hint_new->last_presence_message = message;
05896          message = subtype = NULL;
05897       }
05898    }
05899 
05900    /* Prevent multiple add hints from adding the same hint at the same time. */
05901    ao2_lock(hints);
05902 
05903    /* Search if hint exists, do nothing */
05904    hint_found = ao2_find(hints, e, 0);
05905    if (hint_found) {
05906       ao2_ref(hint_found, -1);
05907       ao2_unlock(hints);
05908       ao2_ref(hint_new, -1);
05909       ast_debug(2, "HINTS: Not re-adding existing hint %s: %s\n",
05910          ast_get_extension_name(e), ast_get_extension_app(e));
05911       return -1;
05912    }
05913 
05914    /* Add new hint to the hints container */
05915    ast_debug(2, "HINTS: Adding hint %s: %s\n",
05916       ast_get_extension_name(e), ast_get_extension_app(e));
05917    ao2_link(hints, hint_new);
05918    if (add_hintdevice(hint_new, ast_get_extension_app(e))) {
05919       ast_log(LOG_WARNING, "Could not add devices for hint: %s@%s.\n",
05920          ast_get_extension_name(e),
05921          ast_get_context_name(ast_get_extension_context(e)));
05922    }
05923 
05924    ao2_unlock(hints);
05925    ao2_ref(hint_new, -1);
05926 
05927    return 0;
05928 }
05929 
05930 /*! \brief Change hint for an extension */
05931 static int ast_change_hint(struct ast_exten *oe, struct ast_exten *ne)
05932 {
05933    struct ast_hint *hint;
05934 
05935    if (!oe || !ne) {
05936       return -1;
05937    }
05938 
05939    ao2_lock(hints);/* Locked to hold off others while we move the hint around. */
05940 
05941    /*
05942     * Unlink the hint from the hints container as the extension
05943     * name (which is the hash value) could change.
05944     */
05945    hint = ao2_find(hints, oe, OBJ_UNLINK);
05946    if (!hint) {
05947       ao2_unlock(hints);
05948       return -1;
05949    }
05950 
05951    remove_hintdevice(hint);
05952 
05953    /* Update the hint and put it back in the hints container. */
05954    ao2_lock(hint);
05955    hint->exten = ne;
05956    ao2_unlock(hint);
05957    ao2_link(hints, hint);
05958    if (add_hintdevice(hint, ast_get_extension_app(ne))) {
05959       ast_log(LOG_WARNING, "Could not add devices for hint: %s@%s.\n",
05960          ast_get_extension_name(ne),
05961          ast_get_context_name(ast_get_extension_context(ne)));
05962    }
05963 
05964    ao2_unlock(hints);
05965    ao2_ref(hint, -1);
05966 
05967    return 0;
05968 }
05969 
05970 
05971 /*! \brief Get hint for channel */
05972 int ast_get_hint(char *hint, int hintsize, char *name, int namesize, struct ast_channel *c, const char *context, const char *exten)
05973 {
05974    struct ast_exten *e = ast_hint_extension(c, context, exten);
05975 
05976    if (e) {
05977       if (hint)
05978          ast_copy_string(hint, ast_get_extension_app(e), hintsize);
05979       if (name) {
05980          const char *tmp = ast_get_extension_app_data(e);
05981          if (tmp)
05982             ast_copy_string(name, tmp, namesize);
05983       }
05984       return -1;
05985    }
05986    return 0;
05987 }
05988 
05989 /*! \brief Get hint for channel */
05990 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)
05991 {
05992    struct ast_exten *e = ast_hint_extension(c, context, exten);
05993 
05994    if (!e) {
05995       return 0;
05996    }
05997 
05998    if (hint) {
05999       ast_str_set(hint, hintsize, "%s", ast_get_extension_app(e));
06000    }
06001    if (name) {
06002       const char *tmp = ast_get_extension_app_data(e);
06003       if (tmp) {
06004          ast_str_set(name, namesize, "%s", tmp);
06005       }
06006    }
06007    return -1;
06008 }
06009 
06010 int ast_exists_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
06011 {
06012    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCH, 0, 0);
06013 }
06014 
06015 int ast_findlabel_extension(struct ast_channel *c, const char *context, const char *exten, const char *label, const char *callerid)
06016 {
06017    return pbx_extension_helper(c, NULL, context, exten, 0, label, callerid, E_FINDLABEL, 0, 0);
06018 }
06019 
06020 int ast_findlabel_extension2(struct ast_channel *c, struct ast_context *con, const char *exten, const char *label, const char *callerid)
06021 {
06022    return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, E_FINDLABEL, 0, 0);
06023 }
06024 
06025 int ast_canmatch_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
06026 {
06027    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_CANMATCH, 0, 0);
06028 }
06029 
06030 int ast_matchmore_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
06031 {
06032    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCHMORE, 0, 0);
06033 }
06034 
06035 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)
06036 {
06037    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_SPAWN, found, combined_find_spawn);
06038 }
06039 
06040 void ast_pbx_h_exten_run(struct ast_channel *chan, const char *context)
06041 {
06042    int autoloopflag;
06043    int found;
06044    int spawn_error;
06045 
06046    ast_channel_lock(chan);
06047 
06048    if (ast_channel_cdr(chan) && ast_opt_end_cdr_before_h_exten) {
06049       ast_cdr_end(ast_channel_cdr(chan));
06050    }
06051 
06052    /* Set h exten location */
06053    if (context != ast_channel_context(chan)) {
06054       ast_channel_context_set(chan, context);
06055    }
06056    ast_channel_exten_set(chan, "h");
06057    ast_channel_priority_set(chan, 1);
06058 
06059    /*
06060     * Make sure that the channel is marked as hungup since we are
06061     * going to run the h exten on it.
06062     */
06063    ast_softhangup_nolock(chan, AST_SOFTHANGUP_APPUNLOAD);
06064 
06065    /* Save autoloop flag */
06066    autoloopflag = ast_test_flag(ast_channel_flags(chan), AST_FLAG_IN_AUTOLOOP);
06067    ast_set_flag(ast_channel_flags(chan), AST_FLAG_IN_AUTOLOOP);
06068    ast_channel_unlock(chan);
06069 
06070    for (;;) {
06071       spawn_error = ast_spawn_extension(chan, ast_channel_context(chan),
06072          ast_channel_exten(chan), ast_channel_priority(chan),
06073          S_COR(ast_channel_caller(chan)->id.number.valid,
06074             ast_channel_caller(chan)->id.number.str, NULL), &found, 1);
06075 
06076       ast_channel_lock(chan);
06077       if (spawn_error) {
06078          /* The code after the loop needs the channel locked. */
06079          break;
06080       }
06081       ast_channel_priority_set(chan, ast_channel_priority(chan) + 1);
06082       ast_channel_unlock(chan);
06083    }
06084    if (found && spawn_error) {
06085       /* Something bad happened, or a hangup has been requested. */
06086       ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n",
06087          ast_channel_context(chan), ast_channel_exten(chan),
06088          ast_channel_priority(chan), ast_channel_name(chan));
06089       ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n",
06090          ast_channel_context(chan), ast_channel_exten(chan),
06091          ast_channel_priority(chan), ast_channel_name(chan));
06092    }
06093 
06094    /* An "h" exten has been run, so indicate that one has been run. */
06095    ast_set_flag(ast_channel_flags(chan), AST_FLAG_BRIDGE_HANGUP_RUN);
06096 
06097    /* Restore autoloop flag */
06098    ast_set2_flag(ast_channel_flags(chan), autoloopflag, AST_FLAG_IN_AUTOLOOP);
06099    ast_channel_unlock(chan);
06100 }
06101 
06102 int ast_pbx_hangup_handler_run(struct ast_channel *chan)
06103 {
06104    struct ast_hangup_handler_list *handlers;
06105    struct ast_hangup_handler *h_handler;
06106 
06107    ast_channel_lock(chan);
06108    handlers = ast_channel_hangup_handlers(chan);
06109    if (AST_LIST_EMPTY(handlers)) {
06110       ast_channel_unlock(chan);
06111       return 0;
06112    }
06113 
06114    if (ast_channel_cdr(chan) && ast_opt_end_cdr_before_h_exten) {
06115       ast_cdr_end(ast_channel_cdr(chan));
06116    }
06117 
06118    /*
06119     * Make sure that the channel is marked as hungup since we are
06120     * going to run the hangup handlers on it.
06121     */
06122    ast_softhangup_nolock(chan, AST_SOFTHANGUP_APPUNLOAD);
06123 
06124    for (;;) {
06125       handlers = ast_channel_hangup_handlers(chan);
06126       h_handler = AST_LIST_REMOVE_HEAD(handlers, node);
06127       if (!h_handler) {
06128          break;
06129       }
06130 
06131       /*** DOCUMENTATION
06132          <managerEventInstance>
06133             <synopsis>Raised when a hangup handler is about to be called.</synopsis>
06134             <syntax>
06135                <parameter name="Handler">
06136                   <para>Hangup handler parameter string passed to the Gosub application.</para>
06137                </parameter>
06138             </syntax>
06139          </managerEventInstance>
06140       ***/
06141       manager_event(EVENT_FLAG_DIALPLAN, "HangupHandlerRun",
06142          "Channel: %s\r\n"
06143          "Uniqueid: %s\r\n"
06144          "Handler: %s\r\n",
06145          ast_channel_name(chan),
06146          ast_channel_uniqueid(chan),
06147          h_handler->args);
06148       ast_channel_unlock(chan);
06149 
06150       ast_app_exec_sub(NULL, chan, h_handler->args, 1);
06151       ast_free(h_handler);
06152 
06153       ast_channel_lock(chan);
06154    }
06155    ast_channel_unlock(chan);
06156    return 1;
06157 }
06158 
06159 void ast_pbx_hangup_handler_init(struct ast_channel *chan)
06160 {
06161    struct ast_hangup_handler_list *handlers;
06162 
06163    handlers = ast_channel_hangup_handlers(chan);
06164    AST_LIST_HEAD_INIT_NOLOCK(handlers);
06165 }
06166 
06167 void ast_pbx_hangup_handler_destroy(struct ast_channel *chan)
06168 {
06169    struct ast_hangup_handler_list *handlers;
06170    struct ast_hangup_handler *h_handler;
06171 
06172    ast_channel_lock(chan);
06173 
06174    /* Get rid of each of the hangup handlers on the channel */
06175    handlers = ast_channel_hangup_handlers(chan);
06176    while ((h_handler = AST_LIST_REMOVE_HEAD(handlers, node))) {
06177       ast_free(h_handler);
06178    }
06179 
06180    ast_channel_unlock(chan);
06181 }
06182 
06183 int ast_pbx_hangup_handler_pop(struct ast_channel *chan)
06184 {
06185    struct ast_hangup_handler_list *handlers;
06186    struct ast_hangup_handler *h_handler;
06187 
06188    ast_channel_lock(chan);
06189    handlers = ast_channel_hangup_handlers(chan);
06190    h_handler = AST_LIST_REMOVE_HEAD(handlers, node);
06191    if (h_handler) {
06192       /*** DOCUMENTATION
06193          <managerEventInstance>
06194             <synopsis>
06195                Raised when a hangup handler is removed from the handler
06196                stack by the CHANNEL() function.
06197             </synopsis>
06198             <syntax>
06199                <parameter name="Handler">
06200                   <para>Hangup handler parameter string passed to the Gosub application.</para>
06201                </parameter>
06202             </syntax>
06203             <see-also>
06204                <ref type="managerEvent">HangupHandlerPush</ref>
06205                <ref type="function">CHANNEL</ref>
06206             </see-also>
06207          </managerEventInstance>
06208       ***/
06209       manager_event(EVENT_FLAG_DIALPLAN, "HangupHandlerPop",
06210          "Channel: %s\r\n"
06211          "Uniqueid: %s\r\n"
06212          "Handler: %s\r\n",
06213          ast_channel_name(chan),
06214          ast_channel_uniqueid(chan),
06215          h_handler->args);
06216    }
06217    ast_channel_unlock(chan);
06218    if (h_handler) {
06219       ast_free(h_handler);
06220       return 1;
06221    }
06222    return 0;
06223 }
06224 
06225 void ast_pbx_hangup_handler_push(struct ast_channel *chan, const char *handler)
06226 {
06227    struct ast_hangup_handler_list *handlers;
06228    struct ast_hangup_handler *h_handler;
06229    const char *expanded_handler;
06230 
06231    if (ast_strlen_zero(handler)) {
06232       return;
06233    }
06234 
06235    expanded_handler = ast_app_expand_sub_args(chan, handler);
06236    if (!expanded_handler) {
06237       return;
06238    }
06239    h_handler = ast_malloc(sizeof(*h_handler) + 1 + strlen(expanded_handler));
06240    if (!h_handler) {
06241       ast_free((char *) expanded_handler);
06242       return;
06243    }
06244    strcpy(h_handler->args, expanded_handler);/* Safe */
06245    ast_free((char *) expanded_handler);
06246 
06247    ast_channel_lock(chan);
06248 
06249    handlers = ast_channel_hangup_handlers(chan);
06250    AST_LIST_INSERT_HEAD(handlers, h_handler, node);
06251 
06252    /*** DOCUMENTATION
06253       <managerEventInstance>
06254          <synopsis>
06255             Raised when a hangup handler is added to the handler
06256             stack by the CHANNEL() function.
06257          </synopsis>
06258          <syntax>
06259             <parameter name="Handler">
06260                <para>Hangup handler parameter string passed to the Gosub application.</para>
06261             </parameter>
06262          </syntax>
06263          <see-also>
06264             <ref type="managerEvent">HangupHandlerPop</ref>
06265             <ref type="function">CHANNEL</ref>
06266          </see-also>
06267       </managerEventInstance>
06268    ***/
06269    manager_event(EVENT_FLAG_DIALPLAN, "HangupHandlerPush",
06270       "Channel: %s\r\n"
06271       "Uniqueid: %s\r\n"
06272       "Handler: %s\r\n",
06273       ast_channel_name(chan),
06274       ast_channel_uniqueid(chan),
06275       h_handler->args);
06276 
06277    ast_channel_unlock(chan);
06278 }
06279 
06280 #define HANDLER_FORMAT  "%-30s %s\n"
06281 
06282 /*!
06283  * \internal
06284  * \brief CLI output the hangup handler headers.
06285  * \since 11.0
06286  *
06287  * \param fd CLI file descriptor to use.
06288  *
06289  * \return Nothing
06290  */
06291 static void ast_pbx_hangup_handler_headers(int fd)
06292 {
06293    ast_cli(fd, HANDLER_FORMAT, "Channel", "Handler");
06294 }
06295 
06296 /*!
06297  * \internal
06298  * \brief CLI output the channel hangup handlers.
06299  * \since 11.0
06300  *
06301  * \param fd CLI file descriptor to use.
06302  * \param chan Channel to show hangup handlers.
06303  *
06304  * \return Nothing
06305  */
06306 static void ast_pbx_hangup_handler_show(int fd, struct ast_channel *chan)
06307 {
06308    struct ast_hangup_handler_list *handlers;
06309    struct ast_hangup_handler *h_handler;
06310    int first = 1;
06311 
06312    ast_channel_lock(chan);
06313    handlers = ast_channel_hangup_handlers(chan);
06314    AST_LIST_TRAVERSE(handlers, h_handler, node) {
06315       ast_cli(fd, HANDLER_FORMAT, first ? ast_channel_name(chan) : "", h_handler->args);
06316       first = 0;
06317    }
06318    ast_channel_unlock(chan);
06319 }
06320 
06321 /*
06322  * \brief 'show hanguphandlers <channel>' CLI command implementation function...
06323  */
06324 static char *handle_show_hangup_channel(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
06325 {
06326    struct ast_channel *chan;
06327 
06328    switch (cmd) {
06329    case CLI_INIT:
06330       e->command = "core show hanguphandlers";
06331       e->usage =
06332          "Usage: core show hanguphandlers <channel>\n"
06333          "       Show hangup handlers of a specified channel.\n";
06334       return NULL;
06335    case CLI_GENERATE:
06336       return ast_complete_channels(a->line, a->word, a->pos, a->n, e->args);
06337    }
06338 
06339    if (a->argc < 4) {
06340       return CLI_SHOWUSAGE;
06341    }
06342 
06343    chan = ast_channel_get_by_name(a->argv[3]);
06344    if (!chan) {
06345       ast_cli(a->fd, "Channel does not exist.\n");
06346       return CLI_FAILURE;
06347    }
06348 
06349    ast_pbx_hangup_handler_headers(a->fd);
06350    ast_pbx_hangup_handler_show(a->fd, chan);
06351 
06352    ast_channel_unref(chan);
06353 
06354    return CLI_SUCCESS;
06355 }
06356 
06357 /*
06358  * \brief 'show hanguphandlers all' CLI command implementation function...
06359  */
06360 static char *handle_show_hangup_all(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
06361 {
06362    struct ast_channel_iterator *iter;
06363    struct ast_channel *chan;
06364 
06365    switch (cmd) {
06366    case CLI_INIT:
06367       e->command = "core show hanguphandlers all";
06368       e->usage =
06369          "Usage: core show hanguphandlers all\n"
06370          "       Show hangup handlers for all channels.\n";
06371       return NULL;
06372    case CLI_GENERATE:
06373       return ast_complete_channels(a->line, a->word, a->pos, a->n, e->args);
06374    }
06375 
06376    if (a->argc < 4) {
06377       return CLI_SHOWUSAGE;
06378    }
06379 
06380    iter = ast_channel_iterator_all_new();
06381    if (!iter) {
06382       return CLI_FAILURE;
06383    }
06384 
06385    ast_pbx_hangup_handler_headers(a->fd);
06386    for (; (chan = ast_channel_iterator_next(iter)); ast_channel_unref(chan)) {
06387       ast_pbx_hangup_handler_show(a->fd, chan);
06388    }
06389    ast_channel_iterator_destroy(iter);
06390 
06391    return CLI_SUCCESS;
06392 }
06393 
06394 /*! helper function to set extension and priority */
06395 static void set_ext_pri(struct ast_channel *c, const char *exten, int pri)
06396 {
06397    ast_channel_lock(c);
06398    ast_channel_exten_set(c, exten);
06399    ast_channel_priority_set(c, pri);
06400    ast_channel_unlock(c);
06401 }
06402 
06403 /*!
06404  * \brief collect digits from the channel into the buffer.
06405  * \param c, buf, buflen, pos
06406  * \param waittime is in milliseconds
06407  * \retval 0 on timeout or done.
06408  * \retval -1 on error.
06409 */
06410 static int collect_digits(struct ast_channel *c, int waittime, char *buf, int buflen, int pos)
06411 {
06412    int digit;
06413 
06414    buf[pos] = '\0';  /* make sure it is properly terminated */
06415    while (ast_matchmore_extension(c, ast_channel_context(c), buf, 1,
06416       S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
06417       /* As long as we're willing to wait, and as long as it's not defined,
06418          keep reading digits until we can't possibly get a right answer anymore.  */
06419       digit = ast_waitfordigit(c, waittime);
06420       if (ast_channel_softhangup_internal_flag(c) & AST_SOFTHANGUP_ASYNCGOTO) {
06421          ast_channel_clear_softhangup(c, AST_SOFTHANGUP_ASYNCGOTO);
06422       } else {
06423          if (!digit) /* No entry */
06424             break;
06425          if (digit < 0) /* Error, maybe a  hangup */
06426             return -1;
06427          if (pos < buflen - 1) { /* XXX maybe error otherwise ? */
06428             buf[pos++] = digit;
06429             buf[pos] = '\0';
06430          }
06431          waittime = ast_channel_pbx(c)->dtimeoutms;
06432       }
06433    }
06434    return 0;
06435 }
06436 
06437 static enum ast_pbx_result __ast_pbx_run(struct ast_channel *c,
06438       struct ast_pbx_args *args)
06439 {
06440    int found = 0; /* set if we find at least one match */
06441    int res = 0;
06442    int autoloopflag;
06443    int error = 0;    /* set an error conditions */
06444    struct ast_pbx *pbx;
06445    struct ast_callid *callid;
06446 
06447    /* A little initial setup here */
06448    if (ast_channel_pbx(c)) {
06449       ast_log(LOG_WARNING, "%s already has PBX structure??\n", ast_channel_name(c));
06450       /* XXX and now what ? */
06451       ast_free(ast_channel_pbx(c));
06452    }
06453    if (!(pbx = ast_calloc(1, sizeof(*pbx)))) {
06454       return -1;
06455    }
06456 
06457    callid = ast_read_threadstorage_callid();
06458    /* If the thread isn't already associated with a callid, we should create that association. */
06459    if (!callid) {
06460       /* Associate new PBX thread with the channel call id if it is availble.
06461        * If not, create a new one instead.
06462        */
06463       callid = ast_channel_callid(c);
06464       if (!callid) {
06465          callid = ast_create_callid();
06466          if (callid) {
06467             ast_channel_callid_set(c, callid);
06468          }
06469       }
06470       ast_callid_threadassoc_add(callid);
06471       callid = ast_callid_unref(callid);
06472    } else {
06473       /* Nothing to do here, The thread is already bound to a callid.  Let's just get rid of the reference. */
06474       ast_callid_unref(callid);
06475    }
06476 
06477    ast_channel_pbx_set(c, pbx);
06478    /* Set reasonable defaults */
06479    ast_channel_pbx(c)->rtimeoutms = 10000;
06480    ast_channel_pbx(c)->dtimeoutms = 5000;
06481 
06482    autoloopflag = ast_test_flag(ast_channel_flags(c), AST_FLAG_IN_AUTOLOOP);  /* save value to restore at the end */
06483    ast_set_flag(ast_channel_flags(c), AST_FLAG_IN_AUTOLOOP);
06484 
06485    if (ast_strlen_zero(ast_channel_exten(c))) {
06486       /* If not successful fall back to 's' - but only if there is no given exten  */
06487       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));
06488       /* XXX the original code used the existing priority in the call to
06489        * ast_exists_extension(), and reset it to 1 afterwards.
06490        * I believe the correct thing is to set it to 1 immediately.
06491       */
06492       set_ext_pri(c, "s", 1);
06493    }
06494 
06495    ast_channel_lock(c);
06496    if (ast_channel_cdr(c)) {
06497       /* allow CDR variables that have been collected after channel was created to be visible during call */
06498       ast_cdr_update(c);
06499    }
06500    ast_channel_unlock(c);
06501    for (;;) {
06502       char dst_exten[256]; /* buffer to accumulate digits */
06503       int pos = 0;      /* XXX should check bounds */
06504       int digit = 0;
06505       int invalid = 0;
06506       int timeout = 0;
06507 
06508       /* No digits pressed yet */
06509       dst_exten[pos] = '\0';
06510 
06511       /* loop on priorities in this context/exten */
06512       while (!(res = ast_spawn_extension(c, ast_channel_context(c), ast_channel_exten(c), ast_channel_priority(c),
06513          S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL),
06514          &found, 1))) {
06515          if (!ast_check_hangup(c)) {
06516             ast_channel_priority_set(c, ast_channel_priority(c) + 1);
06517             continue;
06518          }
06519 
06520          /* Check softhangup flags. */
06521          if (ast_channel_softhangup_internal_flag(c) & AST_SOFTHANGUP_ASYNCGOTO) {
06522             ast_channel_clear_softhangup(c, AST_SOFTHANGUP_ASYNCGOTO);
06523             continue;
06524          }
06525          if (ast_channel_softhangup_internal_flag(c) & AST_SOFTHANGUP_TIMEOUT) {
06526             if (ast_exists_extension(c, ast_channel_context(c), "T", 1,
06527                S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
06528                set_ext_pri(c, "T", 1);
06529                /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
06530                memset(ast_channel_whentohangup(c), 0, sizeof(*ast_channel_whentohangup(c)));
06531                ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT);
06532                continue;
06533             } else if (ast_exists_extension(c, ast_channel_context(c), "e", 1,
06534                S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
06535                raise_exception(c, "ABSOLUTETIMEOUT", 1);
06536                /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
06537                memset(ast_channel_whentohangup(c), 0, sizeof(*ast_channel_whentohangup(c)));
06538                ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT);
06539                continue;
06540             }
06541 
06542             /* Call timed out with no special extension to jump to. */
06543             error = 1;
06544             break;
06545          }
06546          ast_debug(1, "Extension %s, priority %d returned normally even though call was hung up\n",
06547             ast_channel_exten(c), ast_channel_priority(c));
06548          error = 1;
06549          break;
06550       } /* end while  - from here on we can use 'break' to go out */
06551       if (found && res) {
06552          /* Something bad happened, or a hangup has been requested. */
06553          if (strchr("0123456789ABCDEF*#", res)) {
06554             ast_debug(1, "Oooh, got something to jump out with ('%c')!\n", res);
06555             pos = 0;
06556             dst_exten[pos++] = digit = res;
06557             dst_exten[pos] = '\0';
06558          } else if (res == AST_PBX_INCOMPLETE) {
06559             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));
06560             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));
06561 
06562             /* Don't cycle on incomplete - this will happen if the only extension that matches is our "incomplete" extension */
06563             if (!ast_matchmore_extension(c, ast_channel_context(c), ast_channel_exten(c), 1,
06564                S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
06565                invalid = 1;
06566             } else {
06567                ast_copy_string(dst_exten, ast_channel_exten(c), sizeof(dst_exten));
06568                digit = 1;
06569                pos = strlen(dst_exten);
06570             }
06571          } else {
06572             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));
06573             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));
06574 
06575             if ((res == AST_PBX_ERROR)
06576                && ast_exists_extension(c, ast_channel_context(c), "e", 1,
06577                   S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
06578                /* if we are already on the 'e' exten, don't jump to it again */
06579                if (!strcmp(ast_channel_exten(c), "e")) {
06580                   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));
06581                   error = 1;
06582                } else {
06583                   raise_exception(c, "ERROR", 1);
06584                   continue;
06585                }
06586             }
06587 
06588             if (ast_channel_softhangup_internal_flag(c) & AST_SOFTHANGUP_ASYNCGOTO) {
06589                ast_channel_clear_softhangup(c, AST_SOFTHANGUP_ASYNCGOTO);
06590                continue;
06591             }
06592             if (ast_channel_softhangup_internal_flag(c) & AST_SOFTHANGUP_TIMEOUT) {
06593                if (ast_exists_extension(c, ast_channel_context(c), "T", 1,
06594                   S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
06595                   set_ext_pri(c, "T", 1);
06596                   /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
06597                   memset(ast_channel_whentohangup(c), 0, sizeof(*ast_channel_whentohangup(c)));
06598                   ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT);
06599                   continue;
06600                } else if (ast_exists_extension(c, ast_channel_context(c), "e", 1,
06601                   S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
06602                   raise_exception(c, "ABSOLUTETIMEOUT", 1);
06603                   /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
06604                   memset(ast_channel_whentohangup(c), 0, sizeof(*ast_channel_whentohangup(c)));
06605                   ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT);
06606                   continue;
06607                }
06608                /* Call timed out with no special extension to jump to. */
06609             }
06610             ast_channel_lock(c);
06611             if (ast_channel_cdr(c)) {
06612                ast_cdr_update(c);
06613             }
06614             ast_channel_unlock(c);
06615             error = 1;
06616             break;
06617          }
06618       }
06619       if (error)
06620          break;
06621 
06622       /*!\note
06623        * We get here on a failure of some kind:  non-existing extension or
06624        * hangup.  We have options, here.  We can either catch the failure
06625        * and continue, or we can drop out entirely. */
06626 
06627       if (invalid
06628          || (ast_strlen_zero(dst_exten) &&
06629             !ast_exists_extension(c, ast_channel_context(c), ast_channel_exten(c), 1,
06630             S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL)))) {
06631          /*!\note
06632           * If there is no match at priority 1, it is not a valid extension anymore.
06633           * Try to continue at "i" (for invalid) or "e" (for exception) or exit if
06634           * neither exist.
06635           */
06636          if (ast_exists_extension(c, ast_channel_context(c), "i", 1,
06637             S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
06638             ast_verb(3, "Channel '%s' sent to invalid extension: context,exten,priority=%s,%s,%d\n",
06639                ast_channel_name(c), ast_channel_context(c), ast_channel_exten(c), ast_channel_priority(c));
06640             pbx_builtin_setvar_helper(c, "INVALID_EXTEN", ast_channel_exten(c));
06641             set_ext_pri(c, "i", 1);
06642          } else if (ast_exists_extension(c, ast_channel_context(c), "e", 1,
06643             S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
06644             raise_exception(c, "INVALID", 1);
06645          } else {
06646             ast_log(LOG_WARNING, "Channel '%s' sent to invalid extension but no invalid handler: context,exten,priority=%s,%s,%d\n",
06647                ast_channel_name(c), ast_channel_context(c), ast_channel_exten(c), ast_channel_priority(c));
06648             error = 1; /* we know what to do with it */
06649             break;
06650          }
06651       } else if (ast_channel_softhangup_internal_flag(c) & AST_SOFTHANGUP_TIMEOUT) {
06652          /* If we get this far with AST_SOFTHANGUP_TIMEOUT, then we know that the "T" extension is next. */
06653          ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT);
06654       } else { /* keypress received, get more digits for a full extension */
06655          int waittime = 0;
06656          if (digit)
06657             waittime = ast_channel_pbx(c)->dtimeoutms;
06658          else if (!autofallthrough)
06659             waittime = ast_channel_pbx(c)->rtimeoutms;
06660          if (!waittime) {
06661             const char *status = pbx_builtin_getvar_helper(c, "DIALSTATUS");
06662             if (!status)
06663                status = "UNKNOWN";
06664             ast_verb(3, "Auto fallthrough, channel '%s' status is '%s'\n", ast_channel_name(c), status);
06665             if (!strcasecmp(status, "CONGESTION"))
06666                res = pbx_builtin_congestion(c, "10");
06667             else if (!strcasecmp(status, "CHANUNAVAIL"))
06668                res = pbx_builtin_congestion(c, "10");
06669             else if (!strcasecmp(status, "BUSY"))
06670                res = pbx_builtin_busy(c, "10");
06671             error = 1; /* XXX disable message */
06672             break;   /* exit from the 'for' loop */
06673          }
06674 
06675          if (collect_digits(c, waittime, dst_exten, sizeof(dst_exten), pos))
06676             break;
06677          if (res == AST_PBX_INCOMPLETE && ast_strlen_zero(&dst_exten[pos]))
06678             timeout = 1;
06679          if (!timeout
06680             && ast_exists_extension(c, ast_channel_context(c), dst_exten, 1,
06681                S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) { /* Prepare the next cycle */
06682             set_ext_pri(c, dst_exten, 1);
06683          } else {
06684             /* No such extension */
06685             if (!timeout && !ast_strlen_zero(dst_exten)) {
06686                /* An invalid extension */
06687                if (ast_exists_extension(c, ast_channel_context(c), "i", 1,
06688                   S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
06689                   ast_verb(3, "Invalid extension '%s' in context '%s' on %s\n", dst_exten, ast_channel_context(c), ast_channel_name(c));
06690                   pbx_builtin_setvar_helper(c, "INVALID_EXTEN", dst_exten);
06691                   set_ext_pri(c, "i", 1);
06692                } else if (ast_exists_extension(c, ast_channel_context(c), "e", 1,
06693                   S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
06694                   raise_exception(c, "INVALID", 1);
06695                } else {
06696                   ast_log(LOG_WARNING,
06697                      "Invalid extension '%s', but no rule 'i' or 'e' in context '%s'\n",
06698                      dst_exten, ast_channel_context(c));
06699                   found = 1; /* XXX disable message */
06700                   break;
06701                }
06702             } else {
06703                /* A simple timeout */
06704                if (ast_exists_extension(c, ast_channel_context(c), "t", 1,
06705                   S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
06706                   ast_verb(3, "Timeout on %s\n", ast_channel_name(c));
06707                   set_ext_pri(c, "t", 1);
06708                } else if (ast_exists_extension(c, ast_channel_context(c), "e", 1,
06709                   S_COR(ast_channel_caller(c)->id.number.valid, ast_channel_caller(c)->id.number.str, NULL))) {
06710                   raise_exception(c, "RESPONSETIMEOUT", 1);
06711                } else {
06712                   ast_log(LOG_WARNING,
06713                      "Timeout, but no rule 't' or 'e' in context '%s'\n",
06714                      ast_channel_context(c));
06715                   found = 1; /* XXX disable message */
06716                   break;
06717                }
06718             }
06719          }
06720          ast_channel_lock(c);
06721          if (ast_channel_cdr(c)) {
06722             ast_verb(2, "CDR updated on %s\n",ast_channel_name(c));
06723             ast_cdr_update(c);
06724          }
06725          ast_channel_unlock(c);
06726       }
06727    }
06728 
06729    if (!found && !error) {
06730       ast_log(LOG_WARNING, "Don't know what to do with '%s'\n", ast_channel_name(c));
06731    }
06732 
06733    if (!args || !args->no_hangup_chan) {
06734       ast_softhangup(c, AST_SOFTHANGUP_APPUNLOAD);
06735       if (!ast_test_flag(ast_channel_flags(c), AST_FLAG_BRIDGE_HANGUP_RUN)
06736          && ast_exists_extension(c, ast_channel_context(c), "h", 1,
06737             S_COR(ast_channel_caller(c)->id.number.valid,
06738                ast_channel_caller(c)->id.number.str, NULL))) {
06739          ast_pbx_h_exten_run(c, ast_channel_context(c));
06740       }
06741       ast_pbx_hangup_handler_run(c);
06742    }
06743 
06744    ast_set2_flag(ast_channel_flags(c), autoloopflag, AST_FLAG_IN_AUTOLOOP);
06745    ast_clear_flag(ast_channel_flags(c), AST_FLAG_BRIDGE_HANGUP_RUN); /* from one round to the next, make sure this gets cleared */
06746    pbx_destroy(ast_channel_pbx(c));
06747    ast_channel_pbx_set(c, NULL);
06748 
06749    if (!args || !args->no_hangup_chan) {
06750       ast_hangup(c);
06751    }
06752 
06753    return 0;
06754 }
06755 
06756 /*!
06757  * \brief Increase call count for channel
06758  * \retval 0 on success
06759  * \retval non-zero if a configured limit (maxcalls, maxload, minmemfree) was reached
06760 */
06761 static int increase_call_count(const struct ast_channel *c)
06762 {
06763    int failed = 0;
06764    double curloadavg;
06765 #if defined(HAVE_SYSINFO)
06766    long curfreemem;
06767    struct sysinfo sys_info;
06768 #endif
06769 
06770    ast_mutex_lock(&maxcalllock);
06771    if (option_maxcalls) {
06772       if (countcalls >= option_maxcalls) {
06773          ast_log(LOG_WARNING, "Maximum call limit of %d calls exceeded by '%s'!\n", option_maxcalls, ast_channel_name(c));
06774          failed = -1;
06775       }
06776    }
06777    if (option_maxload) {
06778       getloadavg(&curloadavg, 1);
06779       if (curloadavg >= option_maxload) {
06780          ast_log(LOG_WARNING, "Maximum loadavg limit of %f load exceeded by '%s' (currently %f)!\n", option_maxload, ast_channel_name(c), curloadavg);
06781          failed = -1;
06782       }
06783    }
06784 #if defined(HAVE_SYSINFO)
06785    if (option_minmemfree) {
06786       if (!sysinfo(&sys_info)) {
06787          /* make sure that the free system memory is above the configured low watermark
06788           * convert the amount of freeram from mem_units to MB */
06789          curfreemem = sys_info.freeram * sys_info.mem_unit;
06790          curfreemem /= 1024 * 1024;
06791          if (curfreemem < option_minmemfree) {
06792             ast_log(LOG_WARNING, "Available system memory (~%ldMB) is below the configured low watermark (%ldMB)\n", curfreemem, option_minmemfree);
06793             failed = -1;
06794          }
06795       }
06796    }
06797 #endif
06798 
06799    if (!failed) {
06800       countcalls++;
06801       totalcalls++;
06802    }
06803    ast_mutex_unlock(&maxcalllock);
06804 
06805    return failed;
06806 }
06807 
06808 static void decrease_call_count(void)
06809 {
06810    ast_mutex_lock(&maxcalllock);
06811    if (countcalls > 0)
06812       countcalls--;
06813    ast_mutex_unlock(&maxcalllock);
06814 }
06815 
06816 static void destroy_exten(struct ast_exten *e)
06817 {
06818    if (e->priority == PRIORITY_HINT)
06819       ast_remove_hint(e);
06820 
06821    if (e->peer_table)
06822       ast_hashtab_destroy(e->peer_table,0);
06823    if (e->peer_label_table)
06824       ast_hashtab_destroy(e->peer_label_table, 0);
06825    if (e->datad)
06826       e->datad(e->data);
06827    ast_free(e);
06828 }
06829 
06830 static void *pbx_thread(void *data)
06831 {
06832    /* Oh joyeous kernel, we're a new thread, with nothing to do but
06833       answer this channel and get it going.
06834    */
06835    /* NOTE:
06836       The launcher of this function _MUST_ increment 'countcalls'
06837       before invoking the function; it will be decremented when the
06838       PBX has finished running on the channel
06839     */
06840    struct ast_channel *c = data;
06841 
06842    __ast_pbx_run(c, NULL);
06843    decrease_call_count();
06844 
06845    pthread_exit(NULL);
06846 
06847    return NULL;
06848 }
06849 
06850 enum ast_pbx_result ast_pbx_start(struct ast_channel *c)
06851 {
06852    pthread_t t;
06853 
06854    if (!c) {
06855       ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n");
06856       return AST_PBX_FAILED;
06857    }
06858 
06859    if (!ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) {
06860       ast_log(LOG_WARNING, "PBX requires Asterisk to be fully booted\n");
06861       return AST_PBX_FAILED;
06862    }
06863 
06864    if (increase_call_count(c))
06865       return AST_PBX_CALL_LIMIT;
06866 
06867    /* Start a new thread, and get something handling this channel. */
06868    if (ast_pthread_create_detached(&t, NULL, pbx_thread, c)) {
06869       ast_log(LOG_WARNING, "Failed to create new channel thread\n");
06870       decrease_call_count();
06871       return AST_PBX_FAILED;
06872    }
06873 
06874    return AST_PBX_SUCCESS;
06875 }
06876 
06877 enum ast_pbx_result ast_pbx_run_args(struct ast_channel *c, struct ast_pbx_args *args)
06878 {
06879    enum ast_pbx_result res = AST_PBX_SUCCESS;
06880 
06881    if (!ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) {
06882       ast_log(LOG_WARNING, "PBX requires Asterisk to be fully booted\n");
06883       return AST_PBX_FAILED;
06884    }
06885 
06886    if (increase_call_count(c)) {
06887       return AST_PBX_CALL_LIMIT;
06888    }
06889 
06890    res = __ast_pbx_run(c, args);
06891 
06892    decrease_call_count();
06893 
06894    return res;
06895 }
06896 
06897 enum ast_pbx_result ast_pbx_run(struct ast_channel *c)
06898 {
06899    return ast_pbx_run_args(c, NULL);
06900 }
06901 
06902 int ast_active_calls(void)
06903 {
06904    return countcalls;
06905 }
06906 
06907 int ast_processed_calls(void)
06908 {
06909    return totalcalls;
06910 }
06911 
06912 int pbx_set_autofallthrough(int newval)
06913 {
06914    int oldval = autofallthrough;
06915    autofallthrough = newval;
06916    return oldval;
06917 }
06918 
06919 int pbx_set_extenpatternmatchnew(int newval)
06920 {
06921    int oldval = extenpatternmatchnew;
06922    extenpatternmatchnew = newval;
06923    return oldval;
06924 }
06925 
06926 void pbx_set_overrideswitch(const char *newval)
06927 {
06928    if (overrideswitch) {
06929       ast_free(overrideswitch);
06930    }
06931    if (!ast_strlen_zero(newval)) {
06932       overrideswitch = ast_strdup(newval);
06933    } else {
06934       overrideswitch = NULL;
06935    }
06936 }
06937 
06938 /*!
06939  * \brief lookup for a context with a given name,
06940  * \retval found context or NULL if not found.
06941  */
06942 static struct ast_context *find_context(const char *context)
06943 {
06944    struct fake_context item;
06945 
06946    ast_copy_string(item.name, context, sizeof(item.name));
06947 
06948    return ast_hashtab_lookup(contexts_table, &item);
06949 }
06950 
06951 /*!
06952  * \brief lookup for a context with a given name,
06953  * \retval with conlock held if found.
06954  * \retval NULL if not found.
06955  */
06956 static struct ast_context *find_context_locked(const char *context)
06957 {
06958    struct ast_context *c;
06959    struct fake_context item;
06960 
06961    ast_copy_string(item.name, context, sizeof(item.name));
06962 
06963    ast_rdlock_contexts();
06964    c = ast_hashtab_lookup(contexts_table, &item);
06965    if (!c) {
06966       ast_unlock_contexts();
06967    }
06968 
06969    return c;
06970 }
06971 
06972 /*!
06973  * \brief Remove included contexts.
06974  * This function locks contexts list by &conlist, search for the right context
06975  * structure, leave context list locked and call ast_context_remove_include2
06976  * which removes include, unlock contexts list and return ...
06977  */
06978 int ast_context_remove_include(const char *context, const char *include, const char *registrar)
06979 {
06980    int ret = -1;
06981    struct ast_context *c;
06982 
06983    c = find_context_locked(context);
06984    if (c) {
06985       /* found, remove include from this context ... */
06986       ret = ast_context_remove_include2(c, include, registrar);
06987       ast_unlock_contexts();
06988    }
06989    return ret;
06990 }
06991 
06992 /*!
06993  * \brief Locks context, remove included contexts, unlocks context.
06994  * When we call this function, &conlock lock must be locked, because when
06995  * we giving *con argument, some process can remove/change this context
06996  * and after that there can be segfault.
06997  *
06998  * \retval 0 on success.
06999  * \retval -1 on failure.
07000  */
07001 int ast_context_remove_include2(struct ast_context *con, const char *include, const char *registrar)
07002 {
07003    struct ast_include *i, *pi = NULL;
07004    int ret = -1;
07005 
07006    ast_wrlock_context(con);
07007 
07008    /* find our include */
07009    for (i = con->includes; i; pi = i, i = i->next) {
07010       if (!strcmp(i->name, include) &&
07011             (!registrar || !strcmp(i->registrar, registrar))) {
07012          /* remove from list */
07013          ast_verb(3, "Removing inclusion of context '%s' in context '%s; registrar=%s'\n", include, ast_get_context_name(con), registrar);
07014          if (pi)
07015             pi->next = i->next;
07016          else
07017             con->includes = i->next;
07018          /* free include and return */
07019          ast_destroy_timing(&(i->timing));
07020          ast_free(i);
07021          ret = 0;
07022          break;
07023       }
07024    }
07025 
07026    ast_unlock_context(con);
07027 
07028    return ret;
07029 }
07030 
07031 /*!
07032  * \note This function locks contexts list by &conlist, search for the rigt context
07033  * structure, leave context list locked and call ast_context_remove_switch2
07034  * which removes switch, unlock contexts list and return ...
07035  */
07036 int ast_context_remove_switch(const char *context, const char *sw, const char *data, const char *registrar)
07037 {
07038    int ret = -1; /* default error return */
07039    struct ast_context *c;
07040 
07041    c = find_context_locked(context);
07042    if (c) {
07043       /* remove switch from this context ... */
07044       ret = ast_context_remove_switch2(c, sw, data, registrar);
07045       ast_unlock_contexts();
07046    }
07047    return ret;
07048 }
07049 
07050 /*!
07051  * \brief This function locks given context, removes switch, unlock context and
07052  * return.
07053  * \note When we call this function, &conlock lock must be locked, because when
07054  * we giving *con argument, some process can remove/change this context
07055  * and after that there can be segfault.
07056  *
07057  */
07058 int ast_context_remove_switch2(struct ast_context *con, const char *sw, const char *data, const char *registrar)
07059 {
07060    struct ast_sw *i;
07061    int ret = -1;
07062 
07063    ast_wrlock_context(con);
07064 
07065    /* walk switches */
07066    AST_LIST_TRAVERSE_SAFE_BEGIN(&con->alts, i, list) {
07067       if (!strcmp(i->name, sw) && !strcmp(i->data, data) &&
07068          (!registrar || !strcmp(i->registrar, registrar))) {
07069          /* found, remove from list */
07070          ast_verb(3, "Removing switch '%s' from context '%s; registrar=%s'\n", sw, ast_get_context_name(con), registrar);
07071          AST_LIST_REMOVE_CURRENT(list);
07072          ast_free(i); /* free switch and return */
07073          ret = 0;
07074          break;
07075       }
07076    }
07077    AST_LIST_TRAVERSE_SAFE_END;
07078 
07079    ast_unlock_context(con);
07080 
07081    return ret;
07082 }
07083 
07084 /*! \note This function will lock conlock. */
07085 int ast_context_remove_extension(const char *context, const char *extension, int priority, const char *registrar)
07086 {
07087    return ast_context_remove_extension_callerid(context, extension, priority, NULL, AST_EXT_MATCHCID_ANY, registrar);
07088 }
07089 
07090 int ast_context_remove_extension_callerid(const char *context, const char *extension, int priority, const char *callerid, int matchcallerid, const char *registrar)
07091 {
07092    int ret = -1; /* default error return */
07093    struct ast_context *c;
07094 
07095    c = find_context_locked(context);
07096    if (c) { /* ... remove extension ... */
07097       ret = ast_context_remove_extension_callerid2(c, extension, priority, callerid,
07098          matchcallerid, registrar, 0);
07099       ast_unlock_contexts();
07100    }
07101 
07102    return ret;
07103 }
07104 
07105 /*!
07106  * \brief This functionc locks given context, search for the right extension and
07107  * fires out all peer in this extensions with given priority. If priority
07108  * is set to 0, all peers are removed. After that, unlock context and
07109  * return.
07110  * \note When do you want to call this function, make sure that &conlock is locked,
07111  * because some process can handle with your *con context before you lock
07112  * it.
07113  *
07114  */
07115 int ast_context_remove_extension2(struct ast_context *con, const char *extension, int priority, const char *registrar, int already_locked)
07116 {
07117    return ast_context_remove_extension_callerid2(con, extension, priority, NULL, AST_EXT_MATCHCID_ANY, registrar, already_locked);
07118 }
07119 
07120 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)
07121 {
07122    struct ast_exten *exten, *prev_exten = NULL;
07123    struct ast_exten *peer;
07124    struct ast_exten ex, *exten2, *exten3;
07125    char dummy_name[1024];
07126    struct ast_exten *previous_peer = NULL;
07127    struct ast_exten *next_peer = NULL;
07128    int found = 0;
07129 
07130    if (!already_locked)
07131       ast_wrlock_context(con);
07132 
07133 #ifdef NEED_DEBUG
07134    ast_verb(3,"Removing %s/%s/%d%s%s from trees, registrar=%s\n", con->name, extension, priority, matchcallerid ? "/" : "", matchcallerid ? callerid : "", registrar);
07135 #endif
07136 #ifdef CONTEXT_DEBUG
07137    check_contexts(__FILE__, __LINE__);
07138 #endif
07139    /* find this particular extension */
07140    ex.exten = dummy_name;
07141    ex.matchcid = matchcallerid;
07142    ex.cidmatch = callerid;
07143    ast_copy_string(dummy_name, extension, sizeof(dummy_name));
07144    exten = ast_hashtab_lookup(con->root_table, &ex);
07145    if (exten) {
07146       if (priority == 0) {
07147          exten2 = ast_hashtab_remove_this_object(con->root_table, exten);
07148          if (!exten2)
07149             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);
07150          if (con->pattern_tree) {
07151             struct match_char *x = add_exten_to_pattern_tree(con, exten, 1);
07152 
07153             if (x->exten) { /* this test for safety purposes */
07154                x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */
07155                x->exten = 0; /* get rid of what will become a bad pointer */
07156             } else {
07157                ast_log(LOG_WARNING,"Trying to delete an exten from a context, but the pattern tree node returned isn't a full extension\n");
07158             }
07159          }
07160       } else {
07161          ex.priority = priority;
07162          exten2 = ast_hashtab_lookup(exten->peer_table, &ex);
07163          if (exten2) {
07164             if (exten2->label) { /* if this exten has a label, remove that, too */
07165                exten3 = ast_hashtab_remove_this_object(exten->peer_label_table,exten2);
07166                if (!exten3)
07167                   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);
07168             }
07169 
07170             exten3 = ast_hashtab_remove_this_object(exten->peer_table, exten2);
07171             if (!exten3)
07172                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);
07173             if (exten2 == exten && exten2->peer) {
07174                exten2 = ast_hashtab_remove_this_object(con->root_table, exten);
07175                ast_hashtab_insert_immediate(con->root_table, exten2->peer);
07176             }
07177             if (ast_hashtab_size(exten->peer_table) == 0) {
07178                /* well, if the last priority of an exten is to be removed,
07179                   then, the extension is removed, too! */
07180                exten3 = ast_hashtab_remove_this_object(con->root_table, exten);
07181                if (!exten3)
07182                   ast_log(LOG_ERROR,"Did not remove this exten (%s) from the context root_table (%s) (priority %d)\n", exten->exten, con->name, priority);
07183                if (con->pattern_tree) {
07184                   struct match_char *x = add_exten_to_pattern_tree(con, exten, 1);
07185                   if (x->exten) { /* this test for safety purposes */
07186                      x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */
07187                      x->exten = 0; /* get rid of what will become a bad pointer */
07188                   }
07189                }
07190             }
07191          } else {
07192             ast_log(LOG_ERROR,"Could not find priority %d of exten %s in context %s!\n",
07193                   priority, exten->exten, con->name);
07194          }
07195       }
07196    } else {
07197       /* hmmm? this exten is not in this pattern tree? */
07198       ast_log(LOG_WARNING,"Cannot find extension %s in root_table in context %s\n",
07199             extension, con->name);
07200    }
07201 #ifdef NEED_DEBUG
07202    if (con->pattern_tree) {
07203       ast_log(LOG_NOTICE,"match char tree after exten removal:\n");
07204       log_match_char_tree(con->pattern_tree, " ");
07205    }
07206 #endif
07207 
07208    /* scan the extension list to find first matching extension-registrar */
07209    for (exten = con->root; exten; prev_exten = exten, exten = exten->next) {
07210       if (!strcmp(exten->exten, extension) &&
07211          (!registrar || !strcmp(exten->registrar, registrar)) &&
07212          (!matchcallerid || (!ast_strlen_zero(callerid) && !ast_strlen_zero(exten->cidmatch) && !strcmp(exten->cidmatch, callerid)) || (ast_strlen_zero(callerid) && ast_strlen_zero(exten->cidmatch))))
07213          break;
07214    }
07215    if (!exten) {
07216       /* we can't find right extension */
07217       if (!already_locked)
07218          ast_unlock_context(con);
07219       return -1;
07220    }
07221 
07222    /* scan the priority list to remove extension with exten->priority == priority */
07223    for (peer = exten, next_peer = exten->peer ? exten->peer : exten->next;
07224        peer && !strcmp(peer->exten, extension) &&
07225          (!callerid || (!matchcallerid && !peer->matchcid) || (matchcallerid && peer->matchcid && !strcmp(peer->cidmatch, callerid))) ;
07226          peer = next_peer, next_peer = next_peer ? (next_peer->peer ? next_peer->peer : next_peer->next) : NULL) {
07227 
07228       if ((priority == 0 || peer->priority == priority) &&
07229             (!registrar || !strcmp(peer->registrar, registrar) )) {
07230          found = 1;
07231 
07232          /* we are first priority extension? */
07233          if (!previous_peer) {
07234             /*
07235              * We are first in the priority chain, so must update the extension chain.
07236              * The next node is either the next priority or the next extension
07237              */
07238             struct ast_exten *next_node = peer->peer ? peer->peer : peer->next;
07239             if (peer->peer) {
07240                /* move the peer_table and peer_label_table down to the next peer, if
07241                   it is there */
07242                peer->peer->peer_table = peer->peer_table;
07243                peer->peer->peer_label_table = peer->peer_label_table;
07244                peer->peer_table = NULL;
07245                peer->peer_label_table = NULL;
07246             }
07247             if (!prev_exten) {   /* change the root... */
07248                con->root = next_node;
07249             } else {
07250                prev_exten->next = next_node; /* unlink */
07251             }
07252             if (peer->peer)   { /* update the new head of the pri list */
07253                peer->peer->next = peer->next;
07254             }
07255          } else { /* easy, we are not first priority in extension */
07256             previous_peer->peer = peer->peer;
07257          }
07258 
07259 
07260          /* now, free whole priority extension */
07261          destroy_exten(peer);
07262       } else {
07263          previous_peer = peer;
07264       }
07265    }
07266    if (!already_locked)
07267       ast_unlock_context(con);
07268    return found ? 0 : -1;
07269 }
07270 
07271 
07272 /*!
07273  * \note This function locks contexts list by &conlist, searches for the right context
07274  * structure, and locks the macrolock mutex in that context.
07275  * macrolock is used to limit a macro to be executed by one call at a time.
07276  */
07277 int ast_context_lockmacro(const char *context)
07278 {
07279    struct ast_context *c;
07280    int ret = -1;
07281 
07282    c = find_context_locked(context);
07283    if (c) {
07284       ast_unlock_contexts();
07285 
07286       /* if we found context, lock macrolock */
07287       ret = ast_mutex_lock(&c->macrolock);
07288    }
07289 
07290    return ret;
07291 }
07292 
07293 /*!
07294  * \note This function locks contexts list by &conlist, searches for the right context
07295  * structure, and unlocks the macrolock mutex in that context.
07296  * macrolock is used to limit a macro to be executed by one call at a time.
07297  */
07298 int ast_context_unlockmacro(const char *context)
07299 {
07300    struct ast_context *c;
07301    int ret = -1;
07302 
07303    c = find_context_locked(context);
07304    if (c) {
07305       ast_unlock_contexts();
07306 
07307       /* if we found context, unlock macrolock */
07308       ret = ast_mutex_unlock(&c->macrolock);
07309    }
07310 
07311    return ret;
07312 }
07313 
07314 /*! \brief Dynamically register a new dial plan application */
07315 int ast_register_application2(const char *app, int (*execute)(struct ast_channel *, const char *), const char *synopsis, const char *description, void *mod)
07316 {
07317    struct ast_app *tmp, *cur = NULL;
07318    char tmps[80];
07319    int length, res;
07320 #ifdef AST_XML_DOCS
07321    char *tmpxml;
07322 #endif
07323 
07324    AST_RWLIST_WRLOCK(&apps);
07325    AST_RWLIST_TRAVERSE(&apps, tmp, list) {
07326       if (!(res = strcasecmp(app, tmp->name))) {
07327          ast_log(LOG_WARNING, "Already have an application '%s'\n", app);
07328          AST_RWLIST_UNLOCK(&apps);
07329          return -1;
07330       } else if (res < 0)
07331          break;
07332    }
07333 
07334    length = sizeof(*tmp) + strlen(app) + 1;
07335 
07336    if (!(tmp = ast_calloc(1, length))) {
07337       AST_RWLIST_UNLOCK(&apps);
07338       return -1;
07339    }
07340 
07341    if (ast_string_field_init(tmp, 128)) {
07342       AST_RWLIST_UNLOCK(&apps);
07343       ast_free(tmp);
07344       return -1;
07345    }
07346 
07347    strcpy(tmp->name, app);
07348    tmp->execute = execute;
07349    tmp->module = mod;
07350 
07351 #ifdef AST_XML_DOCS
07352    /* Try to lookup the docs in our XML documentation database */
07353    if (ast_strlen_zero(synopsis) && ast_strlen_zero(description)) {
07354       /* load synopsis */
07355       tmpxml = ast_xmldoc_build_synopsis("application", app, ast_module_name(tmp->module));
07356       ast_string_field_set(tmp, synopsis, tmpxml);
07357       ast_free(tmpxml);
07358 
07359       /* load description */
07360       tmpxml = ast_xmldoc_build_description("application", app, ast_module_name(tmp->module));
07361       ast_string_field_set(tmp, description, tmpxml);
07362       ast_free(tmpxml);
07363 
07364       /* load syntax */
07365       tmpxml = ast_xmldoc_build_syntax("application", app, ast_module_name(tmp->module));
07366       ast_string_field_set(tmp, syntax, tmpxml);
07367       ast_free(tmpxml);
07368 
07369       /* load arguments */
07370       tmpxml = ast_xmldoc_build_arguments("application", app, ast_module_name(tmp->module));
07371       ast_string_field_set(tmp, arguments, tmpxml);
07372       ast_free(tmpxml);
07373 
07374       /* load seealso */
07375       tmpxml = ast_xmldoc_build_seealso("application", app, ast_module_name(tmp->module));
07376       ast_string_field_set(tmp, seealso, tmpxml);
07377       ast_free(tmpxml);
07378       tmp->docsrc = AST_XML_DOC;
07379    } else {
07380 #endif
07381       ast_string_field_set(tmp, synopsis, synopsis);
07382       ast_string_field_set(tmp, description, description);
07383 #ifdef AST_XML_DOCS
07384       tmp->docsrc = AST_STATIC_DOC;
07385    }
07386 #endif
07387 
07388    /* Store in alphabetical order */
07389    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&apps, cur, list) {
07390       if (strcasecmp(tmp->name, cur->name) < 0) {
07391          AST_RWLIST_INSERT_BEFORE_CURRENT(tmp, list);
07392          break;
07393       }
07394    }
07395    AST_RWLIST_TRAVERSE_SAFE_END;
07396    if (!cur)
07397       AST_RWLIST_INSERT_TAIL(&apps, tmp, list);
07398 
07399    ast_verb(2, "Registered application '%s'\n", term_color(tmps, tmp->name, COLOR_BRCYAN, 0, sizeof(tmps)));
07400 
07401    AST_RWLIST_UNLOCK(&apps);
07402 
07403    return 0;
07404 }
07405 
07406 /*
07407  * Append to the list. We don't have a tail pointer because we need
07408  * to scan the list anyways to check for duplicates during insertion.
07409  */
07410 int ast_register_switch(struct ast_switch *sw)
07411 {
07412    struct ast_switch *tmp;
07413 
07414    AST_RWLIST_WRLOCK(&switches);
07415    AST_RWLIST_TRAVERSE(&switches, tmp, list) {
07416       if (!strcasecmp(tmp->name, sw->name)) {
07417          AST_RWLIST_UNLOCK(&switches);
07418          ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name);
07419          return -1;
07420       }
07421    }
07422    AST_RWLIST_INSERT_TAIL(&switches, sw, list);
07423    AST_RWLIST_UNLOCK(&switches);
07424 
07425    return 0;
07426 }
07427 
07428 void ast_unregister_switch(struct ast_switch *sw)
07429 {
07430    AST_RWLIST_WRLOCK(&switches);
07431    AST_RWLIST_REMOVE(&switches, sw, list);
07432    AST_RWLIST_UNLOCK(&switches);
07433 }
07434 
07435 /*
07436  * Help for CLI commands ...
07437  */
07438 
07439 static void print_app_docs(struct ast_app *aa, int fd)
07440 {
07441    /* Maximum number of characters added by terminal coloring is 22 */
07442    char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40], stxtitle[40], argtitle[40];
07443    char seealsotitle[40];
07444    char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL, *syntax = NULL, *arguments = NULL;
07445    char *seealso = NULL;
07446    int syntax_size, synopsis_size, description_size, arguments_size, seealso_size;
07447 
07448    snprintf(info, sizeof(info), "\n  -= Info about application '%s' =- \n\n", aa->name);
07449    term_color(infotitle, info, COLOR_MAGENTA, 0, sizeof(infotitle));
07450 
07451    term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40);
07452    term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40);
07453    term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, 40);
07454    term_color(argtitle, "[Arguments]\n", COLOR_MAGENTA, 0, 40);
07455    term_color(seealsotitle, "[See Also]\n", COLOR_MAGENTA, 0, 40);
07456 
07457 #ifdef AST_XML_DOCS
07458    if (aa->docsrc == AST_XML_DOC) {
07459       description = ast_xmldoc_printable(S_OR(aa->description, "Not available"), 1);
07460       arguments = ast_xmldoc_printable(S_OR(aa->arguments, "Not available"), 1);
07461       synopsis = ast_xmldoc_printable(S_OR(aa->synopsis, "Not available"), 1);
07462       seealso = ast_xmldoc_printable(S_OR(aa->seealso, "Not available"), 1);
07463 
07464       if (!synopsis || !description || !arguments || !seealso) {
07465          goto return_cleanup;
07466       }
07467    } else
07468 #endif
07469    {
07470       synopsis_size = strlen(S_OR(aa->synopsis, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
07471       synopsis = ast_malloc(synopsis_size);
07472 
07473       description_size = strlen(S_OR(aa->description, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
07474       description = ast_malloc(description_size);
07475 
07476       arguments_size = strlen(S_OR(aa->arguments, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
07477       arguments = ast_malloc(arguments_size);
07478 
07479       seealso_size = strlen(S_OR(aa->seealso, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
07480       seealso = ast_malloc(seealso_size);
07481 
07482       if (!synopsis || !description || !arguments || !seealso) {
07483          goto return_cleanup;
07484       }
07485 
07486       term_color(synopsis, S_OR(aa->synopsis, "Not available"), COLOR_CYAN, 0, synopsis_size);
07487       term_color(description, S_OR(aa->description, "Not available"),   COLOR_CYAN, 0, description_size);
07488       term_color(arguments, S_OR(aa->arguments, "Not available"), COLOR_CYAN, 0, arguments_size);
07489       term_color(seealso, S_OR(aa->seealso, "Not available"), COLOR_CYAN, 0, seealso_size);
07490    }
07491 
07492    /* Handle the syntax the same for both XML and raw docs */
07493    syntax_size = strlen(S_OR(aa->syntax, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
07494    if (!(syntax = ast_malloc(syntax_size))) {
07495       goto return_cleanup;
07496    }
07497    term_color(syntax, S_OR(aa->syntax, "Not available"), COLOR_CYAN, 0, syntax_size);
07498 
07499    ast_cli(fd, "%s%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n",
07500          infotitle, syntitle, synopsis, destitle, description,
07501          stxtitle, syntax, argtitle, arguments, seealsotitle, seealso);
07502 
07503 return_cleanup:
07504    ast_free(description);
07505    ast_free(arguments);
07506    ast_free(synopsis);
07507    ast_free(seealso);
07508    ast_free(syntax);
07509 }
07510 
07511 /*
07512  * \brief 'show application' CLI command implementation function...
07513  */
07514 static char *handle_show_application(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
07515 {
07516    struct ast_app *aa;
07517    int app, no_registered_app = 1;
07518 
07519    switch (cmd) {
07520    case CLI_INIT:
07521       e->command = "core show application";
07522       e->usage =
07523          "Usage: core show application <application> [<application> [<application> [...]]]\n"
07524          "       Describes a particular application.\n";
07525       return NULL;
07526    case CLI_GENERATE:
07527       /*
07528        * There is a possibility to show informations about more than one
07529        * application at one time. You can type 'show application Dial Echo' and
07530        * you will see informations about these two applications ...
07531        */
07532       return ast_complete_applications(a->line, a->word, a->n);
07533    }
07534 
07535    if (a->argc < 4) {
07536       return CLI_SHOWUSAGE;
07537    }
07538 
07539    AST_RWLIST_RDLOCK(&apps);
07540    AST_RWLIST_TRAVERSE(&apps, aa, list) {
07541       /* Check for each app that was supplied as an argument */
07542       for (app = 3; app < a->argc; app++) {
07543          if (strcasecmp(aa->name, a->argv[app])) {
07544             continue;
07545          }
07546 
07547          /* We found it! */
07548          no_registered_app = 0;
07549 
07550          print_app_docs(aa, a->fd);
07551       }
07552    }
07553    AST_RWLIST_UNLOCK(&apps);
07554 
07555    /* we found at least one app? no? */
07556    if (no_registered_app) {
07557       ast_cli(a->fd, "Your application(s) is (are) not registered\n");
07558       return CLI_FAILURE;
07559    }
07560 
07561    return CLI_SUCCESS;
07562 }
07563 
07564 /*! \brief  handle_show_hints: CLI support for listing registered dial plan hints */
07565 static char *handle_show_hints(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
07566 {
07567    struct ast_hint *hint;
07568    int num = 0;
07569    int watchers;
07570    struct ao2_iterator i;
07571 
07572    switch (cmd) {
07573    case CLI_INIT:
07574       e->command = "core show hints";
07575       e->usage =
07576          "Usage: core show hints\n"
07577          "       List registered hints.\n"
07578          "       Hint details are shown in four columns. In order from left to right, they are:\n"
07579          "       1. Hint extension URI.\n"
07580          "       2. Mapped device state identifiers.\n"
07581          "       3. Current extension state. The aggregate of mapped device states.\n"
07582          "       4. Watchers - number of subscriptions and other entities watching this hint.\n";
07583       return NULL;
07584    case CLI_GENERATE:
07585       return NULL;
07586    }
07587 
07588    if (ao2_container_count(hints) == 0) {
07589       ast_cli(a->fd, "There are no registered dialplan hints\n");
07590       return CLI_SUCCESS;
07591    }
07592    /* ... we have hints ... */
07593    ast_cli(a->fd, "\n    -= Registered Asterisk Dial Plan Hints =-\n");
07594 
07595    i = ao2_iterator_init(hints, 0);
07596    for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) {
07597       ao2_lock(hint);
07598       if (!hint->exten) {
07599          /* The extension has already been destroyed */
07600          ao2_unlock(hint);
07601          continue;
07602       }
07603       watchers = ao2_container_count(hint->callbacks);
07604       ast_cli(a->fd, "   %20s@%-20.20s: %-20.20s  State:%-15.15s Watchers %2d\n",
07605          ast_get_extension_name(hint->exten),
07606          ast_get_context_name(ast_get_extension_context(hint->exten)),
07607          ast_get_extension_app(hint->exten),
07608          ast_extension_state2str(hint->laststate), watchers);
07609       ao2_unlock(hint);
07610       num++;
07611    }
07612    ao2_iterator_destroy(&i);
07613 
07614    ast_cli(a->fd, "----------------\n");
07615    ast_cli(a->fd, "- %d hints registered\n", num);
07616    return CLI_SUCCESS;
07617 }
07618 
07619 /*! \brief autocomplete for CLI command 'core show hint' */
07620 static char *complete_core_show_hint(const char *line, const char *word, int pos, int state)
07621 {
07622    struct ast_hint *hint;
07623    char *ret = NULL;
07624    int which = 0;
07625    int wordlen;
07626    struct ao2_iterator i;
07627 
07628    if (pos != 3)
07629       return NULL;
07630 
07631    wordlen = strlen(word);
07632 
07633    /* walk through all hints */
07634    i = ao2_iterator_init(hints, 0);
07635    for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) {
07636       ao2_lock(hint);
07637       if (!hint->exten) {
07638          /* The extension has already been destroyed */
07639          ao2_unlock(hint);
07640          continue;
07641       }
07642       if (!strncasecmp(word, ast_get_extension_name(hint->exten), wordlen) && ++which > state) {
07643          ret = ast_strdup(ast_get_extension_name(hint->exten));
07644          ao2_unlock(hint);
07645          ao2_ref(hint, -1);
07646          break;
07647       }
07648       ao2_unlock(hint);
07649    }
07650    ao2_iterator_destroy(&i);
07651 
07652    return ret;
07653 }
07654 
07655 /*! \brief  handle_show_hint: CLI support for listing registered dial plan hint */
07656 static char *handle_show_hint(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
07657 {
07658    struct ast_hint *hint;
07659    int watchers;
07660    int num = 0, extenlen;
07661    struct ao2_iterator i;
07662 
07663    switch (cmd) {
07664    case CLI_INIT:
07665       e->command = "core show hint";
07666       e->usage =
07667          "Usage: core show hint <exten>\n"
07668          "       List registered hint.\n"
07669          "       Hint details are shown in four columns. In order from left to right, they are:\n"
07670          "       1. Hint extension URI.\n"
07671          "       2. Mapped device state identifiers.\n"
07672          "       3. Current extension state. The aggregate of mapped device states.\n"
07673          "       4. Watchers - number of subscriptions and other entities watching this hint.\n";
07674 
07675       return NULL;
07676    case CLI_GENERATE:
07677       return complete_core_show_hint(a->line, a->word, a->pos, a->n);
07678    }
07679 
07680    if (a->argc < 4)
07681       return CLI_SHOWUSAGE;
07682 
07683    if (ao2_container_count(hints) == 0) {
07684       ast_cli(a->fd, "There are no registered dialplan hints\n");
07685       return CLI_SUCCESS;
07686    }
07687 
07688    extenlen = strlen(a->argv[3]);
07689    i = ao2_iterator_init(hints, 0);
07690    for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) {
07691       ao2_lock(hint);
07692       if (!hint->exten) {
07693          /* The extension has already been destroyed */
07694          ao2_unlock(hint);
07695          continue;
07696       }
07697       if (!strncasecmp(ast_get_extension_name(hint->exten), a->argv[3], extenlen)) {
07698          watchers = ao2_container_count(hint->callbacks);
07699          ast_cli(a->fd, "   %20s@%-20.20s: %-20.20s  State:%-15.15s Watchers %2d\n",
07700             ast_get_extension_name(hint->exten),
07701             ast_get_context_name(ast_get_extension_context(hint->exten)),
07702             ast_get_extension_app(hint->exten),
07703             ast_extension_state2str(hint->laststate), watchers);
07704          num++;
07705       }
07706       ao2_unlock(hint);
07707    }
07708    ao2_iterator_destroy(&i);
07709    if (!num)
07710       ast_cli(a->fd, "No hints matching extension %s\n", a->argv[3]);
07711    else
07712       ast_cli(a->fd, "%d hint%s matching extension %s\n", num, (num!=1 ? "s":""), a->argv[3]);
07713    return CLI_SUCCESS;
07714 }
07715 
07716 
07717 /*! \brief  handle_show_switches: CLI support for listing registered dial plan switches */
07718 static char *handle_show_switches(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
07719 {
07720    struct ast_switch *sw;
07721 
07722    switch (cmd) {
07723    case CLI_INIT:
07724       e->command = "core show switches";
07725       e->usage =
07726          "Usage: core show switches\n"
07727          "       List registered switches\n";
07728       return NULL;
07729    case CLI_GENERATE:
07730       return NULL;
07731    }
07732 
07733    AST_RWLIST_RDLOCK(&switches);
07734 
07735    if (AST_RWLIST_EMPTY(&switches)) {
07736       AST_RWLIST_UNLOCK(&switches);
07737       ast_cli(a->fd, "There are no registered alternative switches\n");
07738       return CLI_SUCCESS;
07739    }
07740 
07741    ast_cli(a->fd, "\n    -= Registered Asterisk Alternative Switches =-\n");
07742    AST_RWLIST_TRAVERSE(&switches, sw, list)
07743       ast_cli(a->fd, "%s: %s\n", sw->name, sw->description);
07744 
07745    AST_RWLIST_UNLOCK(&switches);
07746 
07747    return CLI_SUCCESS;
07748 }
07749 
07750 static char *handle_show_applications(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
07751 {
07752    struct ast_app *aa;
07753    int like = 0, describing = 0;
07754    int total_match = 0;    /* Number of matches in like clause */
07755    int total_apps = 0;     /* Number of apps registered */
07756    static const char * const choices[] = { "like", "describing", NULL };
07757 
07758    switch (cmd) {
07759    case CLI_INIT:
07760       e->command = "core show applications [like|describing]";
07761       e->usage =
07762          "Usage: core show applications [{like|describing} <text>]\n"
07763          "       List applications which are currently available.\n"
07764          "       If 'like', <text> will be a substring of the app name\n"
07765          "       If 'describing', <text> will be a substring of the description\n";
07766       return NULL;
07767    case CLI_GENERATE:
07768       return (a->pos != 3) ? NULL : ast_cli_complete(a->word, choices, a->n);
07769    }
07770 
07771    AST_RWLIST_RDLOCK(&apps);
07772 
07773    if (AST_RWLIST_EMPTY(&apps)) {
07774       ast_cli(a->fd, "There are no registered applications\n");
07775       AST_RWLIST_UNLOCK(&apps);
07776       return CLI_SUCCESS;
07777    }
07778 
07779    /* core list applications like <keyword> */
07780    if ((a->argc == 5) && (!strcmp(a->argv[3], "like"))) {
07781       like = 1;
07782    } else if ((a->argc > 4) && (!strcmp(a->argv[3], "describing"))) {
07783       describing = 1;
07784    }
07785 
07786    /* core list applications describing <keyword1> [<keyword2>] [...] */
07787    if ((!like) && (!describing)) {
07788       ast_cli(a->fd, "    -= Registered Asterisk Applications =-\n");
07789    } else {
07790       ast_cli(a->fd, "    -= Matching Asterisk Applications =-\n");
07791    }
07792 
07793    AST_RWLIST_TRAVERSE(&apps, aa, list) {
07794       int printapp = 0;
07795       total_apps++;
07796       if (like) {
07797          if (strcasestr(aa->name, a->argv[4])) {
07798             printapp = 1;
07799             total_match++;
07800          }
07801       } else if (describing) {
07802          if (aa->description) {
07803             /* Match all words on command line */
07804             int i;
07805             printapp = 1;
07806             for (i = 4; i < a->argc; i++) {
07807                if (!strcasestr(aa->description, a->argv[i])) {
07808                   printapp = 0;
07809                } else {
07810                   total_match++;
07811                }
07812             }
07813          }
07814       } else {
07815          printapp = 1;
07816       }
07817 
07818       if (printapp) {
07819          ast_cli(a->fd,"  %20s: %s\n", aa->name, aa->synopsis ? aa->synopsis : "<Synopsis not available>");
07820       }
07821    }
07822    if ((!like) && (!describing)) {
07823       ast_cli(a->fd, "    -= %d Applications Registered =-\n",total_apps);
07824    } else {
07825       ast_cli(a->fd, "    -= %d Applications Matching =-\n",total_match);
07826    }
07827 
07828    AST_RWLIST_UNLOCK(&apps);
07829 
07830    return CLI_SUCCESS;
07831 }
07832 
07833 /*
07834  * 'show dialplan' CLI command implementation functions ...
07835  */
07836 static char *complete_show_dialplan_context(const char *line, const char *word, int pos,
07837    int state)
07838 {
07839    struct ast_context *c = NULL;
07840    char *ret = NULL;
07841    int which = 0;
07842    int wordlen;
07843 
07844    /* we are do completion of [exten@]context on second position only */
07845    if (pos != 2)
07846       return NULL;
07847 
07848    ast_rdlock_contexts();
07849 
07850    wordlen = strlen(word);
07851 
07852    /* walk through all contexts and return the n-th match */
07853    while ( (c = ast_walk_contexts(c)) ) {
07854       if (!strncasecmp(word, ast_get_context_name(c), wordlen) && ++which > state) {
07855          ret = ast_strdup(ast_get_context_name(c));
07856          break;
07857       }
07858    }
07859 
07860    ast_unlock_contexts();
07861 
07862    return ret;
07863 }
07864 
07865 /*! \brief Counters for the show dialplan manager command */
07866 struct dialplan_counters {
07867    int total_items;
07868    int total_context;
07869    int total_exten;
07870    int total_prio;
07871    int context_existence;
07872    int extension_existence;
07873 };
07874 
07875 /*! \brief helper function to print an extension */
07876 static void print_ext(struct ast_exten *e, char * buf, int buflen)
07877 {
07878    int prio = ast_get_extension_priority(e);
07879    if (prio == PRIORITY_HINT) {
07880       snprintf(buf, buflen, "hint: %s",
07881          ast_get_extension_app(e));
07882    } else {
07883       snprintf(buf, buflen, "%d. %s(%s)",
07884          prio, ast_get_extension_app(e),
07885          (!ast_strlen_zero(ast_get_extension_app_data(e)) ? (char *)ast_get_extension_app_data(e) : ""));
07886    }
07887 }
07888 
07889 /* XXX not verified */
07890 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[])
07891 {
07892    struct ast_context *c = NULL;
07893    int res = 0, old_total_exten = dpc->total_exten;
07894 
07895    ast_rdlock_contexts();
07896 
07897    /* walk all contexts ... */
07898    while ( (c = ast_walk_contexts(c)) ) {
07899       struct ast_exten *e;
07900       struct ast_include *i;
07901       struct ast_ignorepat *ip;
07902 #ifndef LOW_MEMORY
07903       char buf[1024], buf2[1024];
07904 #else
07905       char buf[256], buf2[256];
07906 #endif
07907       int context_info_printed = 0;
07908 
07909       if (context && strcmp(ast_get_context_name(c), context))
07910          continue;   /* skip this one, name doesn't match */
07911 
07912       dpc->context_existence = 1;
07913 
07914       ast_rdlock_context(c);
07915 
07916       /* are we looking for exten too? if yes, we print context
07917        * only if we find our extension.
07918        * Otherwise print context even if empty ?
07919        * XXX i am not sure how the rinclude is handled.
07920        * I think it ought to go inside.
07921        */
07922       if (!exten) {
07923          dpc->total_context++;
07924          ast_cli(fd, "[ Context '%s' created by '%s' ]\n",
07925             ast_get_context_name(c), ast_get_context_registrar(c));
07926          context_info_printed = 1;
07927       }
07928 
07929       /* walk extensions ... */
07930       e = NULL;
07931       while ( (e = ast_walk_context_extensions(c, e)) ) {
07932          struct ast_exten *p;
07933 
07934          if (exten && !ast_extension_match(ast_get_extension_name(e), exten))
07935             continue;   /* skip, extension match failed */
07936 
07937          dpc->extension_existence = 1;
07938 
07939          /* may we print context info? */
07940          if (!context_info_printed) {
07941             dpc->total_context++;
07942             if (rinclude) { /* TODO Print more info about rinclude */
07943                ast_cli(fd, "[ Included context '%s' created by '%s' ]\n",
07944                   ast_get_context_name(c), ast_get_context_registrar(c));
07945             } else {
07946                ast_cli(fd, "[ Context '%s' created by '%s' ]\n",
07947                   ast_get_context_name(c), ast_get_context_registrar(c));
07948             }
07949             context_info_printed = 1;
07950          }
07951          dpc->total_prio++;
07952 
07953          /* write extension name and first peer */
07954          if (e->matchcid == AST_EXT_MATCHCID_ON)
07955             snprintf(buf, sizeof(buf), "'%s' (CID match '%s') => ", ast_get_extension_name(e), e->cidmatch);
07956          else
07957             snprintf(buf, sizeof(buf), "'%s' =>", ast_get_extension_name(e));
07958 
07959          print_ext(e, buf2, sizeof(buf2));
07960 
07961          ast_cli(fd, "  %-17s %-45s [%s]\n", buf, buf2,
07962             ast_get_extension_registrar(e));
07963 
07964          dpc->total_exten++;
07965          /* walk next extension peers */
07966          p = e;   /* skip the first one, we already got it */
07967          while ( (p = ast_walk_extension_priorities(e, p)) ) {
07968             const char *el = ast_get_extension_label(p);
07969             dpc->total_prio++;
07970             if (el)
07971                snprintf(buf, sizeof(buf), "   [%s]", el);
07972             else
07973                buf[0] = '\0';
07974             print_ext(p, buf2, sizeof(buf2));
07975 
07976             ast_cli(fd,"  %-17s %-45s [%s]\n", buf, buf2,
07977                ast_get_extension_registrar(p));
07978          }
07979       }
07980 
07981       /* walk included and write info ... */
07982       i = NULL;
07983       while ( (i = ast_walk_context_includes(c, i)) ) {
07984          snprintf(buf, sizeof(buf), "'%s'", ast_get_include_name(i));
07985          if (exten) {
07986             /* Check all includes for the requested extension */
07987             if (includecount >= AST_PBX_MAX_STACK) {
07988                ast_log(LOG_WARNING, "Maximum include depth exceeded!\n");
07989             } else {
07990                int dupe = 0;
07991                int x;
07992                for (x = 0; x < includecount; x++) {
07993                   if (!strcasecmp(includes[x], ast_get_include_name(i))) {
07994                      dupe++;
07995                      break;
07996                   }
07997                }
07998                if (!dupe) {
07999                   includes[includecount] = ast_get_include_name(i);
08000                   show_dialplan_helper(fd, ast_get_include_name(i), exten, dpc, i, includecount + 1, includes);
08001                } else {
08002                   ast_log(LOG_WARNING, "Avoiding circular include of %s within %s\n", ast_get_include_name(i), context);
08003                }
08004             }
08005          } else {
08006             ast_cli(fd, "  Include =>        %-45s [%s]\n",
08007                buf, ast_get_include_registrar(i));
08008          }
08009       }
08010 
08011       /* walk ignore patterns and write info ... */
08012       ip = NULL;
08013       while ( (ip = ast_walk_context_ignorepats(c, ip)) ) {
08014          const char *ipname = ast_get_ignorepat_name(ip);
08015          char ignorepat[AST_MAX_EXTENSION];
08016          snprintf(buf, sizeof(buf), "'%s'", ipname);
08017          snprintf(ignorepat, sizeof(ignorepat), "_%s.", ipname);
08018          if (!exten || ast_extension_match(ignorepat, exten)) {
08019             ast_cli(fd, "  Ignore pattern => %-45s [%s]\n",
08020                buf, ast_get_ignorepat_registrar(ip));
08021          }
08022       }
08023       if (!rinclude) {
08024          struct ast_sw *sw = NULL;
08025          while ( (sw = ast_walk_context_switches(c, sw)) ) {
08026             snprintf(buf, sizeof(buf), "'%s/%s'",
08027                ast_get_switch_name(sw),
08028                ast_get_switch_data(sw));
08029             ast_cli(fd, "  Alt. Switch =>    %-45s [%s]\n",
08030                buf, ast_get_switch_registrar(sw));
08031          }
08032       }
08033 
08034       ast_unlock_context(c);
08035 
08036       /* if we print something in context, make an empty line */
08037       if (context_info_printed)
08038          ast_cli(fd, "\n");
08039    }
08040    ast_unlock_contexts();
08041 
08042    return (dpc->total_exten == old_total_exten) ? -1 : res;
08043 }
08044 
08045 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[])
08046 {
08047    struct ast_context *c = NULL;
08048    int res = 0, old_total_exten = dpc->total_exten;
08049 
08050    ast_cli(fd,"\n     In-mem exten Trie for Fast Extension Pattern Matching:\n\n");
08051 
08052    ast_cli(fd,"\n           Explanation: Node Contents Format = <char(s) to match>:<pattern?>:<specif>:[matched extension]\n");
08053    ast_cli(fd,    "                        Where <char(s) to match> is a set of chars, any one of which should match the current character\n");
08054    ast_cli(fd,    "                              <pattern?>: Y if this a pattern match (eg. _XZN[5-7]), N otherwise\n");
08055    ast_cli(fd,    "                              <specif>: an assigned 'exactness' number for this matching char. The lower the number, the more exact the match\n");
08056    ast_cli(fd,    "                              [matched exten]: If all chars matched to this point, which extension this matches. In form: EXTEN:<exten string>\n");
08057    ast_cli(fd,    "                        In general, you match a trie node to a string character, from left to right. All possible matching chars\n");
08058    ast_cli(fd,    "                        are in a string vertically, separated by an unbroken string of '+' characters.\n\n");
08059    ast_rdlock_contexts();
08060 
08061    /* walk all contexts ... */
08062    while ( (c = ast_walk_contexts(c)) ) {
08063       int context_info_printed = 0;
08064 
08065       if (context && strcmp(ast_get_context_name(c), context))
08066          continue;   /* skip this one, name doesn't match */
08067 
08068       dpc->context_existence = 1;
08069 
08070       if (!c->pattern_tree) {
08071          /* Ignore check_return warning from Coverity for ast_exists_extension below */
08072          ast_exists_extension(NULL, c->name, "s", 1, ""); /* do this to force the trie to built, if it is not already */
08073       }
08074 
08075       ast_rdlock_context(c);
08076 
08077       dpc->total_context++;
08078       ast_cli(fd, "[ Context '%s' created by '%s' ]\n",
08079          ast_get_context_name(c), ast_get_context_registrar(c));
08080       context_info_printed = 1;
08081 
08082       if (c->pattern_tree)
08083       {
08084          cli_match_char_tree(c->pattern_tree, " ", fd);
08085       } else {
08086          ast_cli(fd,"\n     No Pattern Trie present. Perhaps the context is empty...or there is trouble...\n\n");
08087       }
08088 
08089       ast_unlock_context(c);
08090 
08091       /* if we print something in context, make an empty line */
08092       if (context_info_printed)
08093          ast_cli(fd, "\n");
08094    }
08095    ast_unlock_contexts();
08096 
08097    return (dpc->total_exten == old_total_exten) ? -1 : res;
08098 }
08099 
08100 static char *handle_show_dialplan(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
08101 {
08102    char *exten = NULL, *context = NULL;
08103    /* Variables used for different counters */
08104    struct dialplan_counters counters;
08105    const char *incstack[AST_PBX_MAX_STACK];
08106 
08107    switch (cmd) {
08108    case CLI_INIT:
08109       e->command = "dialplan show";
08110       e->usage =
08111          "Usage: dialplan show [[exten@]context]\n"
08112          "       Show dialplan\n";
08113       return NULL;
08114    case CLI_GENERATE:
08115       return complete_show_dialplan_context(a->line, a->word, a->pos, a->n);
08116    }
08117 
08118    memset(&counters, 0, sizeof(counters));
08119 
08120    if (a->argc != 2 && a->argc != 3)
08121       return CLI_SHOWUSAGE;
08122 
08123    /* we obtain [exten@]context? if yes, split them ... */
08124    if (a->argc == 3) {
08125       if (strchr(a->argv[2], '@')) {   /* split into exten & context */
08126          context = ast_strdupa(a->argv[2]);
08127          exten = strsep(&context, "@");
08128          /* change empty strings to NULL */
08129          if (ast_strlen_zero(exten))
08130             exten = NULL;
08131       } else { /* no '@' char, only context given */
08132          context = ast_strdupa(a->argv[2]);
08133       }
08134       if (ast_strlen_zero(context))
08135          context = NULL;
08136    }
08137    /* else Show complete dial plan, context and exten are NULL */
08138    show_dialplan_helper(a->fd, context, exten, &counters, NULL, 0, incstack);
08139 
08140    /* check for input failure and throw some error messages */
08141    if (context && !counters.context_existence) {
08142       ast_cli(a->fd, "There is no existence of '%s' context\n", context);
08143       return CLI_FAILURE;
08144    }
08145 
08146    if (exten && !counters.extension_existence) {
08147       if (context)
08148          ast_cli(a->fd, "There is no existence of %s@%s extension\n",
08149             exten, context);
08150       else
08151          ast_cli(a->fd,
08152             "There is no existence of '%s' extension in all contexts\n",
08153             exten);
08154       return CLI_FAILURE;
08155    }
08156 
08157    ast_cli(a->fd,"-= %d %s (%d %s) in %d %s. =-\n",
08158             counters.total_exten, counters.total_exten == 1 ? "extension" : "extensions",
08159             counters.total_prio, counters.total_prio == 1 ? "priority" : "priorities",
08160             counters.total_context, counters.total_context == 1 ? "context" : "contexts");
08161 
08162    /* everything ok */
08163    return CLI_SUCCESS;
08164 }
08165 
08166 /*! \brief Send ack once */
08167 static char *handle_debug_dialplan(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
08168 {
08169    char *exten = NULL, *context = NULL;
08170    /* Variables used for different counters */
08171    struct dialplan_counters counters;
08172    const char *incstack[AST_PBX_MAX_STACK];
08173 
08174    switch (cmd) {
08175    case CLI_INIT:
08176       e->command = "dialplan debug";
08177       e->usage =
08178          "Usage: dialplan debug [context]\n"
08179          "       Show dialplan context Trie(s). Usually only useful to folks debugging the deep internals of the fast pattern matcher\n";
08180       return NULL;
08181    case CLI_GENERATE:
08182       return complete_show_dialplan_context(a->line, a->word, a->pos, a->n);
08183    }
08184 
08185    memset(&counters, 0, sizeof(counters));
08186 
08187    if (a->argc != 2 && a->argc != 3)
08188       return CLI_SHOWUSAGE;
08189 
08190    /* we obtain [exten@]context? if yes, split them ... */
08191    /* note: we ignore the exten totally here .... */
08192    if (a->argc == 3) {
08193       if (strchr(a->argv[2], '@')) {   /* split into exten & context */
08194          context = ast_strdupa(a->argv[2]);
08195          exten = strsep(&context, "@");
08196          /* change empty strings to NULL */
08197          if (ast_strlen_zero(exten))
08198             exten = NULL;
08199       } else { /* no '@' char, only context given */
08200          context = ast_strdupa(a->argv[2]);
08201       }
08202       if (ast_strlen_zero(context))
08203          context = NULL;
08204    }
08205    /* else Show complete dial plan, context and exten are NULL */
08206    show_debug_helper(a->fd, context, exten, &counters, NULL, 0, incstack);
08207 
08208    /* check for input failure and throw some error messages */
08209    if (context && !counters.context_existence) {
08210       ast_cli(a->fd, "There is no existence of '%s' context\n", context);
08211       return CLI_FAILURE;
08212    }
08213 
08214 
08215    ast_cli(a->fd,"-= %d %s. =-\n",
08216          counters.total_context, counters.total_context == 1 ? "context" : "contexts");
08217 
08218    /* everything ok */
08219    return CLI_SUCCESS;
08220 }
08221 
08222 /*! \brief Send ack once */
08223 static void manager_dpsendack(struct mansession *s, const struct message *m)
08224 {
08225    astman_send_listack(s, m, "DialPlan list will follow", "start");
08226 }
08227 
08228 /*! \brief Show dialplan extensions
08229  * XXX this function is similar but not exactly the same as the CLI's
08230  * show dialplan. Must check whether the difference is intentional or not.
08231  */
08232 static int manager_show_dialplan_helper(struct mansession *s, const struct message *m,
08233                const char *actionidtext, const char *context,
08234                const char *exten, struct dialplan_counters *dpc,
08235                struct ast_include *rinclude)
08236 {
08237    struct ast_context *c;
08238    int res = 0, old_total_exten = dpc->total_exten;
08239 
08240    if (ast_strlen_zero(exten))
08241       exten = NULL;
08242    if (ast_strlen_zero(context))
08243       context = NULL;
08244 
08245    ast_debug(3, "manager_show_dialplan: Context: -%s- Extension: -%s-\n", context, exten);
08246 
08247    /* try to lock contexts */
08248    if (ast_rdlock_contexts()) {
08249       astman_send_error(s, m, "Failed to lock contexts");
08250       ast_log(LOG_WARNING, "Failed to lock contexts list for manager: listdialplan\n");
08251       return -1;
08252    }
08253 
08254    c = NULL;      /* walk all contexts ... */
08255    while ( (c = ast_walk_contexts(c)) ) {
08256       struct ast_exten *e;
08257       struct ast_include *i;
08258       struct ast_ignorepat *ip;
08259 
08260       if (context && strcmp(ast_get_context_name(c), context) != 0)
08261          continue;   /* not the name we want */
08262 
08263       dpc->context_existence = 1;
08264       dpc->total_context++;
08265 
08266       ast_debug(3, "manager_show_dialplan: Found Context: %s \n", ast_get_context_name(c));
08267 
08268       if (ast_rdlock_context(c)) {  /* failed to lock */
08269          ast_debug(3, "manager_show_dialplan: Failed to lock context\n");
08270          continue;
08271       }
08272 
08273       /* XXX note- an empty context is not printed */
08274       e = NULL;      /* walk extensions in context  */
08275       while ( (e = ast_walk_context_extensions(c, e)) ) {
08276          struct ast_exten *p;
08277 
08278          /* looking for extension? is this our extension? */
08279          if (exten && !ast_extension_match(ast_get_extension_name(e), exten)) {
08280             /* not the one we are looking for, continue */
08281             ast_debug(3, "manager_show_dialplan: Skipping extension %s\n", ast_get_extension_name(e));
08282             continue;
08283          }
08284          ast_debug(3, "manager_show_dialplan: Found Extension: %s \n", ast_get_extension_name(e));
08285 
08286          dpc->extension_existence = 1;
08287 
08288          dpc->total_exten++;
08289 
08290          p = NULL;      /* walk next extension peers */
08291          while ( (p = ast_walk_extension_priorities(e, p)) ) {
08292             int prio = ast_get_extension_priority(p);
08293 
08294             dpc->total_prio++;
08295             if (!dpc->total_items++)
08296                manager_dpsendack(s, m);
08297             astman_append(s, "Event: ListDialplan\r\n%s", actionidtext);
08298             astman_append(s, "Context: %s\r\nExtension: %s\r\n", ast_get_context_name(c), ast_get_extension_name(e) );
08299 
08300             /* XXX maybe make this conditional, if p != e ? */
08301             if (ast_get_extension_label(p))
08302                astman_append(s, "ExtensionLabel: %s\r\n", ast_get_extension_label(p));
08303 
08304             if (prio == PRIORITY_HINT) {
08305                astman_append(s, "Priority: hint\r\nApplication: %s\r\n", ast_get_extension_app(p));
08306             } else {
08307                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));
08308             }
08309             astman_append(s, "Registrar: %s\r\n\r\n", ast_get_extension_registrar(e));
08310          }
08311       }
08312 
08313       i = NULL;      /* walk included and write info ... */
08314       while ( (i = ast_walk_context_includes(c, i)) ) {
08315          if (exten) {
08316             /* Check all includes for the requested extension */
08317             manager_show_dialplan_helper(s, m, actionidtext, ast_get_include_name(i), exten, dpc, i);
08318          } else {
08319             if (!dpc->total_items++)
08320                manager_dpsendack(s, m);
08321             astman_append(s, "Event: ListDialplan\r\n%s", actionidtext);
08322             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));
08323             astman_append(s, "\r\n");
08324             ast_debug(3, "manager_show_dialplan: Found Included context: %s \n", ast_get_include_name(i));
08325          }
08326       }
08327 
08328       ip = NULL;  /* walk ignore patterns and write info ... */
08329       while ( (ip = ast_walk_context_ignorepats(c, ip)) ) {
08330          const char *ipname = ast_get_ignorepat_name(ip);
08331          char ignorepat[AST_MAX_EXTENSION];
08332 
08333          snprintf(ignorepat, sizeof(ignorepat), "_%s.", ipname);
08334          if (!exten || ast_extension_match(ignorepat, exten)) {
08335             if (!dpc->total_items++)
08336                manager_dpsendack(s, m);
08337             astman_append(s, "Event: ListDialplan\r\n%s", actionidtext);
08338             astman_append(s, "Context: %s\r\nIgnorePattern: %s\r\nRegistrar: %s\r\n", ast_get_context_name(c), ipname, ast_get_ignorepat_registrar(ip));
08339             astman_append(s, "\r\n");
08340          }
08341       }
08342       if (!rinclude) {
08343          struct ast_sw *sw = NULL;
08344          while ( (sw = ast_walk_context_switches(c, sw)) ) {
08345             if (!dpc->total_items++)
08346                manager_dpsendack(s, m);
08347             astman_append(s, "Event: ListDialplan\r\n%s", actionidtext);
08348             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));
08349             astman_append(s, "\r\n");
08350             ast_debug(3, "manager_show_dialplan: Found Switch : %s \n", ast_get_switch_name(sw));
08351          }
08352       }
08353 
08354       ast_unlock_context(c);
08355    }
08356    ast_unlock_contexts();
08357 
08358    if (dpc->total_exten == old_total_exten) {
08359       ast_debug(3, "manager_show_dialplan: Found nothing new\n");
08360       /* Nothing new under the sun */
08361       return -1;
08362    } else {
08363       return res;
08364    }
08365 }
08366 
08367 /*! \brief  Manager listing of dial plan */
08368 static int manager_show_dialplan(struct mansession *s, const struct message *m)
08369 {
08370    const char *exten, *context;
08371    const char *id = astman_get_header(m, "ActionID");
08372    char idtext[256];
08373 
08374    /* Variables used for different counters */
08375    struct dialplan_counters counters;
08376 
08377    if (!ast_strlen_zero(id))
08378       snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id);
08379    else
08380       idtext[0] = '\0';
08381 
08382    memset(&counters, 0, sizeof(counters));
08383 
08384    exten = astman_get_header(m, "Extension");
08385    context = astman_get_header(m, "Context");
08386 
08387    manager_show_dialplan_helper(s, m, idtext, context, exten, &counters, NULL);
08388 
08389    if (!ast_strlen_zero(context) && !counters.context_existence) {
08390       char errorbuf[BUFSIZ];
08391 
08392       snprintf(errorbuf, sizeof(errorbuf), "Did not find context %s", context);
08393       astman_send_error(s, m, errorbuf);
08394       return 0;
08395    }
08396    if (!ast_strlen_zero(exten) && !counters.extension_existence) {
08397       char errorbuf[BUFSIZ];
08398 
08399       if (!ast_strlen_zero(context))
08400          snprintf(errorbuf, sizeof(errorbuf), "Did not find extension %s@%s", exten, context);
08401       else
08402          snprintf(errorbuf, sizeof(errorbuf), "Did not find extension %s in any context", exten);
08403       astman_send_error(s, m, errorbuf);
08404       return 0;
08405    }
08406 
08407    if (!counters.total_items) {
08408       manager_dpsendack(s, m);
08409    }
08410 
08411    astman_append(s, "Event: ShowDialPlanComplete\r\n"
08412       "EventList: Complete\r\n"
08413       "ListItems: %d\r\n"
08414       "ListExtensions: %d\r\n"
08415       "ListPriorities: %d\r\n"
08416       "ListContexts: %d\r\n"
08417       "%s"
08418       "\r\n", counters.total_items, counters.total_exten, counters.total_prio, counters.total_context, idtext);
08419 
08420    /* everything ok */
08421    return 0;
08422 }
08423 
08424 /*! \brief CLI support for listing global variables in a parseable way */
08425 static char *handle_show_globals(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
08426 {
08427    int i = 0;
08428    struct ast_var_t *newvariable;
08429 
08430    switch (cmd) {
08431    case CLI_INIT:
08432       e->command = "dialplan show globals";
08433       e->usage =
08434          "Usage: dialplan show globals\n"
08435          "       List current global dialplan variables and their values\n";
08436       return NULL;
08437    case CLI_GENERATE:
08438       return NULL;
08439    }
08440 
08441    ast_rwlock_rdlock(&globalslock);
08442    AST_LIST_TRAVERSE (&globals, newvariable, entries) {
08443       i++;
08444       ast_cli(a->fd, "   %s=%s\n", ast_var_name(newvariable), ast_var_value(newvariable));
08445    }
08446    ast_rwlock_unlock(&globalslock);
08447    ast_cli(a->fd, "\n    -- %d variable(s)\n", i);
08448 
08449    return CLI_SUCCESS;
08450 }
08451 
08452 #ifdef AST_DEVMODE
08453 static char *handle_show_device2extenstate(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
08454 {
08455    struct ast_devstate_aggregate agg;
08456    int i, j, exten, combined;
08457 
08458    switch (cmd) {
08459    case CLI_INIT:
08460       e->command = "core show device2extenstate";
08461       e->usage =
08462          "Usage: core show device2extenstate\n"
08463          "       Lists device state to extension state combinations.\n";
08464    case CLI_GENERATE:
08465       return NULL;
08466    }
08467    for (i = 0; i < AST_DEVICE_TOTAL; i++) {
08468       for (j = 0; j < AST_DEVICE_TOTAL; j++) {
08469          ast_devstate_aggregate_init(&agg);
08470          ast_devstate_aggregate_add(&agg, i);
08471          ast_devstate_aggregate_add(&agg, j);
08472          combined = ast_devstate_aggregate_result(&agg);
08473          exten = ast_devstate_to_extenstate(combined);
08474          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));
08475       }
08476    }
08477    ast_cli(a->fd, "\n");
08478    return CLI_SUCCESS;
08479 }
08480 #endif
08481 
08482 /*! \brief CLI support for listing chanvar's variables in a parseable way */
08483 static char *handle_show_chanvar(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
08484 {
08485    struct ast_channel *chan = NULL;
08486    struct ast_str *vars = ast_str_alloca(BUFSIZ * 4); /* XXX large because we might have lots of channel vars */
08487 
08488    switch (cmd) {
08489    case CLI_INIT:
08490       e->command = "dialplan show chanvar";
08491       e->usage =
08492          "Usage: dialplan show chanvar <channel>\n"
08493          "       List current channel variables and their values\n";
08494       return NULL;
08495    case CLI_GENERATE:
08496       return ast_complete_channels(a->line, a->word, a->pos, a->n, 3);
08497    }
08498 
08499    if (a->argc != e->args + 1)
08500       return CLI_SHOWUSAGE;
08501 
08502    if (!(chan = ast_channel_get_by_name(a->argv[e->args]))) {
08503       ast_cli(a->fd, "Channel '%s' not found\n", a->argv[e->args]);
08504       return CLI_FAILURE;
08505    }
08506 
08507    pbx_builtin_serialize_variables(chan, &vars);
08508 
08509    if (ast_str_strlen(vars)) {
08510       ast_cli(a->fd, "\nVariables for channel %s:\n%s\n", a->argv[e->args], ast_str_buffer(vars));
08511    }
08512 
08513    chan = ast_channel_unref(chan);
08514 
08515    return CLI_SUCCESS;
08516 }
08517 
08518 static char *handle_set_global(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
08519 {
08520    switch (cmd) {
08521    case CLI_INIT:
08522       e->command = "dialplan set global";
08523       e->usage =
08524          "Usage: dialplan set global <name> <value>\n"
08525          "       Set global dialplan variable <name> to <value>\n";
08526       return NULL;
08527    case CLI_GENERATE:
08528       return NULL;
08529    }
08530 
08531    if (a->argc != e->args + 2)
08532       return CLI_SHOWUSAGE;
08533 
08534    pbx_builtin_setvar_helper(NULL, a->argv[3], a->argv[4]);
08535    ast_cli(a->fd, "\n    -- Global variable '%s' set to '%s'\n", a->argv[3], a->argv[4]);
08536 
08537    return CLI_SUCCESS;
08538 }
08539 
08540 static char *handle_set_chanvar(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
08541 {
08542    struct ast_channel *chan;
08543    const char *chan_name, *var_name, *var_value;
08544 
08545    switch (cmd) {
08546    case CLI_INIT:
08547       e->command = "dialplan set chanvar";
08548       e->usage =
08549          "Usage: dialplan set chanvar <channel> <varname> <value>\n"
08550          "       Set channel variable <varname> to <value>\n";
08551       return NULL;
08552    case CLI_GENERATE:
08553       return ast_complete_channels(a->line, a->word, a->pos, a->n, 3);
08554    }
08555 
08556    if (a->argc != e->args + 3)
08557       return CLI_SHOWUSAGE;
08558 
08559    chan_name = a->argv[e->args];
08560    var_name = a->argv[e->args + 1];
08561    var_value = a->argv[e->args + 2];
08562 
08563    if (!(chan = ast_channel_get_by_name(chan_name))) {
08564       ast_cli(a->fd, "Channel '%s' not found\n", chan_name);
08565       return CLI_FAILURE;
08566    }
08567 
08568    pbx_builtin_setvar_helper(chan, var_name, var_value);
08569 
08570    chan = ast_channel_unref(chan);
08571 
08572    ast_cli(a->fd, "\n    -- Channel variable '%s' set to '%s' for '%s'\n",  var_name, var_value, chan_name);
08573 
08574    return CLI_SUCCESS;
08575 }
08576 
08577 static char *handle_set_extenpatternmatchnew(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
08578 {
08579    int oldval = 0;
08580 
08581    switch (cmd) {
08582    case CLI_INIT:
08583       e->command = "dialplan set extenpatternmatchnew true";
08584       e->usage =
08585          "Usage: dialplan set extenpatternmatchnew true|false\n"
08586          "       Use the NEW extension pattern matching algorithm, true or false.\n";
08587       return NULL;
08588    case CLI_GENERATE:
08589       return NULL;
08590    }
08591 
08592    if (a->argc != 4)
08593       return CLI_SHOWUSAGE;
08594 
08595    oldval =  pbx_set_extenpatternmatchnew(1);
08596 
08597    if (oldval)
08598       ast_cli(a->fd, "\n    -- Still using the NEW pattern match algorithm for extension names in the dialplan.\n");
08599    else
08600       ast_cli(a->fd, "\n    -- Switched to using the NEW pattern match algorithm for extension names in the dialplan.\n");
08601 
08602    return CLI_SUCCESS;
08603 }
08604 
08605 static char *handle_unset_extenpatternmatchnew(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
08606 {
08607    int oldval = 0;
08608 
08609    switch (cmd) {
08610    case CLI_INIT:
08611       e->command = "dialplan set extenpatternmatchnew false";
08612       e->usage =
08613          "Usage: dialplan set extenpatternmatchnew true|false\n"
08614          "       Use the NEW extension pattern matching algorithm, true or false.\n";
08615       return NULL;
08616    case CLI_GENERATE:
08617       return NULL;
08618    }
08619 
08620    if (a->argc != 4)
08621       return CLI_SHOWUSAGE;
08622 
08623    oldval =  pbx_set_extenpatternmatchnew(0);
08624 
08625    if (!oldval)
08626       ast_cli(a->fd, "\n    -- Still using the OLD pattern match algorithm for extension names in the dialplan.\n");
08627    else
08628       ast_cli(a->fd, "\n    -- Switched to using the OLD pattern match algorithm for extension names in the dialplan.\n");
08629 
08630    return CLI_SUCCESS;
08631 }
08632 
08633 /*
08634  * CLI entries for upper commands ...
08635  */
08636 static struct ast_cli_entry pbx_cli[] = {
08637    AST_CLI_DEFINE(handle_show_applications, "Shows registered dialplan applications"),
08638    AST_CLI_DEFINE(handle_show_functions, "Shows registered dialplan functions"),
08639    AST_CLI_DEFINE(handle_show_switches, "Show alternative switches"),
08640    AST_CLI_DEFINE(handle_show_hints, "Show dialplan hints"),
08641    AST_CLI_DEFINE(handle_show_hint, "Show dialplan hint"),
08642    AST_CLI_DEFINE(handle_show_globals, "Show global dialplan variables"),
08643 #ifdef AST_DEVMODE
08644    AST_CLI_DEFINE(handle_show_device2extenstate, "Show expected exten state from multiple device states"),
08645 #endif
08646    AST_CLI_DEFINE(handle_show_chanvar, "Show channel variables"),
08647    AST_CLI_DEFINE(handle_show_function, "Describe a specific dialplan function"),
08648    AST_CLI_DEFINE(handle_show_hangup_all, "Show hangup handlers of all channels"),
08649    AST_CLI_DEFINE(handle_show_hangup_channel, "Show hangup handlers of a specified channel"),
08650    AST_CLI_DEFINE(handle_show_application, "Describe a specific dialplan application"),
08651    AST_CLI_DEFINE(handle_set_global, "Set global dialplan variable"),
08652    AST_CLI_DEFINE(handle_set_chanvar, "Set a channel variable"),
08653    AST_CLI_DEFINE(handle_show_dialplan, "Show dialplan"),
08654    AST_CLI_DEFINE(handle_debug_dialplan, "Show fast extension pattern matching data structures"),
08655    AST_CLI_DEFINE(handle_unset_extenpatternmatchnew, "Use the Old extension pattern matching algorithm."),
08656    AST_CLI_DEFINE(handle_set_extenpatternmatchnew, "Use the New extension pattern matching algorithm."),
08657 };
08658 
08659 static void unreference_cached_app(struct ast_app *app)
08660 {
08661    struct ast_context *context = NULL;
08662    struct ast_exten *eroot = NULL, *e = NULL;
08663 
08664    ast_rdlock_contexts();
08665    while ((context = ast_walk_contexts(context))) {
08666       while ((eroot = ast_walk_context_extensions(context, eroot))) {
08667          while ((e = ast_walk_extension_priorities(eroot, e))) {
08668             if (e->cached_app == app)
08669                e->cached_app = NULL;
08670          }
08671       }
08672    }
08673    ast_unlock_contexts();
08674 
08675    return;
08676 }
08677 
08678 int ast_unregister_application(const char *app)
08679 {
08680    struct ast_app *tmp;
08681 
08682    AST_RWLIST_WRLOCK(&apps);
08683    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&apps, tmp, list) {
08684       if (!strcasecmp(app, tmp->name)) {
08685          unreference_cached_app(tmp);
08686          AST_RWLIST_REMOVE_CURRENT(list);
08687          ast_verb(2, "Unregistered application '%s'\n", tmp->name);
08688          ast_string_field_free_memory(tmp);
08689          ast_free(tmp);
08690          break;
08691       }
08692    }
08693    AST_RWLIST_TRAVERSE_SAFE_END;
08694    AST_RWLIST_UNLOCK(&apps);
08695 
08696    return tmp ? 0 : -1;
08697 }
08698 
08699 struct ast_context *ast_context_find_or_create(struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *name, const char *registrar)
08700 {
08701    struct ast_context *tmp, **local_contexts;
08702    struct fake_context search;
08703    int length = sizeof(struct ast_context) + strlen(name) + 1;
08704 
08705    if (!contexts_table) {
08706       /* Protect creation of contexts_table from reentrancy. */
08707       ast_wrlock_contexts();
08708       if (!contexts_table) {
08709          contexts_table = ast_hashtab_create(17,
08710             ast_hashtab_compare_contexts,
08711             ast_hashtab_resize_java,
08712             ast_hashtab_newsize_java,
08713             ast_hashtab_hash_contexts,
08714             0);
08715       }
08716       ast_unlock_contexts();
08717    }
08718 
08719    ast_copy_string(search.name, name, sizeof(search.name));
08720    if (!extcontexts) {
08721       ast_rdlock_contexts();
08722       local_contexts = &contexts;
08723       tmp = ast_hashtab_lookup(contexts_table, &search);
08724       ast_unlock_contexts();
08725       if (tmp) {
08726          tmp->refcount++;
08727          return tmp;
08728       }
08729    } else { /* local contexts just in a linked list; search there for the new context; slow, linear search, but not frequent */
08730       local_contexts = extcontexts;
08731       tmp = ast_hashtab_lookup(exttable, &search);
08732       if (tmp) {
08733          tmp->refcount++;
08734          return tmp;
08735       }
08736    }
08737 
08738    if ((tmp = ast_calloc(1, length))) {
08739       ast_rwlock_init(&tmp->lock);
08740       ast_mutex_init(&tmp->macrolock);
08741       strcpy(tmp->name, name);
08742       tmp->root = NULL;
08743       tmp->root_table = NULL;
08744       tmp->registrar = ast_strdup(registrar);
08745       tmp->includes = NULL;
08746       tmp->ignorepats = NULL;
08747       tmp->refcount = 1;
08748    } else {
08749       ast_log(LOG_ERROR, "Danger! We failed to allocate a context for %s!\n", name);
08750       return NULL;
08751    }
08752 
08753    if (!extcontexts) {
08754       ast_wrlock_contexts();
08755       tmp->next = *local_contexts;
08756       *local_contexts = tmp;
08757       ast_hashtab_insert_safe(contexts_table, tmp); /*put this context into the tree */
08758       ast_unlock_contexts();
08759       ast_debug(1, "Registered context '%s'(%p) in table %p registrar: %s\n", tmp->name, tmp, contexts_table, registrar);
08760       ast_verb(3, "Registered extension context '%s'; registrar: %s\n", tmp->name, registrar);
08761    } else {
08762       tmp->next = *local_contexts;
08763       if (exttable)
08764          ast_hashtab_insert_immediate(exttable, tmp); /*put this context into the tree */
08765 
08766       *local_contexts = tmp;
08767       ast_debug(1, "Registered context '%s'(%p) in local table %p; registrar: %s\n", tmp->name, tmp, exttable, registrar);
08768       ast_verb(3, "Registered extension context '%s'; registrar: %s\n", tmp->name, registrar);
08769    }
08770    return tmp;
08771 }
08772 
08773 void __ast_context_destroy(struct ast_context *list, struct ast_hashtab *contexttab, struct ast_context *con, const char *registrar);
08774 
08775 struct store_hint {
08776    char *context;
08777    char *exten;
08778    AST_LIST_HEAD_NOLOCK(, ast_state_cb) callbacks;
08779    int laststate;
08780    int last_presence_state;
08781    char *last_presence_subtype;
08782    char *last_presence_message;
08783 
08784    AST_LIST_ENTRY(store_hint) list;
08785    char data[1];
08786 };
08787 
08788 AST_LIST_HEAD_NOLOCK(store_hints, store_hint);
08789 
08790 static void context_merge_incls_swits_igps_other_registrars(struct ast_context *new, struct ast_context *old, const char *registrar)
08791 {
08792    struct ast_include *i;
08793    struct ast_ignorepat *ip;
08794    struct ast_sw *sw;
08795 
08796    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);
08797    /* copy in the includes, switches, and ignorepats */
08798    /* walk through includes */
08799    for (i = NULL; (i = ast_walk_context_includes(old, i)) ; ) {
08800       if (strcmp(ast_get_include_registrar(i), registrar) == 0)
08801          continue; /* not mine */
08802       ast_context_add_include2(new, ast_get_include_name(i), ast_get_include_registrar(i));
08803    }
08804 
08805    /* walk through switches */
08806    for (sw = NULL; (sw = ast_walk_context_switches(old, sw)) ; ) {
08807       if (strcmp(ast_get_switch_registrar(sw), registrar) == 0)
08808          continue; /* not mine */
08809       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));
08810    }
08811 
08812    /* walk thru ignorepats ... */
08813    for (ip = NULL; (ip = ast_walk_context_ignorepats(old, ip)); ) {
08814       if (strcmp(ast_get_ignorepat_registrar(ip), registrar) == 0)
08815          continue; /* not mine */
08816       ast_context_add_ignorepat2(new, ast_get_ignorepat_name(ip), ast_get_ignorepat_registrar(ip));
08817    }
08818 }
08819 
08820 
08821 /* the purpose of this routine is to duplicate a context, with all its substructure,
08822    except for any extens that have a matching registrar */
08823 static void context_merge(struct ast_context **extcontexts, struct ast_hashtab *exttable, struct ast_context *context, const char *registrar)
08824 {
08825    struct ast_context *new = ast_hashtab_lookup(exttable, context); /* is there a match in the new set? */
08826    struct ast_exten *exten_item, *prio_item, *new_exten_item, *new_prio_item;
08827    struct ast_hashtab_iter *exten_iter;
08828    struct ast_hashtab_iter *prio_iter;
08829    int insert_count = 0;
08830    int first = 1;
08831 
08832    /* We'll traverse all the extensions/prios, and see which are not registrar'd with
08833       the current registrar, and copy them to the new context. If the new context does not
08834       exist, we'll create it "on demand". If no items are in this context to copy, then we'll
08835       only create the empty matching context if the old one meets the criteria */
08836 
08837    if (context->root_table) {
08838       exten_iter = ast_hashtab_start_traversal(context->root_table);
08839       while ((exten_item=ast_hashtab_next(exten_iter))) {
08840          if (new) {
08841             new_exten_item = ast_hashtab_lookup(new->root_table, exten_item);
08842          } else {
08843             new_exten_item = NULL;
08844          }
08845          prio_iter = ast_hashtab_start_traversal(exten_item->peer_table);
08846          while ((prio_item=ast_hashtab_next(prio_iter))) {
08847             int res1;
08848             char *dupdstr;
08849 
08850             if (new_exten_item) {
08851                new_prio_item = ast_hashtab_lookup(new_exten_item->peer_table, prio_item);
08852             } else {
08853                new_prio_item = NULL;
08854             }
08855             if (strcmp(prio_item->registrar,registrar) == 0) {
08856                continue;
08857             }
08858             /* make sure the new context exists, so we have somewhere to stick this exten/prio */
08859             if (!new) {
08860                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 */
08861             }
08862 
08863             /* copy in the includes, switches, and ignorepats */
08864             if (first) { /* but, only need to do this once */
08865                context_merge_incls_swits_igps_other_registrars(new, context, registrar);
08866                first = 0;
08867             }
08868 
08869             if (!new) {
08870                ast_log(LOG_ERROR,"Could not allocate a new context for %s in merge_and_delete! Danger!\n", context->name);
08871                ast_hashtab_end_traversal(prio_iter);
08872                ast_hashtab_end_traversal(exten_iter);
08873                return; /* no sense continuing. */
08874             }
08875             /* we will not replace existing entries in the new context with stuff from the old context.
08876                but, if this is because of some sort of registrar conflict, we ought to say something... */
08877 
08878             dupdstr = ast_strdup(prio_item->data);
08879 
08880             res1 = ast_add_extension2(new, 0, prio_item->exten, prio_item->priority, prio_item->label,
08881                                 prio_item->matchcid ? prio_item->cidmatch : NULL, prio_item->app, dupdstr, prio_item->datad, prio_item->registrar);
08882             if (!res1 && new_exten_item && new_prio_item){
08883                ast_verb(3,"Dropping old dialplan item %s/%s/%d [%s(%s)] (registrar=%s) due to conflict with new dialplan\n",
08884                      context->name, prio_item->exten, prio_item->priority, prio_item->app, (char*)prio_item->data, prio_item->registrar);
08885             } else {
08886                /* 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,
08887                 and no double frees take place, either! */
08888                insert_count++;
08889             }
08890          }
08891          ast_hashtab_end_traversal(prio_iter);
08892       }
08893       ast_hashtab_end_traversal(exten_iter);
08894    }
08895 
08896    if (!insert_count && !new && (strcmp(context->registrar, registrar) != 0 ||
08897         (strcmp(context->registrar, registrar) == 0 && context->refcount > 1))) {
08898       /* we could have given it the registrar of the other module who incremented the refcount,
08899          but that's not available, so we give it the registrar we know about */
08900       new = ast_context_find_or_create(extcontexts, exttable, context->name, context->registrar);
08901 
08902       /* copy in the includes, switches, and ignorepats */
08903       context_merge_incls_swits_igps_other_registrars(new, context, registrar);
08904    }
08905 }
08906 
08907 
08908 /* XXX this does not check that multiple contexts are merged */
08909 void ast_merge_contexts_and_delete(struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *registrar)
08910 {
08911    double ft;
08912    struct ast_context *tmp;
08913    struct ast_context *oldcontextslist;
08914    struct ast_hashtab *oldtable;
08915    struct store_hints hints_stored = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
08916    struct store_hints hints_removed = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
08917    struct store_hint *saved_hint;
08918    struct ast_hint *hint;
08919    struct ast_exten *exten;
08920    int length;
08921    struct ast_state_cb *thiscb;
08922    struct ast_hashtab_iter *iter;
08923    struct ao2_iterator i;
08924    struct timeval begintime;
08925    struct timeval writelocktime;
08926    struct timeval endlocktime;
08927    struct timeval enddeltime;
08928 
08929    /*
08930     * It is very important that this function hold the hints
08931     * container lock _and_ the conlock during its operation; not
08932     * only do we need to ensure that the list of contexts and
08933     * extensions does not change, but also that no hint callbacks
08934     * (watchers) are added or removed during the merge/delete
08935     * process
08936     *
08937     * In addition, the locks _must_ be taken in this order, because
08938     * there are already other code paths that use this order
08939     */
08940 
08941    begintime = ast_tvnow();
08942    ast_mutex_lock(&context_merge_lock);/* Serialize ast_merge_contexts_and_delete */
08943    ast_wrlock_contexts();
08944 
08945    if (!contexts_table) {
08946       /* Well, that's odd. There are no contexts. */
08947       contexts_table = exttable;
08948       contexts = *extcontexts;
08949       ast_unlock_contexts();
08950       ast_mutex_unlock(&context_merge_lock);
08951       return;
08952    }
08953 
08954    iter = ast_hashtab_start_traversal(contexts_table);
08955    while ((tmp = ast_hashtab_next(iter))) {
08956       context_merge(extcontexts, exttable, tmp, registrar);
08957    }
08958    ast_hashtab_end_traversal(iter);
08959 
08960    ao2_lock(hints);
08961    writelocktime = ast_tvnow();
08962 
08963    /* preserve all watchers for hints */
08964    i = ao2_iterator_init(hints, AO2_ITERATOR_DONTLOCK);
08965    for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) {
08966       if (ao2_container_count(hint->callbacks)) {
08967          ao2_lock(hint);
08968          if (!hint->exten) {
08969             /* The extension has already been destroyed. (Should never happen here) */
08970             ao2_unlock(hint);
08971             continue;
08972          }
08973 
08974          length = strlen(hint->exten->exten) + strlen(hint->exten->parent->name) + 2
08975             + sizeof(*saved_hint);
08976          if (!(saved_hint = ast_calloc(1, length))) {
08977             ao2_unlock(hint);
08978             continue;
08979          }
08980 
08981          /* This removes all the callbacks from the hint into saved_hint. */
08982          while ((thiscb = ao2_callback(hint->callbacks, OBJ_UNLINK, NULL, NULL))) {
08983             AST_LIST_INSERT_TAIL(&saved_hint->callbacks, thiscb, entry);
08984             /*
08985              * We intentionally do not unref thiscb to account for the
08986              * non-ao2 reference in saved_hint->callbacks
08987              */
08988          }
08989 
08990          saved_hint->laststate = hint->laststate;
08991          saved_hint->context = saved_hint->data;
08992          strcpy(saved_hint->data, hint->exten->parent->name);
08993          saved_hint->exten = saved_hint->data + strlen(saved_hint->context) + 1;
08994          strcpy(saved_hint->exten, hint->exten->exten);
08995          if (hint->last_presence_subtype) {
08996             saved_hint->last_presence_subtype = ast_strdup(hint->last_presence_subtype);
08997          }
08998          if (hint->last_presence_message) {
08999             saved_hint->last_presence_message = ast_strdup(hint->last_presence_message);
09000          }
09001          saved_hint->last_presence_state = hint->last_presence_state;
09002          ao2_unlock(hint);
09003          AST_LIST_INSERT_HEAD(&hints_stored, saved_hint, list);
09004       }
09005    }
09006    ao2_iterator_destroy(&i);
09007 
09008    /* save the old table and list */
09009    oldtable = contexts_table;
09010    oldcontextslist = contexts;
09011 
09012    /* move in the new table and list */
09013    contexts_table = exttable;
09014    contexts = *extcontexts;
09015 
09016    /*
09017     * Restore the watchers for hints that can be found; notify
09018     * those that cannot be restored.
09019     */
09020    while ((saved_hint = AST_LIST_REMOVE_HEAD(&hints_stored, list))) {
09021       struct pbx_find_info q = { .stacklen = 0 };
09022 
09023       exten = pbx_find_extension(NULL, NULL, &q, saved_hint->context, saved_hint->exten,
09024          PRIORITY_HINT, NULL, "", E_MATCH);
09025       /*
09026        * If this is a pattern, dynamically create a new extension for this
09027        * particular match.  Note that this will only happen once for each
09028        * individual extension, because the pattern will no longer match first.
09029        */
09030       if (exten && exten->exten[0] == '_') {
09031          ast_add_extension_nolock(exten->parent->name, 0, saved_hint->exten,
09032             PRIORITY_HINT, NULL, 0, exten->app, ast_strdup(exten->data), ast_free_ptr,
09033             exten->registrar);
09034          /* rwlocks are not recursive locks */
09035          exten = ast_hint_extension_nolock(NULL, saved_hint->context,
09036             saved_hint->exten);
09037       }
09038 
09039       /* Find the hint in the hints container */
09040       hint = exten ? ao2_find(hints, exten, 0) : NULL;
09041       if (!hint) {
09042          /*
09043           * Notify watchers of this removed hint later when we aren't
09044           * encumberd by so many locks.
09045           */
09046          AST_LIST_INSERT_HEAD(&hints_removed, saved_hint, list);
09047       } else {
09048          ao2_lock(hint);
09049          while ((thiscb = AST_LIST_REMOVE_HEAD(&saved_hint->callbacks, entry))) {
09050             ao2_link(hint->callbacks, thiscb);
09051             /* Ref that we added when putting into saved_hint->callbacks */
09052             ao2_ref(thiscb, -1);
09053          }
09054          hint->laststate = saved_hint->laststate;
09055          hint->last_presence_state = saved_hint->last_presence_state;
09056          hint->last_presence_subtype = saved_hint->last_presence_subtype;
09057          hint->last_presence_message = saved_hint->last_presence_message;
09058          ao2_unlock(hint);
09059          ao2_ref(hint, -1);
09060          /*
09061           * The free of saved_hint->last_presence_subtype and
09062           * saved_hint->last_presence_message is not necessary here.
09063           */
09064          ast_free(saved_hint);
09065       }
09066    }
09067 
09068    ao2_unlock(hints);
09069    ast_unlock_contexts();
09070 
09071    /*
09072     * Notify watchers of all removed hints with the same lock
09073     * environment as handle_statechange().
09074     */
09075    while ((saved_hint = AST_LIST_REMOVE_HEAD(&hints_removed, list))) {
09076       /* this hint has been removed, notify the watchers */
09077       while ((thiscb = AST_LIST_REMOVE_HEAD(&saved_hint->callbacks, entry))) {
09078          execute_state_callback(thiscb->change_cb,
09079             saved_hint->context,
09080             saved_hint->exten,
09081             thiscb->data,
09082             AST_HINT_UPDATE_DEVICE,
09083             NULL,
09084             NULL);
09085          /* Ref that we added when putting into saved_hint->callbacks */
09086          ao2_ref(thiscb, -1);
09087       }
09088       ast_free(saved_hint->last_presence_subtype);
09089       ast_free(saved_hint->last_presence_message);
09090       ast_free(saved_hint);
09091    }
09092 
09093    ast_mutex_unlock(&context_merge_lock);
09094    endlocktime = ast_tvnow();
09095 
09096    /*
09097     * The old list and hashtab no longer are relevant, delete them
09098     * while the rest of asterisk is now freely using the new stuff
09099     * instead.
09100     */
09101 
09102    ast_hashtab_destroy(oldtable, NULL);
09103 
09104    for (tmp = oldcontextslist; tmp; ) {
09105       struct ast_context *next;  /* next starting point */
09106 
09107       next = tmp->next;
09108       __ast_internal_context_destroy(tmp);
09109       tmp = next;
09110    }
09111    enddeltime = ast_tvnow();
09112 
09113    ft = ast_tvdiff_us(writelocktime, begintime);
09114    ft /= 1000000.0;
09115    ast_verb(3,"Time to scan old dialplan and merge leftovers back into the new: %8.6f sec\n", ft);
09116 
09117    ft = ast_tvdiff_us(endlocktime, writelocktime);
09118    ft /= 1000000.0;
09119    ast_verb(3,"Time to restore hints and swap in new dialplan: %8.6f sec\n", ft);
09120 
09121    ft = ast_tvdiff_us(enddeltime, endlocktime);
09122    ft /= 1000000.0;
09123    ast_verb(3,"Time to delete the old dialplan: %8.6f sec\n", ft);
09124 
09125    ft = ast_tvdiff_us(enddeltime, begintime);
09126    ft /= 1000000.0;
09127    ast_verb(3,"Total time merge_contexts_delete: %8.6f sec\n", ft);
09128 }
09129 
09130 /*
09131  * errno values
09132  *  EBUSY  - can't lock
09133  *  ENOENT - no existence of context
09134  */
09135 int ast_context_add_include(const char *context, const char *include, const char *registrar)
09136 {
09137    int ret = -1;
09138    struct ast_context *c;
09139 
09140    c = find_context_locked(context);
09141    if (c) {
09142       ret = ast_context_add_include2(c, include, registrar);
09143       ast_unlock_contexts();
09144    }
09145    return ret;
09146 }
09147 
09148 /*! \brief Helper for get_range.
09149  * return the index of the matching entry, starting from 1.
09150  * If names is not supplied, try numeric values.
09151  */
09152 static int lookup_name(const char *s, const char * const names[], int max)
09153 {
09154    int i;
09155 
09156    if (names && *s > '9') {
09157       for (i = 0; names[i]; i++) {
09158          if (!strcasecmp(s, names[i])) {
09159             return i;
09160          }
09161       }
09162    }
09163 
09164    /* Allow months and weekdays to be specified as numbers, as well */
09165    if (sscanf(s, "%2d", &i) == 1 && i >= 1 && i <= max) {
09166       /* What the array offset would have been: "1" would be at offset 0 */
09167       return i - 1;
09168    }
09169    return -1; /* error return */
09170 }
09171 
09172 /*! \brief helper function to return a range up to max (7, 12, 31 respectively).
09173  * names, if supplied, is an array of names that should be mapped to numbers.
09174  */
09175 static unsigned get_range(char *src, int max, const char * const names[], const char *msg)
09176 {
09177    int start, end; /* start and ending position */
09178    unsigned int mask = 0;
09179    char *part;
09180 
09181    /* Check for whole range */
09182    if (ast_strlen_zero(src) || !strcmp(src, "*")) {
09183       return (1 << max) - 1;
09184    }
09185 
09186    while ((part = strsep(&src, "&"))) {
09187       /* Get start and ending position */
09188       char *endpart = strchr(part, '-');
09189       if (endpart) {
09190          *endpart++ = '\0';
09191       }
09192       /* Find the start */
09193       if ((start = lookup_name(part, names, max)) < 0) {
09194          ast_log(LOG_WARNING, "Invalid %s '%s', skipping element\n", msg, part);
09195          continue;
09196       }
09197       if (endpart) { /* find end of range */
09198          if ((end = lookup_name(endpart, names, max)) < 0) {
09199             ast_log(LOG_WARNING, "Invalid end %s '%s', skipping element\n", msg, endpart);
09200             continue;
09201          }
09202       } else {
09203          end = start;
09204       }
09205       /* Fill the mask. Remember that ranges are cyclic */
09206       mask |= (1 << end);   /* initialize with last element */
09207       while (start != end) {
09208          mask |= (1 << start);
09209          if (++start >= max) {
09210             start = 0;
09211          }
09212       }
09213    }
09214    return mask;
09215 }
09216 
09217 /*! \brief store a bitmask of valid times, one bit each 1 minute */
09218 static void get_timerange(struct ast_timing *i, char *times)
09219 {
09220    char *endpart, *part;
09221    int x;
09222    int st_h, st_m;
09223    int endh, endm;
09224    int minute_start, minute_end;
09225 
09226    /* start disabling all times, fill the fields with 0's, as they may contain garbage */
09227    memset(i->minmask, 0, sizeof(i->minmask));
09228 
09229    /* 1-minute per bit */
09230    /* Star is all times */
09231    if (ast_strlen_zero(times) || !strcmp(times, "*")) {
09232       /* 48, because each hour takes 2 integers; 30 bits each */
09233       for (x = 0; x < 48; x++) {
09234          i->minmask[x] = 0x3fffffff; /* 30 bits */
09235       }
09236       return;
09237    }
09238    /* Otherwise expect a range */
09239    while ((part = strsep(&times, "&"))) {
09240       if (!(endpart = strchr(part, '-'))) {
09241          if (sscanf(part, "%2d:%2d", &st_h, &st_m) != 2 || st_h < 0 || st_h > 23 || st_m < 0 || st_m > 59) {
09242             ast_log(LOG_WARNING, "%s isn't a valid time.\n", part);
09243             continue;
09244          }
09245          i->minmask[st_h * 2 + (st_m >= 30 ? 1 : 0)] |= (1 << (st_m % 30));
09246          continue;
09247       }
09248       *endpart++ = '\0';
09249       /* why skip non digits? Mostly to skip spaces */
09250       while (*endpart && !isdigit(*endpart)) {
09251          endpart++;
09252       }
09253       if (!*endpart) {
09254          ast_log(LOG_WARNING, "Invalid time range starting with '%s-'.\n", part);
09255          continue;
09256       }
09257       if (sscanf(part, "%2d:%2d", &st_h, &st_m) != 2 || st_h < 0 || st_h > 23 || st_m < 0 || st_m > 59) {
09258          ast_log(LOG_WARNING, "'%s' isn't a valid start time.\n", part);
09259          continue;
09260       }
09261       if (sscanf(endpart, "%2d:%2d", &endh, &endm) != 2 || endh < 0 || endh > 23 || endm < 0 || endm > 59) {
09262          ast_log(LOG_WARNING, "'%s' isn't a valid end time.\n", endpart);
09263          continue;
09264       }
09265       minute_start = st_h * 60 + st_m;
09266       minute_end = endh * 60 + endm;
09267       /* Go through the time and enable each appropriate bit */
09268       for (x = minute_start; x != minute_end; x = (x + 1) % (24 * 60)) {
09269          i->minmask[x / 30] |= (1 << (x % 30));
09270       }
09271       /* Do the last one */
09272       i->minmask[x / 30] |= (1 << (x % 30));
09273    }
09274    /* All done */
09275    return;
09276 }
09277 
09278 static const char * const days[] =
09279 {
09280    "sun",
09281    "mon",
09282    "tue",
09283    "wed",
09284    "thu",
09285    "fri",
09286    "sat",
09287    NULL,
09288 };
09289 
09290 static const char * const months[] =
09291 {
09292    "jan",
09293    "feb",
09294    "mar",
09295    "apr",
09296    "may",
09297    "jun",
09298    "jul",
09299    "aug",
09300    "sep",
09301    "oct",
09302    "nov",
09303    "dec",
09304    NULL,
09305 };
09306 
09307 int ast_build_timing(struct ast_timing *i, const char *info_in)
09308 {
09309    char *info;
09310    int j, num_fields, last_sep = -1;
09311 
09312    i->timezone = NULL;
09313 
09314    /* Check for empty just in case */
09315    if (ast_strlen_zero(info_in)) {
09316       return 0;
09317    }
09318 
09319    /* make a copy just in case we were passed a static string */
09320    info = ast_strdupa(info_in);
09321 
09322    /* count the number of fields in the timespec */
09323    for (j = 0, num_fields = 1; info[j] != '\0'; j++) {
09324       if (info[j] == ',') {
09325          last_sep = j;
09326          num_fields++;
09327       }
09328    }
09329 
09330    /* save the timezone, if it is specified */
09331    if (num_fields == 5) {
09332       i->timezone = ast_strdup(info + last_sep + 1);
09333    }
09334 
09335    /* Assume everything except time */
09336    i->monthmask = 0xfff;   /* 12 bits */
09337    i->daymask = 0x7fffffffU; /* 31 bits */
09338    i->dowmask = 0x7f; /* 7 bits */
09339    /* on each call, use strsep() to move info to the next argument */
09340    get_timerange(i, strsep(&info, "|,"));
09341    if (info)
09342       i->dowmask = get_range(strsep(&info, "|,"), 7, days, "day of week");
09343    if (info)
09344       i->daymask = get_range(strsep(&info, "|,"), 31, NULL, "day");
09345    if (info)
09346       i->monthmask = get_range(strsep(&info, "|,"), 12, months, "month");
09347    return 1;
09348 }
09349 
09350 int ast_check_timing(const struct ast_timing *i)
09351 {
09352    return ast_check_timing2(i, ast_tvnow());
09353 }
09354 
09355 int ast_check_timing2(const struct ast_timing *i, const struct timeval tv)
09356 {
09357    struct ast_tm tm;
09358 
09359    ast_localtime(&tv, &tm, i->timezone);
09360 
09361    /* If it's not the right month, return */
09362    if (!(i->monthmask & (1 << tm.tm_mon)))
09363       return 0;
09364 
09365    /* If it's not that time of the month.... */
09366    /* Warning, tm_mday has range 1..31! */
09367    if (!(i->daymask & (1 << (tm.tm_mday-1))))
09368       return 0;
09369 
09370    /* If it's not the right day of the week */
09371    if (!(i->dowmask & (1 << tm.tm_wday)))
09372       return 0;
09373 
09374    /* Sanity check the hour just to be safe */
09375    if ((tm.tm_hour < 0) || (tm.tm_hour > 23)) {
09376       ast_log(LOG_WARNING, "Insane time...\n");
09377       return 0;
09378    }
09379 
09380    /* Now the tough part, we calculate if it fits
09381       in the right time based on min/hour */
09382    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))))
09383       return 0;
09384 
09385    /* If we got this far, then we're good */
09386    return 1;
09387 }
09388 
09389 int ast_destroy_timing(struct ast_timing *i)
09390 {
09391    if (i->timezone) {
09392       ast_free(i->timezone);
09393       i->timezone = NULL;
09394    }
09395    return 0;
09396 }
09397 /*
09398  * errno values
09399  *  ENOMEM - out of memory
09400  *  EBUSY  - can't lock
09401  *  EEXIST - already included
09402  *  EINVAL - there is no existence of context for inclusion
09403  */
09404 int ast_context_add_include2(struct ast_context *con, const char *value,
09405    const char *registrar)
09406 {
09407    struct ast_include *new_include;
09408    char *c;
09409    struct ast_include *i, *il = NULL; /* include, include_last */
09410    int length;
09411    char *p;
09412 
09413    length = sizeof(struct ast_include);
09414    length += 2 * (strlen(value) + 1);
09415 
09416    /* allocate new include structure ... */
09417    if (!(new_include = ast_calloc(1, length)))
09418       return -1;
09419    /* Fill in this structure. Use 'p' for assignments, as the fields
09420     * in the structure are 'const char *'
09421     */
09422    p = new_include->stuff;
09423    new_include->name = p;
09424    strcpy(p, value);
09425    p += strlen(value) + 1;
09426    new_include->rname = p;
09427    strcpy(p, value);
09428    /* Strip off timing info, and process if it is there */
09429    if ( (c = strchr(p, ',')) ) {
09430       *c++ = '\0';
09431       new_include->hastime = ast_build_timing(&(new_include->timing), c);
09432    }
09433    new_include->next      = NULL;
09434    new_include->registrar = registrar;
09435 
09436    ast_wrlock_context(con);
09437 
09438    /* ... go to last include and check if context is already included too... */
09439    for (i = con->includes; i; i = i->next) {
09440       if (!strcasecmp(i->name, new_include->name)) {
09441          ast_destroy_timing(&(new_include->timing));
09442          ast_free(new_include);
09443          ast_unlock_context(con);
09444          errno = EEXIST;
09445          return -1;
09446       }
09447       il = i;
09448    }
09449 
09450    /* ... include new context into context list, unlock, return */
09451    if (il)
09452       il->next = new_include;
09453    else
09454       con->includes = new_include;
09455    ast_verb(3, "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con));
09456 
09457    ast_unlock_context(con);
09458 
09459    return 0;
09460 }
09461 
09462 /*
09463  * errno values
09464  *  EBUSY  - can't lock
09465  *  ENOENT - no existence of context
09466  */
09467 int ast_context_add_switch(const char *context, const char *sw, const char *data, int eval, const char *registrar)
09468 {
09469    int ret = -1;
09470    struct ast_context *c;
09471 
09472    c = find_context_locked(context);
09473    if (c) { /* found, add switch to this context */
09474       ret = ast_context_add_switch2(c, sw, data, eval, registrar);
09475       ast_unlock_contexts();
09476    }
09477    return ret;
09478 }
09479 
09480 /*
09481  * errno values
09482  *  ENOMEM - out of memory
09483  *  EBUSY  - can't lock
09484  *  EEXIST - already included
09485  *  EINVAL - there is no existence of context for inclusion
09486  */
09487 int ast_context_add_switch2(struct ast_context *con, const char *value,
09488    const char *data, int eval, const char *registrar)
09489 {
09490    struct ast_sw *new_sw;
09491    struct ast_sw *i;
09492    int length;
09493    char *p;
09494 
09495    length = sizeof(struct ast_sw);
09496    length += strlen(value) + 1;
09497    if (data)
09498       length += strlen(data);
09499    length++;
09500 
09501    /* allocate new sw structure ... */
09502    if (!(new_sw = ast_calloc(1, length)))
09503       return -1;
09504    /* ... fill in this structure ... */
09505    p = new_sw->stuff;
09506    new_sw->name = p;
09507    strcpy(new_sw->name, value);
09508    p += strlen(value) + 1;
09509    new_sw->data = p;
09510    if (data) {
09511       strcpy(new_sw->data, data);
09512       p += strlen(data) + 1;
09513    } else {
09514       strcpy(new_sw->data, "");
09515       p++;
09516    }
09517    new_sw->eval     = eval;
09518    new_sw->registrar = registrar;
09519 
09520    /* ... try to lock this context ... */
09521    ast_wrlock_context(con);
09522 
09523    /* ... go to last sw and check if context is already swd too... */
09524    AST_LIST_TRAVERSE(&con->alts, i, list) {
09525       if (!strcasecmp(i->name, new_sw->name) && !strcasecmp(i->data, new_sw->data)) {
09526          ast_free(new_sw);
09527          ast_unlock_context(con);
09528          errno = EEXIST;
09529          return -1;
09530       }
09531    }
09532 
09533    /* ... sw new context into context list, unlock, return */
09534    AST_LIST_INSERT_TAIL(&con->alts, new_sw, list);
09535 
09536    ast_verb(3, "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con));
09537 
09538    ast_unlock_context(con);
09539 
09540    return 0;
09541 }
09542 
09543 /*
09544  * EBUSY  - can't lock
09545  * ENOENT - there is not context existence
09546  */
09547 int ast_context_remove_ignorepat(const char *context, const char *ignorepat, const char *registrar)
09548 {
09549    int ret = -1;
09550    struct ast_context *c;
09551 
09552    c = find_context_locked(context);
09553    if (c) {
09554       ret = ast_context_remove_ignorepat2(c, ignorepat, registrar);
09555       ast_unlock_contexts();
09556    }
09557    return ret;
09558 }
09559 
09560 int ast_context_remove_ignorepat2(struct ast_context *con, const char *ignorepat, const char *registrar)
09561 {
09562    struct ast_ignorepat *ip, *ipl = NULL;
09563 
09564    ast_wrlock_context(con);
09565 
09566    for (ip = con->ignorepats; ip; ip = ip->next) {
09567       if (!strcmp(ip->pattern, ignorepat) &&
09568          (!registrar || (registrar == ip->registrar))) {
09569          if (ipl) {
09570             ipl->next = ip->next;
09571             ast_free(ip);
09572          } else {
09573             con->ignorepats = ip->next;
09574             ast_free(ip);
09575          }
09576          ast_unlock_context(con);
09577          return 0;
09578       }
09579       ipl = ip;
09580    }
09581 
09582    ast_unlock_context(con);
09583    errno = EINVAL;
09584    return -1;
09585 }
09586 
09587 /*
09588  * EBUSY - can't lock
09589  * ENOENT - there is no existence of context
09590  */
09591 int ast_context_add_ignorepat(const char *context, const char *value, const char *registrar)
09592 {
09593    int ret = -1;
09594    struct ast_context *c;
09595 
09596    c = find_context_locked(context);
09597    if (c) {
09598       ret = ast_context_add_ignorepat2(c, value, registrar);
09599       ast_unlock_contexts();
09600    }
09601    return ret;
09602 }
09603 
09604 int ast_context_add_ignorepat2(struct ast_context *con, const char *value, const char *registrar)
09605 {
09606    struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL;
09607    int length;
09608    char *pattern;
09609    length = sizeof(struct ast_ignorepat);
09610    length += strlen(value) + 1;
09611    if (!(ignorepat = ast_calloc(1, length)))
09612       return -1;
09613    /* The cast to char * is because we need to write the initial value.
09614     * The field is not supposed to be modified otherwise.  Also, gcc 4.2
09615     * sees the cast as dereferencing a type-punned pointer and warns about
09616     * it.  This is the workaround (we're telling gcc, yes, that's really
09617     * what we wanted to do).
09618     */
09619    pattern = (char *) ignorepat->pattern;
09620    strcpy(pattern, value);
09621    ignorepat->next = NULL;
09622    ignorepat->registrar = registrar;
09623    ast_wrlock_context(con);
09624    for (ignorepatc = con->ignorepats; ignorepatc; ignorepatc = ignorepatc->next) {
09625       ignorepatl = ignorepatc;
09626       if (!strcasecmp(ignorepatc->pattern, value)) {
09627          /* Already there */
09628          ast_unlock_context(con);
09629          ast_free(ignorepat);
09630          errno = EEXIST;
09631          return -1;
09632       }
09633    }
09634    if (ignorepatl)
09635       ignorepatl->next = ignorepat;
09636    else
09637       con->ignorepats = ignorepat;
09638    ast_unlock_context(con);
09639    return 0;
09640 
09641 }
09642 
09643 int ast_ignore_pattern(const char *context, const char *pattern)
09644 {
09645    struct ast_context *con = ast_context_find(context);
09646 
09647    if (con) {
09648       struct ast_ignorepat *pat;
09649 
09650       for (pat = con->ignorepats; pat; pat = pat->next) {
09651          if (ast_extension_match(pat->pattern, pattern))
09652             return 1;
09653       }
09654    }
09655 
09656    return 0;
09657 }
09658 
09659 /*
09660  * ast_add_extension_nolock -- use only in situations where the conlock is already held
09661  * ENOENT  - no existence of context
09662  *
09663  */
09664 static int ast_add_extension_nolock(const char *context, int replace, const char *extension,
09665    int priority, const char *label, const char *callerid,
09666    const char *application, void *data, void (*datad)(void *), const char *registrar)
09667 {
09668    int ret = -1;
09669    struct ast_context *c;
09670 
09671    c = find_context(context);
09672    if (c) {
09673       ret = ast_add_extension2_lockopt(c, replace, extension, priority, label, callerid,
09674          application, data, datad, registrar, 1);
09675    }
09676 
09677    return ret;
09678 }
09679 /*
09680  * EBUSY   - can't lock
09681  * ENOENT  - no existence of context
09682  *
09683  */
09684 int ast_add_extension(const char *context, int replace, const char *extension,
09685    int priority, const char *label, const char *callerid,
09686    const char *application, void *data, void (*datad)(void *), const char *registrar)
09687 {
09688    int ret = -1;
09689    struct ast_context *c;
09690 
09691    c = find_context_locked(context);
09692    if (c) {
09693       ret = ast_add_extension2(c, replace, extension, priority, label, callerid,
09694          application, data, datad, registrar);
09695       ast_unlock_contexts();
09696    }
09697 
09698    return ret;
09699 }
09700 
09701 int ast_explicit_goto(struct ast_channel *chan, const char *context, const char *exten, int priority)
09702 {
09703    if (!chan)
09704       return -1;
09705 
09706    ast_channel_lock(chan);
09707 
09708    if (!ast_strlen_zero(context))
09709       ast_channel_context_set(chan, context);
09710    if (!ast_strlen_zero(exten))
09711       ast_channel_exten_set(chan, exten);
09712    if (priority > -1) {
09713       /* see flag description in channel.h for explanation */
09714       if (ast_test_flag(ast_channel_flags(chan), AST_FLAG_IN_AUTOLOOP)) {
09715          --priority;
09716       }
09717       ast_channel_priority_set(chan, priority);
09718    }
09719 
09720    ast_channel_unlock(chan);
09721 
09722    return 0;
09723 }
09724 
09725 int ast_async_goto(struct ast_channel *chan, const char *context, const char *exten, int priority)
09726 {
09727    int res = 0;
09728    struct ast_channel *tmpchan;
09729    struct {
09730       char *accountcode;
09731       char *exten;
09732       char *context;
09733       char *linkedid;
09734       char *name;
09735       struct ast_cdr *cdr;
09736       int amaflags;
09737       int state;
09738       struct ast_format readformat;
09739       struct ast_format writeformat;
09740    } tmpvars = { 0, };
09741 
09742    ast_channel_lock(chan);
09743    if (ast_channel_pbx(chan)) { /* This channel is currently in the PBX */
09744       ast_explicit_goto(chan, context, exten, priority + 1);
09745       ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO);
09746       ast_channel_unlock(chan);
09747       return res;
09748    }
09749 
09750    /* In order to do it when the channel doesn't really exist within
09751     * the PBX, we have to make a new channel, masquerade, and start the PBX
09752     * at the new location */
09753    tmpvars.accountcode = ast_strdupa(ast_channel_accountcode(chan));
09754    tmpvars.exten = ast_strdupa(ast_channel_exten(chan));
09755    tmpvars.context = ast_strdupa(ast_channel_context(chan));
09756    tmpvars.linkedid = ast_strdupa(ast_channel_linkedid(chan));
09757    tmpvars.name = ast_strdupa(ast_channel_name(chan));
09758    tmpvars.amaflags = ast_channel_amaflags(chan);
09759    tmpvars.state = ast_channel_state(chan);
09760    ast_format_copy(&tmpvars.writeformat, ast_channel_writeformat(chan));
09761    ast_format_copy(&tmpvars.readformat, ast_channel_readformat(chan));
09762    tmpvars.cdr = ast_channel_cdr(chan) ? ast_cdr_dup(ast_channel_cdr(chan)) : NULL;
09763 
09764    ast_channel_unlock(chan);
09765 
09766    /* Do not hold any channel locks while calling channel_alloc() since the function
09767     * locks the channel container when linking the new channel in. */
09768    if (!(tmpchan = ast_channel_alloc(0, tmpvars.state, 0, 0, tmpvars.accountcode, tmpvars.exten, tmpvars.context, tmpvars.linkedid, tmpvars.amaflags, "AsyncGoto/%s", tmpvars.name))) {
09769       ast_cdr_discard(tmpvars.cdr);
09770       return -1;
09771    }
09772 
09773    /* copy the cdr info over */
09774    if (tmpvars.cdr) {
09775       ast_cdr_discard(ast_channel_cdr(tmpchan));
09776       ast_channel_cdr_set(tmpchan, tmpvars.cdr);
09777       tmpvars.cdr = NULL;
09778    }
09779 
09780    /* Make formats okay */
09781    ast_format_copy(ast_channel_readformat(tmpchan), &tmpvars.readformat);
09782    ast_format_copy(ast_channel_writeformat(tmpchan), &tmpvars.writeformat);
09783 
09784    /* Setup proper location. Never hold another channel lock while calling this function. */
09785    ast_explicit_goto(tmpchan, S_OR(context, tmpvars.context), S_OR(exten, tmpvars.exten), priority);
09786 
09787    /* Masquerade into tmp channel */
09788    if (ast_channel_masquerade(tmpchan, chan)) {
09789       /* Failed to set up the masquerade.  It's probably chan_local
09790        * in the middle of optimizing itself out.  Sad. :( */
09791       ast_hangup(tmpchan);
09792       tmpchan = NULL;
09793       res = -1;
09794    } else {
09795       ast_do_masquerade(tmpchan);
09796       /* Start the PBX going on our stolen channel */
09797       if (ast_pbx_start(tmpchan)) {
09798          ast_log(LOG_WARNING, "Unable to start PBX on %s\n", ast_channel_name(tmpchan));
09799          ast_hangup(tmpchan);
09800          res = -1;
09801       }
09802    }
09803 
09804    return res;
09805 }
09806 
09807 int ast_async_goto_by_name(const char *channame, const char *context, const char *exten, int priority)
09808 {
09809    struct ast_channel *chan;
09810    int res = -1;
09811 
09812    if ((chan = ast_channel_get_by_name(channame))) {
09813       res = ast_async_goto(chan, context, exten, priority);
09814       chan = ast_channel_unref(chan);
09815    }
09816 
09817    return res;
09818 }
09819 
09820 /*! \brief copy a string skipping whitespace */
09821 static int ext_strncpy(char *dst, const char *src, int len)
09822 {
09823    int count = 0;
09824    int insquares = 0;
09825 
09826    while (*src && (count < len - 1)) {
09827       if (*src == '[') {
09828          insquares = 1;
09829       } else if (*src == ']') {
09830          insquares = 0;
09831       } else if (*src == ' ' && !insquares) {
09832          src++;
09833          continue;
09834       }
09835       *dst = *src;
09836       dst++;
09837       src++;
09838       count++;
09839    }
09840    *dst = '\0';
09841 
09842    return count;
09843 }
09844 
09845 /*!
09846  * \brief add the extension in the priority chain.
09847  * \retval 0 on success.
09848  * \retval -1 on failure.
09849 */
09850 static int add_priority(struct ast_context *con, struct ast_exten *tmp,
09851    struct ast_exten *el, struct ast_exten *e, int replace)
09852 {
09853    struct ast_exten *ep;
09854    struct ast_exten *eh=e;
09855    int repeated_label = 0; /* Track if this label is a repeat, assume no. */
09856 
09857    for (ep = NULL; e ; ep = e, e = e->peer) {
09858       if (e->label && tmp->label && e->priority != tmp->priority && !strcmp(e->label, tmp->label)) {
09859          if (strcmp(e->exten, tmp->exten)) {
09860             ast_log(LOG_WARNING,
09861                "Extension '%s' priority %d in '%s', label '%s' already in use at aliased extension '%s' priority %d\n",
09862                tmp->exten, tmp->priority, con->name, tmp->label, e->exten, e->priority);
09863          } else {
09864             ast_log(LOG_WARNING,
09865                "Extension '%s' priority %d in '%s', label '%s' already in use at priority %d\n",
09866                tmp->exten, tmp->priority, con->name, tmp->label, e->priority);
09867          }
09868          repeated_label = 1;
09869       }
09870       if (e->priority >= tmp->priority) {
09871          break;
09872       }
09873    }
09874 
09875    if (repeated_label) {   /* Discard the label since it's a repeat. */
09876       tmp->label = NULL;
09877    }
09878 
09879    if (!e) {   /* go at the end, and ep is surely set because the list is not empty */
09880       ast_hashtab_insert_safe(eh->peer_table, tmp);
09881 
09882       if (tmp->label) {
09883          ast_hashtab_insert_safe(eh->peer_label_table, tmp);
09884       }
09885       ep->peer = tmp;
09886       return 0;   /* success */
09887    }
09888    if (e->priority == tmp->priority) {
09889       /* Can't have something exactly the same.  Is this a
09890          replacement?  If so, replace, otherwise, bonk. */
09891       if (!replace) {
09892          if (strcmp(e->exten, tmp->exten)) {
09893             ast_log(LOG_WARNING,
09894                "Unable to register extension '%s' priority %d in '%s', already in use by aliased extension '%s'\n",
09895                tmp->exten, tmp->priority, con->name, e->exten);
09896          } else {
09897             ast_log(LOG_WARNING,
09898                "Unable to register extension '%s' priority %d in '%s', already in use\n",
09899                tmp->exten, tmp->priority, con->name);
09900          }
09901          if (tmp->datad) {
09902             tmp->datad(tmp->data);
09903             /* if you free this, null it out */
09904             tmp->data = NULL;
09905          }
09906 
09907          ast_free(tmp);
09908          return -1;
09909       }
09910       /* we are replacing e, so copy the link fields and then update
09911        * whoever pointed to e to point to us
09912        */
09913       tmp->next = e->next; /* not meaningful if we are not first in the peer list */
09914       tmp->peer = e->peer; /* always meaningful */
09915       if (ep)  {     /* We're in the peer list, just insert ourselves */
09916          ast_hashtab_remove_object_via_lookup(eh->peer_table,e);
09917 
09918          if (e->label) {
09919             ast_hashtab_remove_object_via_lookup(eh->peer_label_table,e);
09920          }
09921 
09922          ast_hashtab_insert_safe(eh->peer_table,tmp);
09923          if (tmp->label) {
09924             ast_hashtab_insert_safe(eh->peer_label_table,tmp);
09925          }
09926 
09927          ep->peer = tmp;
09928       } else if (el) {     /* We're the first extension. Take over e's functions */
09929          struct match_char *x = add_exten_to_pattern_tree(con, e, 1);
09930          tmp->peer_table = e->peer_table;
09931          tmp->peer_label_table = e->peer_label_table;
09932          ast_hashtab_remove_object_via_lookup(tmp->peer_table,e);
09933          ast_hashtab_insert_safe(tmp->peer_table,tmp);
09934          if (e->label) {
09935             ast_hashtab_remove_object_via_lookup(tmp->peer_label_table, e);
09936          }
09937          if (tmp->label) {
09938             ast_hashtab_insert_safe(tmp->peer_label_table, tmp);
09939          }
09940 
09941          ast_hashtab_remove_object_via_lookup(con->root_table, e);
09942          ast_hashtab_insert_safe(con->root_table, tmp);
09943          el->next = tmp;
09944          /* The pattern trie points to this exten; replace the pointer,
09945             and all will be well */
09946          if (x) { /* if the trie isn't formed yet, don't sweat this */
09947             if (x->exten) { /* this test for safety purposes */
09948                x->exten = tmp; /* replace what would become a bad pointer */
09949             } else {
09950                ast_log(LOG_ERROR,"Trying to delete an exten from a context, but the pattern tree node returned isn't an extension\n");
09951             }
09952          }
09953       } else {       /* We're the very first extension.  */
09954          struct match_char *x = add_exten_to_pattern_tree(con, e, 1);
09955          ast_hashtab_remove_object_via_lookup(con->root_table, e);
09956          ast_hashtab_insert_safe(con->root_table, tmp);
09957          tmp->peer_table = e->peer_table;
09958          tmp->peer_label_table = e->peer_label_table;
09959          ast_hashtab_remove_object_via_lookup(tmp->peer_table, e);
09960          ast_hashtab_insert_safe(tmp->peer_table, tmp);
09961          if (e->label) {
09962             ast_hashtab_remove_object_via_lookup(tmp->peer_label_table, e);
09963          }
09964          if (tmp->label) {
09965             ast_hashtab_insert_safe(tmp->peer_label_table, tmp);
09966          }
09967 
09968          ast_hashtab_remove_object_via_lookup(con->root_table, e);
09969          ast_hashtab_insert_safe(con->root_table, tmp);
09970          con->root = tmp;
09971          /* The pattern trie points to this exten; replace the pointer,
09972             and all will be well */
09973          if (x) { /* if the trie isn't formed yet; no problem */
09974             if (x->exten) { /* this test for safety purposes */
09975                x->exten = tmp; /* replace what would become a bad pointer */
09976             } else {
09977                ast_log(LOG_ERROR,"Trying to delete an exten from a context, but the pattern tree node returned isn't an extension\n");
09978             }
09979          }
09980       }
09981       if (tmp->priority == PRIORITY_HINT)
09982          ast_change_hint(e,tmp);
09983       /* Destroy the old one */
09984       if (e->datad)
09985          e->datad(e->data);
09986       ast_free(e);
09987    } else { /* Slip ourselves in just before e */
09988       tmp->peer = e;
09989       tmp->next = e->next; /* extension chain, or NULL if e is not the first extension */
09990       if (ep) {         /* Easy enough, we're just in the peer list */
09991          if (tmp->label) {
09992             ast_hashtab_insert_safe(eh->peer_label_table, tmp);
09993          }
09994          ast_hashtab_insert_safe(eh->peer_table, tmp);
09995          ep->peer = tmp;
09996       } else {       /* we are the first in some peer list, so link in the ext list */
09997          tmp->peer_table = e->peer_table;
09998          tmp->peer_label_table = e->peer_label_table;
09999          e->peer_table = 0;
10000          e->peer_label_table = 0;
10001          ast_hashtab_insert_safe(tmp->peer_table, tmp);
10002          if (tmp->label) {
10003             ast_hashtab_insert_safe(tmp->peer_label_table, tmp);
10004          }
10005          ast_hashtab_remove_object_via_lookup(con->root_table, e);
10006          ast_hashtab_insert_safe(con->root_table, tmp);
10007          if (el)
10008             el->next = tmp;   /* in the middle... */
10009          else
10010             con->root = tmp; /* ... or at the head */
10011          e->next = NULL;   /* e is no more at the head, so e->next must be reset */
10012       }
10013       /* And immediately return success. */
10014       if (tmp->priority == PRIORITY_HINT) {
10015          ast_add_hint(tmp);
10016       }
10017    }
10018    return 0;
10019 }
10020 
10021 /*! \brief
10022  * Main interface to add extensions to the list for out context.
10023  *
10024  * We sort extensions in order of matching preference, so that we can
10025  * stop the search as soon as we find a suitable match.
10026  * This ordering also takes care of wildcards such as '.' (meaning
10027  * "one or more of any character") and '!' (which is 'earlymatch',
10028  * meaning "zero or more of any character" but also impacts the
10029  * return value from CANMATCH and EARLYMATCH.
10030  *
10031  * The extension match rules defined in the devmeeting 2006.05.05 are
10032  * quite simple: WE SELECT THE LONGEST MATCH.
10033  * In detail, "longest" means the number of matched characters in
10034  * the extension. In case of ties (e.g. _XXX and 333) in the length
10035  * of a pattern, we give priority to entries with the smallest cardinality
10036  * (e.g, [5-9] comes before [2-8] before the former has only 5 elements,
10037  * while the latter has 7, etc.
10038  * In case of same cardinality, the first element in the range counts.
10039  * If we still have a tie, any final '!' will make this as a possibly
10040  * less specific pattern.
10041  *
10042  * EBUSY - can't lock
10043  * EEXIST - extension with the same priority exist and no replace is set
10044  *
10045  */
10046 int ast_add_extension2(struct ast_context *con,
10047    int replace, const char *extension, int priority, const char *label, const char *callerid,
10048    const char *application, void *data, void (*datad)(void *),
10049    const char *registrar)
10050 {
10051    return ast_add_extension2_lockopt(con, replace, extension, priority, label, callerid,
10052       application, data, datad, registrar, 1);
10053 }
10054 
10055 /*!
10056  * \brief Same as ast_add_extension2() but controls the context locking.
10057  *
10058  * \details
10059  * Does all the work of ast_add_extension2, but adds an arg to
10060  * determine if context locking should be done.
10061  */
10062 static int ast_add_extension2_lockopt(struct ast_context *con,
10063    int replace, const char *extension, int priority, const char *label, const char *callerid,
10064    const char *application, void *data, void (*datad)(void *),
10065    const char *registrar, int lock_context)
10066 {
10067    /*
10068     * Sort extensions (or patterns) according to the rules indicated above.
10069     * These are implemented by the function ext_cmp()).
10070     * All priorities for the same ext/pattern/cid are kept in a list,
10071     * using the 'peer' field  as a link field..
10072     */
10073    struct ast_exten *tmp, *tmp2, *e, *el = NULL;
10074    int res;
10075    int length;
10076    char *p;
10077    char expand_buf[VAR_BUF_SIZE];
10078    struct ast_exten dummy_exten = {0};
10079    char dummy_name[1024];
10080 
10081    if (ast_strlen_zero(extension)) {
10082       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",
10083             con->name);
10084       return -1;
10085    }
10086 
10087    /* If we are adding a hint evalulate in variables and global variables */
10088    if (priority == PRIORITY_HINT && strstr(application, "${") && extension[0] != '_') {
10089       struct ast_channel *c = ast_dummy_channel_alloc();
10090 
10091       if (c) {
10092          ast_channel_exten_set(c, extension);
10093          ast_channel_context_set(c, con->name);
10094       }
10095       pbx_substitute_variables_helper(c, application, expand_buf, sizeof(expand_buf));
10096       application = expand_buf;
10097       if (c) {
10098          ast_channel_unref(c);
10099       }
10100    }
10101 
10102    length = sizeof(struct ast_exten);
10103    length += strlen(extension) + 1;
10104    length += strlen(application) + 1;
10105    if (label)
10106       length += strlen(label) + 1;
10107    if (callerid)
10108       length += strlen(callerid) + 1;
10109    else
10110       length ++;  /* just the '\0' */
10111 
10112    /* Be optimistic:  Build the extension structure first */
10113    if (!(tmp = ast_calloc(1, length)))
10114       return -1;
10115 
10116    if (ast_strlen_zero(label)) /* let's turn empty labels to a null ptr */
10117       label = 0;
10118 
10119    /* use p as dst in assignments, as the fields are const char * */
10120    p = tmp->stuff;
10121    if (label) {
10122       tmp->label = p;
10123       strcpy(p, label);
10124       p += strlen(label) + 1;
10125    }
10126    tmp->exten = p;
10127    p += ext_strncpy(p, extension, strlen(extension) + 1) + 1;
10128    tmp->priority = priority;
10129    tmp->cidmatch = p;   /* but use p for assignments below */
10130 
10131    /* Blank callerid and NULL callerid are two SEPARATE things.  Do NOT confuse the two!!! */
10132    if (callerid) {
10133       p += ext_strncpy(p, callerid, strlen(callerid) + 1) + 1;
10134       tmp->matchcid = AST_EXT_MATCHCID_ON;
10135    } else {
10136       *p++ = '\0';
10137       tmp->matchcid = AST_EXT_MATCHCID_OFF;
10138    }
10139    tmp->app = p;
10140    strcpy(p, application);
10141    tmp->parent = con;
10142    tmp->data = data;
10143    tmp->datad = datad;
10144    tmp->registrar = registrar;
10145 
10146    if (lock_context) {
10147       ast_wrlock_context(con);
10148    }
10149 
10150    if (con->pattern_tree) { /* usually, on initial load, the pattern_tree isn't formed until the first find_exten; so if we are adding
10151                         an extension, and the trie exists, then we need to incrementally add this pattern to it. */
10152       ast_copy_string(dummy_name, extension, sizeof(dummy_name));
10153       dummy_exten.exten = dummy_name;
10154       dummy_exten.matchcid = AST_EXT_MATCHCID_OFF;
10155       dummy_exten.cidmatch = 0;
10156       tmp2 = ast_hashtab_lookup(con->root_table, &dummy_exten);
10157       if (!tmp2) {
10158          /* hmmm, not in the trie; */
10159          add_exten_to_pattern_tree(con, tmp, 0);
10160          ast_hashtab_insert_safe(con->root_table, tmp); /* for the sake of completeness */
10161       }
10162    }
10163    res = 0; /* some compilers will think it is uninitialized otherwise */
10164    for (e = con->root; e; el = e, e = e->next) {   /* scan the extension list */
10165       res = ext_cmp(e->exten, tmp->exten);
10166       if (res == 0) { /* extension match, now look at cidmatch */
10167          if (e->matchcid == AST_EXT_MATCHCID_OFF && tmp->matchcid == AST_EXT_MATCHCID_OFF)
10168             res = 0;
10169          else if (tmp->matchcid == AST_EXT_MATCHCID_ON && e->matchcid == AST_EXT_MATCHCID_OFF)
10170             res = 1;
10171          else if (e->matchcid == AST_EXT_MATCHCID_ON && tmp->matchcid == AST_EXT_MATCHCID_OFF)
10172             res = -1;
10173          else
10174             res = ext_cmp(e->cidmatch, tmp->cidmatch);
10175       }
10176       if (res >= 0)
10177          break;
10178    }
10179    if (e && res == 0) { /* exact match, insert in the priority chain */
10180       res = add_priority(con, tmp, el, e, replace);
10181       if (lock_context) {
10182          ast_unlock_context(con);
10183       }
10184       if (res < 0) {
10185          errno = EEXIST;   /* XXX do we care ? */
10186          return 0; /* XXX should we return -1 maybe ? */
10187       }
10188    } else {
10189       /*
10190        * not an exact match, this is the first entry with this pattern,
10191        * so insert in the main list right before 'e' (if any)
10192        */
10193       tmp->next = e;
10194       if (el) {  /* there is another exten already in this context */
10195          el->next = tmp;
10196          tmp->peer_table = ast_hashtab_create(13,
10197                      hashtab_compare_exten_numbers,
10198                      ast_hashtab_resize_java,
10199                      ast_hashtab_newsize_java,
10200                      hashtab_hash_priority,
10201                      0);
10202          tmp->peer_label_table = ast_hashtab_create(7,
10203                         hashtab_compare_exten_labels,
10204                         ast_hashtab_resize_java,
10205                         ast_hashtab_newsize_java,
10206                         hashtab_hash_labels,
10207                         0);
10208          if (label) {
10209             ast_hashtab_insert_safe(tmp->peer_label_table, tmp);
10210          }
10211          ast_hashtab_insert_safe(tmp->peer_table, tmp);
10212       } else {  /* this is the first exten in this context */
10213          if (!con->root_table)
10214             con->root_table = ast_hashtab_create(27,
10215                                        hashtab_compare_extens,
10216                                        ast_hashtab_resize_java,
10217                                        ast_hashtab_newsize_java,
10218                                        hashtab_hash_extens,
10219                                        0);
10220          con->root = tmp;
10221          con->root->peer_table = ast_hashtab_create(13,
10222                         hashtab_compare_exten_numbers,
10223                         ast_hashtab_resize_java,
10224                         ast_hashtab_newsize_java,
10225                         hashtab_hash_priority,
10226                         0);
10227          con->root->peer_label_table = ast_hashtab_create(7,
10228                            hashtab_compare_exten_labels,
10229                            ast_hashtab_resize_java,
10230                            ast_hashtab_newsize_java,
10231                            hashtab_hash_labels,
10232                            0);
10233          if (label) {
10234             ast_hashtab_insert_safe(con->root->peer_label_table, tmp);
10235          }
10236          ast_hashtab_insert_safe(con->root->peer_table, tmp);
10237 
10238       }
10239       ast_hashtab_insert_safe(con->root_table, tmp);
10240       if (lock_context) {
10241          ast_unlock_context(con);
10242       }
10243       if (tmp->priority == PRIORITY_HINT) {
10244          ast_add_hint(tmp);
10245       }
10246    }
10247    if (option_debug) {
10248       if (tmp->matchcid == AST_EXT_MATCHCID_ON) {
10249          ast_debug(1, "Added extension '%s' priority %d (CID match '%s') to %s (%p)\n",
10250                  tmp->exten, tmp->priority, tmp->cidmatch, con->name, con);
10251       } else {
10252          ast_debug(1, "Added extension '%s' priority %d to %s (%p)\n",
10253                  tmp->exten, tmp->priority, con->name, con);
10254       }
10255    }
10256 
10257    if (tmp->matchcid == AST_EXT_MATCHCID_ON) {
10258       ast_verb(3, "Added extension '%s' priority %d (CID match '%s') to %s\n",
10259              tmp->exten, tmp->priority, tmp->cidmatch, con->name);
10260    } else {
10261       ast_verb(3, "Added extension '%s' priority %d to %s\n",
10262              tmp->exten, tmp->priority, con->name);
10263    }
10264 
10265    return 0;
10266 }
10267 
10268 struct async_stat {
10269    pthread_t p;
10270    struct ast_channel *chan;
10271    char context[AST_MAX_CONTEXT];
10272    char exten[AST_MAX_EXTENSION];
10273    int priority;
10274    int timeout;
10275    char app[AST_MAX_EXTENSION];
10276    char appdata[1024];
10277    int early_media;        /* Connect the bridge if early media arrives, don't wait for answer */
10278 };
10279 
10280 static void *async_wait(void *data)
10281 {
10282    struct async_stat *as = data;
10283    struct ast_channel *chan = as->chan;
10284    int timeout = as->timeout;
10285    int res;
10286    struct ast_frame *f;
10287    struct ast_app *app;
10288    int have_early_media = 0;
10289    struct timeval start = ast_tvnow();
10290    int ms;
10291 
10292    if (chan) {
10293       struct ast_callid *callid = ast_channel_callid(chan);
10294       if (callid) {
10295          ast_callid_threadassoc_add(callid);
10296          ast_callid_unref(callid);
10297       }
10298    }
10299 
10300    while ((ms = ast_remaining_ms(start, timeout)) &&
10301          ast_channel_state(chan) != AST_STATE_UP) {
10302       res = ast_waitfor(chan, ms);
10303       if (res < 1)
10304          break;
10305 
10306       f = ast_read(chan);
10307       if (!f)
10308          break;
10309       if (f->frametype == AST_FRAME_CONTROL) {
10310          if ((f->subclass.integer == AST_CONTROL_BUSY)  ||
10311              (f->subclass.integer == AST_CONTROL_CONGESTION) ) {
10312             ast_frfree(f);
10313             break;
10314          }
10315          if (as->early_media && f->subclass.integer == AST_CONTROL_PROGRESS) {
10316             have_early_media = 1;
10317             ast_frfree(f);
10318             break;
10319          }
10320       }
10321       ast_frfree(f);
10322    }
10323    if (ast_channel_state(chan) == AST_STATE_UP || have_early_media) {
10324       if (have_early_media) {
10325          ast_debug(2, "Activating pbx since we have early media \n");
10326       }
10327       if (!ast_strlen_zero(as->app)) {
10328          app = pbx_findapp(as->app);
10329          if (app) {
10330             ast_verb(3, "Launching %s(%s) on %s\n", as->app, as->appdata, ast_channel_name(chan));
10331             pbx_exec(chan, app, as->appdata);
10332          } else
10333             ast_log(LOG_WARNING, "No such application '%s'\n", as->app);
10334       } else {
10335          if (!ast_strlen_zero(as->context))
10336             ast_channel_context_set(chan, as->context);
10337          if (!ast_strlen_zero(as->exten))
10338             ast_channel_exten_set(chan, as->exten);
10339          if (as->priority > 0)
10340             ast_channel_priority_set(chan, as->priority);
10341          /* Run the PBX */
10342          if (ast_pbx_run(chan)) {
10343             ast_log(LOG_ERROR, "Failed to start PBX on %s\n", ast_channel_name(chan));
10344          } else {
10345             /* PBX will have taken care of this */
10346             chan = NULL;
10347          }
10348       }
10349    }
10350    ast_free(as);
10351    if (chan)
10352       ast_hangup(chan);
10353    return NULL;
10354 }
10355 
10356 /*!
10357  * \brief Function to post an empty cdr after a spool call fails.
10358  * \note This function posts an empty cdr for a failed spool call
10359 */
10360 static int ast_pbx_outgoing_cdr_failed(void)
10361 {
10362    /* allocate a channel */
10363    struct ast_channel *chan = ast_dummy_channel_alloc();
10364 
10365    if (!chan)
10366       return -1;  /* failure */
10367 
10368    ast_channel_cdr_set(chan, ast_cdr_alloc());
10369    if (!ast_channel_cdr(chan)) {
10370       /* allocation of the cdr failed */
10371       chan = ast_channel_unref(chan);   /* free the channel */
10372       return -1;                /* return failure */
10373    }
10374 
10375    /* allocation of the cdr was successful */
10376    ast_cdr_init(ast_channel_cdr(chan), chan);  /* initialize our channel's cdr */
10377    ast_cdr_start(ast_channel_cdr(chan));       /* record the start and stop time */
10378    ast_cdr_end(ast_channel_cdr(chan));
10379    ast_cdr_failed(ast_channel_cdr(chan));      /* set the status to failed */
10380    ast_cdr_detach(ast_channel_cdr(chan));      /* post and free the record */
10381    ast_channel_cdr_set(chan, NULL);
10382    chan = ast_channel_unref(chan);         /* free the channel */
10383 
10384    return 0;  /* success */
10385 }
10386 
10387 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)
10388 {
10389    struct ast_channel *chan;
10390    struct async_stat *as;
10391    struct ast_callid *callid;
10392    int callid_created = 0;
10393    int res = -1, cdr_res = -1;
10394    struct outgoing_helper oh;
10395 
10396    oh.connect_on_early_media = early_media;
10397 
10398    callid_created = ast_callid_threadstorage_auto(&callid);
10399 
10400    if (synchronous) {
10401       oh.context = context;
10402       oh.exten = exten;
10403       oh.priority = priority;
10404       oh.cid_num = cid_num;
10405       oh.cid_name = cid_name;
10406       oh.account = account;
10407       oh.vars = vars;
10408       oh.parent_channel = NULL;
10409 
10410       chan = __ast_request_and_dial(type, cap, NULL, addr, timeout, reason, cid_num, cid_name, &oh);
10411       if (channel) {
10412          *channel = chan;
10413          if (chan)
10414             ast_channel_lock(chan);
10415       }
10416       if (chan) {
10417          /* Bind the callid to the channel if it doesn't already have one on creation */
10418          struct ast_callid *channel_callid = ast_channel_callid(chan);
10419          if (channel_callid) {
10420             ast_callid_unref(channel_callid);
10421          } else {
10422             if (callid) {
10423                ast_channel_callid_set(chan, callid);
10424             }
10425          }
10426 
10427          if (ast_channel_state(chan) == AST_STATE_UP || (early_media && *reason == AST_CONTROL_PROGRESS)) {
10428                res = 0;
10429             ast_verb(4, "Channel %s %s\n", ast_channel_name(chan), ast_channel_state(chan) == AST_STATE_UP ? "was answered" : "got early media");
10430 
10431             if (synchronous > 1) {
10432                if (channel)
10433                   ast_channel_unlock(chan);
10434                if (ast_pbx_run(chan)) {
10435                   ast_log(LOG_ERROR, "Unable to run PBX on %s\n", ast_channel_name(chan));
10436                   if (channel)
10437                      *channel = NULL;
10438                   ast_hangup(chan);
10439                   chan = NULL;
10440                   res = -1;
10441                }
10442             } else {
10443                if (ast_pbx_start(chan)) {
10444                   ast_log(LOG_ERROR, "Unable to start PBX on %s\n", ast_channel_name(chan));
10445                   if (channel) {
10446                      *channel = NULL;
10447                      ast_channel_unlock(chan);
10448                   }
10449                   ast_hangup(chan);
10450                   res = -1;
10451                }
10452                chan = NULL;
10453             }
10454          } else {
10455             ast_verb(4, "Channel %s was never answered.\n", ast_channel_name(chan));
10456 
10457             if (ast_channel_cdr(chan)) { /* update the cdr */
10458                /* here we update the status of the call, which sould be busy.
10459                 * if that fails then we set the status to failed */
10460                if (ast_cdr_disposition(ast_channel_cdr(chan), ast_channel_hangupcause(chan)))
10461                   ast_cdr_failed(ast_channel_cdr(chan));
10462             }
10463 
10464             if (channel) {
10465                *channel = NULL;
10466                ast_channel_unlock(chan);
10467             }
10468             ast_hangup(chan);
10469             chan = NULL;
10470          }
10471       }
10472 
10473       if (res < 0) { /* the call failed for some reason */
10474          if (*reason == 0) { /* if the call failed (not busy or no answer)
10475                         * update the cdr with the failed message */
10476             cdr_res = ast_pbx_outgoing_cdr_failed();
10477             if (cdr_res != 0) {
10478                res = cdr_res;
10479                goto outgoing_exten_cleanup;
10480             }
10481          }
10482 
10483          /* create a fake channel and execute the "failed" extension (if it exists) within the requested context */
10484          /* check if "failed" exists */
10485          if (ast_exists_extension(chan, context, "failed", 1, NULL)) {
10486             chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", NULL, 0, "OutgoingSpoolFailed");
10487             if (chan) {
10488                char failed_reason[4] = "";
10489                if (!ast_strlen_zero(context))
10490                   ast_channel_context_set(chan, context);
10491                set_ext_pri(chan, "failed", 1);
10492                ast_set_variables(chan, vars);
10493                snprintf(failed_reason, sizeof(failed_reason), "%d", *reason);
10494                pbx_builtin_setvar_helper(chan, "REASON", failed_reason);
10495                if (account)
10496                   ast_cdr_setaccount(chan, account);
10497                if (ast_pbx_run(chan)) {
10498                   ast_log(LOG_ERROR, "Unable to run PBX on %s\n", ast_channel_name(chan));
10499                   ast_hangup(chan);
10500                }
10501                chan = NULL;
10502             }
10503          }
10504       }
10505    } else {
10506       struct ast_callid *channel_callid;
10507       if (!(as = ast_calloc(1, sizeof(*as)))) {
10508          res = -1;
10509          goto outgoing_exten_cleanup;
10510       }
10511       chan = ast_request_and_dial(type, cap, NULL, addr, timeout, reason, cid_num, cid_name);
10512       if (channel) {
10513          *channel = chan;
10514          if (chan)
10515             ast_channel_lock(chan);
10516       }
10517       if (!chan) {
10518          ast_free(as);
10519          res = -1;
10520          goto outgoing_exten_cleanup;
10521       }
10522 
10523       /* Bind the newly created callid to the channel if it doesn't already have one on creation. */
10524       channel_callid = ast_channel_callid(chan);
10525       if (channel_callid) {
10526          ast_callid_unref(channel_callid);
10527       } else {
10528          if (callid) {
10529             ast_channel_callid_set(chan, callid);
10530          }
10531       }
10532 
10533       as->chan = chan;
10534       ast_copy_string(as->context, context, sizeof(as->context));
10535       set_ext_pri(as->chan,  exten, priority);
10536       as->timeout = timeout;
10537       ast_set_variables(chan, vars);
10538       if (account)
10539          ast_cdr_setaccount(chan, account);
10540       if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) {
10541          ast_log(LOG_WARNING, "Failed to start async wait\n");
10542          ast_free(as);
10543          if (channel) {
10544             *channel = NULL;
10545             ast_channel_unlock(chan);
10546          }
10547          ast_hangup(chan);
10548          res = -1;
10549          goto outgoing_exten_cleanup;
10550       }
10551       res = 0;
10552    }
10553 
10554 outgoing_exten_cleanup:
10555    ast_callid_threadstorage_auto_clean(callid, callid_created);
10556    ast_variables_destroy(vars);
10557    return res;
10558 }
10559 
10560 struct app_tmp {
10561    struct ast_channel *chan;
10562    pthread_t t;
10563    AST_DECLARE_STRING_FIELDS (
10564       AST_STRING_FIELD(app);
10565       AST_STRING_FIELD(data);
10566    );
10567 };
10568 
10569 /*! \brief run the application and free the descriptor once done */
10570 static void *ast_pbx_run_app(void *data)
10571 {
10572    struct app_tmp *tmp = data;
10573    struct ast_app *app;
10574    app = pbx_findapp(tmp->app);
10575    if (app) {
10576       ast_verb(4, "Launching %s(%s) on %s\n", tmp->app, tmp->data, ast_channel_name(tmp->chan));
10577       pbx_exec(tmp->chan, app, tmp->data);
10578    } else
10579       ast_log(LOG_WARNING, "No such application '%s'\n", tmp->app);
10580    ast_hangup(tmp->chan);
10581    ast_string_field_free_memory(tmp);
10582    ast_free(tmp);
10583    return NULL;
10584 }
10585 
10586 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)
10587 {
10588    struct ast_channel *chan;
10589    struct app_tmp *tmp;
10590    struct ast_callid *callid;
10591    int callid_created;
10592    int res = -1, cdr_res = -1;
10593    struct outgoing_helper oh;
10594 
10595    /* Start by checking for a callid in threadstorage, and if none is found, bind one. */
10596    callid_created = ast_callid_threadstorage_auto(&callid);
10597 
10598    memset(&oh, 0, sizeof(oh));
10599    oh.vars = vars;
10600    oh.account = account;
10601 
10602    if (locked_channel)
10603       *locked_channel = NULL;
10604    if (ast_strlen_zero(app)) {
10605       res = -1;
10606       goto outgoing_app_cleanup;
10607    }
10608    if (synchronous) {
10609       chan = __ast_request_and_dial(type, cap, NULL, addr, timeout, reason, cid_num, cid_name, &oh);
10610       if (chan) {
10611          /* Bind the newly created callid to the channel if it doesn't already have one on creation */
10612          struct ast_callid *channel_callid = ast_channel_callid(chan);
10613          if (channel_callid) {
10614             ast_callid_unref(channel_callid);
10615          } else {
10616             if (callid) {
10617                ast_channel_callid_set(chan, callid);
10618             }
10619          }
10620 
10621          ast_set_variables(chan, vars);
10622          if (account)
10623             ast_cdr_setaccount(chan, account);
10624          if (ast_channel_state(chan) == AST_STATE_UP) {
10625             res = 0;
10626             ast_verb(4, "Channel %s was answered.\n", ast_channel_name(chan));
10627             tmp = ast_calloc(1, sizeof(*tmp));
10628             if (!tmp || ast_string_field_init(tmp, 252)) {
10629                if (tmp) {
10630                   ast_free(tmp);
10631                }
10632                res = -1;
10633             } else {
10634                ast_string_field_set(tmp, app, app);
10635                ast_string_field_set(tmp, data, appdata);
10636                tmp->chan = chan;
10637                if (synchronous > 1) {
10638                   if (locked_channel)
10639                      ast_channel_unlock(chan);
10640                   ast_pbx_run_app(tmp);
10641                } else {
10642                   if (locked_channel)
10643                      ast_channel_lock(chan);
10644                   if (ast_pthread_create_detached(&tmp->t, NULL, ast_pbx_run_app, tmp)) {
10645                      ast_log(LOG_WARNING, "Unable to spawn execute thread on %s: %s\n", ast_channel_name(chan), strerror(errno));
10646                      ast_string_field_free_memory(tmp);
10647                      ast_free(tmp);
10648                      if (locked_channel)
10649                         ast_channel_unlock(chan);
10650                      ast_hangup(chan);
10651                      res = -1;
10652                   } else {
10653                      if (locked_channel)
10654                         *locked_channel = chan;
10655                   }
10656                }
10657             }
10658          } else {
10659             ast_verb(4, "Channel %s was never answered.\n", ast_channel_name(chan));
10660             if (ast_channel_cdr(chan)) { /* update the cdr */
10661                /* here we update the status of the call, which sould be busy.
10662                 * if that fails then we set the status to failed */
10663                if (ast_cdr_disposition(ast_channel_cdr(chan), ast_channel_hangupcause(chan)))
10664                   ast_cdr_failed(ast_channel_cdr(chan));
10665             }
10666             ast_hangup(chan);
10667          }
10668       }
10669 
10670       if (res < 0) { /* the call failed for some reason */
10671          if (*reason == 0) { /* if the call failed (not busy or no answer)
10672                         * update the cdr with the failed message */
10673             cdr_res = ast_pbx_outgoing_cdr_failed();
10674             if (cdr_res != 0) {
10675                res = cdr_res;
10676                goto outgoing_app_cleanup;
10677             }
10678          }
10679       }
10680 
10681    } else {
10682       struct async_stat *as;
10683       struct ast_callid *channel_callid;
10684       if (!(as = ast_calloc(1, sizeof(*as)))) {
10685          res = -1;
10686          goto outgoing_app_cleanup;
10687       }
10688       chan = __ast_request_and_dial(type, cap, NULL, addr, timeout, reason, cid_num, cid_name, &oh);
10689       if (!chan) {
10690          ast_free(as);
10691          res = -1;
10692          goto outgoing_app_cleanup;
10693       }
10694 
10695       /* Bind the newly created callid to the channel if it doesn't already have one on creation. */
10696       channel_callid = ast_channel_callid(chan);
10697       if (channel_callid) {
10698          ast_callid_unref(channel_callid);
10699       } else {
10700          if (callid) {
10701             ast_channel_callid_set(chan, callid);
10702          }
10703       }
10704 
10705       as->chan = chan;
10706       ast_copy_string(as->app, app, sizeof(as->app));
10707       if (appdata)
10708          ast_copy_string(as->appdata,  appdata, sizeof(as->appdata));
10709       as->timeout = timeout;
10710       ast_set_variables(chan, vars);
10711       if (account)
10712          ast_cdr_setaccount(chan, account);
10713       /* Start a new thread, and get something handling this channel. */
10714       if (locked_channel)
10715          ast_channel_lock(chan);
10716       if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) {
10717          ast_log(LOG_WARNING, "Failed to start async wait\n");
10718          ast_free(as);
10719          if (locked_channel)
10720             ast_channel_unlock(chan);
10721          ast_hangup(chan);
10722          res = -1;
10723          goto outgoing_app_cleanup;
10724       } else {
10725          if (locked_channel)
10726             *locked_channel = chan;
10727       }
10728       res = 0;
10729    }
10730 
10731 outgoing_app_cleanup:
10732    ast_callid_threadstorage_auto_clean(callid, callid_created);
10733    ast_variables_destroy(vars);
10734    return res;
10735 }
10736 
10737 /* this is the guts of destroying a context --
10738    freeing up the structure, traversing and destroying the
10739    extensions, switches, ignorepats, includes, etc. etc. */
10740 
10741 static void __ast_internal_context_destroy( struct ast_context *con)
10742 {
10743    struct ast_include *tmpi;
10744    struct ast_sw *sw;
10745    struct ast_exten *e, *el, *en;
10746    struct ast_ignorepat *ipi;
10747    struct ast_context *tmp = con;
10748 
10749    for (tmpi = tmp->includes; tmpi; ) { /* Free includes */
10750       struct ast_include *tmpil = tmpi;
10751       tmpi = tmpi->next;
10752       ast_free(tmpil);
10753    }
10754    for (ipi = tmp->ignorepats; ipi; ) { /* Free ignorepats */
10755       struct ast_ignorepat *ipl = ipi;
10756       ipi = ipi->next;
10757       ast_free(ipl);
10758    }
10759    if (tmp->registrar)
10760       ast_free(tmp->registrar);
10761 
10762    /* destroy the hash tabs */
10763    if (tmp->root_table) {
10764       ast_hashtab_destroy(tmp->root_table, 0);
10765    }
10766    /* and destroy the pattern tree */
10767    if (tmp->pattern_tree)
10768       destroy_pattern_tree(tmp->pattern_tree);
10769 
10770    while ((sw = AST_LIST_REMOVE_HEAD(&tmp->alts, list)))
10771       ast_free(sw);
10772    for (e = tmp->root; e;) {
10773       for (en = e->peer; en;) {
10774          el = en;
10775          en = en->peer;
10776          destroy_exten(el);
10777       }
10778       el = e;
10779       e = e->next;
10780       destroy_exten(el);
10781    }
10782    tmp->root = NULL;
10783    ast_rwlock_destroy(&tmp->lock);
10784    ast_mutex_destroy(&tmp->macrolock);
10785    ast_free(tmp);
10786 }
10787 
10788 
10789 void __ast_context_destroy(struct ast_context *list, struct ast_hashtab *contexttab, struct ast_context *con, const char *registrar)
10790 {
10791    struct ast_context *tmp, *tmpl=NULL;
10792    struct ast_exten *exten_item, *prio_item;
10793 
10794    for (tmp = list; tmp; ) {
10795       struct ast_context *next = NULL; /* next starting point */
10796          /* The following code used to skip forward to the next
10797             context with matching registrar, but this didn't
10798             make sense; individual priorities registrar'd to
10799             the matching registrar could occur in any context! */
10800       ast_debug(1, "Investigate ctx %s %s\n", tmp->name, tmp->registrar);
10801       if (con) {
10802          for (; tmp; tmpl = tmp, tmp = tmp->next) { /* skip to the matching context */
10803             ast_debug(1, "check ctx %s %s\n", tmp->name, tmp->registrar);
10804             if ( !strcasecmp(tmp->name, con->name) ) {
10805                break;   /* found it */
10806             }
10807          }
10808       }
10809 
10810       if (!tmp)   /* not found, we are done */
10811          break;
10812       ast_wrlock_context(tmp);
10813 
10814       if (registrar) {
10815          /* then search thru and remove any extens that match registrar. */
10816          struct ast_hashtab_iter *exten_iter;
10817          struct ast_hashtab_iter *prio_iter;
10818          struct ast_ignorepat *ip, *ipl = NULL, *ipn = NULL;
10819          struct ast_include *i, *pi = NULL, *ni = NULL;
10820          struct ast_sw *sw = NULL;
10821 
10822          /* remove any ignorepats whose registrar matches */
10823          for (ip = tmp->ignorepats; ip; ip = ipn) {
10824             ipn = ip->next;
10825             if (!strcmp(ip->registrar, registrar)) {
10826                if (ipl) {
10827                   ipl->next = ip->next;
10828                   ast_free(ip);
10829                   continue; /* don't change ipl */
10830                } else {
10831                   tmp->ignorepats = ip->next;
10832                   ast_free(ip);
10833                   continue; /* don't change ipl */
10834                }
10835             }
10836             ipl = ip;
10837          }
10838          /* remove any includes whose registrar matches */
10839          for (i = tmp->includes; i; i = ni) {
10840             ni = i->next;
10841             if (strcmp(i->registrar, registrar) == 0) {
10842                /* remove from list */
10843                if (pi) {
10844                   pi->next = i->next;
10845                   /* free include */
10846                   ast_free(i);
10847                   continue; /* don't change pi */
10848                } else {
10849                   tmp->includes = i->next;
10850                   /* free include */
10851                   ast_free(i);
10852                   continue; /* don't change pi */
10853                }
10854             }
10855             pi = i;
10856          }
10857          /* remove any switches whose registrar matches */
10858          AST_LIST_TRAVERSE_SAFE_BEGIN(&tmp->alts, sw, list) {
10859             if (strcmp(sw->registrar,registrar) == 0) {
10860                AST_LIST_REMOVE_CURRENT(list);
10861                ast_free(sw);
10862             }
10863          }
10864          AST_LIST_TRAVERSE_SAFE_END;
10865 
10866          if (tmp->root_table) { /* it is entirely possible that the context is EMPTY */
10867             exten_iter = ast_hashtab_start_traversal(tmp->root_table);
10868             while ((exten_item=ast_hashtab_next(exten_iter))) {
10869                int end_traversal = 1;
10870                prio_iter = ast_hashtab_start_traversal(exten_item->peer_table);
10871                while ((prio_item=ast_hashtab_next(prio_iter))) {
10872                   char extension[AST_MAX_EXTENSION];
10873                   char cidmatch[AST_MAX_EXTENSION];
10874                   if (!prio_item->registrar || strcmp(prio_item->registrar, registrar) != 0) {
10875                      continue;
10876                   }
10877                   ast_verb(3, "Remove %s/%s/%d, registrar=%s; con=%s(%p); con->root=%p\n",
10878                          tmp->name, prio_item->exten, prio_item->priority, registrar, con? con->name : "<nil>", con, con? con->root_table: NULL);
10879                   ast_copy_string(extension, prio_item->exten, sizeof(extension));
10880                   if (prio_item->cidmatch) {
10881                      ast_copy_string(cidmatch, prio_item->cidmatch, sizeof(cidmatch));
10882                   }
10883                   end_traversal &= ast_context_remove_extension_callerid2(tmp, extension, prio_item->priority, cidmatch, prio_item->matchcid, NULL, 1);
10884                }
10885                /* Explanation:
10886                 * ast_context_remove_extension_callerid2 will destroy the extension that it comes across. This
10887                 * destruction includes destroying the exten's peer_table, which we are currently traversing. If
10888                 * ast_context_remove_extension_callerid2 ever should return '0' then this means we have destroyed
10889                 * the hashtable which we are traversing, and thus calling ast_hashtab_end_traversal will result
10890                 * in reading invalid memory. Thus, if we detect that we destroyed the hashtable, then we will simply
10891                 * free the iterator
10892                 */
10893                if (end_traversal) {
10894                   ast_hashtab_end_traversal(prio_iter);
10895                } else {
10896                   ast_free(prio_iter);
10897                }
10898             }
10899             ast_hashtab_end_traversal(exten_iter);
10900          }
10901 
10902          /* delete the context if it's registrar matches, is empty, has refcount of 1, */
10903          /* it's not empty, if it has includes, ignorepats, or switches that are registered from
10904             another registrar. It's not empty if there are any extensions */
10905          if (strcmp(tmp->registrar, registrar) == 0 && tmp->refcount < 2 && !tmp->root && !tmp->ignorepats && !tmp->includes && AST_LIST_EMPTY(&tmp->alts)) {
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          } else {
10919             ast_debug(1,"Couldn't delete ctx %s/%s; refc=%d; tmp.root=%p\n", tmp->name, tmp->registrar,
10920                     tmp->refcount, tmp->root);
10921             ast_unlock_context(tmp);
10922             next = tmp->next;
10923             tmpl = tmp;
10924          }
10925       } else if (con) {
10926          ast_verb(3, "Deleting context %s registrar=%s\n", tmp->name, tmp->registrar);
10927          ast_debug(1, "delete ctx %s %s\n", tmp->name, tmp->registrar);
10928          ast_hashtab_remove_this_object(contexttab, tmp);
10929 
10930          next = tmp->next;
10931          if (tmpl)
10932             tmpl->next = next;
10933          else
10934             contexts = next;
10935          /* Okay, now we're safe to let it go -- in a sense, we were
10936             ready to let it go as soon as we locked it. */
10937          ast_unlock_context(tmp);
10938          __ast_internal_context_destroy(tmp);
10939       }
10940 
10941       /* if we have a specific match, we are done, otherwise continue */
10942       tmp = con ? NULL : next;
10943    }
10944 }
10945 
10946 void ast_context_destroy(struct ast_context *con, const char *registrar)
10947 {
10948    ast_wrlock_contexts();
10949    __ast_context_destroy(contexts, contexts_table, con,registrar);
10950    ast_unlock_contexts();
10951 }
10952 
10953 static void wait_for_hangup(struct ast_channel *chan, const void *data)
10954 {
10955    int res;
10956    struct ast_frame *f;
10957    double waitsec;
10958    int waittime;
10959 
10960    if (ast_strlen_zero(data) || (sscanf(data, "%30lg", &waitsec) != 1) || (waitsec < 0))
10961       waitsec = -1;
10962    if (waitsec > -1) {
10963       waittime = waitsec * 1000.0;
10964       ast_safe_sleep(chan, waittime);
10965    } else do {
10966       res = ast_waitfor(chan, -1);
10967       if (res < 0)
10968          return;
10969       f = ast_read(chan);
10970       if (f)
10971          ast_frfree(f);
10972    } while(f);
10973 }
10974 
10975 /*!
10976  * \ingroup applications
10977  */
10978 static int pbx_builtin_proceeding(struct ast_channel *chan, const char *data)
10979 {
10980    ast_indicate(chan, AST_CONTROL_PROCEEDING);
10981    return 0;
10982 }
10983 
10984 /*!
10985  * \ingroup applications
10986  */
10987 static int pbx_builtin_progress(struct ast_channel *chan, const char *data)
10988 {
10989    ast_indicate(chan, AST_CONTROL_PROGRESS);
10990    return 0;
10991 }
10992 
10993 /*!
10994  * \ingroup applications
10995  */
10996 static int pbx_builtin_ringing(struct ast_channel *chan, const char *data)
10997 {
10998    ast_indicate(chan, AST_CONTROL_RINGING);
10999    return 0;
11000 }
11001 
11002 /*!
11003  * \ingroup applications
11004  */
11005 static int pbx_builtin_busy(struct ast_channel *chan, const char *data)
11006 {
11007    ast_indicate(chan, AST_CONTROL_BUSY);
11008    /* Don't change state of an UP channel, just indicate
11009       busy in audio */
11010    if (ast_channel_state(chan) != AST_STATE_UP) {
11011       ast_setstate(chan, AST_STATE_BUSY);
11012       ast_cdr_busy(ast_channel_cdr(chan));
11013    }
11014    wait_for_hangup(chan, data);
11015    return -1;
11016 }
11017 
11018 /*!
11019  * \ingroup applications
11020  */
11021 static int pbx_builtin_congestion(struct ast_channel *chan, const char *data)
11022 {
11023    ast_indicate(chan, AST_CONTROL_CONGESTION);
11024    /* Don't change state of an UP channel, just indicate
11025       congestion in audio */
11026    if (ast_channel_state(chan) != AST_STATE_UP) {
11027       ast_setstate(chan, AST_STATE_BUSY);
11028       ast_cdr_congestion(ast_channel_cdr(chan));
11029    }
11030    wait_for_hangup(chan, data);
11031    return -1;
11032 }
11033 
11034 /*!
11035  * \ingroup applications
11036  */
11037 static int pbx_builtin_answer(struct ast_channel *chan, const char *data)
11038 {
11039    int delay = 0;
11040    int answer_cdr = 1;
11041    char *parse;
11042    AST_DECLARE_APP_ARGS(args,
11043       AST_APP_ARG(delay);
11044       AST_APP_ARG(answer_cdr);
11045    );
11046 
11047    if (ast_strlen_zero(data)) {
11048       return __ast_answer(chan, 0, 1);
11049    }
11050 
11051    parse = ast_strdupa(data);
11052 
11053    AST_STANDARD_APP_ARGS(args, parse);
11054 
11055    if (!ast_strlen_zero(args.delay) && (ast_channel_state(chan) != AST_STATE_UP))
11056       delay = atoi(data);
11057 
11058    if (delay < 0) {
11059       delay = 0;
11060    }
11061 
11062    if (!ast_strlen_zero(args.answer_cdr) && !strcasecmp(args.answer_cdr, "nocdr")) {
11063       answer_cdr = 0;
11064    }
11065 
11066    return __ast_answer(chan, delay, answer_cdr);
11067 }
11068 
11069 static int pbx_builtin_incomplete(struct ast_channel *chan, const char *data)
11070 {
11071    const char *options = data;
11072    int answer = 1;
11073 
11074    /* Some channels can receive DTMF in unanswered state; some cannot */
11075    if (!ast_strlen_zero(options) && strchr(options, 'n')) {
11076       answer = 0;
11077    }
11078 
11079    /* If the channel is hungup, stop waiting */
11080    if (ast_check_hangup(chan)) {
11081       return -1;
11082    } else if (ast_channel_state(chan) != AST_STATE_UP && answer) {
11083       __ast_answer(chan, 0, 1);
11084    }
11085 
11086    ast_indicate(chan, AST_CONTROL_INCOMPLETE);
11087 
11088    return AST_PBX_INCOMPLETE;
11089 }
11090 
11091 AST_APP_OPTIONS(resetcdr_opts, {
11092    AST_APP_OPTION('w', AST_CDR_FLAG_POSTED),
11093    AST_APP_OPTION('a', AST_CDR_FLAG_LOCKED),
11094    AST_APP_OPTION('v', AST_CDR_FLAG_KEEP_VARS),
11095    AST_APP_OPTION('e', AST_CDR_FLAG_POST_ENABLE),
11096 });
11097 
11098 /*!
11099  * \ingroup applications
11100  */
11101 static int pbx_builtin_resetcdr(struct ast_channel *chan, const char *data)
11102 {
11103    char *args;
11104    struct ast_flags flags = { 0 };
11105 
11106    if (!ast_strlen_zero(data)) {
11107       args = ast_strdupa(data);
11108       ast_app_parse_options(resetcdr_opts, &flags, NULL, args);
11109    }
11110 
11111    ast_cdr_reset(ast_channel_cdr(chan), &flags);
11112 
11113    return 0;
11114 }
11115 
11116 /*!
11117  * \ingroup applications
11118  */
11119 static int pbx_builtin_setamaflags(struct ast_channel *chan, const char *data)
11120 {
11121    /* Copy the AMA Flags as specified */
11122    ast_channel_lock(chan);
11123    ast_cdr_setamaflags(chan, data ? data : "");
11124    ast_channel_unlock(chan);
11125    return 0;
11126 }
11127 
11128 /*!
11129  * \ingroup applications
11130  */
11131 static int pbx_builtin_hangup(struct ast_channel *chan, const char *data)
11132 {
11133    int cause;
11134 
11135    ast_set_hangupsource(chan, "dialplan/builtin", 0);
11136 
11137    if (!ast_strlen_zero(data)) {
11138       cause = ast_str2cause(data);
11139       if (cause <= 0) {
11140          if (sscanf(data, "%30d", &cause) != 1 || cause <= 0) {
11141             ast_log(LOG_WARNING, "Invalid cause given to Hangup(): \"%s\"\n", data);
11142             cause = 0;
11143          }
11144       }
11145    } else {
11146       cause = 0;
11147    }
11148 
11149    ast_channel_lock(chan);
11150    if (cause <= 0) {
11151       cause = ast_channel_hangupcause(chan);
11152       if (cause <= 0) {
11153          cause = AST_CAUSE_NORMAL_CLEARING;
11154       }
11155    }
11156    ast_channel_hangupcause_set(chan, cause);
11157    ast_softhangup_nolock(chan, AST_SOFTHANGUP_EXPLICIT);
11158    ast_channel_unlock(chan);
11159 
11160    return -1;
11161 }
11162 
11163 /*!
11164  * \ingroup functions
11165  */
11166 static int testtime_write(struct ast_channel *chan, const char *cmd, char *var, const char *value)
11167 {
11168    struct ast_tm tm;
11169    struct timeval tv;
11170    char *remainder, result[30], timezone[80];
11171 
11172    /* Turn off testing? */
11173    if (!pbx_checkcondition(value)) {
11174       pbx_builtin_setvar_helper(chan, "TESTTIME", NULL);
11175       return 0;
11176    }
11177 
11178    /* Parse specified time */
11179    if (!(remainder = ast_strptime(value, "%Y/%m/%d %H:%M:%S", &tm))) {
11180       return -1;
11181    }
11182    sscanf(remainder, "%79s", timezone);
11183    tv = ast_mktime(&tm, S_OR(timezone, NULL));
11184 
11185    snprintf(result, sizeof(result), "%ld", (long) tv.tv_sec);
11186    pbx_builtin_setvar_helper(chan, "__TESTTIME", result);
11187    return 0;
11188 }
11189 
11190 static struct ast_custom_function testtime_function = {
11191    .name = "TESTTIME",
11192    .write = testtime_write,
11193 };
11194 
11195 /*!
11196  * \ingroup applications
11197  */
11198 static int pbx_builtin_gotoiftime(struct ast_channel *chan, const char *data)
11199 {
11200    char *s, *ts, *branch1, *branch2, *branch;
11201    struct ast_timing timing;
11202    const char *ctime;
11203    struct timeval tv = ast_tvnow();
11204    long timesecs;
11205 
11206    if (!chan) {
11207       ast_log(LOG_WARNING, "GotoIfTime requires a channel on which to operate\n");
11208       return -1;
11209    }
11210 
11211    if (ast_strlen_zero(data)) {
11212       ast_log(LOG_WARNING, "GotoIfTime requires an argument:\n  <time range>,<days of week>,<days of month>,<months>[,<timezone>]?'labeliftrue':'labeliffalse'\n");
11213       return -1;
11214    }
11215 
11216    ts = s = ast_strdupa(data);
11217 
11218    ast_channel_lock(chan);
11219    if ((ctime = pbx_builtin_getvar_helper(chan, "TESTTIME")) && sscanf(ctime, "%ld", &timesecs) == 1) {
11220       tv.tv_sec = timesecs;
11221    } else if (ctime) {
11222       ast_log(LOG_WARNING, "Using current time to evaluate\n");
11223       /* Reset when unparseable */
11224       pbx_builtin_setvar_helper(chan, "TESTTIME", NULL);
11225    }
11226    ast_channel_unlock(chan);
11227 
11228    /* Separate the Goto path */
11229    strsep(&ts, "?");
11230    branch1 = strsep(&ts,":");
11231    branch2 = strsep(&ts,"");
11232 
11233    /* struct ast_include include contained garbage here, fixed by zeroing it on get_timerange */
11234    if (ast_build_timing(&timing, s) && ast_check_timing2(&timing, tv)) {
11235       branch = branch1;
11236    } else {
11237       branch = branch2;
11238    }
11239    ast_destroy_timing(&timing);
11240 
11241    if (ast_strlen_zero(branch)) {
11242       ast_debug(1, "Not taking any branch\n");
11243       return 0;
11244    }
11245 
11246    return pbx_builtin_goto(chan, branch);
11247 }
11248 
11249 /*!
11250  * \ingroup applications
11251  */
11252 static int pbx_builtin_execiftime(struct ast_channel *chan, const char *data)
11253 {
11254    char *s, *appname;
11255    struct ast_timing timing;
11256    struct ast_app *app;
11257    static const char * const usage = "ExecIfTime requires an argument:\n  <time range>,<days of week>,<days of month>,<months>[,<timezone>]?<appname>[(<appargs>)]";
11258 
11259    if (ast_strlen_zero(data)) {
11260       ast_log(LOG_WARNING, "%s\n", usage);
11261       return -1;
11262    }
11263 
11264    appname = ast_strdupa(data);
11265 
11266    s = strsep(&appname, "?"); /* Separate the timerange and application name/data */
11267    if (!appname) {   /* missing application */
11268       ast_log(LOG_WARNING, "%s\n", usage);
11269       return -1;
11270    }
11271 
11272    if (!ast_build_timing(&timing, s)) {
11273       ast_log(LOG_WARNING, "Invalid Time Spec: %s\nCorrect usage: %s\n", s, usage);
11274       ast_destroy_timing(&timing);
11275       return -1;
11276    }
11277 
11278    if (!ast_check_timing(&timing))  { /* outside the valid time window, just return */
11279       ast_destroy_timing(&timing);
11280       return 0;
11281    }
11282    ast_destroy_timing(&timing);
11283 
11284    /* now split appname(appargs) */
11285    if ((s = strchr(appname, '('))) {
11286       char *e;
11287       *s++ = '\0';
11288       if ((e = strrchr(s, ')')))
11289          *e = '\0';
11290       else
11291          ast_log(LOG_WARNING, "Failed to find closing parenthesis\n");
11292    }
11293 
11294 
11295    if ((app = pbx_findapp(appname))) {
11296       return pbx_exec(chan, app, S_OR(s, ""));
11297    } else {
11298       ast_log(LOG_WARNING, "Cannot locate application %s\n", appname);
11299       return -1;
11300    }
11301 }
11302 
11303 /*!
11304  * \ingroup applications
11305  */
11306 static int pbx_builtin_wait(struct ast_channel *chan, const char *data)
11307 {
11308    int ms;
11309 
11310    /* Wait for "n" seconds */
11311    if (!ast_app_parse_timelen(data, &ms, TIMELEN_SECONDS) && ms > 0) {
11312       return ast_safe_sleep(chan, ms);
11313    }
11314    return 0;
11315 }
11316 
11317 /*!
11318  * \ingroup applications
11319  */
11320 static int pbx_builtin_waitexten(struct ast_channel *chan, const char *data)
11321 {
11322    int ms, res;
11323    struct ast_flags flags = {0};
11324    char *opts[1] = { NULL };
11325    char *parse;
11326    AST_DECLARE_APP_ARGS(args,
11327       AST_APP_ARG(timeout);
11328       AST_APP_ARG(options);
11329    );
11330 
11331    if (!ast_strlen_zero(data)) {
11332       parse = ast_strdupa(data);
11333       AST_STANDARD_APP_ARGS(args, parse);
11334    } else
11335       memset(&args, 0, sizeof(args));
11336 
11337    if (args.options)
11338       ast_app_parse_options(waitexten_opts, &flags, opts, args.options);
11339 
11340    if (ast_test_flag(&flags, WAITEXTEN_MOH) && !opts[0] ) {
11341       ast_log(LOG_WARNING, "The 'm' option has been specified for WaitExten without a class.\n");
11342    } else if (ast_test_flag(&flags, WAITEXTEN_MOH)) {
11343       ast_indicate_data(chan, AST_CONTROL_HOLD, S_OR(opts[0], NULL),
11344          !ast_strlen_zero(opts[0]) ? strlen(opts[0]) + 1 : 0);
11345    } else if (ast_test_flag(&flags, WAITEXTEN_DIALTONE)) {
11346       struct ast_tone_zone_sound *ts = ast_get_indication_tone(ast_channel_zone(chan), "dial");
11347       if (ts) {
11348          ast_playtones_start(chan, 0, ts->data, 0);
11349          ts = ast_tone_zone_sound_unref(ts);
11350       } else {
11351          ast_tonepair_start(chan, 350, 440, 0, 0);
11352       }
11353    }
11354    /* Wait for "n" seconds */
11355    if (!ast_app_parse_timelen(args.timeout, &ms, TIMELEN_SECONDS) && ms > 0) {
11356       /* Yay! */
11357    } else if (ast_channel_pbx(chan)) {
11358       ms = ast_channel_pbx(chan)->rtimeoutms;
11359    } else {
11360       ms = 10000;
11361    }
11362 
11363    res = ast_waitfordigit(chan, ms);
11364    if (!res) {
11365       if (ast_check_hangup(chan)) {
11366          /* Call is hungup for some reason. */
11367          res = -1;
11368       } else if (ast_exists_extension(chan, ast_channel_context(chan), ast_channel_exten(chan), ast_channel_priority(chan) + 1,
11369          S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
11370          ast_verb(3, "Timeout on %s, continuing...\n", ast_channel_name(chan));
11371       } else if (ast_exists_extension(chan, ast_channel_context(chan), "t", 1,
11372          S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
11373          ast_verb(3, "Timeout on %s, going to 't'\n", ast_channel_name(chan));
11374          set_ext_pri(chan, "t", 0); /* 0 will become 1, next time through the loop */
11375       } else if (ast_exists_extension(chan, ast_channel_context(chan), "e", 1,
11376          S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
11377          raise_exception(chan, "RESPONSETIMEOUT", 0); /* 0 will become 1, next time through the loop */
11378       } else {
11379          ast_log(LOG_WARNING, "Timeout but no rule 't' or 'e' in context '%s'\n",
11380             ast_channel_context(chan));
11381          res = -1;
11382       }
11383    }
11384 
11385    if (ast_test_flag(&flags, WAITEXTEN_MOH))
11386       ast_indicate(chan, AST_CONTROL_UNHOLD);
11387    else if (ast_test_flag(&flags, WAITEXTEN_DIALTONE))
11388       ast_playtones_stop(chan);
11389 
11390    return res;
11391 }
11392 
11393 /*!
11394  * \ingroup applications
11395  */
11396 static int pbx_builtin_background(struct ast_channel *chan, const char *data)
11397 {
11398    int res = 0;
11399    int mres = 0;
11400    struct ast_flags flags = {0};
11401    char *parse, exten[2] = "";
11402    AST_DECLARE_APP_ARGS(args,
11403       AST_APP_ARG(filename);
11404       AST_APP_ARG(options);
11405       AST_APP_ARG(lang);
11406       AST_APP_ARG(context);
11407    );
11408 
11409    if (ast_strlen_zero(data)) {
11410       ast_log(LOG_WARNING, "Background requires an argument (filename)\n");
11411       return -1;
11412    }
11413 
11414    parse = ast_strdupa(data);
11415 
11416    AST_STANDARD_APP_ARGS(args, parse);
11417 
11418    if (ast_strlen_zero(args.lang))
11419       args.lang = (char *)ast_channel_language(chan); /* XXX this is const */
11420 
11421    if (ast_strlen_zero(args.context)) {
11422       const char *context;
11423       ast_channel_lock(chan);
11424       if ((context = pbx_builtin_getvar_helper(chan, "MACRO_CONTEXT"))) {
11425          args.context = ast_strdupa(context);
11426       } else {
11427          args.context = ast_strdupa(ast_channel_context(chan));
11428       }
11429       ast_channel_unlock(chan);
11430    }
11431 
11432    if (args.options) {
11433       if (!strcasecmp(args.options, "skip"))
11434          flags.flags = BACKGROUND_SKIP;
11435       else if (!strcasecmp(args.options, "noanswer"))
11436          flags.flags = BACKGROUND_NOANSWER;
11437       else
11438          ast_app_parse_options(background_opts, &flags, NULL, args.options);
11439    }
11440 
11441    /* Answer if need be */
11442    if (ast_channel_state(chan) != AST_STATE_UP) {
11443       if (ast_test_flag(&flags, BACKGROUND_SKIP)) {
11444          goto done;
11445       } else if (!ast_test_flag(&flags, BACKGROUND_NOANSWER)) {
11446          res = ast_answer(chan);
11447       }
11448    }
11449 
11450    if (!res) {
11451       char *back = ast_strip(args.filename);
11452       char *front;
11453 
11454       ast_stopstream(chan);      /* Stop anything playing */
11455       /* Stream the list of files */
11456       while (!res && (front = strsep(&back, "&")) ) {
11457          if ( (res = ast_streamfile(chan, front, args.lang)) ) {
11458             ast_log(LOG_WARNING, "ast_streamfile failed on %s for %s\n", ast_channel_name(chan), (char*)data);
11459             res = 0;
11460             mres = 1;
11461             break;
11462          }
11463          if (ast_test_flag(&flags, BACKGROUND_PLAYBACK)) {
11464             res = ast_waitstream(chan, "");
11465          } else if (ast_test_flag(&flags, BACKGROUND_MATCHEXTEN)) {
11466             res = ast_waitstream_exten(chan, args.context);
11467          } else {
11468             res = ast_waitstream(chan, AST_DIGIT_ANY);
11469          }
11470          ast_stopstream(chan);
11471       }
11472    }
11473 
11474    /*
11475     * If the single digit DTMF is an extension in the specified context, then
11476     * go there and signal no DTMF.  Otherwise, we should exit with that DTMF.
11477     * If we're in Macro, we'll exit and seek that DTMF as the beginning of an
11478     * extension in the Macro's calling context.  If we're not in Macro, then
11479     * we'll simply seek that extension in the calling context.  Previously,
11480     * someone complained about the behavior as it related to the interior of a
11481     * Gosub routine, and the fix (#14011) inadvertently broke FreePBX
11482     * (#14940).  This change should fix both of these situations, but with the
11483     * possible incompatibility that if a single digit extension does not exist
11484     * (but a longer extension COULD have matched), it would have previously
11485     * gone immediately to the "i" extension, but will now need to wait for a
11486     * timeout.
11487     *
11488     * Later, we had to add a flag to disable this workaround, because AGI
11489     * users can EXEC Background and reasonably expect that the DTMF code will
11490     * be returned (see #16434).
11491     */
11492    if (!ast_test_flag(ast_channel_flags(chan), AST_FLAG_DISABLE_WORKAROUNDS)
11493       && (exten[0] = res)
11494       && ast_canmatch_extension(chan, args.context, exten, 1,
11495          S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))
11496       && !ast_matchmore_extension(chan, args.context, exten, 1,
11497          S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
11498       char buf[2] = { 0, };
11499       snprintf(buf, sizeof(buf), "%c", res);
11500       ast_channel_exten_set(chan, buf);
11501       ast_channel_context_set(chan, args.context);
11502       ast_channel_priority_set(chan, 0);
11503       res = 0;
11504    }
11505 done:
11506    pbx_builtin_setvar_helper(chan, "BACKGROUNDSTATUS", mres ? "FAILED" : "SUCCESS");
11507    return res;
11508 }
11509 
11510 /*! Goto
11511  * \ingroup applications
11512  */
11513 static int pbx_builtin_goto(struct ast_channel *chan, const char *data)
11514 {
11515    int res = ast_parseable_goto(chan, data);
11516    if (!res)
11517       ast_verb(3, "Goto (%s,%s,%d)\n", ast_channel_context(chan), ast_channel_exten(chan), ast_channel_priority(chan) + 1);
11518    return res;
11519 }
11520 
11521 
11522 int pbx_builtin_serialize_variables(struct ast_channel *chan, struct ast_str **buf)
11523 {
11524    struct ast_var_t *variables;
11525    const char *var, *val;
11526    int total = 0;
11527 
11528    if (!chan)
11529       return 0;
11530 
11531    ast_str_reset(*buf);
11532 
11533    ast_channel_lock(chan);
11534 
11535    AST_LIST_TRAVERSE(ast_channel_varshead(chan), variables, entries) {
11536       if ((var = ast_var_name(variables)) && (val = ast_var_value(variables))
11537          /* && !ast_strlen_zero(var) && !ast_strlen_zero(val) */
11538          ) {
11539          if (ast_str_append(buf, 0, "%s=%s\n", var, val) < 0) {
11540             ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n");
11541             break;
11542          } else
11543             total++;
11544       } else
11545          break;
11546    }
11547 
11548    ast_channel_unlock(chan);
11549 
11550    return total;
11551 }
11552 
11553 const char *pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
11554 {
11555    struct ast_var_t *variables;
11556    const char *ret = NULL;
11557    int i;
11558    struct varshead *places[2] = { NULL, &globals };
11559 
11560    if (!name)
11561       return NULL;
11562 
11563    if (chan) {
11564       ast_channel_lock(chan);
11565       places[0] = ast_channel_varshead(chan);
11566    }
11567 
11568    for (i = 0; i < 2; i++) {
11569       if (!places[i])
11570          continue;
11571       if (places[i] == &globals)
11572          ast_rwlock_rdlock(&globalslock);
11573       AST_LIST_TRAVERSE(places[i], variables, entries) {
11574          if (!strcmp(name, ast_var_name(variables))) {
11575             ret = ast_var_value(variables);
11576             break;
11577          }
11578       }
11579       if (places[i] == &globals)
11580          ast_rwlock_unlock(&globalslock);
11581       if (ret)
11582          break;
11583    }
11584 
11585    if (chan)
11586       ast_channel_unlock(chan);
11587 
11588    return ret;
11589 }
11590 
11591 void pbx_builtin_pushvar_helper(struct ast_channel *chan, const char *name, const char *value)
11592 {
11593    struct ast_var_t *newvariable;
11594    struct varshead *headp;
11595 
11596    if (name[strlen(name)-1] == ')') {
11597       char *function = ast_strdupa(name);
11598 
11599       ast_log(LOG_WARNING, "Cannot push a value onto a function\n");
11600       ast_func_write(chan, function, value);
11601       return;
11602    }
11603 
11604    if (chan) {
11605       ast_channel_lock(chan);
11606       headp = ast_channel_varshead(chan);
11607    } else {
11608       ast_rwlock_wrlock(&globalslock);
11609       headp = &globals;
11610    }
11611 
11612    if (value && (newvariable = ast_var_assign(name, value))) {
11613       if (headp == &globals)
11614          ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value);
11615       AST_LIST_INSERT_HEAD(headp, newvariable, entries);
11616    }
11617 
11618    if (chan)
11619       ast_channel_unlock(chan);
11620    else
11621       ast_rwlock_unlock(&globalslock);
11622 }
11623 
11624 int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
11625 {
11626    struct ast_var_t *newvariable;
11627    struct varshead *headp;
11628    const char *nametail = name;
11629 
11630    if (name[strlen(name) - 1] == ')') {
11631       char *function = ast_strdupa(name);
11632 
11633       return ast_func_write(chan, function, value);
11634    }
11635 
11636    if (chan) {
11637       ast_channel_lock(chan);
11638       headp = ast_channel_varshead(chan);
11639    } else {
11640       ast_rwlock_wrlock(&globalslock);
11641       headp = &globals;
11642    }
11643 
11644    /* For comparison purposes, we have to strip leading underscores */
11645    if (*nametail == '_') {
11646       nametail++;
11647       if (*nametail == '_')
11648          nametail++;
11649    }
11650 
11651    AST_LIST_TRAVERSE_SAFE_BEGIN(headp, newvariable, entries) {
11652       if (strcmp(ast_var_name(newvariable), nametail) == 0) {
11653          /* there is already such a variable, delete it */
11654          AST_LIST_REMOVE_CURRENT(entries);
11655          ast_var_delete(newvariable);
11656          break;
11657       }
11658    }
11659    AST_LIST_TRAVERSE_SAFE_END;
11660 
11661    if (value && (newvariable = ast_var_assign(name, value))) {
11662       if (headp == &globals)
11663          ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value);
11664       AST_LIST_INSERT_HEAD(headp, newvariable, entries);
11665       /*** DOCUMENTATION
11666          <managerEventInstance>
11667             <synopsis>Raised when a variable is set to a particular value.</synopsis>
11668          </managerEventInstance>
11669       ***/
11670       manager_event(EVENT_FLAG_DIALPLAN, "VarSet",
11671          "Channel: %s\r\n"
11672          "Variable: %s\r\n"
11673          "Value: %s\r\n"
11674          "Uniqueid: %s\r\n",
11675          chan ? ast_channel_name(chan) : "none", name, value,
11676          chan ? ast_channel_uniqueid(chan) : "none");
11677    }
11678 
11679    if (chan)
11680       ast_channel_unlock(chan);
11681    else
11682       ast_rwlock_unlock(&globalslock);
11683    return 0;
11684 }
11685 
11686 int pbx_builtin_setvar(struct ast_channel *chan, const char *data)
11687 {
11688    char *name, *value, *mydata;
11689 
11690    if (ast_compat_app_set) {
11691       return pbx_builtin_setvar_multiple(chan, data);
11692    }
11693 
11694    if (ast_strlen_zero(data)) {
11695       ast_log(LOG_WARNING, "Set requires one variable name/value pair.\n");
11696       return 0;
11697    }
11698 
11699    mydata = ast_strdupa(data);
11700    name = strsep(&mydata, "=");
11701    value = mydata;
11702    if (!value) {
11703       ast_log(LOG_WARNING, "Set requires an '=' to be a valid assignment.\n");
11704       return 0;
11705    }
11706 
11707    if (strchr(name, ' ')) {
11708       ast_log(LOG_WARNING, "Please avoid unnecessary spaces on variables as it may lead to unexpected results ('%s' set to '%s').\n", name, mydata);
11709    }
11710 
11711    pbx_builtin_setvar_helper(chan, name, value);
11712 
11713    return 0;
11714 }
11715 
11716 int pbx_builtin_setvar_multiple(struct ast_channel *chan, const char *vdata)
11717 {
11718    char *data;
11719    int x;
11720    AST_DECLARE_APP_ARGS(args,
11721       AST_APP_ARG(pair)[24];
11722    );
11723    AST_DECLARE_APP_ARGS(pair,
11724       AST_APP_ARG(name);
11725       AST_APP_ARG(value);
11726    );
11727 
11728    if (ast_strlen_zero(vdata)) {
11729       ast_log(LOG_WARNING, "MSet requires at least one variable name/value pair.\n");
11730       return 0;
11731    }
11732 
11733    data = ast_strdupa(vdata);
11734    AST_STANDARD_APP_ARGS(args, data);
11735 
11736    for (x = 0; x < args.argc; x++) {
11737       AST_NONSTANDARD_APP_ARGS(pair, args.pair[x], '=');
11738       if (pair.argc == 2) {
11739          pbx_builtin_setvar_helper(chan, pair.name, pair.value);
11740          if (strchr(pair.name, ' '))
11741             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);
11742       } else if (!chan) {
11743          ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '='\n", pair.name);
11744       } else {
11745          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));
11746       }
11747    }
11748 
11749    return 0;
11750 }
11751 
11752 int pbx_builtin_importvar(struct ast_channel *chan, const char *data)
11753 {
11754    char *name;
11755    char *value;
11756    char *channel;
11757    char tmp[VAR_BUF_SIZE];
11758    static int deprecation_warning = 0;
11759 
11760    if (ast_strlen_zero(data)) {
11761       ast_log(LOG_WARNING, "Ignoring, since there is no variable to set\n");
11762       return 0;
11763    }
11764    tmp[0] = 0;
11765    if (!deprecation_warning) {
11766       ast_log(LOG_WARNING, "ImportVar is deprecated.  Please use Set(varname=${IMPORT(channel,variable)}) instead.\n");
11767       deprecation_warning = 1;
11768    }
11769 
11770    value = ast_strdupa(data);
11771    name = strsep(&value,"=");
11772    channel = strsep(&value,",");
11773    if (channel && value && name) { /*! \todo XXX should do !ast_strlen_zero(..) of the args ? */
11774       struct ast_channel *chan2 = ast_channel_get_by_name(channel);
11775       if (chan2) {
11776          char *s = ast_alloca(strlen(value) + 4);
11777          sprintf(s, "${%s}", value);
11778          pbx_substitute_variables_helper(chan2, s, tmp, sizeof(tmp) - 1);
11779          chan2 = ast_channel_unref(chan2);
11780       }
11781       pbx_builtin_setvar_helper(chan, name, tmp);
11782    }
11783 
11784    return(0);
11785 }
11786 
11787 static int pbx_builtin_noop(struct ast_channel *chan, const char *data)
11788 {
11789    return 0;
11790 }
11791 
11792 void pbx_builtin_clear_globals(void)
11793 {
11794    struct ast_var_t *vardata;
11795 
11796    ast_rwlock_wrlock(&globalslock);
11797    while ((vardata = AST_LIST_REMOVE_HEAD(&globals, entries)))
11798       ast_var_delete(vardata);
11799    ast_rwlock_unlock(&globalslock);
11800 }
11801 
11802 int pbx_checkcondition(const char *condition)
11803 {
11804    int res;
11805    if (ast_strlen_zero(condition)) {                /* NULL or empty strings are false */
11806       return 0;
11807    } else if (sscanf(condition, "%30d", &res) == 1) { /* Numbers are evaluated for truth */
11808       return res;
11809    } else {                                         /* Strings are true */
11810       return 1;
11811    }
11812 }
11813 
11814 static int pbx_builtin_gotoif(struct ast_channel *chan, const char *data)
11815 {
11816    char *condition, *branch1, *branch2, *branch;
11817    char *stringp;
11818 
11819    if (ast_strlen_zero(data)) {
11820       ast_log(LOG_WARNING, "Ignoring, since there is no variable to check\n");
11821       return 0;
11822    }
11823 
11824    stringp = ast_strdupa(data);
11825    condition = strsep(&stringp,"?");
11826    branch1 = strsep(&stringp,":");
11827    branch2 = strsep(&stringp,"");
11828    branch = pbx_checkcondition(condition) ? branch1 : branch2;
11829 
11830    if (ast_strlen_zero(branch)) {
11831       ast_debug(1, "Not taking any branch\n");
11832       return 0;
11833    }
11834 
11835    return pbx_builtin_goto(chan, branch);
11836 }
11837 
11838 static int pbx_builtin_saynumber(struct ast_channel *chan, const char *data)
11839 {
11840    char tmp[256];
11841    char *number = tmp;
11842    char *options;
11843 
11844    if (ast_strlen_zero(data)) {
11845       ast_log(LOG_WARNING, "SayNumber requires an argument (number)\n");
11846       return -1;
11847    }
11848    ast_copy_string(tmp, data, sizeof(tmp));
11849    strsep(&number, ",");
11850    options = strsep(&number, ",");
11851    if (options) {
11852       if ( strcasecmp(options, "f") && strcasecmp(options, "m") &&
11853          strcasecmp(options, "c") && strcasecmp(options, "n") ) {
11854          ast_log(LOG_WARNING, "SayNumber gender option is either 'f', 'm', 'c' or 'n'\n");
11855          return -1;
11856       }
11857    }
11858 
11859    if (ast_say_number(chan, atoi(tmp), "", ast_channel_language(chan), options)) {
11860       ast_log(LOG_WARNING, "We were unable to say the number %s, is it too large?\n", tmp);
11861    }
11862 
11863    return 0;
11864 }
11865 
11866 static int pbx_builtin_saydigits(struct ast_channel *chan, const char *data)
11867 {
11868    int res = 0;
11869 
11870    if (data)
11871       res = ast_say_digit_str(chan, data, "", ast_channel_language(chan));
11872    return res;
11873 }
11874 
11875 static int pbx_builtin_saycharacters(struct ast_channel *chan, const char *data)
11876 {
11877    int res = 0;
11878 
11879    if (data)
11880       res = ast_say_character_str(chan, data, "", ast_channel_language(chan));
11881    return res;
11882 }
11883 
11884 static int pbx_builtin_sayphonetic(struct ast_channel *chan, const char *data)
11885 {
11886    int res = 0;
11887 
11888    if (data)
11889       res = ast_say_phonetic_str(chan, data, "", ast_channel_language(chan));
11890    return res;
11891 }
11892 
11893 static void presencechange_destroy(void *data)
11894 {
11895    struct presencechange *pc = data;
11896    ast_free(pc->provider);
11897    ast_free(pc->subtype);
11898    ast_free(pc->message);
11899 }
11900 
11901 static void presence_state_cb(const struct ast_event *event, void *unused)
11902 {
11903    struct presencechange *pc;
11904    const char *tmp;
11905 
11906    if (!(pc = ao2_alloc(sizeof(*pc), presencechange_destroy))) {
11907       return;
11908    }
11909 
11910    tmp = ast_event_get_ie_str(event, AST_EVENT_IE_PRESENCE_PROVIDER);
11911    if (ast_strlen_zero(tmp)) {
11912       ast_log(LOG_ERROR, "Received invalid event that had no presence provider IE\n");
11913       ao2_ref(pc, -1);
11914       return;
11915    }
11916    pc->provider = ast_strdup(tmp);
11917 
11918    pc->state = ast_event_get_ie_uint(event, AST_EVENT_IE_PRESENCE_STATE);
11919    if (pc->state < 0) {
11920       ao2_ref(pc, -1);
11921       return;
11922    }
11923 
11924    if ((tmp = ast_event_get_ie_str(event, AST_EVENT_IE_PRESENCE_SUBTYPE))) {
11925       pc->subtype = ast_strdup(tmp);
11926    }
11927 
11928    if ((tmp = ast_event_get_ie_str(event, AST_EVENT_IE_PRESENCE_MESSAGE))) {
11929       pc->message = ast_strdup(tmp);
11930    }
11931 
11932    /* The task processor thread is taking our reference to the presencechange object. */
11933    if (ast_taskprocessor_push(extension_state_tps, handle_presencechange, pc) < 0) {
11934       ao2_ref(pc, -1);
11935    }
11936 }
11937 
11938 static void device_state_cb(const struct ast_event *event, void *unused)
11939 {
11940    const char *device;
11941    struct statechange *sc;
11942 
11943    device = ast_event_get_ie_str(event, AST_EVENT_IE_DEVICE);
11944    if (ast_strlen_zero(device)) {
11945       ast_log(LOG_ERROR, "Received invalid event that had no device IE\n");
11946       return;
11947    }
11948 
11949    if (!(sc = ast_calloc(1, sizeof(*sc) + strlen(device) + 1)))
11950       return;
11951    strcpy(sc->dev, device);
11952    if (ast_taskprocessor_push(extension_state_tps, handle_statechange, sc) < 0) {
11953       ast_free(sc);
11954    }
11955 }
11956 
11957 /*!
11958  * \internal
11959  * \brief Implements the hints data provider.
11960  */
11961 static int hints_data_provider_get(const struct ast_data_search *search,
11962    struct ast_data *data_root)
11963 {
11964    struct ast_data *data_hint;
11965    struct ast_hint *hint;
11966    int watchers;
11967    struct ao2_iterator i;
11968 
11969    if (ao2_container_count(hints) == 0) {
11970       return 0;
11971    }
11972 
11973    i = ao2_iterator_init(hints, 0);
11974    for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) {
11975       watchers = ao2_container_count(hint->callbacks);
11976       data_hint = ast_data_add_node(data_root, "hint");
11977       if (!data_hint) {
11978          continue;
11979       }
11980       ast_data_add_str(data_hint, "extension", ast_get_extension_name(hint->exten));
11981       ast_data_add_str(data_hint, "context", ast_get_context_name(ast_get_extension_context(hint->exten)));
11982       ast_data_add_str(data_hint, "application", ast_get_extension_app(hint->exten));
11983       ast_data_add_str(data_hint, "state", ast_extension_state2str(hint->laststate));
11984       ast_data_add_str(data_hint, "presence_state", ast_presence_state2str(hint->last_presence_state));
11985       ast_data_add_str(data_hint, "presence_subtype", S_OR(hint->last_presence_subtype, ""));
11986       ast_data_add_str(data_hint, "presence_subtype", S_OR(hint->last_presence_message, ""));
11987       ast_data_add_int(data_hint, "watchers", watchers);
11988 
11989       if (!ast_data_search_match(search, data_hint)) {
11990          ast_data_remove_node(data_root, data_hint);
11991       }
11992    }
11993    ao2_iterator_destroy(&i);
11994 
11995    return 0;
11996 }
11997 
11998 static const struct ast_data_handler hints_data_provider = {
11999    .version = AST_DATA_HANDLER_VERSION,
12000    .get = hints_data_provider_get
12001 };
12002 
12003 static const struct ast_data_entry pbx_data_providers[] = {
12004    AST_DATA_ENTRY("asterisk/core/hints", &hints_data_provider),
12005 };
12006 
12007 /*! \internal \brief Clean up resources on Asterisk shutdown.
12008  * \note Cleans up resources allocated in load_pbx */
12009 static void unload_pbx(void)
12010 {
12011    int x;
12012 
12013    if (presence_state_sub) {
12014       presence_state_sub = ast_event_unsubscribe(presence_state_sub);
12015    }
12016    if (device_state_sub) {
12017       device_state_sub = ast_event_unsubscribe(device_state_sub);
12018    }
12019 
12020    /* Unregister builtin applications */
12021    for (x = 0; x < ARRAY_LEN(builtins); x++) {
12022       ast_unregister_application(builtins[x].name);
12023    }
12024    ast_manager_unregister("ShowDialPlan");
12025    ast_cli_unregister_multiple(pbx_cli, ARRAY_LEN(pbx_cli));
12026    ast_custom_function_unregister(&exception_function);
12027    ast_custom_function_unregister(&testtime_function);
12028    ast_data_unregister(NULL);
12029    if (extension_state_tps) {
12030       extension_state_tps = ast_taskprocessor_unreference(extension_state_tps);
12031    }
12032 }
12033 
12034 int load_pbx(void)
12035 {
12036    int x;
12037 
12038    ast_register_atexit(unload_pbx);
12039 
12040    /* Initialize the PBX */
12041    ast_verb(1, "Asterisk PBX Core Initializing\n");
12042    if (!(extension_state_tps = ast_taskprocessor_get("pbx-core", 0))) {
12043       ast_log(LOG_WARNING, "failed to create pbx-core taskprocessor\n");
12044    }
12045 
12046    ast_verb(1, "Registering builtin applications:\n");
12047    ast_cli_register_multiple(pbx_cli, ARRAY_LEN(pbx_cli));
12048    ast_data_register_multiple_core(pbx_data_providers, ARRAY_LEN(pbx_data_providers));
12049    __ast_custom_function_register(&exception_function, NULL);
12050    __ast_custom_function_register(&testtime_function, NULL);
12051 
12052    /* Register builtin applications */
12053    for (x = 0; x < ARRAY_LEN(builtins); x++) {
12054       ast_verb(1, "[%s]\n", builtins[x].name);
12055       if (ast_register_application2(builtins[x].name, builtins[x].execute, NULL, NULL, NULL)) {
12056          ast_log(LOG_ERROR, "Unable to register builtin application '%s'\n", builtins[x].name);
12057          return -1;
12058       }
12059    }
12060 
12061    /* Register manager application */
12062    ast_manager_register_xml_core("ShowDialPlan", EVENT_FLAG_CONFIG | EVENT_FLAG_REPORTING, manager_show_dialplan);
12063 
12064    if (!(device_state_sub = ast_event_subscribe(AST_EVENT_DEVICE_STATE, device_state_cb, "pbx Device State Change", NULL,
12065          AST_EVENT_IE_END))) {
12066       return -1;
12067    }
12068 
12069    if (!(presence_state_sub = ast_event_subscribe(AST_EVENT_PRESENCE_STATE, presence_state_cb, "pbx Presence State Change", NULL,
12070          AST_EVENT_IE_END))) {
12071       return -1;
12072    }
12073 
12074    return 0;
12075 }
12076 
12077 /*
12078  * Lock context list functions ...
12079  */
12080 int ast_wrlock_contexts(void)
12081 {
12082    return ast_mutex_lock(&conlock);
12083 }
12084 
12085 int ast_rdlock_contexts(void)
12086 {
12087    return ast_mutex_lock(&conlock);
12088 }
12089 
12090 int ast_unlock_contexts(void)
12091 {
12092    return ast_mutex_unlock(&conlock);
12093 }
12094 
12095 /*
12096  * Lock context ...
12097  */
12098 int ast_wrlock_context(struct ast_context *con)
12099 {
12100    return ast_rwlock_wrlock(&con->lock);
12101 }
12102 
12103 int ast_rdlock_context(struct ast_context *con)
12104 {
12105    return ast_rwlock_rdlock(&con->lock);
12106 }
12107 
12108 int ast_unlock_context(struct ast_context *con)
12109 {
12110    return ast_rwlock_unlock(&con->lock);
12111 }
12112 
12113 /*
12114  * Name functions ...
12115  */
12116 const char *ast_get_context_name(struct ast_context *con)
12117 {
12118    return con ? con->name : NULL;
12119 }
12120 
12121 struct ast_context *ast_get_extension_context(struct ast_exten *exten)
12122 {
12123    return exten ? exten->parent : NULL;
12124 }
12125 
12126 const char *ast_get_extension_name(struct ast_exten *exten)
12127 {
12128    return exten ? exten->exten : NULL;
12129 }
12130 
12131 const char *ast_get_extension_label(struct ast_exten *exten)
12132 {
12133    return exten ? exten->label : NULL;
12134 }
12135 
12136 const char *ast_get_include_name(struct ast_include *inc)
12137 {
12138    return inc ? inc->name : NULL;
12139 }
12140 
12141 const char *ast_get_ignorepat_name(struct ast_ignorepat *ip)
12142 {
12143    return ip ? ip->pattern : NULL;
12144 }
12145 
12146 int ast_get_extension_priority(struct ast_exten *exten)
12147 {
12148    return exten ? exten->priority : -1;
12149 }
12150 
12151 /*
12152  * Registrar info functions ...
12153  */
12154 const char *ast_get_context_registrar(struct ast_context *c)
12155 {
12156    return c ? c->registrar : NULL;
12157 }
12158 
12159 const char *ast_get_extension_registrar(struct ast_exten *e)
12160 {
12161    return e ? e->registrar : NULL;
12162 }
12163 
12164 const char *ast_get_include_registrar(struct ast_include *i)
12165 {
12166    return i ? i->registrar : NULL;
12167 }
12168 
12169 const char *ast_get_ignorepat_registrar(struct ast_ignorepat *ip)
12170 {
12171    return ip ? ip->registrar : NULL;
12172 }
12173 
12174 int ast_get_extension_matchcid(struct ast_exten *e)
12175 {
12176    return e ? e->matchcid : 0;
12177 }
12178 
12179 const char *ast_get_extension_cidmatch(struct ast_exten *e)
12180 {
12181    return e ? e->cidmatch : NULL;
12182 }
12183 
12184 const char *ast_get_extension_app(struct ast_exten *e)
12185 {
12186    return e ? e->app : NULL;
12187 }
12188 
12189 void *ast_get_extension_app_data(struct ast_exten *e)
12190 {
12191    return e ? e->data : NULL;
12192 }
12193 
12194 const char *ast_get_switch_name(struct ast_sw *sw)
12195 {
12196    return sw ? sw->name : NULL;
12197 }
12198 
12199 const char *ast_get_switch_data(struct ast_sw *sw)
12200 {
12201    return sw ? sw->data : NULL;
12202 }
12203 
12204 int ast_get_switch_eval(struct ast_sw *sw)
12205 {
12206    return sw->eval;
12207 }
12208 
12209 const char *ast_get_switch_registrar(struct ast_sw *sw)
12210 {
12211    return sw ? sw->registrar : NULL;
12212 }
12213 
12214 /*
12215  * Walking functions ...
12216  */
12217 struct ast_context *ast_walk_contexts(struct ast_context *con)
12218 {
12219    return con ? con->next : contexts;
12220 }
12221 
12222 struct ast_exten *ast_walk_context_extensions(struct ast_context *con,
12223    struct ast_exten *exten)
12224 {
12225    if (!exten)
12226       return con ? con->root : NULL;
12227    else
12228       return exten->next;
12229 }
12230 
12231 struct ast_sw *ast_walk_context_switches(struct ast_context *con,
12232    struct ast_sw *sw)
12233 {
12234    if (!sw)
12235       return con ? AST_LIST_FIRST(&con->alts) : NULL;
12236    else
12237       return AST_LIST_NEXT(sw, list);
12238 }
12239 
12240 struct ast_exten *ast_walk_extension_priorities(struct ast_exten *exten,
12241    struct ast_exten *priority)
12242 {
12243    return priority ? priority->peer : exten;
12244 }
12245 
12246 struct ast_include *ast_walk_context_includes(struct ast_context *con,
12247    struct ast_include *inc)
12248 {
12249    if (!inc)
12250       return con ? con->includes : NULL;
12251    else
12252       return inc->next;
12253 }
12254 
12255 struct ast_ignorepat *ast_walk_context_ignorepats(struct ast_context *con,
12256    struct ast_ignorepat *ip)
12257 {
12258    if (!ip)
12259       return con ? con->ignorepats : NULL;
12260    else
12261       return ip->next;
12262 }
12263 
12264 int ast_context_verify_includes(struct ast_context *con)
12265 {
12266    struct ast_include *inc = NULL;
12267    int res = 0;
12268 
12269    while ( (inc = ast_walk_context_includes(con, inc)) ) {
12270       if (ast_context_find(inc->rname))
12271          continue;
12272 
12273       res = -1;
12274       ast_log(LOG_WARNING, "Context '%s' tries to include nonexistent context '%s'\n",
12275          ast_get_context_name(con), inc->rname);
12276       break;
12277    }
12278 
12279    return res;
12280 }
12281 
12282 
12283 static int __ast_goto_if_exists(struct ast_channel *chan, const char *context, const char *exten, int priority, int async)
12284 {
12285    int (*goto_func)(struct ast_channel *chan, const char *context, const char *exten, int priority);
12286 
12287    if (!chan)
12288       return -2;
12289 
12290    if (context == NULL)
12291       context = ast_channel_context(chan);
12292    if (exten == NULL)
12293       exten = ast_channel_exten(chan);
12294 
12295    goto_func = (async) ? ast_async_goto : ast_explicit_goto;
12296    if (ast_exists_extension(chan, context, exten, priority,
12297       S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL)))
12298       return goto_func(chan, context, exten, priority);
12299    else {
12300       return AST_PBX_GOTO_FAILED;
12301    }
12302 }
12303 
12304 int ast_goto_if_exists(struct ast_channel *chan, const char* context, const char *exten, int priority)
12305 {
12306    return __ast_goto_if_exists(chan, context, exten, priority, 0);
12307 }
12308 
12309 int ast_async_goto_if_exists(struct ast_channel *chan, const char * context, const char *exten, int priority)
12310 {
12311    return __ast_goto_if_exists(chan, context, exten, priority, 1);
12312 }
12313 
12314 static int pbx_parseable_goto(struct ast_channel *chan, const char *goto_string, int async)
12315 {
12316    char *exten, *pri, *context;
12317    char *stringp;
12318    int ipri;
12319    int mode = 0;
12320 
12321    if (ast_strlen_zero(goto_string)) {
12322       ast_log(LOG_WARNING, "Goto requires an argument ([[context,]extension,]priority)\n");
12323       return -1;
12324    }
12325    stringp = ast_strdupa(goto_string);
12326    context = strsep(&stringp, ","); /* guaranteed non-null */
12327    exten = strsep(&stringp, ",");
12328    pri = strsep(&stringp, ",");
12329    if (!exten) {  /* Only a priority in this one */
12330       pri = context;
12331       exten = NULL;
12332       context = NULL;
12333    } else if (!pri) {   /* Only an extension and priority in this one */
12334       pri = exten;
12335       exten = context;
12336       context = NULL;
12337    }
12338    if (*pri == '+') {
12339       mode = 1;
12340       pri++;
12341    } else if (*pri == '-') {
12342       mode = -1;
12343       pri++;
12344    }
12345    if (sscanf(pri, "%30d", &ipri) != 1) {
12346       ipri = ast_findlabel_extension(chan, context ? context : ast_channel_context(chan),
12347          exten ? exten : ast_channel_exten(chan), pri,
12348          S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL));
12349       if (ipri < 1) {
12350          ast_log(LOG_WARNING, "Priority '%s' must be a number > 0, or valid label\n", pri);
12351          return -1;
12352       } else
12353          mode = 0;
12354    }
12355    /* At this point we have a priority and maybe an extension and a context */
12356 
12357    if (mode)
12358       ipri = ast_channel_priority(chan) + (ipri * mode);
12359 
12360    if (async)
12361       ast_async_goto(chan, context, exten, ipri);
12362    else
12363       ast_explicit_goto(chan, context, exten, ipri);
12364 
12365    return 0;
12366 
12367 }
12368 
12369 int ast_parseable_goto(struct ast_channel *chan, const char *goto_string)
12370 {
12371    return pbx_parseable_goto(chan, goto_string, 0);
12372 }
12373 
12374 int ast_async_parseable_goto(struct ast_channel *chan, const char *goto_string)
12375 {
12376    return pbx_parseable_goto(chan, goto_string, 1);
12377 }
12378 
12379 char *ast_complete_applications(const char *line, const char *word, int state)
12380 {
12381    struct ast_app *app = NULL;
12382    int which = 0;
12383    char *ret = NULL;
12384    size_t wordlen = strlen(word);
12385 
12386    AST_RWLIST_RDLOCK(&apps);
12387    AST_RWLIST_TRAVERSE(&apps, app, list) {
12388       if (!strncasecmp(word, app->name, wordlen) && ++which > state) {
12389          ret = ast_strdup(app->name);
12390          break;
12391       }
12392    }
12393    AST_RWLIST_UNLOCK(&apps);
12394 
12395    return ret;
12396 }
12397 
12398 static int hint_hash(const void *obj, const int flags)
12399 {
12400    const struct ast_hint *hint = obj;
12401    const char *exten_name;
12402    int res;
12403 
12404    exten_name = ast_get_extension_name(hint->exten);
12405    if (ast_strlen_zero(exten_name)) {
12406       /*
12407        * If the exten or extension name isn't set, return 0 so that
12408        * the ao2_find() search will start in the first bucket.
12409        */
12410       res = 0;
12411    } else {
12412       res = ast_str_case_hash(exten_name);
12413    }
12414 
12415    return res;
12416 }
12417 
12418 static int hint_cmp(void *obj, void *arg, int flags)
12419 {
12420    const struct ast_hint *hint = obj;
12421    const struct ast_exten *exten = arg;
12422 
12423    return (hint->exten == exten) ? CMP_MATCH | CMP_STOP : 0;
12424 }
12425 
12426 static int statecbs_cmp(void *obj, void *arg, int flags)
12427 {
12428    const struct ast_state_cb *state_cb = obj;
12429    ast_state_cb_type change_cb = arg;
12430 
12431    return (state_cb->change_cb == change_cb) ? CMP_MATCH | CMP_STOP : 0;
12432 }
12433 
12434 /*!
12435  * \internal
12436  * \brief Clean up resources on Asterisk shutdown
12437  */
12438 static void pbx_shutdown(void)
12439 {
12440    if (hints) {
12441       ao2_ref(hints, -1);
12442       hints = NULL;
12443    }
12444    if (hintdevices) {
12445       ao2_ref(hintdevices, -1);
12446       hintdevices = NULL;
12447    }
12448    if (statecbs) {
12449       ao2_ref(statecbs, -1);
12450       statecbs = NULL;
12451    }
12452    if (contexts_table) {
12453       ast_hashtab_destroy(contexts_table, NULL);
12454    }
12455    pbx_builtin_clear_globals();
12456 }
12457 
12458 int ast_pbx_init(void)
12459 {
12460    hints = ao2_container_alloc(HASH_EXTENHINT_SIZE, hint_hash, hint_cmp);
12461    hintdevices = ao2_container_alloc(HASH_EXTENHINT_SIZE, hintdevice_hash_cb, hintdevice_cmp_multiple);
12462    statecbs = ao2_container_alloc(1, NULL, statecbs_cmp);
12463 
12464    ast_register_atexit(pbx_shutdown);
12465 
12466    return (hints && hintdevices && statecbs) ? 0 : -1;
12467 }