Mon Mar 19 11:30:28 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 #include "asterisk.h"
00026 
00027 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 352955 $")
00028 
00029 #include "asterisk/_private.h"
00030 #include "asterisk/paths.h"   /* use ast_config_AST_SYSTEM_NAME */
00031 #include <ctype.h>
00032 #include <time.h>
00033 #include <sys/time.h>
00034 #if defined(HAVE_SYSINFO)
00035 #include <sys/sysinfo.h>
00036 #endif
00037 #if defined(SOLARIS)
00038 #include <sys/loadavg.h>
00039 #endif
00040 
00041 #include "asterisk/lock.h"
00042 #include "asterisk/cli.h"
00043 #include "asterisk/pbx.h"
00044 #include "asterisk/channel.h"
00045 #include "asterisk/file.h"
00046 #include "asterisk/callerid.h"
00047 #include "asterisk/cdr.h"
00048 #include "asterisk/cel.h"
00049 #include "asterisk/config.h"
00050 #include "asterisk/term.h"
00051 #include "asterisk/time.h"
00052 #include "asterisk/manager.h"
00053 #include "asterisk/ast_expr.h"
00054 #include "asterisk/linkedlists.h"
00055 #define  SAY_STUBS   /* generate declarations and stubs for say methods */
00056 #include "asterisk/say.h"
00057 #include "asterisk/utils.h"
00058 #include "asterisk/causes.h"
00059 #include "asterisk/musiconhold.h"
00060 #include "asterisk/app.h"
00061 #include "asterisk/devicestate.h"
00062 #include "asterisk/event.h"
00063 #include "asterisk/hashtab.h"
00064 #include "asterisk/module.h"
00065 #include "asterisk/indications.h"
00066 #include "asterisk/taskprocessor.h"
00067 #include "asterisk/xmldoc.h"
00068 #include "asterisk/astobj2.h"
00069 
00070 /*!
00071  * \note I M P O R T A N T :
00072  *
00073  *    The speed of extension handling will likely be among the most important
00074  * aspects of this PBX.  The switching scheme as it exists right now isn't
00075  * terribly bad (it's O(N+M), where N is the # of extensions and M is the avg #
00076  * of priorities, but a constant search time here would be great ;-)
00077  *
00078  * A new algorithm to do searching based on a 'compiled' pattern tree is introduced
00079  * here, and shows a fairly flat (constant) search time, even for over
00080  * 10000 patterns.
00081  *
00082  * Also, using a hash table for context/priority name lookup can help prevent
00083  * the find_extension routines from absorbing exponential cpu cycles as the number
00084  * of contexts/priorities grow. I've previously tested find_extension with red-black trees,
00085  * which have O(log2(n)) speed. Right now, I'm using hash tables, which do
00086  * searches (ideally) in O(1) time. While these techniques do not yield much
00087  * speed in small dialplans, they are worth the trouble in large dialplans.
00088  *
00089  */
00090 
00091 /*** DOCUMENTATION
00092    <application name="Answer" language="en_US">
00093       <synopsis>
00094          Answer a channel if ringing.
00095       </synopsis>
00096       <syntax>
00097          <parameter name="delay">
00098             <para>Asterisk will wait this number of milliseconds before returning to
00099             the dialplan after answering the call.</para>
00100          </parameter>
00101          <parameter name="nocdr">
00102             <para>Asterisk will send an answer signal to the calling phone, but will not
00103             set the disposition or answer time in the CDR for this call.</para>
00104          </parameter>
00105       </syntax>
00106       <description>
00107          <para>If the call has not been answered, this application will
00108          answer it. Otherwise, it has no effect on the call.</para>
00109       </description>
00110       <see-also>
00111          <ref type="application">Hangup</ref>
00112       </see-also>
00113    </application>
00114    <application name="BackGround" language="en_US">
00115       <synopsis>
00116          Play an audio file while waiting for digits of an extension to go to.
00117       </synopsis>
00118       <syntax>
00119          <parameter name="filenames" required="true" argsep="&amp;">
00120             <argument name="filename1" required="true" />
00121             <argument name="filename2" multiple="true" />
00122          </parameter>
00123          <parameter name="options">
00124             <optionlist>
00125                <option name="s">
00126                   <para>Causes the playback of the message to be skipped
00127                   if the channel is not in the <literal>up</literal> state (i.e. it
00128                   hasn't been answered yet). If this happens, the
00129                   application will return immediately.</para>
00130                </option>
00131                <option name="n">
00132                   <para>Don't answer the channel before playing the files.</para>
00133                </option>
00134                <option name="m">
00135                   <para>Only break if a digit hit matches a one digit
00136                   extension in the destination context.</para>
00137                </option>
00138             </optionlist>
00139          </parameter>
00140          <parameter name="langoverride">
00141             <para>Explicitly specifies which language to attempt to use for the requested sound files.</para>
00142          </parameter>
00143          <parameter name="context">
00144             <para>This is the dialplan context that this application will use when exiting
00145             to a dialed extension.</para>
00146          </parameter>
00147       </syntax>
00148       <description>
00149          <para>This application will play the given list of files <emphasis>(do not put extension)</emphasis>
00150          while waiting for an extension to be dialed by the calling channel. To continue waiting
00151          for digits after this application has finished playing files, the <literal>WaitExten</literal>
00152          application should be used.</para>
00153          <para>If one of the requested sound files does not exist, call processing will be terminated.</para>
00154          <para>This application sets the following channel variable upon completion:</para>
00155          <variablelist>
00156             <variable name="BACKGROUNDSTATUS">
00157                <para>The status of the background attempt as a text string.</para>
00158                <value name="SUCCESS" />
00159                <value name="FAILED" />
00160             </variable>
00161          </variablelist>
00162       </description>
00163       <see-also>
00164          <ref type="application">ControlPlayback</ref>
00165          <ref type="application">WaitExten</ref>
00166          <ref type="application">BackgroundDetect</ref>
00167          <ref type="function">TIMEOUT</ref>
00168       </see-also>
00169    </application>
00170    <application name="Busy" language="en_US">
00171       <synopsis>
00172          Indicate the Busy condition.
00173       </synopsis>
00174       <syntax>
00175          <parameter name="timeout">
00176             <para>If specified, the calling channel will be hung up after the specified number of seconds.
00177             Otherwise, this application will wait until the calling channel hangs up.</para>
00178          </parameter>
00179       </syntax>
00180       <description>
00181          <para>This application will indicate the busy condition to the calling channel.</para>
00182       </description>
00183       <see-also>
00184          <ref type="application">Congestion</ref>
00185          <ref type="application">Progress</ref>
00186          <ref type="application">Playtones</ref>
00187          <ref type="application">Hangup</ref>
00188       </see-also>
00189    </application>
00190    <application name="Congestion" language="en_US">
00191       <synopsis>
00192          Indicate the Congestion condition.
00193       </synopsis>
00194       <syntax>
00195          <parameter name="timeout">
00196             <para>If specified, the calling channel will be hung up after the specified number of seconds.
00197             Otherwise, this application will wait until the calling channel hangs up.</para>
00198          </parameter>
00199       </syntax>
00200       <description>
00201          <para>This application will indicate the congestion condition to the calling channel.</para>
00202       </description>
00203       <see-also>
00204          <ref type="application">Busy</ref>
00205          <ref type="application">Progress</ref>
00206          <ref type="application">Playtones</ref>
00207          <ref type="application">Hangup</ref>
00208       </see-also>
00209    </application>
00210    <application name="ExecIfTime" language="en_US">
00211       <synopsis>
00212          Conditional application execution based on the current time.
00213       </synopsis>
00214       <syntax argsep="?">
00215          <parameter name="day_condition" required="true">
00216             <argument name="times" required="true" />
00217             <argument name="weekdays" required="true" />
00218             <argument name="mdays" required="true" />
00219             <argument name="months" required="true" />
00220             <argument name="timezone" required="false" />
00221          </parameter>
00222          <parameter name="appname" required="true" hasparams="optional">
00223             <argument name="appargs" required="true" />
00224          </parameter>
00225       </syntax>
00226       <description>
00227          <para>This application will execute the specified dialplan application, with optional
00228          arguments, if the current time matches the given time specification.</para>
00229       </description>
00230       <see-also>
00231          <ref type="application">Exec</ref>
00232          <ref type="application">TryExec</ref>
00233       </see-also>
00234    </application>
00235    <application name="Goto" language="en_US">
00236       <synopsis>
00237          Jump to a particular priority, extension, or context.
00238       </synopsis>
00239       <syntax>
00240          <parameter name="context" />
00241          <parameter name="extensions" />
00242          <parameter name="priority" required="true" />
00243       </syntax>
00244       <description>
00245          <para>This application will set the current context, extension, and priority in the channel structure.
00246          After it completes, the pbx engine will continue dialplan execution at the specified location.
00247          If no specific <replaceable>extension</replaceable>, or <replaceable>extension</replaceable> and
00248          <replaceable>context</replaceable>, are specified, then this application will
00249          just set the specified <replaceable>priority</replaceable> of the current extension.</para>
00250          <para>At least a <replaceable>priority</replaceable> is required as an argument, or the goto will
00251          return a <literal>-1</literal>,  and the channel and call will be terminated.</para>
00252          <para>If the location that is put into the channel information is bogus, and asterisk cannot
00253          find that location in the dialplan, then the execution engine will try to find and execute the code in
00254          the <literal>i</literal> (invalid) extension in the current context. If that does not exist, it will try to execute the
00255          <literal>h</literal> extension. If neither the <literal>h</literal> nor <literal>i</literal> extensions
00256          have been defined, the channel is hung up, and the execution of instructions on the channel is terminated.
00257          What this means is that, for example, you specify a context that does not exist, then
00258          it will not be possible to find the <literal>h</literal> or <literal>i</literal> extensions,
00259          and the call will terminate!</para>
00260       </description>
00261       <see-also>
00262          <ref type="application">GotoIf</ref>
00263          <ref type="application">GotoIfTime</ref>
00264          <ref type="application">Gosub</ref>
00265          <ref type="application">Macro</ref>
00266       </see-also>
00267    </application>
00268    <application name="GotoIf" language="en_US">
00269       <synopsis>
00270          Conditional goto.
00271       </synopsis>
00272       <syntax argsep="?">
00273          <parameter name="condition" required="true" />
00274          <parameter name="destination" required="true" argsep=":">
00275             <argument name="labeliftrue">
00276                <para>Continue at <replaceable>labeliftrue</replaceable> if the condition is true.</para>
00277             </argument>
00278             <argument name="labeliffalse">
00279                <para>Continue at <replaceable>labeliffalse</replaceable> if the condition is false.</para>
00280             </argument>
00281          </parameter>
00282       </syntax>
00283       <description>
00284          <para>This application will set the current context, extension, and priority in the channel structure
00285          based on the evaluation of the given condition. After this application completes, the
00286          pbx engine will continue dialplan execution at the specified location in the dialplan.
00287          The labels are specified with the same syntax as used within the Goto application.
00288          If the label chosen by the condition is omitted, no jump is performed, and the execution passes to the
00289          next instruction. If the target location is bogus, and does not exist, the execution engine will try
00290          to find and execute the code in the <literal>i</literal> (invalid) extension in the current context.
00291          If that does not exist, it will try to execute the <literal>h</literal> extension.
00292          If neither the <literal>h</literal> nor <literal>i</literal> extensions have been defined,
00293          the channel is hung up, and the execution of instructions on the channel is terminated.
00294          Remember that this command can set the current context, and if the context specified
00295          does not exist, then it will not be able to find any 'h' or 'i' extensions there, and
00296          the channel and call will both be terminated!.</para>
00297       </description>
00298       <see-also>
00299          <ref type="application">Goto</ref>
00300          <ref type="application">GotoIfTime</ref>
00301          <ref type="application">GosubIf</ref>
00302          <ref type="application">MacroIf</ref>
00303       </see-also>
00304    </application>
00305    <application name="GotoIfTime" language="en_US">
00306       <synopsis>
00307          Conditional Goto based on the current time.
00308       </synopsis>
00309       <syntax argsep="?">
00310          <parameter name="condition" required="true">
00311             <argument name="times" required="true" />
00312             <argument name="weekdays" required="true" />
00313             <argument name="mdays" required="true" />
00314             <argument name="months" required="true" />
00315             <argument name="timezone" required="false" />
00316          </parameter>
00317          <parameter name="destination" required="true" argsep=":">
00318             <argument name="labeliftrue" />
00319             <argument name="labeliffalse" />
00320          </parameter>
00321       </syntax>
00322       <description>
00323          <para>This application will set the context, extension, and priority in the channel structure
00324          based on the evaluation of the given time specification. After this application completes,
00325          the pbx engine will continue dialplan execution at the specified location in the dialplan.
00326          If the current time is within the given time specification, the channel will continue at
00327          <replaceable>labeliftrue</replaceable>. Otherwise the channel will continue at <replaceable>labeliffalse</replaceable>.
00328          If the label chosen by the condition is omitted, no jump is performed, and execution passes to the next
00329          instruction. If the target jump location is bogus, the same actions would be taken as for <literal>Goto</literal>.
00330          Further information on the time specification can be found in examples
00331          illustrating how to do time-based context includes in the dialplan.</para>
00332       </description>
00333       <see-also>
00334          <ref type="application">GotoIf</ref>
00335          <ref type="function">IFTIME</ref>
00336          <ref type="function">TESTTIME</ref>
00337       </see-also>
00338    </application>
00339    <application name="ImportVar" language="en_US">
00340       <synopsis>
00341          Import a variable from a channel into a new variable.
00342       </synopsis>
00343       <syntax argsep="=">
00344          <parameter name="newvar" required="true" />
00345          <parameter name="vardata" required="true">
00346             <argument name="channelname" required="true" />
00347             <argument name="variable" required="true" />
00348          </parameter>
00349       </syntax>
00350       <description>
00351          <para>This application imports a <replaceable>variable</replaceable> from the specified
00352          <replaceable>channel</replaceable> (as opposed to the current one) and stores it as a variable
00353          (<replaceable>newvar</replaceable>) in the current channel (the channel that is calling this
00354          application). Variables created by this application have the same inheritance properties as those
00355          created with the <literal>Set</literal> application.</para>
00356       </description>
00357       <see-also>
00358          <ref type="application">Set</ref>
00359       </see-also>
00360    </application>
00361    <application name="Hangup" language="en_US">
00362       <synopsis>
00363          Hang up the calling channel.
00364       </synopsis>
00365       <syntax>
00366          <parameter name="causecode">
00367             <para>If a <replaceable>causecode</replaceable> is given the channel's
00368             hangup cause will be set to the given value.</para>
00369          </parameter>
00370       </syntax>
00371       <description>
00372          <para>This application will hang up the calling channel.</para>
00373       </description>
00374       <see-also>
00375          <ref type="application">Answer</ref>
00376          <ref type="application">Busy</ref>
00377          <ref type="application">Congestion</ref>
00378       </see-also>
00379    </application>
00380    <application name="Incomplete" language="en_US">
00381       <synopsis>
00382          Returns AST_PBX_INCOMPLETE value.
00383       </synopsis>
00384       <syntax>
00385          <parameter name="n">
00386             <para>If specified, then Incomplete will not attempt to answer the channel first.</para>
00387             <note><para>Most channel types need to be in Answer state in order to receive DTMF.</para></note>
00388          </parameter>
00389       </syntax>
00390       <description>
00391          <para>Signals the PBX routines that the previous matched extension is incomplete
00392          and that further input should be allowed before matching can be considered
00393          to be complete.  Can be used within a pattern match when certain criteria warrants
00394          a longer match.</para>
00395       </description>
00396    </application>
00397    <application name="NoOp" language="en_US">
00398       <synopsis>
00399          Do Nothing (No Operation).
00400       </synopsis>
00401       <syntax>
00402          <parameter name="text">
00403             <para>Any text provided can be viewed at the Asterisk CLI.</para>
00404          </parameter>
00405       </syntax>
00406       <description>
00407          <para>This application does nothing. However, it is useful for debugging purposes.</para>
00408          <para>This method can be used to see the evaluations of variables or functions without having any effect.</para>
00409       </description>
00410       <see-also>
00411          <ref type="application">Verbose</ref>
00412          <ref type="application">Log</ref>
00413       </see-also>
00414    </application>
00415    <application name="Proceeding" language="en_US">
00416       <synopsis>
00417          Indicate proceeding.
00418       </synopsis>
00419       <syntax />
00420       <description>
00421          <para>This application will request that a proceeding message be provided to the calling channel.</para>
00422       </description>
00423    </application>
00424    <application name="Progress" language="en_US">
00425       <synopsis>
00426          Indicate progress.
00427       </synopsis>
00428       <syntax />
00429       <description>
00430          <para>This application will request that in-band progress information be provided to the calling channel.</para>
00431       </description>
00432       <see-also>
00433          <ref type="application">Busy</ref>
00434          <ref type="application">Congestion</ref>
00435          <ref type="application">Ringing</ref>
00436          <ref type="application">Playtones</ref>
00437       </see-also>
00438    </application>
00439    <application name="RaiseException" language="en_US">
00440       <synopsis>
00441          Handle an exceptional condition.
00442       </synopsis>
00443       <syntax>
00444          <parameter name="reason" required="true" />
00445       </syntax>
00446       <description>
00447          <para>This application will jump to the <literal>e</literal> extension in the current context, setting the
00448          dialplan function EXCEPTION(). If the <literal>e</literal> extension does not exist, the call will hangup.</para>
00449       </description>
00450       <see-also>
00451          <ref type="function">Exception</ref>
00452       </see-also>
00453    </application>
00454    <application name="ResetCDR" language="en_US">
00455       <synopsis>
00456          Resets the Call Data Record.
00457       </synopsis>
00458       <syntax>
00459          <parameter name="options">
00460             <optionlist>
00461                <option name="w">
00462                   <para>Store the current CDR record before resetting it.</para>
00463                </option>
00464                <option name="a">
00465                   <para>Store any stacked records.</para>
00466                </option>
00467                <option name="v">
00468                   <para>Save CDR variables.</para>
00469                </option>
00470                <option name="e">
00471                   <para>Enable CDR only (negate effects of NoCDR).</para>
00472                </option>
00473             </optionlist>
00474          </parameter>
00475       </syntax>
00476       <description>
00477          <para>This application causes the Call Data Record to be reset.</para>
00478       </description>
00479       <see-also>
00480          <ref type="application">ForkCDR</ref>
00481          <ref type="application">NoCDR</ref>
00482       </see-also>
00483    </application>
00484    <application name="Ringing" language="en_US">
00485       <synopsis>
00486          Indicate ringing tone.
00487       </synopsis>
00488       <syntax />
00489       <description>
00490          <para>This application will request that the channel indicate a ringing tone to the user.</para>
00491       </description>
00492       <see-also>
00493          <ref type="application">Busy</ref>
00494          <ref type="application">Congestion</ref>
00495          <ref type="application">Progress</ref>
00496          <ref type="application">Playtones</ref>
00497       </see-also>
00498    </application>
00499    <application name="SayAlpha" language="en_US">
00500       <synopsis>
00501          Say Alpha.
00502       </synopsis>
00503       <syntax>
00504          <parameter name="string" required="true" />
00505       </syntax>
00506       <description>
00507          <para>This application will play the sounds that correspond to the letters of the
00508          given <replaceable>string</replaceable>.</para>
00509       </description>
00510       <see-also>
00511          <ref type="application">SayDigits</ref>
00512          <ref type="application">SayNumber</ref>
00513          <ref type="application">SayPhonetic</ref>
00514          <ref type="function">CHANNEL</ref>
00515       </see-also>
00516    </application>
00517    <application name="SayDigits" language="en_US">
00518       <synopsis>
00519          Say Digits.
00520       </synopsis>
00521       <syntax>
00522          <parameter name="digits" required="true" />
00523       </syntax>
00524       <description>
00525          <para>This application will play the sounds that correspond to the digits of
00526          the given number. This will use the language that is currently set for the channel.</para>
00527       </description>
00528       <see-also>
00529          <ref type="application">SayAlpha</ref>
00530          <ref type="application">SayNumber</ref>
00531          <ref type="application">SayPhonetic</ref>
00532          <ref type="function">CHANNEL</ref>
00533       </see-also>
00534    </application>
00535    <application name="SayNumber" language="en_US">
00536       <synopsis>
00537          Say Number.
00538       </synopsis>
00539       <syntax>
00540          <parameter name="digits" required="true" />
00541          <parameter name="gender" />
00542       </syntax>
00543       <description>
00544          <para>This application will play the sounds that correspond to the given <replaceable>digits</replaceable>.
00545          Optionally, a <replaceable>gender</replaceable> may be specified. This will use the language that is currently
00546          set for the channel. See the CHANNEL() function for more information on setting the language for the channel.</para>
00547       </description>
00548       <see-also>
00549          <ref type="application">SayAlpha</ref>
00550          <ref type="application">SayDigits</ref>
00551          <ref type="application">SayPhonetic</ref>
00552          <ref type="function">CHANNEL</ref>
00553       </see-also>
00554    </application>
00555    <application name="SayPhonetic" language="en_US">
00556       <synopsis>
00557          Say Phonetic.
00558       </synopsis>
00559       <syntax>
00560          <parameter name="string" required="true" />
00561       </syntax>
00562       <description>
00563          <para>This application will play the sounds from the phonetic alphabet that correspond to the
00564          letters in the given <replaceable>string</replaceable>.</para>
00565       </description>
00566       <see-also>
00567          <ref type="application">SayAlpha</ref>
00568          <ref type="application">SayDigits</ref>
00569          <ref type="application">SayNumber</ref>
00570       </see-also>
00571    </application>
00572    <application name="Set" language="en_US">
00573       <synopsis>
00574          Set channel variable or function value.
00575       </synopsis>
00576       <syntax argsep="=">
00577          <parameter name="name" required="true" />
00578          <parameter name="value" required="true" />
00579       </syntax>
00580       <description>
00581          <para>This function can be used to set the value of channel variables or dialplan functions.
00582          When setting variables, if the variable name is prefixed with <literal>_</literal>,
00583          the variable will be inherited into channels created from the current channel.
00584          If the variable name is prefixed with <literal>__</literal>, the variable will be
00585          inherited into channels created from the current channel and all children channels.</para>
00586          <note><para>If (and only if), in <filename>/etc/asterisk/asterisk.conf</filename>, you have
00587          a <literal>[compat]</literal> category, and you have <literal>app_set = 1.4</literal> under that, then
00588          the behavior of this app changes, and strips surrounding quotes from the right hand side as
00589          it did previously in 1.4.
00590          The advantages of not stripping out quoting, and not caring about the separator characters (comma and vertical bar)
00591          were sufficient to make these changes in 1.6. Confusion about how many backslashes would be needed to properly
00592          protect separators and quotes in various database access strings has been greatly
00593          reduced by these changes.</para></note>
00594       </description>
00595       <see-also>
00596          <ref type="application">MSet</ref>
00597          <ref type="function">GLOBAL</ref>
00598          <ref type="function">SET</ref>
00599          <ref type="function">ENV</ref>
00600       </see-also>
00601    </application>
00602    <application name="MSet" language="en_US">
00603       <synopsis>
00604          Set channel variable(s) or function value(s).
00605       </synopsis>
00606       <syntax>
00607          <parameter name="set1" required="true" argsep="=">
00608             <argument name="name1" required="true" />
00609             <argument name="value1" required="true" />
00610          </parameter>
00611          <parameter name="set2" multiple="true" argsep="=">
00612             <argument name="name2" required="true" />
00613             <argument name="value2" required="true" />
00614          </parameter>
00615       </syntax>
00616       <description>
00617          <para>This function can be used to set the value of channel variables or dialplan functions.
00618          When setting variables, if the variable name is prefixed with <literal>_</literal>,
00619          the variable will be inherited into channels created from the current channel
00620          If the variable name is prefixed with <literal>__</literal>, the variable will be
00621          inherited into channels created from the current channel and all children channels.
00622          MSet behaves in a similar fashion to the way Set worked in 1.2/1.4 and is thus
00623          prone to doing things that you may not expect. For example, it strips surrounding
00624          double-quotes from the right-hand side (value). If you need to put a separator
00625          character (comma or vert-bar), you will need to escape them by inserting a backslash
00626          before them. Avoid its use if possible.</para>
00627       </description>
00628       <see-also>
00629          <ref type="application">Set</ref>
00630       </see-also>
00631    </application>
00632    <application name="SetAMAFlags" language="en_US">
00633       <synopsis>
00634          Set the AMA Flags.
00635       </synopsis>
00636       <syntax>
00637          <parameter name="flag" />
00638       </syntax>
00639       <description>
00640          <para>This application will set the channel's AMA Flags for billing purposes.</para>
00641       </description>
00642       <see-also>
00643          <ref type="function">CDR</ref>
00644       </see-also>
00645    </application>
00646    <application name="Wait" language="en_US">
00647       <synopsis>
00648          Waits for some time.
00649       </synopsis>
00650       <syntax>
00651          <parameter name="seconds" required="true">
00652             <para>Can be passed with fractions of a second. For example, <literal>1.5</literal> will ask the
00653             application to wait for 1.5 seconds.</para>
00654          </parameter>
00655       </syntax>
00656       <description>
00657          <para>This application waits for a specified number of <replaceable>seconds</replaceable>.</para>
00658       </description>
00659    </application>
00660    <application name="WaitExten" language="en_US">
00661       <synopsis>
00662          Waits for an extension to be entered.
00663       </synopsis>
00664       <syntax>
00665          <parameter name="seconds">
00666             <para>Can be passed with fractions of a second. For example, <literal>1.5</literal> will ask the
00667             application to wait for 1.5 seconds.</para>
00668          </parameter>
00669          <parameter name="options">
00670             <optionlist>
00671                <option name="m">
00672                   <para>Provide music on hold to the caller while waiting for an extension.</para>
00673                   <argument name="x">
00674                      <para>Specify the class for music on hold. <emphasis>CHANNEL(musicclass) will
00675                      be used instead if set</emphasis></para>
00676                   </argument>
00677                </option>
00678             </optionlist>
00679          </parameter>
00680       </syntax>
00681       <description>
00682          <para>This application waits for the user to enter a new extension for a specified number
00683          of <replaceable>seconds</replaceable>.</para>
00684          <xi:include xpointer="xpointer(/docs/application[@name='Macro']/description/warning[2])" />
00685       </description>
00686       <see-also>
00687          <ref type="application">Background</ref>
00688          <ref type="function">TIMEOUT</ref>
00689       </see-also>
00690    </application>
00691    <function name="EXCEPTION" language="en_US">
00692       <synopsis>
00693          Retrieve the details of the current dialplan exception.
00694       </synopsis>
00695       <syntax>
00696          <parameter name="field" required="true">
00697             <para>The following fields are available for retrieval:</para>
00698             <enumlist>
00699                <enum name="reason">
00700                   <para>INVALID, ERROR, RESPONSETIMEOUT, ABSOLUTETIMEOUT, or custom
00701                   value set by the RaiseException() application</para>
00702                </enum>
00703                <enum name="context">
00704                   <para>The context executing when the exception occurred.</para>
00705                </enum>
00706                <enum name="exten">
00707                   <para>The extension executing when the exception occurred.</para>
00708                </enum>
00709                <enum name="priority">
00710                   <para>The numeric priority executing when the exception occurred.</para>
00711                </enum>
00712             </enumlist>
00713          </parameter>
00714       </syntax>
00715       <description>
00716          <para>Retrieve the details (specified <replaceable>field</replaceable>) of the current dialplan exception.</para>
00717       </description>
00718       <see-also>
00719          <ref type="application">RaiseException</ref>
00720       </see-also>
00721    </function>
00722    <function name="TESTTIME" language="en_US">
00723       <synopsis>
00724          Sets a time to be used with the channel to test logical conditions.
00725       </synopsis>
00726       <syntax>
00727          <parameter name="date" required="true" argsep=" ">
00728             <para>Date in ISO 8601 format</para>
00729          </parameter>
00730          <parameter name="time" required="true" argsep=" ">
00731             <para>Time in HH:MM:SS format (24-hour time)</para>
00732          </parameter>
00733          <parameter name="zone" required="false">
00734             <para>Timezone name</para>
00735          </parameter>
00736       </syntax>
00737       <description>
00738          <para>To test dialplan timing conditions at times other than the current time, use
00739          this function to set an alternate date and time.  For example, you may wish to evaluate
00740          whether a location will correctly identify to callers that the area is closed on Christmas
00741          Day, when Christmas would otherwise fall on a day when the office is normally open.</para>
00742       </description>
00743       <see-also>
00744          <ref type="application">GotoIfTime</ref>
00745       </see-also>
00746    </function>
00747    <manager name="ShowDialPlan" language="en_US">
00748       <synopsis>
00749          Show dialplan contexts and extensions
00750       </synopsis>
00751       <syntax>
00752          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00753          <parameter name="Extension">
00754             <para>Show a specific extension.</para>
00755          </parameter>
00756          <parameter name="Context">
00757             <para>Show a specific context.</para>
00758          </parameter>
00759       </syntax>
00760       <description>
00761          <para>Show dialplan contexts and extensions. Be aware that showing the full dialplan
00762          may take a lot of capacity.</para>
00763       </description>
00764    </manager>
00765  ***/
00766 
00767 #ifdef LOW_MEMORY
00768 #define EXT_DATA_SIZE 256
00769 #else
00770 #define EXT_DATA_SIZE 8192
00771 #endif
00772 
00773 #define SWITCH_DATA_LENGTH 256
00774 
00775 #define VAR_BUF_SIZE 4096
00776 
00777 #define  VAR_NORMAL     1
00778 #define  VAR_SOFTTRAN   2
00779 #define  VAR_HARDTRAN   3
00780 
00781 #define BACKGROUND_SKIP    (1 << 0)
00782 #define BACKGROUND_NOANSWER   (1 << 1)
00783 #define BACKGROUND_MATCHEXTEN (1 << 2)
00784 #define BACKGROUND_PLAYBACK   (1 << 3)
00785 
00786 AST_APP_OPTIONS(background_opts, {
00787    AST_APP_OPTION('s', BACKGROUND_SKIP),
00788    AST_APP_OPTION('n', BACKGROUND_NOANSWER),
00789    AST_APP_OPTION('m', BACKGROUND_MATCHEXTEN),
00790    AST_APP_OPTION('p', BACKGROUND_PLAYBACK),
00791 });
00792 
00793 #define WAITEXTEN_MOH      (1 << 0)
00794 #define WAITEXTEN_DIALTONE (1 << 1)
00795 
00796 AST_APP_OPTIONS(waitexten_opts, {
00797    AST_APP_OPTION_ARG('m', WAITEXTEN_MOH, 0),
00798    AST_APP_OPTION_ARG('d', WAITEXTEN_DIALTONE, 0),
00799 });
00800 
00801 struct ast_context;
00802 struct ast_app;
00803 
00804 static struct ast_taskprocessor *device_state_tps;
00805 
00806 AST_THREADSTORAGE(switch_data);
00807 AST_THREADSTORAGE(extensionstate_buf);
00808 
00809 /*!
00810    \brief ast_exten: An extension
00811    The dialplan is saved as a linked list with each context
00812    having it's own linked list of extensions - one item per
00813    priority.
00814 */
00815 struct ast_exten {
00816    char *exten;         /*!< Extension name */
00817    int matchcid;        /*!< Match caller id ? */
00818    const char *cidmatch;      /*!< Caller id to match for this extension */
00819    int priority;        /*!< Priority */
00820    const char *label;      /*!< Label */
00821    struct ast_context *parent;   /*!< The context this extension belongs to  */
00822    const char *app;     /*!< Application to execute */
00823    struct ast_app *cached_app;     /*!< Cached location of application */
00824    void *data;       /*!< Data to use (arguments) */
00825    void (*datad)(void *);     /*!< Data destructor */
00826    struct ast_exten *peer;    /*!< Next higher priority with our extension */
00827    struct ast_hashtab *peer_table;    /*!< Priorities list in hashtab form -- only on the head of the peer list */
00828    struct ast_hashtab *peer_label_table; /*!< labeled priorities in the peers -- only on the head of the peer list */
00829    const char *registrar;     /*!< Registrar */
00830    struct ast_exten *next;    /*!< Extension with a greater ID */
00831    char stuff[0];
00832 };
00833 
00834 /*! \brief ast_include: include= support in extensions.conf */
00835 struct ast_include {
00836    const char *name;
00837    const char *rname;         /*!< Context to include */
00838    const char *registrar;        /*!< Registrar */
00839    int hastime;            /*!< If time construct exists */
00840    struct ast_timing timing;               /*!< time construct */
00841    struct ast_include *next;     /*!< Link them together */
00842    char stuff[0];
00843 };
00844 
00845 /*! \brief ast_sw: Switch statement in extensions.conf */
00846 struct ast_sw {
00847    char *name;
00848    const char *registrar;        /*!< Registrar */
00849    char *data;          /*!< Data load */
00850    int eval;
00851    AST_LIST_ENTRY(ast_sw) list;
00852    char stuff[0];
00853 };
00854 
00855 /*! \brief ast_ignorepat: Ignore patterns in dial plan */
00856 struct ast_ignorepat {
00857    const char *registrar;
00858    struct ast_ignorepat *next;
00859    const char pattern[0];
00860 };
00861 
00862 /*! \brief match_char: forms a syntax tree for quick matching of extension patterns */
00863 struct match_char
00864 {
00865    int is_pattern; /* the pattern started with '_' */
00866    int deleted;    /* if this is set, then... don't return it */
00867    int specificity; /* simply the strlen of x, or 10 for X, 9 for Z, and 8 for N; and '.' and '!' will add 11 ? */
00868    struct match_char *alt_char;
00869    struct match_char *next_char;
00870    struct ast_exten *exten; /* attached to last char of a pattern for exten */
00871    char x[1];       /* the pattern itself-- matches a single char */
00872 };
00873 
00874 struct scoreboard  /* make sure all fields are 0 before calling new_find_extension */
00875 {
00876    int total_specificity;
00877    int total_length;
00878    char last_char;   /* set to ! or . if they are the end of the pattern */
00879    int canmatch;     /* if the string to match was just too short */
00880    struct match_char *node;
00881    struct ast_exten *canmatch_exten;
00882    struct ast_exten *exten;
00883 };
00884 
00885 /*! \brief ast_context: An extension context */
00886 struct ast_context {
00887    ast_rwlock_t lock;         /*!< A lock to prevent multiple threads from clobbering the context */
00888    struct ast_exten *root;       /*!< The root of the list of extensions */
00889    struct ast_hashtab *root_table;            /*!< For exact matches on the extensions in the pattern tree, and for traversals of the pattern_tree  */
00890    struct match_char *pattern_tree;        /*!< A tree to speed up extension pattern matching */
00891    struct ast_context *next;     /*!< Link them together */
00892    struct ast_include *includes;    /*!< Include other contexts */
00893    struct ast_ignorepat *ignorepats;   /*!< Patterns for which to continue playing dialtone */
00894    char *registrar;        /*!< Registrar -- make sure you malloc this, as the registrar may have to survive module unloads */
00895    int refcount;                   /*!< each module that would have created this context should inc/dec this as appropriate */
00896    AST_LIST_HEAD_NOLOCK(, ast_sw) alts;   /*!< Alternative switches */
00897    ast_mutex_t macrolock;        /*!< A lock to implement "exclusive" macros - held whilst a call is executing in the macro */
00898    char name[0];           /*!< Name of the context */
00899 };
00900 
00901 /*! \brief ast_app: A registered application */
00902 struct ast_app {
00903    int (*execute)(struct ast_channel *chan, const char *data);
00904    AST_DECLARE_STRING_FIELDS(
00905       AST_STRING_FIELD(synopsis);     /*!< Synopsis text for 'show applications' */
00906       AST_STRING_FIELD(description);  /*!< Description (help text) for 'show application &lt;name&gt;' */
00907       AST_STRING_FIELD(syntax);       /*!< Syntax text for 'core show applications' */
00908       AST_STRING_FIELD(arguments);    /*!< Arguments description */
00909       AST_STRING_FIELD(seealso);      /*!< See also */
00910    );
00911 #ifdef AST_XML_DOCS
00912    enum ast_doc_src docsrc;      /*!< Where the documentation come from. */
00913 #endif
00914    AST_RWLIST_ENTRY(ast_app) list;     /*!< Next app in list */
00915    struct ast_module *module;    /*!< Module this app belongs to */
00916    char name[0];           /*!< Name of the application */
00917 };
00918 
00919 /*! \brief ast_state_cb: An extension state notify register item */
00920 struct ast_state_cb {
00921    /*! Watcher ID returned when registered. */
00922    int id;
00923    /*! Arbitrary data passed for callbacks. */
00924    void *data;
00925    /*! Callback when state changes. */
00926    ast_state_cb_type change_cb;
00927    /*! Callback when destroyed so any resources given by the registerer can be freed. */
00928    ast_state_cb_destroy_type destroy_cb;
00929    /*! \note Only used by ast_merge_contexts_and_delete */
00930    AST_LIST_ENTRY(ast_state_cb) entry;
00931 };
00932 
00933 /*!
00934  * \brief Structure for dial plan hints
00935  *
00936  * \note Hints are pointers from an extension in the dialplan to
00937  * one or more devices (tech/name)
00938  *
00939  * See \ref AstExtState
00940  */
00941 struct ast_hint {
00942    /*!
00943     * \brief Hint extension
00944     *
00945     * \note
00946     * Will never be NULL while the hint is in the hints container.
00947     */
00948    struct ast_exten *exten;
00949    struct ao2_container *callbacks; /*!< Callback container for this extension */
00950    int laststate;       /*!< Last known state */
00951    char context_name[AST_MAX_CONTEXT];/*!< Context of destroyed hint extension. */
00952    char exten_name[AST_MAX_EXTENSION];/*!< Extension of destroyed hint extension. */
00953 };
00954 
00955 /* --- Hash tables of various objects --------*/
00956 #ifdef LOW_MEMORY
00957 #define HASH_EXTENHINT_SIZE 17
00958 #else
00959 #define HASH_EXTENHINT_SIZE 563
00960 #endif
00961 
00962 static const struct cfextension_states {
00963    int extension_state;
00964    const char * const text;
00965 } extension_states[] = {
00966    { AST_EXTENSION_NOT_INUSE,                     "Idle" },
00967    { AST_EXTENSION_INUSE,                         "InUse" },
00968    { AST_EXTENSION_BUSY,                          "Busy" },
00969    { AST_EXTENSION_UNAVAILABLE,                   "Unavailable" },
00970    { AST_EXTENSION_RINGING,                       "Ringing" },
00971    { AST_EXTENSION_INUSE | AST_EXTENSION_RINGING, "InUse&Ringing" },
00972    { AST_EXTENSION_ONHOLD,                        "Hold" },
00973    { AST_EXTENSION_INUSE | AST_EXTENSION_ONHOLD,  "InUse&Hold" }
00974 };
00975 
00976 struct statechange {
00977    AST_LIST_ENTRY(statechange) entry;
00978    char dev[0];
00979 };
00980 
00981 struct pbx_exception {
00982    AST_DECLARE_STRING_FIELDS(
00983       AST_STRING_FIELD(context); /*!< Context associated with this exception */
00984       AST_STRING_FIELD(exten);   /*!< Exten associated with this exception */
00985       AST_STRING_FIELD(reason);     /*!< The exception reason */
00986    );
00987 
00988    int priority;           /*!< Priority associated with this exception */
00989 };
00990 
00991 static int pbx_builtin_answer(struct ast_channel *, const char *);
00992 static int pbx_builtin_goto(struct ast_channel *, const char *);
00993 static int pbx_builtin_hangup(struct ast_channel *, const char *);
00994 static int pbx_builtin_background(struct ast_channel *, const char *);
00995 static int pbx_builtin_wait(struct ast_channel *, const char *);
00996 static int pbx_builtin_waitexten(struct ast_channel *, const char *);
00997 static int pbx_builtin_incomplete(struct ast_channel *, const char *);
00998 static int pbx_builtin_resetcdr(struct ast_channel *, const char *);
00999 static int pbx_builtin_setamaflags(struct ast_channel *, const char *);
01000 static int pbx_builtin_ringing(struct ast_channel *, const char *);
01001 static int pbx_builtin_proceeding(struct ast_channel *, const char *);
01002 static int pbx_builtin_progress(struct ast_channel *, const char *);
01003 static int pbx_builtin_congestion(struct ast_channel *, const char *);
01004 static int pbx_builtin_busy(struct ast_channel *, const char *);
01005 static int pbx_builtin_noop(struct ast_channel *, const char *);
01006 static int pbx_builtin_gotoif(struct ast_channel *, const char *);
01007 static int pbx_builtin_gotoiftime(struct ast_channel *, const char *);
01008 static int pbx_builtin_execiftime(struct ast_channel *, const char *);
01009 static int pbx_builtin_saynumber(struct ast_channel *, const char *);
01010 static int pbx_builtin_saydigits(struct ast_channel *, const char *);
01011 static int pbx_builtin_saycharacters(struct ast_channel *, const char *);
01012 static int pbx_builtin_sayphonetic(struct ast_channel *, const char *);
01013 static int matchcid(const char *cidpattern, const char *callerid);
01014 #ifdef NEED_DEBUG
01015 static void log_match_char_tree(struct match_char *node, char *prefix); /* for use anywhere */
01016 #endif
01017 static int pbx_builtin_importvar(struct ast_channel *, const char *);
01018 static void set_ext_pri(struct ast_channel *c, const char *exten, int pri);
01019 static void new_find_extension(const char *str, struct scoreboard *score,
01020       struct match_char *tree, int length, int spec, const char *callerid,
01021       const char *label, enum ext_match_t action);
01022 static struct match_char *already_in_tree(struct match_char *current, char *pat, int is_pattern);
01023 static struct match_char *add_exten_to_pattern_tree(struct ast_context *con,
01024       struct ast_exten *e1, int findonly);
01025 static void create_match_char_tree(struct ast_context *con);
01026 static struct ast_exten *get_canmatch_exten(struct match_char *node);
01027 static void destroy_pattern_tree(struct match_char *pattern_tree);
01028 static int hashtab_compare_extens(const void *ha_a, const void *ah_b);
01029 static int hashtab_compare_exten_numbers(const void *ah_a, const void *ah_b);
01030 static int hashtab_compare_exten_labels(const void *ah_a, const void *ah_b);
01031 static unsigned int hashtab_hash_extens(const void *obj);
01032 static unsigned int hashtab_hash_priority(const void *obj);
01033 static unsigned int hashtab_hash_labels(const void *obj);
01034 static void __ast_internal_context_destroy( struct ast_context *con);
01035 static int ast_add_extension_nolock(const char *context, int replace, const char *extension,
01036    int priority, const char *label, const char *callerid,
01037    const char *application, void *data, void (*datad)(void *), const char *registrar);
01038 static int ast_add_extension2_lockopt(struct ast_context *con,
01039    int replace, const char *extension, int priority, const char *label, const char *callerid,
01040    const char *application, void *data, void (*datad)(void *),
01041    const char *registrar, int lock_context);
01042 static struct ast_context *find_context_locked(const char *context);
01043 static struct ast_context *find_context(const char *context);
01044 
01045 /*!
01046  * \internal
01047  * \brief Character array comparison function for qsort.
01048  *
01049  * \param a Left side object.
01050  * \param b Right side object.
01051  *
01052  * \retval <0 if a < b
01053  * \retval =0 if a = b
01054  * \retval >0 if a > b
01055  */
01056 static int compare_char(const void *a, const void *b)
01057 {
01058    const unsigned char *ac = a;
01059    const unsigned char *bc = b;
01060 
01061    return *ac - *bc;
01062 }
01063 
01064 /* labels, contexts are case sensitive  priority numbers are ints */
01065 int ast_hashtab_compare_contexts(const void *ah_a, const void *ah_b)
01066 {
01067    const struct ast_context *ac = ah_a;
01068    const struct ast_context *bc = ah_b;
01069    if (!ac || !bc) /* safety valve, but it might prevent a crash you'd rather have happen */
01070       return 1;
01071    /* assume context names are registered in a string table! */
01072    return strcmp(ac->name, bc->name);
01073 }
01074 
01075 static int hashtab_compare_extens(const void *ah_a, const void *ah_b)
01076 {
01077    const struct ast_exten *ac = ah_a;
01078    const struct ast_exten *bc = ah_b;
01079    int x = strcmp(ac->exten, bc->exten);
01080    if (x) { /* if exten names are diff, then return */
01081       return x;
01082    }
01083 
01084    /* but if they are the same, do the cidmatch values match? */
01085    if (ac->matchcid && bc->matchcid) {
01086       return strcmp(ac->cidmatch,bc->cidmatch);
01087    } else if (!ac->matchcid && !bc->matchcid) {
01088       return 0; /* if there's no matchcid on either side, then this is a match */
01089    } else {
01090       return 1; /* if there's matchcid on one but not the other, they are different */
01091    }
01092 }
01093 
01094 static int hashtab_compare_exten_numbers(const void *ah_a, const void *ah_b)
01095 {
01096    const struct ast_exten *ac = ah_a;
01097    const struct ast_exten *bc = ah_b;
01098    return ac->priority != bc->priority;
01099 }
01100 
01101 static int hashtab_compare_exten_labels(const void *ah_a, const void *ah_b)
01102 {
01103    const struct ast_exten *ac = ah_a;
01104    const struct ast_exten *bc = ah_b;
01105    return strcmp(S_OR(ac->label, ""), S_OR(bc->label, ""));
01106 }
01107 
01108 unsigned int ast_hashtab_hash_contexts(const void *obj)
01109 {
01110    const struct ast_context *ac = obj;
01111    return ast_hashtab_hash_string(ac->name);
01112 }
01113 
01114 static unsigned int hashtab_hash_extens(const void *obj)
01115 {
01116    const struct ast_exten *ac = obj;
01117    unsigned int x = ast_hashtab_hash_string(ac->exten);
01118    unsigned int y = 0;
01119    if (ac->matchcid)
01120       y = ast_hashtab_hash_string(ac->cidmatch);
01121    return x+y;
01122 }
01123 
01124 static unsigned int hashtab_hash_priority(const void *obj)
01125 {
01126    const struct ast_exten *ac = obj;
01127    return ast_hashtab_hash_int(ac->priority);
01128 }
01129 
01130 static unsigned int hashtab_hash_labels(const void *obj)
01131 {
01132    const struct ast_exten *ac = obj;
01133    return ast_hashtab_hash_string(S_OR(ac->label, ""));
01134 }
01135 
01136 
01137 AST_RWLOCK_DEFINE_STATIC(globalslock);
01138 static struct varshead globals = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
01139 
01140 static int autofallthrough = 1;
01141 static int extenpatternmatchnew = 0;
01142 static char *overrideswitch = NULL;
01143 
01144 /*! \brief Subscription for device state change events */
01145 static struct ast_event_sub *device_state_sub;
01146 
01147 AST_MUTEX_DEFINE_STATIC(maxcalllock);
01148 static int countcalls;
01149 static int totalcalls;
01150 
01151 static AST_RWLIST_HEAD_STATIC(acf_root, ast_custom_function);
01152 
01153 /*! \brief Declaration of builtin applications */
01154 static struct pbx_builtin {
01155    char name[AST_MAX_APP];
01156    int (*execute)(struct ast_channel *chan, const char *data);
01157 } builtins[] =
01158 {
01159    /* These applications are built into the PBX core and do not
01160       need separate modules */
01161 
01162    { "Answer",         pbx_builtin_answer },
01163    { "BackGround",     pbx_builtin_background },
01164    { "Busy",           pbx_builtin_busy },
01165    { "Congestion",     pbx_builtin_congestion },
01166    { "ExecIfTime",     pbx_builtin_execiftime },
01167    { "Goto",           pbx_builtin_goto },
01168    { "GotoIf",         pbx_builtin_gotoif },
01169    { "GotoIfTime",     pbx_builtin_gotoiftime },
01170    { "ImportVar",      pbx_builtin_importvar },
01171    { "Hangup",         pbx_builtin_hangup },
01172    { "Incomplete",     pbx_builtin_incomplete },
01173    { "NoOp",           pbx_builtin_noop },
01174    { "Proceeding",     pbx_builtin_proceeding },
01175    { "Progress",       pbx_builtin_progress },
01176    { "RaiseException", pbx_builtin_raise_exception },
01177    { "ResetCDR",       pbx_builtin_resetcdr },
01178    { "Ringing",        pbx_builtin_ringing },
01179    { "SayAlpha",       pbx_builtin_saycharacters },
01180    { "SayDigits",      pbx_builtin_saydigits },
01181    { "SayNumber",      pbx_builtin_saynumber },
01182    { "SayPhonetic",    pbx_builtin_sayphonetic },
01183    { "Set",            pbx_builtin_setvar },
01184    { "MSet",           pbx_builtin_setvar_multiple },
01185    { "SetAMAFlags",    pbx_builtin_setamaflags },
01186    { "Wait",           pbx_builtin_wait },
01187    { "WaitExten",      pbx_builtin_waitexten }
01188 };
01189 
01190 static struct ast_context *contexts;
01191 static struct ast_hashtab *contexts_table = NULL;
01192 
01193 /*!
01194  * \brief Lock for the ast_context list
01195  * \note
01196  * This lock MUST be recursive, or a deadlock on reload may result.  See
01197  * https://issues.asterisk.org/view.php?id=17643
01198  */
01199 AST_MUTEX_DEFINE_STATIC(conlock);
01200 
01201 /*!
01202  * \brief Lock to hold off restructuring of hints by ast_merge_contexts_and_delete.
01203  */
01204 AST_MUTEX_DEFINE_STATIC(context_merge_lock);
01205 
01206 static AST_RWLIST_HEAD_STATIC(apps, ast_app);
01207 
01208 static AST_RWLIST_HEAD_STATIC(switches, ast_switch);
01209 
01210 static int stateid = 1;
01211 /*!
01212  * \note When holding this container's lock, do _not_ do
01213  * anything that will cause conlock to be taken, unless you
01214  * _already_ hold it.  The ast_merge_contexts_and_delete function
01215  * will take the locks in conlock/hints order, so any other
01216  * paths that require both locks must also take them in that
01217  * order.
01218  */
01219 static struct ao2_container *hints;
01220 
01221 static struct ao2_container *statecbs;
01222 
01223 #ifdef CONTEXT_DEBUG
01224 
01225 /* these routines are provided for doing run-time checks
01226    on the extension structures, in case you are having
01227    problems, this routine might help you localize where
01228    the problem is occurring. It's kinda like a debug memory
01229    allocator's arena checker... It'll eat up your cpu cycles!
01230    but you'll see, if you call it in the right places,
01231    right where your problems began...
01232 */
01233 
01234 /* you can break on the check_contexts_trouble()
01235 routine in your debugger to stop at the moment
01236 there's a problem */
01237 void check_contexts_trouble(void);
01238 
01239 void check_contexts_trouble(void)
01240 {
01241    int x = 1;
01242    x = 2;
01243 }
01244 
01245 int check_contexts(char *, int);
01246 
01247 int check_contexts(char *file, int line )
01248 {
01249    struct ast_hashtab_iter *t1;
01250    struct ast_context *c1, *c2;
01251    int found = 0;
01252    struct ast_exten *e1, *e2, *e3;
01253    struct ast_exten ex;
01254 
01255    /* try to find inconsistencies */
01256    /* is every context in the context table in the context list and vice-versa ? */
01257 
01258    if (!contexts_table) {
01259       ast_log(LOG_NOTICE,"Called from: %s:%d: No contexts_table!\n", file, line);
01260       usleep(500000);
01261    }
01262 
01263    t1 = ast_hashtab_start_traversal(contexts_table);
01264    while( (c1 = ast_hashtab_next(t1))) {
01265       for(c2=contexts;c2;c2=c2->next) {
01266          if (!strcmp(c1->name, c2->name)) {
01267             found = 1;
01268             break;
01269          }
01270       }
01271       if (!found) {
01272          ast_log(LOG_NOTICE,"Called from: %s:%d: Could not find the %s context in the linked list\n", file, line, c1->name);
01273          check_contexts_trouble();
01274       }
01275    }
01276    ast_hashtab_end_traversal(t1);
01277    for(c2=contexts;c2;c2=c2->next) {
01278       c1 = find_context_locked(c2->name);
01279       if (!c1) {
01280          ast_log(LOG_NOTICE,"Called from: %s:%d: Could not find the %s context in the hashtab\n", file, line, c2->name);
01281          check_contexts_trouble();
01282       } else
01283          ast_unlock_contexts();
01284    }
01285 
01286    /* loop thru all contexts, and verify the exten structure compares to the 
01287       hashtab structure */
01288    for(c2=contexts;c2;c2=c2->next) {
01289       c1 = find_context_locked(c2->name);
01290       if (c1) {
01291          ast_unlock_contexts();
01292 
01293          /* is every entry in the root list also in the root_table? */
01294          for(e1 = c1->root; e1; e1=e1->next)
01295          {
01296             char dummy_name[1024];
01297             ex.exten = dummy_name;
01298             ex.matchcid = e1->matchcid;
01299             ex.cidmatch = e1->cidmatch;
01300             ast_copy_string(dummy_name, e1->exten, sizeof(dummy_name));
01301             e2 = ast_hashtab_lookup(c1->root_table, &ex);
01302             if (!e2) {
01303                if (e1->matchcid) {
01304                   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 );
01305                } else {
01306                   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 );
01307                }
01308                check_contexts_trouble();
01309             }
01310          }
01311 
01312          /* is every entry in the root_table also in the root list? */ 
01313          if (!c2->root_table) {
01314             if (c2->root) {
01315                ast_log(LOG_NOTICE,"Called from: %s:%d: No c2->root_table for context %s!\n", file, line, c2->name);
01316                usleep(500000);
01317             }
01318          } else {
01319             t1 = ast_hashtab_start_traversal(c2->root_table);
01320             while( (e2 = ast_hashtab_next(t1)) ) {
01321                for(e1=c2->root;e1;e1=e1->next) {
01322                   if (!strcmp(e1->exten, e2->exten)) {
01323                      found = 1;
01324                      break;
01325                   }
01326                }
01327                if (!found) {
01328                   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);
01329                   check_contexts_trouble();
01330                }
01331 
01332             }
01333             ast_hashtab_end_traversal(t1);
01334          }
01335       }
01336       /* is every priority reflected in the peer_table at the head of the list? */
01337 
01338       /* is every entry in the root list also in the root_table? */
01339       /* are the per-extension peer_tables in the right place? */
01340 
01341       for(e1 = c2->root; e1; e1 = e1->next) {
01342 
01343          for(e2=e1;e2;e2=e2->peer) {
01344             ex.priority = e2->priority;
01345             if (e2 != e1 && e2->peer_table) {
01346                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 );
01347                check_contexts_trouble();
01348             }
01349 
01350             if (e2 != e1 && e2->peer_label_table) {
01351                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 );
01352                check_contexts_trouble();
01353             }
01354 
01355             if (e2 == e1 && !e2->peer_table){
01356                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 );
01357                check_contexts_trouble();
01358             }
01359 
01360             if (e2 == e1 && !e2->peer_label_table) {
01361                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 );
01362                check_contexts_trouble();
01363             }
01364 
01365 
01366             e3 = ast_hashtab_lookup(e1->peer_table, &ex);
01367             if (!e3) {
01368                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 );
01369                check_contexts_trouble();
01370             }
01371          }
01372 
01373          if (!e1->peer_table){
01374             ast_log(LOG_NOTICE,"Called from: %s:%d: No e1->peer_table!\n", file, line);
01375             usleep(500000);
01376          }
01377 
01378          /* is every entry in the peer_table also in the peer list? */
01379          t1 = ast_hashtab_start_traversal(e1->peer_table);
01380          while( (e2 = ast_hashtab_next(t1)) ) {
01381             for(e3=e1;e3;e3=e3->peer) {
01382                if (e3->priority == e2->priority) {
01383                   found = 1;
01384                   break;
01385                }
01386             }
01387             if (!found) {
01388                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 );
01389                check_contexts_trouble();
01390             }
01391          }
01392          ast_hashtab_end_traversal(t1);
01393       }
01394    }
01395    return 0;
01396 }
01397 #endif
01398 
01399 /*
01400    \note This function is special. It saves the stack so that no matter
01401    how many times it is called, it returns to the same place */
01402 int pbx_exec(struct ast_channel *c, /*!< Channel */
01403         struct ast_app *app,  /*!< Application */
01404         const char *data)     /*!< Data for execution */
01405 {
01406    int res;
01407    struct ast_module_user *u = NULL;
01408    const char *saved_c_appl;
01409    const char *saved_c_data;
01410 
01411    if (c->cdr && !ast_check_hangup(c))
01412       ast_cdr_setapp(c->cdr, app->name, data);
01413 
01414    /* save channel values */
01415    saved_c_appl= c->appl;
01416    saved_c_data= c->data;
01417 
01418    c->appl = app->name;
01419    c->data = data;
01420    ast_cel_report_event(c, AST_CEL_APP_START, NULL, NULL, NULL);
01421 
01422    if (app->module)
01423       u = __ast_module_user_add(app->module, c);
01424    if (strcasecmp(app->name, "system") && !ast_strlen_zero(data) &&
01425          strchr(data, '|') && !strchr(data, ',') && !ast_opt_dont_warn) {
01426       ast_log(LOG_WARNING, "The application delimiter is now the comma, not "
01427          "the pipe.  Did you forget to convert your dialplan?  (%s(%s))\n",
01428          app->name, (char *) data);
01429    }
01430    res = app->execute(c, S_OR(data, ""));
01431    if (app->module && u)
01432       __ast_module_user_remove(app->module, u);
01433    ast_cel_report_event(c, AST_CEL_APP_END, NULL, NULL, NULL);
01434    /* restore channel values */
01435    c->appl = saved_c_appl;
01436    c->data = saved_c_data;
01437    return res;
01438 }
01439 
01440 
01441 /*! Go no deeper than this through includes (not counting loops) */
01442 #define AST_PBX_MAX_STACK  128
01443 
01444 /*! \brief Find application handle in linked list
01445  */
01446 struct ast_app *pbx_findapp(const char *app)
01447 {
01448    struct ast_app *tmp;
01449 
01450    AST_RWLIST_RDLOCK(&apps);
01451    AST_RWLIST_TRAVERSE(&apps, tmp, list) {
01452       if (!strcasecmp(tmp->name, app))
01453          break;
01454    }
01455    AST_RWLIST_UNLOCK(&apps);
01456 
01457    return tmp;
01458 }
01459 
01460 static struct ast_switch *pbx_findswitch(const char *sw)
01461 {
01462    struct ast_switch *asw;
01463 
01464    AST_RWLIST_RDLOCK(&switches);
01465    AST_RWLIST_TRAVERSE(&switches, asw, list) {
01466       if (!strcasecmp(asw->name, sw))
01467          break;
01468    }
01469    AST_RWLIST_UNLOCK(&switches);
01470 
01471    return asw;
01472 }
01473 
01474 static inline int include_valid(struct ast_include *i)
01475 {
01476    if (!i->hastime)
01477       return 1;
01478 
01479    return ast_check_timing(&(i->timing));
01480 }
01481 
01482 static void pbx_destroy(struct ast_pbx *p)
01483 {
01484    ast_free(p);
01485 }
01486 
01487 /* form a tree that fully describes all the patterns in a context's extensions
01488  * in this tree, a "node" represents an individual character or character set
01489  * meant to match the corresponding character in a dial string. The tree
01490  * consists of a series of match_char structs linked in a chain
01491  * via the alt_char pointers. More than one pattern can share the same parts of the
01492  * tree as other extensions with the same pattern to that point.
01493  * My first attempt to duplicate the finding of the 'best' pattern was flawed in that
01494  * I misunderstood the general algorithm. I thought that the 'best' pattern
01495  * was the one with lowest total score. This was not true. Thus, if you have
01496  * patterns "1XXXXX" and "X11111", you would be tempted to say that "X11111" is
01497  * the "best" match because it has fewer X's, and is therefore more specific,
01498  * but this is not how the old algorithm works. It sorts matching patterns
01499  * in a similar collating sequence as sorting alphabetic strings, from left to
01500  * right. Thus, "1XXXXX" comes before "X11111", and would be the "better" match,
01501  * because "1" is more specific than "X".
01502  * So, to accomodate this philosophy, I sort the tree branches along the alt_char
01503  * line so they are lowest to highest in specificity numbers. This way, as soon
01504  * as we encounter our first complete match, we automatically have the "best"
01505  * match and can stop the traversal immediately. Same for CANMATCH/MATCHMORE.
01506  * If anyone would like to resurrect the "wrong" pattern trie searching algorithm,
01507  * they are welcome to revert pbx to before 1 Apr 2008.
01508  * As an example, consider these 4 extensions:
01509  * (a) NXXNXXXXXX
01510  * (b) 307754XXXX
01511  * (c) fax
01512  * (d) NXXXXXXXXX
01513  *
01514  * In the above, between (a) and (d), (a) is a more specific pattern than (d), and would win over
01515  * most numbers. For all numbers beginning with 307754, (b) should always win.
01516  *
01517  * These pattern should form a (sorted) tree that looks like this:
01518  *   { "3" }  --next-->  { "0" }  --next--> { "7" } --next--> { "7" } --next--> { "5" } ... blah ... --> { "X" exten_match: (b) }
01519  *      |
01520  *      |alt
01521  *      |
01522  *   { "f" }  --next-->  { "a" }  --next--> { "x"  exten_match: (c) }
01523  *   { "N" }  --next-->  { "X" }  --next--> { "X" } --next--> { "N" } --next--> { "X" } ... blah ... --> { "X" exten_match: (a) }
01524  *      |                                                        |
01525  *      |                                                        |alt
01526  *      |alt                                                     |
01527  *      |                                                     { "X" } --next--> { "X" } ... blah ... --> { "X" exten_match: (d) }
01528  *      |
01529  *     NULL
01530  *
01531  *   In the above, I could easily turn "N" into "23456789", but I think that a quick "if( *z >= '2' && *z <= '9' )" might take
01532  *   fewer CPU cycles than a call to strchr("23456789",*z), where *z is the char to match...
01533  *
01534  *   traversal is pretty simple: one routine merely traverses the alt list, and for each matching char in the pattern,  it calls itself
01535  *   on the corresponding next pointer, incrementing also the pointer of the string to be matched, and passing the total specificity and length.
01536  *   We pass a pointer to a scoreboard down through, also.
01537  *   The scoreboard isn't as necessary to the revised algorithm, but I kept it as a handy way to return the matched extension.
01538  *   The first complete match ends the traversal, which should make this version of the pattern matcher faster
01539  *   the previous. The same goes for "CANMATCH" or "MATCHMORE"; the first such match ends the traversal. In both
01540  *   these cases, the reason we can stop immediately, is because the first pattern match found will be the "best"
01541  *   according to the sort criteria.
01542  *   Hope the limit on stack depth won't be a problem... this routine should
01543  *   be pretty lean as far a stack usage goes. Any non-match terminates the recursion down a branch.
01544  *
01545  *   In the above example, with the number "3077549999" as the pattern, the traversor could match extensions a, b and d.  All are
01546  *   of length 10; they have total specificities of  24580, 10246, and 25090, respectively, not that this matters
01547  *   at all. (b) wins purely because the first character "3" is much more specific (lower specificity) than "N". I have
01548  *   left the specificity totals in the code as an artifact; at some point, I will strip it out.
01549  *
01550  *   Just how much time this algorithm might save over a plain linear traversal over all possible patterns is unknown,
01551  *   because it's a function of how many extensions are stored in a context. With thousands of extensions, the speedup
01552  *   can be very noticeable. The new matching algorithm can run several hundreds of times faster, if not a thousand or
01553  *   more times faster in extreme cases.
01554  *
01555  *   MatchCID patterns are also supported, and stored in the tree just as the extension pattern is. Thus, you
01556  *   can have patterns in your CID field as well.
01557  *
01558  * */
01559 
01560 
01561 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)
01562 {
01563    /* if this extension is marked as deleted, then skip this -- if it never shows
01564       on the scoreboard, it will never be found, nor will halt the traversal. */
01565    if (deleted)
01566       return;
01567    board->total_specificity = spec;
01568    board->total_length = length;
01569    board->exten = exten;
01570    board->last_char = last;
01571    board->node = node;
01572 #ifdef NEED_DEBUG_HERE
01573    ast_log(LOG_NOTICE,"Scoreboarding (LONGER) %s, len=%d, score=%d\n", exten->exten, length, spec);
01574 #endif
01575 }
01576 
01577 #ifdef NEED_DEBUG
01578 static void log_match_char_tree(struct match_char *node, char *prefix)
01579 {
01580    char extenstr[40];
01581    struct ast_str *my_prefix = ast_str_alloca(1024);
01582 
01583    extenstr[0] = '\0';
01584 
01585    if (node && node->exten)
01586       snprintf(extenstr, sizeof(extenstr), "(%p)", node->exten);
01587 
01588    if (strlen(node->x) > 1) {
01589       ast_debug(1, "%s[%s]:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y':'N',
01590          node->deleted? 'D':'-', node->specificity, node->exten? "EXTEN:":"",
01591          node->exten ? node->exten->exten : "", extenstr);
01592    } else {
01593       ast_debug(1, "%s%s:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y':'N',
01594          node->deleted? 'D':'-', node->specificity, node->exten? "EXTEN:":"",
01595          node->exten ? node->exten->exten : "", extenstr);
01596    }
01597 
01598    ast_str_set(&my_prefix, 0, "%s+       ", prefix);
01599 
01600    if (node->next_char)
01601       log_match_char_tree(node->next_char, ast_str_buffer(my_prefix));
01602 
01603    if (node->alt_char)
01604       log_match_char_tree(node->alt_char, prefix);
01605 }
01606 #endif
01607 
01608 static void cli_match_char_tree(struct match_char *node, char *prefix, int fd)
01609 {
01610    char extenstr[40];
01611    struct ast_str *my_prefix = ast_str_alloca(1024);
01612 
01613    extenstr[0] = '\0';
01614 
01615    if (node && node->exten)
01616       snprintf(extenstr, sizeof(extenstr), "(%p)", node->exten);
01617 
01618    if (strlen(node->x) > 1) {
01619       ast_cli(fd, "%s[%s]:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y' : 'N',
01620          node->deleted ? 'D' : '-', node->specificity, node->exten? "EXTEN:" : "",
01621          node->exten ? node->exten->exten : "", extenstr);
01622    } else {
01623       ast_cli(fd, "%s%s:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y' : 'N',
01624          node->deleted ? 'D' : '-', node->specificity, node->exten? "EXTEN:" : "",
01625          node->exten ? node->exten->exten : "", extenstr);
01626    }
01627 
01628    ast_str_set(&my_prefix, 0, "%s+       ", prefix);
01629 
01630    if (node->next_char)
01631       cli_match_char_tree(node->next_char, ast_str_buffer(my_prefix), fd);
01632 
01633    if (node->alt_char)
01634       cli_match_char_tree(node->alt_char, prefix, fd);
01635 }
01636 
01637 static struct ast_exten *get_canmatch_exten(struct match_char *node)
01638 {
01639    /* find the exten at the end of the rope */
01640    struct match_char *node2 = node;
01641 
01642    for (node2 = node; node2; node2 = node2->next_char) {
01643       if (node2->exten) {
01644 #ifdef NEED_DEBUG_HERE
01645          ast_log(LOG_NOTICE,"CanMatch_exten returns exten %s(%p)\n", node2->exten->exten, node2->exten);
01646 #endif
01647          return node2->exten;
01648       }
01649    }
01650 #ifdef NEED_DEBUG_HERE
01651    ast_log(LOG_NOTICE,"CanMatch_exten returns NULL, match_char=%s\n", node->x);
01652 #endif
01653    return 0;
01654 }
01655 
01656 static struct ast_exten *trie_find_next_match(struct match_char *node)
01657 {
01658    struct match_char *m3;
01659    struct match_char *m4;
01660    struct ast_exten *e3;
01661 
01662    if (node && node->x[0] == '.' && !node->x[1]) { /* dot and ! will ALWAYS be next match in a matchmore */
01663       return node->exten;
01664    }
01665 
01666    if (node && node->x[0] == '!' && !node->x[1]) {
01667       return node->exten;
01668    }
01669 
01670    if (!node || !node->next_char) {
01671       return NULL;
01672    }
01673 
01674    m3 = node->next_char;
01675 
01676    if (m3->exten) {
01677       return m3->exten;
01678    }
01679    for (m4 = m3->alt_char; m4; m4 = m4->alt_char) {
01680       if (m4->exten) {
01681          return m4->exten;
01682       }
01683    }
01684    for (m4 = m3; m4; m4 = m4->alt_char) {
01685       e3 = trie_find_next_match(m3);
01686       if (e3) {
01687          return e3;
01688       }
01689    }
01690 
01691    return NULL;
01692 }
01693 
01694 #ifdef DEBUG_THIS
01695 static char *action2str(enum ext_match_t action)
01696 {
01697    switch (action) {
01698    case E_MATCH:
01699       return "MATCH";
01700    case E_CANMATCH:
01701       return "CANMATCH";
01702    case E_MATCHMORE:
01703       return "MATCHMORE";
01704    case E_FINDLABEL:
01705       return "FINDLABEL";
01706    case E_SPAWN:
01707       return "SPAWN";
01708    default:
01709       return "?ACTION?";
01710    }
01711 }
01712 
01713 #endif
01714 
01715 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)
01716 {
01717    struct match_char *p; /* note minimal stack storage requirements */
01718    struct ast_exten pattern = { .label = label };
01719 #ifdef DEBUG_THIS
01720    if (tree)
01721       ast_log(LOG_NOTICE,"new_find_extension called with %s on (sub)tree %s action=%s\n", str, tree->x, action2str(action));
01722    else
01723       ast_log(LOG_NOTICE,"new_find_extension called with %s on (sub)tree NULL action=%s\n", str, action2str(action));
01724 #endif
01725    for (p = tree; p; p = p->alt_char) {
01726       if (p->is_pattern) {
01727          if (p->x[0] == 'N') {
01728             if (p->x[1] == 0 && *str >= '2' && *str <= '9' ) {
01729 #define  NEW_MATCHER_CHK_MATCH          \
01730                if (p->exten && !(*(str + 1))) { /* if a shorter pattern matches along the way, might as well report it */             \
01731                   if (action == E_MATCH || action == E_SPAWN || action == E_FINDLABEL) { /* if in CANMATCH/MATCHMORE, don't let matches get in the way */   \
01732                      update_scoreboard(score, length + 1, spec + p->specificity, p->exten, 0, callerid, p->deleted, p);                 \
01733                      if (!p->deleted) {                                                                                           \
01734                         if (action == E_FINDLABEL) {                                                                             \
01735                            if (ast_hashtab_lookup(score->exten->peer_label_table, &pattern)) {                                  \
01736                               ast_debug(4, "Found label in preferred extension\n");                                            \
01737                               return;                                                                                          \
01738                            }                                                                                                    \
01739                         } else {                                                                                                 \
01740                            ast_debug(4, "returning an exact match-- first found-- %s\n", p->exten->exten);                       \
01741                            return; /* the first match, by definition, will be the best, because of the sorted tree */           \
01742                         }                                                                                                        \
01743                      }                                                                                                            \
01744                   }                                                                                                                \
01745                }
01746                
01747 #define  NEW_MATCHER_RECURSE             \
01748                if (p->next_char && (*(str + 1) || (p->next_char->x[0] == '/' && p->next_char->x[1] == 0)                 \
01749                                                 || p->next_char->x[0] == '!')) {                                          \
01750                   if (*(str + 1) || p->next_char->x[0] == '!') {                                                         \
01751                      new_find_extension(str + 1, score, p->next_char, length + 1, spec + p->specificity, callerid, label, action); \
01752                      if (score->exten)  {                                                                             \
01753                           ast_debug(4 ,"returning an exact match-- %s\n", score->exten->exten);                         \
01754                         return; /* the first match is all we need */                                                 \
01755                      }                                                                                    \
01756                   } else {                                                                                             \
01757                      new_find_extension("/", score, p->next_char, length + 1, spec + p->specificity, callerid, label, action);    \
01758                      if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) {      \
01759                           ast_debug(4,"returning a (can/more) match--- %s\n", score->exten ? score->exten->exten :     \
01760                                         "NULL");                                                                        \
01761                         return; /* the first match is all we need */                                                 \
01762                      }                                                                                    \
01763                   }                                                                                                    \
01764                } else if ((p->next_char || action == E_CANMATCH) && !*(str + 1)) {                                                                  \
01765                   score->canmatch = 1;                                                                                 \
01766                   score->canmatch_exten = get_canmatch_exten(p);                                                       \
01767                   if (action == E_CANMATCH || action == E_MATCHMORE) {                                                 \
01768                        ast_debug(4, "returning a canmatch/matchmore--- str=%s\n", str);                                  \
01769                      return;                                                                                          \
01770                   }                                                                                        \
01771                }
01772                
01773                NEW_MATCHER_CHK_MATCH;
01774                NEW_MATCHER_RECURSE;
01775             }
01776          } else if (p->x[0] == 'Z') {
01777             if (p->x[1] == 0 && *str >= '1' && *str <= '9' ) {
01778                NEW_MATCHER_CHK_MATCH;
01779                NEW_MATCHER_RECURSE;
01780             }
01781          } else if (p->x[0] == 'X') { 
01782             if (p->x[1] == 0 && *str >= '0' && *str <= '9' ) {
01783                NEW_MATCHER_CHK_MATCH;
01784                NEW_MATCHER_RECURSE;
01785             }
01786          } else if (p->x[0] == '.' && p->x[1] == 0) {
01787             /* how many chars will the . match against? */
01788             int i = 0;
01789             const char *str2 = str;
01790             while (*str2 && *str2 != '/') {
01791                str2++;
01792                i++;
01793             }
01794             if (p->exten && *str2 != '/') {
01795                update_scoreboard(score, length + i, spec + (i * p->specificity), p->exten, '.', callerid, p->deleted, p);
01796                if (score->exten) {
01797                   ast_debug(4,"return because scoreboard has a match with '/'--- %s\n", score->exten->exten);
01798                   return; /* the first match is all we need */
01799                }
01800             }
01801             if (p->next_char && p->next_char->x[0] == '/' && p->next_char->x[1] == 0) {
01802                new_find_extension("/", score, p->next_char, length + i, spec+(p->specificity*i), callerid, label, action);
01803                if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) {
01804                   ast_debug(4, "return because scoreboard has exact match OR CANMATCH/MATCHMORE & canmatch set--- %s\n", score->exten ? score->exten->exten : "NULL");
01805                   return; /* the first match is all we need */
01806                }
01807             }
01808          } else if (p->x[0] == '!' && p->x[1] == 0) {
01809             /* how many chars will the . match against? */
01810             int i = 1;
01811             const char *str2 = str;
01812             while (*str2 && *str2 != '/') {
01813                str2++;
01814                i++;
01815             }
01816             if (p->exten && *str2 != '/') {
01817                update_scoreboard(score, length + 1, spec + (p->specificity * i), p->exten, '!', callerid, p->deleted, p);
01818                if (score->exten) {
01819                   ast_debug(4, "return because scoreboard has a '!' match--- %s\n", score->exten->exten);
01820                   return; /* the first match is all we need */
01821                }
01822             }
01823             if (p->next_char && p->next_char->x[0] == '/' && p->next_char->x[1] == 0) {
01824                new_find_extension("/", score, p->next_char, length + i, spec + (p->specificity * i), callerid, label, action);
01825                if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) {
01826                   ast_debug(4, "return because scoreboard has exact match OR CANMATCH/MATCHMORE & canmatch set with '/' and '!'--- %s\n", score->exten ? score->exten->exten : "NULL");
01827                   return; /* the first match is all we need */
01828                }
01829             }
01830          } else if (p->x[0] == '/' && p->x[1] == 0) {
01831             /* the pattern in the tree includes the cid match! */
01832             if (p->next_char && callerid && *callerid) {
01833                new_find_extension(callerid, score, p->next_char, length + 1, spec, callerid, label, action);
01834                if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) {
01835                   ast_debug(4, "return because scoreboard has exact match OR CANMATCH/MATCHMORE & canmatch set with '/'--- %s\n", score->exten ? score->exten->exten : "NULL");
01836                   return; /* the first match is all we need */
01837                }
01838             }
01839          } else if (strchr(p->x, *str)) {
01840             ast_debug(4, "Nothing strange about this match\n");
01841             NEW_MATCHER_CHK_MATCH;
01842             NEW_MATCHER_RECURSE;
01843          }
01844       } else if (strchr(p->x, *str)) {
01845          ast_debug(4, "Nothing strange about this match\n");
01846          NEW_MATCHER_CHK_MATCH;
01847          NEW_MATCHER_RECURSE;
01848       }
01849    }
01850    ast_debug(4, "return at end of func\n");
01851 }
01852 
01853 /* the algorithm for forming the extension pattern tree is also a bit simple; you
01854  * traverse all the extensions in a context, and for each char of the extension,
01855  * you see if it exists in the tree; if it doesn't, you add it at the appropriate
01856  * spot. What more can I say? At the end of each exten, you cap it off by adding the
01857  * address of the extension involved. Duplicate patterns will be complained about.
01858  *
01859  * Ideally, this would be done for each context after it is created and fully
01860  * filled. It could be done as a finishing step after extensions.conf or .ael is
01861  * loaded, or it could be done when the first search is encountered. It should only
01862  * have to be done once, until the next unload or reload.
01863  *
01864  * I guess forming this pattern tree would be analogous to compiling a regex. Except
01865  * that a regex only handles 1 pattern, really. This trie holds any number
01866  * of patterns. Well, really, it **could** be considered a single pattern,
01867  * where the "|" (or) operator is allowed, I guess, in a way, sort of...
01868  */
01869 
01870 static struct match_char *already_in_tree(struct match_char *current, char *pat, int is_pattern)
01871 {
01872    struct match_char *t;
01873 
01874    if (!current) {
01875       return 0;
01876    }
01877 
01878    for (t = current; t; t = t->alt_char) {
01879       if (is_pattern == t->is_pattern && !strcmp(pat, t->x)) {/* uh, we may want to sort exploded [] contents to make matching easy */
01880          return t;
01881       }
01882    }
01883 
01884    return 0;
01885 }
01886 
01887 /* The first arg is the location of the tree ptr, or the
01888    address of the next_char ptr in the node, so we can mess
01889    with it, if we need to insert at the beginning of the list */
01890 
01891 static void insert_in_next_chars_alt_char_list(struct match_char **parent_ptr, struct match_char *node)
01892 {
01893    struct match_char *curr, *lcurr;
01894 
01895    /* insert node into the tree at "current", so the alt_char list from current is
01896       sorted in increasing value as you go to the leaves */
01897    if (!(*parent_ptr)) {
01898       *parent_ptr = node;
01899       return;
01900    }
01901 
01902    if ((*parent_ptr)->specificity > node->specificity) {
01903       /* insert at head */
01904       node->alt_char = (*parent_ptr);
01905       *parent_ptr = node;
01906       return;
01907    } 
01908 
01909    lcurr = *parent_ptr;
01910    for (curr = (*parent_ptr)->alt_char; curr; curr = curr->alt_char) {
01911       if (curr->specificity > node->specificity) {
01912          node->alt_char = curr;
01913          lcurr->alt_char = node;
01914          break;
01915       }
01916       lcurr = curr;
01917    }
01918 
01919    if (!curr) {
01920       lcurr->alt_char = node;
01921    }
01922 
01923 }
01924 
01925 struct pattern_node {
01926    /*! Pattern node specificity */
01927    int specif;
01928    /*! Pattern node match characters. */
01929    char buf[256];
01930 };
01931 
01932 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)
01933 {
01934    struct match_char *m;
01935 
01936    if (!(m = ast_calloc(1, sizeof(*m) + strlen(pattern->buf)))) {
01937       return NULL;
01938    }
01939 
01940    /* strcpy is safe here since we know its size and have allocated
01941     * just enough space for when we allocated m
01942     */
01943    strcpy(m->x, pattern->buf);
01944 
01945    /* the specificity scores are the same as used in the old
01946       pattern matcher. */
01947    m->is_pattern = is_pattern;
01948    if (pattern->specif == 1 && is_pattern && pattern->buf[0] == 'N') {
01949       m->specificity = 0x0832;
01950    } else if (pattern->specif == 1 && is_pattern && pattern->buf[0] == 'Z') {
01951       m->specificity = 0x0931;
01952    } else if (pattern->specif == 1 && is_pattern && pattern->buf[0] == 'X') {
01953       m->specificity = 0x0a30;
01954    } else if (pattern->specif == 1 && is_pattern && pattern->buf[0] == '.') {
01955       m->specificity = 0x18000;
01956    } else if (pattern->specif == 1 && is_pattern && pattern->buf[0] == '!') {
01957       m->specificity = 0x28000;
01958    } else {
01959       m->specificity = pattern->specif;
01960    }
01961 
01962    if (!con->pattern_tree) {
01963       insert_in_next_chars_alt_char_list(&con->pattern_tree, m);
01964    } else {
01965       if (already) { /* switch to the new regime (traversing vs appending)*/
01966          insert_in_next_chars_alt_char_list(nextcharptr, m);
01967       } else {
01968          insert_in_next_chars_alt_char_list(&current->next_char, m);
01969       }
01970    }
01971 
01972    return m;
01973 }
01974 
01975 /*!
01976  * \internal
01977  * \brief Extract the next exten pattern node.
01978  *
01979  * \param node Pattern node to fill.
01980  * \param src Next source character to read.
01981  * \param pattern TRUE if the exten is a pattern.
01982  * \param extenbuf Original exten buffer to use in diagnostic messages.
01983  *
01984  * \retval Ptr to next extenbuf pos to read.
01985  */
01986 static const char *get_pattern_node(struct pattern_node *node, const char *src, int pattern, const char *extenbuf)
01987 {
01988 #define INC_DST_OVERFLOW_CHECK                     \
01989    do {                                   \
01990       if (dst - node->buf < sizeof(node->buf) - 1) {  \
01991          ++dst;                              \
01992       } else {                            \
01993          overflow = 1;                       \
01994       }                                   \
01995    } while (0)
01996 
01997    node->specif = 0;
01998    node->buf[0] = '\0';
01999    while (*src) {
02000       if (*src == '[' && pattern) {
02001          char *dst = node->buf;
02002          const char *src_next;
02003          int length;
02004          int overflow = 0;
02005 
02006          /* get past the '[' */
02007          ++src;
02008          for (;;) {
02009             if (*src == '\\') {
02010                /* Escaped character. */
02011                ++src;
02012                if (*src == '[' || *src == '\\' || *src == '-' || *src == ']') {
02013                   *dst = *src++;
02014                   INC_DST_OVERFLOW_CHECK;
02015                }
02016             } else if (*src == '-') {
02017                unsigned char first;
02018                unsigned char last;
02019 
02020                src_next = src;
02021                first = *(src_next - 1);
02022                last = *++src_next;
02023 
02024                if (last == '\\') {
02025                   /* Escaped character. */
02026                   last = *++src_next;
02027                }
02028 
02029                /* Possible char range. */
02030                if (node->buf[0] && last) {
02031                   /* Expand the char range. */
02032                   while (++first <= last) {
02033                      *dst = first;
02034                      INC_DST_OVERFLOW_CHECK;
02035                   }
02036                   src = src_next + 1;
02037                } else {
02038                   /*
02039                    * There was no left or right char for the range.
02040                    * It is just a '-'.
02041                    */
02042                   *dst = *src++;
02043                   INC_DST_OVERFLOW_CHECK;
02044                }
02045             } else if (*src == '\0') {
02046                ast_log(LOG_WARNING,
02047                   "A matching ']' was not found for '[' in exten pattern '%s'\n",
02048                   extenbuf);
02049                break;
02050             } else if (*src == ']') {
02051                ++src;
02052                break;
02053             } else {
02054                *dst = *src++;
02055                INC_DST_OVERFLOW_CHECK;
02056             }
02057          }
02058          /* null terminate the exploded range */
02059          *dst = '\0';
02060 
02061          if (overflow) {
02062             ast_log(LOG_ERROR,
02063                "Expanded character set too large to deal with in exten pattern '%s'. Ignoring character set.\n",
02064                extenbuf);
02065             node->buf[0] = '\0';
02066             continue;
02067          }
02068 
02069          /* Sort the characters in character set. */
02070          length = strlen(node->buf);
02071          if (!length) {
02072             ast_log(LOG_WARNING, "Empty character set in exten pattern '%s'. Ignoring.\n",
02073                extenbuf);
02074             node->buf[0] = '\0';
02075             continue;
02076          }
02077          qsort(node->buf, length, 1, compare_char);
02078 
02079          /* Remove duplicate characters from character set. */
02080          dst = node->buf;
02081          src_next = node->buf;
02082          while (*src_next++) {
02083             if (*dst != *src_next) {
02084                *++dst = *src_next;
02085             }
02086          }
02087 
02088          length = strlen(node->buf);
02089          length <<= 8;
02090          node->specif = length | (unsigned char) node->buf[0];
02091          break;
02092       } else if (*src == '-') {
02093          /* Skip dashes in all extensions. */
02094          ++src;
02095       } else {
02096          if (*src == '\\') {
02097             /*
02098              * XXX The escape character here does not remove any special
02099              * meaning to characters except the '[', '\\', and '-'
02100              * characters since they are special only in this function.
02101              */
02102             node->buf[0] = *++src;
02103             if (!node->buf[0]) {
02104                break;
02105             }
02106          } else {
02107             node->buf[0] = *src;
02108             if (pattern) {
02109                /* make sure n,x,z patterns are canonicalized to N,X,Z */
02110                if (node->buf[0] == 'n') {
02111                   node->buf[0] = 'N';
02112                } else if (node->buf[0] == 'x') {
02113                   node->buf[0] = 'X';
02114                } else if (node->buf[0] == 'z') {
02115                   node->buf[0] = 'Z';
02116                }
02117             }
02118          }
02119          node->buf[1] = '\0';
02120          node->specif = 1;
02121          ++src;
02122          break;
02123       }
02124    }
02125    return src;
02126 
02127 #undef INC_DST_OVERFLOW_CHECK
02128 }
02129 
02130 static struct match_char *add_exten_to_pattern_tree(struct ast_context *con, struct ast_exten *e1, int findonly)
02131 {
02132    struct match_char *m1 = NULL;
02133    struct match_char *m2 = NULL;
02134    struct match_char **m0;
02135    const char *pos;
02136    int already;
02137    int pattern = 0;
02138    int idx_cur;
02139    int idx_next;
02140    char extenbuf[512];
02141    struct pattern_node pat_node[2];
02142 
02143    if (e1->matchcid) {
02144       if (sizeof(extenbuf) < strlen(e1->exten) + strlen(e1->cidmatch) + 2) {
02145          ast_log(LOG_ERROR,
02146             "The pattern %s/%s is too big to deal with: it will be ignored! Disaster!\n",
02147             e1->exten, e1->cidmatch);
02148          return NULL;
02149       }
02150       sprintf(extenbuf, "%s/%s", e1->exten, e1->cidmatch);/* Safe.  We just checked. */
02151    } else {
02152       ast_copy_string(extenbuf, e1->exten, sizeof(extenbuf));
02153    }
02154 
02155 #ifdef NEED_DEBUG
02156    ast_log(LOG_DEBUG, "Adding exten %s to tree\n", extenbuf);
02157 #endif
02158    m1 = con->pattern_tree; /* each pattern starts over at the root of the pattern tree */
02159    m0 = &con->pattern_tree;
02160    already = 1;
02161 
02162    pos = extenbuf;
02163    if (*pos == '_') {
02164       pattern = 1;
02165       ++pos;
02166    }
02167    idx_cur = 0;
02168    pos = get_pattern_node(&pat_node[idx_cur], pos, pattern, extenbuf);
02169    for (; pat_node[idx_cur].buf[0]; idx_cur = idx_next) {
02170       idx_next = (idx_cur + 1) % ARRAY_LEN(pat_node);
02171       pos = get_pattern_node(&pat_node[idx_next], pos, pattern, extenbuf);
02172 
02173       /* See about adding node to tree. */
02174       m2 = NULL;
02175       if (already && (m2 = already_in_tree(m1, pat_node[idx_cur].buf, pattern))
02176          && m2->next_char) {
02177          if (!pat_node[idx_next].buf[0]) {
02178             /*
02179              * This is the end of the pattern, but not the end of the tree.
02180              * Mark this node with the exten... a shorter pattern might win
02181              * if the longer one doesn't match.
02182              */
02183             if (findonly) {
02184                return m2;
02185             }
02186             if (m2->exten) {
02187                ast_log(LOG_WARNING, "Found duplicate exten. Had %s found %s\n",
02188                   m2->deleted ? "(deleted/invalid)" : m2->exten->exten, e1->exten);
02189             }
02190             m2->exten = e1;
02191             m2->deleted = 0;
02192          }
02193          m1 = m2->next_char; /* m1 points to the node to compare against */
02194          m0 = &m2->next_char; /* m0 points to the ptr that points to m1 */
02195       } else { /* not already OR not m2 OR nor m2->next_char */
02196          if (m2) {
02197             if (findonly) {
02198                return m2;
02199             }
02200             m1 = m2; /* while m0 stays the same */
02201          } else {
02202             if (findonly) {
02203                return m1;
02204             }
02205             m1 = add_pattern_node(con, m1, &pat_node[idx_cur], pattern, already, m0);
02206             if (!m1) { /* m1 is the node just added */
02207                return NULL;
02208             }
02209             m0 = &m1->next_char;
02210          }
02211          if (!pat_node[idx_next].buf[0]) {
02212             if (m2 && m2->exten) {
02213                ast_log(LOG_WARNING, "Found duplicate exten. Had %s found %s\n",
02214                   m2->deleted ? "(deleted/invalid)" : m2->exten->exten, e1->exten);
02215             }
02216             m1->deleted = 0;
02217             m1->exten = e1;
02218          }
02219 
02220          /* The 'already' variable is a mini-optimization designed to make it so that we
02221           * don't have to call already_in_tree when we know it will return false.
02222           */
02223          already = 0;
02224       }
02225    }
02226    return m1;
02227 }
02228 
02229 static void create_match_char_tree(struct ast_context *con)
02230 {
02231    struct ast_hashtab_iter *t1;
02232    struct ast_exten *e1;
02233 #ifdef NEED_DEBUG
02234    int biggest_bucket, resizes, numobjs, numbucks;
02235 
02236    ast_log(LOG_DEBUG,"Creating Extension Trie for context %s(%p)\n", con->name, con);
02237    ast_hashtab_get_stats(con->root_table, &biggest_bucket, &resizes, &numobjs, &numbucks);
02238    ast_log(LOG_DEBUG,"This tree has %d objects in %d bucket lists, longest list=%d objects, and has resized %d times\n",
02239          numobjs, numbucks, biggest_bucket, resizes);
02240 #endif
02241    t1 = ast_hashtab_start_traversal(con->root_table);
02242    while ((e1 = ast_hashtab_next(t1))) {
02243       if (e1->exten) {
02244          add_exten_to_pattern_tree(con, e1, 0);
02245       } else {
02246          ast_log(LOG_ERROR, "Attempt to create extension with no extension name.\n");
02247       }
02248    }
02249    ast_hashtab_end_traversal(t1);
02250 }
02251 
02252 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! */
02253 {
02254    /* destroy all the alternates */
02255    if (pattern_tree->alt_char) {
02256       destroy_pattern_tree(pattern_tree->alt_char);
02257       pattern_tree->alt_char = 0;
02258    }
02259    /* destroy all the nexts */
02260    if (pattern_tree->next_char) {
02261       destroy_pattern_tree(pattern_tree->next_char);
02262       pattern_tree->next_char = 0;
02263    }
02264    pattern_tree->exten = 0; /* never hurts to make sure there's no pointers laying around */
02265    ast_free(pattern_tree);
02266 }
02267 
02268 /*
02269  * Special characters used in patterns:
02270  * '_'   underscore is the leading character of a pattern.
02271  *    In other position it is treated as a regular char.
02272  * .  one or more of any character. Only allowed at the end of
02273  *    a pattern.
02274  * !  zero or more of anything. Also impacts the result of CANMATCH
02275  *    and MATCHMORE. Only allowed at the end of a pattern.
02276  *    In the core routine, ! causes a match with a return code of 2.
02277  *    In turn, depending on the search mode: (XXX check if it is implemented)
02278  *    - E_MATCH retuns 1 (does match)
02279  *    - E_MATCHMORE returns 0 (no match)
02280  *    - E_CANMATCH returns 1 (does match)
02281  *
02282  * /  should not appear as it is considered the separator of the CID info.
02283  *    XXX at the moment we may stop on this char.
02284  *
02285  * X Z N match ranges 0-9, 1-9, 2-9 respectively.
02286  * [  denotes the start of a set of character. Everything inside
02287  *    is considered literally. We can have ranges a-d and individual
02288  *    characters. A '[' and '-' can be considered literally if they
02289  *    are just before ']'.
02290  *    XXX currently there is no way to specify ']' in a range, nor \ is
02291  *    considered specially.
02292  *
02293  * When we compare a pattern with a specific extension, all characters in the extension
02294  * itself are considered literally.
02295  * XXX do we want to consider space as a separator as well ?
02296  * XXX do we want to consider the separators in non-patterns as well ?
02297  */
02298 
02299 /*!
02300  * \brief helper functions to sort extensions and patterns in the desired way,
02301  * so that more specific patterns appear first.
02302  *
02303  * ext_cmp1 compares individual characters (or sets of), returning
02304  * an int where bits 0-7 are the ASCII code of the first char in the set,
02305  * while bit 8-15 are the cardinality of the set minus 1.
02306  * This way more specific patterns (smaller cardinality) appear first.
02307  * Wildcards have a special value, so that we can directly compare them to
02308  * sets by subtracting the two values. In particular:
02309  *  0x000xx    one character, xx
02310  *  0x0yyxx    yy character set starting with xx
02311  *  0x10000    '.' (one or more of anything)
02312  *  0x20000    '!' (zero or more of anything)
02313  *  0x30000    NUL (end of string)
02314  *  0x40000    error in set.
02315  * The pointer to the string is advanced according to needs.
02316  * NOTES:
02317  * 1. the empty set is equivalent to NUL.
02318  * 2. given that a full set has always 0 as the first element,
02319  *    we could encode the special cases as 0xffXX where XX
02320  *    is 1, 2, 3, 4 as used above.
02321  */
02322 static int ext_cmp1(const char **p, unsigned char *bitwise)
02323 {
02324    int c, cmin = 0xff, count = 0;
02325    const char *end;
02326 
02327    /* load value and advance pointer */
02328    c = *(*p)++;
02329 
02330    /* always return unless we have a set of chars */
02331    switch (toupper(c)) {
02332    default: /* ordinary character */
02333       bitwise[c / 8] = 1 << (c % 8);
02334       return 0x0100 | (c & 0xff);
02335 
02336    case 'N':   /* 2..9 */
02337       bitwise[6] = 0xfc;
02338       bitwise[7] = 0x03;
02339       return 0x0800 | '2';
02340 
02341    case 'X':   /* 0..9 */
02342       bitwise[6] = 0xff;
02343       bitwise[7] = 0x03;
02344       return 0x0A00 | '0';
02345 
02346    case 'Z':   /* 1..9 */
02347       bitwise[6] = 0xfe;
02348       bitwise[7] = 0x03;
02349       return 0x0900 | '1';
02350 
02351    case '.':   /* wildcard */
02352       return 0x18000;
02353 
02354    case '!':   /* earlymatch */
02355       return 0x28000;   /* less specific than NULL */
02356 
02357    case '\0':  /* empty string */
02358       *p = NULL;
02359       return 0x30000;
02360 
02361    case '[':   /* pattern */
02362       break;
02363    }
02364    /* locate end of set */
02365    end = strchr(*p, ']');
02366 
02367    if (end == NULL) {
02368       ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n");
02369       return 0x40000;   /* XXX make this entry go last... */
02370    }
02371 
02372    for (; *p < end  ; (*p)++) {
02373       unsigned char c1, c2;   /* first-last char in range */
02374       c1 = (unsigned char)((*p)[0]);
02375       if (*p + 2 < end && (*p)[1] == '-') { /* this is a range */
02376          c2 = (unsigned char)((*p)[2]);
02377          *p += 2;    /* skip a total of 3 chars */
02378       } else {        /* individual character */
02379          c2 = c1;
02380       }
02381       if (c1 < cmin) {
02382          cmin = c1;
02383       }
02384       for (; c1 <= c2; c1++) {
02385          unsigned char mask = 1 << (c1 % 8);
02386          /*!\note If two patterns score the same, the one with the lowest
02387           * ascii values will compare as coming first. */
02388          /* Flag the character as included (used) and count it. */
02389          if (!(bitwise[ c1 / 8 ] & mask)) {
02390             bitwise[ c1 / 8 ] |= mask;
02391             count += 0x100;
02392          }
02393       }
02394    }
02395    (*p)++;
02396    return count == 0 ? 0x30000 : (count | cmin);
02397 }
02398 
02399 /*!
02400  * \brief the full routine to compare extensions in rules.
02401  */
02402 static int ext_cmp(const char *a, const char *b)
02403 {
02404    /* make sure non-patterns come first.
02405     * If a is not a pattern, it either comes first or
02406     * we do a more complex pattern comparison.
02407     */
02408    int ret = 0;
02409 
02410    if (a[0] != '_')
02411       return (b[0] == '_') ? -1 : strcmp(a, b);
02412 
02413    /* Now we know a is a pattern; if b is not, a comes first */
02414    if (b[0] != '_')
02415       return 1;
02416 
02417    /* ok we need full pattern sorting routine.
02418     * skip past the underscores */
02419    ++a; ++b;
02420    do {
02421       unsigned char bitwise[2][32] = { { 0, } };
02422       ret = ext_cmp1(&a, bitwise[0]) - ext_cmp1(&b, bitwise[1]);
02423       if (ret == 0) {
02424          /* Are the classes different, even though they score the same? */
02425          ret = memcmp(bitwise[0], bitwise[1], 32);
02426       }
02427    } while (!ret && a && b);
02428    if (ret == 0) {
02429       return 0;
02430    } else {
02431       return (ret > 0) ? 1 : -1;
02432    }
02433 }
02434 
02435 int ast_extension_cmp(const char *a, const char *b)
02436 {
02437    return ext_cmp(a, b);
02438 }
02439 
02440 /*!
02441  * \internal
02442  * \brief used ast_extension_{match|close}
02443  * mode is as follows:
02444  * E_MATCH     success only on exact match
02445  * E_MATCHMORE success only on partial match (i.e. leftover digits in pattern)
02446  * E_CANMATCH  either of the above.
02447  * \retval 0 on no-match
02448  * \retval 1 on match
02449  * \retval 2 on early match.
02450  */
02451 
02452 static int _extension_match_core(const char *pattern, const char *data, enum ext_match_t mode)
02453 {
02454    mode &= E_MATCH_MASK;   /* only consider the relevant bits */
02455 
02456 #ifdef NEED_DEBUG_HERE
02457    ast_log(LOG_NOTICE,"match core: pat: '%s', dat: '%s', mode=%d\n", pattern, data, (int)mode);
02458 #endif
02459 
02460    if ( (mode == E_MATCH) && (pattern[0] == '_') && (!strcasecmp(pattern,data)) ) { /* note: if this test is left out, then _x. will not match _x. !!! */
02461 #ifdef NEED_DEBUG_HERE
02462       ast_log(LOG_NOTICE,"return (1) - pattern matches pattern\n");
02463 #endif
02464       return 1;
02465    }
02466 
02467    if (pattern[0] != '_') { /* not a pattern, try exact or partial match */
02468       int ld = strlen(data), lp = strlen(pattern);
02469 
02470       if (lp < ld) {    /* pattern too short, cannot match */
02471 #ifdef NEED_DEBUG_HERE
02472          ast_log(LOG_NOTICE,"return (0) - pattern too short, cannot match\n");
02473 #endif
02474          return 0;
02475       }
02476       /* depending on the mode, accept full or partial match or both */
02477       if (mode == E_MATCH) {
02478 #ifdef NEED_DEBUG_HERE
02479          ast_log(LOG_NOTICE,"return (!strcmp(%s,%s) when mode== E_MATCH)\n", pattern, data);
02480 #endif
02481          return !strcmp(pattern, data); /* 1 on match, 0 on fail */
02482       }
02483       if (ld == 0 || !strncasecmp(pattern, data, ld)) { /* partial or full match */
02484 #ifdef NEED_DEBUG_HERE
02485          ast_log(LOG_NOTICE,"return (mode(%d) == E_MATCHMORE ? lp(%d) > ld(%d) : 1)\n", mode, lp, ld);
02486 #endif
02487          return (mode == E_MATCHMORE) ? lp > ld : 1; /* XXX should consider '!' and '/' ? */
02488       } else {
02489 #ifdef NEED_DEBUG_HERE
02490          ast_log(LOG_NOTICE,"return (0) when ld(%d) > 0 && pattern(%s) != data(%s)\n", ld, pattern, data);
02491 #endif
02492          return 0;
02493       }
02494    }
02495    pattern++; /* skip leading _ */
02496    /*
02497     * XXX below we stop at '/' which is a separator for the CID info. However we should
02498     * not store '/' in the pattern at all. When we insure it, we can remove the checks.
02499     */
02500    while (*data && *pattern && *pattern != '/') {
02501       const char *end;
02502 
02503       if (*data == '-') { /* skip '-' in data (just a separator) */
02504          data++;
02505          continue;
02506       }
02507       switch (toupper(*pattern)) {
02508       case '[':   /* a range */
02509          end = strchr(pattern+1, ']'); /* XXX should deal with escapes ? */
02510          if (end == NULL) {
02511             ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n");
02512             return 0;   /* unconditional failure */
02513          }
02514          for (pattern++; pattern != end; pattern++) {
02515             if (pattern+2 < end && pattern[1] == '-') { /* this is a range */
02516                if (*data >= pattern[0] && *data <= pattern[2])
02517                   break;   /* match found */
02518                else {
02519                   pattern += 2; /* skip a total of 3 chars */
02520                   continue;
02521                }
02522             } else if (*data == pattern[0])
02523                break;   /* match found */
02524          }
02525          if (pattern == end) {
02526 #ifdef NEED_DEBUG_HERE
02527             ast_log(LOG_NOTICE,"return (0) when pattern==end\n");
02528 #endif
02529             return 0;
02530          }
02531          pattern = end; /* skip and continue */
02532          break;
02533       case 'N':
02534          if (*data < '2' || *data > '9') {
02535 #ifdef NEED_DEBUG_HERE
02536             ast_log(LOG_NOTICE,"return (0) N is matched\n");
02537 #endif
02538             return 0;
02539          }
02540          break;
02541       case 'X':
02542          if (*data < '0' || *data > '9') {
02543 #ifdef NEED_DEBUG_HERE
02544             ast_log(LOG_NOTICE,"return (0) X is matched\n");
02545 #endif
02546             return 0;
02547          }
02548          break;
02549       case 'Z':
02550          if (*data < '1' || *data > '9') {
02551 #ifdef NEED_DEBUG_HERE
02552             ast_log(LOG_NOTICE,"return (0) Z is matched\n");
02553 #endif
02554             return 0;
02555          }
02556          break;
02557       case '.':   /* Must match, even with more digits */
02558 #ifdef NEED_DEBUG_HERE
02559          ast_log(LOG_NOTICE, "return (1) when '.' is matched\n");
02560 #endif
02561          return 1;
02562       case '!':   /* Early match */
02563 #ifdef NEED_DEBUG_HERE
02564          ast_log(LOG_NOTICE, "return (2) when '!' is matched\n");
02565 #endif
02566          return 2;
02567       case ' ':
02568       case '-':   /* Ignore these in patterns */
02569          data--; /* compensate the final data++ */
02570          break;
02571       default:
02572          if (*data != *pattern) {
02573 #ifdef NEED_DEBUG_HERE
02574             ast_log(LOG_NOTICE, "return (0) when *data(%c) != *pattern(%c)\n", *data, *pattern);
02575 #endif
02576             return 0;
02577          }
02578       }
02579       data++;
02580       pattern++;
02581    }
02582    if (*data)        /* data longer than pattern, no match */ {
02583 #ifdef NEED_DEBUG_HERE
02584       ast_log(LOG_NOTICE, "return (0) when data longer than pattern\n");
02585 #endif
02586       return 0;
02587    }
02588 
02589    /*
02590     * match so far, but ran off the end of the data.
02591     * Depending on what is next, determine match or not.
02592     */
02593    if (*pattern == '\0' || *pattern == '/') {   /* exact match */
02594 #ifdef NEED_DEBUG_HERE
02595       ast_log(LOG_NOTICE, "at end, return (%d) in 'exact match'\n", (mode==E_MATCHMORE) ? 0 : 1);
02596 #endif
02597       return (mode == E_MATCHMORE) ? 0 : 1;  /* this is a failure for E_MATCHMORE */
02598    } else if (*pattern == '!')   {     /* early match */
02599 #ifdef NEED_DEBUG_HERE
02600       ast_log(LOG_NOTICE, "at end, return (2) when '!' is matched\n");
02601 #endif
02602       return 2;
02603    } else {                /* partial match */
02604 #ifdef NEED_DEBUG_HERE
02605       ast_log(LOG_NOTICE, "at end, return (%d) which deps on E_MATCH\n", (mode == E_MATCH) ? 0 : 1);
02606 #endif
02607       return (mode == E_MATCH) ? 0 : 1;   /* this is a failure for E_MATCH */
02608    }
02609 }
02610 
02611 /*
02612  * Wrapper around _extension_match_core() to do performance measurement
02613  * using the profiling code.
02614  */
02615 static int extension_match_core(const char *pattern, const char *data, enum ext_match_t mode)
02616 {
02617    int i;
02618    static int prof_id = -2;   /* marker for 'unallocated' id */
02619    if (prof_id == -2) {
02620       prof_id = ast_add_profile("ext_match", 0);
02621    }
02622    ast_mark(prof_id, 1);
02623    i = _extension_match_core(ast_strlen_zero(pattern) ? "" : pattern, ast_strlen_zero(data) ? "" : data, mode);
02624    ast_mark(prof_id, 0);
02625    return i;
02626 }
02627 
02628 int ast_extension_match(const char *pattern, const char *data)
02629 {
02630    return extension_match_core(pattern, data, E_MATCH);
02631 }
02632 
02633 int ast_extension_close(const char *pattern, const char *data, int needmore)
02634 {
02635    if (needmore != E_MATCHMORE && needmore != E_CANMATCH)
02636       ast_log(LOG_WARNING, "invalid argument %d\n", needmore);
02637    return extension_match_core(pattern, data, needmore);
02638 }
02639 
02640 struct fake_context /* this struct is purely for matching in the hashtab */
02641 {
02642    ast_rwlock_t lock;
02643    struct ast_exten *root;
02644    struct ast_hashtab *root_table;
02645    struct match_char *pattern_tree;
02646    struct ast_context *next;
02647    struct ast_include *includes;
02648    struct ast_ignorepat *ignorepats;
02649    const char *registrar;
02650    int refcount;
02651    AST_LIST_HEAD_NOLOCK(, ast_sw) alts;
02652    ast_mutex_t macrolock;
02653    char name[256];
02654 };
02655 
02656 struct ast_context *ast_context_find(const char *name)
02657 {
02658    struct ast_context *tmp;
02659    struct fake_context item;
02660 
02661    if (!name) {
02662       return NULL;
02663    }
02664    ast_rdlock_contexts();
02665    if (contexts_table) {
02666       ast_copy_string(item.name, name, sizeof(item.name));
02667       tmp = ast_hashtab_lookup(contexts_table, &item);
02668    } else {
02669       tmp = NULL;
02670       while ((tmp = ast_walk_contexts(tmp))) {
02671          if (!strcasecmp(name, tmp->name)) {
02672             break;
02673          }
02674       }
02675    }
02676    ast_unlock_contexts();
02677    return tmp;
02678 }
02679 
02680 #define STATUS_NO_CONTEXT  1
02681 #define STATUS_NO_EXTENSION   2
02682 #define STATUS_NO_PRIORITY 3
02683 #define STATUS_NO_LABEL    4
02684 #define STATUS_SUCCESS     5
02685 
02686 static int matchcid(const char *cidpattern, const char *callerid)
02687 {
02688    /* If the Caller*ID pattern is empty, then we're matching NO Caller*ID, so
02689       failing to get a number should count as a match, otherwise not */
02690 
02691    if (ast_strlen_zero(callerid)) {
02692       return ast_strlen_zero(cidpattern) ? 1 : 0;
02693    }
02694 
02695    return ast_extension_match(cidpattern, callerid);
02696 }
02697 
02698 struct ast_exten *pbx_find_extension(struct ast_channel *chan,
02699    struct ast_context *bypass, struct pbx_find_info *q,
02700    const char *context, const char *exten, int priority,
02701    const char *label, const char *callerid, enum ext_match_t action)
02702 {
02703    int x, res;
02704    struct ast_context *tmp = NULL;
02705    struct ast_exten *e = NULL, *eroot = NULL;
02706    struct ast_include *i = NULL;
02707    struct ast_sw *sw = NULL;
02708    struct ast_exten pattern = {NULL, };
02709    struct scoreboard score = {0, };
02710    struct ast_str *tmpdata = NULL;
02711 
02712    pattern.label = label;
02713    pattern.priority = priority;
02714 #ifdef NEED_DEBUG_HERE
02715    ast_log(LOG_NOTICE, "Looking for cont/ext/prio/label/action = %s/%s/%d/%s/%d\n", context, exten, priority, label, (int) action);
02716 #endif
02717 
02718    /* Initialize status if appropriate */
02719    if (q->stacklen == 0) {
02720       q->status = STATUS_NO_CONTEXT;
02721       q->swo = NULL;
02722       q->data = NULL;
02723       q->foundcontext = NULL;
02724    } else if (q->stacklen >= AST_PBX_MAX_STACK) {
02725       ast_log(LOG_WARNING, "Maximum PBX stack exceeded\n");
02726       return NULL;
02727    }
02728 
02729    /* Check first to see if we've already been checked */
02730    for (x = 0; x < q->stacklen; x++) {
02731       if (!strcasecmp(q->incstack[x], context))
02732          return NULL;
02733    }
02734 
02735    if (bypass) { /* bypass means we only look there */
02736       tmp = bypass;
02737    } else {      /* look in contexts */
02738       tmp = find_context(context);
02739       if (!tmp) {
02740          return NULL;
02741       }
02742    }
02743 
02744    if (q->status < STATUS_NO_EXTENSION)
02745       q->status = STATUS_NO_EXTENSION;
02746 
02747    /* Do a search for matching extension */
02748 
02749    eroot = NULL;
02750    score.total_specificity = 0;
02751    score.exten = 0;
02752    score.total_length = 0;
02753    if (!tmp->pattern_tree && tmp->root_table) {
02754       create_match_char_tree(tmp);
02755 #ifdef NEED_DEBUG
02756       ast_log(LOG_DEBUG, "Tree Created in context %s:\n", context);
02757       log_match_char_tree(tmp->pattern_tree," ");
02758 #endif
02759    }
02760 #ifdef NEED_DEBUG
02761    ast_log(LOG_NOTICE, "The Trie we are searching in:\n");
02762    log_match_char_tree(tmp->pattern_tree, "::  ");
02763 #endif
02764 
02765    do {
02766       if (!ast_strlen_zero(overrideswitch)) {
02767          char *osw = ast_strdupa(overrideswitch), *name;
02768          struct ast_switch *asw;
02769          ast_switch_f *aswf = NULL;
02770          char *datap;
02771          int eval = 0;
02772 
02773          name = strsep(&osw, "/");
02774          asw = pbx_findswitch(name);
02775 
02776          if (!asw) {
02777             ast_log(LOG_WARNING, "No such switch '%s'\n", name);
02778             break;
02779          }
02780 
02781          if (osw && strchr(osw, '$')) {
02782             eval = 1;
02783          }
02784 
02785          if (eval && !(tmpdata = ast_str_thread_get(&switch_data, 512))) {
02786             ast_log(LOG_WARNING, "Can't evaluate overrideswitch?!");
02787             break;
02788          } else if (eval) {
02789             /* Substitute variables now */
02790             pbx_substitute_variables_helper(chan, osw, ast_str_buffer(tmpdata), ast_str_size(tmpdata));
02791             datap = ast_str_buffer(tmpdata);
02792          } else {
02793             datap = osw;
02794          }
02795 
02796          /* equivalent of extension_match_core() at the switch level */
02797          if (action == E_CANMATCH)
02798             aswf = asw->canmatch;
02799          else if (action == E_MATCHMORE)
02800             aswf = asw->matchmore;
02801          else /* action == E_MATCH */
02802             aswf = asw->exists;
02803          if (!aswf) {
02804             res = 0;
02805          } else {
02806             if (chan) {
02807                ast_autoservice_start(chan);
02808             }
02809             res = aswf(chan, context, exten, priority, callerid, datap);
02810             if (chan) {
02811                ast_autoservice_stop(chan);
02812             }
02813          }
02814          if (res) {  /* Got a match */
02815             q->swo = asw;
02816             q->data = datap;
02817             q->foundcontext = context;
02818             /* XXX keep status = STATUS_NO_CONTEXT ? */
02819             return NULL;
02820          }
02821       }
02822    } while (0);
02823 
02824    if (extenpatternmatchnew) {
02825       new_find_extension(exten, &score, tmp->pattern_tree, 0, 0, callerid, label, action);
02826       eroot = score.exten;
02827 
02828       if (score.last_char == '!' && action == E_MATCHMORE) {
02829          /* We match an extension ending in '!'.
02830           * The decision in this case is final and is NULL (no match).
02831           */
02832 #ifdef NEED_DEBUG_HERE
02833          ast_log(LOG_NOTICE,"Returning MATCHMORE NULL with exclamation point.\n");
02834 #endif
02835          return NULL;
02836       }
02837 
02838       if (!eroot && (action == E_CANMATCH || action == E_MATCHMORE) && score.canmatch_exten) {
02839          q->status = STATUS_SUCCESS;
02840 #ifdef NEED_DEBUG_HERE
02841          ast_log(LOG_NOTICE,"Returning CANMATCH exten %s\n", score.canmatch_exten->exten);
02842 #endif
02843          return score.canmatch_exten;
02844       }
02845 
02846       if ((action == E_MATCHMORE || action == E_CANMATCH)  && eroot) {
02847          if (score.node) {
02848             struct ast_exten *z = trie_find_next_match(score.node);
02849             if (z) {
02850 #ifdef NEED_DEBUG_HERE
02851                ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten %s\n", z->exten);
02852 #endif
02853             } else {
02854                if (score.canmatch_exten) {
02855 #ifdef NEED_DEBUG_HERE
02856                   ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE canmatchmatch exten %s(%p)\n", score.canmatch_exten->exten, score.canmatch_exten);
02857 #endif
02858                   return score.canmatch_exten;
02859                } else {
02860 #ifdef NEED_DEBUG_HERE
02861                   ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten NULL\n");
02862 #endif
02863                }
02864             }
02865             return z;
02866          }
02867 #ifdef NEED_DEBUG_HERE
02868          ast_log(LOG_NOTICE, "Returning CANMATCH/MATCHMORE NULL (no next_match)\n");
02869 #endif
02870          return NULL;  /* according to the code, complete matches are null matches in MATCHMORE mode */
02871       }
02872 
02873       if (eroot) {
02874          /* found entry, now look for the right priority */
02875          if (q->status < STATUS_NO_PRIORITY)
02876             q->status = STATUS_NO_PRIORITY;
02877          e = NULL;
02878          if (action == E_FINDLABEL && label ) {
02879             if (q->status < STATUS_NO_LABEL)
02880                q->status = STATUS_NO_LABEL;
02881             e = ast_hashtab_lookup(eroot->peer_label_table, &pattern);
02882          } else {
02883             e = ast_hashtab_lookup(eroot->peer_table, &pattern);
02884          }
02885          if (e) { /* found a valid match */
02886             q->status = STATUS_SUCCESS;
02887             q->foundcontext = context;
02888 #ifdef NEED_DEBUG_HERE
02889             ast_log(LOG_NOTICE,"Returning complete match of exten %s\n", e->exten);
02890 #endif
02891             return e;
02892          }
02893       }
02894    } else {   /* the old/current default exten pattern match algorithm */
02895 
02896       /* scan the list trying to match extension and CID */
02897       eroot = NULL;
02898       while ( (eroot = ast_walk_context_extensions(tmp, eroot)) ) {
02899          int match = extension_match_core(eroot->exten, exten, action);
02900          /* 0 on fail, 1 on match, 2 on earlymatch */
02901 
02902          if (!match || (eroot->matchcid && !matchcid(eroot->cidmatch, callerid)))
02903             continue;   /* keep trying */
02904          if (match == 2 && action == E_MATCHMORE) {
02905             /* We match an extension ending in '!'.
02906              * The decision in this case is final and is NULL (no match).
02907              */
02908             return NULL;
02909          }
02910          /* found entry, now look for the right priority */
02911          if (q->status < STATUS_NO_PRIORITY)
02912             q->status = STATUS_NO_PRIORITY;
02913          e = NULL;
02914          if (action == E_FINDLABEL && label ) {
02915             if (q->status < STATUS_NO_LABEL)
02916                q->status = STATUS_NO_LABEL;
02917             e = ast_hashtab_lookup(eroot->peer_label_table, &pattern);
02918          } else {
02919             e = ast_hashtab_lookup(eroot->peer_table, &pattern);
02920          }
02921          if (e) { /* found a valid match */
02922             q->status = STATUS_SUCCESS;
02923             q->foundcontext = context;
02924             return e;
02925          }
02926       }
02927    }
02928 
02929    /* Check alternative switches */
02930    AST_LIST_TRAVERSE(&tmp->alts, sw, list) {
02931       struct ast_switch *asw = pbx_findswitch(sw->name);
02932       ast_switch_f *aswf = NULL;
02933       char *datap;
02934 
02935       if (!asw) {
02936          ast_log(LOG_WARNING, "No such switch '%s'\n", sw->name);
02937          continue;
02938       }
02939 
02940       /* Substitute variables now */
02941       if (sw->eval) {
02942          if (!(tmpdata = ast_str_thread_get(&switch_data, 512))) {
02943             ast_log(LOG_WARNING, "Can't evaluate switch?!");
02944             continue;
02945          }
02946          pbx_substitute_variables_helper(chan, sw->data, ast_str_buffer(tmpdata), ast_str_size(tmpdata));
02947       }
02948 
02949       /* equivalent of extension_match_core() at the switch level */
02950       if (action == E_CANMATCH)
02951          aswf = asw->canmatch;
02952       else if (action == E_MATCHMORE)
02953          aswf = asw->matchmore;
02954       else /* action == E_MATCH */
02955          aswf = asw->exists;
02956       datap = sw->eval ? ast_str_buffer(tmpdata) : sw->data;
02957       if (!aswf)
02958          res = 0;
02959       else {
02960          if (chan)
02961             ast_autoservice_start(chan);
02962          res = aswf(chan, context, exten, priority, callerid, datap);
02963          if (chan)
02964             ast_autoservice_stop(chan);
02965       }
02966       if (res) {  /* Got a match */
02967          q->swo = asw;
02968          q->data = datap;
02969          q->foundcontext = context;
02970          /* XXX keep status = STATUS_NO_CONTEXT ? */
02971          return NULL;
02972       }
02973    }
02974    q->incstack[q->stacklen++] = tmp->name;   /* Setup the stack */
02975    /* Now try any includes we have in this context */
02976    for (i = tmp->includes; i; i = i->next) {
02977       if (include_valid(i)) {
02978          if ((e = pbx_find_extension(chan, bypass, q, i->rname, exten, priority, label, callerid, action))) {
02979 #ifdef NEED_DEBUG_HERE
02980             ast_log(LOG_NOTICE,"Returning recursive match of %s\n", e->exten);
02981 #endif
02982             return e;
02983          }
02984          if (q->swo)
02985             return NULL;
02986       }
02987    }
02988    return NULL;
02989 }
02990 
02991 /*!
02992  * \brief extract offset:length from variable name.
02993  * \return 1 if there is a offset:length part, which is
02994  * trimmed off (values go into variables)
02995  */
02996 static int parse_variable_name(char *var, int *offset, int *length, int *isfunc)
02997 {
02998    int parens = 0;
02999 
03000    *offset = 0;
03001    *length = INT_MAX;
03002    *isfunc = 0;
03003    for (; *var; var++) {
03004       if (*var == '(') {
03005          (*isfunc)++;
03006          parens++;
03007       } else if (*var == ')') {
03008          parens--;
03009       } else if (*var == ':' && parens == 0) {
03010          *var++ = '\0';
03011          sscanf(var, "%30d:%30d", offset, length);
03012          return 1; /* offset:length valid */
03013       }
03014    }
03015    return 0;
03016 }
03017 
03018 /*!
03019  *\brief takes a substring. It is ok to call with value == workspace.
03020  * \param value
03021  * \param offset < 0 means start from the end of the string and set the beginning
03022  *   to be that many characters back.
03023  * \param length is the length of the substring, a value less than 0 means to leave
03024  * that many off the end.
03025  * \param workspace
03026  * \param workspace_len
03027  * Always return a copy in workspace.
03028  */
03029 static char *substring(const char *value, int offset, int length, char *workspace, size_t workspace_len)
03030 {
03031    char *ret = workspace;
03032    int lr;  /* length of the input string after the copy */
03033 
03034    ast_copy_string(workspace, value, workspace_len); /* always make a copy */
03035 
03036    lr = strlen(ret); /* compute length after copy, so we never go out of the workspace */
03037 
03038    /* Quick check if no need to do anything */
03039    if (offset == 0 && length >= lr) /* take the whole string */
03040       return ret;
03041 
03042    if (offset < 0)   {  /* translate negative offset into positive ones */
03043       offset = lr + offset;
03044       if (offset < 0) /* If the negative offset was greater than the length of the string, just start at the beginning */
03045          offset = 0;
03046    }
03047 
03048    /* too large offset result in empty string so we know what to return */
03049    if (offset >= lr)
03050       return ret + lr;  /* the final '\0' */
03051 
03052    ret += offset;    /* move to the start position */
03053    if (length >= 0 && length < lr - offset)  /* truncate if necessary */
03054       ret[length] = '\0';
03055    else if (length < 0) {
03056       if (lr > offset - length) /* After we remove from the front and from the rear, is there anything left? */
03057          ret[lr + length - offset] = '\0';
03058       else
03059          ret[0] = '\0';
03060    }
03061 
03062    return ret;
03063 }
03064 
03065 static const char *ast_str_substring(struct ast_str *value, int offset, int length)
03066 {
03067    int lr;  /* length of the input string after the copy */
03068 
03069    lr = ast_str_strlen(value); /* compute length after copy, so we never go out of the workspace */
03070 
03071    /* Quick check if no need to do anything */
03072    if (offset == 0 && length >= lr) /* take the whole string */
03073       return ast_str_buffer(value);
03074 
03075    if (offset < 0)   {  /* translate negative offset into positive ones */
03076       offset = lr + offset;
03077       if (offset < 0) /* If the negative offset was greater than the length of the string, just start at the beginning */
03078          offset = 0;
03079    }
03080 
03081    /* too large offset result in empty string so we know what to return */
03082    if (offset >= lr) {
03083       ast_str_reset(value);
03084       return ast_str_buffer(value);
03085    }
03086 
03087    if (offset > 0) {
03088       /* Go ahead and chop off the beginning */
03089       memmove(ast_str_buffer(value), ast_str_buffer(value) + offset, ast_str_strlen(value) - offset + 1);
03090       lr -= offset;
03091    }
03092 
03093    if (length >= 0 && length < lr) {   /* truncate if necessary */
03094       char *tmp = ast_str_buffer(value);
03095       tmp[length] = '\0';
03096       ast_str_update(value);
03097    } else if (length < 0) {
03098       if (lr > -length) { /* After we remove from the front and from the rear, is there anything left? */
03099          char *tmp = ast_str_buffer(value);
03100          tmp[lr + length] = '\0';
03101          ast_str_update(value);
03102       } else {
03103          ast_str_reset(value);
03104       }
03105    } else {
03106       /* Nothing to do, but update the buffer length */
03107       ast_str_update(value);
03108    }
03109 
03110    return ast_str_buffer(value);
03111 }
03112 
03113 /*! \brief  Support for Asterisk built-in variables in the dialplan
03114 
03115 \note See also
03116    - \ref AstVar  Channel variables
03117    - \ref AstCauses The HANGUPCAUSE variable
03118  */
03119 void pbx_retrieve_variable(struct ast_channel *c, const char *var, char **ret, char *workspace, int workspacelen, struct varshead *headp)
03120 {
03121    struct ast_str *str = ast_str_create(16);
03122    const char *cret;
03123 
03124    cret = ast_str_retrieve_variable(&str, 0, c, headp, var);
03125    ast_copy_string(workspace, ast_str_buffer(str), workspacelen);
03126    *ret = cret ? workspace : NULL;
03127    ast_free(str);
03128 }
03129 
03130 const char *ast_str_retrieve_variable(struct ast_str **str, ssize_t maxlen, struct ast_channel *c, struct varshead *headp, const char *var)
03131 {
03132    const char not_found = '\0';
03133    char *tmpvar;
03134    const char *ret;
03135    const char *s; /* the result */
03136    int offset, length;
03137    int i, need_substring;
03138    struct varshead *places[2] = { headp, &globals };  /* list of places where we may look */
03139 
03140    if (c) {
03141       ast_channel_lock(c);
03142       places[0] = &c->varshead;
03143    }
03144    /*
03145     * Make a copy of var because parse_variable_name() modifies the string.
03146     * Then if called directly, we might need to run substring() on the result;
03147     * remember this for later in 'need_substring', 'offset' and 'length'
03148     */
03149    tmpvar = ast_strdupa(var); /* parse_variable_name modifies the string */
03150    need_substring = parse_variable_name(tmpvar, &offset, &length, &i /* ignored */);
03151 
03152    /*
03153     * Look first into predefined variables, then into variable lists.
03154     * Variable 's' points to the result, according to the following rules:
03155     * s == &not_found (set at the beginning) means that we did not find a
03156     * matching variable and need to look into more places.
03157     * If s != &not_found, s is a valid result string as follows:
03158     * s = NULL if the variable does not have a value;
03159     * you typically do this when looking for an unset predefined variable.
03160     * s = workspace if the result has been assembled there;
03161     * typically done when the result is built e.g. with an snprintf(),
03162     * so we don't need to do an additional copy.
03163     * s != workspace in case we have a string, that needs to be copied
03164     * (the ast_copy_string is done once for all at the end).
03165     * Typically done when the result is already available in some string.
03166     */
03167    s = &not_found;   /* default value */
03168    if (c) { /* This group requires a valid channel */
03169       /* Names with common parts are looked up a piece at a time using strncmp. */
03170       if (!strncmp(var, "CALL", 4)) {
03171          if (!strncmp(var + 4, "ING", 3)) {
03172             if (!strcmp(var + 7, "PRES")) {        /* CALLINGPRES */
03173                ast_str_set(str, maxlen, "%d",
03174                   ast_party_id_presentation(&c->caller.id));
03175                s = ast_str_buffer(*str);
03176             } else if (!strcmp(var + 7, "ANI2")) {    /* CALLINGANI2 */
03177                ast_str_set(str, maxlen, "%d", c->caller.ani2);
03178                s = ast_str_buffer(*str);
03179             } else if (!strcmp(var + 7, "TON")) {     /* CALLINGTON */
03180                ast_str_set(str, maxlen, "%d", c->caller.id.number.plan);
03181                s = ast_str_buffer(*str);
03182             } else if (!strcmp(var + 7, "TNS")) {     /* CALLINGTNS */
03183                ast_str_set(str, maxlen, "%d", c->dialed.transit_network_select);
03184                s = ast_str_buffer(*str);
03185             }
03186          }
03187       } else if (!strcmp(var, "HINT")) {
03188          s = ast_str_get_hint(str, maxlen, NULL, 0, c, c->context, c->exten) ? ast_str_buffer(*str) : NULL;
03189       } else if (!strcmp(var, "HINTNAME")) {
03190          s = ast_str_get_hint(NULL, 0, str, maxlen, c, c->context, c->exten) ? ast_str_buffer(*str) : NULL;
03191       } else if (!strcmp(var, "EXTEN")) {
03192          s = c->exten;
03193       } else if (!strcmp(var, "CONTEXT")) {
03194          s = c->context;
03195       } else if (!strcmp(var, "PRIORITY")) {
03196          ast_str_set(str, maxlen, "%d", c->priority);
03197          s = ast_str_buffer(*str);
03198       } else if (!strcmp(var, "CHANNEL")) {
03199          s = c->name;
03200       } else if (!strcmp(var, "UNIQUEID")) {
03201          s = c->uniqueid;
03202       } else if (!strcmp(var, "HANGUPCAUSE")) {
03203          ast_str_set(str, maxlen, "%d", c->hangupcause);
03204          s = ast_str_buffer(*str);
03205       }
03206    }
03207    if (s == &not_found) { /* look for more */
03208       if (!strcmp(var, "EPOCH")) {
03209          ast_str_set(str, maxlen, "%u", (int) time(NULL));
03210          s = ast_str_buffer(*str);
03211       } else if (!strcmp(var, "SYSTEMNAME")) {
03212          s = ast_config_AST_SYSTEM_NAME;
03213       } else if (!strcmp(var, "ENTITYID")) {
03214          char workspace[20];
03215          ast_eid_to_str(workspace, sizeof(workspace), &ast_eid_default);
03216          s = workspace;
03217       }
03218    }
03219    /* if not found, look into chanvars or global vars */
03220    for (i = 0; s == &not_found && i < ARRAY_LEN(places); i++) {
03221       struct ast_var_t *variables;
03222       if (!places[i])
03223          continue;
03224       if (places[i] == &globals)
03225          ast_rwlock_rdlock(&globalslock);
03226       AST_LIST_TRAVERSE(places[i], variables, entries) {
03227          if (!strcasecmp(ast_var_name(variables), var)) {
03228             s = ast_var_value(variables);
03229             break;
03230          }
03231       }
03232       if (places[i] == &globals)
03233          ast_rwlock_unlock(&globalslock);
03234    }
03235    if (s == &not_found || s == NULL) {
03236       ast_debug(5, "Result of '%s' is NULL\n", var);
03237       ret = NULL;
03238    } else {
03239       ast_debug(5, "Result of '%s' is '%s'\n", var, s);
03240       if (s != ast_str_buffer(*str)) {
03241          ast_str_set(str, maxlen, "%s", s);
03242       }
03243       ret = ast_str_buffer(*str);
03244       if (need_substring) {
03245          ret = ast_str_substring(*str, offset, length);
03246          ast_debug(2, "Final result of '%s' is '%s'\n", var, ret);
03247       }
03248    }
03249 
03250    if (c) {
03251       ast_channel_unlock(c);
03252    }
03253    return ret;
03254 }
03255 
03256 static void exception_store_free(void *data)
03257 {
03258    struct pbx_exception *exception = data;
03259    ast_string_field_free_memory(exception);
03260    ast_free(exception);
03261 }
03262 
03263 static struct ast_datastore_info exception_store_info = {
03264    .type = "EXCEPTION",
03265    .destroy = exception_store_free,
03266 };
03267 
03268 /*!
03269  * \internal
03270  * \brief Set the PBX to execute the exception extension.
03271  *
03272  * \param chan Channel to raise the exception on.
03273  * \param reason Reason exception is raised.
03274  * \param priority Dialplan priority to set.
03275  *
03276  * \retval 0 on success.
03277  * \retval -1 on error.
03278  */
03279 static int raise_exception(struct ast_channel *chan, const char *reason, int priority)
03280 {
03281    struct ast_datastore *ds = ast_channel_datastore_find(chan, &exception_store_info, NULL);
03282    struct pbx_exception *exception = NULL;
03283 
03284    if (!ds) {
03285       ds = ast_datastore_alloc(&exception_store_info, NULL);
03286       if (!ds)
03287          return -1;
03288       if (!(exception = ast_calloc_with_stringfields(1, struct pbx_exception, 128))) {
03289          ast_datastore_free(ds);
03290          return -1;
03291       }
03292       ds->data = exception;
03293       ast_channel_datastore_add(chan, ds);
03294    } else
03295       exception = ds->data;
03296 
03297    ast_string_field_set(exception, reason, reason);
03298    ast_string_field_set(exception, context, chan->context);
03299    ast_string_field_set(exception, exten, chan->exten);
03300    exception->priority = chan->priority;
03301    set_ext_pri(chan, "e", priority);
03302    return 0;
03303 }
03304 
03305 int pbx_builtin_raise_exception(struct ast_channel *chan, const char *reason)
03306 {
03307    /* Priority will become 1, next time through the AUTOLOOP */
03308    return raise_exception(chan, reason, 0);
03309 }
03310 
03311 static int acf_exception_read(struct ast_channel *chan, const char *name, char *data, char *buf, size_t buflen)
03312 {
03313    struct ast_datastore *ds = ast_channel_datastore_find(chan, &exception_store_info, NULL);
03314    struct pbx_exception *exception = NULL;
03315    if (!ds || !ds->data)
03316       return -1;
03317    exception = ds->data;
03318    if (!strcasecmp(data, "REASON"))
03319       ast_copy_string(buf, exception->reason, buflen);
03320    else if (!strcasecmp(data, "CONTEXT"))
03321       ast_copy_string(buf, exception->context, buflen);
03322    else if (!strncasecmp(data, "EXTEN", 5))
03323       ast_copy_string(buf, exception->exten, buflen);
03324    else if (!strcasecmp(data, "PRIORITY"))
03325       snprintf(buf, buflen, "%d", exception->priority);
03326    else
03327       return -1;
03328    return 0;
03329 }
03330 
03331 static struct ast_custom_function exception_function = {
03332    .name = "EXCEPTION",
03333    .read = acf_exception_read,
03334 };
03335 
03336 static char *handle_show_functions(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
03337 {
03338    struct ast_custom_function *acf;
03339    int count_acf = 0;
03340    int like = 0;
03341 
03342    switch (cmd) {
03343    case CLI_INIT:
03344       e->command = "core show functions [like]";
03345       e->usage =
03346          "Usage: core show functions [like <text>]\n"
03347          "       List builtin functions, optionally only those matching a given string\n";
03348       return NULL;
03349    case CLI_GENERATE:
03350       return NULL;
03351    }
03352 
03353    if (a->argc == 5 && (!strcmp(a->argv[3], "like")) ) {
03354       like = 1;
03355    } else if (a->argc != 3) {
03356       return CLI_SHOWUSAGE;
03357    }
03358 
03359    ast_cli(a->fd, "%s Custom Functions:\n--------------------------------------------------------------------------------\n", like ? "Matching" : "Installed");
03360 
03361    AST_RWLIST_RDLOCK(&acf_root);
03362    AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) {
03363       if (!like || strstr(acf->name, a->argv[4])) {
03364          count_acf++;
03365          ast_cli(a->fd, "%-20.20s  %-35.35s  %s\n",
03366             S_OR(acf->name, ""),
03367             S_OR(acf->syntax, ""),
03368             S_OR(acf->synopsis, ""));
03369       }
03370    }
03371    AST_RWLIST_UNLOCK(&acf_root);
03372 
03373    ast_cli(a->fd, "%d %scustom functions installed.\n", count_acf, like ? "matching " : "");
03374 
03375    return CLI_SUCCESS;
03376 }
03377 
03378 static char *handle_show_function(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
03379 {
03380    struct ast_custom_function *acf;
03381    /* Maximum number of characters added by terminal coloring is 22 */
03382    char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40], argtitle[40], seealsotitle[40];
03383    char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL, *seealso = NULL;
03384    char stxtitle[40], *syntax = NULL, *arguments = NULL;
03385    int syntax_size, description_size, synopsis_size, arguments_size, seealso_size;
03386    char *ret = NULL;
03387    int which = 0;
03388    int wordlen;
03389 
03390    switch (cmd) {
03391    case CLI_INIT:
03392       e->command = "core show function";
03393       e->usage =
03394          "Usage: core show function <function>\n"
03395          "       Describe a particular dialplan function.\n";
03396       return NULL;
03397    case CLI_GENERATE:
03398       wordlen = strlen(a->word);
03399       /* case-insensitive for convenience in this 'complete' function */
03400       AST_RWLIST_RDLOCK(&acf_root);
03401       AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) {
03402          if (!strncasecmp(a->word, acf->name, wordlen) && ++which > a->n) {
03403             ret = ast_strdup(acf->name);
03404             break;
03405          }
03406       }
03407       AST_RWLIST_UNLOCK(&acf_root);
03408 
03409       return ret;
03410    }
03411 
03412    if (a->argc < 4) {
03413       return CLI_SHOWUSAGE;
03414    }
03415 
03416    if (!(acf = ast_custom_function_find(a->argv[3]))) {
03417       ast_cli(a->fd, "No function by that name registered.\n");
03418       return CLI_FAILURE;
03419    }
03420 
03421    syntax_size = strlen(S_OR(acf->syntax, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
03422    if (!(syntax = ast_malloc(syntax_size))) {
03423       ast_cli(a->fd, "Memory allocation failure!\n");
03424       return CLI_FAILURE;
03425    }
03426 
03427    snprintf(info, sizeof(info), "\n  -= Info about function '%s' =- \n\n", acf->name);
03428    term_color(infotitle, info, COLOR_MAGENTA, 0, sizeof(infotitle));
03429    term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40);
03430    term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40);
03431    term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, 40);
03432    term_color(argtitle, "[Arguments]\n", COLOR_MAGENTA, 0, 40);
03433    term_color(seealsotitle, "[See Also]\n", COLOR_MAGENTA, 0, 40);
03434    term_color(syntax, S_OR(acf->syntax, "Not available"), COLOR_CYAN, 0, syntax_size);
03435 #ifdef AST_XML_DOCS
03436    if (acf->docsrc == AST_XML_DOC) {
03437       arguments = ast_xmldoc_printable(S_OR(acf->arguments, "Not available"), 1);
03438       synopsis = ast_xmldoc_printable(S_OR(acf->synopsis, "Not available"), 1);
03439       description = ast_xmldoc_printable(S_OR(acf->desc, "Not available"), 1);
03440       seealso = ast_xmldoc_printable(S_OR(acf->seealso, "Not available"), 1);
03441    } else
03442 #endif
03443    {
03444       synopsis_size = strlen(S_OR(acf->synopsis, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
03445       synopsis = ast_malloc(synopsis_size);
03446 
03447       description_size = strlen(S_OR(acf->desc, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
03448       description = ast_malloc(description_size);
03449 
03450       arguments_size = strlen(S_OR(acf->arguments, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
03451       arguments = ast_malloc(arguments_size);
03452 
03453       seealso_size = strlen(S_OR(acf->seealso, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
03454       seealso = ast_malloc(seealso_size);
03455 
03456       /* check allocated memory. */
03457       if (!synopsis || !description || !arguments || !seealso) {
03458          ast_free(synopsis);
03459          ast_free(description);
03460          ast_free(arguments);
03461          ast_free(seealso);
03462          ast_free(syntax);
03463          return CLI_FAILURE;
03464       }
03465 
03466       term_color(arguments, S_OR(acf->arguments, "Not available"), COLOR_CYAN, 0, arguments_size);
03467       term_color(synopsis, S_OR(acf->synopsis, "Not available"), COLOR_CYAN, 0, synopsis_size);
03468       term_color(description, S_OR(acf->desc, "Not available"), COLOR_CYAN, 0, description_size);
03469       term_color(seealso, S_OR(acf->seealso, "Not available"), COLOR_CYAN, 0, seealso_size);
03470    }
03471 
03472    ast_cli(a->fd, "%s%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n",
03473          infotitle, syntitle, synopsis, destitle, description,
03474          stxtitle, syntax, argtitle, arguments, seealsotitle, seealso);
03475 
03476    ast_free(arguments);
03477    ast_free(synopsis);
03478    ast_free(description);
03479    ast_free(seealso);
03480    ast_free(syntax);
03481 
03482    return CLI_SUCCESS;
03483 }
03484 
03485 struct ast_custom_function *ast_custom_function_find(const char *name)
03486 {
03487    struct ast_custom_function *acf = NULL;
03488 
03489    AST_RWLIST_RDLOCK(&acf_root);
03490    AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) {
03491       if (!strcmp(name, acf->name))
03492          break;
03493    }
03494    AST_RWLIST_UNLOCK(&acf_root);
03495 
03496    return acf;
03497 }
03498 
03499 int ast_custom_function_unregister(struct ast_custom_function *acf)
03500 {
03501    struct ast_custom_function *cur;
03502 
03503    if (!acf) {
03504       return -1;
03505    }
03506 
03507    AST_RWLIST_WRLOCK(&acf_root);
03508    if ((cur = AST_RWLIST_REMOVE(&acf_root, acf, acflist))) {
03509 #ifdef AST_XML_DOCS
03510       if (cur->docsrc == AST_XML_DOC) {
03511          ast_string_field_free_memory(acf);
03512       }
03513 #endif
03514       ast_verb(2, "Unregistered custom function %s\n", cur->name);
03515    }
03516    AST_RWLIST_UNLOCK(&acf_root);
03517 
03518    return cur ? 0 : -1;
03519 }
03520 
03521 /*! \internal
03522  *  \brief Retrieve the XML documentation of a specified ast_custom_function,
03523  *         and populate ast_custom_function string fields.
03524  *  \param acf ast_custom_function structure with empty 'desc' and 'synopsis'
03525  *             but with a function 'name'.
03526  *  \retval -1 On error.
03527  *  \retval 0 On succes.
03528  */
03529 static int acf_retrieve_docs(struct ast_custom_function *acf)
03530 {
03531 #ifdef AST_XML_DOCS
03532    char *tmpxml;
03533 
03534    /* Let's try to find it in the Documentation XML */
03535    if (!ast_strlen_zero(acf->desc) || !ast_strlen_zero(acf->synopsis)) {
03536       return 0;
03537    }
03538 
03539    if (ast_string_field_init(acf, 128)) {
03540       return -1;
03541    }
03542 
03543    /* load synopsis */
03544    tmpxml = ast_xmldoc_build_synopsis("function", acf->name, ast_module_name(acf->mod));
03545    ast_string_field_set(acf, synopsis, tmpxml);
03546    ast_free(tmpxml);
03547 
03548    /* load description */
03549    tmpxml = ast_xmldoc_build_description("function", acf->name, ast_module_name(acf->mod));
03550    ast_string_field_set(acf, desc, tmpxml);
03551    ast_free(tmpxml);
03552 
03553    /* load syntax */
03554    tmpxml = ast_xmldoc_build_syntax("function", acf->name, ast_module_name(acf->mod));
03555    ast_string_field_set(acf, syntax, tmpxml);
03556    ast_free(tmpxml);
03557 
03558    /* load arguments */
03559    tmpxml = ast_xmldoc_build_arguments("function", acf->name, ast_module_name(acf->mod));
03560    ast_string_field_set(acf, arguments, tmpxml);
03561    ast_free(tmpxml);
03562 
03563    /* load seealso */
03564    tmpxml = ast_xmldoc_build_seealso("function", acf->name, ast_module_name(acf->mod));
03565    ast_string_field_set(acf, seealso, tmpxml);
03566    ast_free(tmpxml);
03567 
03568    acf->docsrc = AST_XML_DOC;
03569 #endif
03570 
03571    return 0;
03572 }
03573 
03574 int __ast_custom_function_register(struct ast_custom_function *acf, struct ast_module *mod)
03575 {
03576    struct ast_custom_function *cur;
03577    char tmps[80];
03578 
03579    if (!acf) {
03580       return -1;
03581    }
03582 
03583    acf->mod = mod;
03584 #ifdef AST_XML_DOCS
03585    acf->docsrc = AST_STATIC_DOC;
03586 #endif
03587 
03588    if (acf_retrieve_docs(acf)) {
03589       return -1;
03590    }
03591 
03592    AST_RWLIST_WRLOCK(&acf_root);
03593 
03594    AST_RWLIST_TRAVERSE(&acf_root, cur, acflist) {
03595       if (!strcmp(acf->name, cur->name)) {
03596          ast_log(LOG_ERROR, "Function %s already registered.\n", acf->name);
03597          AST_RWLIST_UNLOCK(&acf_root);
03598          return -1;
03599       }
03600    }
03601 
03602    /* Store in alphabetical order */
03603    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&acf_root, cur, acflist) {
03604       if (strcasecmp(acf->name, cur->name) < 0) {
03605          AST_RWLIST_INSERT_BEFORE_CURRENT(acf, acflist);
03606          break;
03607       }
03608    }
03609    AST_RWLIST_TRAVERSE_SAFE_END;
03610 
03611    if (!cur) {
03612       AST_RWLIST_INSERT_TAIL(&acf_root, acf, acflist);
03613    }
03614 
03615    AST_RWLIST_UNLOCK(&acf_root);
03616 
03617    ast_verb(2, "Registered custom function '%s'\n", term_color(tmps, acf->name, COLOR_BRCYAN, 0, sizeof(tmps)));
03618 
03619    return 0;
03620 }
03621 
03622 /*! \brief return a pointer to the arguments of the function,
03623  * and terminates the function name with '\\0'
03624  */
03625 static char *func_args(char *function)
03626 {
03627    char *args = strchr(function, '(');
03628 
03629    if (!args) {
03630       ast_log(LOG_WARNING, "Function '%s' doesn't contain parentheses.  Assuming null argument.\n", function);
03631    } else {
03632       char *p;
03633       *args++ = '\0';
03634       if ((p = strrchr(args, ')'))) {
03635          *p = '\0';
03636       } else {
03637          ast_log(LOG_WARNING, "Can't find trailing parenthesis for function '%s(%s'?\n", function, args);
03638       }
03639    }
03640    return args;
03641 }
03642 
03643 int ast_func_read(struct ast_channel *chan, const char *function, char *workspace, size_t len)
03644 {
03645    char *copy = ast_strdupa(function);
03646    char *args = func_args(copy);
03647    struct ast_custom_function *acfptr = ast_custom_function_find(copy);
03648    int res;
03649    struct ast_module_user *u = NULL;
03650 
03651    if (acfptr == NULL) {
03652       ast_log(LOG_ERROR, "Function %s not registered\n", copy);
03653    } else if (!acfptr->read && !acfptr->read2) {
03654       ast_log(LOG_ERROR, "Function %s cannot be read\n", copy);
03655    } else if (acfptr->read) {
03656       if (acfptr->mod) {
03657          u = __ast_module_user_add(acfptr->mod, chan);
03658       }
03659       res = acfptr->read(chan, copy, args, workspace, len);
03660       if (acfptr->mod && u) {
03661          __ast_module_user_remove(acfptr->mod, u);
03662       }
03663       return res;
03664    } else {
03665       struct ast_str *str = ast_str_create(16);
03666       if (acfptr->mod) {
03667          u = __ast_module_user_add(acfptr->mod, chan);
03668       }
03669       res = acfptr->read2(chan, copy, args, &str, 0);
03670       if (acfptr->mod && u) {
03671          __ast_module_user_remove(acfptr->mod, u);
03672       }
03673       ast_copy_string(workspace, ast_str_buffer(str), len > ast_str_size(str) ? ast_str_size(str) : len);
03674       ast_free(str);
03675       return res;
03676    }
03677    return -1;
03678 }
03679 
03680 int ast_func_read2(struct ast_channel *chan, const char *function, struct ast_str **str, ssize_t maxlen)
03681 {
03682    char *copy = ast_strdupa(function);
03683    char *args = func_args(copy);
03684    struct ast_custom_function *acfptr = ast_custom_function_find(copy);
03685    int res;
03686    struct ast_module_user *u = NULL;
03687 
03688    if (acfptr == NULL) {
03689       ast_log(LOG_ERROR, "Function %s not registered\n", copy);
03690    } else if (!acfptr->read && !acfptr->read2) {
03691       ast_log(LOG_ERROR, "Function %s cannot be read\n", copy);
03692    } else {
03693       if (acfptr->mod) {
03694          u = __ast_module_user_add(acfptr->mod, chan);
03695       }
03696       ast_str_reset(*str);
03697       if (acfptr->read2) {
03698          /* ast_str enabled */
03699          res = acfptr->read2(chan, copy, args, str, maxlen);
03700       } else {
03701          /* Legacy function pointer, allocate buffer for result */
03702          int maxsize = ast_str_size(*str);
03703          if (maxlen > -1) {
03704             if (maxlen == 0) {
03705                if (acfptr->read_max) {
03706                   maxsize = acfptr->read_max;
03707                } else {
03708                   maxsize = VAR_BUF_SIZE;
03709                }
03710             } else {
03711                maxsize = maxlen;
03712             }
03713             ast_str_make_space(str, maxsize);
03714          }
03715          res = acfptr->read(chan, copy, args, ast_str_buffer(*str), maxsize);
03716       }
03717       if (acfptr->mod && u) {
03718          __ast_module_user_remove(acfptr->mod, u);
03719       }
03720       return res;
03721    }
03722    return -1;
03723 }
03724 
03725 int ast_func_write(struct ast_channel *chan, const char *function, const char *value)
03726 {
03727    char *copy = ast_strdupa(function);
03728    char *args = func_args(copy);
03729    struct ast_custom_function *acfptr = ast_custom_function_find(copy);
03730 
03731    if (acfptr == NULL)
03732       ast_log(LOG_ERROR, "Function %s not registered\n", copy);
03733    else if (!acfptr->write)
03734       ast_log(LOG_ERROR, "Function %s cannot be written to\n", copy);
03735    else {
03736       int res;
03737       struct ast_module_user *u = NULL;
03738       if (acfptr->mod)
03739          u = __ast_module_user_add(acfptr->mod, chan);
03740       res = acfptr->write(chan, copy, args, value);
03741       if (acfptr->mod && u)
03742          __ast_module_user_remove(acfptr->mod, u);
03743       return res;
03744    }
03745 
03746    return -1;
03747 }
03748 
03749 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)
03750 {
03751    /* Substitutes variables into buf, based on string templ */
03752    char *cp4 = NULL;
03753    const char *tmp, *whereweare;
03754    int orig_size = 0;
03755    int offset, offset2, isfunction;
03756    const char *nextvar, *nextexp, *nextthing;
03757    const char *vars, *vare;
03758    char *finalvars;
03759    int pos, brackets, needsub, len;
03760    struct ast_str *substr1 = ast_str_create(16), *substr2 = NULL, *substr3 = ast_str_create(16);
03761 
03762    ast_str_reset(*buf);
03763    whereweare = tmp = templ;
03764    while (!ast_strlen_zero(whereweare)) {
03765       /* reset our buffer */
03766       ast_str_reset(substr3);
03767 
03768       /* Assume we're copying the whole remaining string */
03769       pos = strlen(whereweare);
03770       nextvar = NULL;
03771       nextexp = NULL;
03772       nextthing = strchr(whereweare, '$');
03773       if (nextthing) {
03774          switch (nextthing[1]) {
03775          case '{':
03776             nextvar = nextthing;
03777             pos = nextvar - whereweare;
03778             break;
03779          case '[':
03780             nextexp = nextthing;
03781             pos = nextexp - whereweare;
03782             break;
03783          default:
03784             pos = 1;
03785          }
03786       }
03787 
03788       if (pos) {
03789          /* Copy that many bytes */
03790          ast_str_append_substr(buf, maxlen, whereweare, pos);
03791 
03792          templ += pos;
03793          whereweare += pos;
03794       }
03795 
03796       if (nextvar) {
03797          /* We have a variable.  Find the start and end, and determine
03798             if we are going to have to recursively call ourselves on the
03799             contents */
03800          vars = vare = nextvar + 2;
03801          brackets = 1;
03802          needsub = 0;
03803 
03804          /* Find the end of it */
03805          while (brackets && *vare) {
03806             if ((vare[0] == '$') && (vare[1] == '{')) {
03807                needsub++;
03808             } else if (vare[0] == '{') {
03809                brackets++;
03810             } else if (vare[0] == '}') {
03811                brackets--;
03812             } else if ((vare[0] == '$') && (vare[1] == '['))
03813                needsub++;
03814             vare++;
03815          }
03816          if (brackets)
03817             ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n");
03818          len = vare - vars - 1;
03819 
03820          /* Skip totally over variable string */
03821          whereweare += (len + 3);
03822 
03823          /* Store variable name (and truncate) */
03824          ast_str_set_substr(&substr1, 0, vars, len);
03825          ast_debug(5, "Evaluating '%s' (from '%s' len %d)\n", ast_str_buffer(substr1), vars, len);
03826 
03827          /* Substitute if necessary */
03828          if (needsub) {
03829             size_t used;
03830             if (!substr2) {
03831                substr2 = ast_str_create(16);
03832             }
03833 
03834             ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), &used);
03835             finalvars = ast_str_buffer(substr2);
03836          } else {
03837             finalvars = ast_str_buffer(substr1);
03838          }
03839 
03840          parse_variable_name(finalvars, &offset, &offset2, &isfunction);
03841          if (isfunction) {
03842             /* Evaluate function */
03843             if (c || !headp) {
03844                cp4 = ast_func_read2(c, finalvars, &substr3, 0) ? NULL : ast_str_buffer(substr3);
03845             } else {
03846                struct varshead old;
03847                struct ast_channel *bogus = ast_dummy_channel_alloc();
03848                if (bogus) {
03849                   memcpy(&old, &bogus->varshead, sizeof(old));
03850                   memcpy(&bogus->varshead, headp, sizeof(bogus->varshead));
03851                   cp4 = ast_func_read2(c, finalvars, &substr3, 0) ? NULL : ast_str_buffer(substr3);
03852                   /* Don't deallocate the varshead that was passed in */
03853                   memcpy(&bogus->varshead, &old, sizeof(bogus->varshead));
03854                   ast_channel_unref(bogus);
03855                } else {
03856                   ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution.  Function results may be blank.\n");
03857                }
03858             }
03859             ast_debug(2, "Function result is '%s'\n", cp4 ? cp4 : "(null)");
03860          } else {
03861             /* Retrieve variable value */
03862             ast_str_retrieve_variable(&substr3, 0, c, headp, finalvars);
03863             cp4 = ast_str_buffer(substr3);
03864          }
03865          if (cp4) {
03866             ast_str_substring(substr3, offset, offset2);
03867             ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3));
03868          }
03869       } else if (nextexp) {
03870          /* We have an expression.  Find the start and end, and determine
03871             if we are going to have to recursively call ourselves on the
03872             contents */
03873          vars = vare = nextexp + 2;
03874          brackets = 1;
03875          needsub = 0;
03876 
03877          /* Find the end of it */
03878          while (brackets && *vare) {
03879             if ((vare[0] == '$') && (vare[1] == '[')) {
03880                needsub++;
03881                brackets++;
03882                vare++;
03883             } else if (vare[0] == '[') {
03884                brackets++;
03885             } else if (vare[0] == ']') {
03886                brackets--;
03887             } else if ((vare[0] == '$') && (vare[1] == '{')) {
03888                needsub++;
03889                vare++;
03890             }
03891             vare++;
03892          }
03893          if (brackets)
03894             ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n");
03895          len = vare - vars - 1;
03896 
03897          /* Skip totally over expression */
03898          whereweare += (len + 3);
03899 
03900          /* Store variable name (and truncate) */
03901          ast_str_set_substr(&substr1, 0, vars, len);
03902 
03903          /* Substitute if necessary */
03904          if (needsub) {
03905             size_t used;
03906             if (!substr2) {
03907                substr2 = ast_str_create(16);
03908             }
03909 
03910             ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), &used);
03911             finalvars = ast_str_buffer(substr2);
03912          } else {
03913             finalvars = ast_str_buffer(substr1);
03914          }
03915 
03916          if (ast_str_expr(&substr3, 0, c, finalvars)) {
03917             ast_debug(2, "Expression result is '%s'\n", ast_str_buffer(substr3));
03918          }
03919          ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3));
03920       }
03921    }
03922    *used = ast_str_strlen(*buf) - orig_size;
03923    ast_free(substr1);
03924    ast_free(substr2);
03925    ast_free(substr3);
03926 }
03927 
03928 void ast_str_substitute_variables(struct ast_str **buf, ssize_t maxlen, struct ast_channel *chan, const char *templ)
03929 {
03930    size_t used;
03931    ast_str_substitute_variables_full(buf, maxlen, chan, NULL, templ, &used);
03932 }
03933 
03934 void ast_str_substitute_variables_varshead(struct ast_str **buf, ssize_t maxlen, struct varshead *headp, const char *templ)
03935 {
03936    size_t used;
03937    ast_str_substitute_variables_full(buf, maxlen, NULL, headp, templ, &used);
03938 }
03939 
03940 void pbx_substitute_variables_helper_full(struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int count, size_t *used)
03941 {
03942    /* Substitutes variables into cp2, based on string cp1, cp2 NO LONGER NEEDS TO BE ZEROED OUT!!!!  */
03943    char *cp4 = NULL;
03944    const char *tmp, *whereweare, *orig_cp2 = cp2;
03945    int length, offset, offset2, isfunction;
03946    char *workspace = NULL;
03947    char *ltmp = NULL, *var = NULL;
03948    char *nextvar, *nextexp, *nextthing;
03949    char *vars, *vare;
03950    int pos, brackets, needsub, len;
03951 
03952    *cp2 = 0; /* just in case nothing ends up there */
03953    whereweare=tmp=cp1;
03954    while (!ast_strlen_zero(whereweare) && count) {
03955       /* Assume we're copying the whole remaining string */
03956       pos = strlen(whereweare);
03957       nextvar = NULL;
03958       nextexp = NULL;
03959       nextthing = strchr(whereweare, '$');
03960       if (nextthing) {
03961          switch (nextthing[1]) {
03962          case '{':
03963             nextvar = nextthing;
03964             pos = nextvar - whereweare;
03965             break;
03966          case '[':
03967             nextexp = nextthing;
03968             pos = nextexp - whereweare;
03969             break;
03970          default:
03971             pos = 1;
03972          }
03973       }
03974 
03975       if (pos) {
03976          /* Can't copy more than 'count' bytes */
03977          if (pos > count)
03978             pos = count;
03979 
03980          /* Copy that many bytes */
03981          memcpy(cp2, whereweare, pos);
03982 
03983          count -= pos;
03984          cp2 += pos;
03985          whereweare += pos;
03986          *cp2 = 0;
03987       }
03988 
03989       if (nextvar) {
03990          /* We have a variable.  Find the start and end, and determine
03991             if we are going to have to recursively call ourselves on the
03992             contents */
03993          vars = vare = nextvar + 2;
03994          brackets = 1;
03995          needsub = 0;
03996 
03997          /* Find the end of it */
03998          while (brackets && *vare) {
03999             if ((vare[0] == '$') && (vare[1] == '{')) {
04000                needsub++;
04001             } else if (vare[0] == '{') {
04002                brackets++;
04003             } else if (vare[0] == '}') {
04004                brackets--;
04005             } else if ((vare[0] == '$') && (vare[1] == '['))
04006                needsub++;
04007             vare++;
04008          }
04009          if (brackets)
04010             ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n");
04011          len = vare - vars - 1;
04012 
04013          /* Skip totally over variable string */
04014          whereweare += (len + 3);
04015 
04016          if (!var)
04017             var = alloca(VAR_BUF_SIZE);
04018 
04019          /* Store variable name (and truncate) */
04020          ast_copy_string(var, vars, len + 1);
04021 
04022          /* Substitute if necessary */
04023          if (needsub) {
04024             size_t used;
04025             if (!ltmp)
04026                ltmp = alloca(VAR_BUF_SIZE);
04027 
04028             pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &used);
04029             vars = ltmp;
04030          } else {
04031             vars = var;
04032          }
04033 
04034          if (!workspace)
04035             workspace = alloca(VAR_BUF_SIZE);
04036 
04037          workspace[0] = '\0';
04038 
04039          parse_variable_name(vars, &offset, &offset2, &isfunction);
04040          if (isfunction) {
04041             /* Evaluate function */
04042             if (c || !headp)
04043                cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace;
04044             else {
04045                struct varshead old;
04046                struct ast_channel *c = ast_dummy_channel_alloc();
04047                if (c) {
04048                   memcpy(&old, &c->varshead, sizeof(old));
04049                   memcpy(&c->varshead, headp, sizeof(c->varshead));
04050                   cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace;
04051                   /* Don't deallocate the varshead that was passed in */
04052                   memcpy(&c->varshead, &old, sizeof(c->varshead));
04053                   c = ast_channel_unref(c);
04054                } else {
04055                   ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution.  Function results may be blank.\n");
04056                }
04057             }
04058             ast_debug(2, "Function result is '%s'\n", cp4 ? cp4 : "(null)");
04059          } else {
04060             /* Retrieve variable value */
04061             pbx_retrieve_variable(c, vars, &cp4, workspace, VAR_BUF_SIZE, headp);
04062          }
04063          if (cp4) {
04064             cp4 = substring(cp4, offset, offset2, workspace, VAR_BUF_SIZE);
04065 
04066             length = strlen(cp4);
04067             if (length > count)
04068                length = count;
04069             memcpy(cp2, cp4, length);
04070             count -= length;
04071             cp2 += length;
04072             *cp2 = 0;
04073          }
04074       } else if (nextexp) {
04075          /* We have an expression.  Find the start and end, and determine
04076             if we are going to have to recursively call ourselves on the
04077             contents */
04078          vars = vare = nextexp + 2;
04079          brackets = 1;
04080          needsub = 0;
04081 
04082          /* Find the end of it */
04083          while (brackets && *vare) {
04084             if ((vare[0] == '$') && (vare[1] == '[')) {
04085                needsub++;
04086                brackets++;
04087                vare++;
04088             } else if (vare[0] == '[') {
04089                brackets++;
04090             } else if (vare[0] == ']') {
04091                brackets--;
04092             } else if ((vare[0] == '$') && (vare[1] == '{')) {
04093                needsub++;
04094                vare++;
04095             }
04096             vare++;
04097          }
04098          if (brackets)
04099             ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n");
04100          len = vare - vars - 1;
04101 
04102          /* Skip totally over expression */
04103          whereweare += (len + 3);
04104 
04105          if (!var)
04106             var = alloca(VAR_BUF_SIZE);
04107 
04108          /* Store variable name (and truncate) */
04109          ast_copy_string(var, vars, len + 1);
04110 
04111          /* Substitute if necessary */
04112          if (needsub) {
04113             size_t used;
04114             if (!ltmp)
04115                ltmp = alloca(VAR_BUF_SIZE);
04116 
04117             pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &used);
04118             vars = ltmp;
04119          } else {
04120             vars = var;
04121          }
04122 
04123          length = ast_expr(vars, cp2, count, c);
04124 
04125          if (length) {
04126             ast_debug(1, "Expression result is '%s'\n", cp2);
04127             count -= length;
04128             cp2 += length;
04129             *cp2 = 0;
04130          }
04131       }
04132    }
04133    *used = cp2 - orig_cp2;
04134 }
04135 
04136 void pbx_substitute_variables_helper(struct ast_channel *c, const char *cp1, char *cp2, int count)
04137 {
04138    size_t used;
04139    pbx_substitute_variables_helper_full(c, (c) ? &c->varshead : NULL, cp1, cp2, count, &used);
04140 }
04141 
04142 void pbx_substitute_variables_varshead(struct varshead *headp, const char *cp1, char *cp2, int count)
04143 {
04144    size_t used;
04145    pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count, &used);
04146 }
04147 
04148 static void pbx_substitute_variables(char *passdata, int datalen, struct ast_channel *c, struct ast_exten *e)
04149 {
04150    const char *tmp;
04151 
04152    /* Nothing more to do */
04153    if (!e->data) {
04154       *passdata = '\0';
04155       return;
04156    }
04157 
04158    /* No variables or expressions in e->data, so why scan it? */
04159    if ((!(tmp = strchr(e->data, '$'))) || (!strstr(tmp, "${") && !strstr(tmp, "$["))) {
04160       ast_copy_string(passdata, e->data, datalen);
04161       return;
04162    }
04163 
04164    pbx_substitute_variables_helper(c, e->data, passdata, datalen - 1);
04165 }
04166 
04167 /*!
04168  * \brief The return value depends on the action:
04169  *
04170  * E_MATCH, E_CANMATCH, E_MATCHMORE require a real match,
04171  * and return 0 on failure, -1 on match;
04172  * E_FINDLABEL maps the label to a priority, and returns
04173  * the priority on success, ... XXX
04174  * E_SPAWN, spawn an application,
04175  *
04176  * \retval 0 on success.
04177  * \retval  -1 on failure.
04178  *
04179  * \note The channel is auto-serviced in this function, because doing an extension
04180  * match may block for a long time.  For example, if the lookup has to use a network
04181  * dialplan switch, such as DUNDi or IAX2, it may take a while.  However, the channel
04182  * auto-service code will queue up any important signalling frames to be processed
04183  * after this is done.
04184  */
04185 static int pbx_extension_helper(struct ast_channel *c, struct ast_context *con,
04186   const char *context, const char *exten, int priority,
04187   const char *label, const char *callerid, enum ext_match_t action, int *found, int combined_find_spawn)
04188 {
04189    struct ast_exten *e;
04190    struct ast_app *app;
04191    int res;
04192    struct pbx_find_info q = { .stacklen = 0 }; /* the rest is reset in pbx_find_extension */
04193    char passdata[EXT_DATA_SIZE];
04194 
04195    int matching_action = (action == E_MATCH || action == E_CANMATCH || action == E_MATCHMORE);
04196 
04197    ast_rdlock_contexts();
04198    if (found)
04199       *found = 0;
04200 
04201    e = pbx_find_extension(c, con, &q, context, exten, priority, label, callerid, action);
04202    if (e) {
04203       if (found)
04204          *found = 1;
04205       if (matching_action) {
04206          ast_unlock_contexts();
04207          return -1;  /* success, we found it */
04208       } else if (action == E_FINDLABEL) { /* map the label to a priority */
04209          res = e->priority;
04210          ast_unlock_contexts();
04211          return res; /* the priority we were looking for */
04212       } else { /* spawn */
04213          if (!e->cached_app)
04214             e->cached_app = pbx_findapp(e->app);
04215          app = e->cached_app;
04216          ast_unlock_contexts();
04217          if (!app) {
04218             ast_log(LOG_WARNING, "No application '%s' for extension (%s, %s, %d)\n", e->app, context, exten, priority);
04219             return -1;
04220          }
04221          if (c->context != context)
04222             ast_copy_string(c->context, context, sizeof(c->context));
04223          if (c->exten != exten)
04224             ast_copy_string(c->exten, exten, sizeof(c->exten));
04225          c->priority = priority;
04226          pbx_substitute_variables(passdata, sizeof(passdata), c, e);
04227 #ifdef CHANNEL_TRACE
04228          ast_channel_trace_update(c);
04229 #endif
04230          ast_debug(1, "Launching '%s'\n", app->name);
04231          if (VERBOSITY_ATLEAST(3)) {
04232             char tmp[80], tmp2[80], tmp3[EXT_DATA_SIZE];
04233             ast_verb(3, "Executing [%s@%s:%d] %s(\"%s\", \"%s\") %s\n",
04234                exten, context, priority,
04235                term_color(tmp, app->name, COLOR_BRCYAN, 0, sizeof(tmp)),
04236                term_color(tmp2, c->name, COLOR_BRMAGENTA, 0, sizeof(tmp2)),
04237                term_color(tmp3, passdata, COLOR_BRMAGENTA, 0, sizeof(tmp3)),
04238                "in new stack");
04239          }
04240          manager_event(EVENT_FLAG_DIALPLAN, "Newexten",
04241                "Channel: %s\r\n"
04242                "Context: %s\r\n"
04243                "Extension: %s\r\n"
04244                "Priority: %d\r\n"
04245                "Application: %s\r\n"
04246                "AppData: %s\r\n"
04247                "Uniqueid: %s\r\n",
04248                c->name, c->context, c->exten, c->priority, app->name, passdata, c->uniqueid);
04249          return pbx_exec(c, app, passdata);  /* 0 on success, -1 on failure */
04250       }
04251    } else if (q.swo) {  /* not found here, but in another switch */
04252       if (found)
04253          *found = 1;
04254       ast_unlock_contexts();
04255       if (matching_action) {
04256          return -1;
04257       } else {
04258          if (!q.swo->exec) {
04259             ast_log(LOG_WARNING, "No execution engine for switch %s\n", q.swo->name);
04260             res = -1;
04261          }
04262          return q.swo->exec(c, q.foundcontext ? q.foundcontext : context, exten, priority, callerid, q.data);
04263       }
04264    } else { /* not found anywhere, see what happened */
04265       ast_unlock_contexts();
04266       /* Using S_OR here because Solaris doesn't like NULL being passed to ast_log */
04267       switch (q.status) {
04268       case STATUS_NO_CONTEXT:
04269          if (!matching_action && !combined_find_spawn)
04270             ast_log(LOG_NOTICE, "Cannot find extension context '%s'\n", S_OR(context, ""));
04271          break;
04272       case STATUS_NO_EXTENSION:
04273          if (!matching_action && !combined_find_spawn)
04274             ast_log(LOG_NOTICE, "Cannot find extension '%s' in context '%s'\n", exten, S_OR(context, ""));
04275          break;
04276       case STATUS_NO_PRIORITY:
04277          if (!matching_action && !combined_find_spawn)
04278             ast_log(LOG_NOTICE, "No such priority %d in extension '%s' in context '%s'\n", priority, exten, S_OR(context, ""));
04279          break;
04280       case STATUS_NO_LABEL:
04281          if (context && !combined_find_spawn)
04282             ast_log(LOG_NOTICE, "No such label '%s' in extension '%s' in context '%s'\n", label, exten, S_OR(context, ""));
04283          break;
04284       default:
04285          ast_debug(1, "Shouldn't happen!\n");
04286       }
04287 
04288       return (matching_action) ? 0 : -1;
04289    }
04290 }
04291 
04292 /*! \brief Find hint for given extension in context */
04293 static struct ast_exten *ast_hint_extension_nolock(struct ast_channel *c, const char *context, const char *exten)
04294 {
04295    struct pbx_find_info q = { .stacklen = 0 }; /* the rest is set in pbx_find_context */
04296    return pbx_find_extension(c, NULL, &q, context, exten, PRIORITY_HINT, NULL, "", E_MATCH);
04297 }
04298 
04299 static struct ast_exten *ast_hint_extension(struct ast_channel *c, const char *context, const char *exten)
04300 {
04301    struct ast_exten *e;
04302    ast_rdlock_contexts();
04303    e = ast_hint_extension_nolock(c, context, exten);
04304    ast_unlock_contexts();
04305    return e;
04306 }
04307 
04308 enum ast_extension_states ast_devstate_to_extenstate(enum ast_device_state devstate)
04309 {
04310    switch (devstate) {
04311    case AST_DEVICE_ONHOLD:
04312       return AST_EXTENSION_ONHOLD;
04313    case AST_DEVICE_BUSY:
04314       return AST_EXTENSION_BUSY;
04315    case AST_DEVICE_UNKNOWN:
04316       return AST_EXTENSION_NOT_INUSE;
04317    case AST_DEVICE_UNAVAILABLE:
04318    case AST_DEVICE_INVALID:
04319       return AST_EXTENSION_UNAVAILABLE;
04320    case AST_DEVICE_RINGINUSE:
04321       return (AST_EXTENSION_INUSE | AST_EXTENSION_RINGING);
04322    case AST_DEVICE_RINGING:
04323       return AST_EXTENSION_RINGING;
04324    case AST_DEVICE_INUSE:
04325       return AST_EXTENSION_INUSE;
04326    case AST_DEVICE_NOT_INUSE:
04327       return AST_EXTENSION_NOT_INUSE;
04328    case AST_DEVICE_TOTAL: /* not a device state, included for completeness */
04329       break;
04330    }
04331 
04332    return AST_EXTENSION_NOT_INUSE;
04333 }
04334 
04335 static int ast_extension_state3(struct ast_str *hint_app)
04336 {
04337    char *cur;
04338    char *rest;
04339    struct ast_devstate_aggregate agg;
04340 
04341    /* One or more devices separated with a & character */
04342    rest = ast_str_buffer(hint_app);
04343 
04344    ast_devstate_aggregate_init(&agg);
04345    while ((cur = strsep(&rest, "&"))) {
04346       ast_devstate_aggregate_add(&agg, ast_device_state(cur));
04347    }
04348 
04349    return ast_devstate_to_extenstate(ast_devstate_aggregate_result(&agg));
04350 }
04351 
04352 /*! \brief Check state of extension by using hints */
04353 static int ast_extension_state2(struct ast_exten *e)
04354 {
04355    struct ast_str *hint_app = ast_str_thread_get(&extensionstate_buf, 32);
04356 
04357    if (!e || !hint_app) {
04358       return -1;
04359    }
04360 
04361    ast_str_set(&hint_app, 0, "%s", ast_get_extension_app(e));
04362    return ast_extension_state3(hint_app);
04363 }
04364 
04365 /*! \brief Return extension_state as string */
04366 const char *ast_extension_state2str(int extension_state)
04367 {
04368    int i;
04369 
04370    for (i = 0; (i < ARRAY_LEN(extension_states)); i++) {
04371       if (extension_states[i].extension_state == extension_state)
04372          return extension_states[i].text;
04373    }
04374    return "Unknown";
04375 }
04376 
04377 /*! \brief Check extension state for an extension by using hint */
04378 int ast_extension_state(struct ast_channel *c, const char *context, const char *exten)
04379 {
04380    struct ast_exten *e;
04381 
04382    if (!(e = ast_hint_extension(c, context, exten))) {  /* Do we have a hint for this extension ? */
04383       return -1;                   /* No hint, return -1 */
04384    }
04385 
04386    if (e->exten[0] == '_') {
04387       /* Create this hint on-the-fly */
04388       ast_add_extension(e->parent->name, 0, exten, e->priority, e->label,
04389          e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr,
04390          e->registrar);
04391       if (!(e = ast_hint_extension(c, context, exten))) {
04392          /* Improbable, but not impossible */
04393          return -1;
04394       }
04395    }
04396 
04397    return ast_extension_state2(e);  /* Check all devices in the hint */
04398 }
04399 
04400 static int handle_statechange(void *datap)
04401 {
04402    struct ast_hint *hint;
04403    struct ast_str *hint_app;
04404    struct statechange *sc = datap;
04405    struct ao2_iterator i;
04406    struct ao2_iterator cb_iter;
04407    char context_name[AST_MAX_CONTEXT];
04408    char exten_name[AST_MAX_EXTENSION];
04409 
04410    hint_app = ast_str_create(1024);
04411    if (!hint_app) {
04412       ast_free(sc);
04413       return -1;
04414    }
04415 
04416    ast_mutex_lock(&context_merge_lock);/* Hold off ast_merge_contexts_and_delete */
04417    i = ao2_iterator_init(hints, 0);
04418    for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) {
04419       struct ast_state_cb *state_cb;
04420       char *cur, *parse;
04421       int state;
04422 
04423       ao2_lock(hint);
04424       if (!hint->exten) {
04425          /* The extension has already been destroyed */
04426          ao2_unlock(hint);
04427          continue;
04428       }
04429 
04430       /* Does this hint monitor the device that changed state? */
04431       ast_str_set(&hint_app, 0, "%s", ast_get_extension_app(hint->exten));
04432       parse = ast_str_buffer(hint_app);
04433       while ((cur = strsep(&parse, "&"))) {
04434          if (!strcasecmp(cur, sc->dev)) {
04435             /* The hint monitors the device. */
04436             break;
04437          }
04438       }
04439       if (!cur) {
04440          /* The hint does not monitor the device. */
04441          ao2_unlock(hint);
04442          continue;
04443       }
04444 
04445       /*
04446        * Save off strings in case the hint extension gets destroyed
04447        * while we are notifying the watchers.
04448        */
04449       ast_copy_string(context_name,
04450          ast_get_context_name(ast_get_extension_context(hint->exten)),
04451          sizeof(context_name));
04452       ast_copy_string(exten_name, ast_get_extension_name(hint->exten),
04453          sizeof(exten_name));
04454       ast_str_set(&hint_app, 0, "%s", ast_get_extension_app(hint->exten));
04455       ao2_unlock(hint);
04456 
04457       /*
04458        * Get device state for this hint.
04459        *
04460        * NOTE: We cannot hold any locks while determining the hint
04461        * device state or notifying the watchers without causing a
04462        * deadlock.  (conlock, hints, and hint)
04463        */
04464       state = ast_extension_state3(hint_app);
04465       if (state == hint->laststate) {
04466          continue;
04467       }
04468 
04469       /* Device state changed since last check - notify the watchers. */
04470       hint->laststate = state;   /* record we saw the change */
04471 
04472       /* For general callbacks */
04473       cb_iter = ao2_iterator_init(statecbs, 0);
04474       for (; (state_cb = ao2_iterator_next(&cb_iter)); ao2_ref(state_cb, -1)) {
04475          state_cb->change_cb(context_name, exten_name, state, state_cb->data);
04476       }
04477       ao2_iterator_destroy(&cb_iter);
04478 
04479       /* For extension callbacks */
04480       cb_iter = ao2_iterator_init(hint->callbacks, 0);
04481       for (; (state_cb = ao2_iterator_next(&cb_iter)); ao2_ref(state_cb, -1)) {
04482          state_cb->change_cb(context_name, exten_name, state, state_cb->data);
04483       }
04484       ao2_iterator_destroy(&cb_iter);
04485    }
04486    ao2_iterator_destroy(&i);
04487    ast_mutex_unlock(&context_merge_lock);
04488 
04489    ast_free(hint_app);
04490    ast_free(sc);
04491    return 0;
04492 }
04493 
04494 /*!
04495  * \internal
04496  * \brief Destroy the given state callback object.
04497  *
04498  * \param doomed State callback to destroy.
04499  *
04500  * \return Nothing
04501  */
04502 static void destroy_state_cb(void *doomed)
04503 {
04504    struct ast_state_cb *state_cb = doomed;
04505 
04506    if (state_cb->destroy_cb) {
04507       state_cb->destroy_cb(state_cb->id, state_cb->data);
04508    }
04509 }
04510 
04511 /*! \brief Add watcher for extension states with destructor */
04512 int ast_extension_state_add_destroy(const char *context, const char *exten,
04513    ast_state_cb_type change_cb, ast_state_cb_destroy_type destroy_cb, void *data)
04514 {
04515    struct ast_hint *hint;
04516    struct ast_state_cb *state_cb;
04517    struct ast_exten *e;
04518    int id;
04519 
04520    /* If there's no context and extension:  add callback to statecbs list */
04521    if (!context && !exten) {
04522       /* Prevent multiple adds from adding the same change_cb at the same time. */
04523       ao2_lock(statecbs);
04524 
04525       /* Remove any existing change_cb. */
04526       ao2_find(statecbs, change_cb, OBJ_UNLINK | OBJ_NODATA);
04527 
04528       /* Now insert the change_cb */
04529       if (!(state_cb = ao2_alloc(sizeof(*state_cb), destroy_state_cb))) {
04530          ao2_unlock(statecbs);
04531          return -1;
04532       }
04533       state_cb->id = 0;
04534       state_cb->change_cb = change_cb;
04535       state_cb->destroy_cb = destroy_cb;
04536       state_cb->data = data;
04537       ao2_link(statecbs, state_cb);
04538 
04539       ao2_ref(state_cb, -1);
04540       ao2_unlock(statecbs);
04541       return 0;
04542    }
04543 
04544    if (!context || !exten)
04545       return -1;
04546 
04547    /* This callback type is for only one hint, so get the hint */
04548    e = ast_hint_extension(NULL, context, exten);
04549    if (!e) {
04550       return -1;
04551    }
04552 
04553    /* If this is a pattern, dynamically create a new extension for this
04554     * particular match.  Note that this will only happen once for each
04555     * individual extension, because the pattern will no longer match first.
04556     */
04557    if (e->exten[0] == '_') {
04558       ast_add_extension(e->parent->name, 0, exten, e->priority, e->label,
04559          e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr,
04560          e->registrar);
04561       e = ast_hint_extension(NULL, context, exten);
04562       if (!e || e->exten[0] == '_') {
04563          return -1;
04564       }
04565    }
04566 
04567    /* Find the hint in the hints container */
04568    ao2_lock(hints);/* Locked to hold off ast_merge_contexts_and_delete */
04569    hint = ao2_find(hints, e, 0);
04570    if (!hint) {
04571       ao2_unlock(hints);
04572       return -1;
04573    }
04574 
04575    /* Now insert the callback in the callback list  */
04576    if (!(state_cb = ao2_alloc(sizeof(*state_cb), destroy_state_cb))) {
04577       ao2_ref(hint, -1);
04578       ao2_unlock(hints);
04579       return -1;
04580    }
04581    do {
04582       id = stateid++;      /* Unique ID for this callback */
04583       /* Do not allow id to ever be -1 or 0. */
04584    } while (id == -1 || id == 0);
04585    state_cb->id = id;
04586    state_cb->change_cb = change_cb; /* Pointer to callback routine */
04587    state_cb->destroy_cb = destroy_cb;
04588    state_cb->data = data;     /* Data for the callback */
04589    ao2_link(hint->callbacks, state_cb);
04590 
04591    ao2_ref(state_cb, -1);
04592    ao2_ref(hint, -1);
04593    ao2_unlock(hints);
04594 
04595    return id;
04596 }
04597 
04598 /*! \brief Add watcher for extension states */
04599 int ast_extension_state_add(const char *context, const char *exten,
04600    ast_state_cb_type change_cb, void *data)
04601 {
04602    return ast_extension_state_add_destroy(context, exten, change_cb, NULL, data);
04603 }
04604 
04605 /*! \brief Remove a watcher from the callback list */
04606 static int find_hint_by_cb_id(void *obj, void *arg, int flags)
04607 {
04608    struct ast_state_cb *state_cb;
04609    const struct ast_hint *hint = obj;
04610    int *id = arg;
04611 
04612    if ((state_cb = ao2_find(hint->callbacks, id, 0))) {
04613       ao2_ref(state_cb, -1);
04614       return CMP_MATCH | CMP_STOP;
04615    }
04616 
04617    return 0;
04618 }
04619 
04620 /*! \brief  ast_extension_state_del: Remove a watcher from the callback list */
04621 int ast_extension_state_del(int id, ast_state_cb_type change_cb)
04622 {
04623    struct ast_state_cb *p_cur;
04624    int ret = -1;
04625 
04626    if (!id) {  /* id == 0 is a callback without extension */
04627       if (!change_cb) {
04628          return ret;
04629       }
04630       p_cur = ao2_find(statecbs, change_cb, OBJ_UNLINK);
04631       if (p_cur) {
04632          ret = 0;
04633          ao2_ref(p_cur, -1);
04634       }
04635    } else { /* callback with extension, find the callback based on ID */
04636       struct ast_hint *hint;
04637 
04638       ao2_lock(hints);/* Locked to hold off ast_merge_contexts_and_delete */
04639       hint = ao2_callback(hints, 0, find_hint_by_cb_id, &id);
04640       if (hint) {
04641          p_cur = ao2_find(hint->callbacks, &id, OBJ_UNLINK);
04642          if (p_cur) {
04643             ret = 0;
04644             ao2_ref(p_cur, -1);
04645          }
04646          ao2_ref(hint, -1);
04647       }
04648       ao2_unlock(hints);
04649    }
04650 
04651    return ret;
04652 }
04653 
04654 
04655 static int hint_id_cmp(void *obj, void *arg, int flags)
04656 {
04657    const struct ast_state_cb *cb = obj;
04658    int *id = arg;
04659 
04660    return (cb->id == *id) ? CMP_MATCH | CMP_STOP : 0;
04661 }
04662 
04663 /*!
04664  * \internal
04665  * \brief Destroy the given hint object.
04666  *
04667  * \param obj Hint to destroy.
04668  *
04669  * \return Nothing
04670  */
04671 static void destroy_hint(void *obj)
04672 {
04673    struct ast_hint *hint = obj;
04674 
04675    if (hint->callbacks) {
04676       struct ast_state_cb *state_cb;
04677       const char *context_name;
04678       const char *exten_name;
04679 
04680       if (hint->exten) {
04681          context_name = ast_get_context_name(ast_get_extension_context(hint->exten));
04682          exten_name = ast_get_extension_name(hint->exten);
04683          hint->exten = NULL;
04684       } else {
04685          /* The extension has already been destroyed */
04686          context_name = hint->context_name;
04687          exten_name = hint->exten_name;
04688       }
04689       while ((state_cb = ao2_callback(hint->callbacks, OBJ_UNLINK, NULL, NULL))) {
04690          /* Notify with -1 and remove all callbacks */
04691          /* NOTE: The casts will not be needed for v1.10 and later */
04692          state_cb->change_cb((char *) context_name, (char *) exten_name,
04693             AST_EXTENSION_DEACTIVATED, state_cb->data);
04694          ao2_ref(state_cb, -1);
04695       }
04696       ao2_ref(hint->callbacks, -1);
04697    }
04698 }
04699 
04700 /*! \brief Remove hint from extension */
04701 static int ast_remove_hint(struct ast_exten *e)
04702 {
04703    /* Cleanup the Notifys if hint is removed */
04704    struct ast_hint *hint;
04705 
04706    if (!e) {
04707       return -1;
04708    }
04709 
04710    hint = ao2_find(hints, e, OBJ_UNLINK);
04711    if (!hint) {
04712       return -1;
04713    }
04714 
04715    /*
04716     * The extension is being destroyed so we must save some
04717     * information to notify that the extension is deactivated.
04718     */
04719    ao2_lock(hint);
04720    ast_copy_string(hint->context_name,
04721       ast_get_context_name(ast_get_extension_context(hint->exten)),
04722       sizeof(hint->context_name));
04723    ast_copy_string(hint->exten_name, ast_get_extension_name(hint->exten),
04724       sizeof(hint->exten_name));
04725    hint->exten = NULL;
04726    ao2_unlock(hint);
04727 
04728    ao2_ref(hint, -1);
04729 
04730    return 0;
04731 }
04732 
04733 /*! \brief Add hint to hint list, check initial extension state */
04734 static int ast_add_hint(struct ast_exten *e)
04735 {
04736    struct ast_hint *hint_new;
04737    struct ast_hint *hint_found;
04738 
04739    if (!e) {
04740       return -1;
04741    }
04742 
04743    /*
04744     * We must create the hint we wish to add before determining if
04745     * it is already in the hints container to avoid possible
04746     * deadlock when getting the current extension state.
04747     */
04748    hint_new = ao2_alloc(sizeof(*hint_new), destroy_hint);
04749    if (!hint_new) {
04750       return -1;
04751    }
04752 
04753    /* Initialize new hint. */
04754    hint_new->callbacks = ao2_container_alloc(1, NULL, hint_id_cmp);
04755    if (!hint_new->callbacks) {
04756       ao2_ref(hint_new, -1);
04757       return -1;
04758    }
04759    hint_new->exten = e;
04760    hint_new->laststate = ast_extension_state2(e);
04761 
04762    /* Prevent multiple add hints from adding the same hint at the same time. */
04763    ao2_lock(hints);
04764 
04765    /* Search if hint exists, do nothing */
04766    hint_found = ao2_find(hints, e, 0);
04767    if (hint_found) {
04768       ao2_ref(hint_found, -1);
04769       ao2_unlock(hints);
04770       ao2_ref(hint_new, -1);
04771       ast_debug(2, "HINTS: Not re-adding existing hint %s: %s\n",
04772          ast_get_extension_name(e), ast_get_extension_app(e));
04773       return -1;
04774    }
04775 
04776    /* Add new hint to the hints container */
04777    ast_debug(2, "HINTS: Adding hint %s: %s\n",
04778       ast_get_extension_name(e), ast_get_extension_app(e));
04779    ao2_link(hints, hint_new);
04780 
04781    ao2_unlock(hints);
04782    ao2_ref(hint_new, -1);
04783 
04784    return 0;
04785 }
04786 
04787 /*! \brief Change hint for an extension */
04788 static int ast_change_hint(struct ast_exten *oe, struct ast_exten *ne)
04789 {
04790    struct ast_hint *hint;
04791 
04792    if (!oe || !ne) {
04793       return -1;
04794    }
04795 
04796    ao2_lock(hints);/* Locked to hold off others while we move the hint around. */
04797 
04798    /*
04799     * Unlink the hint from the hints container as the extension
04800     * name (which is the hash value) could change.
04801     */
04802    hint = ao2_find(hints, oe, OBJ_UNLINK);
04803    if (!hint) {
04804       ao2_unlock(hints);
04805       return -1;
04806    }
04807 
04808    /* Update the hint and put it back in the hints container. */
04809    ao2_lock(hint);
04810    hint->exten = ne;
04811    ao2_unlock(hint);
04812    ao2_link(hints, hint);
04813 
04814    ao2_unlock(hints);
04815    ao2_ref(hint, -1);
04816 
04817    return 0;
04818 }
04819 
04820 
04821 /*! \brief Get hint for channel */
04822 int ast_get_hint(char *hint, int hintsize, char *name, int namesize, struct ast_channel *c, const char *context, const char *exten)
04823 {
04824    struct ast_exten *e = ast_hint_extension(c, context, exten);
04825 
04826    if (e) {
04827       if (hint)
04828          ast_copy_string(hint, ast_get_extension_app(e), hintsize);
04829       if (name) {
04830          const char *tmp = ast_get_extension_app_data(e);
04831          if (tmp)
04832             ast_copy_string(name, tmp, namesize);
04833       }
04834       return -1;
04835    }
04836    return 0;
04837 }
04838 
04839 /*! \brief Get hint for channel */
04840 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)
04841 {
04842    struct ast_exten *e = ast_hint_extension(c, context, exten);
04843 
04844    if (!e) {
04845       return 0;
04846    }
04847 
04848    if (hint) {
04849       ast_str_set(hint, hintsize, "%s", ast_get_extension_app(e));
04850    }
04851    if (name) {
04852       const char *tmp = ast_get_extension_app_data(e);
04853       if (tmp) {
04854          ast_str_set(name, namesize, "%s", tmp);
04855       }
04856    }
04857    return -1;
04858 }
04859 
04860 int ast_exists_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
04861 {
04862    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCH, 0, 0);
04863 }
04864 
04865 int ast_findlabel_extension(struct ast_channel *c, const char *context, const char *exten, const char *label, const char *callerid)
04866 {
04867    return pbx_extension_helper(c, NULL, context, exten, 0, label, callerid, E_FINDLABEL, 0, 0);
04868 }
04869 
04870 int ast_findlabel_extension2(struct ast_channel *c, struct ast_context *con, const char *exten, const char *label, const char *callerid)
04871 {
04872    return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, E_FINDLABEL, 0, 0);
04873 }
04874 
04875 int ast_canmatch_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
04876 {
04877    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_CANMATCH, 0, 0);
04878 }
04879 
04880 int ast_matchmore_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
04881 {
04882    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCHMORE, 0, 0);
04883 }
04884 
04885 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)
04886 {
04887    return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_SPAWN, found, combined_find_spawn);
04888 }
04889 
04890 /*! helper function to set extension and priority */
04891 static void set_ext_pri(struct ast_channel *c, const char *exten, int pri)
04892 {
04893    ast_channel_lock(c);
04894    ast_copy_string(c->exten, exten, sizeof(c->exten));
04895    c->priority = pri;
04896    ast_channel_unlock(c);
04897 }
04898 
04899 /*!
04900  * \brief collect digits from the channel into the buffer.
04901  * \param c, buf, buflen, pos
04902  * \param waittime is in milliseconds
04903  * \retval 0 on timeout or done.
04904  * \retval -1 on error.
04905 */
04906 static int collect_digits(struct ast_channel *c, int waittime, char *buf, int buflen, int pos)
04907 {
04908    int digit;
04909 
04910    buf[pos] = '\0';  /* make sure it is properly terminated */
04911    while (ast_matchmore_extension(c, c->context, buf, 1,
04912       S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
04913       /* As long as we're willing to wait, and as long as it's not defined,
04914          keep reading digits until we can't possibly get a right answer anymore.  */
04915       digit = ast_waitfordigit(c, waittime);
04916       if (c->_softhangup & AST_SOFTHANGUP_ASYNCGOTO) {
04917          ast_channel_clear_softhangup(c, AST_SOFTHANGUP_ASYNCGOTO);
04918       } else {
04919          if (!digit) /* No entry */
04920             break;
04921          if (digit < 0) /* Error, maybe a  hangup */
04922             return -1;
04923          if (pos < buflen - 1) { /* XXX maybe error otherwise ? */
04924             buf[pos++] = digit;
04925             buf[pos] = '\0';
04926          }
04927          waittime = c->pbx->dtimeoutms;
04928       }
04929    }
04930    return 0;
04931 }
04932 
04933 static enum ast_pbx_result __ast_pbx_run(struct ast_channel *c,
04934       struct ast_pbx_args *args)
04935 {
04936    int found = 0; /* set if we find at least one match */
04937    int res = 0;
04938    int autoloopflag;
04939    int error = 0;    /* set an error conditions */
04940 
04941    /* A little initial setup here */
04942    if (c->pbx) {
04943       ast_log(LOG_WARNING, "%s already has PBX structure??\n", c->name);
04944       /* XXX and now what ? */
04945       ast_free(c->pbx);
04946    }
04947    if (!(c->pbx = ast_calloc(1, sizeof(*c->pbx))))
04948       return -1;
04949    /* Set reasonable defaults */
04950    c->pbx->rtimeoutms = 10000;
04951    c->pbx->dtimeoutms = 5000;
04952 
04953    autoloopflag = ast_test_flag(c, AST_FLAG_IN_AUTOLOOP);   /* save value to restore at the end */
04954    ast_set_flag(c, AST_FLAG_IN_AUTOLOOP);
04955 
04956    /* Start by trying whatever the channel is set to */
04957    if (!ast_exists_extension(c, c->context, c->exten, c->priority,
04958       S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
04959       /* If not successful fall back to 's' */
04960       ast_verb(2, "Starting %s at %s,%s,%d failed so falling back to exten 's'\n", c->name, c->context, c->exten, c->priority);
04961       /* XXX the original code used the existing priority in the call to
04962        * ast_exists_extension(), and reset it to 1 afterwards.
04963        * I believe the correct thing is to set it to 1 immediately.
04964        */
04965       set_ext_pri(c, "s", 1);
04966       if (!ast_exists_extension(c, c->context, c->exten, c->priority,
04967          S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
04968          /* JK02: And finally back to default if everything else failed */
04969          ast_verb(2, "Starting %s at %s,%s,%d still failed so falling back to context 'default'\n", c->name, c->context, c->exten, c->priority);
04970          ast_copy_string(c->context, "default", sizeof(c->context));
04971       }
04972    }
04973    ast_channel_lock(c);
04974    if (c->cdr) {
04975       /* allow CDR variables that have been collected after channel was created to be visible during call */
04976       ast_cdr_update(c);
04977    }
04978    ast_channel_unlock(c);
04979    for (;;) {
04980       char dst_exten[256]; /* buffer to accumulate digits */
04981       int pos = 0;      /* XXX should check bounds */
04982       int digit = 0;
04983       int invalid = 0;
04984       int timeout = 0;
04985 
04986       /* loop on priorities in this context/exten */
04987       while (!(res = ast_spawn_extension(c, c->context, c->exten, c->priority,
04988          S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL),
04989          &found, 1))) {
04990          if (!ast_check_hangup(c)) {
04991             ++c->priority;
04992             continue;
04993          }
04994 
04995          /* Check softhangup flags. */
04996          if (c->_softhangup & AST_SOFTHANGUP_ASYNCGOTO) {
04997             ast_channel_clear_softhangup(c, AST_SOFTHANGUP_ASYNCGOTO);
04998             continue;
04999          }
05000          if (c->_softhangup & AST_SOFTHANGUP_TIMEOUT) {
05001             if (ast_exists_extension(c, c->context, "T", 1,
05002                S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
05003                set_ext_pri(c, "T", 1);
05004                /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
05005                memset(&c->whentohangup, 0, sizeof(c->whentohangup));
05006                ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT);
05007                continue;
05008             } else if (ast_exists_extension(c, c->context, "e", 1,
05009                S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
05010                raise_exception(c, "ABSOLUTETIMEOUT", 1);
05011                /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
05012                memset(&c->whentohangup, 0, sizeof(c->whentohangup));
05013                ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT);
05014                continue;
05015             }
05016 
05017             /* Call timed out with no special extension to jump to. */
05018             error = 1;
05019             break;
05020          }
05021          ast_debug(1, "Extension %s, priority %d returned normally even though call was hung up\n",
05022             c->exten, c->priority);
05023          error = 1;
05024          break;
05025       } /* end while  - from here on we can use 'break' to go out */
05026       if (found && res) {
05027          /* Something bad happened, or a hangup has been requested. */
05028          if (strchr("0123456789ABCDEF*#", res)) {
05029             ast_debug(1, "Oooh, got something to jump out with ('%c')!\n", res);
05030             pos = 0;
05031             dst_exten[pos++] = digit = res;
05032             dst_exten[pos] = '\0';
05033          } else if (res == AST_PBX_INCOMPLETE) {
05034             ast_debug(1, "Spawn extension (%s,%s,%d) exited INCOMPLETE on '%s'\n", c->context, c->exten, c->priority, c->name);
05035             ast_verb(2, "Spawn extension (%s, %s, %d) exited INCOMPLETE on '%s'\n", c->context, c->exten, c->priority, c->name);
05036 
05037             /* Don't cycle on incomplete - this will happen if the only extension that matches is our "incomplete" extension */
05038             if (!ast_matchmore_extension(c, c->context, c->exten, 1,
05039                S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
05040                invalid = 1;
05041             } else {
05042                ast_copy_string(dst_exten, c->exten, sizeof(dst_exten));
05043                digit = 1;
05044                pos = strlen(dst_exten);
05045             }
05046          } else {
05047             ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
05048             ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
05049 
05050             if ((res == AST_PBX_ERROR)
05051                && ast_exists_extension(c, c->context, "e", 1,
05052                   S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
05053                /* if we are already on the 'e' exten, don't jump to it again */
05054                if (!strcmp(c->exten, "e")) {
05055                   ast_verb(2, "Spawn extension (%s, %s, %d) exited ERROR while already on 'e' exten on '%s'\n", c->context, c->exten, c->priority, c->name);
05056                   error = 1;
05057                } else {
05058                   raise_exception(c, "ERROR", 1);
05059                   continue;
05060                }
05061             }
05062 
05063             if (c->_softhangup & AST_SOFTHANGUP_ASYNCGOTO) {
05064                ast_channel_clear_softhangup(c, AST_SOFTHANGUP_ASYNCGOTO);
05065                continue;
05066             }
05067             if (c->_softhangup & AST_SOFTHANGUP_TIMEOUT) {
05068                if (ast_exists_extension(c, c->context, "T", 1,
05069                   S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
05070                   set_ext_pri(c, "T", 1);
05071                   /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
05072                   memset(&c->whentohangup, 0, sizeof(c->whentohangup));
05073                   ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT);
05074                   continue;
05075                } else if (ast_exists_extension(c, c->context, "e", 1,
05076                   S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
05077                   raise_exception(c, "ABSOLUTETIMEOUT", 1);
05078                   /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
05079                   memset(&c->whentohangup, 0, sizeof(c->whentohangup));
05080                   ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT);
05081                   continue;
05082                }
05083                /* Call timed out with no special extension to jump to. */
05084             }
05085             ast_channel_lock(c);
05086             if (c->cdr) {
05087                ast_cdr_update(c);
05088             }
05089             ast_channel_unlock(c);
05090             error = 1;
05091             break;
05092          }
05093       }
05094       if (error)
05095          break;
05096 
05097       /*!\note
05098        * We get here on a failure of some kind:  non-existing extension or
05099        * hangup.  We have options, here.  We can either catch the failure
05100        * and continue, or we can drop out entirely. */
05101 
05102       if (invalid
05103          || !ast_exists_extension(c, c->context, c->exten, 1,
05104             S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
05105          /*!\note
05106           * If there is no match at priority 1, it is not a valid extension anymore.
05107           * Try to continue at "i" (for invalid) or "e" (for exception) or exit if
05108           * neither exist.
05109           */
05110          if (ast_exists_extension(c, c->context, "i", 1,
05111             S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
05112             ast_verb(3, "Sent into invalid extension '%s' in context '%s' on %s\n", c->exten, c->context, c->name);
05113             pbx_builtin_setvar_helper(c, "INVALID_EXTEN", c->exten);
05114             set_ext_pri(c, "i", 1);
05115          } else if (ast_exists_extension(c, c->context, "e", 1,
05116             S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
05117             raise_exception(c, "INVALID", 1);
05118          } else {
05119             ast_log(LOG_WARNING, "Channel '%s' sent into invalid extension '%s' in context '%s', but no invalid handler\n",
05120                c->name, c->exten, c->context);
05121             error = 1; /* we know what to do with it */
05122             break;
05123          }
05124       } else if (c->_softhangup & AST_SOFTHANGUP_TIMEOUT) {
05125          /* If we get this far with AST_SOFTHANGUP_TIMEOUT, then we know that the "T" extension is next. */
05126          ast_channel_clear_softhangup(c, AST_SOFTHANGUP_TIMEOUT);
05127       } else { /* keypress received, get more digits for a full extension */
05128          int waittime = 0;
05129          if (digit)
05130             waittime = c->pbx->dtimeoutms;
05131          else if (!autofallthrough)
05132             waittime = c->pbx->rtimeoutms;
05133          if (!waittime) {
05134             const char *status = pbx_builtin_getvar_helper(c, "DIALSTATUS");
05135             if (!status)
05136                status = "UNKNOWN";
05137             ast_verb(3, "Auto fallthrough, channel '%s' status is '%s'\n", c->name, status);
05138             if (!strcasecmp(status, "CONGESTION"))
05139                res = pbx_builtin_congestion(c, "10");
05140             else if (!strcasecmp(status, "CHANUNAVAIL"))
05141                res = pbx_builtin_congestion(c, "10");
05142             else if (!strcasecmp(status, "BUSY"))
05143                res = pbx_builtin_busy(c, "10");
05144             error = 1; /* XXX disable message */
05145             break;   /* exit from the 'for' loop */
05146          }
05147 
05148          if (collect_digits(c, waittime, dst_exten, sizeof(dst_exten), pos))
05149             break;
05150          if (res == AST_PBX_INCOMPLETE && ast_strlen_zero(&dst_exten[pos]))
05151             timeout = 1;
05152          if (!timeout
05153             && ast_exists_extension(c, c->context, dst_exten, 1,
05154                S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { /* Prepare the next cycle */
05155             set_ext_pri(c, dst_exten, 1);
05156          } else {
05157             /* No such extension */
05158             if (!timeout && !ast_strlen_zero(dst_exten)) {
05159                /* An invalid extension */
05160                if (ast_exists_extension(c, c->context, "i", 1,
05161                   S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
05162                   ast_verb(3, "Invalid extension '%s' in context '%s' on %s\n", dst_exten, c->context, c->name);
05163                   pbx_builtin_setvar_helper(c, "INVALID_EXTEN", dst_exten);
05164                   set_ext_pri(c, "i", 1);
05165                } else if (ast_exists_extension(c, c->context, "e", 1,
05166                   S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
05167                   raise_exception(c, "INVALID", 1);
05168                } else {
05169                   ast_log(LOG_WARNING,
05170                      "Invalid extension '%s', but no rule 'i' or 'e' in context '%s'\n",
05171                      dst_exten, c->context);
05172                   found = 1; /* XXX disable message */
05173                   break;
05174                }
05175             } else {
05176                /* A simple timeout */
05177                if (ast_exists_extension(c, c->context, "t", 1,
05178                   S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
05179                   ast_verb(3, "Timeout on %s\n", c->name);
05180                   set_ext_pri(c, "t", 1);
05181                } else if (ast_exists_extension(c, c->context, "e", 1,
05182                   S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
05183                   raise_exception(c, "RESPONSETIMEOUT", 1);
05184                } else {
05185                   ast_log(LOG_WARNING,
05186                      "Timeout, but no rule 't' or 'e' in context '%s'\n",
05187                      c->context);
05188                   found = 1; /* XXX disable message */
05189                   break;
05190                }
05191             }
05192          }
05193          ast_channel_lock(c);
05194          if (c->cdr) {
05195             ast_verb(2, "CDR updated on %s\n",c->name);
05196             ast_cdr_update(c);
05197          }
05198          ast_channel_unlock(c);
05199       }
05200    }
05201 
05202    if (!found && !error) {
05203       ast_log(LOG_WARNING, "Don't know what to do with '%s'\n", c->name);
05204    }
05205 
05206    if (!args || !args->no_hangup_chan) {
05207       ast_softhangup(c, AST_SOFTHANGUP_APPUNLOAD);
05208    }
05209 
05210    if ((!args || !args->no_hangup_chan)
05211       && !ast_test_flag(c, AST_FLAG_BRIDGE_HANGUP_RUN)
05212       && ast_exists_extension(c, c->context, "h", 1,
05213          S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
05214       set_ext_pri(c, "h", 1);
05215       if (c->cdr && ast_opt_end_cdr_before_h_exten) {
05216          ast_cdr_end(c->cdr);
05217       }
05218       while ((res = ast_spawn_extension(c, c->context, c->exten, c->priority,
05219          S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL),
05220          &found, 1)) == 0) {
05221          c->priority++;
05222       }
05223       if (found && res) {
05224          /* Something bad happened, or a hangup has been requested. */
05225          ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
05226          ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
05227       }
05228    }
05229    ast_set2_flag(c, autoloopflag, AST_FLAG_IN_AUTOLOOP);
05230    ast_clear_flag(c, AST_FLAG_BRIDGE_HANGUP_RUN); /* from one round to the next, make sure this gets cleared */
05231    pbx_destroy(c->pbx);
05232    c->pbx = NULL;
05233 
05234    if (!args || !args->no_hangup_chan) {
05235       ast_hangup(c);
05236    }
05237 
05238    return 0;
05239 }
05240 
05241 /*!
05242  * \brief Increase call count for channel
05243  * \retval 0 on success
05244  * \retval non-zero if a configured limit (maxcalls, maxload, minmemfree) was reached 
05245 */
05246 static int increase_call_count(const struct ast_channel *c)
05247 {
05248    int failed = 0;
05249    double curloadavg;
05250 #if defined(HAVE_SYSINFO)
05251    long curfreemem;
05252    struct sysinfo sys_info;
05253 #endif
05254 
05255    ast_mutex_lock(&maxcalllock);
05256    if (option_maxcalls) {
05257       if (countcalls >= option_maxcalls) {
05258          ast_log(LOG_WARNING, "Maximum call limit of %d calls exceeded by '%s'!\n", option_maxcalls, c->name);
05259          failed = -1;
05260       }
05261    }
05262    if (option_maxload) {
05263       getloadavg(&curloadavg, 1);
05264       if (curloadavg >= option_maxload) {
05265          ast_log(LOG_WARNING, "Maximum loadavg limit of %f load exceeded by '%s' (currently %f)!\n", option_maxload, c->name, curloadavg);
05266          failed = -1;
05267       }
05268    }
05269 #if defined(HAVE_SYSINFO)
05270    if (option_minmemfree) {
05271       if (!sysinfo(&sys_info)) {
05272          /* make sure that the free system memory is above the configured low watermark
05273           * convert the amount of freeram from mem_units to MB */
05274          curfreemem = sys_info.freeram * sys_info.mem_unit;
05275          curfreemem /= 1024 * 1024;
05276          if (curfreemem < option_minmemfree) {
05277             ast_log(LOG_WARNING, "Available system memory (~%ldMB) is below the configured low watermark (%ldMB)\n", curfreemem, option_minmemfree);
05278             failed = -1;
05279          }
05280       }
05281    }
05282 #endif
05283 
05284    if (!failed) {
05285       countcalls++;
05286       totalcalls++;
05287    }
05288    ast_mutex_unlock(&maxcalllock);
05289 
05290    return failed;
05291 }
05292 
05293 static void decrease_call_count(void)
05294 {
05295    ast_mutex_lock(&maxcalllock);
05296    if (countcalls > 0)
05297       countcalls--;
05298    ast_mutex_unlock(&maxcalllock);
05299 }
05300 
05301 static void destroy_exten(struct ast_exten *e)
05302 {
05303    if (e->priority == PRIORITY_HINT)
05304       ast_remove_hint(e);
05305 
05306    if (e->peer_table)
05307       ast_hashtab_destroy(e->peer_table,0);
05308    if (e->peer_label_table)
05309       ast_hashtab_destroy(e->peer_label_table, 0);
05310    if (e->datad)
05311       e->datad(e->data);
05312    ast_free(e);
05313 }
05314 
05315 static void *pbx_thread(void *data)
05316 {
05317    /* Oh joyeous kernel, we're a new thread, with nothing to do but
05318       answer this channel and get it going.
05319    */
05320    /* NOTE:
05321       The launcher of this function _MUST_ increment 'countcalls'
05322       before invoking the function; it will be decremented when the
05323       PBX has finished running on the channel
05324     */
05325    struct ast_channel *c = data;
05326 
05327    __ast_pbx_run(c, NULL);
05328    decrease_call_count();
05329 
05330    pthread_exit(NULL);
05331 
05332    return NULL;
05333 }
05334 
05335 enum ast_pbx_result ast_pbx_start(struct ast_channel *c)
05336 {
05337    pthread_t t;
05338 
05339    if (!c) {
05340       ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n");
05341       return AST_PBX_FAILED;
05342    }
05343 
05344    if (!ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) {
05345       ast_log(LOG_WARNING, "PBX requires Asterisk to be fully booted\n");
05346       return AST_PBX_FAILED;
05347    }
05348 
05349    if (increase_call_count(c))
05350       return AST_PBX_CALL_LIMIT;
05351 
05352    /* Start a new thread, and get something handling this channel. */
05353    if (ast_pthread_create_detached(&t, NULL, pbx_thread, c)) {
05354       ast_log(LOG_WARNING, "Failed to create new channel thread\n");
05355       decrease_call_count();
05356       return AST_PBX_FAILED;
05357    }
05358 
05359    return AST_PBX_SUCCESS;
05360 }
05361 
05362 enum ast_pbx_result ast_pbx_run_args(struct ast_channel *c, struct ast_pbx_args *args)
05363 {
05364    enum ast_pbx_result res = AST_PBX_SUCCESS;
05365 
05366    if (!ast_test_flag(&ast_options, AST_OPT_FLAG_FULLY_BOOTED)) {
05367       ast_log(LOG_WARNING, "PBX requires Asterisk to be fully booted\n");
05368       return AST_PBX_FAILED;
05369    }
05370 
05371    if (increase_call_count(c)) {
05372       return AST_PBX_CALL_LIMIT;
05373    }
05374 
05375    res = __ast_pbx_run(c, args);
05376 
05377    decrease_call_count();
05378 
05379    return res;
05380 }
05381 
05382 enum ast_pbx_result ast_pbx_run(struct ast_channel *c)
05383 {
05384    return ast_pbx_run_args(c, NULL);
05385 }
05386 
05387 int ast_active_calls(void)
05388 {
05389    return countcalls;
05390 }
05391 
05392 int ast_processed_calls(void)
05393 {
05394    return totalcalls;
05395 }
05396 
05397 int pbx_set_autofallthrough(int newval)
05398 {
05399    int oldval = autofallthrough;
05400    autofallthrough = newval;
05401    return oldval;
05402 }
05403 
05404 int pbx_set_extenpatternmatchnew(int newval)
05405 {
05406    int oldval = extenpatternmatchnew;
05407    extenpatternmatchnew = newval;
05408    return oldval;
05409 }
05410 
05411 void pbx_set_overrideswitch(const char *newval)
05412 {
05413    if (overrideswitch) {
05414       ast_free(overrideswitch);
05415    }
05416    if (!ast_strlen_zero(newval)) {
05417       overrideswitch = ast_strdup(newval);
05418    } else {
05419       overrideswitch = NULL;
05420    }
05421 }
05422 
05423 /*!
05424  * \brief lookup for a context with a given name,
05425  * \retval found context or NULL if not found.
05426  */
05427 static struct ast_context *find_context(const char *context)
05428 {
05429    struct fake_context item;
05430 
05431    ast_copy_string(item.name, context, sizeof(item.name));
05432 
05433    return ast_hashtab_lookup(contexts_table, &item);
05434 }
05435 
05436 /*!
05437  * \brief lookup for a context with a given name,
05438  * \retval with conlock held if found.
05439  * \retval NULL if not found.
05440  */
05441 static struct ast_context *find_context_locked(const char *context)
05442 {
05443    struct ast_context *c;
05444    struct fake_context item;
05445 
05446    ast_copy_string(item.name, context, sizeof(item.name));
05447 
05448    ast_rdlock_contexts();
05449    c = ast_hashtab_lookup(contexts_table, &item);
05450    if (!c) {
05451       ast_unlock_contexts();
05452    }
05453 
05454    return c;
05455 }
05456 
05457 /*!
05458  * \brief Remove included contexts.
05459  * This function locks contexts list by &conlist, search for the right context
05460  * structure, leave context list locked and call ast_context_remove_include2
05461  * which removes include, unlock contexts list and return ...
05462  */
05463 int ast_context_remove_include(const char *context, const char *include, const char *registrar)
05464 {
05465    int ret = -1;
05466    struct ast_context *c;
05467 
05468    c = find_context_locked(context);
05469    if (c) {
05470       /* found, remove include from this context ... */
05471       ret = ast_context_remove_include2(c, include, registrar);
05472       ast_unlock_contexts();
05473    }
05474    return ret;
05475 }
05476 
05477 /*!
05478  * \brief Locks context, remove included contexts, unlocks context.
05479  * When we call this function, &conlock lock must be locked, because when
05480  * we giving *con argument, some process can remove/change this context
05481  * and after that there can be segfault.
05482  *
05483  * \retval 0 on success.
05484  * \retval -1 on failure.
05485  */
05486 int ast_context_remove_include2(struct ast_context *con, const char *include, const char *registrar)
05487 {
05488    struct ast_include *i, *pi = NULL;
05489    int ret = -1;
05490 
05491    ast_wrlock_context(con);
05492 
05493    /* find our include */
05494    for (i = con->includes; i; pi = i, i = i->next) {
05495       if (!strcmp(i->name, include) &&
05496             (!registrar || !strcmp(i->registrar, registrar))) {
05497          /* remove from list */
05498          ast_verb(3, "Removing inclusion of context '%s' in context '%s; registrar=%s'\n", include, ast_get_context_name(con), registrar);
05499          if (pi)
05500             pi->next = i->next;
05501          else
05502             con->includes = i->next;
05503          /* free include and return */
05504          ast_destroy_timing(&(i->timing));
05505          ast_free(i);
05506          ret = 0;
05507          break;
05508       }
05509    }
05510 
05511    ast_unlock_context(con);
05512 
05513    return ret;
05514 }
05515 
05516 /*!
05517  * \note This function locks contexts list by &conlist, search for the rigt context
05518  * structure, leave context list locked and call ast_context_remove_switch2
05519  * which removes switch, unlock contexts list and return ...
05520  */
05521 int ast_context_remove_switch(const char *context, const char *sw, const char *data, const char *registrar)
05522 {
05523    int ret = -1; /* default error return */
05524    struct ast_context *c;
05525 
05526    c = find_context_locked(context);
05527    if (c) {
05528       /* remove switch from this context ... */
05529       ret = ast_context_remove_switch2(c, sw, data, registrar);
05530       ast_unlock_contexts();
05531    }
05532    return ret;
05533 }
05534 
05535 /*!
05536  * \brief This function locks given context, removes switch, unlock context and
05537  * return.
05538  * \note When we call this function, &conlock lock must be locked, because when
05539  * we giving *con argument, some process can remove/change this context
05540  * and after that there can be segfault.
05541  *
05542  */
05543 int ast_context_remove_switch2(struct ast_context *con, const char *sw, const char *data, const char *registrar)
05544 {
05545    struct ast_sw *i;
05546    int ret = -1;
05547 
05548    ast_wrlock_context(con);
05549 
05550    /* walk switches */
05551    AST_LIST_TRAVERSE_SAFE_BEGIN(&con->alts, i, list) {
05552       if (!strcmp(i->name, sw) && !strcmp(i->data, data) &&
05553          (!registrar || !strcmp(i->registrar, registrar))) {
05554          /* found, remove from list */
05555          ast_verb(3, "Removing switch '%s' from context '%s; registrar=%s'\n", sw, ast_get_context_name(con), registrar);
05556          AST_LIST_REMOVE_CURRENT(list);
05557          ast_free(i); /* free switch and return */
05558          ret = 0;
05559          break;
05560       }
05561    }
05562    AST_LIST_TRAVERSE_SAFE_END;
05563 
05564    ast_unlock_context(con);
05565 
05566    return ret;
05567 }
05568 
05569 /*! \note This function will lock conlock. */
05570 int ast_context_remove_extension(const char *context, const char *extension, int priority, const char *registrar)
05571 {
05572    return ast_context_remove_extension_callerid(context, extension, priority, NULL, 0, registrar);
05573 }
05574 
05575 int ast_context_remove_extension_callerid(const char *context, const char *extension, int priority, const char *callerid, int matchcallerid, const char *registrar)
05576 {
05577    int ret = -1; /* default error return */
05578    struct ast_context *c;
05579 
05580    c = find_context_locked(context);
05581    if (c) { /* ... remove extension ... */
05582       ret = ast_context_remove_extension_callerid2(c, extension, priority, callerid,
05583          matchcallerid, registrar, 0);
05584       ast_unlock_contexts();
05585    }
05586 
05587    return ret;
05588 }
05589 
05590 /*!
05591  * \brief This functionc locks given context, search for the right extension and
05592  * fires out all peer in this extensions with given priority. If priority
05593  * is set to 0, all peers are removed. After that, unlock context and
05594  * return.
05595  * \note When do you want to call this function, make sure that &conlock is locked,
05596  * because some process can handle with your *con context before you lock
05597  * it.
05598  *
05599  */
05600 int ast_context_remove_extension2(struct ast_context *con, const char *extension, int priority, const char *registrar, int already_locked)
05601 {
05602    return ast_context_remove_extension_callerid2(con, extension, priority, NULL, 0, registrar, already_locked);
05603 }
05604 
05605 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)
05606 {
05607    struct ast_exten *exten, *prev_exten = NULL;
05608    struct ast_exten *peer;
05609    struct ast_exten ex, *exten2, *exten3;
05610    char dummy_name[1024];
05611    struct ast_exten *previous_peer = NULL;
05612    struct ast_exten *next_peer = NULL;
05613    int found = 0;
05614 
05615    if (!already_locked)
05616       ast_wrlock_context(con);
05617 
05618    /* Handle this is in the new world */
05619 
05620    /* FIXME For backwards compatibility, if callerid==NULL, then remove ALL
05621     * peers, not just those matching the callerid. */
05622 #ifdef NEED_DEBUG
05623    ast_verb(3,"Removing %s/%s/%d%s%s from trees, registrar=%s\n", con->name, extension, priority, matchcallerid ? "/" : "", matchcallerid ? callerid : "", registrar);
05624 #endif
05625 #ifdef CONTEXT_DEBUG
05626    check_contexts(__FILE__, __LINE__);
05627 #endif
05628    /* find this particular extension */
05629    ex.exten = dummy_name;
05630    ex.matchcid = matchcallerid && !ast_strlen_zero(callerid); /* don't say match if there's no callerid */
05631    ex.cidmatch = callerid;
05632    ast_copy_string(dummy_name, extension, sizeof(dummy_name));
05633    exten = ast_hashtab_lookup(con->root_table, &ex);
05634    if (exten) {
05635       if (priority == 0) {
05636          exten2 = ast_hashtab_remove_this_object(con->root_table, exten);
05637          if (!exten2)
05638             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);
05639          if (con->pattern_tree) {
05640             struct match_char *x = add_exten_to_pattern_tree(con, exten, 1);
05641 
05642             if (x->exten) { /* this test for safety purposes */
05643                x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */
05644                x->exten = 0; /* get rid of what will become a bad pointer */
05645             } else {
05646                ast_log(LOG_WARNING,"Trying to delete an exten from a context, but the pattern tree node returned isn't a full extension\n");
05647             }
05648          }
05649       } else {
05650          ex.priority = priority;
05651          exten2 = ast_hashtab_lookup(exten->peer_table, &ex);
05652          if (exten2) {
05653 
05654             if (exten2->label) { /* if this exten has a label, remove that, too */
05655                exten3 = ast_hashtab_remove_this_object(exten->peer_label_table,exten2);
05656                if (!exten3)
05657                   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);
05658             }
05659 
05660             exten3 = ast_hashtab_remove_this_object(exten->peer_table, exten2);
05661             if (!exten3)
05662                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);
05663             if (exten2 == exten && exten2->peer) {
05664                exten2 = ast_hashtab_remove_this_object(con->root_table, exten);
05665                ast_hashtab_insert_immediate(con->root_table, exten2->peer);
05666             }
05667             if (ast_hashtab_size(exten->peer_table) == 0) {
05668                /* well, if the last priority of an exten is to be removed,
05669                   then, the extension is removed, too! */
05670                exten3 = ast_hashtab_remove_this_object(con->root_table, exten);
05671                if (!exten3)
05672                   ast_log(LOG_ERROR,"Did not remove this exten (%s) from the context root_table (%s) (priority %d)\n", exten->exten, con->name, priority);
05673                if (con->pattern_tree) {
05674                   struct match_char *x = add_exten_to_pattern_tree(con, exten, 1);
05675                   if (x->exten) { /* this test for safety purposes */
05676                      x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */
05677                      x->exten = 0; /* get rid of what will become a bad pointer */
05678                   }
05679                }
05680             }
05681          } else {
05682             ast_log(LOG_ERROR,"Could not find priority %d of exten %s in context %s!\n",
05683                   priority, exten->exten, con->name);
05684          }
05685       }
05686    } else {
05687       /* hmmm? this exten is not in this pattern tree? */
05688       ast_log(LOG_WARNING,"Cannot find extension %s in root_table in context %s\n",
05689             extension, con->name);
05690    }
05691 #ifdef NEED_DEBUG
05692    if (con->pattern_tree) {
05693       ast_log(LOG_NOTICE,"match char tree after exten removal:\n");
05694       log_match_char_tree(con->pattern_tree, " ");
05695    }
05696 #endif
05697 
05698    /* scan the extension list to find first matching extension-registrar */
05699    for (exten = con->root; exten; prev_exten = exten, exten = exten->next) {
05700       if (!strcmp(exten->exten, extension) &&
05701          (!registrar || !strcmp(exten->registrar, registrar)) &&
05702          (!matchcallerid || (!ast_strlen_zero(callerid) && !ast_strlen_zero(exten->cidmatch) && !strcmp(exten->cidmatch, callerid)) || (ast_strlen_zero(callerid) && ast_strlen_zero(exten->cidmatch))))
05703          break;
05704    }
05705    if (!exten) {
05706       /* we can't find right extension */
05707       if (!already_locked)
05708          ast_unlock_context(con);
05709       return -1;
05710    }
05711 
05712    /* scan the priority list to remove extension with exten->priority == priority */
05713    for (peer = exten, next_peer = exten->peer ? exten->peer : exten->next;
05714        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)));
05715          peer = next_peer, next_peer = next_peer ? (next_peer->peer ? next_peer->peer : next_peer->next) : NULL) {
05716       if ((priority == 0 || peer->priority == priority) &&
05717             (!callerid || !matchcallerid || (matchcallerid && !strcmp(peer->cidmatch, callerid))) &&
05718             (!registrar || !strcmp(peer->registrar, registrar) )) {
05719          found = 1;
05720 
05721          /* we are first priority extension? */
05722          if (!previous_peer) {
05723             /*
05724              * We are first in the priority chain, so must update the extension chain.
05725              * The next node is either the next priority or the next extension
05726              */
05727             struct ast_exten *next_node = peer->peer ? peer->peer : peer->next;
05728             if (peer->peer) {
05729                /* move the peer_table and peer_label_table down to the next peer, if
05730                   it is there */
05731                peer->peer->peer_table = peer->peer_table;
05732                peer->peer->peer_label_table = peer->peer_label_table;
05733                peer->peer_table = NULL;
05734                peer->peer_label_table = NULL;
05735             }
05736             if (!prev_exten) {   /* change the root... */
05737                con->root = next_node;
05738             } else {
05739                prev_exten->next = next_node; /* unlink */
05740             }
05741             if (peer->peer)   { /* update the new head of the pri list */
05742                peer->peer->next = peer->next;
05743             }
05744          } else { /* easy, we are not first priority in extension */
05745             previous_peer->peer = peer->peer;
05746          }
05747 
05748          /* now, free whole priority extension */
05749          destroy_exten(peer);
05750       } else {
05751          previous_peer = peer;
05752       }
05753    }
05754    if (!already_locked)
05755       ast_unlock_context(con);
05756    return found ? 0 : -1;
05757 }
05758 
05759 
05760 /*!
05761  * \note This function locks contexts list by &conlist, searches for the right context
05762  * structure, and locks the macrolock mutex in that context.
05763  * macrolock is used to limit a macro to be executed by one call at a time.
05764  */
05765 int ast_context_lockmacro(const char *context)
05766 {
05767    struct ast_context *c;
05768    int ret = -1;
05769 
05770    c = find_context_locked(context);
05771    if (c) {
05772       ast_unlock_contexts();
05773 
05774       /* if we found context, lock macrolock */
05775       ret = ast_mutex_lock(&c->macrolock);
05776    }
05777 
05778    return ret;
05779 }
05780 
05781 /*!
05782  * \note This function locks contexts list by &conlist, searches for the right context
05783  * structure, and unlocks the macrolock mutex in that context.
05784  * macrolock is used to limit a macro to be executed by one call at a time.
05785  */
05786 int ast_context_unlockmacro(const char *context)
05787 {
05788    struct ast_context *c;
05789    int ret = -1;
05790 
05791    c = find_context_locked(context);
05792    if (c) {
05793       ast_unlock_contexts();
05794 
05795       /* if we found context, unlock macrolock */
05796       ret = ast_mutex_unlock(&c->macrolock);
05797    }
05798 
05799    return ret;
05800 }
05801 
05802 /*! \brief Dynamically register a new dial plan application */
05803 int ast_register_application2(const char *app, int (*execute)(struct ast_channel *, const char *), const char *synopsis, const char *description, void *mod)
05804 {
05805    struct ast_app *tmp, *cur = NULL;
05806    char tmps[80];
05807    int length, res;
05808 #ifdef AST_XML_DOCS
05809    char *tmpxml;
05810 #endif
05811 
05812    AST_RWLIST_WRLOCK(&apps);
05813    AST_RWLIST_TRAVERSE(&apps, tmp, list) {
05814       if (!(res = strcasecmp(app, tmp->name))) {
05815          ast_log(LOG_WARNING, "Already have an application '%s'\n", app);
05816          AST_RWLIST_UNLOCK(&apps);
05817          return -1;
05818       } else if (res < 0)
05819          break;
05820    }
05821 
05822    length = sizeof(*tmp) + strlen(app) + 1;
05823 
05824    if (!(tmp = ast_calloc(1, length))) {
05825       AST_RWLIST_UNLOCK(&apps);
05826       return -1;
05827    }
05828 
05829    if (ast_string_field_init(tmp, 128)) {
05830       AST_RWLIST_UNLOCK(&apps);
05831       ast_free(tmp);
05832       return -1;
05833    }
05834 
05835    strcpy(tmp->name, app);
05836    tmp->execute = execute;
05837    tmp->module = mod;
05838 
05839 #ifdef AST_XML_DOCS
05840    /* Try to lookup the docs in our XML documentation database */
05841    if (ast_strlen_zero(synopsis) && ast_strlen_zero(description)) {
05842       /* load synopsis */
05843       tmpxml = ast_xmldoc_build_synopsis("application", app, ast_module_name(tmp->module));
05844       ast_string_field_set(tmp, synopsis, tmpxml);
05845       ast_free(tmpxml);
05846 
05847       /* load description */
05848       tmpxml = ast_xmldoc_build_description("application", app, ast_module_name(tmp->module));
05849       ast_string_field_set(tmp, description, tmpxml);
05850       ast_free(tmpxml);
05851 
05852       /* load syntax */
05853       tmpxml = ast_xmldoc_build_syntax("application", app, ast_module_name(tmp->module));
05854       ast_string_field_set(tmp, syntax, tmpxml);
05855       ast_free(tmpxml);
05856 
05857       /* load arguments */
05858       tmpxml = ast_xmldoc_build_arguments("application", app, ast_module_name(tmp->module));
05859       ast_string_field_set(tmp, arguments, tmpxml);
05860       ast_free(tmpxml);
05861 
05862       /* load seealso */
05863       tmpxml = ast_xmldoc_build_seealso("application", app, ast_module_name(tmp->module));
05864       ast_string_field_set(tmp, seealso, tmpxml);
05865       ast_free(tmpxml);
05866       tmp->docsrc = AST_XML_DOC;
05867    } else {
05868 #endif
05869       ast_string_field_set(tmp, synopsis, synopsis);
05870       ast_string_field_set(tmp, description, description);
05871 #ifdef AST_XML_DOCS
05872       tmp->docsrc = AST_STATIC_DOC;
05873    }
05874 #endif
05875 
05876    /* Store in alphabetical order */
05877    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&apps, cur, list) {
05878       if (strcasecmp(tmp->name, cur->name) < 0) {
05879          AST_RWLIST_INSERT_BEFORE_CURRENT(tmp, list);
05880          break;
05881       }
05882    }
05883    AST_RWLIST_TRAVERSE_SAFE_END;
05884    if (!cur)
05885       AST_RWLIST_INSERT_TAIL(&apps, tmp, list);
05886 
05887    ast_verb(2, "Registered application '%s'\n", term_color(tmps, tmp->name, COLOR_BRCYAN, 0, sizeof(tmps)));
05888 
05889    AST_RWLIST_UNLOCK(&apps);
05890 
05891    return 0;
05892 }
05893 
05894 /*
05895  * Append to the list. We don't have a tail pointer because we need
05896  * to scan the list anyways to check for duplicates during insertion.
05897  */
05898 int ast_register_switch(struct ast_switch *sw)
05899 {
05900    struct ast_switch *tmp;
05901 
05902    AST_RWLIST_WRLOCK(&switches);
05903    AST_RWLIST_TRAVERSE(&switches, tmp, list) {
05904       if (!strcasecmp(tmp->name, sw->name)) {
05905          AST_RWLIST_UNLOCK(&switches);
05906          ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name);
05907          return -1;
05908       }
05909    }
05910    AST_RWLIST_INSERT_TAIL(&switches, sw, list);
05911    AST_RWLIST_UNLOCK(&switches);
05912 
05913    return 0;
05914 }
05915 
05916 void ast_unregister_switch(struct ast_switch *sw)
05917 {
05918    AST_RWLIST_WRLOCK(&switches);
05919    AST_RWLIST_REMOVE(&switches, sw, list);
05920    AST_RWLIST_UNLOCK(&switches);
05921 }
05922 
05923 /*
05924  * Help for CLI commands ...
05925  */
05926 
05927 static void print_app_docs(struct ast_app *aa, int fd)
05928 {
05929    /* Maximum number of characters added by terminal coloring is 22 */
05930    char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40], stxtitle[40], argtitle[40];
05931    char seealsotitle[40];
05932    char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL, *syntax = NULL, *arguments = NULL;
05933    char *seealso = NULL;
05934    int syntax_size, synopsis_size, description_size, arguments_size, seealso_size;
05935 
05936    snprintf(info, sizeof(info), "\n  -= Info about application '%s' =- \n\n", aa->name);
05937    term_color(infotitle, info, COLOR_MAGENTA, 0, sizeof(infotitle));
05938 
05939    term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40);
05940    term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40);
05941    term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, 40);
05942    term_color(argtitle, "[Arguments]\n", COLOR_MAGENTA, 0, 40);
05943    term_color(seealsotitle, "[See Also]\n", COLOR_MAGENTA, 0, 40);
05944 
05945 #ifdef AST_XML_DOCS
05946    if (aa->docsrc == AST_XML_DOC) {
05947       description = ast_xmldoc_printable(S_OR(aa->description, "Not available"), 1);
05948       arguments = ast_xmldoc_printable(S_OR(aa->arguments, "Not available"), 1);
05949       synopsis = ast_xmldoc_printable(S_OR(aa->synopsis, "Not available"), 1);
05950       seealso = ast_xmldoc_printable(S_OR(aa->seealso, "Not available"), 1);
05951 
05952       if (!synopsis || !description || !arguments || !seealso) {
05953          goto return_cleanup;
05954       }
05955    } else
05956 #endif
05957    {
05958       synopsis_size = strlen(S_OR(aa->synopsis, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
05959       synopsis = ast_malloc(synopsis_size);
05960 
05961       description_size = strlen(S_OR(aa->description, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
05962       description = ast_malloc(description_size);
05963 
05964       arguments_size = strlen(S_OR(aa->arguments, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
05965       arguments = ast_malloc(arguments_size);
05966 
05967       seealso_size = strlen(S_OR(aa->seealso, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
05968       seealso = ast_malloc(seealso_size);
05969 
05970       if (!synopsis || !description || !arguments || !seealso) {
05971          goto return_cleanup;
05972       }
05973 
05974       term_color(synopsis, S_OR(aa->synopsis, "Not available"), COLOR_CYAN, 0, synopsis_size);
05975       term_color(description, S_OR(aa->description, "Not available"),   COLOR_CYAN, 0, description_size);
05976       term_color(arguments, S_OR(aa->arguments, "Not available"), COLOR_CYAN, 0, arguments_size);
05977       term_color(seealso, S_OR(aa->seealso, "Not available"), COLOR_CYAN, 0, seealso_size);
05978    }
05979 
05980    /* Handle the syntax the same for both XML and raw docs */
05981    syntax_size = strlen(S_OR(aa->syntax, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
05982    if (!(syntax = ast_malloc(syntax_size))) {
05983       goto return_cleanup;
05984    }
05985    term_color(syntax, S_OR(aa->syntax, "Not available"), COLOR_CYAN, 0, syntax_size);
05986 
05987    ast_cli(fd, "%s%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n",
05988          infotitle, syntitle, synopsis, destitle, description,
05989          stxtitle, syntax, argtitle, arguments, seealsotitle, seealso);
05990 
05991 return_cleanup:
05992    ast_free(description);
05993    ast_free(arguments);
05994    ast_free(synopsis);
05995    ast_free(seealso);
05996    ast_free(syntax);
05997 }
05998 
05999 /*
06000  * \brief 'show application' CLI command implementation function...
06001  */
06002 static char *handle_show_application(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
06003 {
06004    struct ast_app *aa;
06005    int app, no_registered_app = 1;
06006 
06007    switch (cmd) {
06008    case CLI_INIT:
06009       e->command = "core show application";
06010       e->usage =
06011          "Usage: core show application <application> [<application> [<application> [...]]]\n"
06012          "       Describes a particular application.\n";
06013       return NULL;
06014    case CLI_GENERATE:
06015       /*
06016        * There is a possibility to show informations about more than one
06017        * application at one time. You can type 'show application Dial Echo' and
06018        * you will see informations about these two applications ...
06019        */
06020       return ast_complete_applications(a->line, a->word, a->n);
06021    }
06022 
06023    if (a->argc < 4) {
06024       return CLI_SHOWUSAGE;
06025    }
06026 
06027    AST_RWLIST_RDLOCK(&apps);
06028    AST_RWLIST_TRAVERSE(&apps, aa, list) {
06029       /* Check for each app that was supplied as an argument */
06030       for (app = 3; app < a->argc; app++) {
06031          if (strcasecmp(aa->name, a->argv[app])) {
06032             continue;
06033          }
06034 
06035          /* We found it! */
06036          no_registered_app = 0;
06037 
06038          print_app_docs(aa, a->fd);
06039       }
06040    }
06041    AST_RWLIST_UNLOCK(&apps);
06042 
06043    /* we found at least one app? no? */
06044    if (no_registered_app) {
06045       ast_cli(a->fd, "Your application(s) is (are) not registered\n");
06046       return CLI_FAILURE;
06047    }
06048 
06049    return CLI_SUCCESS;
06050 }
06051 
06052 /*! \brief  handle_show_hints: CLI support for listing registered dial plan hints */
06053 static char *handle_show_hints(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
06054 {
06055    struct ast_hint *hint;
06056    int num = 0;
06057    int watchers;
06058    struct ao2_iterator i;
06059 
06060    switch (cmd) {
06061    case CLI_INIT:
06062       e->command = "core show hints";
06063       e->usage =
06064          "Usage: core show hints\n"
06065          "       List registered hints\n";
06066       return NULL;
06067    case CLI_GENERATE:
06068       return NULL;
06069    }
06070 
06071    if (ao2_container_count(hints) == 0) {
06072       ast_cli(a->fd, "There are no registered dialplan hints\n");
06073       return CLI_SUCCESS;
06074    }
06075    /* ... we have hints ... */
06076    ast_cli(a->fd, "\n    -= Registered Asterisk Dial Plan Hints =-\n");
06077 
06078    i = ao2_iterator_init(hints, 0);
06079    for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) {
06080       ao2_lock(hint);
06081       if (!hint->exten) {
06082          /* The extension has already been destroyed */
06083          ao2_unlock(hint);
06084          continue;
06085       }
06086       watchers = ao2_container_count(hint->callbacks);
06087       ast_cli(a->fd, "   %20s@%-20.20s: %-20.20s  State:%-15.15s Watchers %2d\n",
06088          ast_get_extension_name(hint->exten),
06089          ast_get_context_name(ast_get_extension_context(hint->exten)),
06090          ast_get_extension_app(hint->exten),
06091          ast_extension_state2str(hint->laststate), watchers);
06092       ao2_unlock(hint);
06093       num++;
06094    }
06095    ao2_iterator_destroy(&i);
06096 
06097    ast_cli(a->fd, "----------------\n");
06098    ast_cli(a->fd, "- %d hints registered\n", num);
06099    return CLI_SUCCESS;
06100 }
06101 
06102 /*! \brief autocomplete for CLI command 'core show hint' */
06103 static char *complete_core_show_hint(const char *line, const char *word, int pos, int state)
06104 {
06105    struct ast_hint *hint;
06106    char *ret = NULL;
06107    int which = 0;
06108    int wordlen;
06109    struct ao2_iterator i;
06110 
06111    if (pos != 3)
06112       return NULL;
06113 
06114    wordlen = strlen(word);
06115 
06116    /* walk through all hints */
06117    i = ao2_iterator_init(hints, 0);
06118    for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) {
06119       ao2_lock(hint);
06120       if (!hint->exten) {
06121          /* The extension has already been destroyed */
06122          ao2_unlock(hint);
06123          continue;
06124       }
06125       if (!strncasecmp(word, ast_get_extension_name(hint->exten), wordlen) && ++which > state) {
06126          ret = ast_strdup(ast_get_extension_name(hint->exten));
06127          ao2_unlock(hint);
06128          ao2_ref(hint, -1);
06129          break;
06130       }
06131       ao2_unlock(hint);
06132    }
06133    ao2_iterator_destroy(&i);
06134 
06135    return ret;
06136 }
06137 
06138 /*! \brief  handle_show_hint: CLI support for listing registered dial plan hint */
06139 static char *handle_show_hint(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
06140 {
06141    struct ast_hint *hint;
06142    int watchers;
06143    int num = 0, extenlen;
06144    struct ao2_iterator i;
06145 
06146    switch (cmd) {
06147    case CLI_INIT:
06148       e->command = "core show hint";
06149       e->usage =
06150          "Usage: core show hint <exten>\n"
06151          "       List registered hint\n";
06152       return NULL;
06153    case CLI_GENERATE:
06154       return complete_core_show_hint(a->line, a->word, a->pos, a->n);
06155    }
06156 
06157    if (a->argc < 4)
06158       return CLI_SHOWUSAGE;
06159 
06160    if (ao2_container_count(hints) == 0) {
06161       ast_cli(a->fd, "There are no registered dialplan hints\n");
06162       return CLI_SUCCESS;
06163    }
06164    
06165    extenlen = strlen(a->argv[3]);
06166    i = ao2_iterator_init(hints, 0);
06167    for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) {
06168       ao2_lock(hint);
06169       if (!hint->exten) {
06170          /* The extension has already been destroyed */
06171          ao2_unlock(hint);
06172          continue;
06173       }
06174       if (!strncasecmp(ast_get_extension_name(hint->exten), a->argv[3], extenlen)) {
06175          watchers = ao2_container_count(hint->callbacks);
06176          ast_cli(a->fd, "   %20s@%-20.20s: %-20.20s  State:%-15.15s Watchers %2d\n",
06177             ast_get_extension_name(hint->exten),
06178             ast_get_context_name(ast_get_extension_context(hint->exten)),
06179             ast_get_extension_app(hint->exten),
06180             ast_extension_state2str(hint->laststate), watchers);
06181          num++;
06182       }
06183       ao2_unlock(hint);
06184    }
06185    ao2_iterator_destroy(&i);
06186    if (!num)
06187       ast_cli(a->fd, "No hints matching extension %s\n", a->argv[3]);
06188    else
06189       ast_cli(a->fd, "%d hint%s matching extension %s\n", num, (num!=1 ? "s":""), a->argv[3]);
06190    return CLI_SUCCESS;
06191 }
06192 
06193 
06194 /*! \brief  handle_show_switches: CLI support for listing registered dial plan switches */
06195 static char *handle_show_switches(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
06196 {
06197    struct ast_switch *sw;
06198 
06199    switch (cmd) {
06200    case CLI_INIT:
06201       e->command = "core show switches";
06202       e->usage =
06203          "Usage: core show switches\n"
06204          "       List registered switches\n";
06205       return NULL;
06206    case CLI_GENERATE:
06207       return NULL;
06208    }
06209 
06210    AST_RWLIST_RDLOCK(&switches);
06211 
06212    if (AST_RWLIST_EMPTY(&switches)) {
06213       AST_RWLIST_UNLOCK(&switches);
06214       ast_cli(a->fd, "There are no registered alternative switches\n");
06215       return CLI_SUCCESS;
06216    }
06217 
06218    ast_cli(a->fd, "\n    -= Registered Asterisk Alternative Switches =-\n");
06219    AST_RWLIST_TRAVERSE(&switches, sw, list)
06220       ast_cli(a->fd, "%s: %s\n", sw->name, sw->description);
06221 
06222    AST_RWLIST_UNLOCK(&switches);
06223 
06224    return CLI_SUCCESS;
06225 }
06226 
06227 static char *handle_show_applications(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
06228 {
06229    struct ast_app *aa;
06230    int like = 0, describing = 0;
06231    int total_match = 0;    /* Number of matches in like clause */
06232    int total_apps = 0;     /* Number of apps registered */
06233    static const char * const choices[] = { "like", "describing", NULL };
06234 
06235    switch (cmd) {
06236    case CLI_INIT:
06237       e->command = "core show applications [like|describing]";
06238       e->usage =
06239          "Usage: core show applications [{like|describing} <text>]\n"
06240          "       List applications which are currently available.\n"
06241          "       If 'like', <text> will be a substring of the app name\n"
06242          "       If 'describing', <text> will be a substring of the description\n";
06243       return NULL;
06244    case CLI_GENERATE:
06245       return (a->pos != 3) ? NULL : ast_cli_complete(a->word, choices, a->n);
06246    }
06247 
06248    AST_RWLIST_RDLOCK(&apps);
06249 
06250    if (AST_RWLIST_EMPTY(&apps)) {
06251       ast_cli(a->fd, "There are no registered applications\n");
06252       AST_RWLIST_UNLOCK(&apps);
06253       return CLI_SUCCESS;
06254    }
06255 
06256    /* core list applications like <keyword> */
06257    if ((a->argc == 5) && (!strcmp(a->argv[3], "like"))) {
06258       like = 1;
06259    } else if ((a->argc > 4) && (!strcmp(a->argv[3], "describing"))) {
06260       describing = 1;
06261    }
06262 
06263    /* core list applications describing <keyword1> [<keyword2>] [...] */
06264    if ((!like) && (!describing)) {
06265       ast_cli(a->fd, "    -= Registered Asterisk Applications =-\n");
06266    } else {
06267       ast_cli(a->fd, "    -= Matching Asterisk Applications =-\n");
06268    }
06269 
06270    AST_RWLIST_TRAVERSE(&apps, aa, list) {
06271       int printapp = 0;
06272       total_apps++;
06273       if (like) {
06274          if (strcasestr(aa->name, a->argv[4])) {
06275             printapp = 1;
06276             total_match++;
06277          }
06278       } else if (describing) {
06279          if (aa->description) {
06280             /* Match all words on command line */
06281             int i;
06282             printapp = 1;
06283             for (i = 4; i < a->argc; i++) {
06284                if (!strcasestr(aa->description, a->argv[i])) {
06285                   printapp = 0;
06286                } else {
06287                   total_match++;
06288                }
06289             }
06290          }
06291       } else {
06292          printapp = 1;
06293       }
06294 
06295       if (printapp) {
06296          ast_cli(a->fd,"  %20s: %s\n", aa->name, aa->synopsis ? aa->synopsis : "<Synopsis not available>");
06297       }
06298    }
06299    if ((!like) && (!describing)) {
06300       ast_cli(a->fd, "    -= %d Applications Registered =-\n",total_apps);
06301    } else {
06302       ast_cli(a->fd, "    -= %d Applications Matching =-\n",total_match);
06303    }
06304 
06305    AST_RWLIST_UNLOCK(&apps);
06306 
06307    return CLI_SUCCESS;
06308 }
06309 
06310 /*
06311  * 'show dialplan' CLI command implementation functions ...
06312  */
06313 static char *complete_show_dialplan_context(const char *line, const char *word, int pos,
06314    int state)
06315 {
06316    struct ast_context *c = NULL;
06317    char *ret = NULL;
06318    int which = 0;
06319    int wordlen;
06320 
06321    /* we are do completion of [exten@]context on second position only */
06322    if (pos != 2)
06323       return NULL;
06324 
06325    ast_rdlock_contexts();
06326 
06327    wordlen = strlen(word);
06328 
06329    /* walk through all contexts and return the n-th match */
06330    while ( (c = ast_walk_contexts(c)) ) {
06331       if (!strncasecmp(word, ast_get_context_name(c), wordlen) && ++which > state) {
06332          ret = ast_strdup(ast_get_context_name(c));
06333          break;
06334       }
06335    }
06336 
06337    ast_unlock_contexts();
06338 
06339    return ret;
06340 }
06341 
06342 /*! \brief Counters for the show dialplan manager command */
06343 struct dialplan_counters {
06344    int total_items;
06345    int total_context;
06346    int total_exten;
06347    int total_prio;
06348    int context_existence;
06349    int extension_existence;
06350 };
06351 
06352 /*! \brief helper function to print an extension */
06353 static void print_ext(struct ast_exten *e, char * buf, int buflen)
06354 {
06355    int prio = ast_get_extension_priority(e);
06356    if (prio == PRIORITY_HINT) {
06357       snprintf(buf, buflen, "hint: %s",
06358          ast_get_extension_app(e));
06359    } else {
06360       snprintf(buf, buflen, "%d. %s(%s)",
06361          prio, ast_get_extension_app(e),
06362          (!ast_strlen_zero(ast_get_extension_app_data(e)) ? (char *)ast_get_extension_app_data(e) : ""));
06363    }
06364 }
06365 
06366 /* XXX not verified */
06367 static int show_dialplan_helper(int fd, const char *context, const char *exten, struct dialplan_counters *dpc, struct ast_include *rinclude, int includecount, const char *includes[])
06368 {
06369    struct ast_context *c = NULL;
06370    int res = 0, old_total_exten = dpc->total_exten;
06371 
06372    ast_rdlock_contexts();
06373 
06374    /* walk all contexts ... */
06375    while ( (c = ast_walk_contexts(c)) ) {
06376       struct ast_exten *e;
06377       struct ast_include *i;
06378       struct ast_ignorepat *ip;
06379       char buf[256], buf2[256];
06380       int context_info_printed = 0;
06381 
06382       if (context && strcmp(ast_get_context_name(c), context))
06383          continue;   /* skip this one, name doesn't match */
06384 
06385       dpc->context_existence = 1;
06386 
06387       ast_rdlock_context(c);
06388 
06389       /* are we looking for exten too? if yes, we print context
06390        * only if we find our extension.
06391        * Otherwise print context even if empty ?
06392        * XXX i am not sure how the rinclude is handled.
06393        * I think it ought to go inside.
06394        */
06395       if (!exten) {
06396          dpc->total_context++;
06397          ast_cli(fd, "[ Context '%s' created by '%s' ]\n",
06398             ast_get_context_name(c), ast_get_context_registrar(c));
06399          context_info_printed = 1;
06400       }
06401 
06402       /* walk extensions ... */
06403       e = NULL;
06404       while ( (e = ast_walk_context_extensions(c, e)) ) {
06405          struct ast_exten *p;
06406 
06407          if (exten && !ast_extension_match(ast_get_extension_name(e), exten))
06408             continue;   /* skip, extension match failed */
06409 
06410          dpc->extension_existence = 1;
06411 
06412          /* may we print context info? */
06413          if (!context_info_printed) {
06414             dpc->total_context++;
06415             if (rinclude) { /* TODO Print more info about rinclude */
06416                ast_cli(fd, "[ Included context '%s' created by '%s' ]\n",
06417                   ast_get_context_name(c), ast_get_context_registrar(c));
06418             } else {
06419                ast_cli(fd, "[ Context '%s' created by '%s' ]\n",
06420                   ast_get_context_name(c), ast_get_context_registrar(c));
06421             }
06422             context_info_printed = 1;
06423          }
06424          dpc->total_prio++;
06425 
06426          /* write extension name and first peer */
06427          if (e->matchcid)
06428             snprintf(buf, sizeof(buf), "'%s' (CID match '%s') => ", ast_get_extension_name(e), e->cidmatch);
06429          else
06430             snprintf(buf, sizeof(buf), "'%s' =>", ast_get_extension_name(e));
06431 
06432          print_ext(e, buf2, sizeof(buf2));
06433 
06434          ast_cli(fd, "  %-17s %-45s [%s]\n", buf, buf2,
06435             ast_get_extension_registrar(e));
06436 
06437          dpc->total_exten++;
06438          /* walk next extension peers */
06439          p = e;   /* skip the first one, we already got it */
06440          while ( (p = ast_walk_extension_priorities(e, p)) ) {
06441             const char *el = ast_get_extension_label(p);
06442             dpc->total_prio++;
06443             if (el)
06444                snprintf(buf, sizeof(buf), "   [%s]", el);
06445             else
06446                buf[0] = '\0';
06447             print_ext(p, buf2, sizeof(buf2));
06448 
06449             ast_cli(fd,"  %-17s %-45s [%s]\n", buf, buf2,
06450                ast_get_extension_registrar(p));
06451          }
06452       }
06453 
06454       /* walk included and write info ... */
06455       i = NULL;
06456       while ( (i = ast_walk_context_includes(c, i)) ) {
06457          snprintf(buf, sizeof(buf), "'%s'", ast_get_include_name(i));
06458          if (exten) {
06459             /* Check all includes for the requested extension */
06460             if (includecount >= AST_PBX_MAX_STACK) {
06461                ast_log(LOG_WARNING, "Maximum include depth exceeded!\n");
06462             } else {
06463                int dupe = 0;
06464                int x;
06465                for (x = 0; x < includecount; x++) {
06466                   if (!strcasecmp(includes[x], ast_get_include_name(i))) {
06467                      dupe++;
06468                      break;
06469                   }
06470                }
06471                if (!dupe) {
06472                   includes[includecount] = ast_get_include_name(i);
06473                   show_dialplan_helper(fd, ast_get_include_name(i), exten, dpc, i, includecount + 1, includes);
06474                } else {
06475                   ast_log(LOG_WARNING, "Avoiding circular include of %s within %s\n", ast_get_include_name(i), context);
06476                }
06477             }
06478          } else {
06479             ast_cli(fd, "  Include =>        %-45s [%s]\n",
06480                buf, ast_get_include_registrar(i));
06481          }
06482       }
06483 
06484       /* walk ignore patterns and write info ... */
06485       ip = NULL;
06486       while ( (ip = ast_walk_context_ignorepats(c, ip)) ) {
06487          const char *ipname = ast_get_ignorepat_name(ip);
06488          char ignorepat[AST_MAX_EXTENSION];
06489          snprintf(buf, sizeof(buf), "'%s'", ipname);
06490          snprintf(ignorepat, sizeof(ignorepat), "_%s.", ipname);
06491          if (!exten || ast_extension_match(ignorepat, exten)) {
06492             ast_cli(fd, "  Ignore pattern => %-45s [%s]\n",
06493                buf, ast_get_ignorepat_registrar(ip));
06494          }
06495       }
06496       if (!rinclude) {
06497          struct ast_sw *sw = NULL;
06498          while ( (sw = ast_walk_context_switches(c, sw)) ) {
06499             snprintf(buf, sizeof(buf), "'%s/%s'",
06500                ast_get_switch_name(sw),
06501                ast_get_switch_data(sw));
06502             ast_cli(fd, "  Alt. Switch =>    %-45s [%s]\n",
06503                buf, ast_get_switch_registrar(sw));
06504          }
06505       }
06506 
06507       ast_unlock_context(c);
06508 
06509       /* if we print something in context, make an empty line */
06510       if (context_info_printed)
06511          ast_cli(fd, "\n");
06512    }
06513    ast_unlock_contexts();
06514 
06515    return (dpc->total_exten == old_total_exten) ? -1 : res;
06516 }
06517 
06518 static int show_debug_helper(int fd, const char *context, const char *exten, struct dialplan_counters *dpc, struct ast_include *rinclude, int includecount, const char *includes[])
06519 {
06520    struct ast_context *c = NULL;
06521    int res = 0, old_total_exten = dpc->total_exten;
06522 
06523    ast_cli(fd,"\n     In-mem exten Trie for Fast Extension Pattern Matching:\n\n");
06524 
06525    ast_cli(fd,"\n           Explanation: Node Contents Format = <char(s) to match>:<pattern?>:<specif>:[matched extension]\n");
06526    ast_cli(fd,    "                        Where <char(s) to match> is a set of chars, any one of which should match the current character\n");
06527    ast_cli(fd,    "                              <pattern?>: Y if this a pattern match (eg. _XZN[5-7]), N otherwise\n");
06528    ast_cli(fd,    "                              <specif>: an assigned 'exactness' number for this matching char. The lower the number, the more exact the match\n");
06529    ast_cli(fd,    "                              [matched exten]: If all chars matched to this point, which extension this matches. In form: EXTEN:<exten string>\n");
06530    ast_cli(fd,    "                        In general, you match a trie node to a string character, from left to right. All possible matching chars\n");
06531    ast_cli(fd,    "                        are in a string vertically, separated by an unbroken string of '+' characters.\n\n");
06532    ast_rdlock_contexts();
06533 
06534    /* walk all contexts ... */
06535    while ( (c = ast_walk_contexts(c)) ) {
06536       int context_info_printed = 0;
06537 
06538       if (context && strcmp(ast_get_context_name(c), context))
06539          continue;   /* skip this one, name doesn't match */
06540 
06541       dpc->context_existence = 1;
06542 
06543       if (!c->pattern_tree)
06544          ast_exists_extension(NULL, c->name, "s", 1, ""); /* do this to force the trie to built, if it is not already */
06545 
06546       ast_rdlock_context(c);
06547 
06548       dpc->total_context++;
06549       ast_cli(fd, "[ Context '%s' created by '%s' ]\n",
06550          ast_get_context_name(c), ast_get_context_registrar(c));
06551       context_info_printed = 1;
06552 
06553       if (c->pattern_tree)
06554       {
06555          cli_match_char_tree(c->pattern_tree, " ", fd);
06556       } else {
06557          ast_cli(fd,"\n     No Pattern Trie present. Perhaps the context is empty...or there is trouble...\n\n");
06558       }
06559 
06560       ast_unlock_context(c);
06561 
06562       /* if we print something in context, make an empty line */
06563       if (context_info_printed)
06564          ast_cli(fd, "\n");
06565    }
06566    ast_unlock_contexts();
06567 
06568    return (dpc->total_exten == old_total_exten) ? -1 : res;
06569 }
06570 
06571 static char *handle_show_dialplan(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
06572 {
06573    char *exten = NULL, *context = NULL;
06574    /* Variables used for different counters */
06575    struct dialplan_counters counters;
06576    const char *incstack[AST_PBX_MAX_STACK];
06577 
06578    switch (cmd) {
06579    case CLI_INIT:
06580       e->command = "dialplan show";
06581       e->usage =
06582          "Usage: dialplan show [[exten@]context]\n"
06583          "       Show dialplan\n";
06584       return NULL;
06585    case CLI_GENERATE:
06586       return complete_show_dialplan_context(a->line, a->word, a->pos, a->n);
06587    }
06588 
06589    memset(&counters, 0, sizeof(counters));
06590 
06591    if (a->argc != 2 && a->argc != 3)
06592       return CLI_SHOWUSAGE;
06593 
06594    /* we obtain [exten@]context? if yes, split them ... */
06595    if (a->argc == 3) {
06596       if (strchr(a->argv[2], '@')) {   /* split into exten & context */
06597          context = ast_strdupa(a->argv[2]);
06598          exten = strsep(&context, "@");
06599          /* change empty strings to NULL */
06600          if (ast_strlen_zero(exten))
06601             exten = NULL;
06602       } else { /* no '@' char, only context given */
06603          context = ast_strdupa(a->argv[2]);
06604       }
06605       if (ast_strlen_zero(context))
06606          context = NULL;
06607    }
06608    /* else Show complete dial plan, context and exten are NULL */
06609    show_dialplan_helper(a->fd, context, exten, &counters, NULL, 0, incstack);
06610 
06611    /* check for input failure and throw some error messages */
06612    if (context && !counters.context_existence) {
06613       ast_cli(a->fd, "There is no existence of '%s' context\n", context);
06614       return CLI_FAILURE;
06615    }
06616 
06617    if (exten && !counters.extension_existence) {
06618       if (context)
06619          ast_cli(a->fd, "There is no existence of %s@%s extension\n",
06620             exten, context);
06621       else
06622          ast_cli(a->fd,
06623             "There is no existence of '%s' extension in all contexts\n",
06624             exten);
06625       return CLI_FAILURE;
06626    }
06627 
06628    ast_cli(a->fd,"-= %d %s (%d %s) in %d %s. =-\n",
06629             counters.total_exten, counters.total_exten == 1 ? "extension" : "extensions",
06630             counters.total_prio, counters.total_prio == 1 ? "priority" : "priorities",
06631             counters.total_context, counters.total_context == 1 ? "context" : "contexts");
06632 
06633    /* everything ok */
06634    return CLI_SUCCESS;
06635 }
06636 
06637 /*! \brief Send ack once */
06638 static char *handle_debug_dialplan(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
06639 {
06640    char *exten = NULL, *context = NULL;
06641    /* Variables used for different counters */
06642    struct dialplan_counters counters;
06643    const char *incstack[AST_PBX_MAX_STACK];
06644 
06645    switch (cmd) {
06646    case CLI_INIT:
06647       e->command = "dialplan debug";
06648       e->usage =
06649          "Usage: dialplan debug [context]\n"
06650          "       Show dialplan context Trie(s). Usually only useful to folks debugging the deep internals of the fast pattern matcher\n";
06651       return NULL;
06652    case CLI_GENERATE:
06653       return complete_show_dialplan_context(a->line, a->word, a->pos, a->n);
06654    }
06655 
06656    memset(&counters, 0, sizeof(counters));
06657 
06658    if (a->argc != 2 && a->argc != 3)
06659       return CLI_SHOWUSAGE;
06660 
06661    /* we obtain [exten@]context? if yes, split them ... */
06662    /* note: we ignore the exten totally here .... */
06663    if (a->argc == 3) {
06664       if (strchr(a->argv[2], '@')) {   /* split into exten & context */
06665          context = ast_strdupa(a->argv[2]);
06666          exten = strsep(&context, "@");
06667          /* change empty strings to NULL */
06668          if (ast_strlen_zero(exten))
06669             exten = NULL;
06670       } else { /* no '@' char, only context given */
06671          context = ast_strdupa(a->argv[2]);
06672       }
06673       if (ast_strlen_zero(context))
06674          context = NULL;
06675    }
06676    /* else Show complete dial plan, context and exten are NULL */
06677    show_debug_helper(a->fd, context, exten, &counters, NULL, 0, incstack);
06678 
06679    /* check for input failure and throw some error messages */
06680    if (context && !counters.context_existence) {
06681       ast_cli(a->fd, "There is no existence of '%s' context\n", context);
06682       return CLI_FAILURE;
06683    }
06684 
06685 
06686    ast_cli(a->fd,"-= %d %s. =-\n",
06687          counters.total_context, counters.total_context == 1 ? "context" : "contexts");
06688 
06689    /* everything ok */
06690    return CLI_SUCCESS;
06691 }
06692 
06693 /*! \brief Send ack once */
06694 static void manager_dpsendack(struct mansession *s, const struct message *m)
06695 {
06696    astman_send_listack(s, m, "DialPlan list will follow", "start");
06697 }
06698 
06699 /*! \brief Show dialplan extensions
06700  * XXX this function is similar but not exactly the same as the CLI's
06701  * show dialplan. Must check whether the difference is intentional or not.
06702  */
06703 static int manager_show_dialplan_helper(struct mansession *s, const struct message *m,
06704                const char *actionidtext, const char *context,
06705                const char *exten, struct dialplan_counters *dpc,
06706                struct ast_include *rinclude)
06707 {
06708    struct ast_context *c;
06709    int res = 0, old_total_exten = dpc->total_exten;
06710 
06711    if (ast_strlen_zero(exten))
06712       exten = NULL;
06713    if (ast_strlen_zero(context))
06714       context = NULL;
06715 
06716    ast_debug(3, "manager_show_dialplan: Context: -%s- Extension: -%s-\n", context, exten);
06717 
06718    /* try to lock contexts */
06719    if (ast_rdlock_contexts()) {
06720       astman_send_error(s, m, "Failed to lock contexts");
06721       ast_log(LOG_WARNING, "Failed to lock contexts list for manager: listdialplan\n");
06722       return -1;
06723    }
06724 
06725    c = NULL;      /* walk all contexts ... */
06726    while ( (c = ast_walk_contexts(c)) ) {
06727       struct ast_exten *e;
06728       struct ast_include *i;
06729       struct ast_ignorepat *ip;
06730 
06731       if (context && strcmp(ast_get_context_name(c), context) != 0)
06732          continue;   /* not the name we want */
06733 
06734       dpc->context_existence = 1;
06735 
06736       ast_debug(3, "manager_show_dialplan: Found Context: %s \n", ast_get_context_name(c));
06737 
06738       if (ast_rdlock_context(c)) {  /* failed to lock */
06739          ast_debug(3, "manager_show_dialplan: Failed to lock context\n");
06740          continue;
06741       }
06742 
06743       /* XXX note- an empty context is not printed */
06744       e = NULL;      /* walk extensions in context  */
06745       while ( (e = ast_walk_context_extensions(c, e)) ) {
06746          struct ast_exten *p;
06747 
06748          /* looking for extension? is this our extension? */
06749          if (exten && !ast_extension_match(ast_get_extension_name(e), exten)) {
06750             /* not the one we are looking for, continue */
06751             ast_debug(3, "manager_show_dialplan: Skipping extension %s\n", ast_get_extension_name(e));
06752             continue;
06753          }
06754          ast_debug(3, "manager_show_dialplan: Found Extension: %s \n", ast_get_extension_name(e));
06755 
06756          dpc->extension_existence = 1;
06757 
06758          /* may we print context info? */
06759          dpc->total_context++;
06760          dpc->total_exten++;
06761 
06762          p = NULL;      /* walk next extension peers */
06763          while ( (p = ast_walk_extension_priorities(e, p)) ) {
06764             int prio = ast_get_extension_priority(p);
06765 
06766             dpc->total_prio++;
06767             if (!dpc->total_items++)
06768                manager_dpsendack(s, m);
06769             astman_append(s, "Event: ListDialplan\r\n%s", actionidtext);
06770             astman_append(s, "Context: %s\r\nExtension: %s\r\n", ast_get_context_name(c), ast_get_extension_name(e) );
06771 
06772             /* XXX maybe make this conditional, if p != e ? */
06773             if (ast_get_extension_label(p))
06774                astman_append(s, "ExtensionLabel: %s\r\n", ast_get_extension_label(p));
06775 
06776             if (prio == PRIORITY_HINT) {
06777                astman_append(s, "Priority: hint\r\nApplication: %s\r\n", ast_get_extension_app(p));
06778             } else {
06779                astman_append(s, "Priority: %d\r\nApplication: %s\r\nAppData: %s\r\n", prio, ast_get_extension_app(p), (char *) ast_get_extension_app_data(p));
06780             }
06781             astman_append(s, "Registrar: %s\r\n\r\n", ast_get_extension_registrar(e));
06782          }
06783       }
06784 
06785       i = NULL;      /* walk included and write info ... */
06786       while ( (i = ast_walk_context_includes(c, i)) ) {
06787          if (exten) {
06788             /* Check all includes for the requested extension */
06789             manager_show_dialplan_helper(s, m, actionidtext, ast_get_include_name(i), exten, dpc, i);
06790          } else {
06791             if (!dpc->total_items++)
06792                manager_dpsendack(s, m);
06793             astman_append(s, "Event: ListDialplan\r\n%s", actionidtext);
06794             astman_append(s, "Context: %s\r\nIncludeContext: %s\r\nRegistrar: %s\r\n", ast_get_context_name(c), ast_get_include_name(i), ast_get_include_registrar(i));
06795             astman_append(s, "\r\n");
06796             ast_debug(3, "manager_show_dialplan: Found Included context: %s \n", ast_get_include_name(i));
06797          }
06798       }
06799 
06800       ip = NULL;  /* walk ignore patterns and write info ... */
06801       while ( (ip = ast_walk_context_ignorepats(c, ip)) ) {
06802          const char *ipname = ast_get_ignorepat_name(ip);
06803          char ignorepat[AST_MAX_EXTENSION];
06804 
06805          snprintf(ignorepat, sizeof(ignorepat), "_%s.", ipname);
06806          if (!exten || ast_extension_match(ignorepat, exten)) {
06807             if (!dpc->total_items++)
06808                manager_dpsendack(s, m);
06809             astman_append(s, "Event: ListDialplan\r\n%s", actionidtext);
06810             astman_append(s, "Context: %s\r\nIgnorePattern: %s\r\nRegistrar: %s\r\n", ast_get_context_name(c), ipname, ast_get_ignorepat_registrar(ip));
06811             astman_append(s, "\r\n");
06812          }
06813       }
06814       if (!rinclude) {
06815          struct ast_sw *sw = NULL;
06816          while ( (sw = ast_walk_context_switches(c, sw)) ) {
06817             if (!dpc->total_items++)
06818                manager_dpsendack(s, m);
06819             astman_append(s, "Event: ListDialplan\r\n%s", actionidtext);
06820             astman_append(s, "Context: %s\r\nSwitch: %s/%s\r\nRegistrar: %s\r\n", ast_get_context_name(c), ast_get_switch_name(sw), ast_get_switch_data(sw), ast_get_switch_registrar(sw));  
06821             astman_append(s, "\r\n");
06822             ast_debug(3, "manager_show_dialplan: Found Switch : %s \n", ast_get_switch_name(sw));
06823          }
06824       }
06825 
06826       ast_unlock_context(c);
06827    }
06828    ast_unlock_contexts();
06829 
06830    if (dpc->total_exten == old_total_exten) {
06831       ast_debug(3, "manager_show_dialplan: Found nothing new\n");
06832       /* Nothing new under the sun */
06833       return -1;
06834    } else {
06835       return res;
06836    }
06837 }
06838 
06839 /*! \brief  Manager listing of dial plan */
06840 static int manager_show_dialplan(struct mansession *s, const struct message *m)
06841 {
06842    const char *exten, *context;
06843    const char *id = astman_get_header(m, "ActionID");
06844    char idtext[256];
06845 
06846    /* Variables used for different counters */
06847    struct dialplan_counters counters;
06848 
06849    if (!ast_strlen_zero(id))
06850       snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id);
06851    else
06852       idtext[0] = '\0';
06853 
06854    memset(&counters, 0, sizeof(counters));
06855 
06856    exten = astman_get_header(m, "Extension");
06857    context = astman_get_header(m, "Context");
06858 
06859    manager_show_dialplan_helper(s, m, idtext, context, exten, &counters, NULL);
06860 
06861    if (context && !counters.context_existence) {
06862       char errorbuf[BUFSIZ];
06863 
06864       snprintf(errorbuf, sizeof(errorbuf), "Did not find context %s", context);
06865       astman_send_error(s, m, errorbuf);
06866       return 0;
06867    }
06868    if (exten && !counters.extension_existence) {
06869       char errorbuf[BUFSIZ];
06870 
06871       if (context)
06872          snprintf(errorbuf, sizeof(errorbuf), "Did not find extension %s@%s", exten, context);
06873       else
06874          snprintf(errorbuf, sizeof(errorbuf), "Did not find extension %s in any context", exten);
06875       astman_send_error(s, m, errorbuf);
06876       return 0;
06877    }
06878 
06879    astman_append(s, "Event: ShowDialPlanComplete\r\n"
06880       "EventList: Complete\r\n"
06881       "ListItems: %d\r\n"
06882       "ListExtensions: %d\r\n"
06883       "ListPriorities: %d\r\n"
06884       "ListContexts: %d\r\n"
06885       "%s"
06886       "\r\n", counters.total_items, counters.total_exten, counters.total_prio, counters.total_context, idtext);
06887 
06888    /* everything ok */
06889    return 0;
06890 }
06891 
06892 /*! \brief CLI support for listing global variables in a parseable way */
06893 static char *handle_show_globals(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
06894 {
06895    int i = 0;
06896    struct ast_var_t *newvariable;
06897 
06898    switch (cmd) {
06899    case CLI_INIT:
06900       e->command = "dialplan show globals";
06901       e->usage =
06902          "Usage: dialplan show globals\n"
06903          "       List current global dialplan variables and their values\n";
06904       return NULL;
06905    case CLI_GENERATE:
06906       return NULL;
06907    }
06908 
06909    ast_rwlock_rdlock(&globalslock);
06910    AST_LIST_TRAVERSE (&globals, newvariable, entries) {
06911       i++;
06912       ast_cli(a->fd, "   %s=%s\n", ast_var_name(newvariable), ast_var_value(newvariable));
06913    }
06914    ast_rwlock_unlock(&globalslock);
06915    ast_cli(a->fd, "\n    -- %d variable(s)\n", i);
06916 
06917    return CLI_SUCCESS;
06918 }
06919 
06920 #ifdef AST_DEVMODE
06921 static char *handle_show_device2extenstate(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
06922 {
06923    struct ast_devstate_aggregate agg;
06924    int i, j, exten, combined;
06925 
06926    switch (cmd) {
06927    case CLI_INIT:
06928       e->command = "core show device2extenstate";
06929       e->usage =
06930          "Usage: core show device2extenstate\n"
06931          "       Lists device state to extension state combinations.\n";
06932    case CLI_GENERATE:
06933       return NULL;
06934    }
06935    for (i = 0; i < AST_DEVICE_TOTAL; i++) {
06936       for (j = 0; j < AST_DEVICE_TOTAL; j++) {
06937          ast_devstate_aggregate_init(&agg);
06938          ast_devstate_aggregate_add(&agg, i);
06939          ast_devstate_aggregate_add(&agg, j);
06940          combined = ast_devstate_aggregate_result(&agg);
06941          exten = ast_devstate_to_extenstate(combined);
06942          ast_cli(a->fd, "\n Exten:%14s  CombinedDevice:%12s  Dev1:%12s  Dev2:%12s", ast_extension_state2str(exten), ast_devstate_str(combined), ast_devstate_str(j), ast_devstate_str(i));
06943       }
06944    }
06945    ast_cli(a->fd, "\n");
06946    return CLI_SUCCESS;
06947 }
06948 #endif
06949 
06950 /*! \brief CLI support for listing chanvar's variables in a parseable way */
06951 static char *handle_show_chanvar(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
06952 {
06953    struct ast_channel *chan = NULL;
06954    struct ast_str *vars = ast_str_alloca(BUFSIZ * 4); /* XXX large because we might have lots of channel vars */
06955 
06956    switch (cmd) {
06957    case CLI_INIT:
06958       e->command = "dialplan show chanvar";
06959       e->usage =
06960          "Usage: dialplan show chanvar <channel>\n"
06961          "       List current channel variables and their values\n";
06962       return NULL;
06963    case CLI_GENERATE:
06964       return ast_complete_channels(a->line, a->word, a->pos, a->n, 3);
06965    }
06966 
06967    if (a->argc != e->args + 1)
06968       return CLI_SHOWUSAGE;
06969 
06970    if (!(chan = ast_channel_get_by_name(a->argv[e->args]))) {
06971       ast_cli(a->fd, "Channel '%s' not found\n", a->argv[e->args]);
06972       return CLI_FAILURE;
06973    }
06974 
06975    pbx_builtin_serialize_variables(chan, &vars);
06976 
06977    if (ast_str_strlen(vars)) {
06978       ast_cli(a->fd, "\nVariables for channel %s:\n%s\n", a->argv[e->args], ast_str_buffer(vars));
06979    }
06980 
06981    chan = ast_channel_unref(chan);
06982 
06983    return CLI_SUCCESS;
06984 }
06985 
06986 static char *handle_set_global(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
06987 {
06988    switch (cmd) {
06989    case CLI_INIT:
06990       e->command = "dialplan set global";
06991       e->usage =
06992          "Usage: dialplan set global <name> <value>\n"
06993          "       Set global dialplan variable <name> to <value>\n";
06994       return NULL;
06995    case CLI_GENERATE:
06996       return NULL;
06997    }
06998 
06999    if (a->argc != e->args + 2)
07000       return CLI_SHOWUSAGE;
07001 
07002    pbx_builtin_setvar_helper(NULL, a->argv[3], a->argv[4]);
07003    ast_cli(a->fd, "\n    -- Global variable '%s' set to '%s'\n", a->argv[3], a->argv[4]);
07004 
07005    return CLI_SUCCESS;
07006 }
07007 
07008 static char *handle_set_chanvar(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
07009 {
07010    struct ast_channel *chan;
07011    const char *chan_name, *var_name, *var_value;
07012 
07013    switch (cmd) {
07014    case CLI_INIT:
07015       e->command = "dialplan set chanvar";
07016       e->usage =
07017          "Usage: dialplan set chanvar <channel> <varname> <value>\n"
07018          "       Set channel variable <varname> to <value>\n";
07019       return NULL;
07020    case CLI_GENERATE:
07021       return ast_complete_channels(a->line, a->word, a->pos, a->n, 3);
07022    }
07023 
07024    if (a->argc != e->args + 3)
07025       return CLI_SHOWUSAGE;
07026 
07027    chan_name = a->argv[e->args];
07028    var_name = a->argv[e->args + 1];
07029    var_value = a->argv[e->args + 2];
07030 
07031    if (!(chan = ast_channel_get_by_name(chan_name))) {
07032       ast_cli(a->fd, "Channel '%s' not found\n", chan_name);
07033       return CLI_FAILURE;
07034    }
07035 
07036    pbx_builtin_setvar_helper(chan, var_name, var_value);
07037 
07038    chan = ast_channel_unref(chan);
07039 
07040    ast_cli(a->fd, "\n    -- Channel variable '%s' set to '%s' for '%s'\n",  var_name, var_value, chan_name);
07041 
07042    return CLI_SUCCESS;
07043 }
07044 
07045 static char *handle_set_extenpatternmatchnew(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
07046 {
07047    int oldval = 0;
07048 
07049    switch (cmd) {
07050    case CLI_INIT:
07051       e->command = "dialplan set extenpatternmatchnew true";
07052       e->usage =
07053          "Usage: dialplan set extenpatternmatchnew true|false\n"
07054          "       Use the NEW extension pattern matching algorithm, true or false.\n";
07055       return NULL;
07056    case CLI_GENERATE:
07057       return NULL;
07058    }
07059 
07060    if (a->argc != 4)
07061       return CLI_SHOWUSAGE;
07062 
07063    oldval =  pbx_set_extenpatternmatchnew(1);
07064 
07065    if (oldval)
07066       ast_cli(a->fd, "\n    -- Still using the NEW pattern match algorithm for extension names in the dialplan.\n");
07067    else
07068       ast_cli(a->fd, "\n    -- Switched to using the NEW pattern match algorithm for extension names in the dialplan.\n");
07069 
07070    return CLI_SUCCESS;
07071 }
07072 
07073 static char *handle_unset_extenpatternmatchnew(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
07074 {
07075    int oldval = 0;
07076 
07077    switch (cmd) {
07078    case CLI_INIT:
07079       e->command = "dialplan set extenpatternmatchnew false";
07080       e->usage =
07081          "Usage: dialplan set extenpatternmatchnew true|false\n"
07082          "       Use the NEW extension pattern matching algorithm, true or false.\n";
07083       return NULL;
07084    case CLI_GENERATE:
07085       return NULL;
07086    }
07087 
07088    if (a->argc != 4)
07089       return CLI_SHOWUSAGE;
07090 
07091    oldval =  pbx_set_extenpatternmatchnew(0);
07092 
07093    if (!oldval)
07094       ast_cli(a->fd, "\n    -- Still using the OLD pattern match algorithm for extension names in the dialplan.\n");
07095    else
07096       ast_cli(a->fd, "\n    -- Switched to using the OLD pattern match algorithm for extension names in the dialplan.\n");
07097 
07098    return CLI_SUCCESS;
07099 }
07100 
07101 /*
07102  * CLI entries for upper commands ...
07103  */
07104 static struct ast_cli_entry pbx_cli[] = {
07105    AST_CLI_DEFINE(handle_show_applications, "Shows registered dialplan applications"),
07106    AST_CLI_DEFINE(handle_show_functions, "Shows registered dialplan functions"),
07107    AST_CLI_DEFINE(handle_show_switches, "Show alternative switches"),
07108    AST_CLI_DEFINE(handle_show_hints, "Show dialplan hints"),
07109    AST_CLI_DEFINE(handle_show_hint, "Show dialplan hint"),
07110    AST_CLI_DEFINE(handle_show_globals, "Show global dialplan variables"),
07111 #ifdef AST_DEVMODE
07112    AST_CLI_DEFINE(handle_show_device2extenstate, "Show expected exten state from multiple device states"),
07113 #endif
07114    AST_CLI_DEFINE(handle_show_chanvar, "Show channel variables"),
07115    AST_CLI_DEFINE(handle_show_function, "Describe a specific dialplan function"),
07116    AST_CLI_DEFINE(handle_show_application, "Describe a specific dialplan application"),
07117    AST_CLI_DEFINE(handle_set_global, "Set global dialplan variable"),
07118    AST_CLI_DEFINE(handle_set_chanvar, "Set a channel variable"),
07119    AST_CLI_DEFINE(handle_show_dialplan, "Show dialplan"),
07120    AST_CLI_DEFINE(handle_debug_dialplan, "Show fast extension pattern matching data structures"),
07121    AST_CLI_DEFINE(handle_unset_extenpatternmatchnew, "Use the Old extension pattern matching algorithm."),
07122    AST_CLI_DEFINE(handle_set_extenpatternmatchnew, "Use the New extension pattern matching algorithm."),
07123 };
07124 
07125 static void unreference_cached_app(struct ast_app *app)
07126 {
07127    struct ast_context *context = NULL;
07128    struct ast_exten *eroot = NULL, *e = NULL;
07129 
07130    ast_rdlock_contexts();
07131    while ((context = ast_walk_contexts(context))) {
07132       while ((eroot = ast_walk_context_extensions(context, eroot))) {
07133          while ((e = ast_walk_extension_priorities(eroot, e))) {
07134             if (e->cached_app == app)
07135                e->cached_app = NULL;
07136          }
07137       }
07138    }
07139    ast_unlock_contexts();
07140 
07141    return;
07142 }
07143 
07144 int ast_unregister_application(const char *app)
07145 {
07146    struct ast_app *tmp;
07147 
07148    AST_RWLIST_WRLOCK(&apps);
07149    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&apps, tmp, list) {
07150       if (!strcasecmp(app, tmp->name)) {
07151          unreference_cached_app(tmp);
07152          AST_RWLIST_REMOVE_CURRENT(list);
07153          ast_verb(2, "Unregistered application '%s'\n", tmp->name);
07154          ast_string_field_free_memory(tmp);
07155          ast_free(tmp);
07156          break;
07157       }
07158    }
07159    AST_RWLIST_TRAVERSE_SAFE_END;
07160    AST_RWLIST_UNLOCK(&apps);
07161 
07162    return tmp ? 0 : -1;
07163 }
07164 
07165 struct ast_context *ast_context_find_or_create(struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *name, const char *registrar)
07166 {
07167    struct ast_context *tmp, **local_contexts;
07168    struct fake_context search;
07169    int length = sizeof(struct ast_context) + strlen(name) + 1;
07170 
07171    if (!contexts_table) {
07172       /* Protect creation of contexts_table from reentrancy. */
07173       ast_wrlock_contexts();
07174       if (!contexts_table) {
07175          contexts_table = ast_hashtab_create(17,
07176             ast_hashtab_compare_contexts,
07177             ast_hashtab_resize_java,
07178             ast_hashtab_newsize_java,
07179             ast_hashtab_hash_contexts,
07180             0);
07181       }
07182       ast_unlock_contexts();
07183    }
07184 
07185    ast_copy_string(search.name, name, sizeof(search.name));
07186    if (!extcontexts) {
07187       ast_rdlock_contexts();
07188       local_contexts = &contexts;
07189       tmp = ast_hashtab_lookup(contexts_table, &search);
07190       ast_unlock_contexts();
07191       if (tmp) {
07192          tmp->refcount++;
07193          return tmp;
07194       }
07195    } else { /* local contexts just in a linked list; search there for the new context; slow, linear search, but not frequent */
07196       local_contexts = extcontexts;
07197       tmp = ast_hashtab_lookup(exttable, &search);
07198       if (tmp) {
07199          tmp->refcount++;
07200          return tmp;
07201       }
07202    }
07203 
07204    if ((tmp = ast_calloc(1, length))) {
07205       ast_rwlock_init(&tmp->lock);
07206       ast_mutex_init(&tmp->macrolock);
07207       strcpy(tmp->name, name);
07208       tmp->root = NULL;
07209       tmp->root_table = NULL;
07210       tmp->registrar = ast_strdup(registrar);
07211       tmp->includes = NULL;
07212       tmp->ignorepats = NULL;
07213       tmp->refcount = 1;
07214    } else {
07215       ast_log(LOG_ERROR, "Danger! We failed to allocate a context for %s!\n", name);
07216       return NULL;
07217    }
07218 
07219    if (!extcontexts) {
07220       ast_wrlock_contexts();
07221       tmp->next = *local_contexts;
07222       *local_contexts = tmp;
07223       ast_hashtab_insert_safe(contexts_table, tmp); /*put this context into the tree */
07224       ast_unlock_contexts();
07225       ast_debug(1, "Registered context '%s'(%p) in table %p registrar: %s\n", tmp->name, tmp, contexts_table, registrar);
07226       ast_verb(3, "Registered extension context '%s'; registrar: %s\n", tmp->name, registrar);
07227    } else {
07228       tmp->next = *local_contexts;
07229       if (exttable)
07230          ast_hashtab_insert_immediate(exttable, tmp); /*put this context into the tree */
07231 
07232       *local_contexts = tmp;
07233       ast_debug(1, "Registered context '%s'(%p) in local table %p; registrar: %s\n", tmp->name, tmp, exttable, registrar);
07234       ast_verb(3, "Registered extension context '%s'; registrar: %s\n", tmp->name, registrar);
07235    }
07236    return tmp;
07237 }
07238 
07239 void __ast_context_destroy(struct ast_context *list, struct ast_hashtab *contexttab, struct ast_context *con, const char *registrar);
07240 
07241 struct store_hint {
07242    char *context;
07243    char *exten;
07244    AST_LIST_HEAD_NOLOCK(, ast_state_cb) callbacks;
07245    int laststate;
07246    AST_LIST_ENTRY(store_hint) list;
07247    char data[1];
07248 };
07249 
07250 AST_LIST_HEAD_NOLOCK(store_hints, store_hint);
07251 
07252 static void context_merge_incls_swits_igps_other_registrars(struct ast_context *new, struct ast_context *old, const char *registrar)
07253 {
07254    struct ast_include *i;
07255    struct ast_ignorepat *ip;
07256    struct ast_sw *sw;
07257 
07258    ast_verb(3, "merging incls/swits/igpats from old(%s) to new(%s) context, registrar = %s\n", ast_get_context_name(old), ast_get_context_name(new), registrar);
07259    /* copy in the includes, switches, and ignorepats */
07260    /* walk through includes */
07261    for (i = NULL; (i = ast_walk_context_includes(old, i)) ; ) {
07262       if (strcmp(ast_get_include_registrar(i), registrar) == 0)
07263          continue; /* not mine */
07264       ast_context_add_include2(new, ast_get_include_name(i), ast_get_include_registrar(i));
07265    }
07266 
07267    /* walk through switches */
07268    for (sw = NULL; (sw = ast_walk_context_switches(old, sw)) ; ) {
07269       if (strcmp(ast_get_switch_registrar(sw), registrar) == 0)
07270          continue; /* not mine */
07271       ast_context_add_switch2(new, ast_get_switch_name(sw), ast_get_switch_data(sw), ast_get_switch_eval(sw), ast_get_switch_registrar(sw));
07272    }
07273 
07274    /* walk thru ignorepats ... */
07275    for (ip = NULL; (ip = ast_walk_context_ignorepats(old, ip)); ) {
07276       if (strcmp(ast_get_ignorepat_registrar(ip), registrar) == 0)
07277          continue; /* not mine */
07278       ast_context_add_ignorepat2(new, ast_get_ignorepat_name(ip), ast_get_ignorepat_registrar(ip));
07279    }
07280 }
07281 
07282 
07283 /* the purpose of this routine is to duplicate a context, with all its substructure,
07284    except for any extens that have a matching registrar */
07285 static void context_merge(struct ast_context **extcontexts, struct ast_hashtab *exttable, struct ast_context *context, const char *registrar)
07286 {
07287    struct ast_context *new = ast_hashtab_lookup(exttable, context); /* is there a match in the new set? */
07288    struct ast_exten *exten_item, *prio_item, *new_exten_item, *new_prio_item;
07289    struct ast_hashtab_iter *exten_iter;
07290    struct ast_hashtab_iter *prio_iter;
07291    int insert_count = 0;
07292    int first = 1;
07293 
07294    /* We'll traverse all the extensions/prios, and see which are not registrar'd with
07295       the current registrar, and copy them to the new context. If the new context does not
07296       exist, we'll create it "on demand". If no items are in this context to copy, then we'll
07297       only create the empty matching context if the old one meets the criteria */
07298 
07299    if (context->root_table) {
07300       exten_iter = ast_hashtab_start_traversal(context->root_table);
07301       while ((exten_item=ast_hashtab_next(exten_iter))) {
07302          if (new) {
07303             new_exten_item = ast_hashtab_lookup(new->root_table, exten_item);
07304          } else {
07305             new_exten_item = NULL;
07306          }
07307          prio_iter = ast_hashtab_start_traversal(exten_item->peer_table);
07308          while ((prio_item=ast_hashtab_next(prio_iter))) {
07309             int res1;
07310             char *dupdstr;
07311 
07312             if (new_exten_item) {
07313                new_prio_item = ast_hashtab_lookup(new_exten_item->peer_table, prio_item);
07314             } else {
07315                new_prio_item = NULL;
07316             }
07317             if (strcmp(prio_item->registrar,registrar) == 0) {
07318                continue;
07319             }
07320             /* make sure the new context exists, so we have somewhere to stick this exten/prio */
07321             if (!new) {
07322                new = ast_context_find_or_create(extcontexts, exttable, context->name, prio_item->registrar); /* a new context created via priority from a different context in the old dialplan, gets its registrar from the prio's registrar */
07323             }
07324 
07325             /* copy in the includes, switches, and ignorepats */
07326             if (first) { /* but, only need to do this once */
07327                context_merge_incls_swits_igps_other_registrars(new, context, registrar);
07328                first = 0;
07329             }
07330 
07331             if (!new) {
07332                ast_log(LOG_ERROR,"Could not allocate a new context for %s in merge_and_delete! Danger!\n", context->name);
07333                return; /* no sense continuing. */
07334             }
07335             /* we will not replace existing entries in the new context with stuff from the old context.
07336                but, if this is because of some sort of registrar conflict, we ought to say something... */
07337 
07338             dupdstr = ast_strdup(prio_item->data);
07339 
07340             res1 = ast_add_extension2(new, 0, prio_item->exten, prio_item->priority, prio_item->label, 
07341                                 prio_item->matchcid ? prio_item->cidmatch : NULL, prio_item->app, dupdstr, prio_item->datad, prio_item->registrar);
07342             if (!res1 && new_exten_item && new_prio_item){
07343                ast_verb(3,"Dropping old dialplan item %s/%s/%d [%s(%s)] (registrar=%s) due to conflict with new dialplan\n",
07344                      context->name, prio_item->exten, prio_item->priority, prio_item->app, (char*)prio_item->data, prio_item->registrar);
07345             } else {
07346                /* we do NOT pass the priority data from the old to the new -- we pass a copy of it, so no changes to the current dialplan take place,
07347                 and no double frees take place, either! */
07348                insert_count++;
07349             }
07350          }
07351          ast_hashtab_end_traversal(prio_iter);
07352       }
07353       ast_hashtab_end_traversal(exten_iter);
07354    }
07355 
07356    if (!insert_count && !new && (strcmp(context->registrar, registrar) != 0 ||
07357         (strcmp(context->registrar, registrar) == 0 && context->refcount > 1))) {
07358       /* we could have given it the registrar of the other module who incremented the refcount,
07359          but that's not available, so we give it the registrar we know about */
07360       new = ast_context_find_or_create(extcontexts, exttable, context->name, context->registrar);
07361 
07362       /* copy in the includes, switches, and ignorepats */
07363       context_merge_incls_swits_igps_other_registrars(new, context, registrar);
07364    }
07365 }
07366 
07367 
07368 /* XXX this does not check that multiple contexts are merged */
07369 void ast_merge_contexts_and_delete(struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *registrar)
07370 {
07371    double ft;
07372    struct ast_context *tmp;
07373    struct ast_context *oldcontextslist;
07374    struct ast_hashtab *oldtable;
07375    struct store_hints hints_stored = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
07376    struct store_hints hints_removed = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
07377    struct store_hint *saved_hint;
07378    struct ast_hint *hint;
07379    struct ast_exten *exten;
07380    int length;
07381    struct ast_state_cb *thiscb;
07382    struct ast_hashtab_iter *iter;
07383    struct ao2_iterator i;
07384    struct timeval begintime;
07385    struct timeval writelocktime;
07386    struct timeval endlocktime;
07387    struct timeval enddeltime;
07388 
07389    /*
07390     * It is very important that this function hold the hints
07391     * container lock _and_ the conlock during its operation; not
07392     * only do we need to ensure that the list of contexts and
07393     * extensions does not change, but also that no hint callbacks
07394     * (watchers) are added or removed during the merge/delete
07395     * process
07396     *
07397     * In addition, the locks _must_ be taken in this order, because
07398     * there are already other code paths that use this order
07399     */
07400 
07401    begintime = ast_tvnow();
07402    ast_mutex_lock(&context_merge_lock);/* Serialize ast_merge_contexts_and_delete */
07403    ast_wrlock_contexts();
07404    iter = ast_hashtab_start_traversal(contexts_table);
07405    while ((tmp = ast_hashtab_next(iter))) {
07406       context_merge(extcontexts, exttable, tmp, registrar);
07407    }
07408    ast_hashtab_end_traversal(iter);
07409 
07410    ao2_lock(hints);
07411    writelocktime = ast_tvnow();
07412 
07413    /* preserve all watchers for hints */
07414    i = ao2_iterator_init(hints, AO2_ITERATOR_DONTLOCK);
07415    for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) {
07416       if (ao2_container_count(hint->callbacks)) {
07417          ao2_lock(hint);
07418          if (!hint->exten) {
07419             /* The extension has already been destroyed. (Should never happen here) */
07420             ao2_unlock(hint);
07421             continue;
07422          }
07423 
07424          length = strlen(hint->exten->exten) + strlen(hint->exten->parent->name) + 2
07425             + sizeof(*saved_hint);
07426          if (!(saved_hint = ast_calloc(1, length))) {
07427             ao2_unlock(hint);
07428             continue;
07429          }
07430 
07431          /* This removes all the callbacks from the hint into saved_hint. */
07432          while ((thiscb = ao2_callback(hint->callbacks, OBJ_UNLINK, NULL, NULL))) {
07433             AST_LIST_INSERT_TAIL(&saved_hint->callbacks, thiscb, entry);
07434             /*
07435              * We intentionally do not unref thiscb to account for the
07436              * non-ao2 reference in saved_hint->callbacks
07437              */
07438          }
07439 
07440          saved_hint->laststate = hint->laststate;
07441          saved_hint->context = saved_hint->data;
07442          strcpy(saved_hint->data, hint->exten->parent->name);
07443          saved_hint->exten = saved_hint->data + strlen(saved_hint->context) + 1;
07444          strcpy(saved_hint->exten, hint->exten->exten);
07445          ao2_unlock(hint);
07446          AST_LIST_INSERT_HEAD(&hints_stored, saved_hint, list);
07447       }
07448    }
07449    ao2_iterator_destroy(&i);
07450 
07451    /* save the old table and list */
07452    oldtable = contexts_table;
07453    oldcontextslist = contexts;
07454 
07455    /* move in the new table and list */
07456    contexts_table = exttable;
07457    contexts = *extcontexts;
07458 
07459    /*
07460     * Restore the watchers for hints that can be found; notify
07461     * those that cannot be restored.
07462     */
07463    while ((saved_hint = AST_LIST_REMOVE_HEAD(&hints_stored, list))) {
07464       struct pbx_find_info q = { .stacklen = 0 };
07465 
07466       exten = pbx_find_extension(NULL, NULL, &q, saved_hint->context, saved_hint->exten,
07467          PRIORITY_HINT, NULL, "", E_MATCH);
07468       /*
07469        * If this is a pattern, dynamically create a new extension for this
07470        * particular match.  Note that this will only happen once for each
07471        * individual extension, because the pattern will no longer match first.
07472        */
07473       if (exten && exten->exten[0] == '_') {
07474          ast_add_extension_nolock(exten->parent->name, 0, saved_hint->exten,
07475             PRIORITY_HINT, NULL, 0, exten->app, ast_strdup(exten->data), ast_free_ptr,
07476             exten->registrar);
07477          /* rwlocks are not recursive locks */
07478          exten = ast_hint_extension_nolock(NULL, saved_hint->context,
07479             saved_hint->exten);
07480       }
07481 
07482       /* Find the hint in the hints container */
07483       hint = exten ? ao2_find(hints, exten, 0) : NULL;
07484       if (!hint) {
07485          /*
07486           * Notify watchers of this removed hint later when we aren't
07487           * encumberd by so many locks.
07488           */
07489          AST_LIST_INSERT_HEAD(&hints_removed, saved_hint, list);
07490       } else {
07491          ao2_lock(hint);
07492          while ((thiscb = AST_LIST_REMOVE_HEAD(&saved_hint->callbacks, entry))) {
07493             ao2_link(hint->callbacks, thiscb);
07494             /* Ref that we added when putting into saved_hint->callbacks */
07495             ao2_ref(thiscb, -1);
07496          }
07497          hint->laststate = saved_hint->laststate;
07498          ao2_unlock(hint);
07499          ao2_ref(hint, -1);
07500          ast_free(saved_hint);
07501       }
07502    }
07503 
07504    ao2_unlock(hints);
07505    ast_unlock_contexts();
07506 
07507    /*
07508     * Notify watchers of all removed hints with the same lock
07509     * environment as handle_statechange().
07510     */
07511    while ((saved_hint = AST_LIST_REMOVE_HEAD(&hints_removed, list))) {
07512       /* this hint has been removed, notify the watchers */
07513       while ((thiscb = AST_LIST_REMOVE_HEAD(&saved_hint->callbacks, entry))) {
07514          thiscb->change_cb(saved_hint->context, saved_hint->exten,
07515             AST_EXTENSION_REMOVED, thiscb->data);
07516          /* Ref that we added when putting into saved_hint->callbacks */
07517          ao2_ref(thiscb, -1);
07518       }
07519       ast_free(saved_hint);
07520    }
07521 
07522    ast_mutex_unlock(&context_merge_lock);
07523    endlocktime = ast_tvnow();
07524 
07525    /*
07526     * The old list and hashtab no longer are relevant, delete them
07527     * while the rest of asterisk is now freely using the new stuff
07528     * instead.
07529     */
07530 
07531    ast_hashtab_destroy(oldtable, NULL);
07532 
07533    for (tmp = oldcontextslist; tmp; ) {
07534       struct ast_context *next;  /* next starting point */
07535 
07536       next = tmp->next;
07537       __ast_internal_context_destroy(tmp);
07538       tmp = next;
07539    }
07540    enddeltime = ast_tvnow();
07541 
07542    ft = ast_tvdiff_us(writelocktime, begintime);
07543    ft /= 1000000.0;
07544    ast_verb(3,"Time to scan old dialplan and merge leftovers back into the new: %8.6f sec\n", ft);
07545 
07546    ft = ast_tvdiff_us(endlocktime, writelocktime);
07547    ft /= 1000000.0;
07548    ast_verb(3,"Time to restore hints and swap in new dialplan: %8.6f sec\n", ft);
07549 
07550    ft = ast_tvdiff_us(enddeltime, endlocktime);
07551    ft /= 1000000.0;
07552    ast_verb(3,"Time to delete the old dialplan: %8.6f sec\n", ft);
07553 
07554    ft = ast_tvdiff_us(enddeltime, begintime);
07555    ft /= 1000000.0;
07556    ast_verb(3,"Total time merge_contexts_delete: %8.6f sec\n", ft);
07557 }
07558 
07559 /*
07560  * errno values
07561  *  EBUSY  - can't lock
07562  *  ENOENT - no existence of context
07563  */
07564 int ast_context_add_include(const char *context, const char *include, const char *registrar)
07565 {
07566    int ret = -1;
07567    struct ast_context *c;
07568 
07569    c = find_context_locked(context);
07570    if (c) {
07571       ret = ast_context_add_include2(c, include, registrar);
07572       ast_unlock_contexts();
07573    }
07574    return ret;
07575 }
07576 
07577 /*! \brief Helper for get_range.
07578  * return the index of the matching entry, starting from 1.
07579  * If names is not supplied, try numeric values.
07580  */
07581 static int lookup_name(const char *s, const char * const names[], int max)
07582 {
07583    int i;
07584 
07585    if (names && *s > '9') {
07586       for (i = 0; names[i]; i++) {
07587          if (!strcasecmp(s, names[i])) {
07588             return i;
07589          }
07590       }
07591    }
07592 
07593    /* Allow months and weekdays to be specified as numbers, as well */
07594    if (sscanf(s, "%2d", &i) == 1 && i >= 1 && i <= max) {
07595       /* What the array offset would have been: "1" would be at offset 0 */
07596       return i - 1;
07597    }
07598    return -1; /* error return */
07599 }
07600 
07601 /*! \brief helper function to return a range up to max (7, 12, 31 respectively).
07602  * names, if supplied, is an array of names that should be mapped to numbers.
07603  */
07604 static unsigned get_range(char *src, int max, const char * const names[], const char *msg)
07605 {
07606    int start, end; /* start and ending position */
07607    unsigned int mask = 0;
07608    char *part;
07609 
07610    /* Check for whole range */
07611    if (ast_strlen_zero(src) || !strcmp(src, "*")) {
07612       return (1 << max) - 1;
07613    }
07614 
07615    while ((part = strsep(&src, "&"))) {
07616       /* Get start and ending position */
07617       char *endpart = strchr(part, '-');
07618       if (endpart) {
07619          *endpart++ = '\0';
07620       }
07621       /* Find the start */
07622       if ((start = lookup_name(part, names, max)) < 0) {
07623          ast_log(LOG_WARNING, "Invalid %s '%s', skipping element\n", msg, part);
07624          continue;
07625       }
07626       if (endpart) { /* find end of range */
07627          if ((end = lookup_name(endpart, names, max)) < 0) {
07628             ast_log(LOG_WARNING, "Invalid end %s '%s', skipping element\n", msg, endpart);
07629             continue;
07630          }
07631       } else {
07632          end = start;
07633       }
07634       /* Fill the mask. Remember that ranges are cyclic */
07635       mask |= (1 << end);   /* initialize with last element */
07636       while (start != end) {
07637          mask |= (1 << start);
07638          if (++start >= max) {
07639             start = 0;
07640          }
07641       }
07642    }
07643    return mask;
07644 }
07645 
07646 /*! \brief store a bitmask of valid times, one bit each 1 minute */
07647 static void get_timerange(struct ast_timing *i, char *times)
07648 {
07649    char *endpart, *part;
07650    int x;
07651    int st_h, st_m;
07652    int endh, endm;
07653    int minute_start, minute_end;
07654 
07655    /* start disabling all times, fill the fields with 0's, as they may contain garbage */
07656    memset(i->minmask, 0, sizeof(i->minmask));
07657 
07658    /* 1-minute per bit */
07659    /* Star is all times */
07660    if (ast_strlen_zero(times) || !strcmp(times, "*")) {
07661       /* 48, because each hour takes 2 integers; 30 bits each */
07662       for (x = 0; x < 48; x++) {
07663          i->minmask[x] = 0x3fffffff; /* 30 bits */
07664       }
07665       return;
07666    }
07667    /* Otherwise expect a range */
07668    while ((part = strsep(&times, "&"))) {
07669       if (!(endpart = strchr(part, '-'))) {
07670          if (sscanf(part, "%2d:%2d", &st_h, &st_m) != 2 || st_h < 0 || st_h > 23 || st_m < 0 || st_m > 59) {
07671             ast_log(LOG_WARNING, "%s isn't a valid time.\n", part);
07672             continue;
07673          }
07674          i->minmask[st_h * 2 + (st_m >= 30 ? 1 : 0)] |= (1 << (st_m % 30));
07675          continue;
07676       }
07677       *endpart++ = '\0';
07678       /* why skip non digits? Mostly to skip spaces */
07679       while (*endpart && !isdigit(*endpart)) {
07680          endpart++;
07681       }
07682       if (!*endpart) {
07683          ast_log(LOG_WARNING, "Invalid time range starting with '%s-'.\n", part);
07684          continue;
07685       }
07686       if (sscanf(part, "%2d:%2d", &st_h, &st_m) != 2 || st_h < 0 || st_h > 23 || st_m < 0 || st_m > 59) {
07687          ast_log(LOG_WARNING, "'%s' isn't a valid start time.\n", part);
07688          continue;
07689       }
07690       if (sscanf(endpart, "%2d:%2d", &endh, &endm) != 2 || endh < 0 || endh > 23 || endm < 0 || endm > 59) {
07691          ast_log(LOG_WARNING, "'%s' isn't a valid end time.\n", endpart);
07692          continue;
07693       }
07694       minute_start = st_h * 60 + st_m;
07695       minute_end = endh * 60 + endm;
07696       /* Go through the time and enable each appropriate bit */
07697       for (x = minute_start; x != minute_end; x = (x + 1) % (24 * 60)) {
07698          i->minmask[x / 30] |= (1 << (x % 30));
07699       }
07700       /* Do the last one */
07701       i->minmask[x / 30] |= (1 << (x % 30));
07702    }
07703    /* All done */
07704    return;
07705 }
07706 
07707 static const char * const days[] =
07708 {
07709    "sun",
07710    "mon",
07711    "tue",
07712    "wed",
07713    "thu",
07714    "fri",
07715    "sat",
07716    NULL,
07717 };
07718 
07719 static const char * const months[] =
07720 {
07721    "jan",
07722    "feb",
07723    "mar",
07724    "apr",
07725    "may",
07726    "jun",
07727    "jul",
07728    "aug",
07729    "sep",
07730    "oct",
07731    "nov",
07732    "dec",
07733    NULL,
07734 };
07735 
07736 int ast_build_timing(struct ast_timing *i, const char *info_in)
07737 {
07738    char *info;
07739    int j, num_fields, last_sep = -1;
07740 
07741    /* Check for empty just in case */
07742    if (ast_strlen_zero(info_in)) {
07743       return 0;
07744    }
07745 
07746    /* make a copy just in case we were passed a static string */
07747    info = ast_strdupa(info_in);
07748 
07749    /* count the number of fields in the timespec */
07750    for (j = 0, num_fields = 1; info[j] != '\0'; j++) {
07751       if (info[j] == ',') {
07752          last_sep = j;
07753          num_fields++;
07754       }
07755    }
07756 
07757    /* save the timezone, if it is specified */
07758    if (num_fields == 5) {
07759       i->timezone = ast_strdup(info + last_sep + 1);
07760    } else {
07761       i->timezone = NULL;
07762    }
07763 
07764    /* Assume everything except time */
07765    i->monthmask = 0xfff;   /* 12 bits */
07766    i->daymask = 0x7fffffffU; /* 31 bits */
07767    i->dowmask = 0x7f; /* 7 bits */
07768    /* on each call, use strsep() to move info to the next argument */
07769    get_timerange(i, strsep(&info, "|,"));
07770    if (info)
07771       i->dowmask = get_range(strsep(&info, "|,"), 7, days, "day of week");
07772    if (info)
07773       i->daymask = get_range(strsep(&info, "|,"), 31, NULL, "day");
07774    if (info)
07775       i->monthmask = get_range(strsep(&info, "|,"), 12, months, "month");
07776    return 1;
07777 }
07778 
07779 int ast_check_timing(const struct ast_timing *i)
07780 {
07781    return ast_check_timing2(i, ast_tvnow());
07782 }
07783 
07784 int ast_check_timing2(const struct ast_timing *i, const struct timeval tv)
07785 {
07786    struct ast_tm tm;
07787 
07788    ast_localtime(&tv, &tm, i->timezone);
07789 
07790    /* If it's not the right month, return */
07791    if (!(i->monthmask & (1 << tm.tm_mon)))
07792       return 0;
07793 
07794    /* If it's not that time of the month.... */
07795    /* Warning, tm_mday has range 1..31! */
07796    if (!(i->daymask & (1 << (tm.tm_mday-1))))
07797       return 0;
07798 
07799    /* If it's not the right day of the week */
07800    if (!(i->dowmask & (1 << tm.tm_wday)))
07801       return 0;
07802 
07803    /* Sanity check the hour just to be safe */
07804    if ((tm.tm_hour < 0) || (tm.tm_hour > 23)) {
07805       ast_log(LOG_WARNING, "Insane time...\n");
07806       return 0;
07807    }
07808 
07809    /* Now the tough part, we calculate if it fits
07810       in the right time based on min/hour */
07811    if (!(i->minmask[tm.tm_hour * 2 + (tm.tm_min >= 30 ? 1 : 0)] & (1 << (tm.tm_min >= 30 ? tm.tm_min - 30 : tm.tm_min))))
07812       return 0;
07813 
07814    /* If we got this far, then we're good */
07815    return 1;
07816 }
07817 
07818 int ast_destroy_timing(struct ast_timing *i)
07819 {
07820    if (i->timezone) {
07821       ast_free(i->timezone);
07822       i->timezone = NULL;
07823    }
07824    return 0;
07825 }
07826 /*
07827  * errno values
07828  *  ENOMEM - out of memory
07829  *  EBUSY  - can't lock
07830  *  EEXIST - already included
07831  *  EINVAL - there is no existence of context for inclusion
07832  */
07833 int ast_context_add_include2(struct ast_context *con, const char *value,
07834    const char *registrar)
07835 {
07836    struct ast_include *new_include;
07837    char *c;
07838    struct ast_include *i, *il = NULL; /* include, include_last */
07839    int length;
07840    char *p;
07841 
07842    length = sizeof(struct ast_include);
07843    length += 2 * (strlen(value) + 1);
07844 
07845    /* allocate new include structure ... */
07846    if (!(new_include = ast_calloc(1, length)))
07847       return -1;
07848    /* Fill in this structure. Use 'p' for assignments, as the fields
07849     * in the structure are 'const char *'
07850     */
07851    p = new_include->stuff;
07852    new_include->name = p;
07853    strcpy(p, value);
07854    p += strlen(value) + 1;
07855    new_include->rname = p;
07856    strcpy(p, value);
07857    /* Strip off timing info, and process if it is there */
07858    if ( (c = strchr(p, ',')) ) {
07859       *c++ = '\0';
07860       new_include->hastime = ast_build_timing(&(new_include->timing), c);
07861    }
07862    new_include->next      = NULL;
07863    new_include->registrar = registrar;
07864 
07865    ast_wrlock_context(con);
07866 
07867    /* ... go to last include and check if context is already included too... */
07868    for (i = con->includes; i; i = i->next) {
07869       if (!strcasecmp(i->name, new_include->name)) {
07870          ast_destroy_timing(&(new_include->timing));
07871          ast_free(new_include);
07872          ast_unlock_context(con);
07873          errno = EEXIST;
07874          return -1;
07875       }
07876       il = i;
07877    }
07878 
07879    /* ... include new context into context list, unlock, return */
07880    if (il)
07881       il->next = new_include;
07882    else
07883       con->includes = new_include;
07884    ast_verb(3, "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con));
07885 
07886    ast_unlock_context(con);
07887 
07888    return 0;
07889 }
07890 
07891 /*
07892  * errno values
07893  *  EBUSY  - can't lock
07894  *  ENOENT - no existence of context
07895  */
07896 int ast_context_add_switch(const char *context, const char *sw, const char *data, int eval, const char *registrar)
07897 {
07898    int ret = -1;
07899    struct ast_context *c;
07900 
07901    c = find_context_locked(context);
07902    if (c) { /* found, add switch to this context */
07903       ret = ast_context_add_switch2(c, sw, data, eval, registrar);
07904       ast_unlock_contexts();
07905    }
07906    return ret;
07907 }
07908 
07909 /*
07910  * errno values
07911  *  ENOMEM - out of memory
07912  *  EBUSY  - can't lock
07913  *  EEXIST - already included
07914  *  EINVAL - there is no existence of context for inclusion
07915  */
07916 int ast_context_add_switch2(struct ast_context *con, const char *value,
07917    const char *data, int eval, const char *registrar)
07918 {
07919    struct ast_sw *new_sw;
07920    struct ast_sw *i;
07921    int length;
07922    char *p;
07923 
07924    length = sizeof(struct ast_sw);
07925    length += strlen(value) + 1;
07926    if (data)
07927       length += strlen(data);
07928    length++;
07929 
07930    /* allocate new sw structure ... */
07931    if (!(new_sw = ast_calloc(1, length)))
07932       return -1;
07933    /* ... fill in this structure ... */
07934    p = new_sw->stuff;
07935    new_sw->name = p;
07936    strcpy(new_sw->name, value);
07937    p += strlen(value) + 1;
07938    new_sw->data = p;
07939    if (data) {
07940       strcpy(new_sw->data, data);
07941       p += strlen(data) + 1;
07942    } else {
07943       strcpy(new_sw->data, "");
07944       p++;
07945    }
07946    new_sw->eval     = eval;
07947    new_sw->registrar = registrar;
07948 
07949    /* ... try to lock this context ... */
07950    ast_wrlock_context(con);
07951 
07952    /* ... go to last sw and check if context is already swd too... */
07953    AST_LIST_TRAVERSE(&con->alts, i, list) {
07954       if (!strcasecmp(i->name, new_sw->name) && !strcasecmp(i->data, new_sw->data)) {
07955          ast_free(new_sw);
07956          ast_unlock_context(con);
07957          errno = EEXIST;
07958          return -1;
07959       }
07960    }
07961 
07962    /* ... sw new context into context list, unlock, return */
07963    AST_LIST_INSERT_TAIL(&con->alts, new_sw, list);
07964 
07965    ast_verb(3, "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con));
07966 
07967    ast_unlock_context(con);
07968 
07969    return 0;
07970 }
07971 
07972 /*
07973  * EBUSY  - can't lock
07974  * ENOENT - there is not context existence
07975  */
07976 int ast_context_remove_ignorepat(const char *context, const char *ignorepat, const char *registrar)
07977 {
07978    int ret = -1;
07979    struct ast_context *c;
07980 
07981    c = find_context_locked(context);
07982    if (c) {
07983       ret = ast_context_remove_ignorepat2(c, ignorepat, registrar);
07984       ast_unlock_contexts();
07985    }
07986    return ret;
07987 }
07988 
07989 int ast_context_remove_ignorepat2(struct ast_context *con, const char *ignorepat, const char *registrar)
07990 {
07991    struct ast_ignorepat *ip, *ipl = NULL;
07992 
07993    ast_wrlock_context(con);
07994 
07995    for (ip = con->ignorepats; ip; ip = ip->next) {
07996       if (!strcmp(ip->pattern, ignorepat) &&
07997          (!registrar || (registrar == ip->registrar))) {
07998          if (ipl) {
07999             ipl->next = ip->next;
08000             ast_free(ip);
08001          } else {
08002             con->ignorepats = ip->next;
08003             ast_free(ip);
08004          }
08005          ast_unlock_context(con);
08006          return 0;
08007       }
08008       ipl = ip;
08009    }
08010 
08011    ast_unlock_context(con);
08012    errno = EINVAL;
08013    return -1;
08014 }
08015 
08016 /*
08017  * EBUSY - can't lock
08018  * ENOENT - there is no existence of context
08019  */
08020 int ast_context_add_ignorepat(const char *context, const char *value, const char *registrar)
08021 {
08022    int ret = -1;
08023    struct ast_context *c;
08024 
08025    c = find_context_locked(context);
08026    if (c) {
08027       ret = ast_context_add_ignorepat2(c, value, registrar);
08028       ast_unlock_contexts();
08029    }
08030    return ret;
08031 }
08032 
08033 int ast_context_add_ignorepat2(struct ast_context *con, const char *value, const char *registrar)
08034 {
08035    struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL;
08036    int length;
08037    char *pattern;
08038    length = sizeof(struct ast_ignorepat);
08039    length += strlen(value) + 1;
08040    if (!(ignorepat = ast_calloc(1, length)))
08041       return -1;
08042    /* The cast to char * is because we need to write the initial value.
08043     * The field is not supposed to be modified otherwise.  Also, gcc 4.2
08044     * sees the cast as dereferencing a type-punned pointer and warns about
08045     * it.  This is the workaround (we're telling gcc, yes, that's really
08046     * what we wanted to do).
08047     */
08048    pattern = (char *) ignorepat->pattern;
08049    strcpy(pattern, value);
08050    ignorepat->next = NULL;
08051    ignorepat->registrar = registrar;
08052    ast_wrlock_context(con);
08053    for (ignorepatc = con->ignorepats; ignorepatc; ignorepatc = ignorepatc->next) {
08054       ignorepatl = ignorepatc;
08055       if (!strcasecmp(ignorepatc->pattern, value)) {
08056          /* Already there */
08057          ast_unlock_context(con);
08058          errno = EEXIST;
08059          return -1;
08060       }
08061    }
08062    if (ignorepatl)
08063       ignorepatl->next = ignorepat;
08064    else
08065       con->ignorepats = ignorepat;
08066    ast_unlock_context(con);
08067    return 0;
08068 
08069 }
08070 
08071 int ast_ignore_pattern(const char *context, const char *pattern)
08072 {
08073    struct ast_context *con = ast_context_find(context);
08074 
08075    if (con) {
08076       struct ast_ignorepat *pat;
08077 
08078       for (pat = con->ignorepats; pat; pat = pat->next) {
08079          if (ast_extension_match(pat->pattern, pattern))
08080             return 1;
08081       }
08082    }
08083 
08084    return 0;
08085 }
08086 
08087 /*
08088  * ast_add_extension_nolock -- use only in situations where the conlock is already held
08089  * ENOENT  - no existence of context
08090  *
08091  */
08092 static int ast_add_extension_nolock(const char *context, int replace, const char *extension,
08093    int priority, const char *label, const char *callerid,
08094    const char *application, void *data, void (*datad)(void *), const char *registrar)
08095 {
08096    int ret = -1;
08097    struct ast_context *c;
08098 
08099    c = find_context(context);
08100    if (c) {
08101       ret = ast_add_extension2_lockopt(c, replace, extension, priority, label, callerid,
08102          application, data, datad, registrar, 1);
08103    }
08104 
08105    return ret;
08106 }
08107 /*
08108  * EBUSY   - can't lock
08109  * ENOENT  - no existence of context
08110  *
08111  */
08112 int ast_add_extension(const char *context, int replace, const char *extension,
08113    int priority, const char *label, const char *callerid,
08114    const char *application, void *data, void (*datad)(void *), const char *registrar)
08115 {
08116    int ret = -1;
08117    struct ast_context *c;
08118 
08119    c = find_context_locked(context);
08120    if (c) {
08121       ret = ast_add_extension2(c, replace, extension, priority, label, callerid,
08122          application, data, datad, registrar);
08123       ast_unlock_contexts();
08124    }
08125 
08126    return ret;
08127 }
08128 
08129 int ast_explicit_goto(struct ast_channel *chan, const char *context, const char *exten, int priority)
08130 {
08131    if (!chan)
08132       return -1;
08133 
08134    ast_channel_lock(chan);
08135 
08136    if (!ast_strlen_zero(context))
08137       ast_copy_string(chan->context, context, sizeof(chan->context));
08138    if (!ast_strlen_zero(exten))
08139       ast_copy_string(chan->exten, exten, sizeof(chan->exten));
08140    if (priority > -1) {
08141       chan->priority = priority;
08142       /* see flag description in channel.h for explanation */
08143       if (ast_test_flag(chan, AST_FLAG_IN_AUTOLOOP))
08144          chan->priority--;
08145    }
08146 
08147    ast_channel_unlock(chan);
08148 
08149    return 0;
08150 }
08151 
08152 int ast_async_goto(struct ast_channel *chan, const char *context, const char *exten, int priority)
08153 {
08154    int res = 0;
08155    struct ast_channel *tmpchan;
08156    struct {
08157       char *accountcode;
08158       char *exten;
08159       char *context;
08160       char *linkedid;
08161       char *name;
08162       struct ast_cdr *cdr;
08163       int amaflags;
08164       int state;
08165       format_t readformat;
08166       format_t writeformat;
08167    } tmpvars = { 0, };
08168 
08169    ast_channel_lock(chan);
08170    if (chan->pbx) { /* This channel is currently in the PBX */
08171       ast_explicit_goto(chan, context, exten, priority + 1);
08172       ast_softhangup_nolock(chan, AST_SOFTHANGUP_ASYNCGOTO);
08173       ast_channel_unlock(chan);
08174       return res;
08175    }
08176 
08177    /* In order to do it when the channel doesn't really exist within
08178     * the PBX, we have to make a new channel, masquerade, and start the PBX
08179     * at the new location */
08180    tmpvars.accountcode = ast_strdupa(chan->accountcode);
08181    tmpvars.exten = ast_strdupa(chan->exten);
08182    tmpvars.context = ast_strdupa(chan->context);
08183    tmpvars.linkedid = ast_strdupa(chan->linkedid);
08184    tmpvars.name = ast_strdupa(chan->name);
08185    tmpvars.amaflags = chan->amaflags;
08186    tmpvars.state = chan->_state;
08187    tmpvars.writeformat = chan->writeformat;
08188    tmpvars.readformat = chan->readformat;
08189    tmpvars.cdr = chan->cdr ? ast_cdr_dup(chan->cdr) : NULL;
08190 
08191    ast_channel_unlock(chan);
08192 
08193    /* Do not hold any channel locks while calling channel_alloc() since the function
08194     * locks the channel container when linking the new channel in. */
08195    if (!(tmpchan = ast_channel_alloc(0, tmpvars.state, 0, 0, tmpvars.accountcode, tmpvars.exten, tmpvars.context, tmpvars.linkedid, tmpvars.amaflags, "AsyncGoto/%s", tmpvars.name))) {
08196       ast_cdr_discard(tmpvars.cdr);
08197       return -1;
08198    }
08199 
08200    /* copy the cdr info over */
08201    if (tmpvars.cdr) {
08202       ast_cdr_discard(tmpchan->cdr);
08203       tmpchan->cdr = tmpvars.cdr;
08204       tmpvars.cdr = NULL;
08205    }
08206 
08207    /* Make formats okay */
08208    tmpchan->readformat = tmpvars.readformat;
08209    tmpchan->writeformat = tmpvars.writeformat;
08210 
08211    /* Setup proper location. Never hold another channel lock while calling this function. */
08212    ast_explicit_goto(tmpchan, S_OR(context, tmpvars.context), S_OR(exten, tmpvars.exten), priority);
08213 
08214    /* Masquerade into tmp channel */
08215    if (ast_channel_masquerade(tmpchan, chan)) {
08216       /* Failed to set up the masquerade.  It's probably chan_local
08217        * in the middle of optimizing itself out.  Sad. :( */
08218       ast_hangup(tmpchan);
08219       tmpchan = NULL;
08220       res = -1;
08221    } else {
08222       ast_do_masquerade(tmpchan);
08223       /* Start the PBX going on our stolen channel */
08224       if (ast_pbx_start(tmpchan)) {
08225          ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmpchan->name);
08226          ast_hangup(tmpchan);
08227          res = -1;
08228       }
08229    }
08230 
08231    return res;
08232 }
08233 
08234 int ast_async_goto_by_name(const char *channame, const char *context, const char *exten, int priority)
08235 {
08236    struct ast_channel *chan;
08237    int res = -1;
08238 
08239    if ((chan = ast_channel_get_by_name(channame))) {
08240       res = ast_async_goto(chan, context, exten, priority);
08241       chan = ast_channel_unref(chan);
08242    }
08243 
08244    return res;
08245 }
08246 
08247 /*! \brief copy a string skipping whitespace */
08248 static int ext_strncpy(char *dst, const char *src, int len)
08249 {
08250    int count = 0;
08251    int insquares = 0;
08252 
08253    while (*src && (count < len - 1)) {
08254       if (*src == '[') {
08255          insquares = 1;
08256       } else if (*src == ']') {
08257          insquares = 0;
08258       } else if (*src == ' ' && !insquares) {
08259          src++;
08260          continue;
08261       }
08262       *dst = *src;
08263       dst++;
08264       src++;
08265       count++;
08266    }
08267    *dst = '\0';
08268 
08269    return count;
08270 }
08271 
08272 /*!
08273  * \brief add the extension in the priority chain.
08274  * \retval 0 on success.
08275  * \retval -1 on failure.
08276 */
08277 static int add_priority(struct ast_context *con, struct ast_exten *tmp,
08278    struct ast_exten *el, struct ast_exten *e, int replace)
08279 {
08280    struct ast_exten *ep;
08281    struct ast_exten *eh=e;
08282    int repeated_label = 0; /* Track if this label is a repeat, assume no. */
08283 
08284    for (ep = NULL; e ; ep = e, e = e->peer) {
08285       if (e->label && tmp->label && e->priority != tmp->priority && !strcmp(e->label, tmp->label)) {
08286          ast_log(LOG_WARNING, "Extension '%s', priority %d in '%s', label '%s' already in use at "
08287                "priority %d\n", tmp->exten, tmp->priority, con->name, tmp->label, e->priority);
08288          repeated_label = 1;
08289       }
08290       if (e->priority >= tmp->priority) {
08291          break;
08292       }
08293    }
08294 
08295    if (repeated_label) {   /* Discard the label since it's a repeat. */
08296       tmp->label = NULL;
08297    }
08298 
08299    if (!e) {   /* go at the end, and ep is surely set because the list is not empty */
08300       ast_hashtab_insert_safe(eh->peer_table, tmp);
08301 
08302       if (tmp->label) {
08303          ast_hashtab_insert_safe(eh->peer_label_table, tmp);
08304       }
08305       ep->peer = tmp;
08306       return 0;   /* success */
08307    }
08308    if (e->priority == tmp->priority) {
08309       /* Can't have something exactly the same.  Is this a
08310          replacement?  If so, replace, otherwise, bonk. */
08311       if (!replace) {
08312          ast_log(LOG_WARNING, "Unable to register extension '%s', priority %d in '%s', already in use\n", tmp->exten, tmp->priority, con->name);
08313          if (tmp->datad) {
08314             tmp->datad(tmp->data);
08315             /* if you free this, null it out */
08316             tmp->data = NULL;
08317          }
08318 
08319          ast_free(tmp);
08320          return -1;
08321       }
08322       /* we are replacing e, so copy the link fields and then update
08323        * whoever pointed to e to point to us
08324        */
08325       tmp->next = e->next; /* not meaningful if we are not first in the peer list */
08326       tmp->peer = e->peer; /* always meaningful */
08327       if (ep)  {     /* We're in the peer list, just insert ourselves */
08328          ast_hashtab_remove_object_via_lookup(eh->peer_table,e);
08329 
08330          if (e->label) {
08331             ast_hashtab_remove_object_via_lookup(eh->peer_label_table,e);
08332          }
08333 
08334          ast_hashtab_insert_safe(eh->peer_table,tmp);
08335          if (tmp->label) {
08336             ast_hashtab_insert_safe(eh->peer_label_table,tmp);
08337          }
08338 
08339          ep->peer = tmp;
08340       } else if (el) {     /* We're the first extension. Take over e's functions */
08341          struct match_char *x = add_exten_to_pattern_tree(con, e, 1);
08342          tmp->peer_table = e->peer_table;
08343          tmp->peer_label_table = e->peer_label_table;
08344          ast_hashtab_remove_object_via_lookup(tmp->peer_table,e);
08345          ast_hashtab_insert_safe(tmp->peer_table,tmp);
08346          if (e->label) {
08347             ast_hashtab_remove_object_via_lookup(tmp->peer_label_table, e);
08348          }
08349          if (tmp->label) {
08350             ast_hashtab_insert_safe(tmp->peer_label_table, tmp);
08351          }
08352 
08353          ast_hashtab_remove_object_via_lookup(con->root_table, e);
08354          ast_hashtab_insert_safe(con->root_table, tmp);
08355          el->next = tmp;
08356          /* The pattern trie points to this exten; replace the pointer,
08357             and all will be well */
08358          if (x) { /* if the trie isn't formed yet, don't sweat this */
08359             if (x->exten) { /* this test for safety purposes */
08360                x->exten = tmp; /* replace what would become a bad pointer */
08361             } else {
08362                ast_log(LOG_ERROR,"Trying to delete an exten from a context, but the pattern tree node returned isn't an extension\n");
08363             }
08364          }
08365       } else {       /* We're the very first extension.  */
08366          struct match_char *x = add_exten_to_pattern_tree(con, e, 1);
08367          ast_hashtab_remove_object_via_lookup(con->root_table, e);
08368          ast_hashtab_insert_safe(con->root_table, tmp);
08369          tmp->peer_table = e->peer_table;
08370          tmp->peer_label_table = e->peer_label_table;
08371          ast_hashtab_remove_object_via_lookup(tmp->peer_table, e);
08372          ast_hashtab_insert_safe(tmp->peer_table, tmp);
08373          if (e->label) {
08374             ast_hashtab_remove_object_via_lookup(tmp->peer_label_table, e);
08375          }
08376          if (tmp->label) {
08377             ast_hashtab_insert_safe(tmp->peer_label_table, tmp);
08378          }
08379 
08380          ast_hashtab_remove_object_via_lookup(con->root_table, e);
08381          ast_hashtab_insert_safe(con->root_table, tmp);
08382          con->root = tmp;
08383          /* The pattern trie points to this exten; replace the pointer,
08384             and all will be well */
08385          if (x) { /* if the trie isn't formed yet; no problem */
08386             if (x->exten) { /* this test for safety purposes */
08387                x->exten = tmp; /* replace what would become a bad pointer */
08388             } else {
08389                ast_log(LOG_ERROR,"Trying to delete an exten from a context, but the pattern tree node returned isn't an extension\n");
08390             }
08391          }
08392       }
08393       if (tmp->priority == PRIORITY_HINT)
08394          ast_change_hint(e,tmp);
08395       /* Destroy the old one */
08396       if (e->datad)
08397          e->datad(e->data);
08398       ast_free(e);
08399    } else { /* Slip ourselves in just before e */
08400       tmp->peer = e;
08401       tmp->next = e->next; /* extension chain, or NULL if e is not the first extension */
08402       if (ep) {         /* Easy enough, we're just in the peer list */
08403          if (tmp->label) {
08404             ast_hashtab_insert_safe(eh->peer_label_table, tmp);
08405          }
08406          ast_hashtab_insert_safe(eh->peer_table, tmp);
08407          ep->peer = tmp;
08408       } else {       /* we are the first in some peer list, so link in the ext list */
08409          tmp->peer_table = e->peer_table;
08410          tmp->peer_label_table = e->peer_label_table;
08411          e->peer_table = 0;
08412          e->peer_label_table = 0;
08413          ast_hashtab_insert_safe(tmp->peer_table, tmp);
08414          if (tmp->label) {
08415             ast_hashtab_insert_safe(tmp->peer_label_table, tmp);
08416          }
08417          ast_hashtab_remove_object_via_lookup(con->root_table, e);
08418          ast_hashtab_insert_safe(con->root_table, tmp);
08419          if (el)
08420             el->next = tmp;   /* in the middle... */
08421          else
08422             con->root = tmp; /* ... or at the head */
08423          e->next = NULL;   /* e is no more at the head, so e->next must be reset */
08424       }
08425       /* And immediately return success. */
08426       if (tmp->priority == PRIORITY_HINT) {
08427          ast_add_hint(tmp);
08428       }
08429    }
08430    return 0;
08431 }
08432 
08433 /*! \brief
08434  * Main interface to add extensions to the list for out context.
08435  *
08436  * We sort extensions in order of matching preference, so that we can
08437  * stop the search as soon as we find a suitable match.
08438  * This ordering also takes care of wildcards such as '.' (meaning
08439  * "one or more of any character") and '!' (which is 'earlymatch',
08440  * meaning "zero or more of any character" but also impacts the
08441  * return value from CANMATCH and EARLYMATCH.
08442  *
08443  * The extension match rules defined in the devmeeting 2006.05.05 are
08444  * quite simple: WE SELECT THE LONGEST MATCH.
08445  * In detail, "longest" means the number of matched characters in
08446  * the extension. In case of ties (e.g. _XXX and 333) in the length
08447  * of a pattern, we give priority to entries with the smallest cardinality
08448  * (e.g, [5-9] comes before [2-8] before the former has only 5 elements,
08449  * while the latter has 7, etc.
08450  * In case of same cardinality, the first element in the range counts.
08451  * If we still have a tie, any final '!' will make this as a possibly
08452  * less specific pattern.
08453  *
08454  * EBUSY - can't lock
08455  * EEXIST - extension with the same priority exist and no replace is set
08456  *
08457  */
08458 int ast_add_extension2(struct ast_context *con,
08459    int replace, const char *extension, int priority, const char *label, const char *callerid,
08460    const char *application, void *data, void (*datad)(void *),
08461    const char *registrar)
08462 {
08463    return ast_add_extension2_lockopt(con, replace, extension, priority, label, callerid,
08464       application, data, datad, registrar, 1);
08465 }
08466 
08467 /*!
08468  * \brief Same as ast_add_extension2() but controls the context locking.
08469  *
08470  * \details
08471  * Does all the work of ast_add_extension2, but adds an arg to
08472  * determine if context locking should be done.
08473  */
08474 static int ast_add_extension2_lockopt(struct ast_context *con,
08475    int replace, const char *extension, int priority, const char *label, const char *callerid,
08476    const char *application, void *data, void (*datad)(void *),
08477    const char *registrar, int lock_context)
08478 {
08479    /*
08480     * Sort extensions (or patterns) according to the rules indicated above.
08481     * These are implemented by the function ext_cmp()).
08482     * All priorities for the same ext/pattern/cid are kept in a list,
08483     * using the 'peer' field  as a link field..
08484     */
08485    struct ast_exten *tmp, *tmp2, *e, *el = NULL;
08486    int res;
08487    int length;
08488    char *p;
08489    char expand_buf[VAR_BUF_SIZE];
08490    struct ast_exten dummy_exten = {0};
08491    char dummy_name[1024];
08492 
08493    if (ast_strlen_zero(extension)) {
08494       ast_log(LOG_ERROR,"You have to be kidding-- add exten '' to context %s? Figure out a name and call me back. Action ignored.\n",
08495             con->name);
08496       return -1;
08497    }
08498 
08499    /* If we are adding a hint evalulate in variables and global variables */
08500    if (priority == PRIORITY_HINT && strstr(application, "${") && !strstr(extension, "_")) {
08501       struct ast_channel *c = ast_dummy_channel_alloc();
08502 
08503       if (c) {
08504          ast_copy_string(c->exten, extension, sizeof(c->exten));
08505          ast_copy_string(c->context, con->name, sizeof(c->context));
08506       }
08507       pbx_substitute_variables_helper(c, application, expand_buf, sizeof(expand_buf));
08508       application = expand_buf;
08509       if (c) {
08510          ast_channel_unref(c);
08511       }
08512    }
08513 
08514    length = sizeof(struct ast_exten);
08515    length += strlen(extension) + 1;
08516    length += strlen(application) + 1;
08517    if (label)
08518       length += strlen(label) + 1;
08519    if (callerid)
08520       length += strlen(callerid) + 1;
08521    else
08522       length ++;  /* just the '\0' */
08523 
08524    /* Be optimistic:  Build the extension structure first */
08525    if (!(tmp = ast_calloc(1, length)))
08526       return -1;
08527 
08528    if (ast_strlen_zero(label)) /* let's turn empty labels to a null ptr */
08529       label = 0;
08530 
08531    /* use p as dst in assignments, as the fields are const char * */
08532    p = tmp->stuff;
08533    if (label) {
08534       tmp->label = p;
08535       strcpy(p, label);
08536       p += strlen(label) + 1;
08537    }
08538    tmp->exten = p;
08539    p += ext_strncpy(p, extension, strlen(extension) + 1) + 1;
08540    tmp->priority = priority;
08541    tmp->cidmatch = p;   /* but use p for assignments below */
08542 
08543    /* Blank callerid and NULL callerid are two SEPARATE things.  Do NOT confuse the two!!! */
08544    if (callerid) {
08545       p += ext_strncpy(p, callerid, strlen(callerid) + 1) + 1;
08546       tmp->matchcid = 1;
08547    } else {
08548       *p++ = '\0';
08549       tmp->matchcid = 0;
08550    }
08551    tmp->app = p;
08552    strcpy(p, application);
08553    tmp->parent = con;
08554    tmp->data = data;
08555    tmp->datad = datad;
08556    tmp->registrar = registrar;
08557 
08558    if (lock_context) {
08559       ast_wrlock_context(con);
08560    }
08561 
08562    if (con->pattern_tree) { /* usually, on initial load, the pattern_tree isn't formed until the first find_exten; so if we are adding
08563                         an extension, and the trie exists, then we need to incrementally add this pattern to it. */
08564       ast_copy_string(dummy_name, extension, sizeof(dummy_name));
08565       dummy_exten.exten = dummy_name;
08566       dummy_exten.matchcid = 0;
08567       dummy_exten.cidmatch = 0;
08568       tmp2 = ast_hashtab_lookup(con->root_table, &dummy_exten);
08569       if (!tmp2) {
08570          /* hmmm, not in the trie; */
08571          add_exten_to_pattern_tree(con, tmp, 0);
08572          ast_hashtab_insert_safe(con->root_table, tmp); /* for the sake of completeness */
08573       }
08574    }
08575    res = 0; /* some compilers will think it is uninitialized otherwise */
08576    for (e = con->root; e; el = e, e = e->next) {   /* scan the extension list */
08577       res = ext_cmp(e->exten, tmp->exten);
08578       if (res == 0) { /* extension match, now look at cidmatch */
08579          if (!e->matchcid && !tmp->matchcid)
08580             res = 0;
08581          else if (tmp->matchcid && !e->matchcid)
08582             res = 1;
08583          else if (e->matchcid && !tmp->matchcid)
08584             res = -1;
08585          else
08586             res = ext_cmp(e->cidmatch, tmp->cidmatch);
08587       }
08588       if (res >= 0)
08589          break;
08590    }
08591    if (e && res == 0) { /* exact match, insert in the priority chain */
08592       res = add_priority(con, tmp, el, e, replace);
08593       if (lock_context) {
08594          ast_unlock_context(con);
08595       }
08596       if (res < 0) {
08597          errno = EEXIST;   /* XXX do we care ? */
08598          return 0; /* XXX should we return -1 maybe ? */
08599       }
08600    } else {
08601       /*
08602        * not an exact match, this is the first entry with this pattern,
08603        * so insert in the main list right before 'e' (if any)
08604        */
08605       tmp->next = e;
08606       if (el) {  /* there is another exten already in this context */
08607          el->next = tmp;
08608          tmp->peer_table = ast_hashtab_create(13,
08609                      hashtab_compare_exten_numbers,
08610                      ast_hashtab_resize_java,
08611                      ast_hashtab_newsize_java,
08612                      hashtab_hash_priority,
08613                      0);
08614          tmp->peer_label_table = ast_hashtab_create(7,
08615                         hashtab_compare_exten_labels,
08616                         ast_hashtab_resize_java,
08617                         ast_hashtab_newsize_java,
08618                         hashtab_hash_labels,
08619                         0);
08620          if (label) {
08621             ast_hashtab_insert_safe(tmp->peer_label_table, tmp);
08622          }
08623          ast_hashtab_insert_safe(tmp->peer_table, tmp);
08624       } else {  /* this is the first exten in this context */
08625          if (!con->root_table)
08626             con->root_table = ast_hashtab_create(27,
08627                                        hashtab_compare_extens,
08628                                        ast_hashtab_resize_java,
08629                                        ast_hashtab_newsize_java,
08630                                        hashtab_hash_extens,
08631                                        0);
08632          con->root = tmp;
08633          con->root->peer_table = ast_hashtab_create(13,
08634                         hashtab_compare_exten_numbers,
08635                         ast_hashtab_resize_java,
08636                         ast_hashtab_newsize_java,
08637                         hashtab_hash_priority,
08638                         0);
08639          con->root->peer_label_table = ast_hashtab_create(7,
08640                            hashtab_compare_exten_labels,
08641                            ast_hashtab_resize_java,
08642                            ast_hashtab_newsize_java,
08643                            hashtab_hash_labels,
08644                            0);
08645          if (label) {
08646             ast_hashtab_insert_safe(con->root->peer_label_table, tmp);
08647          }
08648          ast_hashtab_insert_safe(con->root->peer_table, tmp);
08649 
08650       }
08651       ast_hashtab_insert_safe(con->root_table, tmp);
08652       if (lock_context) {
08653          ast_unlock_context(con);
08654       }
08655       if (tmp->priority == PRIORITY_HINT) {
08656          ast_add_hint(tmp);
08657       }
08658    }
08659    if (option_debug) {
08660       if (tmp->matchcid) {
08661          ast_debug(1, "Added extension '%s' priority %d (CID match '%s') to %s (%p)\n",
08662                  tmp->exten, tmp->priority, tmp->cidmatch, con->name, con);
08663       } else {
08664          ast_debug(1, "Added extension '%s' priority %d to %s (%p)\n",
08665                  tmp->exten, tmp->priority, con->name, con);
08666       }
08667    }
08668 
08669    if (tmp->matchcid) {
08670       ast_verb(3, "Added extension '%s' priority %d (CID match '%s') to %s\n",
08671              tmp->exten, tmp->priority, tmp->cidmatch, con->name);
08672    } else {
08673       ast_verb(3, "Added extension '%s' priority %d to %s\n",
08674              tmp->exten, tmp->priority, con->name);
08675    }
08676 
08677    return 0;
08678 }
08679 
08680 struct async_stat {
08681    pthread_t p;
08682    struct ast_channel *chan;
08683    char context[AST_MAX_CONTEXT];
08684    char exten[AST_MAX_EXTENSION];
08685    int priority;
08686    int timeout;
08687    char app[AST_MAX_EXTENSION];
08688    char appdata[1024];
08689 };
08690 
08691 static void *async_wait(void *data)
08692 {
08693    struct async_stat *as = data;
08694    struct ast_channel *chan = as->chan;
08695    int timeout = as->timeout;
08696    int res;
08697    struct ast_frame *f;
08698    struct ast_app *app;
08699 
08700    while (timeout && (chan->_state != AST_STATE_UP)) {
08701       res = ast_waitfor(chan, timeout);
08702       if (res < 1)
08703          break;
08704       if (timeout > -1)
08705          timeout = res;
08706       f = ast_read(chan);
08707       if (!f)
08708          break;
08709       if (f->frametype == AST_FRAME_CONTROL) {
08710          if ((f->subclass.integer == AST_CONTROL_BUSY)  ||
08711              (f->subclass.integer == AST_CONTROL_CONGESTION) ) {
08712             ast_frfree(f);
08713             break;
08714          }
08715       }
08716       ast_frfree(f);
08717    }
08718    if (chan->_state == AST_STATE_UP) {
08719       if (!ast_strlen_zero(as->app)) {
08720          app = pbx_findapp(as->app);
08721          if (app) {
08722             ast_verb(3, "Launching %s(%s) on %s\n", as->app, as->appdata, chan->name);
08723             pbx_exec(chan, app, as->appdata);
08724          } else
08725             ast_log(LOG_WARNING, "No such application '%s'\n", as->app);
08726       } else {
08727          if (!ast_strlen_zero(as->context))
08728             ast_copy_string(chan->context, as->context, sizeof(chan->context));
08729          if (!ast_strlen_zero(as->exten))
08730             ast_copy_string(chan->exten, as->exten, sizeof(chan->exten));
08731          if (as->priority > 0)
08732             chan->priority = as->priority;
08733          /* Run the PBX */
08734          if (ast_pbx_run(chan)) {
08735             ast_log(LOG_ERROR, "Failed to start PBX on %s\n", chan->name);
08736          } else {
08737             /* PBX will have taken care of this */
08738             chan = NULL;
08739          }
08740       }
08741    }
08742    ast_free(as);
08743    if (chan)
08744       ast_hangup(chan);
08745    return NULL;
08746 }
08747 
08748 /*!
08749  * \brief Function to post an empty cdr after a spool call fails.
08750  * \note This function posts an empty cdr for a failed spool call
08751 */
08752 static int ast_pbx_outgoing_cdr_failed(void)
08753 {
08754    /* allocate a channel */
08755    struct ast_channel *chan = ast_dummy_channel_alloc();
08756 
08757    if (!chan)
08758       return -1;  /* failure */
08759 
08760    chan->cdr = ast_cdr_alloc();
08761    if (!chan->cdr) {
08762       /* allocation of the cdr failed */
08763       chan = ast_channel_unref(chan);   /* free the channel */
08764       return -1;                /* return failure */
08765    }
08766 
08767    /* allocation of the cdr was successful */
08768    ast_cdr_init(chan->cdr, chan);  /* initialize our channel's cdr */
08769    ast_cdr_start(chan->cdr);       /* record the start and stop time */
08770    ast_cdr_end(chan->cdr);
08771    ast_cdr_failed(chan->cdr);      /* set the status to failed */
08772    ast_cdr_detach(chan->cdr);      /* post and free the record */
08773    chan->cdr = NULL;
08774    chan = ast_channel_unref(chan);         /* free the channel */
08775 
08776    return 0;  /* success */
08777 }
08778 
08779 int ast_pbx_outgoing_exten(const char *type, format_t format, void *data, int timeout, const char *context, const char *exten, int priority, int *reason, int synchronous, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **channel)
08780 {
08781    struct ast_channel *chan;
08782    struct async_stat *as;
08783    int res = -1, cdr_res = -1;
08784    struct outgoing_helper oh;
08785 
08786    if (synchronous) {
08787       oh.context = context;
08788       oh.exten = exten;
08789       oh.priority = priority;
08790       oh.cid_num = cid_num;
08791       oh.cid_name = cid_name;
08792       oh.account = account;
08793       oh.vars = vars;
08794       oh.parent_channel = NULL;
08795 
08796       chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh);
08797       if (channel) {
08798          *channel = chan;
08799          if (chan)
08800             ast_channel_lock(chan);
08801       }
08802       if (chan) {
08803          if (chan->_state == AST_STATE_UP) {
08804                res = 0;
08805             ast_verb(4, "Channel %s was answered.\n", chan->name);
08806 
08807             if (synchronous > 1) {
08808                if (channel)
08809                   ast_channel_unlock(chan);
08810                if (ast_pbx_run(chan)) {
08811                   ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name);
08812                   if (channel)
08813                      *channel = NULL;
08814                   ast_hangup(chan);
08815                   chan = NULL;
08816                   res = -1;
08817                }
08818             } else {
08819                if (ast_pbx_start(chan)) {
08820                   ast_log(LOG_ERROR, "Unable to start PBX on %s\n", chan->name);
08821                   if (channel) {
08822                      *channel = NULL;
08823                      ast_channel_unlock(chan);
08824                   }
08825                   ast_hangup(chan);
08826                   res = -1;
08827                }
08828                chan = NULL;
08829             }
08830          } else {
08831             ast_verb(4, "Channel %s was never answered.\n", chan->name);
08832 
08833             if (chan->cdr) { /* update the cdr */
08834                /* here we update the status of the call, which sould be busy.
08835                 * if that fails then we set the status to failed */
08836                if (ast_cdr_disposition(chan->cdr, chan->hangupcause))
08837                   ast_cdr_failed(chan->cdr);
08838             }
08839 
08840             if (channel) {
08841                *channel = NULL;
08842                ast_channel_unlock(chan);
08843             }
08844             ast_hangup(chan);
08845             chan = NULL;
08846          }
08847       }
08848 
08849       if (res < 0) { /* the call failed for some reason */
08850          if (*reason == 0) { /* if the call failed (not busy or no answer)
08851                         * update the cdr with the failed message */
08852             cdr_res = ast_pbx_outgoing_cdr_failed();
08853             if (cdr_res != 0) {
08854                res = cdr_res;
08855                goto outgoing_exten_cleanup;
08856             }
08857          }
08858 
08859          /* create a fake channel and execute the "failed" extension (if it exists) within the requested context */
08860          /* check if "failed" exists */
08861          if (ast_exists_extension(chan, context, "failed", 1, NULL)) {
08862             chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", NULL, 0, "OutgoingSpoolFailed");
08863             if (chan) {
08864                char failed_reason[4] = "";
08865                if (!ast_strlen_zero(context))
08866                   ast_copy_string(chan->context, context, sizeof(chan->context));
08867                set_ext_pri(chan, "failed", 1);
08868                ast_set_variables(chan, vars);
08869                snprintf(failed_reason, sizeof(failed_reason), "%d", *reason);
08870                pbx_builtin_setvar_helper(chan, "REASON", failed_reason);
08871                if (account)
08872                   ast_cdr_setaccount(chan, account);
08873                if (ast_pbx_run(chan)) {
08874                   ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name);
08875                   ast_hangup(chan);
08876                }
08877                chan = NULL;
08878             }
08879          }
08880       }
08881    } else {
08882       if (!(as = ast_calloc(1, sizeof(*as)))) {
08883          res = -1;
08884          goto outgoing_exten_cleanup;
08885       }
08886       chan = ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name);
08887       if (channel) {
08888          *channel = chan;
08889          if (chan)
08890             ast_channel_lock(chan);
08891       }
08892       if (!chan) {
08893          ast_free(as);
08894          res = -1;
08895          goto outgoing_exten_cleanup;
08896       }
08897       as->chan = chan;
08898       ast_copy_string(as->context, context, sizeof(as->context));
08899       set_ext_pri(as->chan,  exten, priority);
08900       as->timeout = timeout;
08901       ast_set_variables(chan, vars);
08902       if (account)
08903          ast_cdr_setaccount(chan, account);
08904       if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) {
08905          ast_log(LOG_WARNING, "Failed to start async wait\n");
08906          ast_free(as);
08907          if (channel) {
08908             *channel = NULL;
08909             ast_channel_unlock(chan);
08910          }
08911          ast_hangup(chan);
08912          res = -1;
08913          goto outgoing_exten_cleanup;
08914       }
08915       res = 0;
08916    }
08917 outgoing_exten_cleanup:
08918    ast_variables_destroy(vars);
08919    return res;
08920 }
08921 
08922 struct app_tmp {
08923    struct ast_channel *chan;
08924    pthread_t t;
08925    AST_DECLARE_STRING_FIELDS (
08926       AST_STRING_FIELD(app);
08927       AST_STRING_FIELD(data);
08928    );
08929 };
08930 
08931 /*! \brief run the application and free the descriptor once done */
08932 static void *ast_pbx_run_app(void *data)
08933 {
08934    struct app_tmp *tmp = data;
08935    struct ast_app *app;
08936    app = pbx_findapp(tmp->app);
08937    if (app) {
08938       ast_verb(4, "Launching %s(%s) on %s\n", tmp->app, tmp->data, tmp->chan->name);
08939       pbx_exec(tmp->chan, app, tmp->data);
08940    } else
08941       ast_log(LOG_WARNING, "No such application '%s'\n", tmp->app);
08942    ast_hangup(tmp->chan);
08943    ast_string_field_free_memory(tmp);
08944    ast_free(tmp);
08945    return NULL;
08946 }
08947 
08948 int ast_pbx_outgoing_app(const char *type, format_t format, void *data, int timeout, const char *app, const char *appdata, int *reason, int synchronous, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel)
08949 {
08950    struct ast_channel *chan;
08951    struct app_tmp *tmp;
08952    int res = -1, cdr_res = -1;
08953    struct outgoing_helper oh;
08954 
08955    memset(&oh, 0, sizeof(oh));
08956    oh.vars = vars;
08957    oh.account = account;
08958 
08959    if (locked_channel)
08960       *locked_channel = NULL;
08961    if (ast_strlen_zero(app)) {
08962       res = -1;
08963       goto outgoing_app_cleanup;
08964    }
08965    if (synchronous) {
08966       chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh);
08967       if (chan) {
08968          ast_set_variables(chan, vars);
08969          if (account)
08970             ast_cdr_setaccount(chan, account);
08971          if (chan->_state == AST_STATE_UP) {
08972             res = 0;
08973             ast_verb(4, "Channel %s was answered.\n", chan->name);
08974             tmp = ast_calloc(1, sizeof(*tmp));
08975             if (!tmp || ast_string_field_init(tmp, 252)) {
08976                if (tmp) {
08977                   ast_free(tmp);
08978                }
08979                res = -1;
08980             } else {
08981                ast_string_field_set(tmp, app, app);
08982                ast_string_field_set(tmp, data, appdata);
08983                tmp->chan = chan;
08984                if (synchronous > 1) {
08985                   if (locked_channel)
08986                      ast_channel_unlock(chan);
08987                   ast_pbx_run_app(tmp);
08988                } else {
08989                   if (locked_channel)
08990                      ast_channel_lock(chan);
08991                   if (ast_pthread_create_detached(&tmp->t, NULL, ast_pbx_run_app, tmp)) {
08992                      ast_log(LOG_WARNING, "Unable to spawn execute thread on %s: %s\n", chan->name, strerror(errno));
08993                      ast_string_field_free_memory(tmp);
08994                      ast_free(tmp);
08995                      if (locked_channel)
08996                         ast_channel_unlock(chan);
08997                      ast_hangup(chan);
08998                      res = -1;
08999                   } else {
09000                      if (locked_channel)
09001                         *locked_channel = chan;
09002                   }
09003                }
09004             }
09005          } else {
09006             ast_verb(4, "Channel %s was never answered.\n", chan->name);
09007             if (chan->cdr) { /* update the cdr */
09008                /* here we update the status of the call, which sould be busy.
09009                 * if that fails then we set the status to failed */
09010                if (ast_cdr_disposition(chan->cdr, chan->hangupcause))
09011                   ast_cdr_failed(chan->cdr);
09012             }
09013             ast_hangup(chan);
09014          }
09015       }
09016 
09017       if (res < 0) { /* the call failed for some reason */
09018          if (*reason == 0) { /* if the call failed (not busy or no answer)
09019                         * update the cdr with the failed message */
09020             cdr_res = ast_pbx_outgoing_cdr_failed();
09021             if (cdr_res != 0) {
09022                res = cdr_res;
09023                goto outgoing_app_cleanup;
09024             }
09025          }
09026       }
09027 
09028    } else {
09029       struct async_stat *as;
09030       if (!(as = ast_calloc(1, sizeof(*as)))) {
09031          res = -1;
09032          goto outgoing_app_cleanup;
09033       }
09034       chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh);
09035       if (!chan) {
09036          ast_free(as);
09037          res = -1;
09038          goto outgoing_app_cleanup;
09039       }
09040       as->chan = chan;
09041       ast_copy_string(as->app, app, sizeof(as->app));
09042       if (appdata)
09043          ast_copy_string(as->appdata,  appdata, sizeof(as->appdata));
09044       as->timeout = timeout;
09045       ast_set_variables(chan, vars);
09046       if (account)
09047          ast_cdr_setaccount(chan, account);
09048       /* Start a new thread, and get something handling this channel. */
09049       if (locked_channel)
09050          ast_channel_lock(chan);
09051       if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) {
09052          ast_log(LOG_WARNING, "Failed to start async wait\n");
09053          ast_free(as);
09054          if (locked_channel)
09055             ast_channel_unlock(chan);
09056          ast_hangup(chan);
09057          res = -1;
09058          goto outgoing_app_cleanup;
09059       } else {
09060          if (locked_channel)
09061             *locked_channel = chan;
09062       }
09063       res = 0;
09064    }
09065 outgoing_app_cleanup:
09066    ast_variables_destroy(vars);
09067    return res;
09068 }
09069 
09070 /* this is the guts of destroying a context --
09071    freeing up the structure, traversing and destroying the
09072    extensions, switches, ignorepats, includes, etc. etc. */
09073 
09074 static void __ast_internal_context_destroy( struct ast_context *con)
09075 {
09076    struct ast_include *tmpi;
09077    struct ast_sw *sw;
09078    struct ast_exten *e, *el, *en;
09079    struct ast_ignorepat *ipi;
09080    struct ast_context *tmp = con;
09081 
09082    for (tmpi = tmp->includes; tmpi; ) { /* Free includes */
09083       struct ast_include *tmpil = tmpi;
09084       tmpi = tmpi->next;
09085       ast_free(tmpil);
09086    }
09087    for (ipi = tmp->ignorepats; ipi; ) { /* Free ignorepats */
09088       struct ast_ignorepat *ipl = ipi;
09089       ipi = ipi->next;
09090       ast_free(ipl);
09091    }
09092    if (tmp->registrar)
09093       ast_free(tmp->registrar);
09094 
09095    /* destroy the hash tabs */
09096    if (tmp->root_table) {
09097       ast_hashtab_destroy(tmp->root_table, 0);
09098    }
09099    /* and destroy the pattern tree */
09100    if (tmp->pattern_tree)
09101       destroy_pattern_tree(tmp->pattern_tree);
09102 
09103    while ((sw = AST_LIST_REMOVE_HEAD(&tmp->alts, list)))
09104       ast_free(sw);
09105    for (e = tmp->root; e;) {
09106       for (en = e->peer; en;) {
09107          el = en;
09108          en = en->peer;
09109          destroy_exten(el);
09110       }
09111       el = e;
09112       e = e->next;
09113       destroy_exten(el);
09114    }
09115    tmp->root = NULL;
09116    ast_rwlock_destroy(&tmp->lock);
09117    ast_free(tmp);
09118 }
09119 
09120 
09121 void __ast_context_destroy(struct ast_context *list, struct ast_hashtab *contexttab, struct ast_context *con, const char *registrar)
09122 {
09123    struct ast_context *tmp, *tmpl=NULL;
09124    struct ast_exten *exten_item, *prio_item;
09125 
09126    for (tmp = list; tmp; ) {
09127       struct ast_context *next = NULL; /* next starting point */
09128          /* The following code used to skip forward to the next
09129             context with matching registrar, but this didn't
09130             make sense; individual priorities registrar'd to
09131             the matching registrar could occur in any context! */
09132       ast_debug(1, "Investigate ctx %s %s\n", tmp->name, tmp->registrar);
09133       if (con) {
09134          for (; tmp; tmpl = tmp, tmp = tmp->next) { /* skip to the matching context */
09135             ast_debug(1, "check ctx %s %s\n", tmp->name, tmp->registrar);
09136             if ( !strcasecmp(tmp->name, con->name) ) {
09137                break;   /* found it */
09138             }
09139          }
09140       }
09141 
09142       if (!tmp)   /* not found, we are done */
09143          break;
09144       ast_wrlock_context(tmp);
09145 
09146       if (registrar) {
09147          /* then search thru and remove any extens that match registrar. */
09148          struct ast_hashtab_iter *exten_iter;
09149          struct ast_hashtab_iter *prio_iter;
09150          struct ast_ignorepat *ip, *ipl = NULL, *ipn = NULL;
09151          struct ast_include *i, *pi = NULL, *ni = NULL;
09152          struct ast_sw *sw = NULL;
09153 
09154          /* remove any ignorepats whose registrar matches */
09155          for (ip = tmp->ignorepats; ip; ip = ipn) {
09156             ipn = ip->next;
09157             if (!strcmp(ip->registrar, registrar)) {
09158                if (ipl) {
09159                   ipl->next = ip->next;
09160                   ast_free(ip);
09161                   continue; /* don't change ipl */
09162                } else {
09163                   tmp->ignorepats = ip->next;
09164                   ast_free(ip);
09165                   continue; /* don't change ipl */
09166                }
09167             }
09168             ipl = ip;
09169          }
09170          /* remove any includes whose registrar matches */
09171          for (i = tmp->includes; i; i = ni) {
09172             ni = i->next;
09173             if (strcmp(i->registrar, registrar) == 0) {
09174                /* remove from list */
09175                if (pi) {
09176                   pi->next = i->next;
09177                   /* free include */
09178                   ast_free(i);
09179                   continue; /* don't change pi */
09180                } else {
09181                   tmp->includes = i->next;
09182                   /* free include */
09183                   ast_free(i);
09184                   continue; /* don't change pi */
09185                }
09186             }
09187             pi = i;
09188          }
09189          /* remove any switches whose registrar matches */
09190          AST_LIST_TRAVERSE_SAFE_BEGIN(&tmp->alts, sw, list) {
09191             if (strcmp(sw->registrar,registrar) == 0) {
09192                AST_LIST_REMOVE_CURRENT(list);
09193                ast_free(sw);
09194             }
09195          }
09196          AST_LIST_TRAVERSE_SAFE_END;
09197 
09198          if (tmp->root_table) { /* it is entirely possible that the context is EMPTY */
09199             exten_iter = ast_hashtab_start_traversal(tmp->root_table);
09200             while ((exten_item=ast_hashtab_next(exten_iter))) {
09201                int end_traversal = 1;
09202                prio_iter = ast_hashtab_start_traversal(exten_item->peer_table);
09203                while ((prio_item=ast_hashtab_next(prio_iter))) {
09204                   char extension[AST_MAX_EXTENSION];
09205                   char cidmatch[AST_MAX_EXTENSION];
09206                   if (!prio_item->registrar || strcmp(prio_item->registrar, registrar) != 0) {
09207                      continue;
09208                   }
09209                   ast_verb(3, "Remove %s/%s/%d, registrar=%s; con=%s(%p); con->root=%p\n",
09210                          tmp->name, prio_item->exten, prio_item->priority, registrar, con? con->name : "<nil>", con, con? con->root_table: NULL);
09211                   /* set matchcid to 1 to insure we get a direct match, and NULL registrar to make sure no wildcarding is done */
09212                   ast_copy_string(extension, prio_item->exten, sizeof(extension));
09213                   if (prio_item->cidmatch) {
09214                      ast_copy_string(cidmatch, prio_item->cidmatch, sizeof(cidmatch));
09215                   }
09216                   end_traversal &= ast_context_remove_extension_callerid2(tmp, extension, prio_item->priority, prio_item->cidmatch ? cidmatch : NULL, 1, NULL, 1);
09217                }
09218                /* Explanation:
09219                 * ast_context_remove_extension_callerid2 will destroy the extension that it comes across. This
09220                 * destruction includes destroying the exten's peer_table, which we are currently traversing. If
09221                 * ast_context_remove_extension_callerid2 ever should return '0' then this means we have destroyed
09222                 * the hashtable which we are traversing, and thus calling ast_hashtab_end_traversal will result
09223                 * in reading invalid memory. Thus, if we detect that we destroyed the hashtable, then we will simply
09224                 * free the iterator
09225                 */
09226                if (end_traversal) {
09227                   ast_hashtab_end_traversal(prio_iter);
09228                } else {
09229                   ast_free(prio_iter);
09230                }
09231             }
09232             ast_hashtab_end_traversal(exten_iter);
09233          }
09234 
09235          /* delete the context if it's registrar matches, is empty, has refcount of 1, */
09236          /* it's not empty, if it has includes, ignorepats, or switches that are registered from
09237             another registrar. It's not empty if there are any extensions */
09238          if (strcmp(tmp->registrar, registrar) == 0 && tmp->refcount < 2 && !tmp->root && !tmp->ignorepats && !tmp->includes && AST_LIST_EMPTY(&tmp->alts)) {
09239             ast_debug(1, "delete ctx %s %s\n", tmp->name, tmp->registrar);
09240             ast_hashtab_remove_this_object(contexttab, tmp);
09241 
09242             next = tmp->next;
09243             if (tmpl)
09244                tmpl->next = next;
09245             else
09246                contexts = next;
09247             /* Okay, now we're safe to let it go -- in a sense, we were
09248                ready to let it go as soon as we locked it. */
09249             ast_unlock_context(tmp);
09250             __ast_internal_context_destroy(tmp);
09251          } else {
09252             ast_debug(1,"Couldn't delete ctx %s/%s; refc=%d; tmp.root=%p\n", tmp->name, tmp->registrar,
09253                     tmp->refcount, tmp->root);
09254             ast_unlock_context(tmp);
09255             next = tmp->next;
09256             tmpl = tmp;
09257          }
09258       } else if (con) {
09259          ast_verb(3, "Deleting context %s registrar=%s\n", tmp->name, tmp->registrar);
09260          ast_debug(1, "delete ctx %s %s\n", tmp->name, tmp->registrar);
09261          ast_hashtab_remove_this_object(contexttab, tmp);
09262 
09263          next = tmp->next;
09264          if (tmpl)
09265             tmpl->next = next;
09266          else
09267             contexts = next;
09268          /* Okay, now we're safe to let it go -- in a sense, we were
09269             ready to let it go as soon as we locked it. */
09270          ast_unlock_context(tmp);
09271          __ast_internal_context_destroy(tmp);
09272       }
09273 
09274       /* if we have a specific match, we are done, otherwise continue */
09275       tmp = con ? NULL : next;
09276    }
09277 }
09278 
09279 void ast_context_destroy(struct ast_context *con, const char *registrar)
09280 {
09281    ast_wrlock_contexts();
09282    __ast_context_destroy(contexts, contexts_table, con,registrar);
09283    ast_unlock_contexts();
09284 }
09285 
09286 static void wait_for_hangup(struct ast_channel *chan, const void *data)
09287 {
09288    int res;
09289    struct ast_frame *f;
09290    double waitsec;
09291    int waittime;
09292 
09293    if (ast_strlen_zero(data) || (sscanf(data, "%30lg", &waitsec) != 1) || (waitsec < 0))
09294       waitsec = -1;
09295    if (waitsec > -1) {
09296       waittime = waitsec * 1000.0;
09297       ast_safe_sleep(chan, waittime);
09298    } else do {
09299       res = ast_waitfor(chan, -1);
09300       if (res < 0)
09301          return;
09302       f = ast_read(chan);
09303       if (f)
09304          ast_frfree(f);
09305    } while(f);
09306 }
09307 
09308 /*!
09309  * \ingroup applications
09310  */
09311 static int pbx_builtin_proceeding(struct ast_channel *chan, const char *data)
09312 {
09313    ast_indicate(chan, AST_CONTROL_PROCEEDING);
09314    return 0;
09315 }
09316 
09317 /*!
09318  * \ingroup applications
09319  */
09320 static int pbx_builtin_progress(struct ast_channel *chan, const char *data)
09321 {
09322    ast_indicate(chan, AST_CONTROL_PROGRESS);
09323    return 0;
09324 }
09325 
09326 /*!
09327  * \ingroup applications
09328  */
09329 static int pbx_builtin_ringing(struct ast_channel *chan, const char *data)
09330 {
09331    ast_indicate(chan, AST_CONTROL_RINGING);
09332    return 0;
09333 }
09334 
09335 /*!
09336  * \ingroup applications
09337  */
09338 static int pbx_builtin_busy(struct ast_channel *chan, const char *data)
09339 {
09340    ast_indicate(chan, AST_CONTROL_BUSY);
09341    /* Don't change state of an UP channel, just indicate
09342       busy in audio */
09343    if (chan->_state != AST_STATE_UP) {
09344       ast_setstate(chan, AST_STATE_BUSY);
09345       ast_cdr_busy(chan->cdr);
09346    }
09347    wait_for_hangup(chan, data);
09348    return -1;
09349 }
09350 
09351 /*!
09352  * \ingroup applications
09353  */
09354 static int pbx_builtin_congestion(struct ast_channel *chan, const char *data)
09355 {
09356    ast_indicate(chan, AST_CONTROL_CONGESTION);
09357    /* Don't change state of an UP channel, just indicate
09358       congestion in audio */
09359    if (chan->_state != AST_STATE_UP)
09360       ast_setstate(chan, AST_STATE_BUSY);
09361    wait_for_hangup(chan, data);
09362    return -1;
09363 }
09364 
09365 /*!
09366  * \ingroup applications
09367  */
09368 static int pbx_builtin_answer(struct ast_channel *chan, const char *data)
09369 {
09370    int delay = 0;
09371    int answer_cdr = 1;
09372    char *parse;
09373    AST_DECLARE_APP_ARGS(args,
09374       AST_APP_ARG(delay);
09375       AST_APP_ARG(answer_cdr);
09376    );
09377 
09378    if (ast_strlen_zero(data)) {
09379       return __ast_answer(chan, 0, 1);
09380    }
09381 
09382    parse = ast_strdupa(data);
09383 
09384    AST_STANDARD_APP_ARGS(args, parse);
09385 
09386    if (!ast_strlen_zero(args.delay) && (chan->_state != AST_STATE_UP))
09387       delay = atoi(data);
09388 
09389    if (delay < 0) {
09390       delay = 0;
09391    }
09392 
09393    if (!ast_strlen_zero(args.answer_cdr) && !strcasecmp(args.answer_cdr, "nocdr")) {
09394       answer_cdr = 0;
09395    }
09396 
09397    return __ast_answer(chan, delay, answer_cdr);
09398 }
09399 
09400 static int pbx_builtin_incomplete(struct ast_channel *chan, const char *data)
09401 {
09402    const char *options = data;
09403    int answer = 1;
09404 
09405    /* Some channels can receive DTMF in unanswered state; some cannot */
09406    if (!ast_strlen_zero(options) && strchr(options, 'n')) {
09407       answer = 0;
09408    }
09409 
09410    /* If the channel is hungup, stop waiting */
09411    if (ast_check_hangup(chan)) {
09412       return -1;
09413    } else if (chan->_state != AST_STATE_UP && answer) {
09414       __ast_answer(chan, 0, 1);
09415    }
09416 
09417    ast_indicate(chan, AST_CONTROL_INCOMPLETE);
09418 
09419    return AST_PBX_INCOMPLETE;
09420 }
09421 
09422 AST_APP_OPTIONS(resetcdr_opts, {
09423    AST_APP_OPTION('w', AST_CDR_FLAG_POSTED),
09424    AST_APP_OPTION('a', AST_CDR_FLAG_LOCKED),
09425    AST_APP_OPTION('v', AST_CDR_FLAG_KEEP_VARS),
09426    AST_APP_OPTION('e', AST_CDR_FLAG_POST_ENABLE),
09427 });
09428 
09429 /*!
09430  * \ingroup applications
09431  */
09432 static int pbx_builtin_resetcdr(struct ast_channel *chan, const char *data)
09433 {
09434    char *args;
09435    struct ast_flags flags = { 0 };
09436 
09437    if (!ast_strlen_zero(data)) {
09438       args = ast_strdupa(data);
09439       ast_app_parse_options(resetcdr_opts, &flags, NULL, args);
09440    }
09441 
09442    ast_cdr_reset(chan->cdr, &flags);
09443 
09444    return 0;
09445 }
09446 
09447 /*!
09448  * \ingroup applications
09449  */
09450 static int pbx_builtin_setamaflags(struct ast_channel *chan, const char *data)
09451 {
09452    /* Copy the AMA Flags as specified */
09453    ast_channel_lock(chan);
09454    ast_cdr_setamaflags(chan, data ? data : "");
09455    ast_channel_unlock(chan);
09456    return 0;
09457 }
09458 
09459 /*!
09460  * \ingroup applications
09461  */
09462 static int pbx_builtin_hangup(struct ast_channel *chan, const char *data)
09463 {
09464    ast_set_hangupsource(chan, "dialplan/builtin", 0);
09465 
09466    if (!ast_strlen_zero(data)) {
09467       int cause;
09468       char *endptr;
09469 
09470       if ((cause = ast_str2cause(data)) > -1) {
09471          chan->hangupcause = cause;
09472          return -1;
09473       }
09474 
09475       cause = strtol((const char *) data, &endptr, 10);
09476       if (cause != 0 || (data != endptr)) {
09477          chan->hangupcause = cause;
09478          return -1;
09479       }
09480 
09481       ast_log(LOG_WARNING, "Invalid cause given to Hangup(): \"%s\"\n", (char *) data);
09482    }
09483 
09484    if (!chan->hangupcause) {
09485       chan->hangupcause = AST_CAUSE_NORMAL_CLEARING;
09486    }
09487 
09488    return -1;
09489 }
09490 
09491 /*!
09492  * \ingroup functions
09493  */
09494 static int testtime_write(struct ast_channel *chan, const char *cmd, char *var, const char *value)
09495 {
09496    struct ast_tm tm;
09497    struct timeval tv;
09498    char *remainder, result[30], timezone[80];
09499 
09500    /* Turn off testing? */
09501    if (!pbx_checkcondition(value)) {
09502       pbx_builtin_setvar_helper(chan, "TESTTIME", NULL);
09503       return 0;
09504    }
09505 
09506    /* Parse specified time */
09507    if (!(remainder = ast_strptime(value, "%Y/%m/%d %H:%M:%S", &tm))) {
09508       return -1;
09509    }
09510    sscanf(remainder, "%79s", timezone);
09511    tv = ast_mktime(&tm, S_OR(timezone, NULL));
09512 
09513    snprintf(result, sizeof(result), "%ld", (long) tv.tv_sec);
09514    pbx_builtin_setvar_helper(chan, "__TESTTIME", result);
09515    return 0;
09516 }
09517 
09518 static struct ast_custom_function testtime_function = {
09519    .name = "TESTTIME",
09520    .write = testtime_write,
09521 };
09522 
09523 /*!
09524  * \ingroup applications
09525  */
09526 static int pbx_builtin_gotoiftime(struct ast_channel *chan, const char *data)
09527 {
09528    char *s, *ts, *branch1, *branch2, *branch;
09529    struct ast_timing timing;
09530    const char *ctime;
09531    struct timeval tv = ast_tvnow();
09532    long timesecs;
09533 
09534    if (ast_strlen_zero(data)) {
09535       ast_log(LOG_WARNING, "GotoIfTime requires an argument:\n  <time range>,<days of week>,<days of month>,<months>[,<timezone>]?'labeliftrue':'labeliffalse'\n");
09536       return -1;
09537    }
09538 
09539    ts = s = ast_strdupa(data);
09540 
09541    if (chan) {
09542       ast_channel_lock(chan);
09543       if ((ctime = pbx_builtin_getvar_helper(chan, "TESTTIME")) && sscanf(ctime, "%ld", &timesecs) == 1) {
09544          tv.tv_sec = timesecs;
09545       } else if (ctime) {
09546          ast_log(LOG_WARNING, "Using current time to evaluate\n");
09547          /* Reset when unparseable */
09548          pbx_builtin_setvar_helper(chan, "TESTTIME", NULL);
09549       }
09550       ast_channel_unlock(chan);
09551    }
09552    /* Separate the Goto path */
09553    strsep(&ts, "?");
09554    branch1 = strsep(&ts,":");
09555    branch2 = strsep(&ts,"");
09556 
09557    /* struct ast_include include contained garbage here, fixed by zeroing it on get_timerange */
09558    if (ast_build_timing(&timing, s) && ast_check_timing2(&timing, tv)) {
09559       branch = branch1;
09560    } else {
09561       branch = branch2;
09562    }
09563    ast_destroy_timing(&timing);
09564 
09565    if (ast_strlen_zero(branch)) {
09566       ast_debug(1, "Not taking any branch\n");
09567       return 0;
09568    }
09569 
09570    return pbx_builtin_goto(chan, branch);
09571 }
09572 
09573 /*!
09574  * \ingroup applications
09575  */
09576 static int pbx_builtin_execiftime(struct ast_channel *chan, const char *data)
09577 {
09578    char *s, *appname;
09579    struct ast_timing timing;
09580    struct ast_app *app;
09581    static const char * const usage = "ExecIfTime requires an argument:\n  <time range>,<days of week>,<days of month>,<months>[,<timezone>]?<appname>[(<appargs>)]";
09582 
09583    if (ast_strlen_zero(data)) {
09584       ast_log(LOG_WARNING, "%s\n", usage);
09585       return -1;
09586    }
09587 
09588    appname = ast_strdupa(data);
09589 
09590    s = strsep(&appname, "?"); /* Separate the timerange and application name/data */
09591    if (!appname) {   /* missing application */
09592       ast_log(LOG_WARNING, "%s\n", usage);
09593       return -1;
09594    }
09595 
09596    if (!ast_build_timing(&timing, s)) {
09597       ast_log(LOG_WARNING, "Invalid Time Spec: %s\nCorrect usage: %s\n", s, usage);
09598       ast_destroy_timing(&timing);
09599       return -1;
09600    }
09601 
09602    if (!ast_check_timing(&timing))  { /* outside the valid time window, just return */
09603       ast_destroy_timing(&timing);
09604       return 0;
09605    }
09606    ast_destroy_timing(&timing);
09607 
09608    /* now split appname(appargs) */
09609    if ((s = strchr(appname, '('))) {
09610       char *e;
09611       *s++ = '\0';
09612       if ((e = strrchr(s, ')')))
09613          *e = '\0';
09614       else
09615          ast_log(LOG_WARNING, "Failed to find closing parenthesis\n");
09616    }
09617 
09618 
09619    if ((app = pbx_findapp(appname))) {
09620       return pbx_exec(chan, app, S_OR(s, ""));
09621    } else {
09622       ast_log(LOG_WARNING, "Cannot locate application %s\n", appname);
09623       return -1;
09624    }
09625 }
09626 
09627 /*!
09628  * \ingroup applications
09629  */
09630 static int pbx_builtin_wait(struct ast_channel *chan, const char *data)
09631 {
09632    int ms;
09633 
09634    /* Wait for "n" seconds */
09635    if (!ast_app_parse_timelen(data, &ms, TIMELEN_SECONDS) && ms > 0) {
09636       return ast_safe_sleep(chan, ms);
09637    }
09638    return 0;
09639 }
09640 
09641 /*!
09642  * \ingroup applications
09643  */
09644 static int pbx_builtin_waitexten(struct ast_channel *chan, const char *data)
09645 {
09646    int ms, res;
09647    struct ast_flags flags = {0};
09648    char *opts[1] = { NULL };
09649    char *parse;
09650    AST_DECLARE_APP_ARGS(args,
09651       AST_APP_ARG(timeout);
09652       AST_APP_ARG(options);
09653    );
09654 
09655    if (!ast_strlen_zero(data)) {
09656       parse = ast_strdupa(data);
09657       AST_STANDARD_APP_ARGS(args, parse);
09658    } else
09659       memset(&args, 0, sizeof(args));
09660 
09661    if (args.options)
09662       ast_app_parse_options(waitexten_opts, &flags, opts, args.options);
09663 
09664    if (ast_test_flag(&flags, WAITEXTEN_MOH) && !opts[0] ) {
09665       ast_log(LOG_WARNING, "The 'm' option has been specified for WaitExten without a class.\n"); 
09666    } else if (ast_test_flag(&flags, WAITEXTEN_MOH)) {
09667       ast_indicate_data(chan, AST_CONTROL_HOLD, S_OR(opts[0], NULL), strlen(opts[0]));
09668    } else if (ast_test_flag(&flags, WAITEXTEN_DIALTONE)) {
09669       struct ast_tone_zone_sound *ts = ast_get_indication_tone(chan->zone, "dial");
09670       if (ts) {
09671          ast_playtones_start(chan, 0, ts->data, 0);
09672          ts = ast_tone_zone_sound_unref(ts);
09673       } else {
09674          ast_tonepair_start(chan, 350, 440, 0, 0);
09675       }
09676    }
09677    /* Wait for "n" seconds */
09678    if (!ast_app_parse_timelen(args.timeout, &ms, TIMELEN_SECONDS) && ms > 0) {
09679       /* Yay! */
09680    } else if (chan->pbx) {
09681       ms = chan->pbx->rtimeoutms;
09682    } else {
09683       ms = 10000;
09684    }
09685 
09686    res = ast_waitfordigit(chan, ms);
09687    if (!res) {
09688       if (ast_check_hangup(chan)) {
09689          /* Call is hungup for some reason. */
09690          res = -1;
09691       } else if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 1,
09692          S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
09693          ast_verb(3, "Timeout on %s, continuing...\n", chan->name);
09694       } else if (ast_exists_extension(chan, chan->context, "t", 1,
09695          S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
09696          ast_verb(3, "Timeout on %s, going to 't'\n", chan->name);
09697          set_ext_pri(chan, "t", 0); /* 0 will become 1, next time through the loop */
09698       } else if (ast_exists_extension(chan, chan->context, "e", 1,
09699          S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
09700          raise_exception(chan, "RESPONSETIMEOUT", 0); /* 0 will become 1, next time through the loop */
09701       } else {
09702          ast_log(LOG_WARNING, "Timeout but no rule 't' or 'e' in context '%s'\n",
09703             chan->context);
09704          res = -1;
09705       }
09706    }
09707 
09708    if (ast_test_flag(&flags, WAITEXTEN_MOH))
09709       ast_indicate(chan, AST_CONTROL_UNHOLD);
09710    else if (ast_test_flag(&flags, WAITEXTEN_DIALTONE))
09711       ast_playtones_stop(chan);
09712 
09713    return res;
09714 }
09715 
09716 /*!
09717  * \ingroup applications
09718  */
09719 static int pbx_builtin_background(struct ast_channel *chan, const char *data)
09720 {
09721    int res = 0;
09722    int mres = 0;
09723    struct ast_flags flags = {0};
09724    char *parse, exten[2] = "";
09725    AST_DECLARE_APP_ARGS(args,
09726       AST_APP_ARG(filename);
09727       AST_APP_ARG(options);
09728       AST_APP_ARG(lang);
09729       AST_APP_ARG(context);
09730    );
09731 
09732    if (ast_strlen_zero(data)) {
09733       ast_log(LOG_WARNING, "Background requires an argument (filename)\n");
09734       return -1;
09735    }
09736 
09737    parse = ast_strdupa(data);
09738 
09739    AST_STANDARD_APP_ARGS(args, parse);
09740 
09741    if (ast_strlen_zero(args.lang))
09742       args.lang = (char *)chan->language; /* XXX this is const */
09743 
09744    if (ast_strlen_zero(args.context)) {
09745       const char *context;
09746       ast_channel_lock(chan);
09747       if ((context = pbx_builtin_getvar_helper(chan, "MACRO_CONTEXT"))) {
09748          args.context = ast_strdupa(context);
09749       } else {
09750          args.context = chan->context;
09751       }
09752       ast_channel_unlock(chan);
09753    }
09754 
09755    if (args.options) {
09756       if (!strcasecmp(args.options, "skip"))
09757          flags.flags = BACKGROUND_SKIP;
09758       else if (!strcasecmp(args.options, "noanswer"))
09759          flags.flags = BACKGROUND_NOANSWER;
09760       else
09761          ast_app_parse_options(background_opts, &flags, NULL, args.options);
09762    }
09763 
09764    /* Answer if need be */
09765    if (chan->_state != AST_STATE_UP) {
09766       if (ast_test_flag(&flags, BACKGROUND_SKIP)) {
09767          goto done;
09768       } else if (!ast_test_flag(&flags, BACKGROUND_NOANSWER)) {
09769          res = ast_answer(chan);
09770       }
09771    }
09772 
09773    if (!res) {
09774       char *back = ast_strip(args.filename);
09775       char *front;
09776 
09777       ast_stopstream(chan);      /* Stop anything playing */
09778       /* Stream the list of files */
09779       while (!res && (front = strsep(&back, "&")) ) {
09780          if ( (res = ast_streamfile(chan, front, args.lang)) ) {
09781             ast_log(LOG_WARNING, "ast_streamfile failed on %s for %s\n", chan->name, (char*)data);
09782             res = 0;
09783             mres = 1;
09784             break;
09785          }
09786          if (ast_test_flag(&flags, BACKGROUND_PLAYBACK)) {
09787             res = ast_waitstream(chan, "");
09788          } else if (ast_test_flag(&flags, BACKGROUND_MATCHEXTEN)) {
09789             res = ast_waitstream_exten(chan, args.context);
09790          } else {
09791             res = ast_waitstream(chan, AST_DIGIT_ANY);
09792          }
09793          ast_stopstream(chan);
09794       }
09795    }
09796 
09797    /*
09798     * If the single digit DTMF is an extension in the specified context, then
09799     * go there and signal no DTMF.  Otherwise, we should exit with that DTMF.
09800     * If we're in Macro, we'll exit and seek that DTMF as the beginning of an
09801     * extension in the Macro's calling context.  If we're not in Macro, then
09802     * we'll simply seek that extension in the calling context.  Previously,
09803     * someone complained about the behavior as it related to the interior of a
09804     * Gosub routine, and the fix (#14011) inadvertently broke FreePBX
09805     * (#14940).  This change should fix both of these situations, but with the
09806     * possible incompatibility that if a single digit extension does not exist
09807     * (but a longer extension COULD have matched), it would have previously
09808     * gone immediately to the "i" extension, but will now need to wait for a
09809     * timeout.
09810     *
09811     * Later, we had to add a flag to disable this workaround, because AGI
09812     * users can EXEC Background and reasonably expect that the DTMF code will
09813     * be returned (see #16434).
09814     */
09815    if (!ast_test_flag(chan, AST_FLAG_DISABLE_WORKAROUNDS)
09816       && (exten[0] = res)
09817       && ast_canmatch_extension(chan, args.context, exten, 1,
09818          S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))
09819       && !ast_matchmore_extension(chan, args.context, exten, 1,
09820          S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
09821       snprintf(chan->exten, sizeof(chan->exten), "%c", res);
09822       ast_copy_string(chan->context, args.context, sizeof(chan->context));
09823       chan->priority = 0;
09824       res = 0;
09825    }
09826 done:
09827    pbx_builtin_setvar_helper(chan, "BACKGROUNDSTATUS", mres ? "FAILED" : "SUCCESS");
09828    return res;
09829 }
09830 
09831 /*! Goto
09832  * \ingroup applications
09833  */
09834 static int pbx_builtin_goto(struct ast_channel *chan, const char *data)
09835 {
09836    int res = ast_parseable_goto(chan, data);
09837    if (!res)
09838       ast_verb(3, "Goto (%s,%s,%d)\n", chan->context, chan->exten, chan->priority + 1);
09839    return res;
09840 }
09841 
09842 
09843 int pbx_builtin_serialize_variables(struct ast_channel *chan, struct ast_str **buf)
09844 {
09845    struct ast_var_t *variables;
09846    const char *var, *val;
09847    int total = 0;
09848 
09849    if (!chan)
09850       return 0;
09851 
09852    ast_str_reset(*buf);
09853 
09854    ast_channel_lock(chan);
09855 
09856    AST_LIST_TRAVERSE(&chan->varshead, variables, entries) {
09857       if ((var = ast_var_name(variables)) && (val = ast_var_value(variables))
09858          /* && !ast_strlen_zero(var) && !ast_strlen_zero(val) */
09859          ) {
09860          if (ast_str_append(buf, 0, "%s=%s\n", var, val) < 0) {
09861             ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n");
09862             break;
09863          } else
09864             total++;
09865       } else
09866          break;
09867    }
09868 
09869    ast_channel_unlock(chan);
09870 
09871    return total;
09872 }
09873 
09874 const char *pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
09875 {
09876    struct ast_var_t *variables;
09877    const char *ret = NULL;
09878    int i;
09879    struct varshead *places[2] = { NULL, &globals };
09880 
09881    if (!name)
09882       return NULL;
09883 
09884    if (chan) {
09885       ast_channel_lock(chan);
09886       places[0] = &chan->varshead;
09887    }
09888 
09889    for (i = 0; i < 2; i++) {
09890       if (!places[i])
09891          continue;
09892       if (places[i] == &globals)
09893          ast_rwlock_rdlock(&globalslock);
09894       AST_LIST_TRAVERSE(places[i], variables, entries) {
09895          if (!strcmp(name, ast_var_name(variables))) {
09896             ret = ast_var_value(variables);
09897             break;
09898          }
09899       }
09900       if (places[i] == &globals)
09901          ast_rwlock_unlock(&globalslock);
09902       if (ret)
09903          break;
09904    }
09905 
09906    if (chan)
09907       ast_channel_unlock(chan);
09908 
09909    return ret;
09910 }
09911 
09912 void pbx_builtin_pushvar_helper(struct ast_channel *chan, const char *name, const char *value)
09913 {
09914    struct ast_var_t *newvariable;
09915    struct varshead *headp;
09916 
09917    if (name[strlen(name)-1] == ')') {
09918       char *function = ast_strdupa(name);
09919 
09920       ast_log(LOG_WARNING, "Cannot push a value onto a function\n");
09921       ast_func_write(chan, function, value);
09922       return;
09923    }
09924 
09925    if (chan) {
09926       ast_channel_lock(chan);
09927       headp = &chan->varshead;
09928    } else {
09929       ast_rwlock_wrlock(&globalslock);
09930       headp = &globals;
09931    }
09932 
09933    if (value) {
09934       if (headp == &globals)
09935          ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value);
09936       newvariable = ast_var_assign(name, value);
09937       AST_LIST_INSERT_HEAD(headp, newvariable, entries);
09938    }
09939 
09940    if (chan)
09941       ast_channel_unlock(chan);
09942    else
09943       ast_rwlock_unlock(&globalslock);
09944 }
09945 
09946 int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
09947 {
09948    struct ast_var_t *newvariable;
09949    struct varshead *headp;
09950    const char *nametail = name;
09951 
09952    if (name[strlen(name) - 1] == ')') {
09953       char *function = ast_strdupa(name);
09954 
09955       return ast_func_write(chan, function, value);
09956    }
09957 
09958    if (chan) {
09959       ast_channel_lock(chan);
09960       headp = &chan->varshead;
09961    } else {
09962       ast_rwlock_wrlock(&globalslock);
09963       headp = &globals;
09964    }
09965 
09966    /* For comparison purposes, we have to strip leading underscores */
09967    if (*nametail == '_') {
09968       nametail++;
09969       if (*nametail == '_')
09970          nametail++;
09971    }
09972 
09973    AST_LIST_TRAVERSE_SAFE_BEGIN(headp, newvariable, entries) {
09974       if (strcmp(ast_var_name(newvariable), nametail) == 0) {
09975          /* there is already such a variable, delete it */
09976          AST_LIST_REMOVE_CURRENT(entries);
09977          ast_var_delete(newvariable);
09978          break;
09979       }
09980    }
09981    AST_LIST_TRAVERSE_SAFE_END;
09982 
09983    if (value) {
09984       if (headp == &globals)
09985          ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value);
09986       newvariable = ast_var_assign(name, value);
09987       AST_LIST_INSERT_HEAD(headp, newvariable, entries);
09988       manager_event(EVENT_FLAG_DIALPLAN, "VarSet",
09989          "Channel: %s\r\n"
09990          "Variable: %s\r\n"
09991          "Value: %s\r\n"
09992          "Uniqueid: %s\r\n",
09993          chan ? chan->name : "none", name, value,
09994          chan ? chan->uniqueid : "none");
09995    }
09996 
09997    if (chan)
09998       ast_channel_unlock(chan);
09999    else
10000       ast_rwlock_unlock(&globalslock);
10001    return 0;
10002 }
10003 
10004 int pbx_builtin_setvar(struct ast_channel *chan, const char *data)
10005 {
10006    char *name, *value, *mydata;
10007 
10008    if (ast_compat_app_set) {
10009       return pbx_builtin_setvar_multiple(chan, data);
10010    }
10011 
10012    if (ast_strlen_zero(data)) {
10013       ast_log(LOG_WARNING, "Set requires one variable name/value pair.\n");
10014       return 0;
10015    }
10016 
10017    mydata = ast_strdupa(data);
10018    name = strsep(&mydata, "=");
10019    value = mydata;
10020    if (!value) {
10021       ast_log(LOG_WARNING, "Set requires an '=' to be a valid assignment.\n");
10022       return 0;
10023    }
10024 
10025    if (strchr(name, ' ')) {
10026       ast_log(LOG_WARNING, "Please avoid unnecessary spaces on variables as it may lead to unexpected results ('%s' set to '%s').\n", name, mydata);
10027    }
10028 
10029    pbx_builtin_setvar_helper(chan, name, value);
10030 
10031    return 0;
10032 }
10033 
10034 int pbx_builtin_setvar_multiple(struct ast_channel *chan, const char *vdata)
10035 {
10036    char *data;
10037    int x;
10038    AST_DECLARE_APP_ARGS(args,
10039       AST_APP_ARG(pair)[24];
10040    );
10041    AST_DECLARE_APP_ARGS(pair,
10042       AST_APP_ARG(name);
10043       AST_APP_ARG(value);
10044    );
10045 
10046    if (ast_strlen_zero(vdata)) {
10047       ast_log(LOG_WARNING, "MSet requires at least one variable name/value pair.\n");
10048       return 0;
10049    }
10050 
10051    data = ast_strdupa(vdata);
10052    AST_STANDARD_APP_ARGS(args, data);
10053 
10054    for (x = 0; x < args.argc; x++) {
10055       AST_NONSTANDARD_APP_ARGS(pair, args.pair[x], '=');
10056       if (pair.argc == 2) {
10057          pbx_builtin_setvar_helper(chan, pair.name, pair.value);
10058          if (strchr(pair.name, ' '))
10059             ast_log(LOG_WARNING, "Please avoid unnecessary spaces on variables as it may lead to unexpected results ('%s' set to '%s').\n", pair.name, pair.value);
10060       } else if (!chan) {
10061          ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '='\n", pair.name);
10062       } else {
10063          ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '=' (in %s@%s:%d\n", pair.name, chan->exten, chan->context, chan->priority);
10064       }
10065    }
10066 
10067    return 0;
10068 }
10069 
10070 int pbx_builtin_importvar(struct ast_channel *chan, const char *data)
10071 {
10072    char *name;
10073    char *value;
10074    char *channel;
10075    char tmp[VAR_BUF_SIZE];
10076    static int deprecation_warning = 0;
10077 
10078    if (ast_strlen_zero(data)) {
10079       ast_log(LOG_WARNING, "Ignoring, since there is no variable to set\n");
10080       return 0;
10081    }
10082    tmp[0] = 0;
10083    if (!deprecation_warning) {
10084       ast_log(LOG_WARNING, "ImportVar is deprecated.  Please use Set(varname=${IMPORT(channel,variable)}) instead.\n");
10085       deprecation_warning = 1;
10086    }
10087 
10088    value = ast_strdupa(data);
10089    name = strsep(&value,"=");
10090    channel = strsep(&value,",");
10091    if (channel && value && name) { /*! \todo XXX should do !ast_strlen_zero(..) of the args ? */
10092       struct ast_channel *chan2 = ast_channel_get_by_name(channel);
10093       if (chan2) {
10094          char *s = alloca(strlen(value) + 4);
10095          if (s) {
10096             sprintf(s, "${%s}", value);
10097             pbx_substitute_variables_helper(chan2, s, tmp, sizeof(tmp) - 1);
10098          }
10099          chan2 = ast_channel_unref(chan2);
10100       }
10101       pbx_builtin_setvar_helper(chan, name, tmp);
10102    }
10103 
10104    return(0);
10105 }
10106 
10107 static int pbx_builtin_noop(struct ast_channel *chan, const char *data)
10108 {
10109    return 0;
10110 }
10111 
10112 void pbx_builtin_clear_globals(void)
10113 {
10114    struct ast_var_t *vardata;
10115 
10116    ast_rwlock_wrlock(&globalslock);
10117    while ((vardata = AST_LIST_REMOVE_HEAD(&globals, entries)))
10118       ast_var_delete(vardata);
10119    ast_rwlock_unlock(&globalslock);
10120 }
10121 
10122 int pbx_checkcondition(const char *condition)
10123 {
10124    int res;
10125    if (ast_strlen_zero(condition)) {                /* NULL or empty strings are false */
10126       return 0;
10127    } else if (sscanf(condition, "%30d", &res) == 1) { /* Numbers are evaluated for truth */
10128       return res;
10129    } else {                                         /* Strings are true */
10130       return 1;
10131    }
10132 }
10133 
10134 static int pbx_builtin_gotoif(struct ast_channel *chan, const char *data)
10135 {
10136    char *condition, *branch1, *branch2, *branch;
10137    char *stringp;
10138 
10139    if (ast_strlen_zero(data)) {
10140       ast_log(LOG_WARNING, "Ignoring, since there is no variable to check\n");
10141       return 0;
10142    }
10143 
10144    stringp = ast_strdupa(data);
10145    condition = strsep(&stringp,"?");
10146    branch1 = strsep(&stringp,":");
10147    branch2 = strsep(&stringp,"");
10148    branch = pbx_checkcondition(condition) ? branch1 : branch2;
10149 
10150    if (ast_strlen_zero(branch)) {
10151       ast_debug(1, "Not taking any branch\n");
10152       return 0;
10153    }
10154 
10155    return pbx_builtin_goto(chan, branch);
10156 }
10157 
10158 static int pbx_builtin_saynumber(struct ast_channel *chan, const char *data)
10159 {
10160    char tmp[256];
10161    char *number = tmp;
10162    char *options;
10163 
10164    if (ast_strlen_zero(data)) {
10165       ast_log(LOG_WARNING, "SayNumber requires an argument (number)\n");
10166       return -1;
10167    }
10168    ast_copy_string(tmp, data, sizeof(tmp));
10169    strsep(&number, ",");
10170    options = strsep(&number, ",");
10171    if (options) {
10172       if ( strcasecmp(options, "f") && strcasecmp(options, "m") &&
10173          strcasecmp(options, "c") && strcasecmp(options, "n") ) {
10174          ast_log(LOG_WARNING, "SayNumber gender option is either 'f', 'm', 'c' or 'n'\n");
10175          return -1;
10176       }
10177    }
10178 
10179    if (ast_say_number(chan, atoi(tmp), "", chan->language, options)) {
10180       ast_log(LOG_WARNING, "We were unable to say the number %s, is it too large?\n", tmp);
10181    }
10182 
10183    return 0;
10184 }
10185 
10186 static int pbx_builtin_saydigits(struct ast_channel *chan, const char *data)
10187 {
10188    int res = 0;
10189 
10190    if (data)
10191       res = ast_say_digit_str(chan, data, "", chan->language);
10192    return res;
10193 }
10194 
10195 static int pbx_builtin_saycharacters(struct ast_channel *chan, const char *data)
10196 {
10197    int res = 0;
10198 
10199    if (data)
10200       res = ast_say_character_str(chan, data, "", chan->language);
10201    return res;
10202 }
10203 
10204 static int pbx_builtin_sayphonetic(struct ast_channel *chan, const char *data)
10205 {
10206    int res = 0;
10207 
10208    if (data)
10209       res = ast_say_phonetic_str(chan, data, "", chan->language);
10210    return res;
10211 }
10212 
10213 static void device_state_cb(const struct ast_event *event, void *unused)
10214 {
10215    const char *device;
10216    struct statechange *sc;
10217 
10218    device = ast_event_get_ie_str(event, AST_EVENT_IE_DEVICE);
10219    if (ast_strlen_zero(device)) {
10220       ast_log(LOG_ERROR, "Received invalid event that had no device IE\n");
10221       return;
10222    }
10223 
10224    if (!(sc = ast_calloc(1, sizeof(*sc) + strlen(device) + 1)))
10225       return;
10226    strcpy(sc->dev, device);
10227    if (ast_taskprocessor_push(device_state_tps, handle_statechange, sc) < 0) {
10228       ast_free(sc);
10229    }
10230 }
10231 
10232 /*!
10233  * \internal
10234  * \brief Implements the hints data provider.
10235  */
10236 static int hints_data_provider_get(const struct ast_data_search *search,
10237    struct ast_data *data_root)
10238 {
10239    struct ast_data *data_hint;
10240    struct ast_hint *hint;
10241    int watchers;
10242    struct ao2_iterator i;
10243 
10244    if (ao2_container_count(hints) == 0) {
10245       return 0;
10246    }
10247 
10248    i = ao2_iterator_init(hints, 0);
10249    for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) {
10250       watchers = ao2_container_count(hint->callbacks);
10251       data_hint = ast_data_add_node(data_root, "hint");
10252       if (!data_hint) {
10253          continue;
10254       }
10255       ast_data_add_str(data_hint, "extension", ast_get_extension_name(hint->exten));
10256       ast_data_add_str(data_hint, "context", ast_get_context_name(ast_get_extension_context(hint->exten)));
10257       ast_data_add_str(data_hint, "application", ast_get_extension_app(hint->exten));
10258       ast_data_add_str(data_hint, "state", ast_extension_state2str(hint->laststate));
10259       ast_data_add_int(data_hint, "watchers", watchers);
10260 
10261       if (!ast_data_search_match(search, data_hint)) {
10262          ast_data_remove_node(data_root, data_hint);
10263       }
10264    }
10265    ao2_iterator_destroy(&i);
10266 
10267    return 0;
10268 }
10269 
10270 static const struct ast_data_handler hints_data_provider = {
10271    .version = AST_DATA_HANDLER_VERSION,
10272    .get = hints_data_provider_get
10273 };
10274 
10275 static const struct ast_data_entry pbx_data_providers[] = {
10276    AST_DATA_ENTRY("asterisk/core/hints", &hints_data_provider),
10277 };
10278 
10279 int load_pbx(void)
10280 {
10281    int x;
10282 
10283    /* Initialize the PBX */
10284    ast_verb(1, "Asterisk PBX Core Initializing\n");
10285    if (!(device_state_tps = ast_taskprocessor_get("pbx-core", 0))) {
10286       ast_log(LOG_WARNING, "failed to create pbx-core taskprocessor\n");
10287    }
10288 
10289    ast_verb(1, "Registering builtin applications:\n");
10290    ast_cli_register_multiple(pbx_cli, ARRAY_LEN(pbx_cli));
10291    ast_data_register_multiple_core(pbx_data_providers, ARRAY_LEN(pbx_data_providers));
10292    __ast_custom_function_register(&exception_function, NULL);
10293    __ast_custom_function_register(&testtime_function, NULL);
10294 
10295    /* Register builtin applications */
10296    for (x = 0; x < ARRAY_LEN(builtins); x++) {
10297       ast_verb(1, "[%s]\n", builtins[x].name);
10298       if (ast_register_application2(builtins[x].name, builtins[x].execute, NULL, NULL, NULL)) {
10299          ast_log(LOG_ERROR, "Unable to register builtin application '%s'\n", builtins[x].name);
10300          return -1;
10301       }
10302    }
10303 
10304    /* Register manager application */
10305    ast_manager_register_xml("ShowDialPlan", EVENT_FLAG_CONFIG | EVENT_FLAG_REPORTING, manager_show_dialplan);
10306 
10307    if (!(device_state_sub = ast_event_subscribe(AST_EVENT_DEVICE_STATE, device_state_cb, "pbx Device State Change", NULL,
10308          AST_EVENT_IE_END))) {
10309       return -1;
10310    }
10311 
10312    return 0;
10313 }
10314 
10315 /*
10316  * Lock context list functions ...
10317  */
10318 int ast_wrlock_contexts(void)
10319 {
10320    return ast_mutex_lock(&conlock);
10321 }
10322 
10323 int ast_rdlock_contexts(void)
10324 {
10325    return ast_mutex_lock(&conlock);
10326 }
10327 
10328 int ast_unlock_contexts(void)
10329 {
10330    return ast_mutex_unlock(&conlock);
10331 }
10332 
10333 /*
10334  * Lock context ...
10335  */
10336 int ast_wrlock_context(struct ast_context *con)
10337 {
10338    return ast_rwlock_wrlock(&con->lock);
10339 }
10340 
10341 int ast_rdlock_context(struct ast_context *con)
10342 {
10343    return ast_rwlock_rdlock(&con->lock);
10344 }
10345 
10346 int ast_unlock_context(struct ast_context *con)
10347 {
10348    return ast_rwlock_unlock(&con->lock);
10349 }
10350 
10351 /*
10352  * Name functions ...
10353  */
10354 const char *ast_get_context_name(struct ast_context *con)
10355 {
10356    return con ? con->name : NULL;
10357 }
10358 
10359 struct ast_context *ast_get_extension_context(struct ast_exten *exten)
10360 {
10361    return exten ? exten->parent : NULL;
10362 }
10363 
10364 const char *ast_get_extension_name(struct ast_exten *exten)
10365 {
10366    return exten ? exten->exten : NULL;
10367 }
10368 
10369 const char *ast_get_extension_label(struct ast_exten *exten)
10370 {
10371    return exten ? exten->label : NULL;
10372 }
10373 
10374 const char *ast_get_include_name(struct ast_include *inc)
10375 {
10376    return inc ? inc->name : NULL;
10377 }
10378 
10379 const char *ast_get_ignorepat_name(struct ast_ignorepat *ip)
10380 {
10381    return ip ? ip->pattern : NULL;
10382 }
10383 
10384 int ast_get_extension_priority(struct ast_exten *exten)
10385 {
10386    return exten ? exten->priority : -1;
10387 }
10388 
10389 /*
10390  * Registrar info functions ...
10391  */
10392 const char *ast_get_context_registrar(struct ast_context *c)
10393 {
10394    return c ? c->registrar : NULL;
10395 }
10396 
10397 const char *ast_get_extension_registrar(struct ast_exten *e)
10398 {
10399    return e ? e->registrar : NULL;
10400 }
10401 
10402 const char *ast_get_include_registrar(struct ast_include *i)
10403 {
10404    return i ? i->registrar : NULL;
10405 }
10406 
10407 const char *ast_get_ignorepat_registrar(struct ast_ignorepat *ip)
10408 {
10409    return ip ? ip->registrar : NULL;
10410 }
10411 
10412 int ast_get_extension_matchcid(struct ast_exten *e)
10413 {
10414    return e ? e->matchcid : 0;
10415 }
10416 
10417 const char *ast_get_extension_cidmatch(struct ast_exten *e)
10418 {
10419    return e ? e->cidmatch : NULL;
10420 }
10421 
10422 const char *ast_get_extension_app(struct ast_exten *e)
10423 {
10424    return e ? e->app : NULL;
10425 }
10426 
10427 void *ast_get_extension_app_data(struct ast_exten *e)
10428 {
10429    return e ? e->data : NULL;
10430 }
10431 
10432 const char *ast_get_switch_name(struct ast_sw *sw)
10433 {
10434    return sw ? sw->name : NULL;
10435 }
10436 
10437 const char *ast_get_switch_data(struct ast_sw *sw)
10438 {
10439    return sw ? sw->data : NULL;
10440 }
10441 
10442 int ast_get_switch_eval(struct ast_sw *sw)
10443 {
10444    return sw->eval;
10445 }
10446 
10447 const char *ast_get_switch_registrar(struct ast_sw *sw)
10448 {
10449    return sw ? sw->registrar : NULL;
10450 }
10451 
10452 /*
10453  * Walking functions ...
10454  */
10455 struct ast_context *ast_walk_contexts(struct ast_context *con)
10456 {
10457    return con ? con->next : contexts;
10458 }
10459 
10460 struct ast_exten *ast_walk_context_extensions(struct ast_context *con,
10461    struct ast_exten *exten)
10462 {
10463    if (!exten)
10464       return con ? con->root : NULL;
10465    else
10466       return exten->next;
10467 }
10468 
10469 struct ast_sw *ast_walk_context_switches(struct ast_context *con,
10470    struct ast_sw *sw)
10471 {
10472    if (!sw)
10473       return con ? AST_LIST_FIRST(&con->alts) : NULL;
10474    else
10475       return AST_LIST_NEXT(sw, list);
10476 }
10477 
10478 struct ast_exten *ast_walk_extension_priorities(struct ast_exten *exten,
10479    struct ast_exten *priority)
10480 {
10481    return priority ? priority->peer : exten;
10482 }
10483 
10484 struct ast_include *ast_walk_context_includes(struct ast_context *con,
10485    struct ast_include *inc)
10486 {
10487    if (!inc)
10488       return con ? con->includes : NULL;
10489    else
10490       return inc->next;
10491 }
10492 
10493 struct ast_ignorepat *ast_walk_context_ignorepats(struct ast_context *con,
10494    struct ast_ignorepat *ip)
10495 {
10496    if (!ip)
10497       return con ? con->ignorepats : NULL;
10498    else
10499       return ip->next;
10500 }
10501 
10502 int ast_context_verify_includes(struct ast_context *con)
10503 {
10504    struct ast_include *inc = NULL;
10505    int res = 0;
10506 
10507    while ( (inc = ast_walk_context_includes(con, inc)) ) {
10508       if (ast_context_find(inc->rname))
10509          continue;
10510 
10511       res = -1;
10512       ast_log(LOG_WARNING, "Context '%s' tries to include nonexistent context '%s'\n",
10513          ast_get_context_name(con), inc->rname);
10514       break;
10515    }
10516 
10517    return res;
10518 }
10519 
10520 
10521 static int __ast_goto_if_exists(struct ast_channel *chan, const char *context, const char *exten, int priority, int async)
10522 {
10523    int (*goto_func)(struct ast_channel *chan, const char *context, const char *exten, int priority);
10524 
10525    if (!chan)
10526       return -2;
10527 
10528    if (context == NULL)
10529       context = chan->context;
10530    if (exten == NULL)
10531       exten = chan->exten;
10532 
10533    goto_func = (async) ? ast_async_goto : ast_explicit_goto;
10534    if (ast_exists_extension(chan, context, exten, priority,
10535       S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL)))
10536       return goto_func(chan, context, exten, priority);
10537    else {
10538       return AST_PBX_GOTO_FAILED;
10539    }
10540 }
10541 
10542 int ast_goto_if_exists(struct ast_channel *chan, const char* context, const char *exten, int priority)
10543 {
10544    return __ast_goto_if_exists(chan, context, exten, priority, 0);
10545 }
10546 
10547 int ast_async_goto_if_exists(struct ast_channel *chan, const char * context, const char *exten, int priority)
10548 {
10549    return __ast_goto_if_exists(chan, context, exten, priority, 1);
10550 }
10551 
10552 static int pbx_parseable_goto(struct ast_channel *chan, const char *goto_string, int async)
10553 {
10554    char *exten, *pri, *context;
10555    char *stringp;
10556    int ipri;
10557    int mode = 0;
10558 
10559    if (ast_strlen_zero(goto_string)) {
10560       ast_log(LOG_WARNING, "Goto requires an argument ([[context,]extension,]priority)\n");
10561       return -1;
10562    }
10563    stringp = ast_strdupa(goto_string);
10564    context = strsep(&stringp, ","); /* guaranteed non-null */
10565    exten = strsep(&stringp, ",");
10566    pri = strsep(&stringp, ",");
10567    if (!exten) {  /* Only a priority in this one */
10568       pri = context;
10569       exten = NULL;
10570       context = NULL;
10571    } else if (!pri) {   /* Only an extension and priority in this one */
10572       pri = exten;
10573       exten = context;
10574       context = NULL;
10575    }
10576    if (*pri == '+') {
10577       mode = 1;
10578       pri++;
10579    } else if (*pri == '-') {
10580       mode = -1;
10581       pri++;
10582    }
10583    if (sscanf(pri, "%30d", &ipri) != 1) {
10584       ipri = ast_findlabel_extension(chan, context ? context : chan->context,
10585          exten ? exten : chan->exten, pri,
10586          S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL));
10587       if (ipri < 1) {
10588          ast_log(LOG_WARNING, "Priority '%s' must be a number > 0, or valid label\n", pri);
10589          return -1;
10590       } else
10591          mode = 0;
10592    }
10593    /* At this point we have a priority and maybe an extension and a context */
10594 
10595    if (mode)
10596       ipri = chan->priority + (ipri * mode);
10597 
10598    if (async)
10599       ast_async_goto(chan, context, exten, ipri);
10600    else
10601       ast_explicit_goto(chan, context, exten, ipri);
10602 
10603    return 0;
10604 
10605 }
10606 
10607 int ast_parseable_goto(struct ast_channel *chan, const char *goto_string)
10608 {
10609    return pbx_parseable_goto(chan, goto_string, 0);
10610 }
10611 
10612 int ast_async_parseable_goto(struct ast_channel *chan, const char *goto_string)
10613 {
10614    return pbx_parseable_goto(chan, goto_string, 1);
10615 }
10616 
10617 char *ast_complete_applications(const char *line, const char *word, int state)
10618 {
10619    struct ast_app *app = NULL;
10620    int which = 0;
10621    char *ret = NULL;
10622    size_t wordlen = strlen(word);
10623 
10624    AST_RWLIST_RDLOCK(&apps);
10625    AST_RWLIST_TRAVERSE(&apps, app, list) {
10626       if (!strncasecmp(word, app->name, wordlen) && ++which > state) {
10627          ret = ast_strdup(app->name);
10628          break;
10629       }
10630    }
10631    AST_RWLIST_UNLOCK(&apps);
10632 
10633    return ret;
10634 }
10635 
10636 static int hint_hash(const void *obj, const int flags)
10637 {
10638    const struct ast_hint *hint = obj;
10639    const char *exten_name;
10640    int res;
10641 
10642    exten_name = ast_get_extension_name(hint->exten);
10643    if (ast_strlen_zero(exten_name)) {
10644       /*
10645        * If the exten or extension name isn't set, return 0 so that
10646        * the ao2_find() search will start in the first bucket.
10647        */
10648       res = 0;
10649    } else {
10650       res = ast_str_case_hash(exten_name);
10651    }
10652 
10653    return res;
10654 }
10655 
10656 static int hint_cmp(void *obj, void *arg, int flags)
10657 {
10658    const struct ast_hint *hint = obj;
10659    const struct ast_exten *exten = arg;
10660 
10661    return (hint->exten == exten) ? CMP_MATCH | CMP_STOP : 0;
10662 }
10663 
10664 static int statecbs_cmp(void *obj, void *arg, int flags)
10665 {
10666    const struct ast_state_cb *state_cb = obj;
10667    ast_state_cb_type change_cb = arg;
10668 
10669    return (state_cb->change_cb == change_cb) ? CMP_MATCH | CMP_STOP : 0;
10670 }
10671 
10672 int ast_pbx_init(void)
10673 {
10674    hints = ao2_container_alloc(HASH_EXTENHINT_SIZE, hint_hash, hint_cmp);
10675    statecbs = ao2_container_alloc(1, NULL, statecbs_cmp);
10676 
10677    return (hints && statecbs) ? 0 : -1;
10678 }

Generated on Mon Mar 19 11:30:28 2012 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7