aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkpfleming <kpfleming@f38db490-d61c-443f-a65b-d21fe96a405b>2008-11-19 13:19:49 +0000
committerkpfleming <kpfleming@f38db490-d61c-443f-a65b-d21fe96a405b>2008-11-19 13:19:49 +0000
commit84de3e7ec27cbda09e16e0c2a49e330862ac271f (patch)
tree01ab767bcc6afcdf0de8f3c318a97b5122cb720e
parent296683f301336b411ceef41a96ebe5a9684fc6e0 (diff)
Merged revisions 157706 via svnmerge from
https://origsvn.digium.com/svn/asterisk/trunk ........ r157706 | kpfleming | 2008-11-19 06:42:19 -0600 (Wed, 19 Nov 2008) | 5 lines 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/branches/1.6.0@157738 f38db490-d61c-443f-a65b-d21fe96a405b
-rw-r--r--UPGRADE-1.6.txt250
-rw-r--r--UPGRADE.txt269
-rw-r--r--apps/app_stack.c14
-rw-r--r--channels/chan_sip.c2
-rw-r--r--include/asterisk/agi.h48
-rw-r--r--res/res_agi.c285
6 files changed, 485 insertions, 383 deletions
diff --git a/UPGRADE-1.6.txt b/UPGRADE-1.6.txt
new file mode 100644
index 000000000..8fb0a0f71
--- /dev/null
+++ b/UPGRADE-1.6.txt
@@ -0,0 +1,250 @@
+=========================================================
+=== 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
+=== 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.
+
+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.
+
+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.
+
+* 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.
+
+* 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.
+
+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.
+
+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.
diff --git a/UPGRADE.txt b/UPGRADE.txt
index 8fb0a0f71..0f04671d8 100644
--- a/UPGRADE.txt
+++ b/UPGRADE.txt
@@ -1,250 +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.
-
-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.
-
-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.
-
-* 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.
-
-* 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.
-
-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.
-
-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:
+
+* 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.
diff --git a/apps/app_stack.c b/apps/app_stack.c
index 841562536..a6333d8d4 100644
--- a/apps/app_stack.c
+++ b/apps/app_stack.c
@@ -406,11 +406,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;
}
@@ -421,7 +421,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;
}
@@ -455,19 +455,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;
}
diff --git a/channels/chan_sip.c b/channels/chan_sip.c
index e7c5ebb04..a4cec6310 100644
--- a/channels/chan_sip.c
+++ b/channels/chan_sip.c
@@ -4487,7 +4487,7 @@ static int update_call_counter(struct sip_pvt *fup, int event)
int outgoing = fup->outgoing_call;
struct sip_user *u = NULL;
struct sip_peer *p = NULL;
- ast_mutex_t *pu_lock;
+ ast_mutex_t *pu_lock = NULL;
ast_debug(3, "Updating call counter for %s call\n", outgoing ? "outgoing" : "incoming");
diff --git a/include/asterisk/agi.h b/include/asterisk/agi.h
index 609e98815..10c88e632 100644
--- a/include/asterisk/agi.h
+++ b/include/asterisk/agi.h
@@ -61,11 +61,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)
}
diff --git a/res/res_agi.c b/res/res_agi.c
index 2df15c4d8..14d80d969 100644
--- a/res/res_agi.c
+++ b/res/res_agi.c
@@ -114,7 +114,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;
@@ -581,7 +581,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);
@@ -592,7 +592,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;
@@ -743,40 +743,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[])
@@ -787,7 +787,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;
}
@@ -800,7 +800,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;
}
@@ -819,7 +819,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;
}
@@ -832,17 +832,15 @@ 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;
}
- else {
- ast_agi_fdprintf(chan, agi->fd, "200 result=%d (hangup)\n", res);
- return RESULT_FAILURE;
- }
+ ast_agi_send(agi->fd, chan, "200 result=%d (hangup)\n", res);
+ return RESULT_FAILURE;
}
static int handle_recvtext(struct ast_channel *chan, AGI *agi, int argc, char *argv[])
@@ -854,10 +852,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;
}
@@ -879,9 +877,9 @@ static int handle_tddmode(struct ast_channel *chan, AGI *agi, int argc, char *ar
x = 1;
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;
}
@@ -895,7 +893,7 @@ static int handle_sendimage(struct ast_channel *chan, AGI *agi, int argc, char *
res = ast_send_image(chan, argv[2]);
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;
}
@@ -932,7 +930,7 @@ static int handle_controlstreamfile(struct ast_channel *chan, AGI *agi, int argc
res = ast_control_streamfile(chan, argv[3], fwd, rev, stop, pause, 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;
}
@@ -954,7 +952,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;
}
@@ -982,7 +980,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;
}
@@ -1009,7 +1007,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;
}
@@ -1047,7 +1045,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;
}
@@ -1067,7 +1065,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;
}
@@ -1083,7 +1081,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;
}
@@ -1097,7 +1095,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;
}
@@ -1112,7 +1110,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;
}
@@ -1127,7 +1125,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;
}
@@ -1161,7 +1159,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;
}
@@ -1175,7 +1173,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;
}
@@ -1198,11 +1196,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;
}
@@ -1212,7 +1210,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;
}
@@ -1221,7 +1219,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;
}
@@ -1238,7 +1236,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;
}
@@ -1314,12 +1312,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;
@@ -1339,14 +1337,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);
@@ -1361,7 +1359,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)
@@ -1406,7 +1404,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);
}
@@ -1433,7 +1431,7 @@ static int handle_autohangup(struct ast_channel *chan, AGI *agi, int argc, char
chan->whentohangup = time(NULL) + timeout;
else
chan->whentohangup = 0;
- ast_agi_fdprintf(chan, agi->fd, "200 result=0\n");
+ ast_agi_send(agi->fd, chan, "200 result=0\n");
return RESULT_SUCCESS;
}
@@ -1444,7 +1442,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 */
@@ -1452,12 +1450,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;
@@ -1496,7 +1494,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;
@@ -1519,7 +1517,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;
}
@@ -1528,18 +1526,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;
@@ -1551,7 +1549,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;
}
@@ -1571,9 +1569,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;
}
@@ -1592,9 +1590,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);
@@ -1613,7 +1611,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;
}
@@ -1627,9 +1625,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;
}
@@ -1641,7 +1639,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;
}
@@ -1652,7 +1650,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;
}
@@ -1667,7 +1665,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;
}
@@ -1702,7 +1700,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;
}
@@ -1712,7 +1710,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;
}
@@ -1720,14 +1718,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;
}
@@ -1740,12 +1738,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;
}
@@ -1755,9 +1753,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;
@@ -1769,14 +1767,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;
}
@@ -1787,14 +1785,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;
}
@@ -1805,14 +1803,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;
}
@@ -1823,14 +1821,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;
}
@@ -1870,7 +1868,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;
}
@@ -1884,7 +1882,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;
}
@@ -1989,13 +1987,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;
@@ -2003,7 +2001,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;
}
@@ -2418,21 +2416,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++) {
+ if (ast_agi_register(mod, cmd + i) == 1) {
+ x++;
+ continue;
+ }
- for (i = 0; i < len; i++)
- ast_agi_register(mod, cmd + i);
+ /* 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)
@@ -2574,9 +2601,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 */
@@ -2588,7 +2615,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"
@@ -2597,7 +2624,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"
@@ -3018,7 +3045,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");
@@ -3028,7 +3058,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);