PJPROJECT logging: Made easier to get available logging levels.
[asterisk/asterisk.git] / main / pbx_builtins.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2015 Fairview 5 Engineering, LLC
5  *
6  * George Joseph <george.joseph@fairview5.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18
19 /*! \file
20  *
21  * \brief Core PBX builtin routines.
22  *
23  * \author George Joseph <george.joseph@fairview5.com>
24  */
25
26 /*** MODULEINFO
27         <support_level>core</support_level>
28  ***/
29
30 #include "asterisk.h"
31
32 #include "asterisk/_private.h"
33 #include "asterisk/pbx.h"
34 #include "asterisk/causes.h"
35 #include "asterisk/indications.h"
36 #include "asterisk/stasis_channels.h"
37 #include "asterisk/say.h"
38 #include "asterisk/app.h"
39 #include "asterisk/module.h"
40 #include "pbx_private.h"
41
42 /*** DOCUMENTATION
43         <application name="Answer" language="en_US">
44                 <synopsis>
45                         Answer a channel if ringing.
46                 </synopsis>
47                 <syntax>
48                         <parameter name="delay">
49                                 <para>Asterisk will wait this number of milliseconds before returning to
50                                 the dialplan after answering the call.</para>
51                         </parameter>
52                 </syntax>
53                 <description>
54                         <para>If the call has not been answered, this application will
55                         answer it. Otherwise, it has no effect on the call.</para>
56                 </description>
57                 <see-also>
58                         <ref type="application">Hangup</ref>
59                 </see-also>
60         </application>
61         <application name="BackGround" language="en_US">
62                 <synopsis>
63                         Play an audio file while waiting for digits of an extension to go to.
64                 </synopsis>
65                 <syntax>
66                         <parameter name="filenames" required="true" argsep="&amp;">
67                                 <argument name="filename1" required="true" />
68                                 <argument name="filename2" multiple="true" />
69                         </parameter>
70                         <parameter name="options">
71                                 <optionlist>
72                                         <option name="s">
73                                                 <para>Causes the playback of the message to be skipped
74                                                 if the channel is not in the <literal>up</literal> state (i.e. it
75                                                 hasn't been answered yet). If this happens, the
76                                                 application will return immediately.</para>
77                                         </option>
78                                         <option name="n">
79                                                 <para>Don't answer the channel before playing the files.</para>
80                                         </option>
81                                         <option name="m">
82                                                 <para>Only break if a digit hit matches a one digit
83                                                 extension in the destination context.</para>
84                                         </option>
85                                 </optionlist>
86                         </parameter>
87                         <parameter name="langoverride">
88                                 <para>Explicitly specifies which language to attempt to use for the requested sound files.</para>
89                         </parameter>
90                         <parameter name="context">
91                                 <para>This is the dialplan context that this application will use when exiting
92                                 to a dialed extension.</para>
93                         </parameter>
94                 </syntax>
95                 <description>
96                         <para>This application will play the given list of files <emphasis>(do not put extension)</emphasis>
97                         while waiting for an extension to be dialed by the calling channel. To continue waiting
98                         for digits after this application has finished playing files, the <literal>WaitExten</literal>
99                         application should be used.</para>
100                         <para>If one of the requested sound files does not exist, call processing will be terminated.</para>
101                         <para>This application sets the following channel variable upon completion:</para>
102                         <variablelist>
103                                 <variable name="BACKGROUNDSTATUS">
104                                         <para>The status of the background attempt as a text string.</para>
105                                         <value name="SUCCESS" />
106                                         <value name="FAILED" />
107                                 </variable>
108                         </variablelist>
109                 </description>
110                 <see-also>
111                         <ref type="application">ControlPlayback</ref>
112                         <ref type="application">WaitExten</ref>
113                         <ref type="application">BackgroundDetect</ref>
114                         <ref type="function">TIMEOUT</ref>
115                 </see-also>
116         </application>
117         <application name="Busy" language="en_US">
118                 <synopsis>
119                         Indicate the Busy condition.
120                 </synopsis>
121                 <syntax>
122                         <parameter name="timeout">
123                                 <para>If specified, the calling channel will be hung up after the specified number of seconds.
124                                 Otherwise, this application will wait until the calling channel hangs up.</para>
125                         </parameter>
126                 </syntax>
127                 <description>
128                         <para>This application will indicate the busy condition to the calling channel.</para>
129                 </description>
130                 <see-also>
131                         <ref type="application">Congestion</ref>
132                         <ref type="application">Progress</ref>
133                         <ref type="application">Playtones</ref>
134                         <ref type="application">Hangup</ref>
135                 </see-also>
136         </application>
137         <application name="Congestion" language="en_US">
138                 <synopsis>
139                         Indicate the Congestion condition.
140                 </synopsis>
141                 <syntax>
142                         <parameter name="timeout">
143                                 <para>If specified, the calling channel will be hung up after the specified number of seconds.
144                                 Otherwise, this application will wait until the calling channel hangs up.</para>
145                         </parameter>
146                 </syntax>
147                 <description>
148                         <para>This application will indicate the congestion condition to the calling channel.</para>
149                 </description>
150                 <see-also>
151                         <ref type="application">Busy</ref>
152                         <ref type="application">Progress</ref>
153                         <ref type="application">Playtones</ref>
154                         <ref type="application">Hangup</ref>
155                 </see-also>
156         </application>
157         <application name="ExecIfTime" language="en_US">
158                 <synopsis>
159                         Conditional application execution based on the current time.
160                 </synopsis>
161                 <syntax argsep="?">
162                         <parameter name="day_condition" required="true">
163                                 <argument name="times" required="true" />
164                                 <argument name="weekdays" required="true" />
165                                 <argument name="mdays" required="true" />
166                                 <argument name="months" required="true" />
167                                 <argument name="timezone" required="false" />
168                         </parameter>
169                         <parameter name="appname" required="true" hasparams="optional">
170                                 <argument name="appargs" required="true" />
171                         </parameter>
172                 </syntax>
173                 <description>
174                         <para>This application will execute the specified dialplan application, with optional
175                         arguments, if the current time matches the given time specification.</para>
176                 </description>
177                 <see-also>
178                         <ref type="application">Exec</ref>
179                         <ref type="application">ExecIf</ref>
180                         <ref type="application">TryExec</ref>
181                         <ref type="application">GotoIfTime</ref>
182                 </see-also>
183         </application>
184         <application name="Goto" language="en_US">
185                 <synopsis>
186                         Jump to a particular priority, extension, or context.
187                 </synopsis>
188                 <syntax>
189                         <parameter name="context" />
190                         <parameter name="extensions" />
191                         <parameter name="priority" required="true" />
192                 </syntax>
193                 <description>
194                         <para>This application will set the current context, extension, and priority in the channel structure.
195                         After it completes, the pbx engine will continue dialplan execution at the specified location.
196                         If no specific <replaceable>extension</replaceable>, or <replaceable>extension</replaceable> and
197                         <replaceable>context</replaceable>, are specified, then this application will
198                         just set the specified <replaceable>priority</replaceable> of the current extension.</para>
199                         <para>At least a <replaceable>priority</replaceable> is required as an argument, or the goto will
200                         return a <literal>-1</literal>, and the channel and call will be terminated.</para>
201                         <para>If the location that is put into the channel information is bogus, and asterisk cannot
202                         find that location in the dialplan, then the execution engine will try to find and execute the code in
203                         the <literal>i</literal> (invalid) extension in the current context. If that does not exist, it will try to execute the
204                         <literal>h</literal> extension. If neither the <literal>h</literal> nor <literal>i</literal> extensions
205                         have been defined, the channel is hung up, and the execution of instructions on the channel is terminated.
206                         What this means is that, for example, you specify a context that does not exist, then
207                         it will not be possible to find the <literal>h</literal> or <literal>i</literal> extensions,
208                         and the call will terminate!</para>
209                 </description>
210                 <see-also>
211                         <ref type="application">GotoIf</ref>
212                         <ref type="application">GotoIfTime</ref>
213                         <ref type="application">Gosub</ref>
214                         <ref type="application">Macro</ref>
215                 </see-also>
216         </application>
217         <application name="GotoIf" language="en_US">
218                 <synopsis>
219                         Conditional goto.
220                 </synopsis>
221                 <syntax argsep="?">
222                         <parameter name="condition" required="true" />
223                         <parameter name="destination" required="true" argsep=":">
224                                 <argument name="labeliftrue">
225                                         <para>Continue at <replaceable>labeliftrue</replaceable> if the condition is true.
226                                         Takes the form similar to Goto() of [[context,]extension,]priority.</para>
227                                 </argument>
228                                 <argument name="labeliffalse">
229                                         <para>Continue at <replaceable>labeliffalse</replaceable> if the condition is false.
230                                         Takes the form similar to Goto() of [[context,]extension,]priority.</para>
231                                 </argument>
232                         </parameter>
233                 </syntax>
234                 <description>
235                         <para>This application will set the current context, extension, and priority in the channel structure
236                         based on the evaluation of the given condition. After this application completes, the
237                         pbx engine will continue dialplan execution at the specified location in the dialplan.
238                         The labels are specified with the same syntax as used within the Goto application.
239                         If the label chosen by the condition is omitted, no jump is performed, and the execution passes to the
240                         next instruction. If the target location is bogus, and does not exist, the execution engine will try
241                         to find and execute the code in the <literal>i</literal> (invalid) extension in the current context.
242                         If that does not exist, it will try to execute the <literal>h</literal> extension.
243                         If neither the <literal>h</literal> nor <literal>i</literal> extensions have been defined,
244                         the channel is hung up, and the execution of instructions on the channel is terminated.
245                         Remember that this command can set the current context, and if the context specified
246                         does not exist, then it will not be able to find any 'h' or 'i' extensions there, and
247                         the channel and call will both be terminated!.</para>
248                 </description>
249                 <see-also>
250                         <ref type="application">Goto</ref>
251                         <ref type="application">GotoIfTime</ref>
252                         <ref type="application">GosubIf</ref>
253                         <ref type="application">MacroIf</ref>
254                 </see-also>
255         </application>
256         <application name="GotoIfTime" language="en_US">
257                 <synopsis>
258                         Conditional Goto based on the current time.
259                 </synopsis>
260                 <syntax argsep="?">
261                         <parameter name="condition" required="true">
262                                 <argument name="times" required="true" />
263                                 <argument name="weekdays" required="true" />
264                                 <argument name="mdays" required="true" />
265                                 <argument name="months" required="true" />
266                                 <argument name="timezone" required="false" />
267                         </parameter>
268                         <parameter name="destination" required="true" argsep=":">
269                                 <argument name="labeliftrue">
270                                         <para>Continue at <replaceable>labeliftrue</replaceable> if the condition is true.
271                                         Takes the form similar to Goto() of [[context,]extension,]priority.</para>
272                                 </argument>
273                                 <argument name="labeliffalse">
274                                         <para>Continue at <replaceable>labeliffalse</replaceable> if the condition is false.
275                                         Takes the form similar to Goto() of [[context,]extension,]priority.</para>
276                                 </argument>
277                         </parameter>
278                 </syntax>
279                 <description>
280                         <para>This application will set the context, extension, and priority in the channel structure
281                         based on the evaluation of the given time specification. After this application completes,
282                         the pbx engine will continue dialplan execution at the specified location in the dialplan.
283                         If the current time is within the given time specification, the channel will continue at
284                         <replaceable>labeliftrue</replaceable>. Otherwise the channel will continue at <replaceable>labeliffalse</replaceable>.
285                         If the label chosen by the condition is omitted, no jump is performed, and execution passes to the next
286                         instruction. If the target jump location is bogus, the same actions would be taken as for <literal>Goto</literal>.
287                         Further information on the time specification can be found in examples
288                         illustrating how to do time-based context includes in the dialplan.</para>
289                 </description>
290                 <see-also>
291                         <ref type="application">GotoIf</ref>
292                         <ref type="application">Goto</ref>
293                         <ref type="function">IFTIME</ref>
294                         <ref type="function">TESTTIME</ref>
295                 </see-also>
296         </application>
297         <application name="ImportVar" language="en_US">
298                 <synopsis>
299                         Import a variable from a channel into a new variable.
300                 </synopsis>
301                 <syntax argsep="=">
302                         <parameter name="newvar" required="true" />
303                         <parameter name="vardata" required="true">
304                                 <argument name="channelname" required="true" />
305                                 <argument name="variable" required="true" />
306                         </parameter>
307                 </syntax>
308                 <description>
309                         <para>This application imports a <replaceable>variable</replaceable> from the specified
310                         <replaceable>channel</replaceable> (as opposed to the current one) and stores it as a variable
311                         (<replaceable>newvar</replaceable>) in the current channel (the channel that is calling this
312                         application). Variables created by this application have the same inheritance properties as those
313                         created with the <literal>Set</literal> application.</para>
314                 </description>
315                 <see-also>
316                         <ref type="application">Set</ref>
317                 </see-also>
318         </application>
319         <application name="Hangup" language="en_US">
320                 <synopsis>
321                         Hang up the calling channel.
322                 </synopsis>
323                 <syntax>
324                         <parameter name="causecode">
325                                 <para>If a <replaceable>causecode</replaceable> is given the channel's
326                                 hangup cause will be set to the given value.</para>
327                         </parameter>
328                 </syntax>
329                 <description>
330                         <para>This application will hang up the calling channel.</para>
331                 </description>
332                 <see-also>
333                         <ref type="application">Answer</ref>
334                         <ref type="application">Busy</ref>
335                         <ref type="application">Congestion</ref>
336                 </see-also>
337         </application>
338         <application name="Incomplete" language="en_US">
339                 <synopsis>
340                         Returns AST_PBX_INCOMPLETE value.
341                 </synopsis>
342                 <syntax>
343                         <parameter name="n">
344                                 <para>If specified, then Incomplete will not attempt to answer the channel first.</para>
345                                 <note><para>Most channel types need to be in Answer state in order to receive DTMF.</para></note>
346                         </parameter>
347                 </syntax>
348                 <description>
349                         <para>Signals the PBX routines that the previous matched extension is incomplete
350                         and that further input should be allowed before matching can be considered
351                         to be complete.  Can be used within a pattern match when certain criteria warrants
352                         a longer match.</para>
353                 </description>
354         </application>
355         <application name="NoOp" language="en_US">
356                 <synopsis>
357                         Do Nothing (No Operation).
358                 </synopsis>
359                 <syntax>
360                         <parameter name="text">
361                                 <para>Any text provided can be viewed at the Asterisk CLI.</para>
362                         </parameter>
363                 </syntax>
364                 <description>
365                         <para>This application does nothing. However, it is useful for debugging purposes.</para>
366                         <para>This method can be used to see the evaluations of variables or functions without having any effect.</para>
367                 </description>
368                 <see-also>
369                         <ref type="application">Verbose</ref>
370                         <ref type="application">Log</ref>
371                 </see-also>
372         </application>
373         <application name="Proceeding" language="en_US">
374                 <synopsis>
375                         Indicate proceeding.
376                 </synopsis>
377                 <syntax />
378                 <description>
379                         <para>This application will request that a proceeding message be provided to the calling channel.</para>
380                 </description>
381         </application>
382         <application name="Progress" language="en_US">
383                 <synopsis>
384                         Indicate progress.
385                 </synopsis>
386                 <syntax />
387                 <description>
388                         <para>This application will request that in-band progress information be provided to the calling channel.</para>
389                 </description>
390                 <see-also>
391                         <ref type="application">Busy</ref>
392                         <ref type="application">Congestion</ref>
393                         <ref type="application">Ringing</ref>
394                         <ref type="application">Playtones</ref>
395                 </see-also>
396         </application>
397         <application name="RaiseException" language="en_US">
398                 <synopsis>
399                         Handle an exceptional condition.
400                 </synopsis>
401                 <syntax>
402                         <parameter name="reason" required="true" />
403                 </syntax>
404                 <description>
405                         <para>This application will jump to the <literal>e</literal> extension in the current context, setting the
406                         dialplan function EXCEPTION(). If the <literal>e</literal> extension does not exist, the call will hangup.</para>
407                 </description>
408                 <see-also>
409                         <ref type="function">Exception</ref>
410                 </see-also>
411         </application>
412         <application name="Ringing" language="en_US">
413                 <synopsis>
414                         Indicate ringing tone.
415                 </synopsis>
416                 <syntax />
417                 <description>
418                         <para>This application will request that the channel indicate a ringing tone to the user.</para>
419                 </description>
420                 <see-also>
421                         <ref type="application">Busy</ref>
422                         <ref type="application">Congestion</ref>
423                         <ref type="application">Progress</ref>
424                         <ref type="application">Playtones</ref>
425                 </see-also>
426         </application>
427         <application name="SayAlpha" language="en_US">
428                 <synopsis>
429                         Say Alpha.
430                 </synopsis>
431                 <syntax>
432                         <parameter name="string" required="true" />
433                 </syntax>
434                 <description>
435                         <para>This application will play the sounds that correspond to the letters
436                         of the given <replaceable>string</replaceable>. If the channel variable
437                         <variable>SAY_DTMF_INTERRUPT</variable> is set to 'true' (case insensitive),
438                         then this application will react to DTMF in the same way as
439                         <literal>Background</literal>.</para>
440                 </description>
441                 <see-also>
442                         <ref type="application">SayDigits</ref>
443                         <ref type="application">SayNumber</ref>
444                         <ref type="application">SayPhonetic</ref>
445                         <ref type="function">CHANNEL</ref>
446                 </see-also>
447         </application>
448         <application name="SayAlphaCase" language="en_US">
449                 <synopsis>
450                         Say Alpha.
451                 </synopsis>
452                 <syntax>
453                         <parameter name="casetype" required="true" >
454                                 <enumlist>
455                                         <enum name="a">
456                                                 <para>Case sensitive (all) pronunciation.
457                                                 (Ex: SayAlphaCase(a,aBc); - lowercase a uppercase b lowercase c).</para>
458                                         </enum>
459                                         <enum name="l">
460                                                 <para>Case sensitive (lower) pronunciation.
461                                                 (Ex: SayAlphaCase(l,aBc); - lowercase a b lowercase c).</para>
462                                         </enum>
463                                         <enum name="n">
464                                                 <para>Case insensitive pronunciation. Equivalent to SayAlpha.
465                                                 (Ex: SayAlphaCase(n,aBc) - a b c).</para>
466                                         </enum>
467                                         <enum name="u">
468                                                 <para>Case sensitive (upper) pronunciation.
469                                                 (Ex: SayAlphaCase(u,aBc); - a uppercase b c).</para>
470                                         </enum>
471                                 </enumlist>
472                         </parameter>
473                         <parameter name="string" required="true" />
474                 </syntax>
475                 <description>
476                         <para>This application will play the sounds that correspond to the letters of the
477                         given <replaceable>string</replaceable>.  Optionally, a <replaceable>casetype</replaceable> may be
478                         specified.  This will be used for case-insensitive or case-sensitive pronunciations. If the channel
479                         variable <variable>SAY_DTMF_INTERRUPT</variable> is set to 'true' (case insensitive), then this
480                         application will react to DTMF in the same way as <literal>Background</literal>.</para>
481                 </description>
482                 <see-also>
483                         <ref type="application">SayDigits</ref>
484                         <ref type="application">SayNumber</ref>
485                         <ref type="application">SayPhonetic</ref>
486                         <ref type="application">SayAlpha</ref>
487                         <ref type="function">CHANNEL</ref>
488                 </see-also>
489         </application>
490         <application name="SayDigits" language="en_US">
491                 <synopsis>
492                         Say Digits.
493                 </synopsis>
494                 <syntax>
495                         <parameter name="digits" required="true" />
496                 </syntax>
497                 <description>
498                         <para>This application will play the sounds that correspond to the digits of
499                         the given number. This will use the language that is currently set for the channel.
500                         If the channel variable <variable>SAY_DTMF_INTERRUPT</variable> is set to 'true'
501                         (case insensitive), then this application will react to DTMF in the same way as
502                         <literal>Background</literal>.</para>
503                 </description>
504                 <see-also>
505                         <ref type="application">SayAlpha</ref>
506                         <ref type="application">SayNumber</ref>
507                         <ref type="application">SayPhonetic</ref>
508                         <ref type="function">CHANNEL</ref>
509                 </see-also>
510         </application>
511         <application name="SayNumber" language="en_US">
512                 <synopsis>
513                         Say Number.
514                 </synopsis>
515                 <syntax>
516                         <parameter name="digits" required="true" />
517                         <parameter name="gender" />
518                 </syntax>
519                 <description>
520                         <para>This application will play the sounds that correspond to the given
521                         <replaceable>digits</replaceable>. Optionally, a <replaceable>gender</replaceable> may be
522                         specified. This will use the language that is currently set for the channel. See the CHANNEL()
523                         function for more information on setting the language for the channel. If the channel variable
524                         <variable>SAY_DTMF_INTERRUPT</variable> is set to 'true' (case insensitive), then this
525                         application will react to DTMF in the same way as <literal>Background</literal>.</para>
526                 </description>
527                 <see-also>
528                         <ref type="application">SayAlpha</ref>
529                         <ref type="application">SayDigits</ref>
530                         <ref type="application">SayPhonetic</ref>
531                         <ref type="function">CHANNEL</ref>
532                 </see-also>
533         </application>
534         <application name="SayPhonetic" language="en_US">
535                 <synopsis>
536                         Say Phonetic.
537                 </synopsis>
538                 <syntax>
539                         <parameter name="string" required="true" />
540                 </syntax>
541                 <description>
542                         <para>This application will play the sounds from the phonetic alphabet that correspond to the
543                         letters in the given <replaceable>string</replaceable>. If the channel variable
544                         <variable>SAY_DTMF_INTERRUPT</variable> is set to 'true' (case insensitive), then this
545                         application will react to DTMF in the same way as <literal>Background</literal>.</para>
546                 </description>
547                 <see-also>
548                         <ref type="application">SayAlpha</ref>
549                         <ref type="application">SayDigits</ref>
550                         <ref type="application">SayNumber</ref>
551                 </see-also>
552         </application>
553         <application name="SetAMAFlags" language="en_US">
554                 <synopsis>
555                         Set the AMA Flags.
556                 </synopsis>
557                 <syntax>
558                         <parameter name="flag" />
559                 </syntax>
560                 <description>
561                         <para>This application will set the channel's AMA Flags for billing purposes.</para>
562                         <warning><para>This application is deprecated. Please use the CHANNEL function instead.</para></warning>
563                 </description>
564                 <see-also>
565                         <ref type="function">CDR</ref>
566                         <ref type="function">CHANNEL</ref>
567                 </see-also>
568         </application>
569         <application name="Wait" language="en_US">
570                 <synopsis>
571                         Waits for some time.
572                 </synopsis>
573                 <syntax>
574                         <parameter name="seconds" required="true">
575                                 <para>Can be passed with fractions of a second. For example, <literal>1.5</literal> will ask the
576                                 application to wait for 1.5 seconds.</para>
577                         </parameter>
578                 </syntax>
579                 <description>
580                         <para>This application waits for a specified number of <replaceable>seconds</replaceable>.</para>
581                 </description>
582         </application>
583         <application name="WaitExten" language="en_US">
584                 <synopsis>
585                         Waits for an extension to be entered.
586                 </synopsis>
587                 <syntax>
588                         <parameter name="seconds">
589                                 <para>Can be passed with fractions of a second. For example, <literal>1.5</literal> will ask the
590                                 application to wait for 1.5 seconds.</para>
591                         </parameter>
592                         <parameter name="options">
593                                 <optionlist>
594                                         <option name="m">
595                                                 <para>Provide music on hold to the caller while waiting for an extension.</para>
596                                                 <argument name="x">
597                                                         <para>Specify the class for music on hold. <emphasis>CHANNEL(musicclass) will
598                                                         be used instead if set</emphasis></para>
599                                                 </argument>
600                                         </option>
601                                 </optionlist>
602                         </parameter>
603                 </syntax>
604                 <description>
605                         <para>This application waits for the user to enter a new extension for a specified number
606                         of <replaceable>seconds</replaceable>.</para>
607                         <xi:include xpointer="xpointer(/docs/application[@name='Macro']/description/warning[2])" />
608                 </description>
609                 <see-also>
610                         <ref type="application">Background</ref>
611                         <ref type="function">TIMEOUT</ref>
612                 </see-also>
613         </application>
614  ***/
615
616 #define BACKGROUND_SKIP         (1 << 0)
617 #define BACKGROUND_NOANSWER     (1 << 1)
618 #define BACKGROUND_MATCHEXTEN   (1 << 2)
619 #define BACKGROUND_PLAYBACK     (1 << 3)
620
621 AST_APP_OPTIONS(background_opts, {
622         AST_APP_OPTION('s', BACKGROUND_SKIP),
623         AST_APP_OPTION('n', BACKGROUND_NOANSWER),
624         AST_APP_OPTION('m', BACKGROUND_MATCHEXTEN),
625         AST_APP_OPTION('p', BACKGROUND_PLAYBACK),
626 });
627
628 #define WAITEXTEN_MOH           (1 << 0)
629 #define WAITEXTEN_DIALTONE      (1 << 1)
630
631 AST_APP_OPTIONS(waitexten_opts, {
632         AST_APP_OPTION_ARG('m', WAITEXTEN_MOH, 0),
633         AST_APP_OPTION_ARG('d', WAITEXTEN_DIALTONE, 0),
634 });
635
636 int pbx_builtin_raise_exception(struct ast_channel *chan, const char *reason)
637 {
638         /* Priority will become 1, next time through the AUTOLOOP */
639         return raise_exception(chan, reason, 0);
640 }
641
642 /*!
643  * \ingroup applications
644  */
645 static int pbx_builtin_proceeding(struct ast_channel *chan, const char *data)
646 {
647         ast_indicate(chan, AST_CONTROL_PROCEEDING);
648         return 0;
649 }
650
651 /*!
652  * \ingroup applications
653  */
654 static int pbx_builtin_progress(struct ast_channel *chan, const char *data)
655 {
656         ast_indicate(chan, AST_CONTROL_PROGRESS);
657         return 0;
658 }
659
660 /*!
661  * \ingroup applications
662  */
663 static int pbx_builtin_ringing(struct ast_channel *chan, const char *data)
664 {
665         ast_indicate(chan, AST_CONTROL_RINGING);
666         return 0;
667 }
668
669 /*!
670  * \ingroup applications
671  */
672 int indicate_busy(struct ast_channel *chan, const char *data)
673 {
674         ast_indicate(chan, AST_CONTROL_BUSY);
675         /* Don't change state of an UP channel, just indicate
676            busy in audio */
677         ast_channel_lock(chan);
678         if (ast_channel_state(chan) != AST_STATE_UP) {
679                 ast_channel_hangupcause_set(chan, AST_CAUSE_BUSY);
680                 ast_setstate(chan, AST_STATE_BUSY);
681         }
682         ast_channel_unlock(chan);
683         wait_for_hangup(chan, data);
684         return -1;
685 }
686
687 /*!
688  * \ingroup applications
689  */
690 int indicate_congestion(struct ast_channel *chan, const char *data)
691 {
692         ast_indicate(chan, AST_CONTROL_CONGESTION);
693         /* Don't change state of an UP channel, just indicate
694            congestion in audio */
695         ast_channel_lock(chan);
696         if (ast_channel_state(chan) != AST_STATE_UP) {
697                 ast_channel_hangupcause_set(chan, AST_CAUSE_CONGESTION);
698                 ast_setstate(chan, AST_STATE_BUSY);
699         }
700         ast_channel_unlock(chan);
701         wait_for_hangup(chan, data);
702         return -1;
703 }
704
705 /*!
706  * \ingroup applications
707  */
708 static int pbx_builtin_answer(struct ast_channel *chan, const char *data)
709 {
710         int delay = 0;
711         char *parse;
712         AST_DECLARE_APP_ARGS(args,
713                 AST_APP_ARG(delay);
714                 AST_APP_ARG(answer_cdr);
715         );
716
717         if (ast_strlen_zero(data)) {
718                 return __ast_answer(chan, 0);
719         }
720
721         parse = ast_strdupa(data);
722
723         AST_STANDARD_APP_ARGS(args, parse);
724
725         if (!ast_strlen_zero(args.delay) && (ast_channel_state(chan) != AST_STATE_UP))
726                 delay = atoi(data);
727
728         if (delay < 0) {
729                 delay = 0;
730         }
731
732         if (!ast_strlen_zero(args.answer_cdr) && !strcasecmp(args.answer_cdr, "nocdr")) {
733                 ast_log(AST_LOG_WARNING, "The nocdr option for the Answer application has been removed and is no longer supported.\n");
734         }
735
736         return __ast_answer(chan, delay);
737 }
738
739 static int pbx_builtin_incomplete(struct ast_channel *chan, const char *data)
740 {
741         const char *options = data;
742         int answer = 1;
743
744         /* Some channels can receive DTMF in unanswered state; some cannot */
745         if (!ast_strlen_zero(options) && strchr(options, 'n')) {
746                 answer = 0;
747         }
748
749         /* If the channel is hungup, stop waiting */
750         if (ast_check_hangup(chan)) {
751                 return -1;
752         } else if (ast_channel_state(chan) != AST_STATE_UP && answer) {
753                 __ast_answer(chan, 0);
754         }
755
756         ast_indicate(chan, AST_CONTROL_INCOMPLETE);
757
758         return AST_PBX_INCOMPLETE;
759 }
760
761 /*!
762  * \ingroup applications
763  */
764 static int pbx_builtin_setamaflags(struct ast_channel *chan, const char *data)
765 {
766         ast_log(AST_LOG_WARNING, "The SetAMAFlags application is deprecated. Please use the CHANNEL function instead.\n");
767
768         if (ast_strlen_zero(data)) {
769                 ast_log(AST_LOG_WARNING, "No parameter passed to SetAMAFlags\n");
770                 return 0;
771         }
772         /* Copy the AMA Flags as specified */
773         ast_channel_lock(chan);
774         if (isdigit(data[0])) {
775                 int amaflags;
776                 if (sscanf(data, "%30d", &amaflags) != 1) {
777                         ast_log(AST_LOG_WARNING, "Unable to set AMA flags on channel %s\n", ast_channel_name(chan));
778                         ast_channel_unlock(chan);
779                         return 0;
780                 }
781                 ast_channel_amaflags_set(chan, amaflags);
782         } else {
783                 ast_channel_amaflags_set(chan, ast_channel_string2amaflag(data));
784         }
785         ast_channel_unlock(chan);
786         return 0;
787 }
788
789 /*!
790  * \ingroup applications
791  */
792 static int pbx_builtin_hangup(struct ast_channel *chan, const char *data)
793 {
794         int cause;
795
796         ast_set_hangupsource(chan, "dialplan/builtin", 0);
797
798         if (!ast_strlen_zero(data)) {
799                 cause = ast_str2cause(data);
800                 if (cause <= 0) {
801                         if (sscanf(data, "%30d", &cause) != 1 || cause <= 0) {
802                                 ast_log(LOG_WARNING, "Invalid cause given to Hangup(): \"%s\"\n", data);
803                                 cause = 0;
804                         }
805                 }
806         } else {
807                 cause = 0;
808         }
809
810         ast_channel_lock(chan);
811         if (cause <= 0) {
812                 cause = ast_channel_hangupcause(chan);
813                 if (cause <= 0) {
814                         cause = AST_CAUSE_NORMAL_CLEARING;
815                 }
816         }
817         ast_channel_hangupcause_set(chan, cause);
818         ast_softhangup_nolock(chan, AST_SOFTHANGUP_EXPLICIT);
819         ast_channel_unlock(chan);
820
821         return -1;
822 }
823
824 /*! Goto
825  * \ingroup applications
826  */
827 static int pbx_builtin_goto(struct ast_channel *chan, const char *data)
828 {
829         int res = ast_parseable_goto(chan, data);
830         if (!res)
831                 ast_verb(3, "Goto (%s,%s,%d)\n", ast_channel_context(chan), ast_channel_exten(chan), ast_channel_priority(chan) + 1);
832         return res;
833 }
834
835 /*!
836  * \ingroup applications
837  */
838 static int pbx_builtin_gotoiftime(struct ast_channel *chan, const char *data)
839 {
840         char *s, *ts, *branch1, *branch2, *branch;
841         struct ast_timing timing;
842         const char *ctime;
843         struct timeval tv = ast_tvnow();
844         long timesecs;
845
846         if (!chan) {
847                 ast_log(LOG_WARNING, "GotoIfTime requires a channel on which to operate\n");
848                 return -1;
849         }
850
851         if (ast_strlen_zero(data)) {
852                 ast_log(LOG_WARNING, "GotoIfTime requires an argument:\n  <time range>,<days of week>,<days of month>,<months>[,<timezone>]?'labeliftrue':'labeliffalse'\n");
853                 return -1;
854         }
855
856         ts = s = ast_strdupa(data);
857
858         ast_channel_lock(chan);
859         if ((ctime = pbx_builtin_getvar_helper(chan, "TESTTIME")) && sscanf(ctime, "%ld", &timesecs) == 1) {
860                 tv.tv_sec = timesecs;
861         } else if (ctime) {
862                 ast_log(LOG_WARNING, "Using current time to evaluate\n");
863                 /* Reset when unparseable */
864                 pbx_builtin_setvar_helper(chan, "TESTTIME", NULL);
865         }
866         ast_channel_unlock(chan);
867
868         /* Separate the Goto path */
869         strsep(&ts, "?");
870         branch1 = strsep(&ts,":");
871         branch2 = strsep(&ts,"");
872
873         /* struct ast_include include contained garbage here, fixed by zeroing it on get_timerange */
874         if (ast_build_timing(&timing, s) && ast_check_timing2(&timing, tv)) {
875                 branch = branch1;
876         } else {
877                 branch = branch2;
878         }
879         ast_destroy_timing(&timing);
880
881         if (ast_strlen_zero(branch)) {
882                 ast_debug(1, "Not taking any branch\n");
883                 return 0;
884         }
885
886         return pbx_builtin_goto(chan, branch);
887 }
888
889 /*!
890  * \ingroup applications
891  */
892 static int pbx_builtin_execiftime(struct ast_channel *chan, const char *data)
893 {
894         char *s, *appname;
895         struct ast_timing timing;
896         struct ast_app *app;
897         static const char * const usage = "ExecIfTime requires an argument:\n  <time range>,<days of week>,<days of month>,<months>[,<timezone>]?<appname>[(<appargs>)]";
898
899         if (ast_strlen_zero(data)) {
900                 ast_log(LOG_WARNING, "%s\n", usage);
901                 return -1;
902         }
903
904         appname = ast_strdupa(data);
905
906         s = strsep(&appname, "?");      /* Separate the timerange and application name/data */
907         if (!appname) { /* missing application */
908                 ast_log(LOG_WARNING, "%s\n", usage);
909                 return -1;
910         }
911
912         if (!ast_build_timing(&timing, s)) {
913                 ast_log(LOG_WARNING, "Invalid Time Spec: %s\nCorrect usage: %s\n", s, usage);
914                 ast_destroy_timing(&timing);
915                 return -1;
916         }
917
918         if (!ast_check_timing(&timing)) { /* outside the valid time window, just return */
919                 ast_destroy_timing(&timing);
920                 return 0;
921         }
922         ast_destroy_timing(&timing);
923
924         /* now split appname(appargs) */
925         if ((s = strchr(appname, '('))) {
926                 char *e;
927                 *s++ = '\0';
928                 if ((e = strrchr(s, ')')))
929                         *e = '\0';
930                 else
931                         ast_log(LOG_WARNING, "Failed to find closing parenthesis\n");
932         }
933
934
935         if ((app = pbx_findapp(appname))) {
936                 return pbx_exec(chan, app, S_OR(s, ""));
937         } else {
938                 ast_log(LOG_WARNING, "Cannot locate application %s\n", appname);
939                 return -1;
940         }
941 }
942
943 /*!
944  * \ingroup applications
945  */
946 static int pbx_builtin_wait(struct ast_channel *chan, const char *data)
947 {
948         int ms;
949
950         /* Wait for "n" seconds */
951         if (!ast_app_parse_timelen(data, &ms, TIMELEN_SECONDS) && ms > 0) {
952                 return ast_safe_sleep(chan, ms);
953         }
954         return 0;
955 }
956
957 /*!
958  * \ingroup applications
959  */
960 static int pbx_builtin_waitexten(struct ast_channel *chan, const char *data)
961 {
962         int ms, res;
963         struct ast_flags flags = {0};
964         char *opts[1] = { NULL };
965         char *parse;
966         AST_DECLARE_APP_ARGS(args,
967                 AST_APP_ARG(timeout);
968                 AST_APP_ARG(options);
969         );
970
971         if (!ast_strlen_zero(data)) {
972                 parse = ast_strdupa(data);
973                 AST_STANDARD_APP_ARGS(args, parse);
974         } else
975                 memset(&args, 0, sizeof(args));
976
977         if (args.options)
978                 ast_app_parse_options(waitexten_opts, &flags, opts, args.options);
979
980         if (ast_test_flag(&flags, WAITEXTEN_MOH) && !opts[0] ) {
981                 ast_log(LOG_WARNING, "The 'm' option has been specified for WaitExten without a class.\n");
982         } else if (ast_test_flag(&flags, WAITEXTEN_MOH)) {
983                 ast_indicate_data(chan, AST_CONTROL_HOLD, S_OR(opts[0], NULL),
984                         !ast_strlen_zero(opts[0]) ? strlen(opts[0]) + 1 : 0);
985         } else if (ast_test_flag(&flags, WAITEXTEN_DIALTONE)) {
986                 struct ast_tone_zone_sound *ts = ast_get_indication_tone(ast_channel_zone(chan), "dial");
987                 if (ts) {
988                         ast_playtones_start(chan, 0, ts->data, 0);
989                         ts = ast_tone_zone_sound_unref(ts);
990                 } else {
991                         ast_tonepair_start(chan, 350, 440, 0, 0);
992                 }
993         }
994         /* Wait for "n" seconds */
995         if (!ast_app_parse_timelen(args.timeout, &ms, TIMELEN_SECONDS) && ms > 0) {
996                 /* Yay! */
997         } else if (ast_channel_pbx(chan)) {
998                 ms = ast_channel_pbx(chan)->rtimeoutms;
999         } else {
1000                 ms = 10000;
1001         }
1002
1003         res = ast_waitfordigit(chan, ms);
1004         if (!res) {
1005                 if (ast_check_hangup(chan)) {
1006                         /* Call is hungup for some reason. */
1007                         res = -1;
1008                 } else if (ast_exists_extension(chan, ast_channel_context(chan), ast_channel_exten(chan), ast_channel_priority(chan) + 1,
1009                         S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
1010                         ast_verb(3, "Timeout on %s, continuing...\n", ast_channel_name(chan));
1011                 } else if (ast_exists_extension(chan, ast_channel_context(chan), "t", 1,
1012                         S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
1013                         ast_verb(3, "Timeout on %s, going to 't'\n", ast_channel_name(chan));
1014                         set_ext_pri(chan, "t", 0); /* 0 will become 1, next time through the loop */
1015                 } else if (ast_exists_extension(chan, ast_channel_context(chan), "e", 1,
1016                         S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
1017                         raise_exception(chan, "RESPONSETIMEOUT", 0); /* 0 will become 1, next time through the loop */
1018                 } else {
1019                         ast_log(LOG_WARNING, "Timeout but no rule 't' or 'e' in context '%s'\n",
1020                                 ast_channel_context(chan));
1021                         res = -1;
1022                 }
1023         }
1024
1025         if (ast_test_flag(&flags, WAITEXTEN_MOH))
1026                 ast_indicate(chan, AST_CONTROL_UNHOLD);
1027         else if (ast_test_flag(&flags, WAITEXTEN_DIALTONE))
1028                 ast_playtones_stop(chan);
1029
1030         return res;
1031 }
1032
1033 /*!
1034  * \ingroup applications
1035  */
1036 static int pbx_builtin_background(struct ast_channel *chan, const char *data)
1037 {
1038         int res = 0;
1039         int mres = 0;
1040         struct ast_flags flags = {0};
1041         char *parse, exten[2] = "";
1042         AST_DECLARE_APP_ARGS(args,
1043                 AST_APP_ARG(filename);
1044                 AST_APP_ARG(options);
1045                 AST_APP_ARG(lang);
1046                 AST_APP_ARG(context);
1047         );
1048
1049         if (ast_strlen_zero(data)) {
1050                 ast_log(LOG_WARNING, "Background requires an argument (filename)\n");
1051                 return -1;
1052         }
1053
1054         parse = ast_strdupa(data);
1055
1056         AST_STANDARD_APP_ARGS(args, parse);
1057
1058         if (ast_strlen_zero(args.lang))
1059                 args.lang = (char *)ast_channel_language(chan); /* XXX this is const */
1060
1061         if (ast_strlen_zero(args.context)) {
1062                 const char *context;
1063                 ast_channel_lock(chan);
1064                 if ((context = pbx_builtin_getvar_helper(chan, "MACRO_CONTEXT"))) {
1065                         args.context = ast_strdupa(context);
1066                 } else {
1067                         args.context = ast_strdupa(ast_channel_context(chan));
1068                 }
1069                 ast_channel_unlock(chan);
1070         }
1071
1072         if (args.options) {
1073                 if (!strcasecmp(args.options, "skip"))
1074                         flags.flags = BACKGROUND_SKIP;
1075                 else if (!strcasecmp(args.options, "noanswer"))
1076                         flags.flags = BACKGROUND_NOANSWER;
1077                 else
1078                         ast_app_parse_options(background_opts, &flags, NULL, args.options);
1079         }
1080
1081         /* Answer if need be */
1082         if (ast_channel_state(chan) != AST_STATE_UP) {
1083                 if (ast_test_flag(&flags, BACKGROUND_SKIP)) {
1084                         goto done;
1085                 } else if (!ast_test_flag(&flags, BACKGROUND_NOANSWER)) {
1086                         res = ast_answer(chan);
1087                 }
1088         }
1089
1090         if (!res) {
1091                 char *back = ast_strip(args.filename);
1092                 char *front;
1093
1094                 ast_stopstream(chan);           /* Stop anything playing */
1095                 /* Stream the list of files */
1096                 while (!res && (front = strsep(&back, "&")) ) {
1097                         if ( (res = ast_streamfile(chan, front, args.lang)) ) {
1098                                 ast_log(LOG_WARNING, "ast_streamfile failed on %s for %s\n", ast_channel_name(chan), (char*)data);
1099                                 res = 0;
1100                                 mres = 1;
1101                                 break;
1102                         }
1103                         if (ast_test_flag(&flags, BACKGROUND_PLAYBACK)) {
1104                                 res = ast_waitstream(chan, "");
1105                         } else if (ast_test_flag(&flags, BACKGROUND_MATCHEXTEN)) {
1106                                 res = ast_waitstream_exten(chan, args.context);
1107                         } else {
1108                                 res = ast_waitstream(chan, AST_DIGIT_ANY);
1109                         }
1110                         ast_stopstream(chan);
1111                 }
1112         }
1113
1114         /*
1115          * If the single digit DTMF is an extension in the specified context, then
1116          * go there and signal no DTMF.  Otherwise, we should exit with that DTMF.
1117          * If we're in Macro, we'll exit and seek that DTMF as the beginning of an
1118          * extension in the Macro's calling context.  If we're not in Macro, then
1119          * we'll simply seek that extension in the calling context.  Previously,
1120          * someone complained about the behavior as it related to the interior of a
1121          * Gosub routine, and the fix (#14011) inadvertently broke FreePBX
1122          * (#14940).  This change should fix both of these situations, but with the
1123          * possible incompatibility that if a single digit extension does not exist
1124          * (but a longer extension COULD have matched), it would have previously
1125          * gone immediately to the "i" extension, but will now need to wait for a
1126          * timeout.
1127          *
1128          * Later, we had to add a flag to disable this workaround, because AGI
1129          * users can EXEC Background and reasonably expect that the DTMF code will
1130          * be returned (see #16434).
1131          */
1132         if (!ast_test_flag(ast_channel_flags(chan), AST_FLAG_DISABLE_WORKAROUNDS)
1133                 && (exten[0] = res)
1134                 && ast_canmatch_extension(chan, args.context, exten, 1,
1135                         S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))
1136                 && !ast_matchmore_extension(chan, args.context, exten, 1,
1137                         S_COR(ast_channel_caller(chan)->id.number.valid, ast_channel_caller(chan)->id.number.str, NULL))) {
1138                 char buf[2] = { 0, };
1139                 snprintf(buf, sizeof(buf), "%c", res);
1140                 ast_channel_exten_set(chan, buf);
1141                 ast_channel_context_set(chan, args.context);
1142                 ast_channel_priority_set(chan, 0);
1143                 res = 0;
1144         }
1145 done:
1146         pbx_builtin_setvar_helper(chan, "BACKGROUNDSTATUS", mres ? "FAILED" : "SUCCESS");
1147         return res;
1148 }
1149
1150 static int pbx_builtin_noop(struct ast_channel *chan, const char *data)
1151 {
1152         return 0;
1153 }
1154
1155 static int pbx_builtin_gotoif(struct ast_channel *chan, const char *data)
1156 {
1157         char *condition, *branch1, *branch2, *branch;
1158         char *stringp;
1159
1160         if (ast_strlen_zero(data)) {
1161                 ast_log(LOG_WARNING, "Ignoring, since there is no variable to check\n");
1162                 return 0;
1163         }
1164
1165         stringp = ast_strdupa(data);
1166         condition = strsep(&stringp,"?");
1167         branch1 = strsep(&stringp,":");
1168         branch2 = strsep(&stringp,"");
1169         branch = pbx_checkcondition(condition) ? branch1 : branch2;
1170
1171         if (ast_strlen_zero(branch)) {
1172                 ast_debug(1, "Not taking any branch\n");
1173                 return 0;
1174         }
1175
1176         return pbx_builtin_goto(chan, branch);
1177 }
1178
1179 static int pbx_builtin_saynumber(struct ast_channel *chan, const char *data)
1180 {
1181         char tmp[256];
1182         char *number = tmp;
1183         int number_val;
1184         char *options;
1185         int res;
1186         int interrupt = 0;
1187         const char *interrupt_string;
1188
1189         ast_channel_lock(chan);
1190         interrupt_string = pbx_builtin_getvar_helper(chan, "SAY_DTMF_INTERRUPT");
1191         if (ast_true(interrupt_string)) {
1192                 interrupt = 1;
1193         }
1194         ast_channel_unlock(chan);
1195
1196         if (ast_strlen_zero(data)) {
1197                 ast_log(LOG_WARNING, "SayNumber requires an argument (number)\n");
1198                 return -1;
1199         }
1200         ast_copy_string(tmp, data, sizeof(tmp));
1201         strsep(&number, ",");
1202
1203         if (sscanf(tmp, "%d", &number_val) != 1) {
1204                 ast_log(LOG_WARNING, "argument '%s' to SayNumber could not be parsed as a number.\n", tmp);
1205                 return 0;
1206         }
1207
1208         options = strsep(&number, ",");
1209         if (options) {
1210                 if ( strcasecmp(options, "f") && strcasecmp(options, "m") &&
1211                         strcasecmp(options, "c") && strcasecmp(options, "n") ) {
1212                         ast_log(LOG_WARNING, "SayNumber gender option is either 'f', 'm', 'c' or 'n'\n");
1213                         return -1;
1214                 }
1215         }
1216
1217         res = ast_say_number(chan, number_val, interrupt ? AST_DIGIT_ANY : "", ast_channel_language(chan), options);
1218
1219         if (res < 0) {
1220                 ast_log(LOG_WARNING, "We were unable to say the number %s, is it too large?\n", tmp);
1221         }
1222
1223         return interrupt ? res : 0;
1224 }
1225
1226 static int pbx_builtin_saydigits(struct ast_channel *chan, const char *data)
1227 {
1228         int res = 0;
1229         int interrupt = 0;
1230         const char *interrupt_string;
1231
1232         ast_channel_lock(chan);
1233         interrupt_string = pbx_builtin_getvar_helper(chan, "SAY_DTMF_INTERRUPT");
1234         if (ast_true(interrupt_string)) {
1235                 interrupt = 1;
1236         }
1237         ast_channel_unlock(chan);
1238
1239         if (data) {
1240                 res = ast_say_digit_str(chan, data, interrupt ? AST_DIGIT_ANY : "", ast_channel_language(chan));
1241         }
1242
1243         return res;
1244 }
1245
1246 static int pbx_builtin_saycharacters_case(struct ast_channel *chan, const char *data)
1247 {
1248         int res = 0;
1249         int sensitivity = 0;
1250         char *parse;
1251         int interrupt = 0;
1252         const char *interrupt_string;
1253
1254         AST_DECLARE_APP_ARGS(args,
1255                 AST_APP_ARG(options);
1256                 AST_APP_ARG(characters);
1257         );
1258
1259         ast_channel_lock(chan);
1260         interrupt_string = pbx_builtin_getvar_helper(chan, "SAY_DTMF_INTERRUPT");
1261         if (ast_true(interrupt_string)) {
1262                 interrupt = 1;
1263         }
1264         ast_channel_unlock(chan);
1265
1266         if (ast_strlen_zero(data)) {
1267                 ast_log(LOG_WARNING, "SayAlphaCase requires two arguments (options, characters)\n");
1268                 return 0;
1269         }
1270
1271         parse = ast_strdupa(data);
1272         AST_STANDARD_APP_ARGS(args, parse);
1273
1274         if (!args.options || strlen(args.options) != 1) {
1275                 ast_log(LOG_WARNING, "SayAlphaCase options are mutually exclusive and required\n");
1276                 return 0;
1277         }
1278
1279         switch (args.options[0]) {
1280         case 'a':
1281                 sensitivity = AST_SAY_CASE_ALL;
1282                 break;
1283         case 'l':
1284                 sensitivity = AST_SAY_CASE_LOWER;
1285                 break;
1286         case 'n':
1287                 sensitivity = AST_SAY_CASE_NONE;
1288                 break;
1289         case 'u':
1290                 sensitivity = AST_SAY_CASE_UPPER;
1291                 break;
1292         default:
1293                 ast_log(LOG_WARNING, "Invalid option: '%s'\n", args.options);
1294                 return 0;
1295         }
1296
1297         res = ast_say_character_str(chan, args.characters, interrupt ? AST_DIGIT_ANY : "", ast_channel_language(chan), sensitivity);
1298
1299         return res;
1300 }
1301
1302 static int pbx_builtin_saycharacters(struct ast_channel *chan, const char *data)
1303 {
1304         int res = 0;
1305         int interrupt = 0;
1306         const char *interrupt_string;
1307
1308         ast_channel_lock(chan);
1309         interrupt_string = pbx_builtin_getvar_helper(chan, "SAY_DTMF_INTERRUPT");
1310         if (ast_true(interrupt_string)) {
1311                 interrupt = 1;
1312         }
1313         ast_channel_unlock(chan);
1314
1315         if (data) {
1316                 res = ast_say_character_str(chan, data, interrupt ? AST_DIGIT_ANY : "", ast_channel_language(chan), AST_SAY_CASE_NONE);
1317         }
1318
1319         return res;
1320 }
1321
1322 static int pbx_builtin_sayphonetic(struct ast_channel *chan, const char *data)
1323 {
1324         int res = 0;
1325         int interrupt = 0;
1326         const char *interrupt_string;
1327
1328         ast_channel_lock(chan);
1329         interrupt_string = pbx_builtin_getvar_helper(chan, "SAY_DTMF_INTERRUPT");
1330         if (ast_true(interrupt_string)) {
1331                 interrupt = 1;
1332         }
1333         ast_channel_unlock(chan);
1334
1335         if (data)
1336                 res = ast_say_phonetic_str(chan, data, interrupt ? AST_DIGIT_ANY : "", ast_channel_language(chan));
1337         return res;
1338 }
1339
1340 static int pbx_builtin_importvar(struct ast_channel *chan, const char *data)
1341 {
1342         char *name;
1343         char *value;
1344         char *channel;
1345         char tmp[VAR_BUF_SIZE];
1346         static int deprecation_warning = 0;
1347
1348         if (ast_strlen_zero(data)) {
1349                 ast_log(LOG_WARNING, "Ignoring, since there is no variable to set\n");
1350                 return 0;
1351         }
1352         tmp[0] = 0;
1353         if (!deprecation_warning) {
1354                 ast_log(LOG_WARNING, "ImportVar is deprecated.  Please use Set(varname=${IMPORT(channel,variable)}) instead.\n");
1355                 deprecation_warning = 1;
1356         }
1357
1358         value = ast_strdupa(data);
1359         name = strsep(&value,"=");
1360         channel = strsep(&value,",");
1361         if (channel && value && name) { /*! \todo XXX should do !ast_strlen_zero(..) of the args ? */
1362                 struct ast_channel *chan2 = ast_channel_get_by_name(channel);
1363                 if (chan2) {
1364                         char *s = ast_alloca(strlen(value) + 4);
1365                         sprintf(s, "${%s}", value);
1366                         pbx_substitute_variables_helper(chan2, s, tmp, sizeof(tmp) - 1);
1367                         chan2 = ast_channel_unref(chan2);
1368                 }
1369                 pbx_builtin_setvar_helper(chan, name, tmp);
1370         }
1371
1372         return(0);
1373 }
1374
1375 /*! \brief Declaration of builtin applications */
1376 struct pbx_builtin {
1377         char name[AST_MAX_APP];
1378         int (*execute)(struct ast_channel *chan, const char *data);
1379 } builtins[] =
1380 {
1381         /* These applications are built into the PBX core and do not
1382            need separate modules */
1383
1384         { "Answer",         pbx_builtin_answer },
1385         { "BackGround",     pbx_builtin_background },
1386         { "Busy",           indicate_busy },
1387         { "Congestion",     indicate_congestion },
1388         { "ExecIfTime",     pbx_builtin_execiftime },
1389         { "Goto",           pbx_builtin_goto },
1390         { "GotoIf",         pbx_builtin_gotoif },
1391         { "GotoIfTime",     pbx_builtin_gotoiftime },
1392         { "ImportVar",      pbx_builtin_importvar },
1393         { "Hangup",         pbx_builtin_hangup },
1394         { "Incomplete",     pbx_builtin_incomplete },
1395         { "NoOp",           pbx_builtin_noop },
1396         { "Proceeding",     pbx_builtin_proceeding },
1397         { "Progress",       pbx_builtin_progress },
1398         { "RaiseException", pbx_builtin_raise_exception },
1399         { "Ringing",        pbx_builtin_ringing },
1400         { "SayAlpha",       pbx_builtin_saycharacters },
1401         { "SayAlphaCase",   pbx_builtin_saycharacters_case },
1402         { "SayDigits",      pbx_builtin_saydigits },
1403         { "SayNumber",      pbx_builtin_saynumber },
1404         { "SayPhonetic",    pbx_builtin_sayphonetic },
1405         { "SetAMAFlags",    pbx_builtin_setamaflags },
1406         { "Wait",           pbx_builtin_wait },
1407         { "WaitExten",      pbx_builtin_waitexten }
1408 };
1409
1410 static void unload_pbx_builtins(void)
1411 {
1412         int x;
1413
1414         /* Unregister builtin applications */
1415         for (x = 0; x < ARRAY_LEN(builtins); x++) {
1416                 ast_unregister_application(builtins[x].name);
1417         }
1418 }
1419
1420 int load_pbx_builtins(void)
1421 {
1422         int x;
1423
1424         /* Register builtin applications */
1425         for (x = 0; x < ARRAY_LEN(builtins); x++) {
1426                 if (ast_register_application2(builtins[x].name, builtins[x].execute, NULL, NULL, NULL)) {
1427                         ast_log(LOG_ERROR, "Unable to register builtin application '%s'\n", builtins[x].name);
1428                         unload_pbx_builtins();
1429                         return -1;
1430                 }
1431         }
1432
1433         ast_register_cleanup(unload_pbx_builtins);
1434
1435         return 0;
1436 }