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