Mon Jun 27 16:50:54 2011

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

Generated on Mon Jun 27 16:50:55 2011 for Asterisk - The Open Source Telephony Project by  doxygen 1.4.7