dect
/
asterisk
Archived
13
0
Fork 0

make some corrections to the ast_agi_register_multiple(), ast_agi_unregister_multiple() and ast_agi_fdprintf() API calls to be consistent with API guidelines

also, move UPGRADE.txt to UPGRADE-1.6.txt and make the new UPGRADE.txt contain information about upgrading between Asterisk 1.6 releases



git-svn-id: http://svn.digium.com/svn/asterisk/trunk@157706 f38db490-d61c-443f-a65b-d21fe96a405b
This commit is contained in:
kpfleming 2008-11-19 12:42:19 +00:00
parent 421ba24996
commit 7ad42d39db
5 changed files with 544 additions and 441 deletions

311
UPGRADE-1.6.txt Normal file
View File

@ -0,0 +1,311 @@
=========================================================
=== Information for upgrading from Asterisk 1.4 to 1.6
===
===
=== UPGRADE-1.2.txt -- Upgrade info for 1.0 to 1.2
=== UPGRADE-1.4.txt -- Upgrade info for 1.2 to 1.4
=========================================================
AEL:
* Macros are now implemented underneath with the Gosub() application.
Heaven Help You if you wrote code depending on any aspect of this!
Previous to 1.6, macros were implemented with the Macro() app, which
provided a nice feature of auto-returning. The compiler will do its
best to insert a Return() app call at the end of your macro if you did
not include it, but really, you should make sure that all execution
paths within your macros end in "return;".
* The conf2ael program is 'introduced' in this release; it is in a rather
crude state, but deemed useful for making a first pass at converting
extensions.conf code into AEL. More intelligence will come with time.
Core:
* The 'languageprefix' option in asterisk.conf is now deprecated, and
the default sound file layout for non-English sounds is the 'new
style' layout introduced in Asterisk 1.4 (and used by the automatic
sound file installer in the Makefile).
* The ast_expr2 stuff has been modified to handle floating-point numbers.
Numbers of the format D.D are now acceptable input for the expr parser,
Where D is a string of base-10 digits. All math is now done in "long double",
if it is available on your compiler/architecture. This was half-way between
a bug-fix (because the MATH func returns fp by default), and an enhancement.
Also, for those counting on, or needing, integer operations, a series of
'functions' were also added to the expr language, to allow several styles
of rounding/truncation, along with a set of common floating point operations,
like sin, cos, tan, log, pow, etc. The ability to call external functions
like CDR(), etc. was also added, without having to use the ${...} notation.
* The delimiter passed to applications has been changed to the comma (','), as
that is what people are used to using within extensions.conf. If you are
using realtime extensions, you will need to translate your existing dialplan
to use this separator. To use a literal comma, you need merely to escape it
with a backslash ('\'). Another possible side effect is that you may need to
remove the obscene level of backslashing that was necessary for the dialplan
to work correctly in 1.4 and previous versions. This should make writing
dialplans less painful in the future, albeit with the pain of a one-time
conversion. If you would like to avoid this conversion immediately, set
pbx_realtime=1.4 in the [compat] section of asterisk.conf. After
transitioning, set pbx_realtime=1.6 in the same section.
* For the same purpose as above, you may set res_agi=1.4 in the [compat]
section of asterisk.conf to continue to use the '|' delimiter in the EXEC
arguments of AGI applications. After converting to use the ',' delimiter,
change this option to res_agi=1.6.
* The logger.conf option 'rotatetimestamp' has been deprecated in favor of
'rotatestrategy'. This new option supports a 'rotate' strategy that more
closely mimics the system logger in terms of file rotation.
* The concise versions of various CLI commands are now deprecated. We recommend
using the manager interface (AMI) for application integration with Asterisk.
* The following core commands dealing with dialplan has been deprecated: 'core
show globals', 'core set global' and 'core set chanvar'. Use the equivalent
'dialplan show globals', 'dialplan set global' and 'dialplan set chanvar'
instead.
* The silencethreshold used for various applications is now settable via a
centralized config option in dsp.conf.
* The logical value of spaces immediately preceding a standalone 0 previously
evaluated to true. It now evaluates to false. This has confused a good
many people in the past (typically because they failed to realize the space
had any significance). Since this violates the Principle of Least Surprise,
it has been changed.
* The default console now will use colors according to the default background
color, instead of forcing the background color to black. If you are using a
light colored background for your console, you may wish to use the option
flag '-W' to present better color choices for the various messages. However,
if you'd prefer the old method of forcing colors to white text on a black
background, the compatiblity option -B is provided for this purpose.
Voicemail:
* The voicemail configuration values 'maxmessage' and 'minmessage' have
been changed to 'maxsecs' and 'minsecs' to clarify their purpose and
to make them more distinguishable from 'maxmsgs', which sets folder
size. The old variables will continue to work in this version, albeit
with a deprecation warning.
* If you use any interface for modifying voicemail aside from the built in
dialplan applications, then the option "pollmailboxes" *must* be set in
voicemail.conf for message waiting indication (MWI) to work properly. This
is because Voicemail notification is now event based instead of polling
based. The channel drivers are no longer responsible for constantly manually
checking mailboxes for changes so that they can send MWI information to users.
Examples of situations that would require this option are web interfaces to
voicemail or an email client in the case of using IMAP storage.
* The externnotify script should accept an additional (last) parameter
containing the number of urgent messages in the INBOX.
Applications:
* SendImage() no longer hangs up the channel on transmission error or on
another type of error; in those cases, a FAILURE status is stored in
SENDIMAGESTATUS and dialplan execution continues. The possible return values
stored in SENDIMAGESTATUS are: SUCCESS, FAILURE, and UNSUPPORTED. ('OK' has
been replaced with 'SUCCESS', and 'NOSUPPORT' has been replaced with
'UNSUPPORTED'). This change makes the SendImage application more consistent
with other applications.
* ChanIsAvail() now has a 't' option, which allows the specified device
to be queried for state without consulting the channel drivers. This
performs mostly a 'ChanExists' sort of function.
* ChannelRedirect() will not terminate the channel that fails to do a
channelredirect as it has done previously. Instead CHANNELREDIRECT_STATUS
will reflect if the attempt was successful of not.
* SetCallerPres() has been replaced with the CALLERPRES() dialplan function
and is now deprecated.
* DISA()'s fifth argument is now an options argument. If you have previously
used 'NOANSWER' in this argument, you'll need to convert that to the new
option 'n'.
* Macro() is now deprecated. If you need subroutines, you should use the
Gosub()/Return() applications. To replace MacroExclusive(), we have
introduced dialplan functions LOCK(), TRYLOCK(), and UNLOCK(). You may use
these functions in any location where you desire to ensure that only one
channel is executing that path at any one time. The Macro() applications
are deprecated for performance reasons. However, since Macro() has been
around for a long time and so many dialplans depend heavily on it, for the
sake of backwards compatibility it will not be removed . It is also worth
noting that using both Macro() and GoSub() at the same time is _heavily_
discouraged.
* Read() now sets a READSTATUS variable on exit. It does NOT automatically
return -1 (and hangup) anymore on error. If you want to hangup on error,
you need to do so explicitly in your dialplan.
* Privacy() no longer uses privacy.conf, so any options must be specified
directly in the application arguments.
* MusicOnHold application now has duration parameter which allows specifying
timeout in seconds.
* WaitMusicOnHold application is now deprecated in favor of extended MusicOnHold.
* SetMusicOnHold is now deprecated. You should use Set(CHANNEL(musicclass)=...)
instead.
* While app_directory has always relied on having a voicemail.conf or users.conf file
correctly set up, it now is dependent on app_voicemail being compiled as well.
* The arguments in ExecIf changed a bit, to be more like other applications.
The syntax is now ExecIf(<cond>?appiftrue(args):appiffalse(args)).
* The behavior of the Set application now depends upon a compatibility option,
set in asterisk.conf. To use the old 1.4 behavior, which allowed Set to take
multiple key/value pairs, set app_set=1.4 in [compat] in asterisk.conf. To
use the new behavior, which permits variables to be set with embedded commas,
set app_set=1.6 in [compat] in asterisk.conf. Note that you can have both
behaviors at the same time, if you switch to using MSet if you want the old
behavior.
Dialplan Functions:
* QUEUE_MEMBER_COUNT() has been deprecated in favor of the QUEUE_MEMBER() function. For
more information, issue a "show function QUEUE_MEMBER" from the CLI.
CDR:
* The cdr_sqlite module has been marked as deprecated in favor of
cdr_sqlite3_custom. It will potentially be removed from the tree
after Asterisk 1.6 is released.
* The cdr_odbc module now uses res_odbc to manage its connections. The
username and password parameters in cdr_odbc.conf, therefore, are no
longer used. The dsn parameter now points to an entry in res_odbc.conf.
* The uniqueid field in the core Asterisk structure has been changed from a
maximum 31 character field to a 149 character field, to account for all
possible values the systemname prefix could be. In the past, if the
systemname was too long, the uniqueid would have been truncated.
* The cdr_tds module now supports all versions of FreeTDS that contain
the db-lib frontend. It will also now log the userfield variable if
the target database table contains a column for it.
Formats:
* format_wav: The GAIN preprocessor definition and source code that used it
is removed. This change was made in response to user complaints of
choppiness or the clipping of loud signal peaks. To increase the volume
of voicemail messages, use the 'volgain' option in voicemail.conf
Channel Drivers:
* SIP: a small upgrade to support the "Record" button on the SNOM360,
which sends a sip INFO message with a "Record: on" or "Record: off"
header. If Asterisk is set up (via features.conf) to accept "One Touch Monitor"
requests (by default, via '*1'), then the user-configured dialpad sequence
is generated, and recording can be started and stopped via this button. The
file names and formats are all controlled via the normal mechanisms. If the
user has not configured the automon feature, the normal "415 Unsupported media type"
is returned, and nothing is done.
* SIP: The "call-limit" option is marked as deprecated. It still works in this version of
Asterisk, but will be removed in the following version. Please use the groupcount functions
in the dialplan to enforce call limits. The "limitonpeer" configuration option is
now renamed to "counteronpeer".
* SIP: The "username" option is now renamed to "defaultuser" to match "defaultip".
These are used only before registration to call a peer with the uri
sip:defaultuser@defaultip
The "username" setting still work, but is deprecated and will not work in
the next version of Asterisk.
* SIP: All of the functionality in SIPCHANINFO() has been implemented in CHANNEL(),
and you should start using that function instead for retrieving information about
the channel in a technology-agnostic way.
* chan_local.c: the comma delimiter inside the channel name has been changed to a
semicolon, in order to make the Local channel driver compatible with the comma
delimiter change in applications.
* H323: The "tos" setting has changed name to "tos_audio" and "cos" to "cos_audio"
to be compatible with settings in sip.conf. The "tos" and "cos" configuration
is deprecated and will stop working in the next release of Asterisk.
* Console: A new console channel driver, chan_console, has been added to Asterisk.
This new module can not be loaded at the same time as chan_alsa or chan_oss. The
default modules.conf only loads one of them (chan_oss by default). So, unless you
have modified your modules.conf to not use the autoload option, then you will need
to modify modules.conf to add another "noload" line to ensure that only one of
these three modules gets loaded.
* DAHDI: The chan_zap module that supported PSTN interfaces using
Zaptel has been renamed to chan_dahdi, and only supports the DAHDI
telephony driver package for PSTN interfaces. See the
Zaptel-to-DAHDI.txt file for more details on this transition.
* DAHDI: The "msdstrip" option has been deprecated, as it provides no value over
the method of stripping digits in the dialplan using variable substring syntax.
Configuration:
* pbx_dundi.c: tos parameter changed to use new values. Old values like lowdelay,
lowcost and other is not acceptable now. Look into qos.tex for description of
this parameter.
* queues.conf: the queue-lessthan sound file option is no longer available, and the
queue-round-seconds option no longer takes '1' as a valid parameter.
* If you have any third party modules which use a config file variable whose
name ends in a '+', please note that the append capability added to this
version may now conflict with that variable naming scheme. An easy
workaround is to ensure that a space occurs between the '+' and the '=',
to differentiate your variable from the append operator. This potential
conflict is unlikely, but is documented here to be thorough.
* skinny.conf now has seperate sections for lines and devices.
Please have a look at configs/skinny.conf.sample and update
your skinny.conf.
Manager:
* Manager has been upgraded to version 1.1 with a lot of changes.
Please check doc/manager_1_1.txt for information
* The IAXpeers command output has been changed to more closely resemble the
output of the SIPpeers command.
* cdr_manager now reports at the "cdr" level, not at "call" You may need to
change your manager.conf to add the level to existing AMI users, if they
want to see the CDR events generated.
* The Originate command now requires the Originate write permission. For
Originate with the Application parameter, you need the additional System
privilege if you want to do anything that calls out to a subshell.
Queues:
* New queue log events ADDMEMBER and REMOVEMEMBER have been added. Also, a
new value has been added to the TRANSFER event that indicates the caller's
original position in the queue they are being transfered from.
* Prior to Asterisk 1.6.2, queue names were treated in a case-sensitive
manner, meaning that queues with names like "sales" and "sALeS" would
be seen as unique queues. The parsing logic has changed to use case-
insensitive comparisons now when originally hashing based on queue
names, meaning that now the two queues mentioned as examples earlier
will be seen as having the same name.
iLBC Codec:
* Previously, the Asterisk source code distribution included the iLBC
encoder/decoder source code, from Global IP Solutions
(http://www.gipscorp.com). This code is not licensed for
distribution, and thus has been removed from the Asterisk source
code distribution. If you wish to use codec_ilbc to support iLBC
channels in Asterisk, you can run the contrib/scripts/get_ilbc_source.sh
script to download the source and put it in the proper place in
the Asterisk build tree. Once that is done you can follow your normal
steps of building Asterisk. You will need to run 'menuselect' and enable
the iLBC codec in the 'Codec Translators' category.

View File

@ -1,312 +1,27 @@
=========================================================
=== Information for upgrading from Asterisk 1.4 to 1.6
===========================================================
=== Information for upgrading between Asterisk 1.6 versions
===
===
=== UPGRADE-1.2.txt -- Upgrade info for 1.0 to 1.2
=== UPGRADE-1.4.txt -- Upgrade info for 1.2 to 1.4
=== UPGRADE.txt -- Upgrade info for 1.4 to 1.6
=========================================================
AEL:
* Macros are now implemented underneath with the Gosub() application.
Heaven Help You if you wrote code depending on any aspect of this!
Previous to 1.6, macros were implemented with the Macro() app, which
provided a nice feature of auto-returning. The compiler will do its
best to insert a Return() app call at the end of your macro if you did
not include it, but really, you should make sure that all execution
paths within your macros end in "return;".
* The conf2ael program is 'introduced' in this release; it is in a rather
crude state, but deemed useful for making a first pass at converting
extensions.conf code into AEL. More intelligence will come with time.
Core:
* The 'languageprefix' option in asterisk.conf is now deprecated, and
the default sound file layout for non-English sounds is the 'new
style' layout introduced in Asterisk 1.4 (and used by the automatic
sound file installer in the Makefile).
* The ast_expr2 stuff has been modified to handle floating-point numbers.
Numbers of the format D.D are now acceptable input for the expr parser,
Where D is a string of base-10 digits. All math is now done in "long double",
if it is available on your compiler/architecture. This was half-way between
a bug-fix (because the MATH func returns fp by default), and an enhancement.
Also, for those counting on, or needing, integer operations, a series of
'functions' were also added to the expr language, to allow several styles
of rounding/truncation, along with a set of common floating point operations,
like sin, cos, tan, log, pow, etc. The ability to call external functions
like CDR(), etc. was also added, without having to use the ${...} notation.
* The delimiter passed to applications has been changed to the comma (','), as
that is what people are used to using within extensions.conf. If you are
using realtime extensions, you will need to translate your existing dialplan
to use this separator. To use a literal comma, you need merely to escape it
with a backslash ('\'). Another possible side effect is that you may need to
remove the obscene level of backslashing that was necessary for the dialplan
to work correctly in 1.4 and previous versions. This should make writing
dialplans less painful in the future, albeit with the pain of a one-time
conversion. If you would like to avoid this conversion immediately, set
pbx_realtime=1.4 in the [compat] section of asterisk.conf. After
transitioning, set pbx_realtime=1.6 in the same section.
* For the same purpose as above, you may set res_agi=1.4 in the [compat]
section of asterisk.conf to continue to use the '|' delimiter in the EXEC
arguments of AGI applications. After converting to use the ',' delimiter,
change this option to res_agi=1.6.
* The logger.conf option 'rotatetimestamp' has been deprecated in favor of
'rotatestrategy'. This new option supports a 'rotate' strategy that more
closely mimics the system logger in terms of file rotation.
* The concise versions of various CLI commands are now deprecated. We recommend
using the manager interface (AMI) for application integration with Asterisk.
* The following core commands dealing with dialplan has been deprecated: 'core
show globals', 'core set global' and 'core set chanvar'. Use the equivalent
'dialplan show globals', 'dialplan set global' and 'dialplan set chanvar'
instead.
* The silencethreshold used for various applications is now settable via a
centralized config option in dsp.conf.
* The logical value of spaces immediately preceding a standalone 0 previously
evaluated to true. It now evaluates to false. This has confused a good
many people in the past (typically because they failed to realize the space
had any significance). Since this violates the Principle of Least Surprise,
it has been changed.
* The default console now will use colors according to the default background
color, instead of forcing the background color to black. If you are using a
light colored background for your console, you may wish to use the option
flag '-W' to present better color choices for the various messages. However,
if you'd prefer the old method of forcing colors to white text on a black
background, the compatiblity option -B is provided for this purpose.
Voicemail:
* The voicemail configuration values 'maxmessage' and 'minmessage' have
been changed to 'maxsecs' and 'minsecs' to clarify their purpose and
to make them more distinguishable from 'maxmsgs', which sets folder
size. The old variables will continue to work in this version, albeit
with a deprecation warning.
* If you use any interface for modifying voicemail aside from the built in
dialplan applications, then the option "pollmailboxes" *must* be set in
voicemail.conf for message waiting indication (MWI) to work properly. This
is because Voicemail notification is now event based instead of polling
based. The channel drivers are no longer responsible for constantly manually
checking mailboxes for changes so that they can send MWI information to users.
Examples of situations that would require this option are web interfaces to
voicemail or an email client in the case of using IMAP storage.
* The externnotify script should accept an additional (last) parameter
containing the number of urgent messages in the INBOX.
Applications:
* SendImage() no longer hangs up the channel on transmission error or on
another type of error; in those cases, a FAILURE status is stored in
SENDIMAGESTATUS and dialplan execution continues. The possible return values
stored in SENDIMAGESTATUS are: SUCCESS, FAILURE, and UNSUPPORTED. ('OK' has
been replaced with 'SUCCESS', and 'NOSUPPORT' has been replaced with
'UNSUPPORTED'). This change makes the SendImage application more consistent
with other applications.
* ChanIsAvail() now has a 't' option, which allows the specified device
to be queried for state without consulting the channel drivers. This
performs mostly a 'ChanExists' sort of function.
* ChannelRedirect() will not terminate the channel that fails to do a
channelredirect as it has done previously. Instead CHANNELREDIRECT_STATUS
will reflect if the attempt was successful of not.
* SetCallerPres() has been replaced with the CALLERPRES() dialplan function
and is now deprecated.
* DISA()'s fifth argument is now an options argument. If you have previously
used 'NOANSWER' in this argument, you'll need to convert that to the new
option 'n'.
* Macro() is now deprecated. If you need subroutines, you should use the
Gosub()/Return() applications. To replace MacroExclusive(), we have
introduced dialplan functions LOCK(), TRYLOCK(), and UNLOCK(). You may use
these functions in any location where you desire to ensure that only one
channel is executing that path at any one time. The Macro() applications
are deprecated for performance reasons. However, since Macro() has been
around for a long time and so many dialplans depend heavily on it, for the
sake of backwards compatibility it will not be removed . It is also worth
noting that using both Macro() and GoSub() at the same time is _heavily_
discouraged.
* Read() now sets a READSTATUS variable on exit. It does NOT automatically
return -1 (and hangup) anymore on error. If you want to hangup on error,
you need to do so explicitly in your dialplan.
* Privacy() no longer uses privacy.conf, so any options must be specified
directly in the application arguments.
* MusicOnHold application now has duration parameter which allows specifying
timeout in seconds.
* WaitMusicOnHold application is now deprecated in favor of extended MusicOnHold.
* SetMusicOnHold is now deprecated. You should use Set(CHANNEL(musicclass)=...)
instead.
* While app_directory has always relied on having a voicemail.conf or users.conf file
correctly set up, it now is dependent on app_voicemail being compiled as well.
* The arguments in ExecIf changed a bit, to be more like other applications.
The syntax is now ExecIf(<cond>?appiftrue(args):appiffalse(args)).
* The behavior of the Set application now depends upon a compatibility option,
set in asterisk.conf. To use the old 1.4 behavior, which allowed Set to take
multiple key/value pairs, set app_set=1.4 in [compat] in asterisk.conf. To
use the new behavior, which permits variables to be set with embedded commas,
set app_set=1.6 in [compat] in asterisk.conf. Note that you can have both
behaviors at the same time, if you switch to using MSet if you want the old
behavior.
Dialplan Functions:
* QUEUE_MEMBER_COUNT() has been deprecated in favor of the QUEUE_MEMBER() function. For
more information, issue a "show function QUEUE_MEMBER" from the CLI.
CDR:
* The cdr_sqlite module has been marked as deprecated in favor of
cdr_sqlite3_custom. It will potentially be removed from the tree
after Asterisk 1.6 is released.
* The cdr_odbc module now uses res_odbc to manage its connections. The
username and password parameters in cdr_odbc.conf, therefore, are no
longer used. The dsn parameter now points to an entry in res_odbc.conf.
* The uniqueid field in the core Asterisk structure has been changed from a
maximum 31 character field to a 149 character field, to account for all
possible values the systemname prefix could be. In the past, if the
systemname was too long, the uniqueid would have been truncated.
* The cdr_tds module now supports all versions of FreeTDS that contain
the db-lib frontend. It will also now log the userfield variable if
the target database table contains a column for it.
Formats:
* format_wav: The GAIN preprocessor definition and source code that used it
is removed. This change was made in response to user complaints of
choppiness or the clipping of loud signal peaks. To increase the volume
of voicemail messages, use the 'volgain' option in voicemail.conf
Channel Drivers:
* SIP: a small upgrade to support the "Record" button on the SNOM360,
which sends a sip INFO message with a "Record: on" or "Record: off"
header. If Asterisk is set up (via features.conf) to accept "One Touch Monitor"
requests (by default, via '*1'), then the user-configured dialpad sequence
is generated, and recording can be started and stopped via this button. The
file names and formats are all controlled via the normal mechanisms. If the
user has not configured the automon feature, the normal "415 Unsupported media type"
is returned, and nothing is done.
* SIP: The "call-limit" option is marked as deprecated. It still works in this version of
Asterisk, but will be removed in the following version. Please use the groupcount functions
in the dialplan to enforce call limits. The "limitonpeer" configuration option is
now renamed to "counteronpeer".
* SIP: The "username" option is now renamed to "defaultuser" to match "defaultip".
These are used only before registration to call a peer with the uri
sip:defaultuser@defaultip
The "username" setting still work, but is deprecated and will not work in
the next version of Asterisk.
* SIP: All of the functionality in SIPCHANINFO() has been implemented in CHANNEL(),
and you should start using that function instead for retrieving information about
the channel in a technology-agnostic way.
* chan_local.c: the comma delimiter inside the channel name has been changed to a
semicolon, in order to make the Local channel driver compatible with the comma
delimiter change in applications.
* H323: The "tos" setting has changed name to "tos_audio" and "cos" to "cos_audio"
to be compatible with settings in sip.conf. The "tos" and "cos" configuration
is deprecated and will stop working in the next release of Asterisk.
* Console: A new console channel driver, chan_console, has been added to Asterisk.
This new module can not be loaded at the same time as chan_alsa or chan_oss. The
default modules.conf only loads one of them (chan_oss by default). So, unless you
have modified your modules.conf to not use the autoload option, then you will need
to modify modules.conf to add another "noload" line to ensure that only one of
these three modules gets loaded.
* DAHDI: The chan_zap module that supported PSTN interfaces using
Zaptel has been renamed to chan_dahdi, and only supports the DAHDI
telephony driver package for PSTN interfaces. See the
Zaptel-to-DAHDI.txt file for more details on this transition.
* DAHDI: The "msdstrip" option has been deprecated, as it provides no value over
the method of stripping digits in the dialplan using variable substring syntax.
Configuration:
* pbx_dundi.c: tos parameter changed to use new values. Old values like lowdelay,
lowcost and other is not acceptable now. Look into qos.tex for description of
this parameter.
* queues.conf: the queue-lessthan sound file option is no longer available, and the
queue-round-seconds option no longer takes '1' as a valid parameter.
* If you have any third party modules which use a config file variable whose
name ends in a '+', please note that the append capability added to this
version may now conflict with that variable naming scheme. An easy
workaround is to ensure that a space occurs between the '+' and the '=',
to differentiate your variable from the append operator. This potential
conflict is unlikely, but is documented here to be thorough.
* skinny.conf now has seperate sections for lines and devices.
Please have a look at configs/skinny.conf.sample and update
your skinny.conf.
Manager:
* Manager has been upgraded to version 1.1 with a lot of changes.
Please check doc/manager_1_1.txt for information
* The IAXpeers command output has been changed to more closely resemble the
output of the SIPpeers command.
* cdr_manager now reports at the "cdr" level, not at "call" You may need to
change your manager.conf to add the level to existing AMI users, if they
want to see the CDR events generated.
* The Originate command now requires the Originate write permission. For
Originate with the Application parameter, you need the additional System
privilege if you want to do anything that calls out to a subshell.
Queues:
* New queue log events ADDMEMBER and REMOVEMEMBER have been added. Also, a
new value has been added to the TRANSFER event that indicates the caller's
original position in the queue they are being transfered from.
* Prior to Asterisk 1.6.2, queue names were treated in a case-sensitive
manner, meaning that queues with names like "sales" and "sALeS" would
be seen as unique queues. The parsing logic has changed to use case-
insensitive comparisons now when originally hashing based on queue
names, meaning that now the two queues mentioned as examples earlier
will be seen as having the same name.
iLBC Codec:
* Previously, the Asterisk source code distribution included the iLBC
encoder/decoder source code, from Global IP Solutions
(http://www.gipscorp.com). This code is not licensed for
distribution, and thus has been removed from the Asterisk source
code distribution. If you wish to use codec_ilbc to support iLBC
channels in Asterisk, you can run the contrib/scripts/get_ilbc_source.sh
script to download the source and put it in the proper place in
the Asterisk build tree. Once that is done you can follow your normal
steps of building Asterisk. You will need to run 'menuselect' and enable
the iLBC codec in the 'Codec Translators' category.
=== UPGRADE-1.6.txt -- Upgrade info for 1.4 to 1.6
===========================================================
From 1.6.0.1 to 1.6.0.2 or later, or 1.6.1 or later:
* The ast_agi_register_multiple() and ast_agi_unregister_multiple()
API calls were added in 1.6.0, so that modules that provide multiple
AGI commands could register/unregister them all with a single
step. However, these API calls were not implemented properly, and did
not allow the caller to know whether registration or unregistration
succeeded or failed. They have been redefined to now return success
or failure, but this means any code using these functions will need
be recompiled after upgrading to a version of Asterisk containing
these changes. In addition, the source code using these functions
should be reviewed to ensure it can properly react to failure
of registration or unregistration of its API commands.
* The ast_agi_fdprintf() API call has been renamed to ast_agi_send()
to better match what it really does, and the argument order has been
changed to be consistent with other API calls that perform similar
operations.

View File

@ -491,11 +491,11 @@ static int handle_gosub(struct ast_channel *chan, AGI *agi, int argc, char **arg
/* Lookup the priority label */
if ((priority = ast_findlabel_extension(chan, argv[1], argv[2], argv[3], chan->cid.cid_num)) < 0) {
ast_log(LOG_ERROR, "Priority '%s' not found in '%s@%s'\n", argv[3], argv[2], argv[1]);
ast_agi_fdprintf(chan, agi->fd, "200 result=-1 Gosub label not found\n");
ast_agi_send(agi->fd, chan, "200 result=-1 Gosub label not found\n");
return RESULT_FAILURE;
}
} else if (!ast_exists_extension(chan, argv[1], argv[2], priority, chan->cid.cid_num)) {
ast_agi_fdprintf(chan, agi->fd, "200 result=-1 Gosub label not found\n");
ast_agi_send(agi->fd, chan, "200 result=-1 Gosub label not found\n");
return RESULT_FAILURE;
}
@ -506,7 +506,7 @@ static int handle_gosub(struct ast_channel *chan, AGI *agi, int argc, char **arg
if (!(theapp = pbx_findapp("Gosub"))) {
ast_log(LOG_ERROR, "Gosub() cannot be found in the list of loaded applications\n");
ast_agi_fdprintf(chan, agi->fd, "503 result=-2 Gosub is not loaded\n");
ast_agi_send(agi->fd, chan, "503 result=-2 Gosub is not loaded\n");
return RESULT_FAILURE;
}
@ -540,19 +540,19 @@ static int handle_gosub(struct ast_channel *chan, AGI *agi, int argc, char **arg
struct ast_pbx *pbx = chan->pbx;
/* Suppress warning about PBX already existing */
chan->pbx = NULL;
ast_agi_fdprintf(chan, agi->fd, "100 result=0 Trying...\n");
ast_agi_send(agi->fd, chan, "100 result=0 Trying...\n");
ast_pbx_run(chan);
ast_agi_fdprintf(chan, agi->fd, "200 result=0 Gosub complete\n");
ast_agi_send(agi->fd, chan, "200 result=0 Gosub complete\n");
if (chan->pbx) {
ast_free(chan->pbx);
}
chan->pbx = pbx;
} else {
ast_agi_fdprintf(chan, agi->fd, "200 result=%d Gosub failed\n", res);
ast_agi_send(agi->fd, chan, "200 result=%d Gosub failed\n", res);
}
ast_free(gosub_args);
} else {
ast_agi_fdprintf(chan, agi->fd, "503 result=-2 Memory allocation failure\n");
ast_agi_send(agi->fd, chan, "503 result=-2 Memory allocation failure\n");
return RESULT_FAILURE;
}

View File

@ -66,11 +66,53 @@ typedef struct agi_command {
#define AGI_WEAK
#endif
int AGI_WEAK ast_agi_fdprintf(struct ast_channel *chan, int fd, char *fmt, ...);
/*!
* \brief
*
* Sends a string of text to an application connected via AGI.
*
* \param fd The file descriptor for the AGI session (from struct agi_state)
* \param chan Pointer to an associated Asterisk channel, if any
* \param fmt printf-style format string
* \return 0 for success, -1 for failure
*
*/
int AGI_WEAK ast_agi_send(int fd, struct ast_channel *chan, char *fmt, ...) __attribute__((format(printf, 3, 4)));
int AGI_WEAK ast_agi_register(struct ast_module *mod, agi_command *cmd);
int AGI_WEAK ast_agi_unregister(struct ast_module *mod, agi_command *cmd);
void AGI_WEAK ast_agi_register_multiple(struct ast_module *mod, agi_command *cmd, int len);
void AGI_WEAK ast_agi_unregister_multiple(struct ast_module *mod, agi_command *cmd, int len);
/*!
* \brief
*
* Registers a group of AGI commands, provided as an array of struct agi_command
* entries.
*
* \param mod Pointer to the module_info structure for the module that is registering the commands
* \param cmd Pointer to the first entry in the array of commands
* \param len Length of the array (use the ARRAY_LEN macro to determine this easily)
* \return 0 on success, -1 on failure
*
* \note If any command fails to register, all commands previously registered during the operation
* will be unregistered. In other words, this function registers all the provided commands, or none
* of them.
*/
int AGI_WEAK ast_agi_register_multiple(struct ast_module *mod, struct agi_command *cmd, unsigned int len);
/*!
* \brief
*
* Unregisters a group of AGI commands, provided as an array of struct agi_command
* entries.
*
* \param mod Pointer to the module_info structure for the module that is unregistering the commands
* \param cmd Pointer to the first entry in the array of commands
* \param len Length of the array (use the ARRAY_LEN macro to determine this easily)
* \return 0 on success, -1 on failure
*
* \note If any command fails to unregister, this function will continue to unregister the
* remaining commands in the array; it will not reregister the already-unregistered commands.
*/
int AGI_WEAK ast_agi_unregister_multiple(struct ast_module *mod, struct agi_command *cmd, unsigned int len);
#if defined(__cplusplus) || defined(c_plusplus)
}

View File

@ -304,7 +304,7 @@ static agi_command *find_command(char *cmds[], int exact);
AST_THREADSTORAGE(agi_buf);
#define AGI_BUF_INITSIZE 256
int ast_agi_fdprintf(struct ast_channel *chan, int fd, char *fmt, ...)
int ast_agi_send(int fd, struct ast_channel *chan, char *fmt, ...)
{
int res = 0;
va_list ap;
@ -771,7 +771,7 @@ static enum agi_result launch_netscript(char *agiurl, char *argv[], int *fds, in
}
}
if (ast_agi_fdprintf(NULL, s, "agi_network: yes\n") < 0) {
if (ast_agi_send(s, NULL, "agi_network: yes\n") < 0) {
if (errno != EINTR) {
ast_log(LOG_WARNING, "Connect to '%s' failed: %s\n", agiurl, strerror(errno));
close(s);
@ -782,7 +782,7 @@ static enum agi_result launch_netscript(char *agiurl, char *argv[], int *fds, in
/* If we have a script parameter, relay it to the fastagi server */
/* Script parameters take the form of: AGI(agi://my.example.com/?extension=${EXTEN}) */
if (!ast_strlen_zero(script))
ast_agi_fdprintf(NULL, s, "agi_network_script: %s\n", script);
ast_agi_send(s, NULL, "agi_network_script: %s\n", script);
ast_debug(4, "Wow, connected!\n");
fds[0] = s;
@ -911,40 +911,40 @@ static void setup_env(struct ast_channel *chan, char *request, int fd, int enhan
/* Print initial environment, with agi_request always being the first
thing */
ast_agi_fdprintf(chan, fd, "agi_request: %s\n", request);
ast_agi_fdprintf(chan, fd, "agi_channel: %s\n", chan->name);
ast_agi_fdprintf(chan, fd, "agi_language: %s\n", chan->language);
ast_agi_fdprintf(chan, fd, "agi_type: %s\n", chan->tech->type);
ast_agi_fdprintf(chan, fd, "agi_uniqueid: %s\n", chan->uniqueid);
ast_agi_fdprintf(chan, fd, "agi_version: %s\n", ast_get_version());
ast_agi_send(fd, chan, "agi_request: %s\n", request);
ast_agi_send(fd, chan, "agi_channel: %s\n", chan->name);
ast_agi_send(fd, chan, "agi_language: %s\n", chan->language);
ast_agi_send(fd, chan, "agi_type: %s\n", chan->tech->type);
ast_agi_send(fd, chan, "agi_uniqueid: %s\n", chan->uniqueid);
ast_agi_send(fd, chan, "agi_version: %s\n", ast_get_version());
/* ANI/DNIS */
ast_agi_fdprintf(chan, fd, "agi_callerid: %s\n", S_OR(chan->cid.cid_num, "unknown"));
ast_agi_fdprintf(chan, fd, "agi_calleridname: %s\n", S_OR(chan->cid.cid_name, "unknown"));
ast_agi_fdprintf(chan, fd, "agi_callingpres: %d\n", chan->cid.cid_pres);
ast_agi_fdprintf(chan, fd, "agi_callingani2: %d\n", chan->cid.cid_ani2);
ast_agi_fdprintf(chan, fd, "agi_callington: %d\n", chan->cid.cid_ton);
ast_agi_fdprintf(chan, fd, "agi_callingtns: %d\n", chan->cid.cid_tns);
ast_agi_fdprintf(chan, fd, "agi_dnid: %s\n", S_OR(chan->cid.cid_dnid, "unknown"));
ast_agi_fdprintf(chan, fd, "agi_rdnis: %s\n", S_OR(chan->cid.cid_rdnis, "unknown"));
ast_agi_send(fd, chan, "agi_callerid: %s\n", S_OR(chan->cid.cid_num, "unknown"));
ast_agi_send(fd, chan, "agi_calleridname: %s\n", S_OR(chan->cid.cid_name, "unknown"));
ast_agi_send(fd, chan, "agi_callingpres: %d\n", chan->cid.cid_pres);
ast_agi_send(fd, chan, "agi_callingani2: %d\n", chan->cid.cid_ani2);
ast_agi_send(fd, chan, "agi_callington: %d\n", chan->cid.cid_ton);
ast_agi_send(fd, chan, "agi_callingtns: %d\n", chan->cid.cid_tns);
ast_agi_send(fd, chan, "agi_dnid: %s\n", S_OR(chan->cid.cid_dnid, "unknown"));
ast_agi_send(fd, chan, "agi_rdnis: %s\n", S_OR(chan->cid.cid_rdnis, "unknown"));
/* Context information */
ast_agi_fdprintf(chan, fd, "agi_context: %s\n", chan->context);
ast_agi_fdprintf(chan, fd, "agi_extension: %s\n", chan->exten);
ast_agi_fdprintf(chan, fd, "agi_priority: %d\n", chan->priority);
ast_agi_fdprintf(chan, fd, "agi_enhanced: %s\n", enhanced ? "1.0" : "0.0");
ast_agi_send(fd, chan, "agi_context: %s\n", chan->context);
ast_agi_send(fd, chan, "agi_extension: %s\n", chan->exten);
ast_agi_send(fd, chan, "agi_priority: %d\n", chan->priority);
ast_agi_send(fd, chan, "agi_enhanced: %s\n", enhanced ? "1.0" : "0.0");
/* User information */
ast_agi_fdprintf(chan, fd, "agi_accountcode: %s\n", chan->accountcode ? chan->accountcode : "");
ast_agi_fdprintf(chan, fd, "agi_threadid: %ld\n", (long)pthread_self());
ast_agi_send(fd, chan, "agi_accountcode: %s\n", chan->accountcode ? chan->accountcode : "");
ast_agi_send(fd, chan, "agi_threadid: %ld\n", (long)pthread_self());
/* Send any parameters to the fastagi server that have been passed via the agi application */
/* Agi application paramaters take the form of: AGI(/path/to/example/script|${EXTEN}) */
for(count = 1; count < argc; count++)
ast_agi_fdprintf(chan, fd, "agi_arg_%d: %s\n", count, argv[count]);
ast_agi_send(fd, chan, "agi_arg_%d: %s\n", count, argv[count]);
/* End with empty return */
ast_agi_fdprintf(chan, fd, "\n");
ast_agi_send(fd, chan, "\n");
}
static int handle_answer(struct ast_channel *chan, AGI *agi, int argc, char *argv[])
@ -955,7 +955,7 @@ static int handle_answer(struct ast_channel *chan, AGI *agi, int argc, char *arg
if (chan->_state != AST_STATE_UP)
res = ast_answer(chan);
ast_agi_fdprintf(chan, agi->fd, "200 result=%d\n", res);
ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
}
@ -968,7 +968,7 @@ static int handle_waitfordigit(struct ast_channel *chan, AGI *agi, int argc, cha
if (sscanf(argv[3], "%d", &to) != 1)
return RESULT_SHOWUSAGE;
res = ast_waitfordigit_full(chan, to, agi->audio, agi->ctrl);
ast_agi_fdprintf(chan, agi->fd, "200 result=%d\n", res);
ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
}
@ -987,7 +987,7 @@ static int handle_sendtext(struct ast_channel *chan, AGI *agi, int argc, char *a
parsing, then here, add a newline at the end of the string
before sending it to ast_sendtext --DUDE */
res = ast_sendtext(chan, argv[2]);
ast_agi_fdprintf(chan, agi->fd, "200 result=%d\n", res);
ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
}
@ -1000,14 +1000,14 @@ static int handle_recvchar(struct ast_channel *chan, AGI *agi, int argc, char *a
res = ast_recvchar(chan,atoi(argv[2]));
if (res == 0) {
ast_agi_fdprintf(chan, agi->fd, "200 result=%d (timeout)\n", res);
ast_agi_send(agi->fd, chan, "200 result=%d (timeout)\n", res);
return RESULT_SUCCESS;
}
if (res > 0) {
ast_agi_fdprintf(chan, agi->fd, "200 result=%d\n", res);
ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
return RESULT_SUCCESS;
}
ast_agi_fdprintf(chan, agi->fd, "200 result=%d (hangup)\n", res);
ast_agi_send(agi->fd, chan, "200 result=%d (hangup)\n", res);
return RESULT_FAILURE;
}
@ -1020,10 +1020,10 @@ static int handle_recvtext(struct ast_channel *chan, AGI *agi, int argc, char *a
buf = ast_recvtext(chan, atoi(argv[2]));
if (buf) {
ast_agi_fdprintf(chan, agi->fd, "200 result=1 (%s)\n", buf);
ast_agi_send(agi->fd, chan, "200 result=1 (%s)\n", buf);
ast_free(buf);
} else {
ast_agi_fdprintf(chan, agi->fd, "200 result=-1\n");
ast_agi_send(agi->fd, chan, "200 result=-1\n");
}
return RESULT_SUCCESS;
}
@ -1048,9 +1048,9 @@ static int handle_tddmode(struct ast_channel *chan, AGI *agi, int argc, char *ar
}
res = ast_channel_setoption(chan, AST_OPTION_TDD, &x, sizeof(char), 0);
if (res != RESULT_SUCCESS) {
ast_agi_fdprintf(chan, agi->fd, "200 result=0\n");
ast_agi_send(agi->fd, chan, "200 result=0\n");
} else {
ast_agi_fdprintf(chan, agi->fd, "200 result=1\n");
ast_agi_send(agi->fd, chan, "200 result=1\n");
}
return RESULT_SUCCESS;
}
@ -1067,7 +1067,7 @@ static int handle_sendimage(struct ast_channel *chan, AGI *agi, int argc, char *
if (!ast_check_hangup(chan)) {
res = 0;
}
ast_agi_fdprintf(chan, agi->fd, "200 result=%d\n", res);
ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
}
@ -1102,7 +1102,7 @@ static int handle_controlstreamfile(struct ast_channel *chan, AGI *agi, int argc
res = ast_control_streamfile(chan, argv[3], fwd, rev, stop, suspend, NULL, skipms, NULL);
ast_agi_fdprintf(chan, agi->fd, "200 result=%d\n", res);
ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
}
@ -1124,7 +1124,7 @@ static int handle_streamfile(struct ast_channel *chan, AGI *agi, int argc, char
return RESULT_SHOWUSAGE;
if (!(fs = ast_openstream(chan, argv[2], chan->language))) {
ast_agi_fdprintf(chan, agi->fd, "200 result=%d endpos=%ld\n", 0, sample_offset);
ast_agi_send(agi->fd, chan, "200 result=%d endpos=%ld\n", 0, sample_offset);
return RESULT_SUCCESS;
}
@ -1152,7 +1152,7 @@ static int handle_streamfile(struct ast_channel *chan, AGI *agi, int argc, char
/* Stop this command, don't print a result line, as there is a new command */
return RESULT_SUCCESS;
}
ast_agi_fdprintf(chan, agi->fd, "200 result=%d endpos=%ld\n", res, sample_offset);
ast_agi_send(agi->fd, chan, "200 result=%d endpos=%ld\n", res, sample_offset);
return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
}
@ -1179,7 +1179,7 @@ static int handle_getoption(struct ast_channel *chan, AGI *agi, int argc, char *
}
if (!(fs = ast_openstream(chan, argv[2], chan->language))) {
ast_agi_fdprintf(chan, agi->fd, "200 result=%d endpos=%ld\n", 0, sample_offset);
ast_agi_send(agi->fd, chan, "200 result=%d endpos=%ld\n", 0, sample_offset);
ast_log(LOG_WARNING, "Unable to open %s\n", argv[2]);
return RESULT_SUCCESS;
}
@ -1217,7 +1217,7 @@ static int handle_getoption(struct ast_channel *chan, AGI *agi, int argc, char *
res=0;
}
ast_agi_fdprintf(chan, agi->fd, "200 result=%d endpos=%ld\n", res, sample_offset);
ast_agi_send(agi->fd, chan, "200 result=%d endpos=%ld\n", res, sample_offset);
return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
}
@ -1237,7 +1237,7 @@ static int handle_saynumber(struct ast_channel *chan, AGI *agi, int argc, char *
res = ast_say_number_full(chan, num, argv[3], chan->language, argc > 4 ? argv[4] : NULL, agi->audio, agi->ctrl);
if (res == 1)
return RESULT_SUCCESS;
ast_agi_fdprintf(chan, agi->fd, "200 result=%d\n", res);
ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
}
@ -1253,7 +1253,7 @@ static int handle_saydigits(struct ast_channel *chan, AGI *agi, int argc, char *
res = ast_say_digit_str_full(chan, argv[2], argv[3], chan->language, agi->audio, agi->ctrl);
if (res == 1) /* New command */
return RESULT_SUCCESS;
ast_agi_fdprintf(chan, agi->fd, "200 result=%d\n", res);
ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
}
@ -1267,7 +1267,7 @@ static int handle_sayalpha(struct ast_channel *chan, AGI *agi, int argc, char *a
res = ast_say_character_str_full(chan, argv[2], argv[3], chan->language, agi->audio, agi->ctrl);
if (res == 1) /* New command */
return RESULT_SUCCESS;
ast_agi_fdprintf(chan, agi->fd, "200 result=%d\n", res);
ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
}
@ -1282,7 +1282,7 @@ static int handle_saydate(struct ast_channel *chan, AGI *agi, int argc, char *ar
res = ast_say_date(chan, num, argv[3], chan->language);
if (res == 1)
return RESULT_SUCCESS;
ast_agi_fdprintf(chan, agi->fd, "200 result=%d\n", res);
ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
}
@ -1297,7 +1297,7 @@ static int handle_saytime(struct ast_channel *chan, AGI *agi, int argc, char *ar
res = ast_say_time(chan, num, argv[3], chan->language);
if (res == 1)
return RESULT_SUCCESS;
ast_agi_fdprintf(chan, agi->fd, "200 result=%d\n", res);
ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
}
@ -1331,7 +1331,7 @@ static int handle_saydatetime(struct ast_channel *chan, AGI *agi, int argc, char
if (res == 1)
return RESULT_SUCCESS;
ast_agi_fdprintf(chan, agi->fd, "200 result=%d\n", res);
ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
}
@ -1345,7 +1345,7 @@ static int handle_sayphonetic(struct ast_channel *chan, AGI *agi, int argc, char
res = ast_say_phonetic_str_full(chan, argv[2], argv[3], chan->language, agi->audio, agi->ctrl);
if (res == 1) /* New command */
return RESULT_SUCCESS;
ast_agi_fdprintf(chan, agi->fd, "200 result=%d\n", res);
ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
return (res >= 0) ? RESULT_SUCCESS : RESULT_FAILURE;
}
@ -1368,11 +1368,11 @@ static int handle_getdata(struct ast_channel *chan, AGI *agi, int argc, char *ar
if (res == 2) /* New command */
return RESULT_SUCCESS;
else if (res == 1)
ast_agi_fdprintf(chan, agi->fd, "200 result=%s (timeout)\n", data);
ast_agi_send(agi->fd, chan, "200 result=%s (timeout)\n", data);
else if (res < 0 )
ast_agi_fdprintf(chan, agi->fd, "200 result=-1\n");
ast_agi_send(agi->fd, chan, "200 result=-1\n");
else
ast_agi_fdprintf(chan, agi->fd, "200 result=%s\n", data);
ast_agi_send(agi->fd, chan, "200 result=%s\n", data);
return RESULT_SUCCESS;
}
@ -1382,7 +1382,7 @@ static int handle_setcontext(struct ast_channel *chan, AGI *agi, int argc, char
if (argc != 3)
return RESULT_SHOWUSAGE;
ast_copy_string(chan->context, argv[2], sizeof(chan->context));
ast_agi_fdprintf(chan, agi->fd, "200 result=0\n");
ast_agi_send(agi->fd, chan, "200 result=0\n");
return RESULT_SUCCESS;
}
@ -1391,7 +1391,7 @@ static int handle_setextension(struct ast_channel *chan, AGI *agi, int argc, cha
if (argc != 3)
return RESULT_SHOWUSAGE;
ast_copy_string(chan->exten, argv[2], sizeof(chan->exten));
ast_agi_fdprintf(chan, agi->fd, "200 result=0\n");
ast_agi_send(agi->fd, chan, "200 result=0\n");
return RESULT_SUCCESS;
}
@ -1408,7 +1408,7 @@ static int handle_setpriority(struct ast_channel *chan, AGI *agi, int argc, char
}
ast_explicit_goto(chan, NULL, NULL, pri);
ast_agi_fdprintf(chan, agi->fd, "200 result=0\n");
ast_agi_send(agi->fd, chan, "200 result=0\n");
return RESULT_SUCCESS;
}
@ -1483,12 +1483,12 @@ static int handle_recordfile(struct ast_channel *chan, AGI *agi, int argc, char
if (!res)
res = ast_waitstream(chan, argv[4]);
if (res) {
ast_agi_fdprintf(chan, agi->fd, "200 result=%d (randomerror) endpos=%ld\n", res, sample_offset);
ast_agi_send(agi->fd, chan, "200 result=%d (randomerror) endpos=%ld\n", res, sample_offset);
} else {
fs = ast_writefile(argv[2], argv[3], NULL, O_CREAT | O_WRONLY | (sample_offset ? O_APPEND : 0), 0, AST_FILE_MODE);
if (!fs) {
res = -1;
ast_agi_fdprintf(chan, agi->fd, "200 result=%d (writefile)\n", res);
ast_agi_send(agi->fd, chan, "200 result=%d (writefile)\n", res);
if (sildet)
ast_dsp_free(sildet);
return RESULT_FAILURE;
@ -1508,14 +1508,14 @@ static int handle_recordfile(struct ast_channel *chan, AGI *agi, int argc, char
res = ast_waitfor(chan, -1);
if (res < 0) {
ast_closestream(fs);
ast_agi_fdprintf(chan, agi->fd, "200 result=%d (waitfor) endpos=%ld\n", res,sample_offset);
ast_agi_send(agi->fd, chan, "200 result=%d (waitfor) endpos=%ld\n", res,sample_offset);
if (sildet)
ast_dsp_free(sildet);
return RESULT_FAILURE;
}
f = ast_read(chan);
if (!f) {
ast_agi_fdprintf(chan, agi->fd, "200 result=%d (hangup) endpos=%ld\n", -1, sample_offset);
ast_agi_send(agi->fd, chan, "200 result=%d (hangup) endpos=%ld\n", -1, sample_offset);
ast_closestream(fs);
if (sildet)
ast_dsp_free(sildet);
@ -1530,7 +1530,7 @@ static int handle_recordfile(struct ast_channel *chan, AGI *agi, int argc, char
ast_stream_rewind(fs, 200);
ast_truncstream(fs);
sample_offset = ast_tellstream(fs);
ast_agi_fdprintf(chan, agi->fd, "200 result=%d (dtmf) endpos=%ld\n", f->subclass, sample_offset);
ast_agi_send(agi->fd, chan, "200 result=%d (dtmf) endpos=%ld\n", f->subclass, sample_offset);
ast_closestream(fs);
ast_frfree(f);
if (sildet)
@ -1575,7 +1575,7 @@ static int handle_recordfile(struct ast_channel *chan, AGI *agi, int argc, char
ast_truncstream(fs);
sample_offset = ast_tellstream(fs);
}
ast_agi_fdprintf(chan, agi->fd, "200 result=%d (timeout) endpos=%ld\n", res, sample_offset);
ast_agi_send(agi->fd, chan, "200 result=%d (timeout) endpos=%ld\n", res, sample_offset);
ast_closestream(fs);
}
@ -1605,7 +1605,7 @@ static int handle_autohangup(struct ast_channel *chan, AGI *agi, int argc, char
whentohangup.tv_usec = (timeout - whentohangup.tv_sec) * 1000000.0;
}
ast_channel_setwhentohangup_tv(chan, whentohangup);
ast_agi_fdprintf(chan, agi->fd, "200 result=0\n");
ast_agi_send(agi->fd, chan, "200 result=0\n");
return RESULT_SUCCESS;
}
@ -1616,7 +1616,7 @@ static int handle_hangup(struct ast_channel *chan, AGI *agi, int argc, char **ar
if (argc == 1) {
/* no argument: hangup the current channel */
ast_softhangup(chan,AST_SOFTHANGUP_EXPLICIT);
ast_agi_fdprintf(chan, agi->fd, "200 result=1\n");
ast_agi_send(agi->fd, chan, "200 result=1\n");
return RESULT_SUCCESS;
} else if (argc == 2) {
/* one argument: look for info on the specified channel */
@ -1624,12 +1624,12 @@ static int handle_hangup(struct ast_channel *chan, AGI *agi, int argc, char **ar
if (c) {
/* we have a matching channel */
ast_softhangup(c,AST_SOFTHANGUP_EXPLICIT);
ast_agi_fdprintf(chan, agi->fd, "200 result=1\n");
ast_agi_send(agi->fd, chan, "200 result=1\n");
ast_channel_unlock(c);
return RESULT_SUCCESS;
}
/* if we get this far no channel name matched the argument given */
ast_agi_fdprintf(chan, agi->fd, "200 result=-1\n");
ast_agi_send(agi->fd, chan, "200 result=-1\n");
return RESULT_SUCCESS;
} else {
return RESULT_SHOWUSAGE;
@ -1671,7 +1671,7 @@ static int handle_exec(struct ast_channel *chan, AGI *agi, int argc, char **argv
ast_log(LOG_WARNING, "Could not find application (%s)\n", argv[1]);
res = -2;
}
ast_agi_fdprintf(chan, agi->fd, "200 result=%d\n", res);
ast_agi_send(agi->fd, chan, "200 result=%d\n", res);
/* Even though this is wrong, users are depending upon this result. */
return res;
@ -1694,7 +1694,7 @@ static int handle_setcallerid(struct ast_channel *chan, AGI *agi, int argc, char
ast_set_callerid(chan, l, n, NULL);
}
ast_agi_fdprintf(chan, agi->fd, "200 result=1\n");
ast_agi_send(agi->fd, chan, "200 result=1\n");
return RESULT_SUCCESS;
}
@ -1703,18 +1703,18 @@ static int handle_channelstatus(struct ast_channel *chan, AGI *agi, int argc, ch
struct ast_channel *c;
if (argc == 2) {
/* no argument: supply info on the current channel */
ast_agi_fdprintf(chan, agi->fd, "200 result=%d\n", chan->_state);
ast_agi_send(agi->fd, chan, "200 result=%d\n", chan->_state);
return RESULT_SUCCESS;
} else if (argc == 3) {
/* one argument: look for info on the specified channel */
c = ast_get_channel_by_name_locked(argv[2]);
if (c) {
ast_agi_fdprintf(chan, agi->fd, "200 result=%d\n", c->_state);
ast_agi_send(agi->fd, chan, "200 result=%d\n", c->_state);
ast_channel_unlock(c);
return RESULT_SUCCESS;
}
/* if we get this far no channel name matched the argument given */
ast_agi_fdprintf(chan, agi->fd, "200 result=-1\n");
ast_agi_send(agi->fd, chan, "200 result=-1\n");
return RESULT_SUCCESS;
} else {
return RESULT_SHOWUSAGE;
@ -1726,7 +1726,7 @@ static int handle_setvariable(struct ast_channel *chan, AGI *agi, int argc, char
if (argv[3])
pbx_builtin_setvar_helper(chan, argv[2], argv[3]);
ast_agi_fdprintf(chan, agi->fd, "200 result=1\n");
ast_agi_send(agi->fd, chan, "200 result=1\n");
return RESULT_SUCCESS;
}
@ -1746,9 +1746,9 @@ static int handle_getvariable(struct ast_channel *chan, AGI *agi, int argc, char
}
if (ret)
ast_agi_fdprintf(chan, agi->fd, "200 result=1 (%s)\n", ret);
ast_agi_send(agi->fd, chan, "200 result=1 (%s)\n", ret);
else
ast_agi_fdprintf(chan, agi->fd, "200 result=0\n");
ast_agi_send(agi->fd, chan, "200 result=0\n");
return RESULT_SUCCESS;
}
@ -1767,9 +1767,9 @@ static int handle_getvariablefull(struct ast_channel *chan, AGI *agi, int argc,
}
if (chan2) {
pbx_substitute_variables_helper(chan2, argv[3], tmp, sizeof(tmp) - 1);
ast_agi_fdprintf(chan, agi->fd, "200 result=1 (%s)\n", tmp);
ast_agi_send(agi->fd, chan, "200 result=1 (%s)\n", tmp);
} else {
ast_agi_fdprintf(chan, agi->fd, "200 result=0\n");
ast_agi_send(agi->fd, chan, "200 result=0\n");
}
if (chan2 && (chan2 != chan))
ast_channel_unlock(chan2);
@ -1788,7 +1788,7 @@ static int handle_verbose(struct ast_channel *chan, AGI *agi, int argc, char **a
ast_verb(level, "%s: %s\n", chan->data, argv[1]);
ast_agi_fdprintf(chan, agi->fd, "200 result=1\n");
ast_agi_send(agi->fd, chan, "200 result=1\n");
return RESULT_SUCCESS;
}
@ -1802,9 +1802,9 @@ static int handle_dbget(struct ast_channel *chan, AGI *agi, int argc, char **arg
return RESULT_SHOWUSAGE;
res = ast_db_get(argv[2], argv[3], tmp, sizeof(tmp));
if (res)
ast_agi_fdprintf(chan, agi->fd, "200 result=0\n");
ast_agi_send(agi->fd, chan, "200 result=0\n");
else
ast_agi_fdprintf(chan, agi->fd, "200 result=1 (%s)\n", tmp);
ast_agi_send(agi->fd, chan, "200 result=1 (%s)\n", tmp);
return RESULT_SUCCESS;
}
@ -1816,7 +1816,7 @@ static int handle_dbput(struct ast_channel *chan, AGI *agi, int argc, char **arg
if (argc != 5)
return RESULT_SHOWUSAGE;
res = ast_db_put(argv[2], argv[3], argv[4]);
ast_agi_fdprintf(chan, agi->fd, "200 result=%c\n", res ? '0' : '1');
ast_agi_send(agi->fd, chan, "200 result=%c\n", res ? '0' : '1');
return RESULT_SUCCESS;
}
@ -1827,7 +1827,7 @@ static int handle_dbdel(struct ast_channel *chan, AGI *agi, int argc, char **arg
if (argc != 4)
return RESULT_SHOWUSAGE;
res = ast_db_del(argv[2], argv[3]);
ast_agi_fdprintf(chan, agi->fd, "200 result=%c\n", res ? '0' : '1');
ast_agi_send(agi->fd, chan, "200 result=%c\n", res ? '0' : '1');
return RESULT_SUCCESS;
}
@ -1842,7 +1842,7 @@ static int handle_dbdeltree(struct ast_channel *chan, AGI *agi, int argc, char *
else
res = ast_db_deltree(argv[2], NULL);
ast_agi_fdprintf(chan, agi->fd, "200 result=%c\n", res ? '0' : '1');
ast_agi_send(agi->fd, chan, "200 result=%c\n", res ? '0' : '1');
return RESULT_SUCCESS;
}
@ -1877,7 +1877,7 @@ static char *handle_cli_agi_debug(struct ast_cli_entry *e, int cmd, struct ast_c
static int handle_noop(struct ast_channel *chan, AGI *agi, int arg, char *argv[])
{
ast_agi_fdprintf(chan, agi->fd, "200 result=0\n");
ast_agi_send(agi->fd, chan, "200 result=0\n");
return RESULT_SUCCESS;
}
@ -1887,7 +1887,7 @@ static int handle_setmusic(struct ast_channel *chan, AGI *agi, int argc, char *a
ast_moh_start(chan, argc > 3 ? argv[3] : NULL, NULL);
else if (!strncasecmp(argv[2], "off", 3))
ast_moh_stop(chan);
ast_agi_fdprintf(chan, agi->fd, "200 result=0\n");
ast_agi_send(agi->fd, chan, "200 result=0\n");
return RESULT_SUCCESS;
}
@ -1895,14 +1895,14 @@ static int handle_speechcreate(struct ast_channel *chan, AGI *agi, int argc, cha
{
/* If a structure already exists, return an error */
if (agi->speech) {
ast_agi_fdprintf(chan, agi->fd, "200 result=0\n");
ast_agi_send(agi->fd, chan, "200 result=0\n");
return RESULT_SUCCESS;
}
if ((agi->speech = ast_speech_new(argv[2], AST_FORMAT_SLINEAR)))
ast_agi_fdprintf(chan, agi->fd, "200 result=1\n");
ast_agi_send(agi->fd, chan, "200 result=1\n");
else
ast_agi_fdprintf(chan, agi->fd, "200 result=0\n");
ast_agi_send(agi->fd, chan, "200 result=0\n");
return RESULT_SUCCESS;
}
@ -1915,12 +1915,12 @@ static int handle_speechset(struct ast_channel *chan, AGI *agi, int argc, char *
/* Check to make sure speech structure exists */
if (!agi->speech) {
ast_agi_fdprintf(chan, agi->fd, "200 result=0\n");
ast_agi_send(agi->fd, chan, "200 result=0\n");
return RESULT_SUCCESS;
}
ast_speech_change(agi->speech, argv[2], argv[3]);
ast_agi_fdprintf(chan, agi->fd, "200 result=1\n");
ast_agi_send(agi->fd, chan, "200 result=1\n");
return RESULT_SUCCESS;
}
@ -1930,9 +1930,9 @@ static int handle_speechdestroy(struct ast_channel *chan, AGI *agi, int argc, ch
if (agi->speech) {
ast_speech_destroy(agi->speech);
agi->speech = NULL;
ast_agi_fdprintf(chan, agi->fd, "200 result=1\n");
ast_agi_send(agi->fd, chan, "200 result=1\n");
} else {
ast_agi_fdprintf(chan, agi->fd, "200 result=0\n");
ast_agi_send(agi->fd, chan, "200 result=0\n");
}
return RESULT_SUCCESS;
@ -1944,14 +1944,14 @@ static int handle_speechloadgrammar(struct ast_channel *chan, AGI *agi, int argc
return RESULT_SHOWUSAGE;
if (!agi->speech) {
ast_agi_fdprintf(chan, agi->fd, "200 result=0\n");
ast_agi_send(agi->fd, chan, "200 result=0\n");
return RESULT_SUCCESS;
}
if (ast_speech_grammar_load(agi->speech, argv[3], argv[4]))
ast_agi_fdprintf(chan, agi->fd, "200 result=0\n");
ast_agi_send(agi->fd, chan, "200 result=0\n");
else
ast_agi_fdprintf(chan, agi->fd, "200 result=1\n");
ast_agi_send(agi->fd, chan, "200 result=1\n");
return RESULT_SUCCESS;
}
@ -1962,14 +1962,14 @@ static int handle_speechunloadgrammar(struct ast_channel *chan, AGI *agi, int ar
return RESULT_SHOWUSAGE;
if (!agi->speech) {
ast_agi_fdprintf(chan, agi->fd, "200 result=0\n");
ast_agi_send(agi->fd, chan, "200 result=0\n");
return RESULT_SUCCESS;
}
if (ast_speech_grammar_unload(agi->speech, argv[3]))
ast_agi_fdprintf(chan, agi->fd, "200 result=0\n");
ast_agi_send(agi->fd, chan, "200 result=0\n");
else
ast_agi_fdprintf(chan, agi->fd, "200 result=1\n");
ast_agi_send(agi->fd, chan, "200 result=1\n");
return RESULT_SUCCESS;
}
@ -1980,14 +1980,14 @@ static int handle_speechactivategrammar(struct ast_channel *chan, AGI *agi, int
return RESULT_SHOWUSAGE;
if (!agi->speech) {
ast_agi_fdprintf(chan, agi->fd, "200 result=0\n");
ast_agi_send(agi->fd, chan, "200 result=0\n");
return RESULT_SUCCESS;
}
if (ast_speech_grammar_activate(agi->speech, argv[3]))
ast_agi_fdprintf(chan, agi->fd, "200 result=0\n");
ast_agi_send(agi->fd, chan, "200 result=0\n");
else
ast_agi_fdprintf(chan, agi->fd, "200 result=1\n");
ast_agi_send(agi->fd, chan, "200 result=1\n");
return RESULT_SUCCESS;
}
@ -1998,14 +1998,14 @@ static int handle_speechdeactivategrammar(struct ast_channel *chan, AGI *agi, in
return RESULT_SHOWUSAGE;
if (!agi->speech) {
ast_agi_fdprintf(chan, agi->fd, "200 result=0\n");
ast_agi_send(agi->fd, chan, "200 result=0\n");
return RESULT_SUCCESS;
}
if (ast_speech_grammar_deactivate(agi->speech, argv[3]))
ast_agi_fdprintf(chan, agi->fd, "200 result=0\n");
ast_agi_send(agi->fd, chan, "200 result=0\n");
else
ast_agi_fdprintf(chan, agi->fd, "200 result=1\n");
ast_agi_send(agi->fd, chan, "200 result=1\n");
return RESULT_SUCCESS;
}
@ -2045,7 +2045,7 @@ static int handle_speechrecognize(struct ast_channel *chan, AGI *agi, int argc,
return RESULT_SHOWUSAGE;
if (!speech) {
ast_agi_fdprintf(chan, agi->fd, "200 result=0\n");
ast_agi_send(agi->fd, chan, "200 result=0\n");
return RESULT_SUCCESS;
}
@ -2059,7 +2059,7 @@ static int handle_speechrecognize(struct ast_channel *chan, AGI *agi, int argc,
/* We want frames coming in signed linear */
old_read_format = chan->readformat;
if (ast_set_read_format(chan, AST_FORMAT_SLINEAR)) {
ast_agi_fdprintf(chan, agi->fd, "200 result=0\n");
ast_agi_send(agi->fd, chan, "200 result=0\n");
return RESULT_SUCCESS;
}
@ -2164,13 +2164,13 @@ static int handle_speechrecognize(struct ast_channel *chan, AGI *agi, int argc,
i++;
}
/* Print out */
ast_agi_fdprintf(chan, agi->fd, "200 result=1 (speech) endpos=%ld results=%d %s\n", current_offset, i, tmp);
ast_agi_send(agi->fd, chan, "200 result=1 (speech) endpos=%ld results=%d %s\n", current_offset, i, tmp);
} else if (!strcasecmp(reason, "dtmf")) {
ast_agi_fdprintf(chan, agi->fd, "200 result=1 (digit) digit=%c endpos=%ld\n", dtmf, current_offset);
ast_agi_send(agi->fd, chan, "200 result=1 (digit) digit=%c endpos=%ld\n", dtmf, current_offset);
} else if (!strcasecmp(reason, "hangup") || !strcasecmp(reason, "timeout")) {
ast_agi_fdprintf(chan, agi->fd, "200 result=1 (%s) endpos=%ld\n", reason, current_offset);
ast_agi_send(agi->fd, chan, "200 result=1 (%s) endpos=%ld\n", reason, current_offset);
} else {
ast_agi_fdprintf(chan, agi->fd, "200 result=0 endpos=%ld\n", current_offset);
ast_agi_send(agi->fd, chan, "200 result=0 endpos=%ld\n", current_offset);
}
return RESULT_SUCCESS;
@ -2178,7 +2178,7 @@ static int handle_speechrecognize(struct ast_channel *chan, AGI *agi, int argc,
static int handle_asyncagi_break(struct ast_channel *chan, AGI *agi, int argc, char *argv[])
{
ast_agi_fdprintf(chan, agi->fd, "200 result=0\n");
ast_agi_send(agi->fd, chan, "200 result=0\n");
return AST_PBX_KEEPALIVE;
}
@ -2545,21 +2545,50 @@ int ast_agi_unregister(struct ast_module *mod, agi_command *cmd)
return unregistered;
}
void ast_agi_register_multiple(struct ast_module *mod, agi_command *cmd, int len)
int ast_agi_register_multiple(struct ast_module *mod, struct agi_command *cmd, unsigned int len)
{
int i;
unsigned int i, x = 0;
for (i = 0; i < len; i++)
ast_agi_register(mod, cmd + i);
for (i = 0; i < len; i++) {
if (ast_agi_register(mod, cmd + i) == 1) {
x++;
continue;
}
/* registration failed, unregister everything
that had been registered up to that point
*/
for (; x > 0; x--) {
/* we are intentionally ignoring the
result of ast_agi_unregister() here,
but it should be safe to do so since
we just registered these commands and
the only possible way for unregistration
to fail is if the command is not
registered
*/
(void) ast_agi_unregister(mod, cmd + x - 1);
}
return -1;
}
return 0;
}
void ast_agi_unregister_multiple(struct ast_module *mod, agi_command *cmd, int len)
int ast_agi_unregister_multiple(struct ast_module *mod, struct agi_command *cmd, unsigned int len)
{
int i;
unsigned int i;
int res = 0;
for (i = 0; i < len; i++)
ast_agi_unregister(mod, cmd + i);
for (i = 0; i < len; i++) {
/* remember whether any of the unregistration
attempts failed... there is no recourse if
any of them do
*/
res |= ast_agi_unregister(mod, cmd + i);
}
return res;
}
static agi_command *find_command(char *cmds[], int exact)
@ -2701,9 +2730,9 @@ static int agi_handle_command(struct ast_channel *chan, AGI *agi, char *buf, int
"Result: %s\r\n", chan->name, command_id, ami_cmd, resultcode, ami_res);
switch(res) {
case RESULT_SHOWUSAGE:
ast_agi_fdprintf(chan, agi->fd, "520-Invalid command syntax. Proper usage follows:\n");
ast_agi_fdprintf(chan, agi->fd, c->usage);
ast_agi_fdprintf(chan, agi->fd, "520 End of proper usage.\n");
ast_agi_send(agi->fd, chan, "520-Invalid command syntax. Proper usage follows:\n");
ast_agi_send(agi->fd, NULL, "%s", c->usage);
ast_agi_send(agi->fd, chan, "520 End of proper usage.\n");
break;
case AST_PBX_KEEPALIVE:
/* We've been asked to keep alive, so do so */
@ -2715,7 +2744,7 @@ static int agi_handle_command(struct ast_channel *chan, AGI *agi, char *buf, int
return -1;
}
} else if ((c = find_command(argv, 0))) {
ast_agi_fdprintf(chan, agi->fd, "511 Command Not Permitted on a dead channel\n");
ast_agi_send(agi->fd, chan, "511 Command Not Permitted on a dead channel\n");
manager_event(EVENT_FLAG_CALL, "AGIExec",
"SubEvent: End\r\n"
"Channel: %s\r\n"
@ -2724,7 +2753,7 @@ static int agi_handle_command(struct ast_channel *chan, AGI *agi, char *buf, int
"ResultCode: 511\r\n"
"Result: Command not permitted on a dead channel\r\n", chan->name, command_id, ami_cmd);
} else {
ast_agi_fdprintf(chan, agi->fd, "510 Invalid or unknown command\n");
ast_agi_send(agi->fd, chan, "510 Invalid or unknown command\n");
manager_event(EVENT_FLAG_CALL, "AGIExec",
"SubEvent: End\r\n"
"Channel: %s\r\n"
@ -3195,7 +3224,10 @@ static struct ast_cli_entry cli_agi[] = {
static int unload_module(void)
{
ast_cli_unregister_multiple(cli_agi, sizeof(cli_agi) / sizeof(struct ast_cli_entry));
ast_agi_unregister_multiple(ast_module_info->self, commands, sizeof(commands) / sizeof(struct agi_command));
/* we can safely ignore the result of ast_agi_unregister_multiple() here, since it cannot fail, as
we know that these commands were registered by this module and are still registered
*/
(void) ast_agi_unregister_multiple(ast_module_info->self, commands, ARRAY_LEN(commands));
ast_unregister_application(eapp);
ast_unregister_application(deadapp);
ast_manager_unregister("AGI");
@ -3205,7 +3237,10 @@ static int unload_module(void)
static int load_module(void)
{
ast_cli_register_multiple(cli_agi, sizeof(cli_agi) / sizeof(struct ast_cli_entry));
ast_agi_register_multiple(ast_module_info->self, commands, sizeof(commands) / sizeof(struct agi_command));
/* we can safely ignore the result of ast_agi_register_multiple() here, since it cannot fail, as
no other commands have been registered yet
*/
(void) ast_agi_register_multiple(ast_module_info->self, commands, ARRAY_LEN(commands));
ast_register_application(deadapp, deadagi_exec, deadsynopsis, descrip);
ast_register_application(eapp, eagi_exec, esynopsis, descrip);
ast_manager_register2("AGI", EVENT_FLAG_CALL, action_add_agi_cmd, "Add an AGI command to execute by Async AGI", mandescr_asyncagi);