Thu Oct 11 06:33:50 2012

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