Sat Apr 26 2014 22:01:39

Asterisk developer's documentation


res_agi.c
Go to the documentation of this file.
00001 /*
00002  * Asterisk -- An open source telephony toolkit.
00003  *
00004  * Copyright (C) 1999 - 2006, 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 AGI - the Asterisk Gateway Interface
00022  *
00023  * \author Mark Spencer <markster@digium.com>
00024  *
00025  * \todo Convert the rest of the AGI commands over to XML documentation
00026  */
00027 
00028 /*** MODULEINFO
00029    <support_level>core</support_level>
00030  ***/
00031 
00032 #include "asterisk.h"
00033 
00034 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 398061 $")
00035 
00036 #include <math.h>
00037 #include <signal.h>
00038 #include <sys/time.h>
00039 #include <sys/wait.h>
00040 #include <sys/stat.h>
00041 #include <pthread.h>
00042 
00043 #include "asterisk/paths.h"   /* use many ast_config_AST_*_DIR */
00044 #include "asterisk/network.h"
00045 #include "asterisk/file.h"
00046 #include "asterisk/channel.h"
00047 #include "asterisk/pbx.h"
00048 #include "asterisk/module.h"
00049 #include "asterisk/astdb.h"
00050 #include "asterisk/callerid.h"
00051 #include "asterisk/cli.h"
00052 #include "asterisk/image.h"
00053 #include "asterisk/say.h"
00054 #include "asterisk/app.h"
00055 #include "asterisk/dsp.h"
00056 #include "asterisk/musiconhold.h"
00057 #include "asterisk/utils.h"
00058 #include "asterisk/lock.h"
00059 #include "asterisk/strings.h"
00060 #include "asterisk/manager.h"
00061 #include "asterisk/ast_version.h"
00062 #include "asterisk/speech.h"
00063 #include "asterisk/manager.h"
00064 #include "asterisk/term.h"
00065 #include "asterisk/xmldoc.h"
00066 #include "asterisk/srv.h"
00067 #include "asterisk/test.h"
00068 #include "asterisk/netsock2.h"
00069 
00070 #define AST_API_MODULE
00071 #include "asterisk/agi.h"
00072 
00073 /*** DOCUMENTATION
00074    <agi name="answer" language="en_US">
00075       <synopsis>
00076          Answer channel
00077       </synopsis>
00078       <syntax />
00079       <description>
00080          <para>Answers channel if not already in answer state. Returns <literal>-1</literal> on
00081          channel failure, or <literal>0</literal> if successful.</para>
00082       </description>
00083       <see-also>
00084          <ref type="agi">hangup</ref>
00085       </see-also>
00086    </agi>
00087    <agi name="asyncagi break" language="en_US">
00088       <synopsis>
00089          Interrupts Async AGI
00090       </synopsis>
00091       <syntax />
00092       <description>
00093          <para>Interrupts expected flow of Async AGI commands and returns control to previous source
00094          (typically, the PBX dialplan).</para>
00095       </description>
00096       <see-also>
00097          <ref type="agi">hangup</ref>
00098       </see-also>
00099    </agi>
00100    <agi name="channel status" language="en_US">
00101       <synopsis>
00102          Returns status of the connected channel.
00103       </synopsis>
00104       <syntax>
00105          <parameter name="channelname" />
00106       </syntax>
00107       <description>
00108          <para>Returns the status of the specified <replaceable>channelname</replaceable>.
00109          If no channel name is given then returns the status of the current channel.</para>
00110          <para>Return values:</para>
00111          <enumlist>
00112             <enum name="0">
00113                <para>Channel is down and available.</para>
00114             </enum>
00115             <enum name="1">
00116                <para>Channel is down, but reserved.</para>
00117             </enum>
00118             <enum name="2">
00119                <para>Channel is off hook.</para>
00120             </enum>
00121             <enum name="3">
00122                <para>Digits (or equivalent) have been dialed.</para>
00123             </enum>
00124             <enum name="4">
00125                <para>Line is ringing.</para>
00126             </enum>
00127             <enum name="5">
00128                <para>Remote end is ringing.</para>
00129             </enum>
00130             <enum name="6">
00131                <para>Line is up.</para>
00132             </enum>
00133             <enum name="7">
00134                <para>Line is busy.</para>
00135             </enum>
00136          </enumlist>
00137       </description>
00138    </agi>
00139    <agi name="control stream file" language="en_US">
00140       <synopsis>
00141          Sends audio file on channel and allows the listener to control the stream.
00142       </synopsis>
00143       <syntax>
00144          <parameter name="filename" required="true">
00145             <para>The file extension must not be included in the filename.</para>
00146          </parameter>
00147          <parameter name="escape_digits" required="true" />
00148          <parameter name="skipms" />
00149          <parameter name="ffchar">
00150             <para>Defaults to <literal>*</literal></para>
00151          </parameter>
00152          <parameter name="rewchr">
00153             <para>Defaults to <literal>#</literal></para>
00154          </parameter>
00155          <parameter name="pausechr" />
00156       </syntax>
00157       <description>
00158          <para>Send the given file, allowing playback to be controlled by the given
00159          digits, if any. Use double quotes for the digits if you wish none to be
00160          permitted. Returns <literal>0</literal> if playback completes without a digit
00161          being pressed, or the ASCII numerical value of the digit if one was pressed,
00162          or <literal>-1</literal> on error or if the channel was disconnected.</para>
00163       </description>
00164    </agi>
00165    <agi name="database del" language="en_US">
00166       <synopsis>
00167          Removes database key/value
00168       </synopsis>
00169       <syntax>
00170          <parameter name="family" required="true" />
00171          <parameter name="key" required="true" />
00172       </syntax>
00173       <description>
00174          <para>Deletes an entry in the Asterisk database for a given
00175          <replaceable>family</replaceable> and <replaceable>key</replaceable>.</para>
00176          <para>Returns <literal>1</literal> if successful, <literal>0</literal>
00177          otherwise.</para>
00178       </description>
00179    </agi>
00180    <agi name="database deltree" language="en_US">
00181       <synopsis>
00182          Removes database keytree/value
00183       </synopsis>
00184       <syntax>
00185          <parameter name="family" required="true" />
00186          <parameter name="keytree" />
00187       </syntax>
00188       <description>
00189          <para>Deletes a <replaceable>family</replaceable> or specific <replaceable>keytree</replaceable>
00190          within a <replaceable>family</replaceable> in the Asterisk database.</para>
00191          <para>Returns <literal>1</literal> if successful, <literal>0</literal> otherwise.</para>
00192       </description>
00193    </agi>
00194    <agi name="database get" language="en_US">
00195       <synopsis>
00196          Gets database value
00197       </synopsis>
00198       <syntax>
00199          <parameter name="family" required="true" />
00200          <parameter name="key" required="true" />
00201       </syntax>
00202       <description>
00203          <para>Retrieves an entry in the Asterisk database for a given <replaceable>family</replaceable>
00204          and <replaceable>key</replaceable>.</para>
00205          <para>Returns <literal>0</literal> if <replaceable>key</replaceable> is not set.
00206          Returns <literal>1</literal> if <replaceable>key</replaceable> is set and returns the variable
00207          in parenthesis.</para>
00208          <para>Example return code: 200 result=1 (testvariable)</para>
00209       </description>
00210    </agi>
00211    <agi name="database put" language="en_US">
00212       <synopsis>
00213          Adds/updates database value
00214       </synopsis>
00215       <syntax>
00216          <parameter name="family" required="true" />
00217          <parameter name="key" required="true" />
00218          <parameter name="value" required="true" />
00219       </syntax>
00220       <description>
00221          <para>Adds or updates an entry in the Asterisk database for a given
00222          <replaceable>family</replaceable>, <replaceable>key</replaceable>, and
00223          <replaceable>value</replaceable>.</para>
00224          <para>Returns <literal>1</literal> if successful, <literal>0</literal> otherwise.</para>
00225       </description>
00226    </agi>
00227    <agi name="exec" language="en_US">
00228       <synopsis>
00229          Executes a given Application
00230       </synopsis>
00231       <syntax>
00232          <parameter name="application" required="true" />
00233          <parameter name="options" required="true" />
00234       </syntax>
00235       <description>
00236          <para>Executes <replaceable>application</replaceable> with given
00237          <replaceable>options</replaceable>.</para>
00238          <para>Returns whatever the <replaceable>application</replaceable> returns, or
00239          <literal>-2</literal> on failure to find <replaceable>application</replaceable>.</para>
00240       </description>
00241    </agi>
00242    <agi name="get data" language="en_US">
00243       <synopsis>
00244          Prompts for DTMF on a channel
00245       </synopsis>
00246       <syntax>
00247          <parameter name="file" required="true" />
00248          <parameter name="timeout" />
00249          <parameter name="maxdigits" />
00250       </syntax>
00251       <description>
00252          <para>Stream the given <replaceable>file</replaceable>, and receive DTMF data.</para>
00253          <para>Returns the digits received from the channel at the other end.</para>
00254       </description>
00255    </agi>
00256    <agi name="get full variable" language="en_US">
00257       <synopsis>
00258          Evaluates a channel expression
00259       </synopsis>
00260       <syntax>
00261          <parameter name="variablename" required="true" />
00262          <parameter name="channel name" />
00263       </syntax>
00264       <description>
00265          <para>Returns <literal>0</literal> if <replaceable>variablename</replaceable> is not set
00266          or channel does not exist. Returns <literal>1</literal> if <replaceable>variablename</replaceable>
00267          is set and returns the variable in parenthesis. Understands complex variable names and builtin
00268          variables, unlike GET VARIABLE.</para>
00269          <para>Example return code: 200 result=1 (testvariable)</para>
00270       </description>
00271    </agi>
00272    <agi name="get option" language="en_US">
00273       <synopsis>
00274          Stream file, prompt for DTMF, with timeout.
00275       </synopsis>
00276       <syntax>
00277          <parameter name="filename" required="true" />
00278          <parameter name="escape_digits" required="true" />
00279          <parameter name="timeout" />
00280       </syntax>
00281       <description>
00282          <para>Behaves similar to STREAM FILE but used with a timeout option.</para>
00283       </description>
00284       <see-also>
00285          <ref type="agi">stream file</ref>
00286       </see-also>
00287    </agi>
00288    <agi name="get variable" language="en_US">
00289       <synopsis>
00290          Gets a channel variable.
00291       </synopsis>
00292       <syntax>
00293          <parameter name="variablename" required="true" />
00294       </syntax>
00295       <description>
00296          <para>Returns <literal>0</literal> if <replaceable>variablename</replaceable> is not set.
00297          Returns <literal>1</literal> if <replaceable>variablename</replaceable> is set and returns
00298          the variable in parentheses.</para>
00299          <para>Example return code: 200 result=1 (testvariable)</para>
00300       </description>
00301    </agi>
00302    <agi name="hangup" language="en_US">
00303       <synopsis>
00304          Hangup a channel.
00305       </synopsis>
00306       <syntax>
00307          <parameter name="channelname" />
00308       </syntax>
00309       <description>
00310          <para>Hangs up the specified channel. If no channel name is given, hangs
00311          up the current channel</para>
00312       </description>
00313    </agi>
00314    <agi name="noop" language="en_US">
00315       <synopsis>
00316          Does nothing.
00317       </synopsis>
00318       <syntax />
00319       <description>
00320          <para>Does nothing.</para>
00321       </description>
00322    </agi>
00323    <agi name="receive char" language="en_US">
00324       <synopsis>
00325          Receives one character from channels supporting it.
00326       </synopsis>
00327       <syntax>
00328          <parameter name="timeout" required="true">
00329             <para>The maximum time to wait for input in milliseconds, or <literal>0</literal>
00330             for infinite. Most channels</para>
00331          </parameter>
00332       </syntax>
00333       <description>
00334          <para>Receives a character of text on a channel. Most channels do not support
00335          the reception of text. Returns the decimal value of the character
00336          if one is received, or <literal>0</literal> if the channel does not support
00337          text reception. Returns <literal>-1</literal> only on error/hangup.</para>
00338       </description>
00339    </agi>
00340    <agi name="receive text" language="en_US">
00341       <synopsis>
00342          Receives text from channels supporting it.
00343       </synopsis>
00344       <syntax>
00345          <parameter name="timeout" required="true">
00346             <para>The timeout to be the maximum time to wait for input in
00347             milliseconds, or <literal>0</literal> for infinite.</para>
00348          </parameter>
00349       </syntax>
00350       <description>
00351          <para>Receives a string of text on a channel. Most channels 
00352          do not support the reception of text. Returns <literal>-1</literal> for failure
00353          or <literal>1</literal> for success, and the string in parenthesis.</para> 
00354       </description>
00355    </agi>
00356    <agi name="record file" language="en_US">
00357       <synopsis>
00358          Records to a given file.
00359       </synopsis>
00360       <syntax>
00361          <parameter name="filename" required="true" />
00362          <parameter name="format" required="true" />
00363          <parameter name="escape_digits" required="true" />
00364          <parameter name="timeout" required="true" />
00365          <parameter name="offset samples" />
00366          <parameter name="BEEP" />
00367          <parameter name="s=silence" />
00368       </syntax>
00369       <description>
00370          <para>Record to a file until a given dtmf digit in the sequence is received.
00371          Returns <literal>-1</literal> on hangup or error.  The format will specify what kind of file
00372          will be recorded. The <replaceable>timeout</replaceable> is the maximum record time in
00373          milliseconds, or <literal>-1</literal> for no <replaceable>timeout</replaceable>.
00374          <replaceable>offset samples</replaceable> is optional, and, if provided, will seek
00375          to the offset without exceeding the end of the file. <replaceable>silence</replaceable> is
00376          the number of seconds of silence allowed before the function returns despite the
00377          lack of dtmf digits or reaching <replaceable>timeout</replaceable>. <replaceable>silence</replaceable>
00378          value must be preceded by <literal>s=</literal> and is also optional.</para>
00379       </description>
00380    </agi>
00381    <agi name="say alpha" language="en_US">
00382       <synopsis>
00383          Says a given character string.
00384       </synopsis>
00385       <syntax>
00386          <parameter name="number" required="true" />
00387          <parameter name="escape_digits" required="true" />
00388       </syntax>
00389       <description>
00390          <para>Say a given character string, returning early if any of the given DTMF digits
00391          are received on the channel. Returns <literal>0</literal> if playback completes
00392          without a digit being pressed, or the ASCII numerical value of the digit if one
00393          was pressed or <literal>-1</literal> on error/hangup.</para>
00394       </description>
00395    </agi>
00396    <agi name="say digits" language="en_US">
00397       <synopsis>
00398          Says a given digit string.
00399       </synopsis>
00400       <syntax>
00401          <parameter name="number" required="true" />
00402          <parameter name="escape_digits" required="true" />
00403       </syntax>
00404       <description>
00405          <para>Say a given digit string, returning early if any of the given DTMF digits
00406          are received on the channel. Returns <literal>0</literal> if playback completes
00407          without a digit being pressed, or the ASCII numerical value of the digit if one
00408          was pressed or <literal>-1</literal> on error/hangup.</para>
00409       </description>
00410    </agi>
00411    <agi name="say number" language="en_US">
00412       <synopsis>
00413          Says a given number.
00414       </synopsis>
00415       <syntax>
00416          <parameter name="number" required="true" />
00417          <parameter name="escape_digits" required="true" />
00418          <parameter name="gender" />
00419       </syntax>
00420       <description>
00421          <para>Say a given number, returning early if any of the given DTMF digits
00422          are received on the channel.  Returns <literal>0</literal> if playback
00423          completes without a digit being pressed, or the ASCII numerical value of
00424          the digit if one was pressed or <literal>-1</literal> on error/hangup.</para>
00425       </description>
00426    </agi>
00427    <agi name="say phonetic" language="en_US">
00428       <synopsis>
00429          Says a given character string with phonetics.
00430       </synopsis>
00431       <syntax>
00432          <parameter name="string" required="true" />
00433          <parameter name="escape_digits" required="true" />
00434       </syntax>
00435       <description>
00436          <para>Say a given character string with phonetics, returning early if any of the
00437          given DTMF digits are received on the channel. Returns <literal>0</literal> if
00438          playback completes without a digit pressed, the ASCII numerical value of the digit
00439          if one was pressed, or <literal>-1</literal> on error/hangup.</para>
00440       </description>
00441    </agi>
00442    <agi name="say date" language="en_US">
00443       <synopsis>
00444          Says a given date.
00445       </synopsis>
00446       <syntax>
00447          <parameter name="date" required="true">
00448             <para>Is number of seconds elapsed since 00:00:00 on January 1, 1970.
00449             Coordinated Universal Time (UTC).</para>
00450          </parameter>
00451          <parameter name="escape_digits" required="true" />
00452       </syntax>
00453       <description>
00454          <para>Say a given date, returning early if any of the given DTMF digits are
00455          received on the channel. Returns <literal>0</literal> if playback
00456          completes without a digit being pressed, or the ASCII numerical value of the
00457          digit if one was pressed or <literal>-1</literal> on error/hangup.</para>
00458       </description>
00459    </agi>
00460    <agi name="say time" language="en_US">
00461       <synopsis>
00462          Says a given time.
00463       </synopsis>
00464       <syntax>
00465          <parameter name="time" required="true">
00466             <para>Is number of seconds elapsed since 00:00:00 on January 1, 1970.
00467             Coordinated Universal Time (UTC).</para>
00468          </parameter>
00469          <parameter name="escape_digits" required="true" />
00470       </syntax>
00471       <description>
00472          <para>Say a given time, returning early if any of the given DTMF digits are
00473          received on the channel. Returns <literal>0</literal> if playback completes
00474          without a digit being pressed, or the ASCII numerical value of the digit if
00475          one was pressed or <literal>-1</literal> on error/hangup.</para>
00476       </description>
00477    </agi>
00478    <agi name="say datetime" language="en_US">
00479       <synopsis>
00480          Says a given time as specified by the format given.
00481       </synopsis>
00482       <syntax>
00483          <parameter name="time" required="true">
00484             <para>Is number of seconds elapsed since 00:00:00
00485             on January 1, 1970, Coordinated Universal Time (UTC)</para>
00486          </parameter>
00487          <parameter name="escape_digits" required="true" />
00488          <parameter name="format">
00489             <para>Is the format the time should be said in. See
00490             <filename>voicemail.conf</filename> (defaults to <literal>ABdY
00491             'digits/at' IMp</literal>).</para>
00492          </parameter>
00493          <parameter name="timezone">
00494             <para>Acceptable values can be found in <filename>/usr/share/zoneinfo</filename>
00495             Defaults to machine default.</para>
00496          </parameter>
00497       </syntax>
00498       <description>
00499          <para>Say a given time, returning early if any of the given DTMF digits are
00500          received on the channel. Returns <literal>0</literal> if playback
00501          completes without a digit being pressed, or the ASCII numerical value of the
00502          digit if one was pressed or <literal>-1</literal> on error/hangup.</para>
00503       </description>
00504    </agi>
00505    <agi name="send image" language="en_US">
00506       <synopsis>
00507          Sends images to channels supporting it.
00508       </synopsis>
00509       <syntax>
00510          <parameter name="image" required="true" />
00511       </syntax>
00512       <description>
00513          <para>Sends the given image on a channel. Most channels do not support the
00514          transmission of images. Returns <literal>0</literal> if image is sent, or if
00515          the channel does not support image transmission.  Returns <literal>-1</literal>
00516          only on error/hangup. Image names should not include extensions.</para>
00517       </description>
00518    </agi>
00519    <agi name="send text" language="en_US">
00520       <synopsis>
00521          Sends text to channels supporting it.
00522       </synopsis>
00523       <syntax>
00524          <parameter name="text to send" required="true">
00525             <para>Text consisting of greater than one word should be placed
00526             in quotes since the command only accepts a single argument.</para>
00527          </parameter>
00528       </syntax>
00529       <description>
00530          <para>Sends the given text on a channel. Most channels do not support the
00531          transmission of text. Returns <literal>0</literal> if text is sent, or if the
00532          channel does not support text transmission. Returns <literal>-1</literal> only
00533          on error/hangup.</para>
00534       </description>
00535    </agi>
00536    <agi name="set autohangup" language="en_US">
00537       <synopsis>
00538          Autohangup channel in some time.
00539       </synopsis>
00540       <syntax>
00541          <parameter name="time" required="true" />
00542       </syntax>
00543       <description>
00544          <para>Cause the channel to automatically hangup at <replaceable>time</replaceable>
00545          seconds in the future. Of course it can be hungup before then as well. Setting to
00546          <literal>0</literal> will cause the autohangup feature to be disabled on this channel.</para>
00547       </description>
00548    </agi>
00549    <agi name="set callerid" language="en_US">
00550       <synopsis>
00551          Sets callerid for the current channel.
00552       </synopsis>
00553       <syntax>
00554          <parameter name="number" required="true" />
00555       </syntax>
00556       <description>
00557          <para>Changes the callerid of the current channel.</para>
00558       </description>
00559    </agi>
00560    <agi name="set context" language="en_US">
00561       <synopsis>
00562          Sets channel context.
00563       </synopsis>
00564       <syntax>
00565          <parameter name="desired context" required="true" />
00566       </syntax>
00567       <description>
00568          <para>Sets the context for continuation upon exiting the application.</para>
00569       </description>
00570    </agi>
00571    <agi name="set extension" language="en_US">
00572       <synopsis>
00573          Changes channel extension.
00574       </synopsis>
00575       <syntax>
00576          <parameter name="new extension" required="true" />
00577       </syntax>
00578       <description>
00579          <para>Changes the extension for continuation upon exiting the application.</para>
00580       </description>
00581    </agi>
00582    <agi name="set music" language="en_US">
00583       <synopsis>
00584          Enable/Disable Music on hold generator
00585       </synopsis>
00586       <syntax>
00587          <parameter required="true">
00588             <enumlist>
00589                <enum>
00590                   <parameter name="on" literal="true" required="true" />
00591                </enum>
00592                <enum>
00593                   <parameter name="off" literal="true" required="true" />
00594                </enum>
00595             </enumlist>
00596          </parameter>
00597          <parameter name="class" required="true" />
00598       </syntax>
00599       <description>
00600          <para>Enables/Disables the music on hold generator. If <replaceable>class</replaceable>
00601          is not specified, then the <literal>default</literal> music on hold class will be
00602          used. This generator will be stopped automatically when playing a file.</para>
00603          <para>Always returns <literal>0</literal>.</para>
00604       </description>
00605    </agi>
00606    <agi name="set priority" language="en_US">
00607       <synopsis>
00608          Set channel dialplan priority.
00609       </synopsis>
00610       <syntax>
00611          <parameter name="priority" required="true" />
00612       </syntax>
00613       <description>
00614          <para>Changes the priority for continuation upon exiting the application.
00615          The priority must be a valid priority or label.</para>
00616       </description>
00617    </agi>
00618    <agi name="set variable" language="en_US">
00619       <synopsis>
00620          Sets a channel variable.
00621       </synopsis>
00622       <syntax>
00623          <parameter name="variablename" required="true" />
00624          <parameter name="value" required="true" />
00625       </syntax>
00626       <description>
00627          <para>Sets a variable to the current channel.</para>
00628       </description>
00629    </agi>
00630    <agi name="stream file" language="en_US">
00631       <synopsis>
00632          Sends audio file on channel.
00633       </synopsis>
00634       <syntax>
00635          <parameter name="filename" required="true">
00636             <para>File name to play. The file extension must not be
00637             included in the <replaceable>filename</replaceable>.</para>
00638          </parameter>
00639          <parameter name="escape_digits" required="true">
00640             <para>Use double quotes for the digits if you wish none to be
00641             permitted.</para>
00642          </parameter>
00643          <parameter name="sample offset">
00644             <para>If sample offset is provided then the audio will seek to sample
00645             offset before play starts.</para>
00646          </parameter>
00647       </syntax>
00648       <description>
00649          <para>Send the given file, allowing playback to be interrupted by the given
00650          digits, if any. Returns <literal>0</literal> if playback completes without a digit
00651          being pressed, or the ASCII numerical value of the digit if one was pressed,
00652          or <literal>-1</literal> on error or if the channel was disconnected. If
00653          musiconhold is playing before calling stream file it will be automatically
00654          stopped and will not be restarted after completion.</para>
00655       </description>
00656       <see-also>
00657          <ref type="agi">control stream file</ref>
00658       </see-also>
00659    </agi>
00660    <agi name="tdd mode" language="en_US">
00661       <synopsis>
00662          Toggles TDD mode (for the deaf).
00663       </synopsis>
00664       <syntax>
00665          <parameter name="boolean" required="true">
00666             <enumlist>
00667                <enum name="on" />
00668                <enum name="off" />
00669             </enumlist>
00670          </parameter>
00671       </syntax>
00672       <description>
00673          <para>Enable/Disable TDD transmission/reception on a channel. Returns <literal>1</literal> if
00674          successful, or <literal>0</literal> if channel is not TDD-capable.</para>
00675       </description>
00676    </agi>
00677    <agi name="verbose" language="en_US">
00678       <synopsis>
00679          Logs a message to the asterisk verbose log.
00680       </synopsis>
00681       <syntax>
00682          <parameter name="message" required="true" />
00683          <parameter name="level" required="true" />
00684       </syntax>
00685       <description>
00686          <para>Sends <replaceable>message</replaceable> to the console via verbose
00687          message system. <replaceable>level</replaceable> is the verbose level (1-4).
00688          Always returns <literal>1</literal></para>
00689       </description>
00690    </agi>
00691    <agi name="wait for digit" language="en_US">
00692       <synopsis>
00693          Waits for a digit to be pressed.
00694       </synopsis>
00695       <syntax>
00696          <parameter name="timeout" required="true" />
00697       </syntax>
00698       <description>
00699          <para>Waits up to <replaceable>timeout</replaceable> milliseconds for channel to
00700          receive a DTMF digit. Returns <literal>-1</literal> on channel failure, <literal>0</literal>
00701          if no digit is received in the timeout, or the numerical value of the ascii of the digit if
00702          one is received. Use <literal>-1</literal> for the <replaceable>timeout</replaceable> value if
00703          you desire the call to block indefinitely.</para>
00704       </description>
00705    </agi>
00706    <agi name="speech create" language="en_US">
00707       <synopsis>
00708          Creates a speech object.
00709       </synopsis>
00710       <syntax>
00711          <parameter name="engine" required="true" />
00712       </syntax>
00713       <description>
00714          <para>Create a speech object to be used by the other Speech AGI commands.</para>
00715       </description>
00716    </agi>
00717    <agi name="speech set" language="en_US">
00718       <synopsis>
00719          Sets a speech engine setting.
00720       </synopsis>
00721       <syntax>
00722          <parameter name="name" required="true" />
00723          <parameter name="value" required="true" />
00724       </syntax>
00725       <description>
00726          <para>Set an engine-specific setting.</para>
00727       </description>
00728    </agi>
00729    <agi name="speech destroy" language="en_US">
00730       <synopsis>
00731          Destroys a speech object.
00732       </synopsis>
00733       <syntax>
00734       </syntax>
00735       <description>
00736          <para>Destroy the speech object created by <literal>SPEECH CREATE</literal>.</para>
00737       </description>
00738       <see-also>
00739          <ref type="agi">speech create</ref>
00740       </see-also>
00741    </agi>
00742    <agi name="speech load grammar" language="en_US">
00743       <synopsis>
00744          Loads a grammar.
00745       </synopsis>
00746       <syntax>
00747          <parameter name="grammar name" required="true" />
00748          <parameter name="path to grammar" required="true" />
00749       </syntax>
00750       <description>
00751          <para>Loads the specified grammar as the specified name.</para>
00752       </description>
00753    </agi>
00754    <agi name="speech unload grammar" language="en_US">
00755       <synopsis>
00756          Unloads a grammar.
00757       </synopsis>
00758       <syntax>
00759          <parameter name="grammar name" required="true" />
00760       </syntax>
00761       <description>
00762          <para>Unloads the specified grammar.</para>
00763       </description>
00764    </agi>
00765    <agi name="speech activate grammar" language="en_US">
00766       <synopsis>
00767          Activates a grammar.
00768       </synopsis>
00769       <syntax>
00770          <parameter name="grammar name" required="true" />
00771       </syntax>
00772       <description>
00773          <para>Activates the specified grammar on the speech object.</para>
00774       </description>
00775    </agi>
00776    <agi name="speech deactivate grammar" language="en_US">
00777       <synopsis>
00778          Deactivates a grammar.
00779       </synopsis>
00780       <syntax>
00781          <parameter name="grammar name" required="true" />
00782       </syntax>
00783       <description>
00784          <para>Deactivates the specified grammar on the speech object.</para>
00785       </description>
00786    </agi>
00787    <agi name="speech recognize" language="en_US">
00788       <synopsis>
00789          Recognizes speech.
00790       </synopsis>
00791       <syntax>
00792          <parameter name="prompt" required="true" />
00793          <parameter name="timeout" required="true" />
00794          <parameter name="offset" />
00795       </syntax>
00796       <description>
00797          <para>Plays back given <replaceable>prompt</replaceable> while listening for
00798          speech and dtmf.</para>
00799       </description>
00800    </agi>
00801    <application name="AGI" language="en_US">
00802       <synopsis>
00803          Executes an AGI compliant application.
00804       </synopsis>
00805       <syntax>
00806          <parameter name="command" required="true" />
00807          <parameter name="args">
00808             <argument name="arg1" required="true" />
00809             <argument name="arg2" multiple="yes" />
00810          </parameter>
00811       </syntax>
00812       <description>
00813          <para>Executes an Asterisk Gateway Interface compliant
00814          program on a channel. AGI allows Asterisk to launch external programs written
00815          in any language to control a telephony channel, play audio, read DTMF digits,
00816          etc. by communicating with the AGI protocol on <emphasis>stdin</emphasis> and
00817          <emphasis>stdout</emphasis>. As of <literal>1.6.0</literal>, this channel will
00818          not stop dialplan execution on hangup inside of this application. Dialplan
00819          execution will continue normally, even upon hangup until the AGI application
00820          signals a desire to stop (either by exiting or, in the case of a net script, by
00821          closing the connection). A locally executed AGI script will receive SIGHUP on
00822          hangup from the channel except when using DeadAGI. A fast AGI server will
00823          correspondingly receive a HANGUP inline with the command dialog. Both of theses
00824          signals may be disabled by setting the <variable>AGISIGHUP</variable> channel
00825          variable to <literal>no</literal> before executing the AGI application.
00826          Alternatively, if you would like the AGI application to exit immediately
00827          after a channel hangup is detected, set the <variable>AGIEXITONHANGUP</variable>
00828          variable to <literal>yes</literal>.</para>
00829          <para>Use the CLI command <literal>agi show commands</literal> to list available agi
00830          commands.</para>
00831          <para>This application sets the following channel variable upon completion:</para>
00832          <variablelist>
00833             <variable name="AGISTATUS">
00834                <para>The status of the attempt to the run the AGI script
00835                text string, one of:</para>
00836                <value name="SUCCESS" />
00837                <value name="FAILURE" />
00838                <value name="NOTFOUND" />
00839                <value name="HANGUP" />
00840             </variable>
00841          </variablelist>
00842       </description>
00843       <see-also>
00844          <ref type="application">EAGI</ref>
00845          <ref type="application">DeadAGI</ref>
00846       </see-also>
00847    </application>
00848    <application name="EAGI" language="en_US">
00849       <synopsis>
00850          Executes an EAGI compliant application.
00851       </synopsis>
00852       <syntax>
00853          <xi:include xpointer="xpointer(/docs/application[@name='AGI']/syntax/parameter[@name='command'])" />
00854          <xi:include xpointer="xpointer(/docs/application[@name='AGI']/syntax/parameter[@name='args'])" />
00855       </syntax>
00856       <description>
00857          <para>Using 'EAGI' provides enhanced AGI, with incoming audio available out of band
00858          on file descriptor 3.</para>
00859          <xi:include xpointer="xpointer(/docs/application[@name='AGI']/description/para)" />
00860          <xi:include xpointer="xpointer(/docs/application[@name='AGI']/description/variablelist)" />
00861       </description>
00862       <see-also>
00863          <ref type="application">AGI</ref>
00864          <ref type="application">DeadAGI</ref>
00865       </see-also>
00866    </application>
00867    <application name="DeadAGI" language="en_US">
00868       <synopsis>
00869          Executes AGI on a hungup channel.
00870       </synopsis>
00871       <syntax>
00872          <xi:include xpointer="xpointer(/docs/application[@name='AGI']/syntax/parameter[@name='command'])" />
00873          <xi:include xpointer="xpointer(/docs/application[@name='AGI']/syntax/parameter[@name='args'])" />
00874       </syntax>
00875       <description>
00876          <xi:include xpointer="xpointer(/docs/application[@name='AGI']/description/para)" />
00877          <xi:include xpointer="xpointer(/docs/application[@name='AGI']/description/variablelist)" />
00878       </description>
00879       <see-also>
00880          <ref type="application">AGI</ref>
00881          <ref type="application">EAGI</ref>
00882       </see-also>
00883    </application>
00884    <manager name="AGI" language="en_US">
00885       <synopsis>
00886          Add an AGI command to execute by Async AGI.
00887       </synopsis>
00888       <syntax>
00889          <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
00890          <parameter name="Channel" required="true">
00891             <para>Channel that is currently in Async AGI.</para>
00892          </parameter>
00893          <parameter name="Command" required="true">
00894             <para>Application to execute.</para>
00895          </parameter>
00896          <parameter name="CommandID">
00897             <para>This will be sent back in CommandID header of AsyncAGI exec
00898             event notification.</para>
00899          </parameter>
00900       </syntax>
00901       <description>
00902          <para>Add an AGI command to the execute queue of the channel in Async AGI.</para>
00903       </description>
00904    </manager>
00905  ***/
00906 
00907 #define MAX_ARGS 128
00908 #define MAX_CMD_LEN 80
00909 #define AGI_NANDFS_RETRY 3
00910 #define AGI_BUF_LEN 2048
00911 #define SRV_PREFIX "_agi._tcp."
00912 
00913 static char *app = "AGI";
00914 
00915 static char *eapp = "EAGI";
00916 
00917 static char *deadapp = "DeadAGI";
00918 
00919 static int agidebug = 0;
00920 
00921 #define TONE_BLOCK_SIZE 200
00922 
00923 /* Max time to connect to an AGI remote host */
00924 #define MAX_AGI_CONNECT 2000
00925 
00926 #define AGI_PORT 4573
00927 
00928 /*! Special return code for "asyncagi break" command. */
00929 #define ASYNC_AGI_BREAK 3
00930 
00931 enum agi_result {
00932    AGI_RESULT_FAILURE = -1,
00933    AGI_RESULT_SUCCESS,
00934    AGI_RESULT_SUCCESS_FAST,
00935    AGI_RESULT_SUCCESS_ASYNC,
00936    AGI_RESULT_NOTFOUND,
00937    AGI_RESULT_HANGUP,
00938 };
00939 
00940 static agi_command *find_command(const char * const cmds[], int exact);
00941 
00942 AST_THREADSTORAGE(agi_buf);
00943 #define AGI_BUF_INITSIZE 256
00944 
00945 int AST_OPTIONAL_API_NAME(ast_agi_send)(int fd, struct ast_channel *chan, char *fmt, ...)
00946 {
00947    int res = 0;
00948    va_list ap;
00949    struct ast_str *buf;
00950 
00951    if (!(buf = ast_str_thread_get(&agi_buf, AGI_BUF_INITSIZE)))
00952       return -1;
00953 
00954    va_start(ap, fmt);
00955    res = ast_str_set_va(&buf, 0, fmt, ap);
00956    va_end(ap);
00957 
00958    if (res == -1) {
00959       ast_log(LOG_ERROR, "Out of memory\n");
00960       return -1;
00961    }
00962 
00963    if (agidebug) {
00964       if (chan) {
00965          ast_verbose("<%s>AGI Tx >> %s", ast_channel_name(chan), ast_str_buffer(buf));
00966       } else {
00967          ast_verbose("AGI Tx >> %s", ast_str_buffer(buf));
00968       }
00969    }
00970 
00971    return ast_carefulwrite(fd, ast_str_buffer(buf), ast_str_strlen(buf), 100);
00972 }
00973 
00974 /* linked list of AGI commands ready to be executed by Async AGI */
00975 struct agi_cmd {
00976    char *cmd_buffer;
00977    char *cmd_id;
00978    AST_LIST_ENTRY(agi_cmd) entry;
00979 };
00980 
00981 static void free_agi_cmd(struct agi_cmd *cmd)
00982 {
00983    ast_free(cmd->cmd_buffer);
00984    ast_free(cmd->cmd_id);
00985    ast_free(cmd);
00986 }
00987 
00988 /* AGI datastore destructor */
00989 static void agi_destroy_commands_cb(void *data)
00990 {
00991    struct agi_cmd *cmd;
00992    AST_LIST_HEAD(, agi_cmd) *chan_cmds = data;
00993    AST_LIST_LOCK(chan_cmds);
00994    while ( (cmd = AST_LIST_REMOVE_HEAD(chan_cmds, entry)) ) {
00995       free_agi_cmd(cmd);
00996    }
00997    AST_LIST_UNLOCK(chan_cmds);
00998    AST_LIST_HEAD_DESTROY(chan_cmds);
00999    ast_free(chan_cmds);
01000 }
01001 
01002 /* channel datastore to keep the queue of AGI commands in the channel */
01003 static const struct ast_datastore_info agi_commands_datastore_info = {
01004    .type = "AsyncAGI",
01005    .destroy = agi_destroy_commands_cb
01006 };
01007 
01008 static struct agi_cmd *get_agi_cmd(struct ast_channel *chan)
01009 {
01010    struct ast_datastore *store;
01011    struct agi_cmd *cmd;
01012    AST_LIST_HEAD(, agi_cmd) *agi_commands;
01013 
01014    ast_channel_lock(chan);
01015    store = ast_channel_datastore_find(chan, &agi_commands_datastore_info, NULL);
01016    ast_channel_unlock(chan);
01017    if (!store) {
01018       ast_log(LOG_ERROR, "Huh? Async AGI datastore disappeared on Channel %s!\n",
01019          ast_channel_name(chan));
01020       return NULL;
01021    }
01022    agi_commands = store->data;
01023    AST_LIST_LOCK(agi_commands);
01024    cmd = AST_LIST_REMOVE_HEAD(agi_commands, entry);
01025    AST_LIST_UNLOCK(agi_commands);
01026    return cmd;
01027 }
01028 
01029 /* channel is locked when calling this one either from the CLI or manager thread */
01030 static int add_agi_cmd(struct ast_channel *chan, const char *cmd_buff, const char *cmd_id)
01031 {
01032    struct ast_datastore *store;
01033    struct agi_cmd *cmd;
01034    AST_LIST_HEAD(, agi_cmd) *agi_commands;
01035 
01036    store = ast_channel_datastore_find(chan, &agi_commands_datastore_info, NULL);
01037    if (!store) {
01038       ast_log(LOG_WARNING, "Channel %s is not setup for Async AGI.\n", ast_channel_name(chan));
01039       return -1;
01040    }
01041    agi_commands = store->data;
01042    cmd = ast_calloc(1, sizeof(*cmd));
01043    if (!cmd) {
01044       return -1;
01045    }
01046    cmd->cmd_buffer = ast_strdup(cmd_buff);
01047    if (!cmd->cmd_buffer) {
01048       ast_free(cmd);
01049       return -1;
01050    }
01051    cmd->cmd_id = ast_strdup(cmd_id);
01052    if (!cmd->cmd_id) {
01053       ast_free(cmd->cmd_buffer);
01054       ast_free(cmd);
01055       return -1;
01056    }
01057    AST_LIST_LOCK(agi_commands);
01058    AST_LIST_INSERT_TAIL(agi_commands, cmd, entry);
01059    AST_LIST_UNLOCK(agi_commands);
01060    return 0;
01061 }
01062 
01063 static int add_to_agi(struct ast_channel *chan)
01064 {
01065    struct ast_datastore *datastore;
01066    AST_LIST_HEAD(, agi_cmd) *agi_cmds_list;
01067 
01068    /* check if already on AGI */
01069    ast_channel_lock(chan);
01070    datastore = ast_channel_datastore_find(chan, &agi_commands_datastore_info, NULL);
01071    ast_channel_unlock(chan);
01072    if (datastore) {
01073       /* we already have an AGI datastore, let's just
01074          return success */
01075       return 0;
01076    }
01077 
01078    /* the channel has never been on Async AGI,
01079       let's allocate it's datastore */
01080    datastore = ast_datastore_alloc(&agi_commands_datastore_info, "AGI");
01081    if (!datastore) {
01082       return -1;
01083    }
01084    agi_cmds_list = ast_calloc(1, sizeof(*agi_cmds_list));
01085    if (!agi_cmds_list) {
01086       ast_log(LOG_ERROR, "Unable to allocate Async AGI commands list.\n");
01087       ast_datastore_free(datastore);
01088       return -1;
01089    }
01090    datastore->data = agi_cmds_list;
01091    AST_LIST_HEAD_INIT(agi_cmds_list);
01092    ast_channel_lock(chan);
01093    ast_channel_datastore_add(chan, datastore);
01094    ast_channel_unlock(chan);
01095    return 0;
01096 }
01097 
01098 /*!
01099  * \brief CLI command to add applications to execute in Async AGI
01100  * \param e
01101  * \param cmd
01102  * \param a
01103  *
01104  * \retval CLI_SUCCESS on success
01105  * \retval NULL when init or tab completion is used
01106 */
01107 static char *handle_cli_agi_add_cmd(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
01108 {
01109    struct ast_channel *chan;
01110    switch (cmd) {
01111    case CLI_INIT:
01112       e->command = "agi exec";
01113       e->usage = "Usage: agi exec <channel name> <app and arguments> [id]\n"
01114             "       Add AGI command to the execute queue of the specified channel in Async AGI\n";
01115       return NULL;
01116    case CLI_GENERATE:
01117       if (a->pos == 2)
01118          return ast_complete_channels(a->line, a->word, a->pos, a->n, 2);
01119       return NULL;
01120    }
01121 
01122    if (a->argc < 4) {
01123       return CLI_SHOWUSAGE;
01124    }
01125 
01126    if (!(chan = ast_channel_get_by_name(a->argv[2]))) {
01127       ast_cli(a->fd, "Channel %s does not exist.\n", a->argv[2]);
01128       return CLI_FAILURE;
01129    }
01130 
01131    ast_channel_lock(chan);
01132 
01133    if (add_agi_cmd(chan, a->argv[3], (a->argc > 4 ? a->argv[4] : ""))) {
01134       ast_cli(a->fd, "Failed to add AGI command to queue of channel %s\n", ast_channel_name(chan));
01135       ast_channel_unlock(chan);
01136       chan = ast_channel_unref(chan);
01137       return CLI_FAILURE;
01138    }
01139 
01140    ast_debug(1, "Added AGI command to channel %s queue\n", ast_channel_name(chan));
01141 
01142    ast_channel_unlock(chan);
01143    chan = ast_channel_unref(chan);
01144 
01145    return CLI_SUCCESS;
01146 }
01147 
01148 /*!
01149  * \brief Add a new command to execute by the Async AGI application
01150  * \param s
01151  * \param m
01152  *
01153  * It will append the application to the specified channel's queue
01154  * if the channel is not inside Async AGI application it will return an error
01155  * \retval 0 on success or incorrect use
01156  * \retval 1 on failure to add the command ( most likely because the channel
01157  * is not in Async AGI loop )
01158 */
01159 static int action_add_agi_cmd(struct mansession *s, const struct message *m)
01160 {
01161    const char *channel = astman_get_header(m, "Channel");
01162    const char *cmdbuff = astman_get_header(m, "Command");
01163    const char *cmdid   = astman_get_header(m, "CommandID");
01164    struct ast_channel *chan;
01165    char buf[256];
01166 
01167    if (ast_strlen_zero(channel) || ast_strlen_zero(cmdbuff)) {
01168       astman_send_error(s, m, "Both, Channel and Command are *required*");
01169       return 0;
01170    }
01171 
01172    if (!(chan = ast_channel_get_by_name(channel))) {
01173       snprintf(buf, sizeof(buf), "Channel %s does not exist.", channel);
01174       astman_send_error(s, m, buf);
01175       return 0;
01176    }
01177 
01178    ast_channel_lock(chan);
01179 
01180    if (add_agi_cmd(chan, cmdbuff, cmdid)) {
01181       snprintf(buf, sizeof(buf), "Failed to add AGI command to channel %s queue", ast_channel_name(chan));
01182       astman_send_error(s, m, buf);
01183       ast_channel_unlock(chan);
01184       chan = ast_channel_unref(chan);
01185       return 0;
01186    }
01187 
01188    ast_channel_unlock(chan);
01189    chan = ast_channel_unref(chan);
01190 
01191    astman_send_ack(s, m, "Added AGI command to queue");
01192 
01193    return 0;
01194 }
01195 
01196 static enum agi_result agi_handle_command(struct ast_channel *chan, AGI *agi, char *buf, int dead);
01197 static void setup_env(struct ast_channel *chan, char *request, int fd, int enhanced, int argc, char *argv[]);
01198 
01199 /*!
01200  * \internal
01201  * \brief Read and handle a channel frame for Async AGI.
01202  *
01203  * \param chan Channel to read a frame from.
01204  *
01205  * \retval AGI_RESULT_SUCCESS on success.
01206  * \retval AGI_RESULT_HANGUP on hangup.
01207  * \retval AGI_RESULT_FAILURE on error.
01208  */
01209 static enum agi_result async_agi_read_frame(struct ast_channel *chan)
01210 {
01211    struct ast_frame *f;
01212 
01213    f = ast_read(chan);
01214    if (!f) {
01215       ast_debug(3, "No frame read on channel %s, going out ...\n", ast_channel_name(chan));
01216       return AGI_RESULT_HANGUP;
01217    }
01218    if (f->frametype == AST_FRAME_CONTROL) {
01219       /*
01220        * Is there any other frame we should care about besides
01221        * AST_CONTROL_HANGUP?
01222        */
01223       switch (f->subclass.integer) {
01224       case AST_CONTROL_HANGUP:
01225          ast_debug(3, "Got HANGUP frame on channel %s, going out ...\n", ast_channel_name(chan));
01226          ast_frfree(f);
01227          return AGI_RESULT_HANGUP;
01228       default:
01229          break;
01230       }
01231    }
01232    ast_frfree(f);
01233 
01234    return AGI_RESULT_SUCCESS;
01235 }
01236 
01237 static enum agi_result launch_asyncagi(struct ast_channel *chan, char *argv[], int *efd)
01238 {
01239 /* This buffer sizes might cause truncation if the AGI command writes more data
01240    than AGI_BUF_SIZE as result. But let's be serious, is there an AGI command
01241    that writes a response larger than 1024 bytes?, I don't think so, most of
01242    them are just result=blah stuff. However probably if GET VARIABLE is called
01243    and the variable has large amount of data, that could be a problem. We could
01244    make this buffers dynamic, but let's leave that as a second step.
01245 
01246    AMI_BUF_SIZE is twice AGI_BUF_SIZE just for the sake of choosing a safe
01247    number. Some characters of AGI buf will be url encoded to be sent to manager
01248    clients.  An URL encoded character will take 3 bytes, but again, to cause
01249    truncation more than about 70% of the AGI buffer should be URL encoded for
01250    that to happen.  Not likely at all.
01251 
01252    On the other hand. I wonder if read() could eventually return less data than
01253    the amount already available in the pipe? If so, how to deal with that?
01254    So far, my tests on Linux have not had any problems.
01255  */
01256 #define AGI_BUF_SIZE 1024
01257 #define AMI_BUF_SIZE 2048
01258    enum agi_result cmd_status;
01259    struct agi_cmd *cmd;
01260    int res;
01261    int fds[2];
01262    int hungup;
01263    int timeout = 100;
01264    char agi_buffer[AGI_BUF_SIZE + 1];
01265    char ami_buffer[AMI_BUF_SIZE];
01266    enum agi_result returnstatus = AGI_RESULT_SUCCESS;
01267    AGI async_agi;
01268 
01269    if (efd) {
01270       ast_log(LOG_WARNING, "Async AGI does not support Enhanced AGI yet\n");
01271       return AGI_RESULT_FAILURE;
01272    }
01273 
01274    /* add AsyncAGI datastore to the channel */
01275    if (add_to_agi(chan)) {
01276       ast_log(LOG_ERROR, "Failed to start Async AGI on channel %s\n", ast_channel_name(chan));
01277       return AGI_RESULT_FAILURE;
01278    }
01279 
01280    /* this pipe allows us to create a "fake" AGI struct to use
01281       the AGI commands */
01282    res = pipe(fds);
01283    if (res) {
01284       ast_log(LOG_ERROR, "Failed to create Async AGI pipe\n");
01285       /*
01286        * Intentionally do not remove the datastore added with
01287        * add_to_agi() the from channel.  It will be removed when the
01288        * channel is hung up anyway.
01289        */
01290       return AGI_RESULT_FAILURE;
01291    }
01292 
01293    /* handlers will get the pipe write fd and we read the AGI responses
01294       from the pipe read fd */
01295    async_agi.fd = fds[1];
01296    async_agi.ctrl = fds[1];
01297    async_agi.audio = -1; /* no audio support */
01298    async_agi.fast = 0;
01299    async_agi.speech = NULL;
01300 
01301    /* notify possible manager users of a new channel ready to
01302       receive commands */
01303    setup_env(chan, "async", fds[1], 0, 0, NULL);
01304    /* read the environment */
01305    res = read(fds[0], agi_buffer, AGI_BUF_SIZE);
01306    if (res <= 0) {
01307       ast_log(LOG_ERROR, "Failed to read from Async AGI pipe on channel %s: %s\n",
01308             ast_channel_name(chan), res < 0 ? strerror(errno) : "EOF");
01309       returnstatus = AGI_RESULT_FAILURE;
01310       goto async_agi_abort;
01311    }
01312    agi_buffer[res] = '\0';
01313    /* encode it and send it thru the manager so whoever is going to take
01314       care of AGI commands on this channel can decide which AGI commands
01315       to execute based on the setup info */
01316    ast_uri_encode(agi_buffer, ami_buffer, AMI_BUF_SIZE, ast_uri_http);
01317    manager_event(EVENT_FLAG_AGI, "AsyncAGI",
01318       "SubEvent: Start\r\n"
01319       "Channel: %s\r\n"
01320       "Env: %s\r\n", ast_channel_name(chan), ami_buffer);
01321    hungup = ast_check_hangup(chan);
01322    for (;;) {
01323       /*
01324        * Process as many commands as we can.  Commands are added via
01325        * the manager or the cli threads.
01326        */
01327       while (!hungup && (cmd = get_agi_cmd(chan))) {
01328          /* OK, we have a command, let's call the command handler. */
01329          cmd_status = agi_handle_command(chan, &async_agi, cmd->cmd_buffer, 0);
01330 
01331          /*
01332           * The command handler must have written to our fake AGI struct
01333           * fd (the pipe), let's read the response.
01334           */
01335          res = read(fds[0], agi_buffer, AGI_BUF_SIZE);
01336          if (res <= 0) {
01337             ast_log(LOG_ERROR, "Failed to read from Async AGI pipe on channel %s: %s\n",
01338                ast_channel_name(chan), res < 0 ? strerror(errno) : "EOF");
01339             free_agi_cmd(cmd);
01340             returnstatus = AGI_RESULT_FAILURE;
01341             goto async_agi_done;
01342          }
01343          /*
01344           * We have a response, let's send the response thru the manager.
01345           * Include the CommandID if it was specified when the command
01346           * was added.
01347           */
01348          agi_buffer[res] = '\0';
01349          ast_uri_encode(agi_buffer, ami_buffer, AMI_BUF_SIZE, ast_uri_http);
01350          if (ast_strlen_zero(cmd->cmd_id)) {
01351             manager_event(EVENT_FLAG_AGI, "AsyncAGI",
01352                "SubEvent: Exec\r\n"
01353                "Channel: %s\r\n"
01354                "Result: %s\r\n", ast_channel_name(chan), ami_buffer);
01355          } else {
01356             manager_event(EVENT_FLAG_AGI, "AsyncAGI",
01357                "SubEvent: Exec\r\n"
01358                "Channel: %s\r\n"
01359                "CommandID: %s\r\n"
01360                "Result: %s\r\n", ast_channel_name(chan), cmd->cmd_id, ami_buffer);
01361          }
01362          free_agi_cmd(cmd);
01363 
01364          /*
01365           * Check the command status to determine if we should continue
01366           * executing more commands.
01367           */
01368          hungup = ast_check_hangup(chan);
01369          switch (cmd_status) {
01370          case AGI_RESULT_FAILURE:
01371             if (!hungup) {
01372                /* The failure was not because of a hangup. */
01373                returnstatus = AGI_RESULT_FAILURE;
01374                goto async_agi_done;
01375             }
01376             break;
01377          case AGI_RESULT_SUCCESS_ASYNC:
01378             /* Only the "asyncagi break" command does this. */
01379             returnstatus = AGI_RESULT_SUCCESS_ASYNC;
01380             goto async_agi_done;
01381          default:
01382             break;
01383          }
01384       }
01385 
01386       if (!hungup) {
01387          /* Wait a bit for a frame to read or to poll for a new command. */
01388          res = ast_waitfor(chan, timeout);
01389          if (res < 0) {
01390             ast_debug(1, "ast_waitfor returned <= 0 on chan %s\n", ast_channel_name(chan));
01391             returnstatus = AGI_RESULT_FAILURE;
01392             break;
01393          }
01394       } else {
01395          /*
01396           * Read the channel control queue until it is dry so we can
01397           * quit.
01398           */
01399          res = 1;
01400       }
01401       if (0 < res) {
01402          do {
01403             cmd_status = async_agi_read_frame(chan);
01404             if (cmd_status != AGI_RESULT_SUCCESS) {
01405                returnstatus = cmd_status;
01406                goto async_agi_done;
01407             }
01408             hungup = ast_check_hangup(chan);
01409          } while (hungup);
01410       } else {
01411          hungup = ast_check_hangup(chan);
01412       }
01413    }
01414 async_agi_done:
01415 
01416    if (async_agi.speech) {
01417       ast_speech_destroy(async_agi.speech);
01418    }
01419    /* notify manager users this channel cannot be
01420       controlled anymore by Async AGI */
01421    manager_event(EVENT_FLAG_AGI, "AsyncAGI",
01422       "SubEvent: End\r\n"
01423       "Channel: %s\r\n", ast_channel_name(chan));
01424 
01425 async_agi_abort:
01426    /* close the pipe */
01427    close(fds[0]);
01428    close(fds[1]);
01429 
01430    /*
01431     * Intentionally do not remove the datastore added with
01432     * add_to_agi() the from channel.  There might be commands still
01433     * in the queue or in-flight to us and AsyncAGI may get called
01434     * again.  The datastore destructor will be called on channel
01435     * destruction anyway.
01436     */
01437 
01438    if (returnstatus == AGI_RESULT_SUCCESS) {
01439       returnstatus = AGI_RESULT_SUCCESS_ASYNC;
01440    }
01441    return returnstatus;
01442 
01443 #undef AGI_BUF_SIZE
01444 #undef AMI_BUF_SIZE
01445 }
01446 
01447 /*!
01448  * \internal
01449  * \brief Handle the connection that was started by launch_netscript.
01450  *
01451  * \param agiurl Url that we are trying to connect to.
01452  * \param addr Address that host was resolved to.
01453  * \param netsockfd File descriptor of socket.
01454  *
01455  * \retval 0 when connection is succesful.
01456  * \retval 1 when there is an error.
01457  */
01458 static int handle_connection(const char *agiurl, const struct ast_sockaddr addr, const int netsockfd)
01459 {
01460    struct pollfd pfds[1];
01461    int res, conresult;
01462    socklen_t reslen;
01463 
01464    reslen = sizeof(conresult);
01465 
01466    pfds[0].fd = netsockfd;
01467    pfds[0].events = POLLOUT;
01468 
01469    while ((res = ast_poll(pfds, 1, MAX_AGI_CONNECT)) != 1) {
01470       if (errno != EINTR) {
01471          if (!res) {
01472             ast_log(LOG_WARNING, "FastAGI connection to '%s' timed out after MAX_AGI_CONNECT (%d) milliseconds.\n",
01473                agiurl, MAX_AGI_CONNECT);
01474          } else {
01475             ast_log(LOG_WARNING, "Connect to '%s' failed: %s\n", agiurl, strerror(errno));
01476          }
01477 
01478          return 1;
01479       }
01480    }
01481 
01482    if (getsockopt(pfds[0].fd, SOL_SOCKET, SO_ERROR, &conresult, &reslen) < 0) {
01483       ast_log(LOG_WARNING, "Connection to %s failed with error: %s\n",
01484          ast_sockaddr_stringify(&addr), strerror(errno));
01485       return 1;
01486    }
01487 
01488    if (conresult) {
01489       ast_log(LOG_WARNING, "Connecting to '%s' failed for url '%s': %s\n",
01490          ast_sockaddr_stringify(&addr), agiurl, strerror(conresult));
01491       return 1;
01492    }
01493 
01494    return 0;
01495 }
01496 
01497 /* launch_netscript: The fastagi handler.
01498    FastAGI defaults to port 4573 */
01499 static enum agi_result launch_netscript(char *agiurl, char *argv[], int *fds)
01500 {
01501    int s = 0, flags;
01502    char *host, *script;
01503    int num_addrs = 0, i = 0;
01504    struct ast_sockaddr *addrs;
01505 
01506    /* agiurl is "agi://host.domain[:port][/script/name]" */
01507    host = ast_strdupa(agiurl + 6);  /* Remove agi:// */
01508 
01509    /* Strip off any script name */
01510    if ((script = strchr(host, '/'))) {
01511       *script++ = '\0';
01512    } else {
01513       script = "";
01514    }
01515 
01516    if (!(num_addrs = ast_sockaddr_resolve(&addrs, host, 0, AST_AF_UNSPEC))) {
01517       ast_log(LOG_WARNING, "Unable to locate host '%s'\n", host);
01518       return AGI_RESULT_FAILURE;
01519    }
01520 
01521    for (i = 0; i < num_addrs; i++) {
01522       if (!ast_sockaddr_port(&addrs[i])) {
01523          ast_sockaddr_set_port(&addrs[i], AGI_PORT);
01524       }
01525 
01526       if ((s = socket(addrs[i].ss.ss_family, SOCK_STREAM, IPPROTO_TCP)) < 0) {
01527          ast_log(LOG_WARNING, "Unable to create socket: %s\n", strerror(errno));
01528          continue;
01529       }
01530 
01531       if ((flags = fcntl(s, F_GETFL)) < 0) {
01532          ast_log(LOG_WARNING, "fcntl(F_GETFL) failed: %s\n", strerror(errno));
01533          close(s);
01534          continue;
01535       }
01536 
01537       if (fcntl(s, F_SETFL, flags | O_NONBLOCK) < 0) {
01538          ast_log(LOG_WARNING, "fnctl(F_SETFL) failed: %s\n", strerror(errno));
01539          close(s);
01540          continue;
01541       }
01542 
01543       if (ast_connect(s, &addrs[i]) && errno == EINPROGRESS) {
01544 
01545          if (handle_connection(agiurl, addrs[i], s)) {
01546             close(s);
01547             continue;
01548          }
01549 
01550       } else {
01551          ast_log(LOG_WARNING, "Connection to %s failed with unexpected error: %s\n",
01552          ast_sockaddr_stringify(&addrs[i]), strerror(errno));
01553       }
01554 
01555       break;
01556    }
01557 
01558    ast_free(addrs);
01559 
01560    if (i == num_addrs) {
01561       ast_log(LOG_WARNING, "Couldn't connect to any host.  FastAGI failed.\n");
01562       return AGI_RESULT_FAILURE;
01563    }
01564 
01565    if (ast_agi_send(s, NULL, "agi_network: yes\n") < 0) {
01566       if (errno != EINTR) {
01567          ast_log(LOG_WARNING, "Connect to '%s' failed: %s\n", agiurl, strerror(errno));
01568          close(s);
01569          return AGI_RESULT_FAILURE;
01570       }
01571    }
01572 
01573    /* If we have a script parameter, relay it to the fastagi server */
01574    /* Script parameters take the form of: AGI(agi://my.example.com/?extension=${EXTEN}) */
01575    if (!ast_strlen_zero(script)) {
01576       ast_agi_send(s, NULL, "agi_network_script: %s\n", script);
01577    }
01578 
01579    ast_debug(4, "Wow, connected!\n");
01580    fds[0] = s;
01581    fds[1] = s;
01582    return AGI_RESULT_SUCCESS_FAST;
01583 }
01584 
01585 /*!
01586  * \internal
01587  * \brief The HA fastagi handler.
01588  * \param agiurl The request URL as passed to Agi() in the dial plan
01589  * \param argv The parameters after the URL passed to Agi() in the dial plan
01590  * \param fds Input/output file descriptors
01591  *
01592  * Uses SRV lookups to try to connect to a list of FastAGI servers. The hostname in
01593  * the URI is prefixed with _agi._tcp. prior to the DNS resolution. For
01594  * example, if you specify the URI \a hagi://agi.example.com/foo.agi the DNS
01595  * query would be for \a _agi._tcp.agi.example.com and you'll need to make sure
01596  * this resolves.
01597  *
01598  * This function parses the URI, resolves the SRV service name, forms new URIs
01599  * with the results of the DNS lookup, and then calls launch_netscript on the
01600  * new URIs until one succeeds.
01601  *
01602  * \return the result of the AGI operation.
01603  */
01604 static enum agi_result launch_ha_netscript(char *agiurl, char *argv[], int *fds)
01605 {
01606    char *host, *script;
01607    enum agi_result result;
01608    struct srv_context *context = NULL;
01609    int srv_ret;
01610    char service[256];
01611    char resolved_uri[1024];
01612    const char *srvhost;
01613    unsigned short srvport;
01614 
01615    /* format of agiurl is "hagi://host.domain[:port][/script/name]" */
01616    if (strlen(agiurl) < 7) { /* Remove hagi:// */
01617       ast_log(LOG_WARNING, "An error occurred parsing the AGI URI: %s", agiurl);
01618       return AGI_RESULT_FAILURE;
01619    }
01620    host = ast_strdupa(agiurl + 7);
01621 
01622    /* Strip off any script name */
01623    if ((script = strchr(host, '/'))) {
01624       *script++ = '\0';
01625    } else {
01626       script = "";
01627    }
01628 
01629    if (strchr(host, ':')) {
01630       ast_log(LOG_WARNING, "Specifying a port number disables SRV lookups: %s\n", agiurl);
01631       return launch_netscript(agiurl + 1, argv, fds); /* +1 to strip off leading h from hagi:// */
01632    }
01633 
01634    snprintf(service, sizeof(service), "%s%s", SRV_PREFIX, host);
01635 
01636    while (!(srv_ret = ast_srv_lookup(&context, service, &srvhost, &srvport))) {
01637       snprintf(resolved_uri, sizeof(resolved_uri), "agi://%s:%d/%s", srvhost, srvport, script);
01638       result = launch_netscript(resolved_uri, argv, fds);
01639       if (result == AGI_RESULT_FAILURE || result == AGI_RESULT_NOTFOUND) {
01640          ast_log(LOG_WARNING, "AGI request failed for host '%s' (%s:%d)\n", host, srvhost, srvport);
01641       } else {
01642          /* The script launched so we must cleanup the context. */
01643          ast_srv_cleanup(&context);
01644          return result;
01645       }
01646    }
01647    /*
01648     * The DNS SRV lookup failed or we ran out of servers to check.
01649     * ast_srv_lookup() has already cleaned up the context for us.
01650     */
01651    if (srv_ret < 0) {
01652       ast_log(LOG_WARNING, "SRV lookup failed for %s\n", agiurl);
01653    }
01654 
01655    return AGI_RESULT_FAILURE;
01656 }
01657 
01658 static enum agi_result launch_script(struct ast_channel *chan, char *script, char *argv[], int *fds, int *efd, int *opid)
01659 {
01660    char tmp[256];
01661    int pid, toast[2], fromast[2], audio[2], res;
01662    struct stat st;
01663 
01664    if (!strncasecmp(script, "agi://", 6)) {
01665       return (efd == NULL) ? launch_netscript(script, argv, fds) : AGI_RESULT_FAILURE;
01666    }
01667    if (!strncasecmp(script, "hagi://", 7)) {
01668       return (efd == NULL) ? launch_ha_netscript(script, argv, fds) : AGI_RESULT_FAILURE;
01669    }
01670    if (!strncasecmp(script, "agi:async", sizeof("agi:async") - 1)) {
01671       return launch_asyncagi(chan, argv, efd);
01672    }
01673 
01674    if (script[0] != '/') {
01675       snprintf(tmp, sizeof(tmp), "%s/%s", ast_config_AST_AGI_DIR, script);
01676       script = tmp;
01677    }
01678 
01679    /* Before even trying let's see if the file actually exists */
01680    if (stat(script, &st)) {
01681       ast_log(LOG_WARNING, "Failed to execute '%s': File does not exist.\n", script);
01682       return AGI_RESULT_NOTFOUND;
01683    }
01684 
01685    if (pipe(toast)) {
01686       ast_log(LOG_WARNING, "Unable to create toast pipe: %s\n",strerror(errno));
01687       return AGI_RESULT_FAILURE;
01688    }
01689    if (pipe(fromast)) {
01690       ast_log(LOG_WARNING, "unable to create fromast pipe: %s\n", strerror(errno));
01691       close(toast[0]);
01692       close(toast[1]);
01693       return AGI_RESULT_FAILURE;
01694    }
01695    if (efd) {
01696       if (pipe(audio)) {
01697          ast_log(LOG_WARNING, "unable to create audio pipe: %s\n", strerror(errno));
01698          close(fromast[0]);
01699          close(fromast[1]);
01700          close(toast[0]);
01701          close(toast[1]);
01702          return AGI_RESULT_FAILURE;
01703       }
01704       res = fcntl(audio[1], F_GETFL);
01705       if (res > -1)
01706          res = fcntl(audio[1], F_SETFL, res | O_NONBLOCK);
01707       if (res < 0) {
01708          ast_log(LOG_WARNING, "unable to set audio pipe parameters: %s\n", strerror(errno));
01709          close(fromast[0]);
01710          close(fromast[1]);
01711          close(toast[0]);
01712          close(toast[1]);
01713          close(audio[0]);
01714          close(audio[1]);
01715          return AGI_RESULT_FAILURE;
01716       }
01717    }
01718 
01719    if ((pid = ast_safe_fork(1)) < 0) {
01720       ast_log(LOG_WARNING, "Failed to fork(): %s\n", strerror(errno));
01721       return AGI_RESULT_FAILURE;
01722    }
01723    if (!pid) {
01724       /* Pass paths to AGI via environmental variables */
01725       setenv("AST_CONFIG_DIR", ast_config_AST_CONFIG_DIR, 1);
01726       setenv("AST_CONFIG_FILE", ast_config_AST_CONFIG_FILE, 1);
01727       setenv("AST_MODULE_DIR", ast_config_AST_MODULE_DIR, 1);
01728       setenv("AST_SPOOL_DIR", ast_config_AST_SPOOL_DIR, 1);
01729       setenv("AST_MONITOR_DIR", ast_config_AST_MONITOR_DIR, 1);
01730       setenv("AST_VAR_DIR", ast_config_AST_VAR_DIR, 1);
01731       setenv("AST_DATA_DIR", ast_config_AST_DATA_DIR, 1);
01732       setenv("AST_LOG_DIR", ast_config_AST_LOG_DIR, 1);
01733       setenv("AST_AGI_DIR", ast_config_AST_AGI_DIR, 1);
01734       setenv("AST_KEY_DIR", ast_config_AST_KEY_DIR, 1);
01735       setenv("AST_RUN_DIR", ast_config_AST_RUN_DIR, 1);
01736 
01737       /* Don't run AGI scripts with realtime priority -- it causes audio stutter */
01738       ast_set_priority(0);
01739 
01740       /* Redirect stdin and out, provide enhanced audio channel if desired */
01741       dup2(fromast[0], STDIN_FILENO);
01742       dup2(toast[1], STDOUT_FILENO);
01743       if (efd)
01744          dup2(audio[0], STDERR_FILENO + 1);
01745       else
01746          close(STDERR_FILENO + 1);
01747 
01748       /* Close everything but stdin/out/error */
01749       ast_close_fds_above_n(STDERR_FILENO + 1);
01750 
01751       /* Execute script */
01752       /* XXX argv should be deprecated in favor of passing agi_argX paramaters */
01753       execv(script, argv);
01754       /* Can't use ast_log since FD's are closed */
01755       ast_child_verbose(1, "Failed to execute '%s': %s", script, strerror(errno));
01756       /* Special case to set status of AGI to failure */
01757       fprintf(stdout, "failure\n");
01758       fflush(stdout);
01759       _exit(1);
01760    }
01761    ast_verb(3, "Launched AGI Script %s\n", script);
01762    fds[0] = toast[0];
01763    fds[1] = fromast[1];
01764    if (efd)
01765       *efd = audio[1];
01766    /* close what we're not using in the parent */
01767    close(toast[1]);
01768    close(fromast[0]);
01769 
01770    if (efd)
01771       close(audio[0]);
01772 
01773    *opid = pid;
01774    return AGI_RESULT_SUCCESS;
01775 }
01776 
01777 static void setup_env(struct ast_channel *chan, char *request, int fd, int enhanced, int argc, char *argv[])
01778 {
01779    int count;
01780 
01781    /* Print initial environment, with agi_request always being the first
01782       thing */
01783    ast_agi_send(fd, chan, "agi_request: %s\n", request);
01784    ast_agi_send(fd, chan, "agi_channel: %s\n", ast_channel_name(chan));
01785    ast_agi_send(fd, chan, "agi_language: %s\n", ast_channel_language(chan));
01786    ast_agi_send(fd, chan, "agi_type: %s\n", ast_channel_tech(chan)->type);
01787    ast_agi_send(fd, chan, "agi_uniqueid: %s\n", ast_channel_uniqueid(chan));
01788    ast_agi_send(fd, chan, "agi_version: %s\n", ast_get_version());
01789 
01790    /* ANI/DNIS */
01791    ast_agi_send(fd, chan, "agi_callerid: %s\n",
01792       S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, "unknown"));
01793    ast_agi_send(fd, chan, "agi_calleridname: %s\n",
01794       S_COR(ast_channel_caller(chan)->id.name.valid, ast_channel_caller(chan)->id.name.str, "unknown"));
01795    ast_agi_send(fd, chan, "agi_callingpres: %d\n",
01796       ast_party_id_presentation(&ast_channel_caller(chan)->id));
01797    ast_agi_send(fd, chan, "agi_callingani2: %d\n", ast_channel_caller(chan)->ani2);
01798    ast_agi_send(fd, chan, "agi_callington: %d\n", ast_channel_caller(chan)->id.number.plan);
01799    ast_agi_send(fd, chan, "agi_callingtns: %d\n", ast_channel_dialed(chan)->transit_network_select);
01800    ast_agi_send(fd, chan, "agi_dnid: %s\n", S_OR(ast_channel_dialed(chan)->number.str, "unknown"));
01801    ast_agi_send(fd, chan, "agi_rdnis: %s\n",
01802       S_COR(ast_channel_redirecting(chan)->from.number.valid, ast_channel_redirecting(chan)->from.number.str, "unknown"));
01803 
01804    /* Context information */
01805    ast_agi_send(fd, chan, "agi_context: %s\n", ast_channel_context(chan));
01806    ast_agi_send(fd, chan, "agi_extension: %s\n", ast_channel_exten(chan));
01807    ast_agi_send(fd, chan, "agi_priority: %d\n", ast_channel_priority(chan));
01808    ast_agi_send(fd, chan, "agi_enhanced: %s\n", enhanced ? "1.0" : "0.0");
01809 
01810    /* User information */
01811    ast_agi_send(fd, chan, "agi_accountcode: %s\n", ast_channel_accountcode(chan) ? ast_channel_accountcode(chan) : "");
01812    ast_agi_send(fd, chan, "agi_threadid: %ld\n", (long)pthread_self());
01813 
01814    /* Send any parameters to the fastagi server that have been passed via the agi application */
01815    /* Agi application paramaters take the form of: AGI(/path/to/example/script|${EXTEN}) */
01816    for(count = 1; count < argc; count++)
01817       ast_agi_send(fd, chan, "agi_arg_%d: %s\n", count, argv[count]);
01818 
01819    /* End with empty return */
01820    ast_agi_send(fd, chan, "\n");
01821 }
01822 
01823 static int handle_answer(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
01824 {
01825    int res = 0;
01826 
01827    /* Answer the channel */
01828    if (ast_channel_state(chan) != AST_STATE_UP)
01829       res = ast_answer(chan);
01830 
01831    ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
01832    return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
01833 }
01834 
01835 static int handle_asyncagi_break(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
01836 {
01837    ast_agi_send(agi->fd, chan, "200 result=0\n");
01838    return ASYNC_AGI_BREAK;
01839 }
01840 
01841 static int handle_waitfordigit(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
01842 {
01843    int res, to;
01844 
01845    if (argc != 4)
01846       return RESULT_SHOWUSAGE;
01847    if (sscanf(argv[3], "%30d", &to) != 1)
01848       return RESULT_SHOWUSAGE;
01849    res = ast_waitfordigit_full(chan, to, agi->audio, agi->ctrl);
01850    ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
01851    return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
01852 }
01853 
01854 static int handle_sendtext(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
01855 {
01856    int res;
01857 
01858    if (argc != 3)
01859       return RESULT_SHOWUSAGE;
01860 
01861    /* At the moment, the parser (perhaps broken) returns with
01862       the last argument PLUS the newline at the end of the input
01863       buffer. This probably needs to be fixed, but I wont do that
01864       because other stuff may break as a result. The right way
01865       would probably be to strip off the trailing newline before
01866       parsing, then here, add a newline at the end of the string
01867       before sending it to ast_sendtext --DUDE */
01868    res = ast_sendtext(chan, argv[2]);
01869    ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
01870    return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
01871 }
01872 
01873 static int handle_recvchar(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
01874 {
01875    int res;
01876 
01877    if (argc != 3)
01878       return RESULT_SHOWUSAGE;
01879 
01880    res = ast_recvchar(chan,atoi(argv[2]));
01881    if (res == 0) {
01882       ast_agi_send(agi->fd, chan, "200 result=%d (timeout)\n", res);
01883       return RESULT_SUCCESS;
01884    }
01885    if (res > 0) {
01886       ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
01887       return RESULT_SUCCESS;
01888    }
01889    ast_agi_send(agi->fd, chan, "200 result=%d (hangup)\n", res);
01890    return RESULT_FAILURE;
01891 }
01892 
01893 static int handle_recvtext(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
01894 {
01895    char *buf;
01896 
01897    if (argc != 3)
01898       return RESULT_SHOWUSAGE;
01899 
01900    buf = ast_recvtext(chan, atoi(argv[2]));
01901    if (buf) {
01902       ast_agi_send(agi->fd, chan, "200 result=1 (%s)\n", buf);
01903       ast_free(buf);
01904    } else {
01905       ast_agi_send(agi->fd, chan, "200 result=-1\n");
01906    }
01907    return RESULT_SUCCESS;
01908 }
01909 
01910 static int handle_tddmode(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
01911 {
01912    int res, x;
01913 
01914    if (argc != 3)
01915       return RESULT_SHOWUSAGE;
01916 
01917    if (!strncasecmp(argv[2],"on",2)) {
01918       x = 1;
01919    } else  {
01920       x = 0;
01921    }
01922    if (!strncasecmp(argv[2],"mate",4))  {
01923       x = 2;
01924    }
01925    if (!strncasecmp(argv[2],"tdd",3)) {
01926       x = 1;
01927    }
01928    res = ast_channel_setoption(chan, AST_OPTION_TDD, &x, sizeof(char), 0);
01929    if (res) {
01930       /* Set channel option failed */
01931       ast_agi_send(agi->fd, chan, "200 result=0\n");
01932    } else {
01933       ast_agi_send(agi->fd, chan, "200 result=1\n");
01934    }
01935    return RESULT_SUCCESS;
01936 }
01937 
01938 static int handle_sendimage(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
01939 {
01940    int res;
01941 
01942    if (argc != 3) {
01943       return RESULT_SHOWUSAGE;
01944    }
01945 
01946    res = ast_send_image(chan, argv[2]);
01947    if (!ast_check_hangup(chan)) {
01948       res = 0;
01949    }
01950    ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
01951    return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
01952 }
01953 
01954 static int handle_controlstreamfile(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
01955 {
01956    int res = 0, skipms = 3000;
01957    const char *fwd = "#", *rev = "*", *suspend = NULL, *stop = NULL; /* Default values */
01958 
01959    if (argc < 5 || argc > 9) {
01960       return RESULT_SHOWUSAGE;
01961    }
01962 
01963    if (!ast_strlen_zero(argv[4])) {
01964       stop = argv[4];
01965    }
01966 
01967    if ((argc > 5) && (sscanf(argv[5], "%30d", &skipms) != 1)) {
01968       return RESULT_SHOWUSAGE;
01969    }
01970 
01971    if (argc > 6 && !ast_strlen_zero(argv[6])) {
01972       fwd = argv[6];
01973    }
01974 
01975    if (argc > 7 && !ast_strlen_zero(argv[7])) {
01976       rev = argv[7];
01977    }
01978 
01979    if (argc > 8 && !ast_strlen_zero(argv[8])) {
01980       suspend = argv[8];
01981    }
01982 
01983    res = ast_control_streamfile(chan, argv[3], fwd, rev, stop, suspend, NULL, skipms, NULL);
01984 
01985    ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
01986 
01987    return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
01988 }
01989 
01990 static int handle_streamfile(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
01991 {
01992    int res;
01993    struct ast_filestream *fs, *vfs;
01994    long sample_offset = 0, max_length;
01995    const char *edigits = "";
01996 
01997    if (argc < 4 || argc > 5) {
01998       return RESULT_SHOWUSAGE;
01999    }
02000 
02001    if (argv[3]) {
02002       edigits = argv[3];
02003    }
02004 
02005    if ((argc > 4) && (sscanf(argv[4], "%30ld", &sample_offset) != 1)) {
02006       return RESULT_SHOWUSAGE;
02007    }
02008 
02009    if (!(fs = ast_openstream(chan, argv[2], ast_channel_language(chan)))) {
02010       ast_agi_send(agi->fd, chan, "200 result=-1 endpos=%ld\n", sample_offset);
02011       return RESULT_FAILURE;
02012    }
02013 
02014    if ((vfs = ast_openvstream(chan, argv[2], ast_channel_language(chan)))) {
02015       ast_debug(1, "Ooh, found a video stream, too\n");
02016    }
02017 
02018    ast_verb(3, "Playing '%s' (escape_digits=%s) (sample_offset %ld)\n", argv[2], edigits, sample_offset);
02019 
02020    ast_seekstream(fs, 0, SEEK_END);
02021    max_length = ast_tellstream(fs);
02022    ast_seekstream(fs, sample_offset, SEEK_SET);
02023    res = ast_applystream(chan, fs);
02024    if (vfs) {
02025       ast_applystream(chan, vfs);
02026    }
02027    ast_playstream(fs);
02028    if (vfs) {
02029       ast_playstream(vfs);
02030    }
02031 
02032    res = ast_waitstream_full(chan, argv[3], agi->audio, agi->ctrl);
02033    /* this is to check for if ast_waitstream closed the stream, we probably are at
02034     * the end of the stream, return that amount, else check for the amount */
02035    sample_offset = (ast_channel_stream(chan)) ? ast_tellstream(fs) : max_length;
02036    ast_stopstream(chan);
02037    if (res == 1) {
02038       /* Stop this command, don't print a result line, as there is a new command */
02039       return RESULT_SUCCESS;
02040    }
02041    ast_agi_send(agi->fd, chan, "200 result=%d endpos=%ld\n", res, sample_offset);
02042    return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
02043 }
02044 
02045 /*! \brief get option - really similar to the handle_streamfile, but with a timeout */
02046 static int handle_getoption(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
02047 {
02048    int res;
02049    struct ast_filestream *fs, *vfs;
02050    long sample_offset = 0, max_length;
02051    int timeout = 0;
02052    const char *edigits = "";
02053 
02054    if ( argc < 4 || argc > 5 )
02055       return RESULT_SHOWUSAGE;
02056 
02057    if ( argv[3] )
02058       edigits = argv[3];
02059 
02060    if ( argc == 5 )
02061       timeout = atoi(argv[4]);
02062    else if (ast_channel_pbx(chan)->dtimeoutms) {
02063       /* by default dtimeout is set to 5sec */
02064       timeout = ast_channel_pbx(chan)->dtimeoutms; /* in msec */
02065    }
02066 
02067    if (!(fs = ast_openstream(chan, argv[2], ast_channel_language(chan)))) {
02068       ast_agi_send(agi->fd, chan, "200 result=-1 endpos=%ld\n", sample_offset);
02069       ast_log(LOG_WARNING, "Unable to open %s\n", argv[2]);
02070       return RESULT_FAILURE;
02071    }
02072 
02073    if ((vfs = ast_openvstream(chan, argv[2], ast_channel_language(chan))))
02074       ast_debug(1, "Ooh, found a video stream, too\n");
02075 
02076    ast_verb(3, "Playing '%s' (escape_digits=%s) (timeout %d)\n", argv[2], edigits, timeout);
02077 
02078    ast_seekstream(fs, 0, SEEK_END);
02079    max_length = ast_tellstream(fs);
02080    ast_seekstream(fs, sample_offset, SEEK_SET);
02081    res = ast_applystream(chan, fs);
02082    if (vfs)
02083       ast_applystream(chan, vfs);
02084    ast_playstream(fs);
02085    if (vfs)
02086       ast_playstream(vfs);
02087 
02088    res = ast_waitstream_full(chan, argv[3], agi->audio, agi->ctrl);
02089    /* this is to check for if ast_waitstream closed the stream, we probably are at
02090     * the end of the stream, return that amount, else check for the amount */
02091    sample_offset = (ast_channel_stream(chan))?ast_tellstream(fs):max_length;
02092    ast_stopstream(chan);
02093    if (res == 1) {
02094       /* Stop this command, don't print a result line, as there is a new command */
02095       return RESULT_SUCCESS;
02096    }
02097 
02098    /* If the user didnt press a key, wait for digitTimeout*/
02099    if (res == 0 ) {
02100       res = ast_waitfordigit_full(chan, timeout, agi->audio, agi->ctrl);
02101       /* Make sure the new result is in the escape digits of the GET OPTION */
02102       if ( !strchr(edigits,res) )
02103          res=0;
02104    }
02105 
02106    ast_agi_send(agi->fd, chan, "200 result=%d endpos=%ld\n", res, sample_offset);
02107    return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
02108 }
02109 
02110 
02111 
02112 
02113 /*! \brief Say number in various language syntaxes */
02114 /* While waiting, we're sending a NULL.  */
02115 static int handle_saynumber(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
02116 {
02117    int res, num;
02118 
02119    if (argc < 4 || argc > 5)
02120       return RESULT_SHOWUSAGE;
02121    if (sscanf(argv[2], "%30d", &num) != 1)
02122       return RESULT_SHOWUSAGE;
02123    res = ast_say_number_full(chan, num, argv[3], ast_channel_language(chan), argc > 4 ? argv[4] : NULL, agi->audio, agi->ctrl);
02124    if (res == 1)
02125       return RESULT_SUCCESS;
02126    ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
02127    return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
02128 }
02129 
02130 static int handle_saydigits(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
02131 {
02132    int res, num;
02133 
02134    if (argc != 4)
02135       return RESULT_SHOWUSAGE;
02136    if (sscanf(argv[2], "%30d", &num) != 1)
02137       return RESULT_SHOWUSAGE;
02138 
02139    res = ast_say_digit_str_full(chan, argv[2], argv[3], ast_channel_language(chan), agi->audio, agi->ctrl);
02140    if (res == 1) /* New command */
02141       return RESULT_SUCCESS;
02142    ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
02143    return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
02144 }
02145 
02146 static int handle_sayalpha(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
02147 {
02148    int res;
02149 
02150    if (argc != 4)
02151       return RESULT_SHOWUSAGE;
02152 
02153    res = ast_say_character_str_full(chan, argv[2], argv[3], ast_channel_language(chan), agi->audio, agi->ctrl);
02154    if (res == 1) /* New command */
02155       return RESULT_SUCCESS;
02156    ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
02157    return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
02158 }
02159 
02160 static int handle_saydate(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
02161 {
02162    int res, num;
02163 
02164    if (argc != 4)
02165       return RESULT_SHOWUSAGE;
02166    if (sscanf(argv[2], "%30d", &num) != 1)
02167       return RESULT_SHOWUSAGE;
02168    res = ast_say_date(chan, num, argv[3], ast_channel_language(chan));
02169    if (res == 1)
02170       return RESULT_SUCCESS;
02171    ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
02172    return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
02173 }
02174 
02175 static int handle_saytime(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
02176 {
02177    int res, num;
02178 
02179    if (argc != 4)
02180       return RESULT_SHOWUSAGE;
02181    if (sscanf(argv[2], "%30d", &num) != 1)
02182       return RESULT_SHOWUSAGE;
02183    res = ast_say_time(chan, num, argv[3], ast_channel_language(chan));
02184    if (res == 1)
02185       return RESULT_SUCCESS;
02186    ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
02187    return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
02188 }
02189 
02190 static int handle_saydatetime(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
02191 {
02192    int res = 0;
02193    time_t unixtime;
02194    const char *format, *zone = NULL;
02195 
02196    if (argc < 4)
02197       return RESULT_SHOWUSAGE;
02198 
02199    if (argc > 4) {
02200       format = argv[4];
02201    } else {
02202       /* XXX this doesn't belong here, but in the 'say' module */
02203       if (!strcasecmp(ast_channel_language(chan), "de")) {
02204          format = "A dBY HMS";
02205       } else {
02206          format = "ABdY 'digits/at' IMp";
02207       }
02208    }
02209 
02210    if (argc > 5 && !ast_strlen_zero(argv[5]))
02211       zone = argv[5];
02212 
02213    if (ast_get_time_t(argv[2], &unixtime, 0, NULL))
02214       return RESULT_SHOWUSAGE;
02215 
02216    res = ast_say_date_with_format(chan, unixtime, argv[3], ast_channel_language(chan), format, zone);
02217    if (res == 1)
02218       return RESULT_SUCCESS;
02219 
02220    ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
02221    return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
02222 }
02223 
02224 static int handle_sayphonetic(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
02225 {
02226    int res;
02227 
02228    if (argc != 4)
02229       return RESULT_SHOWUSAGE;
02230 
02231    res = ast_say_phonetic_str_full(chan, argv[2], argv[3], ast_channel_language(chan), agi->audio, agi->ctrl);
02232    if (res == 1) /* New command */
02233       return RESULT_SUCCESS;
02234    ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
02235    return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
02236 }
02237 
02238 static int handle_getdata(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
02239 {
02240    int res, max, timeout;
02241    char data[1024];
02242 
02243    if (argc < 3)
02244       return RESULT_SHOWUSAGE;
02245    if (argc >= 4)
02246       timeout = atoi(argv[3]);
02247    else
02248       timeout = 0;
02249    if (argc >= 5)
02250       max = atoi(argv[4]);
02251    else
02252       max = 1024;
02253    res = ast_app_getdata_full(chan, argv[2], data, max, timeout, agi->audio, agi->ctrl);
02254    if (res == 2)        /* New command */
02255       return RESULT_SUCCESS;
02256    else if (res == 1)
02257       ast_agi_send(agi->fd, chan, "200 result=%s (timeout)\n", data);
02258    else if (res < 0 )
02259       ast_agi_send(agi->fd, chan, "200 result=-1\n");
02260    else
02261       ast_agi_send(agi->fd, chan, "200 result=%s\n", data);
02262    return RESULT_SUCCESS;
02263 }
02264 
02265 static int handle_setcontext(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
02266 {
02267 
02268    if (argc != 3)
02269       return RESULT_SHOWUSAGE;
02270    ast_channel_context_set(chan, argv[2]);
02271    ast_agi_send(agi->fd, chan, "200 result=0\n");
02272    return RESULT_SUCCESS;
02273 }
02274 
02275 static int handle_setextension(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
02276 {
02277    if (argc != 3)
02278       return RESULT_SHOWUSAGE;
02279    ast_channel_exten_set(chan, argv[2]);
02280    ast_agi_send(agi->fd, chan, "200 result=0\n");
02281    return RESULT_SUCCESS;
02282 }
02283 
02284 static int handle_setpriority(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
02285 {
02286    int pri;
02287 
02288    if (argc != 3)
02289       return RESULT_SHOWUSAGE;
02290 
02291    if (sscanf(argv[2], "%30d", &pri) != 1) {
02292       pri = ast_findlabel_extension(chan, ast_channel_context(chan), ast_channel_exten(chan), argv[2],
02293          S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL));
02294       if (pri < 1)
02295          return RESULT_SHOWUSAGE;
02296    }
02297 
02298    ast_explicit_goto(chan, NULL, NULL, pri);
02299    ast_agi_send(agi->fd, chan, "200 result=0\n");
02300    return RESULT_SUCCESS;
02301 }
02302 
02303 static int handle_recordfile(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
02304 {
02305    struct ast_filestream *fs;
02306    struct ast_frame *f;
02307    struct timeval start;
02308    long sample_offset = 0;
02309    int res = 0;
02310    int ms;
02311 
02312    struct ast_dsp *sildet=NULL;         /* silence detector dsp */
02313    int totalsilence = 0;
02314    int dspsilence = 0;
02315    int silence = 0;                /* amount of silence to allow */
02316    int gotsilence = 0;             /* did we timeout for silence? */
02317    char *silencestr = NULL;
02318    struct ast_format rfmt;
02319    ast_format_clear(&rfmt);
02320 
02321    /* XXX EAGI FIXME XXX */
02322 
02323    if (argc < 6)
02324       return RESULT_SHOWUSAGE;
02325    if (sscanf(argv[5], "%30d", &ms) != 1)
02326       return RESULT_SHOWUSAGE;
02327 
02328    if (argc > 6)
02329       silencestr = strchr(argv[6],'s');
02330    if ((argc > 7) && (!silencestr))
02331       silencestr = strchr(argv[7],'s');
02332    if ((argc > 8) && (!silencestr))
02333       silencestr = strchr(argv[8],'s');
02334 
02335    if (silencestr) {
02336       if (strlen(silencestr) > 2) {
02337          if ((silencestr[0] == 's') && (silencestr[1] == '=')) {
02338             silencestr++;
02339             silencestr++;
02340             if (silencestr)
02341                silence = atoi(silencestr);
02342             if (silence > 0)
02343                silence *= 1000;
02344          }
02345       }
02346    }
02347 
02348    if (silence > 0) {
02349       ast_format_copy(&rfmt, ast_channel_readformat(chan));
02350       res = ast_set_read_format_by_id(chan, AST_FORMAT_SLINEAR);
02351       if (res < 0) {
02352          ast_log(LOG_WARNING, "Unable to set to linear mode, giving up\n");
02353          ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
02354          return RESULT_FAILURE;
02355       }
02356       sildet = ast_dsp_new();
02357       if (!sildet) {
02358          ast_log(LOG_WARNING, "Unable to create silence detector :(\n");
02359          ast_agi_send(agi->fd, chan, "200 result=-1\n");
02360          return RESULT_FAILURE;
02361       }
02362       ast_dsp_set_threshold(sildet, ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE));
02363    }
02364    
02365    /* backward compatibility, if no offset given, arg[6] would have been
02366     * caught below and taken to be a beep, else if it is a digit then it is a
02367     * offset */
02368    if ((argc >6) && (sscanf(argv[6], "%30ld", &sample_offset) != 1) && (!strchr(argv[6], '=')))
02369       res = ast_streamfile(chan, "beep", ast_channel_language(chan));
02370 
02371    if ((argc > 7) && (!strchr(argv[7], '=')))
02372       res = ast_streamfile(chan, "beep", ast_channel_language(chan));
02373 
02374    if (!res)
02375       res = ast_waitstream(chan, argv[4]);
02376    if (res) {
02377       ast_agi_send(agi->fd, chan, "200 result=%d (randomerror) endpos=%ld\n", res, sample_offset);
02378    } else {
02379       fs = ast_writefile(argv[2], argv[3], NULL, O_CREAT | O_WRONLY | (sample_offset ? O_APPEND : 0), 0, AST_FILE_MODE);
02380       if (!fs) {
02381          res = -1;
02382          ast_agi_send(agi->fd, chan, "200 result=%d (writefile)\n", res);
02383          if (sildet)
02384             ast_dsp_free(sildet);
02385          return RESULT_FAILURE;
02386       }
02387 
02388       /* Request a video update */
02389       ast_indicate(chan, AST_CONTROL_VIDUPDATE);
02390 
02391       ast_channel_stream_set(chan, fs);
02392       ast_applystream(chan,fs);
02393       /* really should have checks */
02394       ast_seekstream(fs, sample_offset, SEEK_SET);
02395       ast_truncstream(fs);
02396 
02397       start = ast_tvnow();
02398       while ((ms < 0) || ast_tvdiff_ms(ast_tvnow(), start) < ms) {
02399          res = ast_waitfor(chan, ms - ast_tvdiff_ms(ast_tvnow(), start));
02400          if (res < 0) {
02401             ast_closestream(fs);
02402             ast_agi_send(agi->fd, chan, "200 result=%d (waitfor) endpos=%ld\n", res,sample_offset);
02403             if (sildet)
02404                ast_dsp_free(sildet);
02405             return RESULT_FAILURE;
02406          }
02407          f = ast_read(chan);
02408          if (!f) {
02409             ast_agi_send(agi->fd, chan, "200 result=%d (hangup) endpos=%ld\n", -1, sample_offset);
02410             ast_closestream(fs);
02411             if (sildet)
02412                ast_dsp_free(sildet);
02413             return RESULT_FAILURE;
02414          }
02415          switch(f->frametype) {
02416          case AST_FRAME_DTMF:
02417             if (strchr(argv[4], f->subclass.integer)) {
02418                /* This is an interrupting chracter, so rewind to chop off any small
02419                   amount of DTMF that may have been recorded
02420                */
02421                ast_stream_rewind(fs, 200);
02422                ast_truncstream(fs);
02423                sample_offset = ast_tellstream(fs);
02424                ast_agi_send(agi->fd, chan, "200 result=%d (dtmf) endpos=%ld\n", f->subclass.integer, sample_offset);
02425                ast_closestream(fs);
02426                ast_frfree(f);
02427                if (sildet)
02428                   ast_dsp_free(sildet);
02429                return RESULT_SUCCESS;
02430             }
02431             break;
02432          case AST_FRAME_VOICE:
02433             ast_writestream(fs, f);
02434             /* this is a safe place to check progress since we know that fs
02435              * is valid after a write, and it will then have our current
02436              * location */
02437             sample_offset = ast_tellstream(fs);
02438             if (silence > 0) {
02439                dspsilence = 0;
02440                ast_dsp_silence(sildet, f, &dspsilence);
02441                if (dspsilence) {
02442                   totalsilence = dspsilence;
02443                } else {
02444                   totalsilence = 0;
02445                }
02446                if (totalsilence > silence) {
02447                   /* Ended happily with silence */
02448                   gotsilence = 1;
02449                   break;
02450                }
02451             }
02452             break;
02453          case AST_FRAME_VIDEO:
02454             ast_writestream(fs, f);
02455          default:
02456             /* Ignore all other frames */
02457             break;
02458          }
02459          ast_frfree(f);
02460          if (gotsilence)
02461             break;
02462       }
02463 
02464       if (gotsilence) {
02465          ast_stream_rewind(fs, silence-1000);
02466          ast_truncstream(fs);
02467          sample_offset = ast_tellstream(fs);
02468       }
02469       ast_agi_send(agi->fd, chan, "200 result=%d (timeout) endpos=%ld\n", res, sample_offset);
02470       ast_closestream(fs);
02471    }
02472 
02473    if (silence > 0) {
02474       res = ast_set_read_format(chan, &rfmt);
02475       if (res)
02476          ast_log(LOG_WARNING, "Unable to restore read format on '%s'\n", ast_channel_name(chan));
02477       ast_dsp_free(sildet);
02478    }
02479 
02480    return RESULT_SUCCESS;
02481 }
02482 
02483 static int handle_autohangup(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
02484 {
02485    double timeout;
02486    struct timeval whentohangup = { 0, 0 };
02487 
02488    if (argc != 3)
02489       return RESULT_SHOWUSAGE;
02490    if (sscanf(argv[2], "%30lf", &timeout) != 1)
02491       return RESULT_SHOWUSAGE;
02492    if (timeout < 0)
02493       timeout = 0;
02494    if (timeout) {
02495       whentohangup.tv_sec = timeout;
02496       whentohangup.tv_usec = (timeout - whentohangup.tv_sec) * 1000000.0;
02497    }
02498    ast_channel_setwhentohangup_tv(chan, whentohangup);
02499    ast_agi_send(agi->fd, chan, "200 result=0\n");
02500    return RESULT_SUCCESS;
02501 }
02502 
02503 static int handle_hangup(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
02504 {
02505    struct ast_channel *c;
02506 
02507    if (argc == 1) {
02508       /* no argument: hangup the current channel */
02509       ast_set_hangupsource(chan, "dialplan/agi", 0);
02510       ast_softhangup(chan,AST_SOFTHANGUP_EXPLICIT);
02511       ast_agi_send(agi->fd, chan, "200 result=1\n");
02512       return RESULT_SUCCESS;
02513    } else if (argc == 2) {
02514       /* one argument: look for info on the specified channel */
02515       if ((c = ast_channel_get_by_name(argv[1]))) {
02516          /* we have a matching channel */
02517          ast_set_hangupsource(c, "dialplan/agi", 0);
02518          ast_softhangup(c, AST_SOFTHANGUP_EXPLICIT);
02519          c = ast_channel_unref(c);
02520          ast_agi_send(agi->fd, chan, "200 result=1\n");
02521          return RESULT_SUCCESS;
02522       }
02523       /* if we get this far no channel name matched the argument given */
02524       ast_agi_send(agi->fd, chan, "200 result=-1\n");
02525       return RESULT_SUCCESS;
02526    } else {
02527       return RESULT_SHOWUSAGE;
02528    }
02529 }
02530 
02531 static int handle_exec(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
02532 {
02533    int res, workaround;
02534    struct ast_app *app_to_exec;
02535 
02536    if (argc < 2)
02537       return RESULT_SHOWUSAGE;
02538 
02539    ast_verb(3, "AGI Script Executing Application: (%s) Options: (%s)\n", argv[1], argc >= 3 ? argv[2] : "");
02540 
02541    if ((app_to_exec = pbx_findapp(argv[1]))) {
02542       if (!(workaround = ast_test_flag(ast_channel_flags(chan), AST_FLAG_DISABLE_WORKAROUNDS))) {
02543          ast_set_flag(ast_channel_flags(chan), AST_FLAG_DISABLE_WORKAROUNDS);
02544       }
02545       if (ast_compat_res_agi && argc >= 3 && !ast_strlen_zero(argv[2])) {
02546          char *compat = ast_alloca(strlen(argv[2]) * 2 + 1), *cptr;
02547          const char *vptr;
02548          for (cptr = compat, vptr = argv[2]; *vptr; vptr++) {
02549             if (*vptr == ',') {
02550                *cptr++ = '\\';
02551                *cptr++ = ',';
02552             } else if (*vptr == '|') {
02553                *cptr++ = ',';
02554             } else {
02555                *cptr++ = *vptr;
02556             }
02557          }
02558          *cptr = '\0';
02559          res = pbx_exec(chan, app_to_exec, compat);
02560       } else {
02561          res = pbx_exec(chan, app_to_exec, argc == 2 ? "" : argv[2]);
02562       }
02563       if (!workaround) {
02564          ast_clear_flag(ast_channel_flags(chan), AST_FLAG_DISABLE_WORKAROUNDS);
02565       }
02566    } else {
02567       ast_log(LOG_WARNING, "Could not find application (%s)\n", argv[1]);
02568       res = -2;
02569    }
02570    ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
02571 
02572    /* Even though this is wrong, users are depending upon this result. */
02573    return res;
02574 }
02575 
02576 static int handle_setcallerid(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
02577 {
02578    char tmp[256]="";
02579    char *l = NULL, *n = NULL;
02580 
02581    if (argv[2]) {
02582       ast_copy_string(tmp, argv[2], sizeof(tmp));
02583       ast_callerid_parse(tmp, &n, &l);
02584       if (l)
02585          ast_shrink_phone_number(l);
02586       else
02587          l = "";
02588       if (!n)
02589          n = "";
02590       ast_set_callerid(chan, l, n, NULL);
02591    }
02592 
02593    ast_agi_send(agi->fd, chan, "200 result=1\n");
02594    return RESULT_SUCCESS;
02595 }
02596 
02597 static int handle_channelstatus(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
02598 {
02599    struct ast_channel *c;
02600    if (argc == 2) {
02601       /* no argument: supply info on the current channel */
02602       ast_agi_send(agi->fd, chan, "200 result=%d\n", ast_channel_state(chan));
02603       return RESULT_SUCCESS;
02604    } else if (argc == 3) {
02605       /* one argument: look for info on the specified channel */
02606       if ((c = ast_channel_get_by_name(argv[2]))) {
02607          ast_agi_send(agi->fd, chan, "200 result=%d\n", ast_channel_state(c));
02608          c = ast_channel_unref(c);
02609          return RESULT_SUCCESS;
02610       }
02611       /* if we get this far no channel name matched the argument given */
02612       ast_agi_send(agi->fd, chan, "200 result=-1\n");
02613       return RESULT_SUCCESS;
02614    } else {
02615       return RESULT_SHOWUSAGE;
02616    }
02617 }
02618 
02619 static int handle_setvariable(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
02620 {
02621    if (argv[3])
02622       pbx_builtin_setvar_helper(chan, argv[2], argv[3]);
02623 
02624    ast_agi_send(agi->fd, chan, "200 result=1\n");
02625    return RESULT_SUCCESS;
02626 }
02627 
02628 static int handle_getvariable(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
02629 {
02630    char *ret;
02631    char tempstr[1024] = "";
02632 
02633    if (argc != 3)
02634       return RESULT_SHOWUSAGE;
02635 
02636    /* check if we want to execute an ast_custom_function */
02637    if (!ast_strlen_zero(argv[2]) && (argv[2][strlen(argv[2]) - 1] == ')')) {
02638       ret = ast_func_read(chan, argv[2], tempstr, sizeof(tempstr)) ? NULL : tempstr;
02639    } else {
02640       pbx_retrieve_variable(chan, argv[2], &ret, tempstr, sizeof(tempstr), NULL);
02641    }
02642 
02643    if (ret)
02644       ast_agi_send(agi->fd, chan, "200 result=1 (%s)\n", ret);
02645    else
02646       ast_agi_send(agi->fd, chan, "200 result=0\n");
02647 
02648    return RESULT_SUCCESS;
02649 }
02650 
02651 static int handle_getvariablefull(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
02652 {
02653    struct ast_channel *chan2 = NULL;
02654 
02655    if (argc != 4 && argc != 5) {
02656       return RESULT_SHOWUSAGE;
02657    }
02658 
02659    if (argc == 5) {
02660       chan2 = ast_channel_get_by_name(argv[4]);
02661    } else {
02662       chan2 = ast_channel_ref(chan);
02663    }
02664 
02665    if (chan2) {
02666       struct ast_str *str = ast_str_create(16);
02667       if (!str) {
02668          ast_agi_send(agi->fd, chan, "200 result=0\n");
02669          return RESULT_SUCCESS;
02670       }
02671       ast_str_substitute_variables(&str, 0, chan2, argv[3]);
02672       ast_agi_send(agi->fd, chan, "200 result=1 (%s)\n", ast_str_buffer(str));
02673       ast_free(str);
02674    } else {
02675       ast_agi_send(agi->fd, chan, "200 result=0\n");
02676    }
02677 
02678    if (chan2) {
02679       chan2 = ast_channel_unref(chan2);
02680    }
02681 
02682    return RESULT_SUCCESS;
02683 }
02684 
02685 static int handle_verbose(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
02686 {
02687    int level = 0;
02688 
02689    if (argc < 2)
02690       return RESULT_SHOWUSAGE;
02691 
02692    if (argv[2])
02693       sscanf(argv[2], "%30d", &level);
02694 
02695    ast_verb(level, "%s: %s\n", ast_channel_data(chan), argv[1]);
02696 
02697    ast_agi_send(agi->fd, chan, "200 result=1\n");
02698 
02699    return RESULT_SUCCESS;
02700 }
02701 
02702 static int handle_dbget(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
02703 {
02704    int res;
02705    struct ast_str *buf;
02706 
02707    if (argc != 4)
02708       return RESULT_SHOWUSAGE;
02709 
02710    if (!(buf = ast_str_create(16))) {
02711       ast_agi_send(agi->fd, chan, "200 result=-1\n");
02712       return RESULT_SUCCESS;
02713    }
02714 
02715    do {
02716       res = ast_db_get(argv[2], argv[3], ast_str_buffer(buf), ast_str_size(buf));
02717       ast_str_update(buf);
02718       if (ast_str_strlen(buf) < ast_str_size(buf) - 1) {
02719          break;
02720       }
02721       if (ast_str_make_space(&buf, ast_str_size(buf) * 2)) {
02722          break;
02723       }
02724    } while (1);
02725    
02726    if (res)
02727       ast_agi_send(agi->fd, chan, "200 result=0\n");
02728    else
02729       ast_agi_send(agi->fd, chan, "200 result=1 (%s)\n", ast_str_buffer(buf));
02730 
02731    ast_free(buf);
02732    return RESULT_SUCCESS;
02733 }
02734 
02735 static int handle_dbput(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
02736 {
02737    int res;
02738 
02739    if (argc != 5)
02740       return RESULT_SHOWUSAGE;
02741    res = ast_db_put(argv[2], argv[3], argv[4]);
02742    ast_agi_send(agi->fd, chan, "200 result=%c\n", res ? '0' : '1');
02743    return RESULT_SUCCESS;
02744 }
02745 
02746 static int handle_dbdel(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
02747 {
02748    int res;
02749 
02750    if (argc != 4)
02751       return RESULT_SHOWUSAGE;
02752    res = ast_db_del(argv[2], argv[3]);
02753    ast_agi_send(agi->fd, chan, "200 result=%c\n", res ? '0' : '1');
02754    return RESULT_SUCCESS;
02755 }
02756 
02757 static int handle_dbdeltree(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
02758 {
02759    int num_deleted;
02760 
02761    if ((argc < 3) || (argc > 4)) {
02762       return RESULT_SHOWUSAGE;
02763    }
02764    if (argc == 4) {
02765       num_deleted = ast_db_deltree(argv[2], argv[3]);
02766    } else {
02767       num_deleted = ast_db_deltree(argv[2], NULL);
02768    }
02769 
02770    ast_agi_send(agi->fd, chan, "200 result=%c\n", num_deleted > 0 ? '0' : '1');
02771    return RESULT_SUCCESS;
02772 }
02773 
02774 static char *handle_cli_agi_debug(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
02775 {
02776    switch (cmd) {
02777    case CLI_INIT:
02778       e->command = "agi set debug [on|off]";
02779       e->usage =
02780          "Usage: agi set debug [on|off]\n"
02781          "       Enables/disables dumping of AGI transactions for\n"
02782          "       debugging purposes.\n";
02783       return NULL;
02784 
02785    case CLI_GENERATE:
02786       return NULL;
02787    }
02788 
02789    if (a->argc != e->args)
02790       return CLI_SHOWUSAGE;
02791 
02792    if (strncasecmp(a->argv[3], "off", 3) == 0) {
02793       agidebug = 0;
02794    } else if (strncasecmp(a->argv[3], "on", 2) == 0) {
02795       agidebug = 1;
02796    } else {
02797       return CLI_SHOWUSAGE;
02798    }
02799    ast_cli(a->fd, "AGI Debugging %sabled\n", agidebug ? "En" : "Dis");
02800    return CLI_SUCCESS;
02801 }
02802 
02803 static int handle_noop(struct ast_channel *chan, AGI *agi, int arg, const char * const argv[])
02804 {
02805    ast_agi_send(agi->fd, chan, "200 result=0\n");
02806    return RESULT_SUCCESS;
02807 }
02808 
02809 static int handle_setmusic(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
02810 {
02811    if (argc < 3) {
02812       return RESULT_SHOWUSAGE;
02813    }
02814    if (!strncasecmp(argv[2], "on", 2))
02815       ast_moh_start(chan, argc > 3 ? argv[3] : NULL, NULL);
02816    else if (!strncasecmp(argv[2], "off", 3))
02817       ast_moh_stop(chan);
02818    ast_agi_send(agi->fd, chan, "200 result=0\n");
02819    return RESULT_SUCCESS;
02820 }
02821 
02822 static int handle_speechcreate(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
02823 {
02824    struct ast_format_cap *cap;
02825    struct ast_format tmpfmt;
02826 
02827    /* If a structure already exists, return an error */
02828    if (agi->speech) {
02829       ast_agi_send(agi->fd, chan, "200 result=0\n");
02830       return RESULT_SUCCESS;
02831    }
02832 
02833    if (!(cap = ast_format_cap_alloc_nolock())) {
02834       return RESULT_FAILURE;
02835    }
02836    ast_format_cap_add(cap, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0));
02837    if ((agi->speech = ast_speech_new(argv[2], cap))) {
02838       ast_agi_send(agi->fd, chan, "200 result=1\n");
02839    } else {
02840       ast_agi_send(agi->fd, chan, "200 result=0\n");
02841    }
02842    cap = ast_format_cap_destroy(cap);
02843 
02844    return RESULT_SUCCESS;
02845 }
02846 
02847 static int handle_speechset(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
02848 {
02849    /* Check for minimum arguments */
02850    if (argc != 4)
02851       return RESULT_SHOWUSAGE;
02852 
02853    /* Check to make sure speech structure exists */
02854    if (!agi->speech) {
02855       ast_agi_send(agi->fd, chan, "200 result=0\n");
02856       return RESULT_SUCCESS;
02857    }
02858 
02859    ast_speech_change(agi->speech, argv[2], argv[3]);
02860    ast_agi_send(agi->fd, chan, "200 result=1\n");
02861 
02862    return RESULT_SUCCESS;
02863 }
02864 
02865 static int handle_speechdestroy(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
02866 {
02867    if (agi->speech) {
02868       ast_speech_destroy(agi->speech);
02869       agi->speech = NULL;
02870       ast_agi_send(agi->fd, chan, "200 result=1\n");
02871    } else {
02872       ast_agi_send(agi->fd, chan, "200 result=0\n");
02873    }
02874 
02875    return RESULT_SUCCESS;
02876 }
02877 
02878 static int handle_speechloadgrammar(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
02879 {
02880    if (argc != 5)
02881       return RESULT_SHOWUSAGE;
02882 
02883    if (!agi->speech) {
02884       ast_agi_send(agi->fd, chan, "200 result=0\n");
02885       return RESULT_SUCCESS;
02886    }
02887 
02888    if (ast_speech_grammar_load(agi->speech, argv[3], argv[4]))
02889       ast_agi_send(agi->fd, chan, "200 result=0\n");
02890    else
02891       ast_agi_send(agi->fd, chan, "200 result=1\n");
02892 
02893    return RESULT_SUCCESS;
02894 }
02895 
02896 static int handle_speechunloadgrammar(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
02897 {
02898    if (argc != 4)
02899       return RESULT_SHOWUSAGE;
02900 
02901    if (!agi->speech) {
02902       ast_agi_send(agi->fd, chan, "200 result=0\n");
02903       return RESULT_SUCCESS;
02904    }
02905 
02906    if (ast_speech_grammar_unload(agi->speech, argv[3]))
02907       ast_agi_send(agi->fd, chan, "200 result=0\n");
02908    else
02909       ast_agi_send(agi->fd, chan, "200 result=1\n");
02910 
02911    return RESULT_SUCCESS;
02912 }
02913 
02914 static int handle_speechactivategrammar(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
02915 {
02916    if (argc != 4)
02917       return RESULT_SHOWUSAGE;
02918 
02919    if (!agi->speech) {
02920       ast_agi_send(agi->fd, chan, "200 result=0\n");
02921       return RESULT_SUCCESS;
02922    }
02923 
02924    if (ast_speech_grammar_activate(agi->speech, argv[3]))
02925       ast_agi_send(agi->fd, chan, "200 result=0\n");
02926    else
02927       ast_agi_send(agi->fd, chan, "200 result=1\n");
02928 
02929    return RESULT_SUCCESS;
02930 }
02931 
02932 static int handle_speechdeactivategrammar(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
02933 {
02934    if (argc != 4)
02935       return RESULT_SHOWUSAGE;
02936 
02937    if (!agi->speech) {
02938       ast_agi_send(agi->fd, chan, "200 result=0\n");
02939       return RESULT_SUCCESS;
02940    }
02941 
02942    if (ast_speech_grammar_deactivate(agi->speech, argv[3]))
02943       ast_agi_send(agi->fd, chan, "200 result=0\n");
02944    else
02945       ast_agi_send(agi->fd, chan, "200 result=1\n");
02946 
02947    return RESULT_SUCCESS;
02948 }
02949 
02950 static int speech_streamfile(struct ast_channel *chan, const char *filename, const char *preflang, int offset)
02951 {
02952    struct ast_filestream *fs = NULL;
02953 
02954    if (!(fs = ast_openstream(chan, filename, preflang)))
02955       return -1;
02956 
02957    if (offset)
02958       ast_seekstream(fs, offset, SEEK_SET);
02959 
02960    if (ast_applystream(chan, fs))
02961       return -1;
02962 
02963    if (ast_playstream(fs))
02964       return -1;
02965 
02966    return 0;
02967 }
02968 
02969 static int handle_speechrecognize(struct ast_channel *chan, AGI *agi, int argc, const char * const argv[])
02970 {
02971    struct ast_speech *speech = agi->speech;
02972    const char *prompt;
02973    char dtmf = 0, tmp[4096] = "", *buf = tmp;
02974    int timeout = 0, offset = 0, res = 0, i = 0;
02975    struct ast_format old_read_format;
02976    long current_offset = 0;
02977    const char *reason = NULL;
02978    struct ast_frame *fr = NULL;
02979    struct ast_speech_result *result = NULL;
02980    size_t left = sizeof(tmp);
02981    time_t start = 0, current;
02982 
02983    if (argc < 4)
02984       return RESULT_SHOWUSAGE;
02985 
02986    if (!speech) {
02987       ast_agi_send(agi->fd, chan, "200 result=0\n");
02988       return RESULT_SUCCESS;
02989    }
02990 
02991    prompt = argv[2];
02992    timeout = atoi(argv[3]);
02993 
02994    /* If offset is specified then convert from text to integer */
02995    if (argc == 5)
02996       offset = atoi(argv[4]);
02997 
02998    /* We want frames coming in signed linear */
02999    ast_format_copy(&old_read_format, ast_channel_readformat(chan));
03000    if (ast_set_read_format_by_id(chan, AST_FORMAT_SLINEAR)) {
03001       ast_agi_send(agi->fd, chan, "200 result=0\n");
03002       return RESULT_SUCCESS;
03003    }
03004 
03005    /* Setup speech structure */
03006    if (speech->state == AST_SPEECH_STATE_NOT_READY || speech->state == AST_SPEECH_STATE_DONE) {
03007       ast_speech_change_state(speech, AST_SPEECH_STATE_NOT_READY);
03008       ast_speech_start(speech);
03009    }
03010 
03011    /* Start playing prompt */
03012    speech_streamfile(chan, prompt, ast_channel_language(chan), offset);
03013 
03014    /* Go into loop reading in frames, passing to speech thingy, checking for hangup, all that jazz */
03015    while (ast_strlen_zero(reason)) {
03016       /* Run scheduled items */
03017                 ast_sched_runq(ast_channel_sched(chan));
03018 
03019       /* See maximum time of waiting */
03020       if ((res = ast_sched_wait(ast_channel_sched(chan))) < 0)
03021          res = 1000;
03022 
03023       /* Wait for frame */
03024       if (ast_waitfor(chan, res) > 0) {
03025          if (!(fr = ast_read(chan))) {
03026             reason = "hangup";
03027             break;
03028          }
03029       }
03030 
03031       /* Perform timeout check */
03032       if ((timeout > 0) && (start > 0)) {
03033          time(&current);
03034          if ((current - start) >= timeout) {
03035             reason = "timeout";
03036             if (fr)
03037                ast_frfree(fr);
03038             break;
03039          }
03040       }
03041 
03042       /* Check the speech structure for any changes */
03043       ast_mutex_lock(&speech->lock);
03044 
03045       /* See if we need to quiet the audio stream playback */
03046       if (ast_test_flag(speech, AST_SPEECH_QUIET) && ast_channel_stream(chan)) {
03047          current_offset = ast_tellstream(ast_channel_stream(chan));
03048          ast_stopstream(chan);
03049          ast_clear_flag(speech, AST_SPEECH_QUIET);
03050       }
03051 
03052       /* Check each state */
03053       switch (speech->state) {
03054       case AST_SPEECH_STATE_READY:
03055          /* If the stream is done, start timeout calculation */
03056          if ((timeout > 0) && start == 0 && ((!ast_channel_stream(chan)) || (ast_channel_streamid(chan) == -1 && ast_channel_timingfunc(chan) == NULL))) {
03057             ast_stopstream(chan);
03058             time(&start);
03059          }
03060          /* Write audio frame data into speech engine if possible */
03061          if (fr && fr->frametype == AST_FRAME_VOICE)
03062             ast_speech_write(speech, fr->data.ptr, fr->datalen);
03063          break;
03064       case AST_SPEECH_STATE_WAIT:
03065          /* Cue waiting sound if not already playing */
03066          if ((!ast_channel_stream(chan)) || (ast_channel_streamid(chan) == -1 && ast_channel_timingfunc(chan) == NULL)) {
03067             ast_stopstream(chan);
03068             /* If a processing sound exists, or is not none - play it */
03069             if (!ast_strlen_zero(speech->processing_sound) && strcasecmp(speech->processing_sound, "none"))
03070                speech_streamfile(chan, speech->processing_sound, ast_channel_language(chan), 0);
03071          }
03072          break;
03073       case AST_SPEECH_STATE_DONE:
03074          /* Get the results */
03075          speech->results = ast_speech_results_get(speech);
03076          /* Change state to not ready */
03077          ast_speech_change_state(speech, AST_SPEECH_STATE_NOT_READY);
03078          reason = "speech";
03079          break;
03080       default:
03081          break;
03082       }
03083       ast_mutex_unlock(&speech->lock);
03084 
03085       /* Check frame for DTMF or hangup */
03086       if (fr) {
03087          if (fr->frametype == AST_FRAME_DTMF) {
03088             reason = "dtmf";
03089             dtmf = fr->subclass.integer;
03090          } else if (fr->frametype == AST_FRAME_CONTROL && fr->subclass.integer == AST_CONTROL_HANGUP) {
03091             reason = "hangup";
03092          }
03093          ast_frfree(fr);
03094       }
03095    }
03096 
03097    if (!strcasecmp(reason, "speech")) {
03098       /* Build string containing speech results */
03099                 for (result = speech->results; result; result = AST_LIST_NEXT(result, list)) {
03100          /* Build result string */
03101          ast_build_string(&buf, &left, "%sscore%d=%d text%d=\"%s\" grammar%d=%s", (i > 0 ? " " : ""), i, result->score, i, result->text, i, result->grammar);
03102                         /* Increment result count */
03103          i++;
03104       }
03105                 /* Print out */
03106       ast_agi_send(agi->fd, chan, "200 result=1 (speech) endpos=%ld results=%d %s\n", current_offset, i, tmp);
03107    } else if (!strcasecmp(reason, "dtmf")) {
03108       ast_agi_send(agi->fd, chan, "200 result=1 (digit) digit=%c endpos=%ld\n", dtmf, current_offset);
03109    } else if (!strcasecmp(reason, "hangup") || !strcasecmp(reason, "timeout")) {
03110       ast_agi_send(agi->fd, chan, "200 result=1 (%s) endpos=%ld\n", reason, current_offset);
03111    } else {
03112       ast_agi_send(agi->fd, chan, "200 result=0 endpos=%ld\n", current_offset);
03113    }
03114 
03115    return RESULT_SUCCESS;
03116 }
03117 
03118 /*!
03119  * \brief AGI commands list
03120  */
03121 static struct agi_command commands[] = {
03122    { { "answer", NULL }, handle_answer, NULL, NULL, 0 },
03123    { { "asyncagi", "break", NULL }, handle_asyncagi_break, NULL, NULL, 1 },
03124    { { "channel", "status", NULL }, handle_channelstatus, NULL, NULL, 0 },
03125    { { "database", "del", NULL }, handle_dbdel, NULL, NULL, 1 },
03126    { { "database", "deltree", NULL }, handle_dbdeltree, NULL, NULL, 1 },
03127    { { "database", "get", NULL }, handle_dbget, NULL, NULL, 1 },
03128    { { "database", "put", NULL }, handle_dbput, NULL, NULL, 1 },
03129    { { "exec", NULL }, handle_exec, NULL, NULL, 1 },
03130    { { "get", "data", NULL }, handle_getdata, NULL, NULL, 0 },
03131    { { "get", "full", "variable", NULL }, handle_getvariablefull, NULL, NULL, 1 },
03132    { { "get", "option", NULL }, handle_getoption, NULL, NULL, 0 },
03133    { { "get", "variable", NULL }, handle_getvariable, NULL, NULL, 1 },
03134    { { "hangup", NULL }, handle_hangup, NULL, NULL, 0 },
03135    { { "noop", NULL }, handle_noop, NULL, NULL, 1 },
03136    { { "receive", "char", NULL }, handle_recvchar, NULL, NULL, 0 },
03137    { { "receive", "text", NULL }, handle_recvtext, NULL, NULL, 0 },
03138    { { "record", "file", NULL }, handle_recordfile, NULL, NULL, 0 }, 
03139    { { "say", "alpha", NULL }, handle_sayalpha, NULL, NULL, 0},
03140    { { "say", "digits", NULL }, handle_saydigits, NULL, NULL, 0 },
03141    { { "say", "number", NULL }, handle_saynumber, NULL, NULL, 0 },
03142    { { "say", "phonetic", NULL }, handle_sayphonetic, NULL, NULL, 0}, 
03143    { { "say", "date", NULL }, handle_saydate, NULL, NULL, 0}, 
03144    { { "say", "time", NULL }, handle_saytime, NULL, NULL, 0}, 
03145    { { "say", "datetime", NULL }, handle_saydatetime, NULL, NULL, 0},
03146    { { "send", "image", NULL }, handle_sendimage, NULL, NULL, 0}, 
03147    { { "send", "text", NULL }, handle_sendtext, NULL, NULL, 0},
03148    { { "set", "autohangup", NULL }, handle_autohangup, NULL, NULL, 0},
03149    { { "set", "callerid", NULL }, handle_setcallerid, NULL, NULL, 0},
03150    { { "set", "context", NULL }, handle_setcontext, NULL, NULL, 0},
03151    { { "set", "extension", NULL }, handle_setextension, NULL, NULL, 0},
03152    { { "set", "music", NULL }, handle_setmusic, NULL, NULL, 0 },
03153    { { "set", "priority", NULL }, handle_setpriority, NULL, NULL, 0 },
03154    { { "set", "variable", NULL }, handle_setvariable, NULL, NULL, 1 },
03155    { { "stream", "file", NULL }, handle_streamfile, NULL, NULL, 0 },
03156    { { "control", "stream", "file", NULL }, handle_controlstreamfile, NULL, NULL, 0 },
03157    { { "tdd", "mode", NULL }, handle_tddmode, NULL, NULL, 0 },
03158    { { "verbose", NULL }, handle_verbose, NULL, NULL, 1 },
03159    { { "wait", "for", "digit", NULL }, handle_waitfordigit, NULL, NULL, 0 },
03160    { { "speech", "create", NULL }, handle_speechcreate, NULL, NULL, 0 },
03161    { { "speech", "set", NULL }, handle_speechset, NULL, NULL, 0 },
03162    { { "speech", "destroy", NULL }, handle_speechdestroy, NULL, NULL, 1 },
03163    { { "speech", "load", "grammar", NULL }, handle_speechloadgrammar, NULL, NULL, 0 },
03164    { { "speech", "unload", "grammar", NULL }, handle_speechunloadgrammar, NULL, NULL, 1 },
03165    { { "speech", "activate", "grammar", NULL }, handle_speechactivategrammar, NULL, NULL, 0 },
03166    { { "speech", "deactivate", "grammar", NULL }, handle_speechdeactivategrammar, NULL, NULL, 0 },
03167    { { "speech", "recognize", NULL }, handle_speechrecognize, NULL, NULL, 0 },
03168 };
03169 
03170 static AST_RWLIST_HEAD_STATIC(agi_commands, agi_command);
03171 
03172 static char *help_workhorse(int fd, const char * const match[])
03173 {
03174    char fullcmd[MAX_CMD_LEN], matchstr[MAX_CMD_LEN];
03175    struct agi_command *e;
03176 
03177    if (match)
03178       ast_join(matchstr, sizeof(matchstr), match);
03179 
03180    ast_cli(fd, "%5.5s %30.30s   %s\n","Dead","Command","Description");
03181    AST_RWLIST_RDLOCK(&agi_commands);
03182    AST_RWLIST_TRAVERSE(&agi_commands, e, list) {
03183       if (!e->cmda[0])
03184          break;
03185       /* Hide commands that start with '_' */
03186       if ((e->cmda[0])[0] == '_')
03187          continue;
03188       ast_join(fullcmd, sizeof(fullcmd), e->cmda);
03189       if (match && strncasecmp(matchstr, fullcmd, strlen(matchstr)))
03190          continue;
03191       ast_cli(fd, "%5.5s %30.30s   %s\n", e->dead ? "Yes" : "No" , fullcmd, S_OR(e->summary, "Not available"));
03192    }
03193    AST_RWLIST_UNLOCK(&agi_commands);
03194 
03195    return CLI_SUCCESS;
03196 }
03197 
03198 int AST_OPTIONAL_API_NAME(ast_agi_register)(struct ast_module *mod, agi_command *cmd)
03199 {
03200    char fullcmd[MAX_CMD_LEN];
03201 
03202    ast_join(fullcmd, sizeof(fullcmd), cmd->cmda);
03203 
03204    if (!find_command(cmd->cmda, 1)) {
03205       *((enum ast_doc_src *) &cmd->docsrc) = AST_STATIC_DOC;
03206       if (ast_strlen_zero(cmd->summary) && ast_strlen_zero(cmd->usage)) {
03207 #ifdef AST_XML_DOCS
03208          *((char **) &cmd->summary) = ast_xmldoc_build_synopsis("agi", fullcmd, NULL);
03209          *((char **) &cmd->usage) = ast_xmldoc_build_description("agi", fullcmd, NULL);
03210          *((char **) &cmd->syntax) = ast_xmldoc_build_syntax("agi", fullcmd, NULL);
03211          *((char **) &cmd->seealso) = ast_xmldoc_build_seealso("agi", fullcmd, NULL);
03212          *((enum ast_doc_src *) &cmd->docsrc) = AST_XML_DOC;
03213 #endif
03214 #ifndef HAVE_NULLSAFE_PRINTF
03215          if (!cmd->summary) {
03216             *((char **) &cmd->summary) = ast_strdup("");
03217          }
03218          if (!cmd->usage) {
03219             *((char **) &cmd->usage) = ast_strdup("");
03220          }
03221          if (!cmd->syntax) {
03222             *((char **) &cmd->syntax) = ast_strdup("");
03223          }
03224          if (!cmd->seealso) {
03225             *((char **) &cmd->seealso) = ast_strdup("");
03226          }
03227 #endif
03228       }
03229 
03230       cmd->mod = mod;
03231       AST_RWLIST_WRLOCK(&agi_commands);
03232       AST_LIST_INSERT_TAIL(&agi_commands, cmd, list);
03233       AST_RWLIST_UNLOCK(&agi_commands);
03234       if (mod != ast_module_info->self)
03235          ast_module_ref(ast_module_info->self);
03236       ast_verb(2, "AGI Command '%s' registered\n",fullcmd);
03237       return 1;
03238    } else {
03239       ast_log(LOG_WARNING, "Command already registered!\n");
03240       return 0;
03241    }
03242 }
03243 
03244 int AST_OPTIONAL_API_NAME(ast_agi_unregister)(struct ast_module *mod, agi_command *cmd)
03245 {
03246    struct agi_command *e;
03247    int unregistered = 0;
03248    char fullcmd[MAX_CMD_LEN];
03249 
03250    ast_join(fullcmd, sizeof(fullcmd), cmd->cmda);
03251 
03252    AST_RWLIST_WRLOCK(&agi_commands);
03253    AST_RWLIST_TRAVERSE_SAFE_BEGIN(&agi_commands, e, list) {
03254       if (cmd == e) {
03255          AST_RWLIST_REMOVE_CURRENT(list);
03256          if (mod != ast_module_info->self)
03257             ast_module_unref(ast_module_info->self);
03258 #ifdef AST_XML_DOCS
03259          if (e->docsrc == AST_XML_DOC) {
03260             ast_free((char *) e->summary);
03261             ast_free((char *) e->usage);
03262             ast_free((char *) e->syntax);
03263             ast_free((char *) e->seealso);
03264             *((char **) &e->summary) = NULL;
03265             *((char **) &e->usage) = NULL;
03266             *((char **) &e->syntax) = NULL;
03267             *((char **) &e->seealso) = NULL;
03268          }
03269 #endif
03270          unregistered=1;
03271          break;
03272       }
03273    }
03274    AST_RWLIST_TRAVERSE_SAFE_END;
03275    AST_RWLIST_UNLOCK(&agi_commands);
03276    if (unregistered)
03277       ast_verb(2, "AGI Command '%s' unregistered\n",fullcmd);
03278    else
03279       ast_log(LOG_WARNING, "Unable to unregister command: '%s'!\n",fullcmd);
03280    return unregistered;
03281 }
03282 
03283 int AST_OPTIONAL_API_NAME(ast_agi_register_multiple)(struct ast_module *mod, struct agi_command *cmd, unsigned int len)
03284 {
03285    unsigned int i, x = 0;
03286 
03287    for (i = 0; i < len; i++) {
03288       if (ast_agi_register(mod, cmd + i) == 1) {
03289          x++;
03290          continue;
03291       }
03292 
03293       /* registration failed, unregister everything
03294          that had been registered up to that point
03295       */
03296       for (; x > 0; x--) {
03297          /* we are intentionally ignoring the
03298             result of ast_agi_unregister() here,
03299             but it should be safe to do so since
03300             we just registered these commands and
03301             the only possible way for unregistration
03302             to fail is if the command is not
03303             registered
03304          */
03305          (void) ast_agi_unregister(mod, cmd + x - 1);
03306       }
03307       return -1;
03308    }
03309 
03310    return 0;
03311 }
03312 
03313 int AST_OPTIONAL_API_NAME(ast_agi_unregister_multiple)(struct ast_module *mod, struct agi_command *cmd, unsigned int len)
03314 {
03315    unsigned int i;
03316    int res = 0;
03317 
03318    for (i = 0; i < len; i++) {
03319       /* remember whether any of the unregistration
03320          attempts failed... there is no recourse if
03321          any of them do
03322       */
03323       res |= ast_agi_unregister(mod, cmd + i);
03324    }
03325 
03326    return res;
03327 }
03328 
03329 static agi_command *find_command(const char * const cmds[], int exact)
03330 {
03331    int y, match;
03332    struct agi_command *e;
03333 
03334    AST_RWLIST_RDLOCK(&agi_commands);
03335    AST_RWLIST_TRAVERSE(&agi_commands, e, list) {
03336       if (!e->cmda[0])
03337          break;
03338       /* start optimistic */
03339       match = 1;
03340       for (y = 0; match && cmds[y]; y++) {
03341          /* If there are no more words in the command (and we're looking for
03342             an exact match) or there is a difference between the two words,
03343             then this is not a match */
03344          if (!e->cmda[y] && !exact)
03345             break;
03346          /* don't segfault if the next part of a command doesn't exist */
03347          if (!e->cmda[y]) {
03348             AST_RWLIST_UNLOCK(&agi_commands);
03349             return NULL;
03350          }
03351          if (strcasecmp(e->cmda[y], cmds[y]))
03352             match = 0;
03353       }
03354       /* If more words are needed to complete the command then this is not
03355          a candidate (unless we're looking for a really inexact answer  */
03356       if ((exact > -1) && e->cmda[y])
03357          match = 0;
03358       if (match) {
03359          AST_RWLIST_UNLOCK(&agi_commands);
03360          return e;
03361       }
03362    }
03363    AST_RWLIST_UNLOCK(&agi_commands);
03364    return NULL;
03365 }
03366 
03367 static int parse_args(char *s, int *max, const char *argv[])
03368 {
03369    int x = 0, quoted = 0, escaped = 0, whitespace = 1;
03370    char *cur;
03371 
03372    cur = s;
03373    while(*s) {
03374       switch(*s) {
03375       case '"':
03376          /* If it's escaped, put a literal quote */
03377          if (escaped)
03378             goto normal;
03379          else
03380             quoted = !quoted;
03381          if (quoted && whitespace) {
03382             /* If we're starting a quote, coming off white space start a new word, too */
03383             argv[x++] = cur;
03384             whitespace=0;
03385          }
03386          escaped = 0;
03387       break;
03388       case ' ':
03389       case '\t':
03390          if (!quoted && !escaped) {
03391             /* If we're not quoted, mark this as whitespace, and
03392                end the previous argument */
03393             whitespace = 1;
03394             *(cur++) = '\0';
03395          } else
03396             /* Otherwise, just treat it as anything else */
03397             goto normal;
03398          break;
03399       case '\\':
03400          /* If we're escaped, print a literal, otherwise enable escaping */
03401          if (escaped) {
03402             goto normal;
03403          } else {
03404             escaped=1;
03405          }
03406          break;
03407       default:
03408 normal:
03409          if (whitespace) {
03410             if (x >= MAX_ARGS -1) {
03411                ast_log(LOG_WARNING, "Too many arguments, truncating\n");
03412                break;
03413             }
03414             /* Coming off of whitespace, start the next argument */
03415             argv[x++] = cur;
03416             whitespace=0;
03417          }
03418          *(cur++) = *s;
03419          escaped=0;
03420       }
03421       s++;
03422    }
03423    /* Null terminate */
03424    *(cur++) = '\0';
03425    argv[x] = NULL;
03426    *max = x;
03427    return 0;
03428 }
03429 
03430 static enum agi_result agi_handle_command(struct ast_channel *chan, AGI *agi, char *buf, int dead)
03431 {
03432    const char *argv[MAX_ARGS];
03433    int argc = MAX_ARGS;
03434    int res;
03435    agi_command *c;
03436    const char *ami_res;
03437    char *ami_cmd = ast_strdupa(buf);
03438    int command_id = ast_random();
03439    int resultcode;
03440 
03441    manager_event(EVENT_FLAG_AGI, "AGIExec",
03442          "SubEvent: Start\r\n"
03443          "Channel: %s\r\n"
03444          "CommandId: %d\r\n"
03445          "Command: %s\r\n", ast_channel_name(chan), command_id, ami_cmd);
03446    parse_args(buf, &argc, argv);
03447    c = find_command(argv, 0);
03448    if (c && (!dead || (dead && c->dead))) {
03449       /* if this command wasn't registered by res_agi, be sure to usecount
03450       the module we are using */
03451       if (c->mod != ast_module_info->self)
03452          ast_module_ref(c->mod);
03453       /* If the AGI command being executed is an actual application (using agi exec)
03454       the app field will be updated in pbx_exec via handle_exec */
03455       if (ast_channel_cdr(chan) && !ast_check_hangup(chan) && strcasecmp(argv[0], "EXEC"))
03456          ast_cdr_setapp(ast_channel_cdr(chan), "AGI", buf);
03457 
03458       res = c->handler(chan, agi, argc, argv);
03459       if (c->mod != ast_module_info->self)
03460          ast_module_unref(c->mod);
03461       switch (res) {
03462       case RESULT_SHOWUSAGE:
03463          ami_res = "Usage";
03464          resultcode = 520;
03465          break;
03466       case RESULT_FAILURE:
03467          ami_res = "Failure";
03468          resultcode = -1;
03469          break;
03470       case ASYNC_AGI_BREAK:
03471       case RESULT_SUCCESS:
03472          ami_res = "Success";
03473          resultcode = 200;
03474          break;
03475       default:
03476          ami_res = "Unknown Result";
03477          resultcode = 200;
03478          break;
03479       }
03480       manager_event(EVENT_FLAG_AGI, "AGIExec",
03481             "SubEvent: End\r\n"
03482             "Channel: %s\r\n"
03483             "CommandId: %d\r\n"
03484             "Command: %s\r\n"
03485             "ResultCode: %d\r\n"
03486             "Result: %s\r\n", ast_channel_name(chan), command_id, ami_cmd, resultcode, ami_res);
03487       switch (res) {
03488       case RESULT_SHOWUSAGE:
03489          if (ast_strlen_zero(c->usage)) {
03490             ast_agi_send(agi->fd, chan, "520 Invalid command syntax.  Proper usage not available.\n");
03491          } else {
03492             ast_agi_send(agi->fd, chan, "520-Invalid command syntax.  Proper usage follows:\n");
03493             ast_agi_send(agi->fd, chan, "%s", c->usage);
03494             ast_agi_send(agi->fd, chan, "520 End of proper usage.\n");
03495          }
03496          break;
03497       case ASYNC_AGI_BREAK:
03498          return AGI_RESULT_SUCCESS_ASYNC;
03499       case RESULT_FAILURE:
03500          /* The RESULT_FAILURE code is usually because the channel hungup. */
03501          return AGI_RESULT_FAILURE;
03502       default:
03503          break;
03504       }
03505    } else if (c) {
03506       ast_agi_send(agi->fd, chan, "511 Command Not Permitted on a dead channel\n");
03507       manager_event(EVENT_FLAG_AGI, "AGIExec",
03508             "SubEvent: End\r\n"
03509             "Channel: %s\r\n"
03510             "CommandId: %d\r\n"
03511             "Command: %s\r\n"
03512             "ResultCode: 511\r\n"
03513             "Result: Command not permitted on a dead channel\r\n", ast_channel_name(chan), command_id, ami_cmd);
03514    } else {
03515       ast_agi_send(agi->fd, chan, "510 Invalid or unknown command\n");
03516       manager_event(EVENT_FLAG_AGI, "AGIExec",
03517             "SubEvent: End\r\n"
03518             "Channel: %s\r\n"
03519             "CommandId: %d\r\n"
03520             "Command: %s\r\n"
03521             "ResultCode: 510\r\n"
03522             "Result: Invalid or unknown command\r\n", ast_channel_name(chan), command_id, ami_cmd);
03523    }
03524    return AGI_RESULT_SUCCESS;
03525 }
03526 static enum agi_result run_agi(struct ast_channel *chan, char *request, AGI *agi, int pid, int *status, int dead, int argc, char *argv[])
03527 {
03528    struct ast_channel *c;
03529    int outfd;
03530    int ms;
03531    int needhup = 0;
03532    enum agi_result returnstatus = AGI_RESULT_SUCCESS;
03533    struct ast_frame *f;
03534    char buf[AGI_BUF_LEN];
03535    char *res = NULL;
03536    FILE *readf;
03537    /* how many times we'll retry if ast_waitfor_nandfs will return without either
03538      channel or file descriptor in case select is interrupted by a system call (EINTR) */
03539    int retry = AGI_NANDFS_RETRY;
03540    int send_sighup;
03541    const char *sighup_str;
03542    const char *exit_on_hangup_str;
03543    int exit_on_hangup;
03544    
03545    ast_channel_lock(chan);
03546    sighup_str = pbx_builtin_getvar_helper(chan, "AGISIGHUP");
03547    send_sighup = !ast_false(sighup_str);
03548    exit_on_hangup_str = pbx_builtin_getvar_helper(chan, "AGIEXITONHANGUP");
03549    exit_on_hangup = ast_true(exit_on_hangup_str);
03550    ast_channel_unlock(chan);
03551 
03552    if (!(readf = fdopen(agi->ctrl, "r"))) {
03553       ast_log(LOG_WARNING, "Unable to fdopen file descriptor\n");
03554       if (send_sighup && pid > -1)
03555          kill(pid, SIGHUP);
03556       close(agi->ctrl);
03557       return AGI_RESULT_FAILURE;
03558    }
03559    
03560    setlinebuf(readf);
03561    setup_env(chan, request, agi->fd, (agi->audio > -1), argc, argv);
03562    for (;;) {
03563       if (needhup) {
03564          needhup = 0;
03565          dead = 1;
03566          if (send_sighup) {
03567             if (pid > -1) {
03568                kill(pid, SIGHUP);
03569             } else if (agi->fast) {
03570                ast_agi_send(agi->fd, chan, "HANGUP\n");
03571             }
03572          }
03573          if (exit_on_hangup) {
03574             break;
03575          }
03576       }
03577       ms = -1;
03578       if (dead) {
03579          c = ast_waitfor_nandfds(&chan, 0, &agi->ctrl, 1, NULL, &outfd, &ms);
03580       } else if (!ast_check_hangup(chan)) {
03581          c = ast_waitfor_nandfds(&chan, 1, &agi->ctrl, 1, NULL, &outfd, &ms);
03582       } else {
03583          /*
03584           * Read the channel control queue until it is dry so we can
03585           * switch to dead mode.
03586           */
03587          c = chan;
03588       }
03589       if (c) {
03590          retry = AGI_NANDFS_RETRY;
03591          /* Idle the channel until we get a command */
03592          f = ast_read(c);
03593          if (!f) {
03594             ast_debug(1, "%s hungup\n", ast_channel_name(chan));
03595             needhup = 1;
03596             if (!returnstatus) {
03597                returnstatus = AGI_RESULT_HANGUP;
03598             }
03599          } else {
03600             /* If it's voice, write it to the audio pipe */
03601             if ((agi->audio > -1) && (f->frametype == AST_FRAME_VOICE)) {
03602                /* Write, ignoring errors */
03603                if (write(agi->audio, f->data.ptr, f->datalen) < 0) {
03604                }
03605             }
03606             ast_frfree(f);
03607          }
03608       } else if (outfd > -1) {
03609          size_t len = sizeof(buf);
03610          size_t buflen = 0;
03611          enum agi_result cmd_status;
03612 
03613          retry = AGI_NANDFS_RETRY;
03614          buf[0] = '\0';
03615 
03616          while (len > 1) {
03617             res = fgets(buf + buflen, len, readf);
03618             if (feof(readf))
03619                break;
03620             if (ferror(readf) && ((errno != EINTR) && (errno != EAGAIN)))
03621                break;
03622             if (res != NULL && !agi->fast)
03623                break;
03624             buflen = strlen(buf);
03625             if (buflen && buf[buflen - 1] == '\n')
03626                break;
03627             len = sizeof(buf) - buflen;
03628             if (agidebug)
03629                ast_verbose("AGI Rx << temp buffer %s - errno %s\nNo \\n received, checking again.\n", buf, strerror(errno));
03630          }
03631 
03632          if (!buf[0]) {
03633             /* Program terminated */
03634             ast_verb(3, "<%s>AGI Script %s completed, returning %d\n", ast_channel_name(chan), request, returnstatus);
03635             if (pid > 0)
03636                waitpid(pid, status, 0);
03637             /* No need to kill the pid anymore, since they closed us */
03638             pid = -1;
03639             break;
03640          }
03641 
03642          /* Special case for inability to execute child process */
03643          if (*buf && strncasecmp(buf, "failure", 7) == 0) {
03644             returnstatus = AGI_RESULT_FAILURE;
03645             break;
03646          }
03647 
03648          /* get rid of trailing newline, if any */
03649          buflen = strlen(buf);
03650          if (buflen && buf[buflen - 1] == '\n') {
03651             buf[buflen - 1] = '\0';
03652          }
03653 
03654          if (agidebug)
03655             ast_verbose("<%s>AGI Rx << %s\n", ast_channel_name(chan), buf);
03656          cmd_status = agi_handle_command(chan, agi, buf, dead);
03657          switch (cmd_status) {
03658          case AGI_RESULT_FAILURE:
03659             if (dead || !ast_check_hangup(chan)) {
03660                /* The failure was not because of a hangup. */
03661                returnstatus = AGI_RESULT_FAILURE;
03662             }
03663             break;
03664          default:
03665             break;
03666          }
03667       } else {
03668          if (--retry <= 0) {
03669             ast_log(LOG_WARNING, "No channel, no fd?\n");
03670             returnstatus = AGI_RESULT_FAILURE;
03671             break;
03672          }
03673       }
03674    }
03675    if (agi->speech) {
03676       ast_speech_destroy(agi->speech);
03677    }
03678    /* Notify process */
03679    if (send_sighup) {
03680       if (pid > -1) {
03681          if (kill(pid, SIGHUP)) {
03682             ast_log(LOG_WARNING, "unable to send SIGHUP to AGI process %d: %s\n", pid, strerror(errno));
03683          } else { /* Give the process a chance to die */
03684             usleep(1);
03685          }
03686          waitpid(pid, status, WNOHANG);
03687       } else if (agi->fast) {
03688          ast_agi_send(agi->fd, chan, "HANGUP\n");
03689       }
03690    }
03691    fclose(readf);
03692    return returnstatus;
03693 }
03694 
03695 static char *handle_cli_agi_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
03696 {
03697    struct agi_command *command;
03698    char fullcmd[MAX_CMD_LEN];
03699    int error = 0;
03700 
03701    switch (cmd) {
03702    case CLI_INIT:
03703       e->command = "agi show commands [topic]";
03704       e->usage =
03705          "Usage: agi show commands [topic] <topic>\n"
03706          "       When called with a topic as an argument, displays usage\n"
03707          "       information on the given command.  If called without a\n"
03708          "       topic, it provides a list of AGI commands.\n";
03709    case CLI_GENERATE:
03710       return NULL;
03711    }
03712    if (a->argc < e->args - 1 || (a->argc >= e->args && strcasecmp(a->argv[e->args - 1], "topic")))
03713       return CLI_SHOWUSAGE;
03714    if (a->argc > e->args - 1) {
03715       command = find_command(a->argv + e->args, 1);
03716       if (command) {
03717          char *synopsis = NULL, *description = NULL, *syntax = NULL, *seealso = NULL;
03718          char info[30 + MAX_CMD_LEN];              /* '-= Info about...' */
03719          char infotitle[30 + MAX_CMD_LEN + AST_TERM_MAX_ESCAPE_CHARS];  /* '-= Info about...' with colors */
03720          char syntitle[11 + AST_TERM_MAX_ESCAPE_CHARS];        /* [Syntax]\n with colors */
03721          char desctitle[15 + AST_TERM_MAX_ESCAPE_CHARS];       /* [Description]\n with colors */
03722          char deadtitle[13 + AST_TERM_MAX_ESCAPE_CHARS];       /* [Runs Dead]\n with colors */
03723          char deadcontent[3 + AST_TERM_MAX_ESCAPE_CHARS];      /* 'Yes' or 'No' with colors */
03724          char seealsotitle[12 + AST_TERM_MAX_ESCAPE_CHARS];    /* [See Also]\n with colors */
03725          char stxtitle[10 + AST_TERM_MAX_ESCAPE_CHARS];        /* [Syntax]\n with colors */
03726          size_t synlen, desclen, seealsolen, stxlen;
03727 
03728          term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, sizeof(syntitle));
03729          term_color(desctitle, "[Description]\n", COLOR_MAGENTA, 0, sizeof(desctitle));
03730          term_color(deadtitle, "[Runs Dead]\n", COLOR_MAGENTA, 0, sizeof(deadtitle));
03731          term_color(seealsotitle, "[See Also]\n", COLOR_MAGENTA, 0, sizeof(seealsotitle));
03732          term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, sizeof(stxtitle));
03733          term_color(deadcontent, command->dead ? "Yes" : "No", COLOR_CYAN, 0, sizeof(deadcontent));
03734 
03735          ast_join(fullcmd, sizeof(fullcmd), a->argv + e->args);
03736          snprintf(info, sizeof(info), "\n  -= Info about agi '%s' =- ", fullcmd);
03737          term_color(infotitle, info, COLOR_CYAN, 0, sizeof(infotitle));
03738 #ifdef AST_XML_DOCS
03739          if (command->docsrc == AST_XML_DOC) {
03740             synopsis = ast_xmldoc_printable(S_OR(command->summary, "Not available"), 1);
03741             description = ast_xmldoc_printable(S_OR(command->usage, "Not available"), 1);
03742             seealso = ast_xmldoc_printable(S_OR(command->seealso, "Not available"), 1);
03743             if (!seealso || !description || !synopsis) {
03744                error = 1;
03745                goto return_cleanup;
03746             }
03747          } else
03748 #endif
03749          {
03750             synlen = strlen(S_OR(command->summary, "Not available")) + AST_TERM_MAX_ESCAPE_CHARS;
03751             synopsis = ast_malloc(synlen);
03752 
03753             desclen = strlen(S_OR(command->usage, "Not available")) + AST_TERM_MAX_ESCAPE_CHARS;
03754             description = ast_malloc(desclen);
03755 
03756             seealsolen = strlen(S_OR(command->seealso, "Not available")) + AST_TERM_MAX_ESCAPE_CHARS;
03757             seealso = ast_malloc(seealsolen);
03758 
03759             if (!synopsis || !description || !seealso) {
03760                error = 1;
03761                goto return_cleanup;
03762             }
03763             term_color(synopsis, S_OR(command->summary, "Not available"), COLOR_CYAN, 0, synlen);
03764             term_color(description, S_OR(command->usage, "Not available"), COLOR_CYAN, 0, desclen);
03765             term_color(seealso, S_OR(command->seealso, "Not available"), COLOR_CYAN, 0, seealsolen);
03766          }
03767 
03768          stxlen = strlen(S_OR(command->syntax, "Not available")) + AST_TERM_MAX_ESCAPE_CHARS;
03769          syntax = ast_malloc(stxlen);
03770          if (!syntax) {
03771             error = 1;
03772             goto return_cleanup;
03773          }
03774          term_color(syntax, S_OR(command->syntax, "Not available"), COLOR_CYAN, 0, stxlen);
03775 
03776          ast_cli(a->fd, "%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n", infotitle, stxtitle, syntax,
03777                desctitle, description, syntitle, synopsis, deadtitle, deadcontent,
03778                seealsotitle, seealso);
03779 return_cleanup:
03780          ast_free(synopsis);
03781          ast_free(description);
03782          ast_free(syntax);
03783          ast_free(seealso);
03784       } else {
03785          if (find_command(a->argv + e->args, -1)) {
03786             return help_workhorse(a->fd, a->argv + e->args);
03787          } else {
03788             ast_join(fullcmd, sizeof(fullcmd), a->argv + e->args);
03789             ast_cli(a->fd, "No such command '%s'.\n", fullcmd);
03790          }
03791       }
03792    } else {
03793       return help_workhorse(a->fd, NULL);
03794    }
03795    return (error ? CLI_FAILURE : CLI_SUCCESS);
03796 }
03797 
03798 /*! \brief Convert string to use HTML escaped characters
03799    \note Maybe this should be a generic function?
03800 */
03801 static void write_html_escaped(FILE *htmlfile, char *str)
03802 {
03803    char *cur = str;
03804 
03805    while(*cur) {
03806       switch (*cur) {
03807       case '<':
03808          fprintf(htmlfile, "%s", "&lt;");
03809          break;
03810       case '>':
03811          fprintf(htmlfile, "%s", "&gt;");
03812          break;
03813       case '&':
03814          fprintf(htmlfile, "%s", "&amp;");
03815          break;
03816       case '"':
03817          fprintf(htmlfile, "%s", "&quot;");
03818          break;
03819       default:
03820          fprintf(htmlfile, "%c", *cur);
03821          break;
03822       }
03823       cur++;
03824    }
03825 
03826    return;
03827 }
03828 
03829 static int write_htmldump(const char *filename)
03830 {
03831    struct agi_command *command;
03832    char fullcmd[MAX_CMD_LEN];
03833    FILE *htmlfile;
03834 
03835    if (!(htmlfile = fopen(filename, "wt")))
03836       return -1;
03837 
03838    fprintf(htmlfile, "<HTML>\n<HEAD>\n<TITLE>AGI Commands</TITLE>\n</HEAD>\n");
03839    fprintf(htmlfile, "<BODY>\n<CENTER><B><H1>AGI Commands</H1></B></CENTER>\n\n");
03840    fprintf(htmlfile, "<TABLE BORDER=\"0\" CELLSPACING=\"10\">\n");
03841 
03842    AST_RWLIST_RDLOCK(&agi_commands);
03843    AST_RWLIST_TRAVERSE(&agi_commands, command, list) {
03844       char *tempstr, *stringp;
03845 
03846       if (!command->cmda[0])  /* end ? */
03847          break;
03848       /* Hide commands that start with '_' */
03849       if ((command->cmda[0])[0] == '_')
03850          continue;
03851       ast_join(fullcmd, sizeof(fullcmd), command->cmda);
03852 
03853       fprintf(htmlfile, "<TR><TD><TABLE BORDER=\"1\" CELLPADDING=\"5\" WIDTH=\"100%%\">\n");
03854       fprintf(htmlfile, "<TR><TH ALIGN=\"CENTER\"><B>%s - %s</B></TH></TR>\n", fullcmd, command->summary);
03855 #ifdef AST_XML_DOCS
03856       stringp = ast_xmldoc_printable(command->usage, 0);
03857 #else
03858       stringp = ast_strdup(command->usage);
03859 #endif
03860       tempstr = strsep(&stringp, "\n");
03861 
03862       fprintf(htmlfile, "<TR><TD ALIGN=\"CENTER\">");
03863       write_html_escaped(htmlfile, tempstr);
03864       fprintf(htmlfile, "</TD></TR>\n");
03865       fprintf(htmlfile, "<TR><TD ALIGN=\"CENTER\">\n");
03866 
03867       while ((tempstr = strsep(&stringp, "\n")) != NULL) {
03868          write_html_escaped(htmlfile, tempstr);
03869          fprintf(htmlfile, "<BR>\n");
03870       }
03871       fprintf(htmlfile, "</TD></TR>\n");
03872       fprintf(htmlfile, "</TABLE></TD></TR>\n\n");
03873       ast_free(stringp);
03874    }
03875    AST_RWLIST_UNLOCK(&agi_commands);
03876    fprintf(htmlfile, "</TABLE>\n</BODY>\n</HTML>\n");
03877    fclose(htmlfile);
03878    return 0;
03879 }
03880 
03881 static char *handle_cli_agi_dump_html(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
03882 {
03883    switch (cmd) {
03884    case CLI_INIT:
03885       e->command = "agi dump html";
03886       e->usage =
03887          "Usage: agi dump html <filename>\n"
03888          "       Dumps the AGI command list in HTML format to the given\n"
03889          "       file.\n";
03890       return NULL;
03891    case CLI_GENERATE:
03892       return NULL;
03893    }
03894    if (a->argc != e->args + 1)
03895       return CLI_SHOWUSAGE;
03896 
03897    if (write_htmldump(a->argv[e->args]) < 0) {
03898       ast_cli(a->fd, "Could not create file '%s'\n", a->argv[e->args]);
03899       return CLI_SHOWUSAGE;
03900    }
03901    ast_cli(a->fd, "AGI HTML commands dumped to: %s\n", a->argv[e->args]);
03902    return CLI_SUCCESS;
03903 }
03904 
03905 static int agi_exec_full(struct ast_channel *chan, const char *data, int enhanced, int dead)
03906 {
03907    enum agi_result res;
03908    char *buf;
03909    int fds[2], efd = -1, pid = -1;
03910    AST_DECLARE_APP_ARGS(args,
03911       AST_APP_ARG(arg)[MAX_ARGS];
03912    );
03913    AGI agi;
03914 
03915    if (ast_strlen_zero(data)) {
03916       ast_log(LOG_WARNING, "AGI requires an argument (script)\n");
03917       return -1;
03918    }
03919    if (dead)
03920       ast_debug(3, "Hungup channel detected, running agi in dead mode.\n");
03921    memset(&agi, 0, sizeof(agi));
03922    buf = ast_strdupa(data);
03923    AST_STANDARD_APP_ARGS(args, buf);
03924    args.argv[args.argc] = NULL;
03925 #if 0
03926     /* Answer if need be */
03927    if (chan->_state != AST_STATE_UP) {
03928       if (ast_answer(chan))
03929          return -1;
03930    }
03931 #endif
03932    res = launch_script(chan, args.argv[0], args.argv, fds, enhanced ? &efd : NULL, &pid);
03933    /* Async AGI do not require run_agi(), so just proceed if normal AGI
03934       or Fast AGI are setup with success. */
03935    if (res == AGI_RESULT_SUCCESS || res == AGI_RESULT_SUCCESS_FAST) {
03936       int status = 0;
03937       agi.fd = fds[1];
03938       agi.ctrl = fds[0];
03939       agi.audio = efd;
03940       agi.fast = (res == AGI_RESULT_SUCCESS_FAST) ? 1 : 0;
03941       res = run_agi(chan, args.argv[0], &agi, pid, &status, dead, args.argc, args.argv);
03942       /* If the fork'd process returns non-zero, set AGISTATUS to FAILURE */
03943       if ((res == AGI_RESULT_SUCCESS || res == AGI_RESULT_SUCCESS_FAST) && status)
03944          res = AGI_RESULT_FAILURE;
03945       if (fds[1] != fds[0])
03946          close(fds[1]);
03947       if (efd > -1)
03948          close(efd);
03949    }
03950    ast_safe_fork_cleanup();
03951 
03952    switch (res) {
03953    case AGI_RESULT_SUCCESS:
03954    case AGI_RESULT_SUCCESS_FAST:
03955    case AGI_RESULT_SUCCESS_ASYNC:
03956       pbx_builtin_setvar_helper(chan, "AGISTATUS", "SUCCESS");
03957       break;
03958    case AGI_RESULT_FAILURE:
03959       pbx_builtin_setvar_helper(chan, "AGISTATUS", "FAILURE");
03960       break;
03961    case AGI_RESULT_NOTFOUND:
03962       pbx_builtin_setvar_helper(chan, "AGISTATUS", "NOTFOUND");
03963       break;
03964    case AGI_RESULT_HANGUP:
03965       pbx_builtin_setvar_helper(chan, "AGISTATUS", "HANGUP");
03966       return -1;
03967    }
03968 
03969    return 0;
03970 }
03971 
03972 static int agi_exec(struct ast_channel *chan, const char *data)
03973 {
03974    if (!ast_check_hangup(chan))
03975       return agi_exec_full(chan, data, 0, 0);
03976    else
03977       return agi_exec_full(chan, data, 0, 1);
03978 }
03979 
03980 static int eagi_exec(struct ast_channel *chan, const char *data)
03981 {
03982    int res;
03983    struct ast_format readformat;
03984 
03985    if (ast_check_hangup(chan)) {
03986       ast_log(LOG_ERROR, "EAGI cannot be run on a dead/hungup channel, please use AGI.\n");
03987       return 0;
03988    }
03989    ast_format_copy(&readformat, ast_channel_readformat(chan));
03990    if (ast_set_read_format_by_id(chan, AST_FORMAT_SLINEAR)) {
03991       ast_log(LOG_WARNING, "Unable to set channel '%s' to linear mode\n", ast_channel_name(chan));
03992       return -1;
03993    }
03994    res = agi_exec_full(chan, data, 1, 0);
03995    if (!res) {
03996       if (ast_set_read_format(chan, &readformat)) {
03997          ast_log(LOG_WARNING, "Unable to restore channel '%s' to format %s\n", ast_channel_name(chan), ast_getformatname(&readformat));
03998       }
03999    }
04000    return res;
04001 }
04002 
04003 static int deadagi_exec(struct ast_channel *chan, const char *data)
04004 {
04005    ast_log(LOG_WARNING, "DeadAGI has been deprecated, please use AGI in all cases!\n");
04006    return agi_exec(chan, data);
04007 }
04008 
04009 static struct ast_cli_entry cli_agi[] = {
04010    AST_CLI_DEFINE(handle_cli_agi_add_cmd,   "Add AGI command to a channel in Async AGI"),
04011    AST_CLI_DEFINE(handle_cli_agi_debug,     "Enable/Disable AGI debugging"),
04012    AST_CLI_DEFINE(handle_cli_agi_show,      "List AGI commands or specific help"),
04013    AST_CLI_DEFINE(handle_cli_agi_dump_html, "Dumps a list of AGI commands in HTML format")
04014 };
04015 
04016 #ifdef TEST_FRAMEWORK
04017 AST_TEST_DEFINE(test_agi_null_docs)
04018 {
04019    int res = AST_TEST_PASS;
04020    struct agi_command noop_command =
04021       { { "testnoop", NULL }, handle_noop, NULL, NULL, 0 };
04022 
04023    switch (cmd) {
04024    case TEST_INIT:
04025       info->name = "null_agi_docs";
04026       info->category = "/res/agi/";
04027       info->summary = "AGI command with no documentation";
04028       info->description = "Test whether an AGI command with no documentation will crash Asterisk";
04029       return AST_TEST_NOT_RUN;
04030    case TEST_EXECUTE:
04031       break;
04032    }
04033 
04034    if (ast_agi_register(ast_module_info->self, &noop_command) == 0) {
04035       ast_test_status_update(test, "Unable to register testnoop command, because res_agi is not loaded.\n");
04036       return AST_TEST_NOT_RUN;
04037    }
04038 
04039 #ifndef HAVE_NULLSAFE_PRINTF
04040    /* Test for condition without actually crashing Asterisk */
04041    if (noop_command.usage == NULL) {
04042       ast_test_status_update(test, "AGI testnoop usage was not updated properly.\n");
04043       res = AST_TEST_FAIL;
04044    }
04045    if (noop_command.syntax == NULL) {
04046       ast_test_status_update(test, "AGI testnoop syntax was not updated properly.\n");
04047       res = AST_TEST_FAIL;
04048    }
04049 #endif
04050 
04051    ast_agi_unregister(ast_module_info->self, &noop_command);
04052    return res;
04053 }
04054 #endif
04055 
04056 static int unload_module(void)
04057 {
04058    ast_cli_unregister_multiple(cli_agi, ARRAY_LEN(cli_agi));
04059    /* we can safely ignore the result of ast_agi_unregister_multiple() here, since it cannot fail, as
04060       we know that these commands were registered by this module and are still registered
04061    */
04062    (void) ast_agi_unregister_multiple(ast_module_info->self, commands, ARRAY_LEN(commands));
04063    ast_unregister_application(eapp);
04064    ast_unregister_application(deadapp);
04065    ast_manager_unregister("AGI");
04066    AST_TEST_UNREGISTER(test_agi_null_docs);
04067    return ast_unregister_application(app);
04068 }
04069 
04070 static int load_module(void)
04071 {
04072    ast_cli_register_multiple(cli_agi, ARRAY_LEN(cli_agi));
04073    /* we can safely ignore the result of ast_agi_register_multiple() here, since it cannot fail, as
04074       no other commands have been registered yet
04075    */
04076    (void) ast_agi_register_multiple(ast_module_info->self, commands, ARRAY_LEN(commands));
04077    ast_register_application_xml(deadapp, deadagi_exec);
04078    ast_register_application_xml(eapp, eagi_exec);
04079    ast_manager_register_xml("AGI", EVENT_FLAG_AGI, action_add_agi_cmd);
04080    AST_TEST_REGISTER(test_agi_null_docs);
04081    return ast_register_application_xml(app, agi_exec);
04082 }
04083 
04084 AST_MODULE_INFO(ASTERISK_GPL_KEY, AST_MODFLAG_GLOBAL_SYMBOLS | AST_MODFLAG_LOAD_ORDER, "Asterisk Gateway Interface (AGI)",
04085       .load = load_module,
04086       .unload = unload_module,
04087       .load_pri = AST_MODPRI_APP_DEPEND,
04088       );