Wed Jan 8 2020 09:49:48

Asterisk developer's documentation


pbx.c
Go to the documentation of this file.
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2008, Digium, Inc.
5  *
6  * Mark Spencer <markster@digium.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 routines.
22  *
23  * \author Mark Spencer <markster@digium.com>
24  */
25 
26 /*** MODULEINFO
27  <support_level>core</support_level>
28  ***/
29 
30 #include "asterisk.h"
31 
32 ASTERISK_FILE_VERSION(__FILE__, "$Revision: 420146 $")
33 
34 #include "asterisk/_private.h"
35 #include "asterisk/paths.h" /* use ast_config_AST_SYSTEM_NAME */
36 #include <ctype.h>
37 #include <time.h>
38 #include <sys/time.h>
39 #if defined(HAVE_SYSINFO)
40 #include <sys/sysinfo.h>
41 #endif
42 #if defined(SOLARIS)
43 #include <sys/loadavg.h>
44 #endif
45 
46 #include "asterisk/lock.h"
47 #include "asterisk/cli.h"
48 #include "asterisk/pbx.h"
49 #include "asterisk/channel.h"
50 #include "asterisk/file.h"
51 #include "asterisk/callerid.h"
52 #include "asterisk/cdr.h"
53 #include "asterisk/cel.h"
54 #include "asterisk/config.h"
55 #include "asterisk/term.h"
56 #include "asterisk/time.h"
57 #include "asterisk/manager.h"
58 #include "asterisk/ast_expr.h"
59 #include "asterisk/linkedlists.h"
60 #define SAY_STUBS /* generate declarations and stubs for say methods */
61 #include "asterisk/say.h"
62 #include "asterisk/utils.h"
63 #include "asterisk/causes.h"
64 #include "asterisk/musiconhold.h"
65 #include "asterisk/app.h"
66 #include "asterisk/devicestate.h"
67 #include "asterisk/event.h"
68 #include "asterisk/hashtab.h"
69 #include "asterisk/module.h"
70 #include "asterisk/indications.h"
71 #include "asterisk/taskprocessor.h"
72 #include "asterisk/xmldoc.h"
73 #include "asterisk/astobj2.h"
74 
75 /*!
76  * \note I M P O R T A N T :
77  *
78  * The speed of extension handling will likely be among the most important
79  * aspects of this PBX. The switching scheme as it exists right now isn't
80  * terribly bad (it's O(N+M), where N is the # of extensions and M is the avg #
81  * of priorities, but a constant search time here would be great ;-)
82  *
83  * A new algorithm to do searching based on a 'compiled' pattern tree is introduced
84  * here, and shows a fairly flat (constant) search time, even for over
85  * 10000 patterns.
86  *
87  * Also, using a hash table for context/priority name lookup can help prevent
88  * the find_extension routines from absorbing exponential cpu cycles as the number
89  * of contexts/priorities grow. I've previously tested find_extension with red-black trees,
90  * which have O(log2(n)) speed. Right now, I'm using hash tables, which do
91  * searches (ideally) in O(1) time. While these techniques do not yield much
92  * speed in small dialplans, they are worth the trouble in large dialplans.
93  *
94  */
95 
96 /*** DOCUMENTATION
97  <application name="Answer" language="en_US">
98  <synopsis>
99  Answer a channel if ringing.
100  </synopsis>
101  <syntax>
102  <parameter name="delay">
103  <para>Asterisk will wait this number of milliseconds before returning to
104  the dialplan after answering the call.</para>
105  </parameter>
106  <parameter name="nocdr">
107  <para>Asterisk will send an answer signal to the calling phone, but will not
108  set the disposition or answer time in the CDR for this call.</para>
109  </parameter>
110  </syntax>
111  <description>
112  <para>If the call has not been answered, this application will
113  answer it. Otherwise, it has no effect on the call.</para>
114  </description>
115  <see-also>
116  <ref type="application">Hangup</ref>
117  </see-also>
118  </application>
119  <application name="BackGround" language="en_US">
120  <synopsis>
121  Play an audio file while waiting for digits of an extension to go to.
122  </synopsis>
123  <syntax>
124  <parameter name="filenames" required="true" argsep="&amp;">
125  <argument name="filename1" required="true" />
126  <argument name="filename2" multiple="true" />
127  </parameter>
128  <parameter name="options">
129  <optionlist>
130  <option name="s">
131  <para>Causes the playback of the message to be skipped
132  if the channel is not in the <literal>up</literal> state (i.e. it
133  hasn't been answered yet). If this happens, the
134  application will return immediately.</para>
135  </option>
136  <option name="n">
137  <para>Don't answer the channel before playing the files.</para>
138  </option>
139  <option name="m">
140  <para>Only break if a digit hit matches a one digit
141  extension in the destination context.</para>
142  </option>
143  </optionlist>
144  </parameter>
145  <parameter name="langoverride">
146  <para>Explicitly specifies which language to attempt to use for the requested sound files.</para>
147  </parameter>
148  <parameter name="context">
149  <para>This is the dialplan context that this application will use when exiting
150  to a dialed extension.</para>
151  </parameter>
152  </syntax>
153  <description>
154  <para>This application will play the given list of files <emphasis>(do not put extension)</emphasis>
155  while waiting for an extension to be dialed by the calling channel. To continue waiting
156  for digits after this application has finished playing files, the <literal>WaitExten</literal>
157  application should be used.</para>
158  <para>If one of the requested sound files does not exist, call processing will be terminated.</para>
159  <para>This application sets the following channel variable upon completion:</para>
160  <variablelist>
161  <variable name="BACKGROUNDSTATUS">
162  <para>The status of the background attempt as a text string.</para>
163  <value name="SUCCESS" />
164  <value name="FAILED" />
165  </variable>
166  </variablelist>
167  </description>
168  <see-also>
169  <ref type="application">ControlPlayback</ref>
170  <ref type="application">WaitExten</ref>
171  <ref type="application">BackgroundDetect</ref>
172  <ref type="function">TIMEOUT</ref>
173  </see-also>
174  </application>
175  <application name="Busy" language="en_US">
176  <synopsis>
177  Indicate the Busy condition.
178  </synopsis>
179  <syntax>
180  <parameter name="timeout">
181  <para>If specified, the calling channel will be hung up after the specified number of seconds.
182  Otherwise, this application will wait until the calling channel hangs up.</para>
183  </parameter>
184  </syntax>
185  <description>
186  <para>This application will indicate the busy condition to the calling channel.</para>
187  </description>
188  <see-also>
189  <ref type="application">Congestion</ref>
190  <ref type="application">Progress</ref>
191  <ref type="application">Playtones</ref>
192  <ref type="application">Hangup</ref>
193  </see-also>
194  </application>
195  <application name="Congestion" language="en_US">
196  <synopsis>
197  Indicate the Congestion condition.
198  </synopsis>
199  <syntax>
200  <parameter name="timeout">
201  <para>If specified, the calling channel will be hung up after the specified number of seconds.
202  Otherwise, this application will wait until the calling channel hangs up.</para>
203  </parameter>
204  </syntax>
205  <description>
206  <para>This application will indicate the congestion condition to the calling channel.</para>
207  </description>
208  <see-also>
209  <ref type="application">Busy</ref>
210  <ref type="application">Progress</ref>
211  <ref type="application">Playtones</ref>
212  <ref type="application">Hangup</ref>
213  </see-also>
214  </application>
215  <application name="ExecIfTime" language="en_US">
216  <synopsis>
217  Conditional application execution based on the current time.
218  </synopsis>
219  <syntax argsep="?">
220  <parameter name="day_condition" required="true">
221  <argument name="times" required="true" />
222  <argument name="weekdays" required="true" />
223  <argument name="mdays" required="true" />
224  <argument name="months" required="true" />
225  <argument name="timezone" required="false" />
226  </parameter>
227  <parameter name="appname" required="true" hasparams="optional">
228  <argument name="appargs" required="true" />
229  </parameter>
230  </syntax>
231  <description>
232  <para>This application will execute the specified dialplan application, with optional
233  arguments, if the current time matches the given time specification.</para>
234  </description>
235  <see-also>
236  <ref type="application">Exec</ref>
237  <ref type="application">ExecIf</ref>
238  <ref type="application">TryExec</ref>
239  <ref type="application">GotoIfTime</ref>
240  </see-also>
241  </application>
242  <application name="Goto" language="en_US">
243  <synopsis>
244  Jump to a particular priority, extension, or context.
245  </synopsis>
246  <syntax>
247  <parameter name="context" />
248  <parameter name="extensions" />
249  <parameter name="priority" required="true" />
250  </syntax>
251  <description>
252  <para>This application will set the current context, extension, and priority in the channel structure.
253  After it completes, the pbx engine will continue dialplan execution at the specified location.
254  If no specific <replaceable>extension</replaceable>, or <replaceable>extension</replaceable> and
255  <replaceable>context</replaceable>, are specified, then this application will
256  just set the specified <replaceable>priority</replaceable> of the current extension.</para>
257  <para>At least a <replaceable>priority</replaceable> is required as an argument, or the goto will
258  return a <literal>-1</literal>, and the channel and call will be terminated.</para>
259  <para>If the location that is put into the channel information is bogus, and asterisk cannot
260  find that location in the dialplan, then the execution engine will try to find and execute the code in
261  the <literal>i</literal> (invalid) extension in the current context. If that does not exist, it will try to execute the
262  <literal>h</literal> extension. If neither the <literal>h</literal> nor <literal>i</literal> extensions
263  have been defined, the channel is hung up, and the execution of instructions on the channel is terminated.
264  What this means is that, for example, you specify a context that does not exist, then
265  it will not be possible to find the <literal>h</literal> or <literal>i</literal> extensions,
266  and the call will terminate!</para>
267  </description>
268  <see-also>
269  <ref type="application">GotoIf</ref>
270  <ref type="application">GotoIfTime</ref>
271  <ref type="application">Gosub</ref>
272  <ref type="application">Macro</ref>
273  </see-also>
274  </application>
275  <application name="GotoIf" language="en_US">
276  <synopsis>
277  Conditional goto.
278  </synopsis>
279  <syntax argsep="?">
280  <parameter name="condition" required="true" />
281  <parameter name="destination" required="true" argsep=":">
282  <argument name="labeliftrue">
283  <para>Continue at <replaceable>labeliftrue</replaceable> if the condition is true.
284  Takes the form similar to Goto() of [[context,]extension,]priority.</para>
285  </argument>
286  <argument name="labeliffalse">
287  <para>Continue at <replaceable>labeliffalse</replaceable> if the condition is false.
288  Takes the form similar to Goto() of [[context,]extension,]priority.</para>
289  </argument>
290  </parameter>
291  </syntax>
292  <description>
293  <para>This application will set the current context, extension, and priority in the channel structure
294  based on the evaluation of the given condition. After this application completes, the
295  pbx engine will continue dialplan execution at the specified location in the dialplan.
296  The labels are specified with the same syntax as used within the Goto application.
297  If the label chosen by the condition is omitted, no jump is performed, and the execution passes to the
298  next instruction. If the target location is bogus, and does not exist, the execution engine will try
299  to find and execute the code in the <literal>i</literal> (invalid) extension in the current context.
300  If that does not exist, it will try to execute the <literal>h</literal> extension.
301  If neither the <literal>h</literal> nor <literal>i</literal> extensions have been defined,
302  the channel is hung up, and the execution of instructions on the channel is terminated.
303  Remember that this command can set the current context, and if the context specified
304  does not exist, then it will not be able to find any 'h' or 'i' extensions there, and
305  the channel and call will both be terminated!.</para>
306  </description>
307  <see-also>
308  <ref type="application">Goto</ref>
309  <ref type="application">GotoIfTime</ref>
310  <ref type="application">GosubIf</ref>
311  <ref type="application">MacroIf</ref>
312  </see-also>
313  </application>
314  <application name="GotoIfTime" language="en_US">
315  <synopsis>
316  Conditional Goto based on the current time.
317  </synopsis>
318  <syntax argsep="?">
319  <parameter name="condition" required="true">
320  <argument name="times" required="true" />
321  <argument name="weekdays" required="true" />
322  <argument name="mdays" required="true" />
323  <argument name="months" required="true" />
324  <argument name="timezone" required="false" />
325  </parameter>
326  <parameter name="destination" required="true" argsep=":">
327  <argument name="labeliftrue">
328  <para>Continue at <replaceable>labeliftrue</replaceable> if the condition is true.
329  Takes the form similar to Goto() of [[context,]extension,]priority.</para>
330  </argument>
331  <argument name="labeliffalse">
332  <para>Continue at <replaceable>labeliffalse</replaceable> if the condition is false.
333  Takes the form similar to Goto() of [[context,]extension,]priority.</para>
334  </argument>
335  </parameter>
336  </syntax>
337  <description>
338  <para>This application will set the context, extension, and priority in the channel structure
339  based on the evaluation of the given time specification. After this application completes,
340  the pbx engine will continue dialplan execution at the specified location in the dialplan.
341  If the current time is within the given time specification, the channel will continue at
342  <replaceable>labeliftrue</replaceable>. Otherwise the channel will continue at <replaceable>labeliffalse</replaceable>.
343  If the label chosen by the condition is omitted, no jump is performed, and execution passes to the next
344  instruction. If the target jump location is bogus, the same actions would be taken as for <literal>Goto</literal>.
345  Further information on the time specification can be found in examples
346  illustrating how to do time-based context includes in the dialplan.</para>
347  </description>
348  <see-also>
349  <ref type="application">GotoIf</ref>
350  <ref type="application">Goto</ref>
351  <ref type="function">IFTIME</ref>
352  <ref type="function">TESTTIME</ref>
353  </see-also>
354  </application>
355  <application name="ImportVar" language="en_US">
356  <synopsis>
357  Import a variable from a channel into a new variable.
358  </synopsis>
359  <syntax argsep="=">
360  <parameter name="newvar" required="true" />
361  <parameter name="vardata" required="true">
362  <argument name="channelname" required="true" />
363  <argument name="variable" required="true" />
364  </parameter>
365  </syntax>
366  <description>
367  <para>This application imports a <replaceable>variable</replaceable> from the specified
368  <replaceable>channel</replaceable> (as opposed to the current one) and stores it as a variable
369  (<replaceable>newvar</replaceable>) in the current channel (the channel that is calling this
370  application). Variables created by this application have the same inheritance properties as those
371  created with the <literal>Set</literal> application.</para>
372  </description>
373  <see-also>
374  <ref type="application">Set</ref>
375  </see-also>
376  </application>
377  <application name="Hangup" language="en_US">
378  <synopsis>
379  Hang up the calling channel.
380  </synopsis>
381  <syntax>
382  <parameter name="causecode">
383  <para>If a <replaceable>causecode</replaceable> is given the channel's
384  hangup cause will be set to the given value.</para>
385  </parameter>
386  </syntax>
387  <description>
388  <para>This application will hang up the calling channel.</para>
389  </description>
390  <see-also>
391  <ref type="application">Answer</ref>
392  <ref type="application">Busy</ref>
393  <ref type="application">Congestion</ref>
394  </see-also>
395  </application>
396  <application name="Incomplete" language="en_US">
397  <synopsis>
398  Returns AST_PBX_INCOMPLETE value.
399  </synopsis>
400  <syntax>
401  <parameter name="n">
402  <para>If specified, then Incomplete will not attempt to answer the channel first.</para>
403  <note><para>Most channel types need to be in Answer state in order to receive DTMF.</para></note>
404  </parameter>
405  </syntax>
406  <description>
407  <para>Signals the PBX routines that the previous matched extension is incomplete
408  and that further input should be allowed before matching can be considered
409  to be complete. Can be used within a pattern match when certain criteria warrants
410  a longer match.</para>
411  </description>
412  </application>
413  <application name="NoOp" language="en_US">
414  <synopsis>
415  Do Nothing (No Operation).
416  </synopsis>
417  <syntax>
418  <parameter name="text">
419  <para>Any text provided can be viewed at the Asterisk CLI.</para>
420  </parameter>
421  </syntax>
422  <description>
423  <para>This application does nothing. However, it is useful for debugging purposes.</para>
424  <para>This method can be used to see the evaluations of variables or functions without having any effect.</para>
425  </description>
426  <see-also>
427  <ref type="application">Verbose</ref>
428  <ref type="application">Log</ref>
429  </see-also>
430  </application>
431  <application name="Proceeding" language="en_US">
432  <synopsis>
433  Indicate proceeding.
434  </synopsis>
435  <syntax />
436  <description>
437  <para>This application will request that a proceeding message be provided to the calling channel.</para>
438  </description>
439  </application>
440  <application name="Progress" language="en_US">
441  <synopsis>
442  Indicate progress.
443  </synopsis>
444  <syntax />
445  <description>
446  <para>This application will request that in-band progress information be provided to the calling channel.</para>
447  </description>
448  <see-also>
449  <ref type="application">Busy</ref>
450  <ref type="application">Congestion</ref>
451  <ref type="application">Ringing</ref>
452  <ref type="application">Playtones</ref>
453  </see-also>
454  </application>
455  <application name="RaiseException" language="en_US">
456  <synopsis>
457  Handle an exceptional condition.
458  </synopsis>
459  <syntax>
460  <parameter name="reason" required="true" />
461  </syntax>
462  <description>
463  <para>This application will jump to the <literal>e</literal> extension in the current context, setting the
464  dialplan function EXCEPTION(). If the <literal>e</literal> extension does not exist, the call will hangup.</para>
465  </description>
466  <see-also>
467  <ref type="function">Exception</ref>
468  </see-also>
469  </application>
470  <application name="ResetCDR" language="en_US">
471  <synopsis>
472  Resets the Call Data Record.
473  </synopsis>
474  <syntax>
475  <parameter name="options">
476  <optionlist>
477  <option name="w">
478  <para>Store the current CDR record before resetting it.</para>
479  </option>
480  <option name="a">
481  <para>Store any stacked records.</para>
482  </option>
483  <option name="v">
484  <para>Save CDR variables.</para>
485  </option>
486  <option name="e">
487  <para>Enable CDR only (negate effects of NoCDR).</para>
488  </option>
489  </optionlist>
490  </parameter>
491  </syntax>
492  <description>
493  <para>This application causes the Call Data Record to be reset.</para>
494  </description>
495  <see-also>
496  <ref type="application">ForkCDR</ref>
497  <ref type="application">NoCDR</ref>
498  </see-also>
499  </application>
500  <application name="Ringing" language="en_US">
501  <synopsis>
502  Indicate ringing tone.
503  </synopsis>
504  <syntax />
505  <description>
506  <para>This application will request that the channel indicate a ringing tone to the user.</para>
507  </description>
508  <see-also>
509  <ref type="application">Busy</ref>
510  <ref type="application">Congestion</ref>
511  <ref type="application">Progress</ref>
512  <ref type="application">Playtones</ref>
513  </see-also>
514  </application>
515  <application name="SayAlpha" language="en_US">
516  <synopsis>
517  Say Alpha.
518  </synopsis>
519  <syntax>
520  <parameter name="string" required="true" />
521  </syntax>
522  <description>
523  <para>This application will play the sounds that correspond to the letters of the
524  given <replaceable>string</replaceable>.</para>
525  </description>
526  <see-also>
527  <ref type="application">SayDigits</ref>
528  <ref type="application">SayNumber</ref>
529  <ref type="application">SayPhonetic</ref>
530  <ref type="function">CHANNEL</ref>
531  </see-also>
532  </application>
533  <application name="SayDigits" language="en_US">
534  <synopsis>
535  Say Digits.
536  </synopsis>
537  <syntax>
538  <parameter name="digits" required="true" />
539  </syntax>
540  <description>
541  <para>This application will play the sounds that correspond to the digits of
542  the given number. This will use the language that is currently set for the channel.</para>
543  </description>
544  <see-also>
545  <ref type="application">SayAlpha</ref>
546  <ref type="application">SayNumber</ref>
547  <ref type="application">SayPhonetic</ref>
548  <ref type="function">CHANNEL</ref>
549  </see-also>
550  </application>
551  <application name="SayNumber" language="en_US">
552  <synopsis>
553  Say Number.
554  </synopsis>
555  <syntax>
556  <parameter name="digits" required="true" />
557  <parameter name="gender" />
558  </syntax>
559  <description>
560  <para>This application will play the sounds that correspond to the given <replaceable>digits</replaceable>.
561  Optionally, a <replaceable>gender</replaceable> may be specified. This will use the language that is currently
562  set for the channel. See the CHANNEL() function for more information on setting the language for the channel.</para>
563  </description>
564  <see-also>
565  <ref type="application">SayAlpha</ref>
566  <ref type="application">SayDigits</ref>
567  <ref type="application">SayPhonetic</ref>
568  <ref type="function">CHANNEL</ref>
569  </see-also>
570  </application>
571  <application name="SayPhonetic" language="en_US">
572  <synopsis>
573  Say Phonetic.
574  </synopsis>
575  <syntax>
576  <parameter name="string" required="true" />
577  </syntax>
578  <description>
579  <para>This application will play the sounds from the phonetic alphabet that correspond to the
580  letters in the given <replaceable>string</replaceable>.</para>
581  </description>
582  <see-also>
583  <ref type="application">SayAlpha</ref>
584  <ref type="application">SayDigits</ref>
585  <ref type="application">SayNumber</ref>
586  </see-also>
587  </application>
588  <application name="SayDate" language="en_US">
589  <synopsis>
590  Says a given unixtime date.
591  </synopsis>
592  <syntax>
593  <parameter name="date" required="true" />
594  <parameter name="escape digits" />
595  </syntax>
596  <description>
597  <para>This application will say a given date, returning early if any of the given DTMF digits are received on the channel.
598  <replaceable>date</replaceable> is given as number of seconds elapsed since 00:00:00 on January 1, 1970, Coordinated Universal Time (UTC).
599  The variable USER_INPUT is set with the ASCII numerical value of the digit if a valid one was pressed before playback completes.
600  </para>
601  </description>
602  <see-also>
603  <ref type="application">SayAlpha</ref>
604  <ref type="application">SayDigits</ref>
605  <ref type="application">SayNumber</ref>
606  </see-also>
607  </application>
608 
609  <application name="SayTime" language="en_US">
610  <synopsis>
611  Says a time given as seconds elapsed since 00:00:00"
612  </synopsis>
613  <syntax>
614  <parameter name="time" required="true" />
615  <parameter name="escape digits" />
616  </syntax>
617  <description>
618  <para>This application will say a given time, returning early if any of the given DTMF digits are received on the channel.
619  <replaceable>time</replaceable> is given as number of seconds elapsed since 00:00:00.
620  For values greater than a day in seconds (24*60*60) only the time part is taken into account.
621  The variable USER_INPUT is set with the ASCII numerical value of the digit if a valid one was pressed before playback completes.
622  </para>
623  </description>
624  <see-also>
625  <ref type="application">SayAlpha</ref>
626  <ref type="application">SayDigits</ref>
627  <ref type="application">SayNumber</ref>
628  </see-also>
629  </application>
630  <application name="Set" language="en_US">
631  <synopsis>
632  Set channel variable or function value.
633  </synopsis>
634  <syntax argsep="=">
635  <parameter name="name" required="true" />
636  <parameter name="value" required="true" />
637  </syntax>
638  <description>
639  <para>This function can be used to set the value of channel variables or dialplan functions.
640  When setting variables, if the variable name is prefixed with <literal>_</literal>,
641  the variable will be inherited into channels created from the current channel.
642  If the variable name is prefixed with <literal>__</literal>, the variable will be
643  inherited into channels created from the current channel and all children channels.</para>
644  <note><para>If (and only if), in <filename>/etc/asterisk/asterisk.conf</filename>, you have
645  a <literal>[compat]</literal> category, and you have <literal>app_set = 1.4</literal> under that, then
646  the behavior of this app changes, and strips surrounding quotes from the right hand side as
647  it did previously in 1.4.
648  The advantages of not stripping out quoting, and not caring about the separator characters (comma and vertical bar)
649  were sufficient to make these changes in 1.6. Confusion about how many backslashes would be needed to properly
650  protect separators and quotes in various database access strings has been greatly
651  reduced by these changes.</para></note>
652  </description>
653  <see-also>
654  <ref type="application">MSet</ref>
655  <ref type="function">GLOBAL</ref>
656  <ref type="function">SET</ref>
657  <ref type="function">ENV</ref>
658  </see-also>
659  </application>
660  <application name="MSet" language="en_US">
661  <synopsis>
662  Set channel variable(s) or function value(s).
663  </synopsis>
664  <syntax>
665  <parameter name="set1" required="true" argsep="=">
666  <argument name="name1" required="true" />
667  <argument name="value1" required="true" />
668  </parameter>
669  <parameter name="set2" multiple="true" argsep="=">
670  <argument name="name2" required="true" />
671  <argument name="value2" required="true" />
672  </parameter>
673  </syntax>
674  <description>
675  <para>This function can be used to set the value of channel variables or dialplan functions.
676  When setting variables, if the variable name is prefixed with <literal>_</literal>,
677  the variable will be inherited into channels created from the current channel
678  If the variable name is prefixed with <literal>__</literal>, the variable will be
679  inherited into channels created from the current channel and all children channels.
680  MSet behaves in a similar fashion to the way Set worked in 1.2/1.4 and is thus
681  prone to doing things that you may not expect. For example, it strips surrounding
682  double-quotes from the right-hand side (value). If you need to put a separator
683  character (comma or vert-bar), you will need to escape them by inserting a backslash
684  before them. Avoid its use if possible.</para>
685  </description>
686  <see-also>
687  <ref type="application">Set</ref>
688  </see-also>
689  </application>
690  <application name="SetAMAFlags" language="en_US">
691  <synopsis>
692  Set the AMA Flags.
693  </synopsis>
694  <syntax>
695  <parameter name="flag" />
696  </syntax>
697  <description>
698  <para>This application will set the channel's AMA Flags for billing purposes.</para>
699  </description>
700  <see-also>
701  <ref type="function">CDR</ref>
702  </see-also>
703  </application>
704  <application name="Wait" language="en_US">
705  <synopsis>
706  Waits for some time.
707  </synopsis>
708  <syntax>
709  <parameter name="seconds" required="true">
710  <para>Can be passed with fractions of a second. For example, <literal>1.5</literal> will ask the
711  application to wait for 1.5 seconds.</para>
712  </parameter>
713  </syntax>
714  <description>
715  <para>This application waits for a specified number of <replaceable>seconds</replaceable>.</para>
716  </description>
717  </application>
718  <application name="WaitExten" language="en_US">
719  <synopsis>
720  Waits for an extension to be entered.
721  </synopsis>
722  <syntax>
723  <parameter name="seconds">
724  <para>Can be passed with fractions of a second. For example, <literal>1.5</literal> will ask the
725  application to wait for 1.5 seconds.</para>
726  </parameter>
727  <parameter name="options">
728  <optionlist>
729  <option name="m">
730  <para>Provide music on hold to the caller while waiting for an extension.</para>
731  <argument name="x">
732  <para>Specify the class for music on hold. <emphasis>CHANNEL(musicclass) will
733  be used instead if set</emphasis></para>
734  </argument>
735  </option>
736  </optionlist>
737  </parameter>
738  </syntax>
739  <description>
740  <para>This application waits for the user to enter a new extension for a specified number
741  of <replaceable>seconds</replaceable>.</para>
742  <xi:include xpointer="xpointer(/docs/application[@name='Macro']/description/warning[2])" />
743  </description>
744  <see-also>
745  <ref type="application">Background</ref>
746  <ref type="function">TIMEOUT</ref>
747  </see-also>
748  </application>
749  <function name="EXCEPTION" language="en_US">
750  <synopsis>
751  Retrieve the details of the current dialplan exception.
752  </synopsis>
753  <syntax>
754  <parameter name="field" required="true">
755  <para>The following fields are available for retrieval:</para>
756  <enumlist>
757  <enum name="reason">
758  <para>INVALID, ERROR, RESPONSETIMEOUT, ABSOLUTETIMEOUT, or custom
759  value set by the RaiseException() application</para>
760  </enum>
761  <enum name="context">
762  <para>The context executing when the exception occurred.</para>
763  </enum>
764  <enum name="exten">
765  <para>The extension executing when the exception occurred.</para>
766  </enum>
767  <enum name="priority">
768  <para>The numeric priority executing when the exception occurred.</para>
769  </enum>
770  </enumlist>
771  </parameter>
772  </syntax>
773  <description>
774  <para>Retrieve the details (specified <replaceable>field</replaceable>) of the current dialplan exception.</para>
775  </description>
776  <see-also>
777  <ref type="application">RaiseException</ref>
778  </see-also>
779  </function>
780  <function name="TESTTIME" language="en_US">
781  <synopsis>
782  Sets a time to be used with the channel to test logical conditions.
783  </synopsis>
784  <syntax>
785  <parameter name="date" required="true" argsep=" ">
786  <para>Date in ISO 8601 format</para>
787  </parameter>
788  <parameter name="time" required="true" argsep=" ">
789  <para>Time in HH:MM:SS format (24-hour time)</para>
790  </parameter>
791  <parameter name="zone" required="false">
792  <para>Timezone name</para>
793  </parameter>
794  </syntax>
795  <description>
796  <para>To test dialplan timing conditions at times other than the current time, use
797  this function to set an alternate date and time. For example, you may wish to evaluate
798  whether a location will correctly identify to callers that the area is closed on Christmas
799  Day, when Christmas would otherwise fall on a day when the office is normally open.</para>
800  </description>
801  <see-also>
802  <ref type="application">GotoIfTime</ref>
803  </see-also>
804  </function>
805  <manager name="ShowDialPlan" language="en_US">
806  <synopsis>
807  Show dialplan contexts and extensions
808  </synopsis>
809  <syntax>
810  <xi:include xpointer="xpointer(/docs/manager[@name='Login']/syntax/parameter[@name='ActionID'])" />
811  <parameter name="Extension">
812  <para>Show a specific extension.</para>
813  </parameter>
814  <parameter name="Context">
815  <para>Show a specific context.</para>
816  </parameter>
817  </syntax>
818  <description>
819  <para>Show dialplan contexts and extensions. Be aware that showing the full dialplan
820  may take a lot of capacity.</para>
821  </description>
822  </manager>
823  ***/
824 
825 #ifdef LOW_MEMORY
826 #define EXT_DATA_SIZE 256
827 #else
828 #define EXT_DATA_SIZE 8192
829 #endif
830 
831 #define SWITCH_DATA_LENGTH 256
832 
833 #define VAR_BUF_SIZE 4096
834 
835 #define VAR_NORMAL 1
836 #define VAR_SOFTTRAN 2
837 #define VAR_HARDTRAN 3
838 
839 #define BACKGROUND_SKIP (1 << 0)
840 #define BACKGROUND_NOANSWER (1 << 1)
841 #define BACKGROUND_MATCHEXTEN (1 << 2)
842 #define BACKGROUND_PLAYBACK (1 << 3)
843 
849 });
850 
851 #define WAITEXTEN_MOH (1 << 0)
852 #define WAITEXTEN_DIALTONE (1 << 1)
853 
857 });
858 
859 struct ast_context;
860 struct ast_app;
861 
863 
866 /*!
867  * \brief A thread local indicating whether the current thread can run
868  * 'dangerous' dialplan functions.
869  */
871 
872 /*!
873  * \brief Set to true (non-zero) to globally allow all dangerous dialplan
874  * functions to run.
875  */
876 static int live_dangerously;
877 
878 /*!
879  \brief ast_exten: An extension
880  The dialplan is saved as a linked list with each context
881  having it's own linked list of extensions - one item per
882  priority.
883 */
884 struct ast_exten {
885  char *exten; /*!< Extension name */
886  int matchcid; /*!< Match caller id ? */
887  const char *cidmatch; /*!< Caller id to match for this extension */
888  int priority; /*!< Priority */
889  const char *label; /*!< Label */
890  struct ast_context *parent; /*!< The context this extension belongs to */
891  const char *app; /*!< Application to execute */
892  struct ast_app *cached_app; /*!< Cached location of application */
893  void *data; /*!< Data to use (arguments) */
894  void (*datad)(void *); /*!< Data destructor */
895  struct ast_exten *peer; /*!< Next higher priority with our extension */
896  struct ast_hashtab *peer_table; /*!< Priorities list in hashtab form -- only on the head of the peer list */
897  struct ast_hashtab *peer_label_table; /*!< labeled priorities in the peers -- only on the head of the peer list */
898  const char *registrar; /*!< Registrar */
899  struct ast_exten *next; /*!< Extension with a greater ID */
900  char stuff[0];
901 };
902 
903 /*! \brief ast_include: include= support in extensions.conf */
904 struct ast_include {
905  const char *name;
906  const char *rname; /*!< Context to include */
907  const char *registrar; /*!< Registrar */
908  int hastime; /*!< If time construct exists */
909  struct ast_timing timing; /*!< time construct */
910  struct ast_include *next; /*!< Link them together */
911  char stuff[0];
912 };
913 
914 /*! \brief ast_sw: Switch statement in extensions.conf */
915 struct ast_sw {
916  char *name;
917  const char *registrar; /*!< Registrar */
918  char *data; /*!< Data load */
919  int eval;
921  char stuff[0];
922 };
923 
924 /*! \brief ast_ignorepat: Ignore patterns in dial plan */
926  const char *registrar;
927  struct ast_ignorepat *next;
928  const char pattern[0];
929 };
930 
931 /*! \brief match_char: forms a syntax tree for quick matching of extension patterns */
933 {
934  int is_pattern; /* the pattern started with '_' */
935  int deleted; /* if this is set, then... don't return it */
936  int specificity; /* simply the strlen of x, or 10 for X, 9 for Z, and 8 for N; and '.' and '!' will add 11 ? */
939  struct ast_exten *exten; /* attached to last char of a pattern for exten */
940  char x[1]; /* the pattern itself-- matches a single char */
941 };
942 
943 struct scoreboard /* make sure all fields are 0 before calling new_find_extension */
944 {
947  char last_char; /* set to ! or . if they are the end of the pattern */
948  int canmatch; /* if the string to match was just too short */
949  struct match_char *node;
951  struct ast_exten *exten;
952 };
953 
954 /*! \brief ast_context: An extension context */
955 struct ast_context {
956  ast_rwlock_t lock; /*!< A lock to prevent multiple threads from clobbering the context */
957  struct ast_exten *root; /*!< The root of the list of extensions */
958  struct ast_hashtab *root_table; /*!< For exact matches on the extensions in the pattern tree, and for traversals of the pattern_tree */
959  struct match_char *pattern_tree; /*!< A tree to speed up extension pattern matching */
960  struct ast_context *next; /*!< Link them together */
961  struct ast_include *includes; /*!< Include other contexts */
962  struct ast_ignorepat *ignorepats; /*!< Patterns for which to continue playing dialtone */
963  char *registrar; /*!< Registrar -- make sure you malloc this, as the registrar may have to survive module unloads */
964  int refcount; /*!< each module that would have created this context should inc/dec this as appropriate */
965  AST_LIST_HEAD_NOLOCK(, ast_sw) alts; /*!< Alternative switches */
966  ast_mutex_t macrolock; /*!< A lock to implement "exclusive" macros - held whilst a call is executing in the macro */
967  char name[0]; /*!< Name of the context */
968 };
969 
970 /*! \brief ast_app: A registered application */
971 struct ast_app {
972  int (*execute)(struct ast_channel *chan, const char *data);
974  AST_STRING_FIELD(synopsis); /*!< Synopsis text for 'show applications' */
975  AST_STRING_FIELD(description); /*!< Description (help text) for 'show application &lt;name&gt;' */
976  AST_STRING_FIELD(syntax); /*!< Syntax text for 'core show applications' */
977  AST_STRING_FIELD(arguments); /*!< Arguments description */
978  AST_STRING_FIELD(seealso); /*!< See also */
979  );
980 #ifdef AST_XML_DOCS
981  enum ast_doc_src docsrc; /*!< Where the documentation come from. */
982 #endif
983  AST_RWLIST_ENTRY(ast_app) list; /*!< Next app in list */
984  struct ast_module *module; /*!< Module this app belongs to */
985  char name[0]; /*!< Name of the application */
986 };
987 
988 /*! \brief ast_state_cb: An extension state notify register item */
989 struct ast_state_cb {
990  /*! Watcher ID returned when registered. */
991  int id;
992  /*! Arbitrary data passed for callbacks. */
993  void *data;
994  /*! Callback when state changes. */
996  /*! Callback when destroyed so any resources given by the registerer can be freed. */
998  /*! \note Only used by ast_merge_contexts_and_delete */
999  AST_LIST_ENTRY(ast_state_cb) entry;
1000 };
1001 
1002 /*!
1003  * \brief Structure for dial plan hints
1004  *
1005  * \note Hints are pointers from an extension in the dialplan to
1006  * one or more devices (tech/name)
1007  *
1008  * See \ref AstExtState
1009  */
1010 struct ast_hint {
1011  /*!
1012  * \brief Hint extension
1013  *
1014  * \note
1015  * Will never be NULL while the hint is in the hints container.
1016  */
1017  struct ast_exten *exten;
1018  struct ao2_container *callbacks; /*!< Callback container for this extension */
1019  int laststate; /*!< Last known state */
1020  char context_name[AST_MAX_CONTEXT];/*!< Context of destroyed hint extension. */
1021  char exten_name[AST_MAX_EXTENSION];/*!< Extension of destroyed hint extension. */
1022 };
1023 
1024 /* --- Hash tables of various objects --------*/
1025 #ifdef LOW_MEMORY
1026 #define HASH_EXTENHINT_SIZE 17
1027 #else
1028 #define HASH_EXTENHINT_SIZE 563
1029 #endif
1030 
1031 static const struct cfextension_states {
1033  const char * const text;
1034 } extension_states[] = {
1035  { AST_EXTENSION_NOT_INUSE, "Idle" },
1036  { AST_EXTENSION_INUSE, "InUse" },
1037  { AST_EXTENSION_BUSY, "Busy" },
1038  { AST_EXTENSION_UNAVAILABLE, "Unavailable" },
1039  { AST_EXTENSION_RINGING, "Ringing" },
1040  { AST_EXTENSION_INUSE | AST_EXTENSION_RINGING, "InUse&Ringing" },
1041  { AST_EXTENSION_ONHOLD, "Hold" },
1042  { AST_EXTENSION_INUSE | AST_EXTENSION_ONHOLD, "InUse&Hold" }
1043 };
1044 
1045 struct statechange {
1046  AST_LIST_ENTRY(statechange) entry;
1047  char dev[0];
1048 };
1049 
1052  AST_STRING_FIELD(context); /*!< Context associated with this exception */
1053  AST_STRING_FIELD(exten); /*!< Exten associated with this exception */
1054  AST_STRING_FIELD(reason); /*!< The exception reason */
1055  );
1056 
1057  int priority; /*!< Priority associated with this exception */
1058 };
1059 
1060 static int pbx_builtin_answer(struct ast_channel *, const char *);
1061 static int pbx_builtin_goto(struct ast_channel *, const char *);
1062 static int pbx_builtin_hangup(struct ast_channel *, const char *);
1063 static int pbx_builtin_background(struct ast_channel *, const char *);
1064 static int pbx_builtin_wait(struct ast_channel *, const char *);
1065 static int pbx_builtin_waitexten(struct ast_channel *, const char *);
1066 static int pbx_builtin_incomplete(struct ast_channel *, const char *);
1067 static int pbx_builtin_resetcdr(struct ast_channel *, const char *);
1068 static int pbx_builtin_setamaflags(struct ast_channel *, const char *);
1069 static int pbx_builtin_ringing(struct ast_channel *, const char *);
1070 static int pbx_builtin_proceeding(struct ast_channel *, const char *);
1071 static int pbx_builtin_progress(struct ast_channel *, const char *);
1072 static int pbx_builtin_congestion(struct ast_channel *, const char *);
1073 static int pbx_builtin_busy(struct ast_channel *, const char *);
1074 static int pbx_builtin_noop(struct ast_channel *, const char *);
1075 static int pbx_builtin_gotoif(struct ast_channel *, const char *);
1076 static int pbx_builtin_gotoiftime(struct ast_channel *, const char *);
1077 static int pbx_builtin_execiftime(struct ast_channel *, const char *);
1078 static int pbx_builtin_saynumber(struct ast_channel *, const char *);
1079 static int pbx_builtin_saydigits(struct ast_channel *, const char *);
1080 static int pbx_builtin_saycharacters(struct ast_channel *, const char *);
1081 static int pbx_builtin_sayphonetic(struct ast_channel *, const char *);
1082 static int pbx_builtin_saydate(struct ast_channel *, const char *);
1083 static int pbx_builtin_saytime(struct ast_channel *, const char *);
1084 static int matchcid(const char *cidpattern, const char *callerid);
1085 #ifdef NEED_DEBUG
1086 static void log_match_char_tree(struct match_char *node, char *prefix); /* for use anywhere */
1087 #endif
1088 static int pbx_builtin_importvar(struct ast_channel *, const char *);
1089 static void set_ext_pri(struct ast_channel *c, const char *exten, int pri);
1090 static void new_find_extension(const char *str, struct scoreboard *score,
1091  struct match_char *tree, int length, int spec, const char *callerid,
1092  const char *label, enum ext_match_t action);
1093 static struct match_char *already_in_tree(struct match_char *current, char *pat, int is_pattern);
1094 static struct match_char *add_exten_to_pattern_tree(struct ast_context *con,
1095  struct ast_exten *e1, int findonly);
1096 static void create_match_char_tree(struct ast_context *con);
1097 static struct ast_exten *get_canmatch_exten(struct match_char *node);
1098 static void destroy_pattern_tree(struct match_char *pattern_tree);
1099 static int hashtab_compare_extens(const void *ha_a, const void *ah_b);
1100 static int hashtab_compare_exten_numbers(const void *ah_a, const void *ah_b);
1101 static int hashtab_compare_exten_labels(const void *ah_a, const void *ah_b);
1102 static unsigned int hashtab_hash_extens(const void *obj);
1103 static unsigned int hashtab_hash_priority(const void *obj);
1104 static unsigned int hashtab_hash_labels(const void *obj);
1105 static void __ast_internal_context_destroy( struct ast_context *con);
1106 static int ast_add_extension_nolock(const char *context, int replace, const char *extension,
1107  int priority, const char *label, const char *callerid,
1108  const char *application, void *data, void (*datad)(void *), const char *registrar);
1109 static int ast_add_extension2_lockopt(struct ast_context *con,
1110  int replace, const char *extension, int priority, const char *label, const char *callerid,
1111  const char *application, void *data, void (*datad)(void *),
1112  const char *registrar, int lock_context);
1113 static struct ast_context *find_context_locked(const char *context);
1114 static struct ast_context *find_context(const char *context);
1115 
1116 /*!
1117  * \internal
1118  * \brief Character array comparison function for qsort.
1119  *
1120  * \param a Left side object.
1121  * \param b Right side object.
1122  *
1123  * \retval <0 if a < b
1124  * \retval =0 if a = b
1125  * \retval >0 if a > b
1126  */
1127 static int compare_char(const void *a, const void *b)
1128 {
1129  const unsigned char *ac = a;
1130  const unsigned char *bc = b;
1131 
1132  return *ac - *bc;
1133 }
1134 
1135 /* labels, contexts are case sensitive priority numbers are ints */
1136 int ast_hashtab_compare_contexts(const void *ah_a, const void *ah_b)
1137 {
1138  const struct ast_context *ac = ah_a;
1139  const struct ast_context *bc = ah_b;
1140  if (!ac || !bc) /* safety valve, but it might prevent a crash you'd rather have happen */
1141  return 1;
1142  /* assume context names are registered in a string table! */
1143  return strcmp(ac->name, bc->name);
1144 }
1145 
1146 static int hashtab_compare_extens(const void *ah_a, const void *ah_b)
1147 {
1148  const struct ast_exten *ac = ah_a;
1149  const struct ast_exten *bc = ah_b;
1150  int x = strcmp(ac->exten, bc->exten);
1151  if (x) { /* if exten names are diff, then return */
1152  return x;
1153  }
1154 
1155  /* but if they are the same, do the cidmatch values match? */
1156  /* not sure which side may be using ast_ext_matchcid_types, so check both */
1158  return 0;
1159  }
1161  return 0;
1162  }
1163  if (ac->matchcid != bc->matchcid) {
1164  return 1;
1165  }
1166  /* all other cases already disposed of, match now required on callerid string (cidmatch) */
1167  /* although ast_add_extension2_lockopt() enforces non-zero ptr, caller may not have */
1168  if (ast_strlen_zero(ac->cidmatch) && ast_strlen_zero(bc->cidmatch)) {
1169  return 0;
1170  }
1171  return strcmp(ac->cidmatch, bc->cidmatch);
1172 }
1173 
1174 static int hashtab_compare_exten_numbers(const void *ah_a, const void *ah_b)
1175 {
1176  const struct ast_exten *ac = ah_a;
1177  const struct ast_exten *bc = ah_b;
1178  return ac->priority != bc->priority;
1179 }
1180 
1181 static int hashtab_compare_exten_labels(const void *ah_a, const void *ah_b)
1182 {
1183  const struct ast_exten *ac = ah_a;
1184  const struct ast_exten *bc = ah_b;
1185  return strcmp(S_OR(ac->label, ""), S_OR(bc->label, ""));
1186 }
1187 
1188 unsigned int ast_hashtab_hash_contexts(const void *obj)
1189 {
1190  const struct ast_context *ac = obj;
1191  return ast_hashtab_hash_string(ac->name);
1192 }
1193 
1194 static unsigned int hashtab_hash_extens(const void *obj)
1195 {
1196  const struct ast_exten *ac = obj;
1197  unsigned int x = ast_hashtab_hash_string(ac->exten);
1198  unsigned int y = 0;
1199  if (ac->matchcid == AST_EXT_MATCHCID_ON)
1201  return x+y;
1202 }
1203 
1204 static unsigned int hashtab_hash_priority(const void *obj)
1205 {
1206  const struct ast_exten *ac = obj;
1207  return ast_hashtab_hash_int(ac->priority);
1208 }
1209 
1210 static unsigned int hashtab_hash_labels(const void *obj)
1211 {
1212  const struct ast_exten *ac = obj;
1213  return ast_hashtab_hash_string(S_OR(ac->label, ""));
1214 }
1215 
1216 
1219 
1220 static int autofallthrough = 1;
1221 static int extenpatternmatchnew = 0;
1222 static char *overrideswitch = NULL;
1223 
1224 /*! \brief Subscription for device state change events */
1226 
1228 static int countcalls;
1229 static int totalcalls;
1230 
1232 
1233 /*!
1234  * \brief Extra information for an \ref ast_custom_function holding privilege
1235  * escalation information. Kept in a separate structure for ABI compatibility.
1236  */
1239  const struct ast_custom_function *acf;
1240  unsigned int read_escalates:1;
1241  unsigned int write_escalates:1;
1242 };
1243 
1245 
1246 /*! \brief Declaration of builtin applications */
1247 static struct pbx_builtin {
1248  char name[AST_MAX_APP];
1249  int (*execute)(struct ast_channel *chan, const char *data);
1250 } builtins[] =
1251 {
1252  /* These applications are built into the PBX core and do not
1253  need separate modules */
1254 
1255  { "Answer", pbx_builtin_answer },
1256  { "BackGround", pbx_builtin_background },
1257  { "Busy", pbx_builtin_busy },
1258  { "Congestion", pbx_builtin_congestion },
1259  { "ExecIfTime", pbx_builtin_execiftime },
1260  { "Goto", pbx_builtin_goto },
1261  { "GotoIf", pbx_builtin_gotoif },
1262  { "GotoIfTime", pbx_builtin_gotoiftime },
1263  { "ImportVar", pbx_builtin_importvar },
1264  { "Hangup", pbx_builtin_hangup },
1265  { "Incomplete", pbx_builtin_incomplete },
1266  { "NoOp", pbx_builtin_noop },
1267  { "Proceeding", pbx_builtin_proceeding },
1268  { "Progress", pbx_builtin_progress },
1269  { "RaiseException", pbx_builtin_raise_exception },
1270  { "ResetCDR", pbx_builtin_resetcdr },
1271  { "Ringing", pbx_builtin_ringing },
1272  { "SayAlpha", pbx_builtin_saycharacters },
1273  { "SayDigits", pbx_builtin_saydigits },
1274  { "SayNumber", pbx_builtin_saynumber },
1275  { "SayPhonetic", pbx_builtin_sayphonetic },
1276  { "SayDate", pbx_builtin_saydate },
1277  { "SayTime", pbx_builtin_saytime },
1278  { "Set", pbx_builtin_setvar },
1279  { "MSet", pbx_builtin_setvar_multiple },
1280  { "SetAMAFlags", pbx_builtin_setamaflags },
1281  { "Wait", pbx_builtin_wait },
1282  { "WaitExten", pbx_builtin_waitexten }
1283 };
1284 
1285 static struct ast_context *contexts;
1286 static struct ast_hashtab *contexts_table = NULL;
1287 
1288 /*!
1289  * \brief Lock for the ast_context list
1290  * \note
1291  * This lock MUST be recursive, or a deadlock on reload may result. See
1292  * https://issues.asterisk.org/view.php?id=17643
1293  */
1295 
1296 /*!
1297  * \brief Lock to hold off restructuring of hints by ast_merge_contexts_and_delete.
1298  */
1300 
1301 static AST_RWLIST_HEAD_STATIC(apps, ast_app);
1302 
1304 
1305 static int stateid = 1;
1306 /*!
1307  * \note When holding this container's lock, do _not_ do
1308  * anything that will cause conlock to be taken, unless you
1309  * _already_ hold it. The ast_merge_contexts_and_delete function
1310  * will take the locks in conlock/hints order, so any other
1311  * paths that require both locks must also take them in that
1312  * order.
1313  */
1314 static struct ao2_container *hints;
1315 
1316 static struct ao2_container *statecbs;
1317 
1318 #ifdef CONTEXT_DEBUG
1319 
1320 /* these routines are provided for doing run-time checks
1321  on the extension structures, in case you are having
1322  problems, this routine might help you localize where
1323  the problem is occurring. It's kinda like a debug memory
1324  allocator's arena checker... It'll eat up your cpu cycles!
1325  but you'll see, if you call it in the right places,
1326  right where your problems began...
1327 */
1328 
1329 /* you can break on the check_contexts_trouble()
1330 routine in your debugger to stop at the moment
1331 there's a problem */
1332 void check_contexts_trouble(void);
1333 
1334 void check_contexts_trouble(void)
1335 {
1336  int x = 1;
1337  x = 2;
1338 }
1339 
1340 int check_contexts(char *, int);
1341 
1342 int check_contexts(char *file, int line )
1343 {
1344  struct ast_hashtab_iter *t1;
1345  struct ast_context *c1, *c2;
1346  int found = 0;
1347  struct ast_exten *e1, *e2, *e3;
1348  struct ast_exten ex;
1349 
1350  /* try to find inconsistencies */
1351  /* is every context in the context table in the context list and vice-versa ? */
1352 
1353  if (!contexts_table) {
1354  ast_log(LOG_NOTICE,"Called from: %s:%d: No contexts_table!\n", file, line);
1355  usleep(500000);
1356  }
1357 
1359  while( (c1 = ast_hashtab_next(t1))) {
1360  for(c2=contexts;c2;c2=c2->next) {
1361  if (!strcmp(c1->name, c2->name)) {
1362  found = 1;
1363  break;
1364  }
1365  }
1366  if (!found) {
1367  ast_log(LOG_NOTICE,"Called from: %s:%d: Could not find the %s context in the linked list\n", file, line, c1->name);
1368  check_contexts_trouble();
1369  }
1370  }
1372  for(c2=contexts;c2;c2=c2->next) {
1373  c1 = find_context_locked(c2->name);
1374  if (!c1) {
1375  ast_log(LOG_NOTICE,"Called from: %s:%d: Could not find the %s context in the hashtab\n", file, line, c2->name);
1376  check_contexts_trouble();
1377  } else
1379  }
1380 
1381  /* loop thru all contexts, and verify the exten structure compares to the
1382  hashtab structure */
1383  for(c2=contexts;c2;c2=c2->next) {
1384  c1 = find_context_locked(c2->name);
1385  if (c1) {
1387 
1388  /* is every entry in the root list also in the root_table? */
1389  for(e1 = c1->root; e1; e1=e1->next)
1390  {
1391  char dummy_name[1024];
1392  ex.exten = dummy_name;
1393  ex.matchcid = e1->matchcid;
1394  ex.cidmatch = e1->cidmatch;
1395  ast_copy_string(dummy_name, e1->exten, sizeof(dummy_name));
1396  e2 = ast_hashtab_lookup(c1->root_table, &ex);
1397  if (!e2) {
1398  if (e1->matchcid == AST_EXT_MATCHCID_ON) {
1399  ast_log(LOG_NOTICE,"Called from: %s:%d: The %s context records the exten %s (CID match: %s) but it is not in its root_table\n", file, line, c2->name, dummy_name, e1->cidmatch );
1400  } else {
1401  ast_log(LOG_NOTICE,"Called from: %s:%d: The %s context records the exten %s but it is not in its root_table\n", file, line, c2->name, dummy_name );
1402  }
1403  check_contexts_trouble();
1404  }
1405  }
1406 
1407  /* is every entry in the root_table also in the root list? */
1408  if (!c2->root_table) {
1409  if (c2->root) {
1410  ast_log(LOG_NOTICE,"Called from: %s:%d: No c2->root_table for context %s!\n", file, line, c2->name);
1411  usleep(500000);
1412  }
1413  } else {
1415  while( (e2 = ast_hashtab_next(t1)) ) {
1416  for(e1=c2->root;e1;e1=e1->next) {
1417  if (!strcmp(e1->exten, e2->exten)) {
1418  found = 1;
1419  break;
1420  }
1421  }
1422  if (!found) {
1423  ast_log(LOG_NOTICE,"Called from: %s:%d: The %s context records the exten %s but it is not in its root_table\n", file, line, c2->name, e2->exten);
1424  check_contexts_trouble();
1425  }
1426 
1427  }
1429  }
1430  }
1431  /* is every priority reflected in the peer_table at the head of the list? */
1432 
1433  /* is every entry in the root list also in the root_table? */
1434  /* are the per-extension peer_tables in the right place? */
1435 
1436  for(e1 = c2->root; e1; e1 = e1->next) {
1437 
1438  for(e2=e1;e2;e2=e2->peer) {
1439  ex.priority = e2->priority;
1440  if (e2 != e1 && e2->peer_table) {
1441  ast_log(LOG_NOTICE,"Called from: %s:%d: The %s context, %s exten, %d priority has a peer_table entry, and shouldn't!\n", file, line, c2->name, e1->exten, e2->priority );
1442  check_contexts_trouble();
1443  }
1444 
1445  if (e2 != e1 && e2->peer_label_table) {
1446  ast_log(LOG_NOTICE,"Called from: %s:%d: The %s context, %s exten, %d priority has a peer_label_table entry, and shouldn't!\n", file, line, c2->name, e1->exten, e2->priority );
1447  check_contexts_trouble();
1448  }
1449 
1450  if (e2 == e1 && !e2->peer_table){
1451  ast_log(LOG_NOTICE,"Called from: %s:%d: The %s context, %s exten, %d priority doesn't have a peer_table!\n", file, line, c2->name, e1->exten, e2->priority );
1452  check_contexts_trouble();
1453  }
1454 
1455  if (e2 == e1 && !e2->peer_label_table) {
1456  ast_log(LOG_NOTICE,"Called from: %s:%d: The %s context, %s exten, %d priority doesn't have a peer_label_table!\n", file, line, c2->name, e1->exten, e2->priority );
1457  check_contexts_trouble();
1458  }
1459 
1460 
1461  e3 = ast_hashtab_lookup(e1->peer_table, &ex);
1462  if (!e3) {
1463  ast_log(LOG_NOTICE,"Called from: %s:%d: The %s context, %s exten, %d priority is not reflected in the peer_table\n", file, line, c2->name, e1->exten, e2->priority );
1464  check_contexts_trouble();
1465  }
1466  }
1467 
1468  if (!e1->peer_table){
1469  ast_log(LOG_NOTICE,"Called from: %s:%d: No e1->peer_table!\n", file, line);
1470  usleep(500000);
1471  }
1472 
1473  /* is every entry in the peer_table also in the peer list? */
1475  while( (e2 = ast_hashtab_next(t1)) ) {
1476  for(e3=e1;e3;e3=e3->peer) {
1477  if (e3->priority == e2->priority) {
1478  found = 1;
1479  break;
1480  }
1481  }
1482  if (!found) {
1483  ast_log(LOG_NOTICE,"Called from: %s:%d: The %s context, %s exten, %d priority is not reflected in the peer list\n", file, line, c2->name, e1->exten, e2->priority );
1484  check_contexts_trouble();
1485  }
1486  }
1488  }
1489  }
1490  return 0;
1491 }
1492 #endif
1493 
1494 /*
1495  \note This function is special. It saves the stack so that no matter
1496  how many times it is called, it returns to the same place */
1497 int pbx_exec(struct ast_channel *c, /*!< Channel */
1498  struct ast_app *app, /*!< Application */
1499  const char *data) /*!< Data for execution */
1500 {
1501  int res;
1502  struct ast_module_user *u = NULL;
1503  const char *saved_c_appl;
1504  const char *saved_c_data;
1505 
1506  if (c->cdr && !ast_check_hangup(c))
1507  ast_cdr_setapp(c->cdr, app->name, data);
1508 
1509  /* save channel values */
1510  saved_c_appl= c->appl;
1511  saved_c_data= c->data;
1512 
1513  c->appl = app->name;
1514  c->data = data;
1515  ast_cel_report_event(c, AST_CEL_APP_START, NULL, NULL, NULL);
1516 
1517  if (app->module)
1518  u = __ast_module_user_add(app->module, c);
1519  if (strcasecmp(app->name, "system") && !ast_strlen_zero(data) &&
1520  strchr(data, '|') && !strchr(data, ',') && !ast_opt_dont_warn) {
1521  ast_log(LOG_WARNING, "The application delimiter is now the comma, not "
1522  "the pipe. Did you forget to convert your dialplan? (%s(%s))\n",
1523  app->name, (char *) data);
1524  }
1525  res = app->execute(c, S_OR(data, ""));
1526  if (app->module && u)
1527  __ast_module_user_remove(app->module, u);
1528  ast_cel_report_event(c, AST_CEL_APP_END, NULL, NULL, NULL);
1529  /* restore channel values */
1530  c->appl = saved_c_appl;
1531  c->data = saved_c_data;
1532  return res;
1533 }
1534 
1535 /*! \brief Find application handle in linked list
1536  */
1537 struct ast_app *pbx_findapp(const char *app)
1538 {
1539  struct ast_app *tmp;
1540 
1542  AST_RWLIST_TRAVERSE(&apps, tmp, list) {
1543  if (!strcasecmp(tmp->name, app))
1544  break;
1545  }
1547 
1548  return tmp;
1549 }
1550 
1551 static struct ast_switch *pbx_findswitch(const char *sw)
1552 {
1553  struct ast_switch *asw;
1554 
1556  AST_RWLIST_TRAVERSE(&switches, asw, list) {
1557  if (!strcasecmp(asw->name, sw))
1558  break;
1559  }
1561 
1562  return asw;
1563 }
1564 
1565 static inline int include_valid(struct ast_include *i)
1566 {
1567  if (!i->hastime)
1568  return 1;
1569 
1570  return ast_check_timing(&(i->timing));
1571 }
1572 
1573 static void pbx_destroy(struct ast_pbx *p)
1574 {
1575  ast_free(p);
1576 }
1577 
1578 /* form a tree that fully describes all the patterns in a context's extensions
1579  * in this tree, a "node" represents an individual character or character set
1580  * meant to match the corresponding character in a dial string. The tree
1581  * consists of a series of match_char structs linked in a chain
1582  * via the alt_char pointers. More than one pattern can share the same parts of the
1583  * tree as other extensions with the same pattern to that point.
1584  * My first attempt to duplicate the finding of the 'best' pattern was flawed in that
1585  * I misunderstood the general algorithm. I thought that the 'best' pattern
1586  * was the one with lowest total score. This was not true. Thus, if you have
1587  * patterns "1XXXXX" and "X11111", you would be tempted to say that "X11111" is
1588  * the "best" match because it has fewer X's, and is therefore more specific,
1589  * but this is not how the old algorithm works. It sorts matching patterns
1590  * in a similar collating sequence as sorting alphabetic strings, from left to
1591  * right. Thus, "1XXXXX" comes before "X11111", and would be the "better" match,
1592  * because "1" is more specific than "X".
1593  * So, to accomodate this philosophy, I sort the tree branches along the alt_char
1594  * line so they are lowest to highest in specificity numbers. This way, as soon
1595  * as we encounter our first complete match, we automatically have the "best"
1596  * match and can stop the traversal immediately. Same for CANMATCH/MATCHMORE.
1597  * If anyone would like to resurrect the "wrong" pattern trie searching algorithm,
1598  * they are welcome to revert pbx to before 1 Apr 2008.
1599  * As an example, consider these 4 extensions:
1600  * (a) NXXNXXXXXX
1601  * (b) 307754XXXX
1602  * (c) fax
1603  * (d) NXXXXXXXXX
1604  *
1605  * In the above, between (a) and (d), (a) is a more specific pattern than (d), and would win over
1606  * most numbers. For all numbers beginning with 307754, (b) should always win.
1607  *
1608  * These pattern should form a (sorted) tree that looks like this:
1609  * { "3" } --next--> { "0" } --next--> { "7" } --next--> { "7" } --next--> { "5" } ... blah ... --> { "X" exten_match: (b) }
1610  * |
1611  * |alt
1612  * |
1613  * { "f" } --next--> { "a" } --next--> { "x" exten_match: (c) }
1614  * { "N" } --next--> { "X" } --next--> { "X" } --next--> { "N" } --next--> { "X" } ... blah ... --> { "X" exten_match: (a) }
1615  * | |
1616  * | |alt
1617  * |alt |
1618  * | { "X" } --next--> { "X" } ... blah ... --> { "X" exten_match: (d) }
1619  * |
1620  * NULL
1621  *
1622  * In the above, I could easily turn "N" into "23456789", but I think that a quick "if( *z >= '2' && *z <= '9' )" might take
1623  * fewer CPU cycles than a call to strchr("23456789",*z), where *z is the char to match...
1624  *
1625  * traversal is pretty simple: one routine merely traverses the alt list, and for each matching char in the pattern, it calls itself
1626  * on the corresponding next pointer, incrementing also the pointer of the string to be matched, and passing the total specificity and length.
1627  * We pass a pointer to a scoreboard down through, also.
1628  * The scoreboard isn't as necessary to the revised algorithm, but I kept it as a handy way to return the matched extension.
1629  * The first complete match ends the traversal, which should make this version of the pattern matcher faster
1630  * the previous. The same goes for "CANMATCH" or "MATCHMORE"; the first such match ends the traversal. In both
1631  * these cases, the reason we can stop immediately, is because the first pattern match found will be the "best"
1632  * according to the sort criteria.
1633  * Hope the limit on stack depth won't be a problem... this routine should
1634  * be pretty lean as far a stack usage goes. Any non-match terminates the recursion down a branch.
1635  *
1636  * In the above example, with the number "3077549999" as the pattern, the traversor could match extensions a, b and d. All are
1637  * of length 10; they have total specificities of 24580, 10246, and 25090, respectively, not that this matters
1638  * at all. (b) wins purely because the first character "3" is much more specific (lower specificity) than "N". I have
1639  * left the specificity totals in the code as an artifact; at some point, I will strip it out.
1640  *
1641  * Just how much time this algorithm might save over a plain linear traversal over all possible patterns is unknown,
1642  * because it's a function of how many extensions are stored in a context. With thousands of extensions, the speedup
1643  * can be very noticeable. The new matching algorithm can run several hundreds of times faster, if not a thousand or
1644  * more times faster in extreme cases.
1645  *
1646  * MatchCID patterns are also supported, and stored in the tree just as the extension pattern is. Thus, you
1647  * can have patterns in your CID field as well.
1648  *
1649  * */
1650 
1651 
1652 static void update_scoreboard(struct scoreboard *board, int length, int spec, struct ast_exten *exten, char last, const char *callerid, int deleted, struct match_char *node)
1653 {
1654  /* if this extension is marked as deleted, then skip this -- if it never shows
1655  on the scoreboard, it will never be found, nor will halt the traversal. */
1656  if (deleted)
1657  return;
1658  board->total_specificity = spec;
1659  board->total_length = length;
1660  board->exten = exten;
1661  board->last_char = last;
1662  board->node = node;
1663 #ifdef NEED_DEBUG_HERE
1664  ast_log(LOG_NOTICE,"Scoreboarding (LONGER) %s, len=%d, score=%d\n", exten->exten, length, spec);
1665 #endif
1666 }
1667 
1668 #ifdef NEED_DEBUG
1669 static void log_match_char_tree(struct match_char *node, char *prefix)
1670 {
1671  char extenstr[40];
1672  struct ast_str *my_prefix = ast_str_alloca(1024);
1673 
1674  extenstr[0] = '\0';
1675 
1676  if (node && node->exten)
1677  snprintf(extenstr, sizeof(extenstr), "(%p)", node->exten);
1678 
1679  if (strlen(node->x) > 1) {
1680  ast_debug(1, "%s[%s]:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y':'N',
1681  node->deleted? 'D':'-', node->specificity, node->exten? "EXTEN:":"",
1682  node->exten ? node->exten->exten : "", extenstr);
1683  } else {
1684  ast_debug(1, "%s%s:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y':'N',
1685  node->deleted? 'D':'-', node->specificity, node->exten? "EXTEN:":"",
1686  node->exten ? node->exten->exten : "", extenstr);
1687  }
1688 
1689  ast_str_set(&my_prefix, 0, "%s+ ", prefix);
1690 
1691  if (node->next_char)
1692  log_match_char_tree(node->next_char, ast_str_buffer(my_prefix));
1693 
1694  if (node->alt_char)
1695  log_match_char_tree(node->alt_char, prefix);
1696 }
1697 #endif
1698 
1699 static void cli_match_char_tree(struct match_char *node, char *prefix, int fd)
1700 {
1701  char extenstr[40];
1702  struct ast_str *my_prefix = ast_str_alloca(1024);
1703 
1704  extenstr[0] = '\0';
1705 
1706  if (node->exten) {
1707  snprintf(extenstr, sizeof(extenstr), "(%p)", node->exten);
1708  }
1709 
1710  if (strlen(node->x) > 1) {
1711  ast_cli(fd, "%s[%s]:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y' : 'N',
1712  node->deleted ? 'D' : '-', node->specificity, node->exten? "EXTEN:" : "",
1713  node->exten ? node->exten->exten : "", extenstr);
1714  } else {
1715  ast_cli(fd, "%s%s:%c:%c:%d:%s%s%s\n", prefix, node->x, node->is_pattern ? 'Y' : 'N',
1716  node->deleted ? 'D' : '-', node->specificity, node->exten? "EXTEN:" : "",
1717  node->exten ? node->exten->exten : "", extenstr);
1718  }
1719 
1720  ast_str_set(&my_prefix, 0, "%s+ ", prefix);
1721 
1722  if (node->next_char)
1723  cli_match_char_tree(node->next_char, ast_str_buffer(my_prefix), fd);
1724 
1725  if (node->alt_char)
1726  cli_match_char_tree(node->alt_char, prefix, fd);
1727 }
1728 
1729 static struct ast_exten *get_canmatch_exten(struct match_char *node)
1730 {
1731  /* find the exten at the end of the rope */
1732  struct match_char *node2 = node;
1733 
1734  for (node2 = node; node2; node2 = node2->next_char) {
1735  if (node2->exten) {
1736 #ifdef NEED_DEBUG_HERE
1737  ast_log(LOG_NOTICE,"CanMatch_exten returns exten %s(%p)\n", node2->exten->exten, node2->exten);
1738 #endif
1739  return node2->exten;
1740  }
1741  }
1742 #ifdef NEED_DEBUG_HERE
1743  ast_log(LOG_NOTICE,"CanMatch_exten returns NULL, match_char=%s\n", node->x);
1744 #endif
1745  return 0;
1746 }
1747 
1748 static struct ast_exten *trie_find_next_match(struct match_char *node)
1749 {
1750  struct match_char *m3;
1751  struct match_char *m4;
1752  struct ast_exten *e3;
1753 
1754  if (node && node->x[0] == '.' && !node->x[1]) { /* dot and ! will ALWAYS be next match in a matchmore */
1755  return node->exten;
1756  }
1757 
1758  if (node && node->x[0] == '!' && !node->x[1]) {
1759  return node->exten;
1760  }
1761 
1762  if (!node || !node->next_char) {
1763  return NULL;
1764  }
1765 
1766  m3 = node->next_char;
1767 
1768  if (m3->exten) {
1769  return m3->exten;
1770  }
1771  for (m4 = m3->alt_char; m4; m4 = m4->alt_char) {
1772  if (m4->exten) {
1773  return m4->exten;
1774  }
1775  }
1776  for (m4 = m3; m4; m4 = m4->alt_char) {
1777  e3 = trie_find_next_match(m3);
1778  if (e3) {
1779  return e3;
1780  }
1781  }
1782 
1783  return NULL;
1784 }
1785 
1786 #ifdef DEBUG_THIS
1787 static char *action2str(enum ext_match_t action)
1788 {
1789  switch (action) {
1790  case E_MATCH:
1791  return "MATCH";
1792  case E_CANMATCH:
1793  return "CANMATCH";
1794  case E_MATCHMORE:
1795  return "MATCHMORE";
1796  case E_FINDLABEL:
1797  return "FINDLABEL";
1798  case E_SPAWN:
1799  return "SPAWN";
1800  default:
1801  return "?ACTION?";
1802  }
1803 }
1804 
1805 #endif
1806 
1807 static void new_find_extension(const char *str, struct scoreboard *score, struct match_char *tree, int length, int spec, const char *callerid, const char *label, enum ext_match_t action)
1808 {
1809  struct match_char *p; /* note minimal stack storage requirements */
1810  struct ast_exten pattern = { .label = label };
1811 #ifdef DEBUG_THIS
1812  if (tree)
1813  ast_log(LOG_NOTICE,"new_find_extension called with %s on (sub)tree %s action=%s\n", str, tree->x, action2str(action));
1814  else
1815  ast_log(LOG_NOTICE,"new_find_extension called with %s on (sub)tree NULL action=%s\n", str, action2str(action));
1816 #endif
1817  for (p = tree; p; p = p->alt_char) {
1818  if (p->is_pattern) {
1819  if (p->x[0] == 'N') {
1820  if (p->x[1] == 0 && *str >= '2' && *str <= '9' ) {
1821 #define NEW_MATCHER_CHK_MATCH \
1822  if (p->exten && !(*(str + 1))) { /* if a shorter pattern matches along the way, might as well report it */ \
1823  if (action == E_MATCH || action == E_SPAWN || action == E_FINDLABEL) { /* if in CANMATCH/MATCHMORE, don't let matches get in the way */ \
1824  update_scoreboard(score, length + 1, spec + p->specificity, p->exten, 0, callerid, p->deleted, p); \
1825  if (!p->deleted) { \
1826  if (action == E_FINDLABEL) { \
1827  if (ast_hashtab_lookup(score->exten->peer_label_table, &pattern)) { \
1828  ast_debug(4, "Found label in preferred extension\n"); \
1829  return; \
1830  } \
1831  } else { \
1832  ast_debug(4, "returning an exact match-- first found-- %s\n", p->exten->exten); \
1833  return; /* the first match, by definition, will be the best, because of the sorted tree */ \
1834  } \
1835  } \
1836  } \
1837  }
1838 
1839 #define NEW_MATCHER_RECURSE \
1840  if (p->next_char && (*(str + 1) || (p->next_char->x[0] == '/' && p->next_char->x[1] == 0) \
1841  || p->next_char->x[0] == '!')) { \
1842  if (*(str + 1) || p->next_char->x[0] == '!') { \
1843  new_find_extension(str + 1, score, p->next_char, length + 1, spec + p->specificity, callerid, label, action); \
1844  if (score->exten) { \
1845  ast_debug(4 ,"returning an exact match-- %s\n", score->exten->exten); \
1846  return; /* the first match is all we need */ \
1847  } \
1848  } else { \
1849  new_find_extension("/", score, p->next_char, length + 1, spec + p->specificity, callerid, label, action); \
1850  if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) { \
1851  ast_debug(4,"returning a (can/more) match--- %s\n", score->exten ? score->exten->exten : \
1852  "NULL"); \
1853  return; /* the first match is all we need */ \
1854  } \
1855  } \
1856  } else if ((p->next_char || action == E_CANMATCH) && !*(str + 1)) { \
1857  score->canmatch = 1; \
1858  score->canmatch_exten = get_canmatch_exten(p); \
1859  if (action == E_CANMATCH || action == E_MATCHMORE) { \
1860  ast_debug(4, "returning a canmatch/matchmore--- str=%s\n", str); \
1861  return; \
1862  } \
1863  }
1864 
1867  }
1868  } else if (p->x[0] == 'Z') {
1869  if (p->x[1] == 0 && *str >= '1' && *str <= '9' ) {
1872  }
1873  } else if (p->x[0] == 'X') {
1874  if (p->x[1] == 0 && *str >= '0' && *str <= '9' ) {
1877  }
1878  } else if (p->x[0] == '.' && p->x[1] == 0) {
1879  /* how many chars will the . match against? */
1880  int i = 0;
1881  const char *str2 = str;
1882  while (*str2 && *str2 != '/') {
1883  str2++;
1884  i++;
1885  }
1886  if (p->exten && *str2 != '/') {
1887  update_scoreboard(score, length + i, spec + (i * p->specificity), p->exten, '.', callerid, p->deleted, p);
1888  if (score->exten) {
1889  ast_debug(4,"return because scoreboard has a match with '/'--- %s\n", score->exten->exten);
1890  return; /* the first match is all we need */
1891  }
1892  }
1893  if (p->next_char && p->next_char->x[0] == '/' && p->next_char->x[1] == 0) {
1894  new_find_extension("/", score, p->next_char, length + i, spec+(p->specificity*i), callerid, label, action);
1895  if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) {
1896  ast_debug(4, "return because scoreboard has exact match OR CANMATCH/MATCHMORE & canmatch set--- %s\n", score->exten ? score->exten->exten : "NULL");
1897  return; /* the first match is all we need */
1898  }
1899  }
1900  } else if (p->x[0] == '!' && p->x[1] == 0) {
1901  /* how many chars will the . match against? */
1902  int i = 1;
1903  const char *str2 = str;
1904  while (*str2 && *str2 != '/') {
1905  str2++;
1906  i++;
1907  }
1908  if (p->exten && *str2 != '/') {
1909  update_scoreboard(score, length + 1, spec + (p->specificity * i), p->exten, '!', callerid, p->deleted, p);
1910  if (score->exten) {
1911  ast_debug(4, "return because scoreboard has a '!' match--- %s\n", score->exten->exten);
1912  return; /* the first match is all we need */
1913  }
1914  }
1915  if (p->next_char && p->next_char->x[0] == '/' && p->next_char->x[1] == 0) {
1916  new_find_extension("/", score, p->next_char, length + i, spec + (p->specificity * i), callerid, label, action);
1917  if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) {
1918  ast_debug(4, "return because scoreboard has exact match OR CANMATCH/MATCHMORE & canmatch set with '/' and '!'--- %s\n", score->exten ? score->exten->exten : "NULL");
1919  return; /* the first match is all we need */
1920  }
1921  }
1922  } else if (p->x[0] == '/' && p->x[1] == 0) {
1923  /* the pattern in the tree includes the cid match! */
1924  if (p->next_char && callerid && *callerid) {
1925  new_find_extension(callerid, score, p->next_char, length + 1, spec, callerid, label, action);
1926  if (score->exten || ((action == E_CANMATCH || action == E_MATCHMORE) && score->canmatch)) {
1927  ast_debug(4, "return because scoreboard has exact match OR CANMATCH/MATCHMORE & canmatch set with '/'--- %s\n", score->exten ? score->exten->exten : "NULL");
1928  return; /* the first match is all we need */
1929  }
1930  }
1931  } else if (strchr(p->x, *str)) {
1932  ast_debug(4, "Nothing strange about this match\n");
1935  }
1936  } else if (strchr(p->x, *str)) {
1937  ast_debug(4, "Nothing strange about this match\n");
1940  }
1941  }
1942  ast_debug(4, "return at end of func\n");
1943 }
1944 
1945 /* the algorithm for forming the extension pattern tree is also a bit simple; you
1946  * traverse all the extensions in a context, and for each char of the extension,
1947  * you see if it exists in the tree; if it doesn't, you add it at the appropriate
1948  * spot. What more can I say? At the end of each exten, you cap it off by adding the
1949  * address of the extension involved. Duplicate patterns will be complained about.
1950  *
1951  * Ideally, this would be done for each context after it is created and fully
1952  * filled. It could be done as a finishing step after extensions.conf or .ael is
1953  * loaded, or it could be done when the first search is encountered. It should only
1954  * have to be done once, until the next unload or reload.
1955  *
1956  * I guess forming this pattern tree would be analogous to compiling a regex. Except
1957  * that a regex only handles 1 pattern, really. This trie holds any number
1958  * of patterns. Well, really, it **could** be considered a single pattern,
1959  * where the "|" (or) operator is allowed, I guess, in a way, sort of...
1960  */
1961 
1962 static struct match_char *already_in_tree(struct match_char *current, char *pat, int is_pattern)
1963 {
1964  struct match_char *t;
1965 
1966  if (!current) {
1967  return 0;
1968  }
1969 
1970  for (t = current; t; t = t->alt_char) {
1971  if (is_pattern == t->is_pattern && !strcmp(pat, t->x)) {/* uh, we may want to sort exploded [] contents to make matching easy */
1972  return t;
1973  }
1974  }
1975 
1976  return 0;
1977 }
1978 
1979 /* The first arg is the location of the tree ptr, or the
1980  address of the next_char ptr in the node, so we can mess
1981  with it, if we need to insert at the beginning of the list */
1982 
1983 static void insert_in_next_chars_alt_char_list(struct match_char **parent_ptr, struct match_char *node)
1984 {
1985  struct match_char *curr, *lcurr;
1986 
1987  /* insert node into the tree at "current", so the alt_char list from current is
1988  sorted in increasing value as you go to the leaves */
1989  if (!(*parent_ptr)) {
1990  *parent_ptr = node;
1991  return;
1992  }
1993 
1994  if ((*parent_ptr)->specificity > node->specificity) {
1995  /* insert at head */
1996  node->alt_char = (*parent_ptr);
1997  *parent_ptr = node;
1998  return;
1999  }
2000 
2001  lcurr = *parent_ptr;
2002  for (curr = (*parent_ptr)->alt_char; curr; curr = curr->alt_char) {
2003  if (curr->specificity > node->specificity) {
2004  node->alt_char = curr;
2005  lcurr->alt_char = node;
2006  break;
2007  }
2008  lcurr = curr;
2009  }
2010 
2011  if (!curr) {
2012  lcurr->alt_char = node;
2013  }
2014 
2015 }
2016 
2018  /*! Pattern node specificity */
2019  int specif;
2020  /*! Pattern node match characters. */
2021  char buf[256];
2022 };
2023 
2024 static struct match_char *add_pattern_node(struct ast_context *con, struct match_char *current, const struct pattern_node *pattern, int is_pattern, int already, struct match_char **nextcharptr)
2025 {
2026  struct match_char *m;
2027 
2028  if (!(m = ast_calloc(1, sizeof(*m) + strlen(pattern->buf)))) {
2029  return NULL;
2030  }
2031 
2032  /* strcpy is safe here since we know its size and have allocated
2033  * just enough space for when we allocated m
2034  */
2035  strcpy(m->x, pattern->buf);
2036 
2037  /* the specificity scores are the same as used in the old
2038  pattern matcher. */
2039  m->is_pattern = is_pattern;
2040  if (pattern->specif == 1 && is_pattern && pattern->buf[0] == 'N') {
2041  m->specificity = 0x0832;
2042  } else if (pattern->specif == 1 && is_pattern && pattern->buf[0] == 'Z') {
2043  m->specificity = 0x0931;
2044  } else if (pattern->specif == 1 && is_pattern && pattern->buf[0] == 'X') {
2045  m->specificity = 0x0a30;
2046  } else if (pattern->specif == 1 && is_pattern && pattern->buf[0] == '.') {
2047  m->specificity = 0x18000;
2048  } else if (pattern->specif == 1 && is_pattern && pattern->buf[0] == '!') {
2049  m->specificity = 0x28000;
2050  } else {
2051  m->specificity = pattern->specif;
2052  }
2053 
2054  if (!con->pattern_tree) {
2056  } else {
2057  if (already) { /* switch to the new regime (traversing vs appending)*/
2058  insert_in_next_chars_alt_char_list(nextcharptr, m);
2059  } else {
2061  }
2062  }
2063 
2064  return m;
2065 }
2066 
2067 /*!
2068  * \internal
2069  * \brief Extract the next exten pattern node.
2070  *
2071  * \param node Pattern node to fill.
2072  * \param src Next source character to read.
2073  * \param pattern TRUE if the exten is a pattern.
2074  * \param extenbuf Original exten buffer to use in diagnostic messages.
2075  *
2076  * \retval Ptr to next extenbuf pos to read.
2077  */
2078 static const char *get_pattern_node(struct pattern_node *node, const char *src, int pattern, const char *extenbuf)
2079 {
2080 #define INC_DST_OVERFLOW_CHECK \
2081  do { \
2082  if (dst - node->buf < sizeof(node->buf) - 1) { \
2083  ++dst; \
2084  } else { \
2085  overflow = 1; \
2086  } \
2087  } while (0)
2088 
2089  node->specif = 0;
2090  node->buf[0] = '\0';
2091  while (*src) {
2092  if (*src == '[' && pattern) {
2093  char *dst = node->buf;
2094  const char *src_next;
2095  int length;
2096  int overflow = 0;
2097 
2098  /* get past the '[' */
2099  ++src;
2100  for (;;) {
2101  if (*src == '\\') {
2102  /* Escaped character. */
2103  ++src;
2104  if (*src == '[' || *src == '\\' || *src == '-' || *src == ']') {
2105  *dst = *src++;
2107  }
2108  } else if (*src == '-') {
2109  unsigned char first;
2110  unsigned char last;
2111 
2112  src_next = src;
2113  first = *(src_next - 1);
2114  last = *++src_next;
2115 
2116  if (last == '\\') {
2117  /* Escaped character. */
2118  last = *++src_next;
2119  }
2120 
2121  /* Possible char range. */
2122  if (node->buf[0] && last) {
2123  /* Expand the char range. */
2124  while (++first <= last) {
2125  *dst = first;
2127  }
2128  src = src_next + 1;
2129  } else {
2130  /*
2131  * There was no left or right char for the range.
2132  * It is just a '-'.
2133  */
2134  *dst = *src++;
2136  }
2137  } else if (*src == '\0') {
2139  "A matching ']' was not found for '[' in exten pattern '%s'\n",
2140  extenbuf);
2141  break;
2142  } else if (*src == ']') {
2143  ++src;
2144  break;
2145  } else {
2146  *dst = *src++;
2148  }
2149  }
2150  /* null terminate the exploded range */
2151  *dst = '\0';
2152 
2153  if (overflow) {
2155  "Expanded character set too large to deal with in exten pattern '%s'. Ignoring character set.\n",
2156  extenbuf);
2157  node->buf[0] = '\0';
2158  continue;
2159  }
2160 
2161  /* Sort the characters in character set. */
2162  length = strlen(node->buf);
2163  if (!length) {
2164  ast_log(LOG_WARNING, "Empty character set in exten pattern '%s'. Ignoring.\n",
2165  extenbuf);
2166  node->buf[0] = '\0';
2167  continue;
2168  }
2169  qsort(node->buf, length, 1, compare_char);
2170 
2171  /* Remove duplicate characters from character set. */
2172  dst = node->buf;
2173  src_next = node->buf;
2174  while (*src_next++) {
2175  if (*dst != *src_next) {
2176  *++dst = *src_next;
2177  }
2178  }
2179 
2180  length = strlen(node->buf);
2181  length <<= 8;
2182  node->specif = length | (unsigned char) node->buf[0];
2183  break;
2184  } else if (*src == '-') {
2185  /* Skip dashes in all extensions. */
2186  ++src;
2187  } else {
2188  if (*src == '\\') {
2189  /*
2190  * XXX The escape character here does not remove any special
2191  * meaning to characters except the '[', '\\', and '-'
2192  * characters since they are special only in this function.
2193  */
2194  node->buf[0] = *++src;
2195  if (!node->buf[0]) {
2196  break;
2197  }
2198  } else {
2199  node->buf[0] = *src;
2200  if (pattern) {
2201  /* make sure n,x,z patterns are canonicalized to N,X,Z */
2202  if (node->buf[0] == 'n') {
2203  node->buf[0] = 'N';
2204  } else if (node->buf[0] == 'x') {
2205  node->buf[0] = 'X';
2206  } else if (node->buf[0] == 'z') {
2207  node->buf[0] = 'Z';
2208  }
2209  }
2210  }
2211  node->buf[1] = '\0';
2212  node->specif = 1;
2213  ++src;
2214  break;
2215  }
2216  }
2217  return src;
2218 
2219 #undef INC_DST_OVERFLOW_CHECK
2220 }
2221 
2222 static struct match_char *add_exten_to_pattern_tree(struct ast_context *con, struct ast_exten *e1, int findonly)
2223 {
2224  struct match_char *m1 = NULL;
2225  struct match_char *m2 = NULL;
2226  struct match_char **m0;
2227  const char *pos;
2228  int already;
2229  int pattern = 0;
2230  int idx_cur;
2231  int idx_next;
2232  char extenbuf[512];
2233  struct pattern_node pat_node[2];
2234 
2235  if (e1->matchcid) {
2236  if (sizeof(extenbuf) < strlen(e1->exten) + strlen(e1->cidmatch) + 2) {
2238  "The pattern %s/%s is too big to deal with: it will be ignored! Disaster!\n",
2239  e1->exten, e1->cidmatch);
2240  return NULL;
2241  }
2242  sprintf(extenbuf, "%s/%s", e1->exten, e1->cidmatch);/* Safe. We just checked. */
2243  } else {
2244  ast_copy_string(extenbuf, e1->exten, sizeof(extenbuf));
2245  }
2246 
2247 #ifdef NEED_DEBUG
2248  ast_log(LOG_DEBUG, "Adding exten %s to tree\n", extenbuf);
2249 #endif
2250  m1 = con->pattern_tree; /* each pattern starts over at the root of the pattern tree */
2251  m0 = &con->pattern_tree;
2252  already = 1;
2253 
2254  pos = extenbuf;
2255  if (*pos == '_') {
2256  pattern = 1;
2257  ++pos;
2258  }
2259  idx_cur = 0;
2260  pos = get_pattern_node(&pat_node[idx_cur], pos, pattern, extenbuf);
2261  for (; pat_node[idx_cur].buf[0]; idx_cur = idx_next) {
2262  idx_next = (idx_cur + 1) % ARRAY_LEN(pat_node);
2263  pos = get_pattern_node(&pat_node[idx_next], pos, pattern, extenbuf);
2264 
2265  /* See about adding node to tree. */
2266  m2 = NULL;
2267  if (already && (m2 = already_in_tree(m1, pat_node[idx_cur].buf, pattern))
2268  && m2->next_char) {
2269  if (!pat_node[idx_next].buf[0]) {
2270  /*
2271  * This is the end of the pattern, but not the end of the tree.
2272  * Mark this node with the exten... a shorter pattern might win
2273  * if the longer one doesn't match.
2274  */
2275  if (findonly) {
2276  return m2;
2277  }
2278  if (m2->exten) {
2279  ast_log(LOG_WARNING, "Found duplicate exten. Had %s found %s\n",
2280  m2->deleted ? "(deleted/invalid)" : m2->exten->exten, e1->exten);
2281  }
2282  m2->exten = e1;
2283  m2->deleted = 0;
2284  }
2285  m1 = m2->next_char; /* m1 points to the node to compare against */
2286  m0 = &m2->next_char; /* m0 points to the ptr that points to m1 */
2287  } else { /* not already OR not m2 OR nor m2->next_char */
2288  if (m2) {
2289  if (findonly) {
2290  return m2;
2291  }
2292  m1 = m2; /* while m0 stays the same */
2293  } else {
2294  if (findonly) {
2295  return m1;
2296  }
2297  m1 = add_pattern_node(con, m1, &pat_node[idx_cur], pattern, already, m0);
2298  if (!m1) { /* m1 is the node just added */
2299  return NULL;
2300  }
2301  m0 = &m1->next_char;
2302  }
2303  if (!pat_node[idx_next].buf[0]) {
2304  if (m2 && m2->exten) {
2305  ast_log(LOG_WARNING, "Found duplicate exten. Had %s found %s\n",
2306  m2->deleted ? "(deleted/invalid)" : m2->exten->exten, e1->exten);
2307  }
2308  m1->deleted = 0;
2309  m1->exten = e1;
2310  }
2311 
2312  /* The 'already' variable is a mini-optimization designed to make it so that we
2313  * don't have to call already_in_tree when we know it will return false.
2314  */
2315  already = 0;
2316  }
2317  }
2318  return m1;
2319 }
2320 
2321 static void create_match_char_tree(struct ast_context *con)
2322 {
2323  struct ast_hashtab_iter *t1;
2324  struct ast_exten *e1;
2325 #ifdef NEED_DEBUG
2326  int biggest_bucket, resizes, numobjs, numbucks;
2327 
2328  ast_log(LOG_DEBUG,"Creating Extension Trie for context %s(%p)\n", con->name, con);
2329  ast_hashtab_get_stats(con->root_table, &biggest_bucket, &resizes, &numobjs, &numbucks);
2330  ast_log(LOG_DEBUG,"This tree has %d objects in %d bucket lists, longest list=%d objects, and has resized %d times\n",
2331  numobjs, numbucks, biggest_bucket, resizes);
2332 #endif
2334  while ((e1 = ast_hashtab_next(t1))) {
2335  if (e1->exten) {
2336  add_exten_to_pattern_tree(con, e1, 0);
2337  } else {
2338  ast_log(LOG_ERROR, "Attempt to create extension with no extension name.\n");
2339  }
2340  }
2342 }
2343 
2344 static void destroy_pattern_tree(struct match_char *pattern_tree) /* pattern tree is a simple binary tree, sort of, so the proper way to destroy it is... recursively! */
2345 {
2346  /* destroy all the alternates */
2347  if (pattern_tree->alt_char) {
2348  destroy_pattern_tree(pattern_tree->alt_char);
2349  pattern_tree->alt_char = 0;
2350  }
2351  /* destroy all the nexts */
2352  if (pattern_tree->next_char) {
2353  destroy_pattern_tree(pattern_tree->next_char);
2354  pattern_tree->next_char = 0;
2355  }
2356  pattern_tree->exten = 0; /* never hurts to make sure there's no pointers laying around */
2357  ast_free(pattern_tree);
2358 }
2359 
2360 /*!
2361  * \internal
2362  * \brief Get the length of the exten string.
2363  *
2364  * \param str Exten to get length.
2365  *
2366  * \retval strlen of exten.
2367  */
2368 static int ext_cmp_exten_strlen(const char *str)
2369 {
2370  int len;
2371 
2372  len = 0;
2373  for (;;) {
2374  /* Ignore '-' chars as eye candy fluff. */
2375  while (*str == '-') {
2376  ++str;
2377  }
2378  if (!*str) {
2379  break;
2380  }
2381  ++str;
2382  ++len;
2383  }
2384  return len;
2385 }
2386 
2387 /*!
2388  * \internal
2389  * \brief Partial comparison of non-pattern extens.
2390  *
2391  * \param left Exten to compare.
2392  * \param right Exten to compare. Also matches if this string ends first.
2393  *
2394  * \retval <0 if left < right
2395  * \retval =0 if left == right
2396  * \retval >0 if left > right
2397  */
2398 static int ext_cmp_exten_partial(const char *left, const char *right)
2399 {
2400  int cmp;
2401 
2402  for (;;) {
2403  /* Ignore '-' chars as eye candy fluff. */
2404  while (*left == '-') {
2405  ++left;
2406  }
2407  while (*right == '-') {
2408  ++right;
2409  }
2410 
2411  if (!*right) {
2412  /*
2413  * Right ended first for partial match or both ended at the same
2414  * time for a match.
2415  */
2416  cmp = 0;
2417  break;
2418  }
2419 
2420  cmp = *left - *right;
2421  if (cmp) {
2422  break;
2423  }
2424  ++left;
2425  ++right;
2426  }
2427  return cmp;
2428 }
2429 
2430 /*!
2431  * \internal
2432  * \brief Comparison of non-pattern extens.
2433  *
2434  * \param left Exten to compare.
2435  * \param right Exten to compare.
2436  *
2437  * \retval <0 if left < right
2438  * \retval =0 if left == right
2439  * \retval >0 if left > right
2440  */
2441 static int ext_cmp_exten(const char *left, const char *right)
2442 {
2443  int cmp;
2444 
2445  for (;;) {
2446  /* Ignore '-' chars as eye candy fluff. */
2447  while (*left == '-') {
2448  ++left;
2449  }
2450  while (*right == '-') {
2451  ++right;
2452  }
2453 
2454  cmp = *left - *right;
2455  if (cmp) {
2456  break;
2457  }
2458  if (!*left) {
2459  /*
2460  * Get here only if both strings ended at the same time. cmp
2461  * would be non-zero if only one string ended.
2462  */
2463  break;
2464  }
2465  ++left;
2466  ++right;
2467  }
2468  return cmp;
2469 }
2470 
2471 /*
2472  * Special characters used in patterns:
2473  * '_' underscore is the leading character of a pattern.
2474  * In other position it is treated as a regular char.
2475  * '-' The '-' is a separator and ignored. Why? So patterns like NXX-XXX-XXXX work.
2476  * . one or more of any character. Only allowed at the end of
2477  * a pattern.
2478  * ! zero or more of anything. Also impacts the result of CANMATCH
2479  * and MATCHMORE. Only allowed at the end of a pattern.
2480  * In the core routine, ! causes a match with a return code of 2.
2481  * In turn, depending on the search mode: (XXX check if it is implemented)
2482  * - E_MATCH retuns 1 (does match)
2483  * - E_MATCHMORE returns 0 (no match)
2484  * - E_CANMATCH returns 1 (does match)
2485  *
2486  * / should not appear as it is considered the separator of the CID info.
2487  * XXX at the moment we may stop on this char.
2488  *
2489  * X Z N match ranges 0-9, 1-9, 2-9 respectively.
2490  * [ denotes the start of a set of character. Everything inside
2491  * is considered literally. We can have ranges a-d and individual
2492  * characters. A '[' and '-' can be considered literally if they
2493  * are just before ']'.
2494  * XXX currently there is no way to specify ']' in a range, nor \ is
2495  * considered specially.
2496  *
2497  * When we compare a pattern with a specific extension, all characters in the extension
2498  * itself are considered literally.
2499  * XXX do we want to consider space as a separator as well ?
2500  * XXX do we want to consider the separators in non-patterns as well ?
2501  */
2502 
2503 /*!
2504  * \brief helper functions to sort extension patterns in the desired way,
2505  * so that more specific patterns appear first.
2506  *
2507  * \details
2508  * The function compares individual characters (or sets of), returning
2509  * an int where bits 0-7 are the ASCII code of the first char in the set,
2510  * bits 8-15 are the number of characters in the set, and bits 16-20 are
2511  * for special cases.
2512  * This way more specific patterns (smaller character sets) appear first.
2513  * Wildcards have a special value, so that we can directly compare them to
2514  * sets by subtracting the two values. In particular:
2515  * 0x001xx one character, character set starting with xx
2516  * 0x0yyxx yy characters, character set starting with xx
2517  * 0x18000 '.' (one or more of anything)
2518  * 0x28000 '!' (zero or more of anything)
2519  * 0x30000 NUL (end of string)
2520  * 0x40000 error in set.
2521  * The pointer to the string is advanced according to needs.
2522  * NOTES:
2523  * 1. the empty set is ignored.
2524  * 2. given that a full set has always 0 as the first element,
2525  * we could encode the special cases as 0xffXX where XX
2526  * is 1, 2, 3, 4 as used above.
2527  */
2528 static int ext_cmp_pattern_pos(const char **p, unsigned char *bitwise)
2529 {
2530 #define BITS_PER 8 /* Number of bits per unit (byte). */
2531  unsigned char c;
2532  unsigned char cmin;
2533  int count;
2534  const char *end;
2535 
2536  do {
2537  /* Get character and advance. (Ignore '-' chars as eye candy fluff.) */
2538  do {
2539  c = *(*p)++;
2540  } while (c == '-');
2541 
2542  /* always return unless we have a set of chars */
2543  switch (c) {
2544  default:
2545  /* ordinary character */
2546  bitwise[c / BITS_PER] = 1 << ((BITS_PER - 1) - (c % BITS_PER));
2547  return 0x0100 | c;
2548 
2549  case 'n':
2550  case 'N':
2551  /* 2..9 */
2552  bitwise[6] = 0x3f;
2553  bitwise[7] = 0xc0;
2554  return 0x0800 | '2';
2555 
2556  case 'x':
2557  case 'X':
2558  /* 0..9 */
2559  bitwise[6] = 0xff;
2560  bitwise[7] = 0xc0;
2561  return 0x0A00 | '0';
2562 
2563  case 'z':
2564  case 'Z':
2565  /* 1..9 */
2566  bitwise[6] = 0x7f;
2567  bitwise[7] = 0xc0;
2568  return 0x0900 | '1';
2569 
2570  case '.':
2571  /* wildcard */
2572  return 0x18000;
2573 
2574  case '!':
2575  /* earlymatch */
2576  return 0x28000; /* less specific than '.' */
2577 
2578  case '\0':
2579  /* empty string */
2580  *p = NULL;
2581  return 0x30000;
2582 
2583  case '[':
2584  /* char set */
2585  break;
2586  }
2587  /* locate end of set */
2588  end = strchr(*p, ']');
2589 
2590  if (!end) {
2591  ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n");
2592  return 0x40000; /* XXX make this entry go last... */
2593  }
2594 
2595  count = 0;
2596  cmin = 0xFF;
2597  for (; *p < end; ++*p) {
2598  unsigned char c1; /* first char in range */
2599  unsigned char c2; /* last char in range */
2600 
2601  c1 = (*p)[0];
2602  if (*p + 2 < end && (*p)[1] == '-') { /* this is a range */
2603  c2 = (*p)[2];
2604  *p += 2; /* skip a total of 3 chars */
2605  } else { /* individual character */
2606  c2 = c1;
2607  }
2608  if (c1 < cmin) {
2609  cmin = c1;
2610  }
2611  for (; c1 <= c2; ++c1) {
2612  unsigned char mask = 1 << ((BITS_PER - 1) - (c1 % BITS_PER));
2613 
2614  /*
2615  * Note: If two character sets score the same, the one with the
2616  * lowest ASCII values will compare as coming first. Must fill
2617  * in most significant bits for lower ASCII values to accomplish
2618  * the desired sort order.
2619  */
2620  if (!(bitwise[c1 / BITS_PER] & mask)) {
2621  /* Add the character to the set. */
2622  bitwise[c1 / BITS_PER] |= mask;
2623  count += 0x100;
2624  }
2625  }
2626  }
2627  ++*p;
2628  } while (!count);/* While the char set was empty. */
2629  return count | cmin;
2630 }
2631 
2632 /*!
2633  * \internal
2634  * \brief Comparison of exten patterns.
2635  *
2636  * \param left Pattern to compare.
2637  * \param right Pattern to compare.
2638  *
2639  * \retval <0 if left < right
2640  * \retval =0 if left == right
2641  * \retval >0 if left > right
2642  */
2643 static int ext_cmp_pattern(const char *left, const char *right)
2644 {
2645  int cmp;
2646  int left_pos;
2647  int right_pos;
2648 
2649  for (;;) {
2650  unsigned char left_bitwise[32] = { 0, };
2651  unsigned char right_bitwise[32] = { 0, };
2652 
2653  left_pos = ext_cmp_pattern_pos(&left, left_bitwise);
2654  right_pos = ext_cmp_pattern_pos(&right, right_bitwise);
2655  cmp = left_pos - right_pos;
2656  if (!cmp) {
2657  /*
2658  * Are the character sets different, even though they score the same?
2659  *
2660  * Note: Must swap left and right to get the sense of the
2661  * comparison correct. Otherwise, we would need to multiply by
2662  * -1 instead.
2663  */
2664  cmp = memcmp(right_bitwise, left_bitwise, ARRAY_LEN(left_bitwise));
2665  }
2666  if (cmp) {
2667  break;
2668  }
2669  if (!left) {
2670  /*
2671  * Get here only if both patterns ended at the same time. cmp
2672  * would be non-zero if only one pattern ended.
2673  */
2674  break;
2675  }
2676  }
2677  return cmp;
2678 }
2679 
2680 /*!
2681  * \internal
2682  * \brief Comparison of dialplan extens for sorting purposes.
2683  *
2684  * \param left Exten/pattern to compare.
2685  * \param right Exten/pattern to compare.
2686  *
2687  * \retval <0 if left < right
2688  * \retval =0 if left == right
2689  * \retval >0 if left > right
2690  */
2691 static int ext_cmp(const char *left, const char *right)
2692 {
2693  /* Make sure non-pattern extens come first. */
2694  if (left[0] != '_') {
2695  if (right[0] == '_') {
2696  return -1;
2697  }
2698  /* Compare two non-pattern extens. */
2699  return ext_cmp_exten(left, right);
2700  }
2701  if (right[0] != '_') {
2702  return 1;
2703  }
2704 
2705  /*
2706  * OK, we need full pattern sorting routine.
2707  *
2708  * Skip past the underscores
2709  */
2710  return ext_cmp_pattern(left + 1, right + 1);
2711 }
2712 
2713 int ast_extension_cmp(const char *a, const char *b)
2714 {
2715  int cmp;
2716 
2717  cmp = ext_cmp(a, b);
2718  if (cmp < 0) {
2719  return -1;
2720  }
2721  if (cmp > 0) {
2722  return 1;
2723  }
2724  return 0;
2725 }
2726 
2727 /*!
2728  * \internal
2729  * \brief used ast_extension_{match|close}
2730  * mode is as follows:
2731  * E_MATCH success only on exact match
2732  * E_MATCHMORE success only on partial match (i.e. leftover digits in pattern)
2733  * E_CANMATCH either of the above.
2734  * \retval 0 on no-match
2735  * \retval 1 on match
2736  * \retval 2 on early match.
2737  */
2738 
2739 static int _extension_match_core(const char *pattern, const char *data, enum ext_match_t mode)
2740 {
2741  mode &= E_MATCH_MASK; /* only consider the relevant bits */
2742 
2743 #ifdef NEED_DEBUG_HERE
2744  ast_log(LOG_NOTICE,"match core: pat: '%s', dat: '%s', mode=%d\n", pattern, data, (int)mode);
2745 #endif
2746 
2747  if (pattern[0] != '_') { /* not a pattern, try exact or partial match */
2748  int lp = ext_cmp_exten_strlen(pattern);
2749  int ld = ext_cmp_exten_strlen(data);
2750 
2751  if (lp < ld) { /* pattern too short, cannot match */
2752 #ifdef NEED_DEBUG_HERE
2753  ast_log(LOG_NOTICE,"return (0) - pattern too short, cannot match\n");
2754 #endif
2755  return 0;
2756  }
2757  /* depending on the mode, accept full or partial match or both */
2758  if (mode == E_MATCH) {
2759 #ifdef NEED_DEBUG_HERE
2760  ast_log(LOG_NOTICE,"return (!ext_cmp_exten(%s,%s) when mode== E_MATCH)\n", pattern, data);
2761 #endif
2762  return !ext_cmp_exten(pattern, data); /* 1 on match, 0 on fail */
2763  }
2764  if (ld == 0 || !ext_cmp_exten_partial(pattern, data)) { /* partial or full match */
2765 #ifdef NEED_DEBUG_HERE
2766  ast_log(LOG_NOTICE,"return (mode(%d) == E_MATCHMORE ? lp(%d) > ld(%d) : 1)\n", mode, lp, ld);
2767 #endif
2768  return (mode == E_MATCHMORE) ? lp > ld : 1; /* XXX should consider '!' and '/' ? */
2769  } else {
2770 #ifdef NEED_DEBUG_HERE
2771  ast_log(LOG_NOTICE,"return (0) when ld(%d) > 0 && pattern(%s) != data(%s)\n", ld, pattern, data);
2772 #endif
2773  return 0;
2774  }
2775  }
2776  if (mode == E_MATCH && data[0] == '_') {
2777  /*
2778  * XXX It is bad design that we don't know if we should be
2779  * comparing data and pattern as patterns or comparing data if
2780  * it conforms to pattern when the function is called. First,
2781  * assume they are both patterns. If they don't match then try
2782  * to see if data conforms to the given pattern.
2783  *
2784  * note: if this test is left out, then _x. will not match _x. !!!
2785  */
2786 #ifdef NEED_DEBUG_HERE
2787  ast_log(LOG_NOTICE, "Comparing as patterns first. pattern:%s data:%s\n", pattern, data);
2788 #endif
2789  if (!ext_cmp_pattern(pattern + 1, data + 1)) {
2790 #ifdef NEED_DEBUG_HERE
2791  ast_log(LOG_NOTICE,"return (1) - pattern matches pattern\n");
2792 #endif
2793  return 1;
2794  }
2795  }
2796 
2797  ++pattern; /* skip leading _ */
2798  /*
2799  * XXX below we stop at '/' which is a separator for the CID info. However we should
2800  * not store '/' in the pattern at all. When we insure it, we can remove the checks.
2801  */
2802  for (;;) {
2803  const char *end;
2804 
2805  /* Ignore '-' chars as eye candy fluff. */
2806  while (*data == '-') {
2807  ++data;
2808  }
2809  while (*pattern == '-') {
2810  ++pattern;
2811  }
2812  if (!*data || !*pattern || *pattern == '/') {
2813  break;
2814  }
2815 
2816  switch (*pattern) {
2817  case '[': /* a range */
2818  ++pattern;
2819  end = strchr(pattern, ']'); /* XXX should deal with escapes ? */
2820  if (!end) {
2821  ast_log(LOG_WARNING, "Wrong usage of [] in the extension\n");
2822  return 0; /* unconditional failure */
2823  }
2824  if (pattern == end) {
2825  /* Ignore empty character sets. */
2826  ++pattern;
2827  continue;
2828  }
2829  for (; pattern < end; ++pattern) {
2830  if (pattern+2 < end && pattern[1] == '-') { /* this is a range */
2831  if (*data >= pattern[0] && *data <= pattern[2])
2832  break; /* match found */
2833  else {
2834  pattern += 2; /* skip a total of 3 chars */
2835  continue;
2836  }
2837  } else if (*data == pattern[0])
2838  break; /* match found */
2839  }
2840  if (pattern >= end) {
2841 #ifdef NEED_DEBUG_HERE
2842  ast_log(LOG_NOTICE,"return (0) when pattern>=end\n");
2843 #endif
2844  return 0;
2845  }
2846  pattern = end; /* skip and continue */
2847  break;
2848  case 'n':
2849  case 'N':
2850  if (*data < '2' || *data > '9') {
2851 #ifdef NEED_DEBUG_HERE
2852  ast_log(LOG_NOTICE,"return (0) N is not matched\n");
2853 #endif
2854  return 0;
2855  }
2856  break;
2857  case 'x':
2858  case 'X':
2859  if (*data < '0' || *data > '9') {
2860 #ifdef NEED_DEBUG_HERE
2861  ast_log(LOG_NOTICE,"return (0) X is not matched\n");
2862 #endif
2863  return 0;
2864  }
2865  break;
2866  case 'z':
2867  case 'Z':
2868  if (*data < '1' || *data > '9') {
2869 #ifdef NEED_DEBUG_HERE
2870  ast_log(LOG_NOTICE,"return (0) Z is not matched\n");
2871 #endif
2872  return 0;
2873  }
2874  break;
2875  case '.': /* Must match, even with more digits */
2876 #ifdef NEED_DEBUG_HERE
2877  ast_log(LOG_NOTICE, "return (1) when '.' is matched\n");
2878 #endif
2879  return 1;
2880  case '!': /* Early match */
2881 #ifdef NEED_DEBUG_HERE
2882  ast_log(LOG_NOTICE, "return (2) when '!' is matched\n");
2883 #endif
2884  return 2;
2885  default:
2886  if (*data != *pattern) {
2887 #ifdef NEED_DEBUG_HERE
2888  ast_log(LOG_NOTICE, "return (0) when *data(%c) != *pattern(%c)\n", *data, *pattern);
2889 #endif
2890  return 0;
2891  }
2892  break;
2893  }
2894  ++data;
2895  ++pattern;
2896  }
2897  if (*data) /* data longer than pattern, no match */ {
2898 #ifdef NEED_DEBUG_HERE
2899  ast_log(LOG_NOTICE, "return (0) when data longer than pattern\n");
2900 #endif
2901  return 0;
2902  }
2903 
2904  /*
2905  * match so far, but ran off the end of data.
2906  * Depending on what is next, determine match or not.
2907  */
2908  if (*pattern == '\0' || *pattern == '/') { /* exact match */
2909 #ifdef NEED_DEBUG_HERE
2910  ast_log(LOG_NOTICE, "at end, return (%d) in 'exact match'\n", (mode==E_MATCHMORE) ? 0 : 1);
2911 #endif
2912  return (mode == E_MATCHMORE) ? 0 : 1; /* this is a failure for E_MATCHMORE */
2913  } else if (*pattern == '!') { /* early match */
2914 #ifdef NEED_DEBUG_HERE
2915  ast_log(LOG_NOTICE, "at end, return (2) when '!' is matched\n");
2916 #endif
2917  return 2;
2918  } else { /* partial match */
2919 #ifdef NEED_DEBUG_HERE
2920  ast_log(LOG_NOTICE, "at end, return (%d) which deps on E_MATCH\n", (mode == E_MATCH) ? 0 : 1);
2921 #endif
2922  return (mode == E_MATCH) ? 0 : 1; /* this is a failure for E_MATCH */
2923  }
2924 }
2925 
2926 /*
2927  * Wrapper around _extension_match_core() to do performance measurement
2928  * using the profiling code.
2929  */
2930 static int extension_match_core(const char *pattern, const char *data, enum ext_match_t mode)
2931 {
2932  int i;
2933  static int prof_id = -2; /* marker for 'unallocated' id */
2934  if (prof_id == -2) {
2935  prof_id = ast_add_profile("ext_match", 0);
2936  }
2937  ast_mark(prof_id, 1);
2938  i = _extension_match_core(ast_strlen_zero(pattern) ? "" : pattern, ast_strlen_zero(data) ? "" : data, mode);
2939  ast_mark(prof_id, 0);
2940  return i;
2941 }
2942 
2943 int ast_extension_match(const char *pattern, const char *data)
2944 {
2945  return extension_match_core(pattern, data, E_MATCH);
2946 }
2947 
2948 int ast_extension_close(const char *pattern, const char *data, int needmore)
2949 {
2950  if (needmore != E_MATCHMORE && needmore != E_CANMATCH)
2951  ast_log(LOG_WARNING, "invalid argument %d\n", needmore);
2952  return extension_match_core(pattern, data, needmore);
2953 }
2954 
2955 struct fake_context /* this struct is purely for matching in the hashtab */
2956 {
2958  struct ast_exten *root;
2964  const char *registrar;
2967  ast_mutex_t macrolock;
2968  char name[256];
2969 };
2970 
2971 struct ast_context *ast_context_find(const char *name)
2972 {
2973  struct ast_context *tmp;
2974  struct fake_context item;
2975 
2976  if (!name) {
2977  return NULL;
2978  }
2980  if (contexts_table) {
2981  ast_copy_string(item.name, name, sizeof(item.name));
2982  tmp = ast_hashtab_lookup(contexts_table, &item);
2983  } else {
2984  tmp = NULL;
2985  while ((tmp = ast_walk_contexts(tmp))) {
2986  if (!strcasecmp(name, tmp->name)) {
2987  break;
2988  }
2989  }
2990  }
2992  return tmp;
2993 }
2994 
2995 #define STATUS_NO_CONTEXT 1
2996 #define STATUS_NO_EXTENSION 2
2997 #define STATUS_NO_PRIORITY 3
2998 #define STATUS_NO_LABEL 4
2999 #define STATUS_SUCCESS 5
3000 
3001 static int matchcid(const char *cidpattern, const char *callerid)
3002 {
3003  /* If the Caller*ID pattern is empty, then we're matching NO Caller*ID, so
3004  failing to get a number should count as a match, otherwise not */
3005 
3006  if (ast_strlen_zero(callerid)) {
3007  return ast_strlen_zero(cidpattern) ? 1 : 0;
3008  }
3009 
3010  return ast_extension_match(cidpattern, callerid);
3011 }
3012 
3014  struct ast_context *bypass, struct pbx_find_info *q,
3015  const char *context, const char *exten, int priority,
3016  const char *label, const char *callerid, enum ext_match_t action)
3017 {
3018  int x, res;
3019  struct ast_context *tmp = NULL;
3020  struct ast_exten *e = NULL, *eroot = NULL;
3021  struct ast_include *i = NULL;
3022  struct ast_sw *sw = NULL;
3023  struct ast_exten pattern = {NULL, };
3024  struct scoreboard score = {0, };
3025  struct ast_str *tmpdata = NULL;
3026 
3027  pattern.label = label;
3028  pattern.priority = priority;
3029 #ifdef NEED_DEBUG_HERE
3030  ast_log(LOG_NOTICE, "Looking for cont/ext/prio/label/action = %s/%s/%d/%s/%d\n", context, exten, priority, label, (int) action);
3031 #endif
3032 
3033  /* Initialize status if appropriate */
3034  if (q->stacklen == 0) {
3036  q->swo = NULL;
3037  q->data = NULL;
3038  q->foundcontext = NULL;
3039  } else if (q->stacklen >= AST_PBX_MAX_STACK) {
3040  ast_log(LOG_WARNING, "Maximum PBX stack exceeded\n");
3041  return NULL;
3042  }
3043 
3044  /* Check first to see if we've already been checked */
3045  for (x = 0; x < q->stacklen; x++) {
3046  if (!strcasecmp(q->incstack[x], context))
3047  return NULL;
3048  }
3049 
3050  if (bypass) { /* bypass means we only look there */
3051  tmp = bypass;
3052  } else { /* look in contexts */
3053  tmp = find_context(context);
3054  if (!tmp) {
3055  return NULL;
3056  }
3057  }
3058 
3059  if (q->status < STATUS_NO_EXTENSION)
3061 
3062  /* Do a search for matching extension */
3063 
3064  eroot = NULL;
3065  score.total_specificity = 0;
3066  score.exten = 0;
3067  score.total_length = 0;
3068  if (!tmp->pattern_tree && tmp->root_table) {
3070 #ifdef NEED_DEBUG
3071  ast_log(LOG_DEBUG, "Tree Created in context %s:\n", context);
3072  log_match_char_tree(tmp->pattern_tree," ");
3073 #endif
3074  }
3075 #ifdef NEED_DEBUG
3076  ast_log(LOG_NOTICE, "The Trie we are searching in:\n");
3077  log_match_char_tree(tmp->pattern_tree, ":: ");
3078 #endif
3079 
3080  do {
3082  char *osw = ast_strdupa(overrideswitch), *name;
3083  struct ast_switch *asw;
3084  ast_switch_f *aswf = NULL;
3085  char *datap;
3086  int eval = 0;
3087 
3088  name = strsep(&osw, "/");
3089  asw = pbx_findswitch(name);
3090 
3091  if (!asw) {
3092  ast_log(LOG_WARNING, "No such switch '%s'\n", name);
3093  break;
3094  }
3095 
3096  if (osw && strchr(osw, '$')) {
3097  eval = 1;
3098  }
3099 
3100  if (eval && !(tmpdata = ast_str_thread_get(&switch_data, 512))) {
3101  ast_log(LOG_WARNING, "Can't evaluate overrideswitch?!\n");
3102  break;
3103  } else if (eval) {
3104  /* Substitute variables now */
3105  pbx_substitute_variables_helper(chan, osw, ast_str_buffer(tmpdata), ast_str_size(tmpdata));
3106  datap = ast_str_buffer(tmpdata);
3107  } else {
3108  datap = osw;
3109  }
3110 
3111  /* equivalent of extension_match_core() at the switch level */
3112  if (action == E_CANMATCH)
3113  aswf = asw->canmatch;
3114  else if (action == E_MATCHMORE)
3115  aswf = asw->matchmore;
3116  else /* action == E_MATCH */
3117  aswf = asw->exists;
3118  if (!aswf) {
3119  res = 0;
3120  } else {
3121  if (chan) {
3122  ast_autoservice_start(chan);
3123  }
3124  res = aswf(chan, context, exten, priority, callerid, datap);
3125  if (chan) {
3126  ast_autoservice_stop(chan);
3127  }
3128  }
3129  if (res) { /* Got a match */
3130  q->swo = asw;
3131  q->data = datap;
3132  q->foundcontext = context;
3133  /* XXX keep status = STATUS_NO_CONTEXT ? */
3134  return NULL;
3135  }
3136  }
3137  } while (0);
3138 
3139  if (extenpatternmatchnew) {
3140  new_find_extension(exten, &score, tmp->pattern_tree, 0, 0, callerid, label, action);
3141  eroot = score.exten;
3142 
3143  if (score.last_char == '!' && action == E_MATCHMORE) {
3144  /* We match an extension ending in '!'.
3145  * The decision in this case is final and is NULL (no match).
3146  */
3147 #ifdef NEED_DEBUG_HERE
3148  ast_log(LOG_NOTICE,"Returning MATCHMORE NULL with exclamation point.\n");
3149 #endif
3150  return NULL;
3151  }
3152 
3153  if (!eroot && (action == E_CANMATCH || action == E_MATCHMORE) && score.canmatch_exten) {
3154  q->status = STATUS_SUCCESS;
3155 #ifdef NEED_DEBUG_HERE
3156  ast_log(LOG_NOTICE,"Returning CANMATCH exten %s\n", score.canmatch_exten->exten);
3157 #endif
3158  return score.canmatch_exten;
3159  }
3160 
3161  if ((action == E_MATCHMORE || action == E_CANMATCH) && eroot) {
3162  if (score.node) {
3163  struct ast_exten *z = trie_find_next_match(score.node);
3164  if (z) {
3165 #ifdef NEED_DEBUG_HERE
3166  ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten %s\n", z->exten);
3167 #endif
3168  } else {
3169  if (score.canmatch_exten) {
3170 #ifdef NEED_DEBUG_HERE
3171  ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE canmatchmatch exten %s(%p)\n", score.canmatch_exten->exten, score.canmatch_exten);
3172 #endif
3173  return score.canmatch_exten;
3174  } else {
3175 #ifdef NEED_DEBUG_HERE
3176  ast_log(LOG_NOTICE,"Returning CANMATCH/MATCHMORE next_match exten NULL\n");
3177 #endif
3178  }
3179  }
3180  return z;
3181  }
3182 #ifdef NEED_DEBUG_HERE
3183  ast_log(LOG_NOTICE, "Returning CANMATCH/MATCHMORE NULL (no next_match)\n");
3184 #endif
3185  return NULL; /* according to the code, complete matches are null matches in MATCHMORE mode */
3186  }
3187 
3188  if (eroot) {
3189  /* found entry, now look for the right priority */
3190  if (q->status < STATUS_NO_PRIORITY)
3192  e = NULL;
3193  if (action == E_FINDLABEL && label ) {
3194  if (q->status < STATUS_NO_LABEL)
3195  q->status = STATUS_NO_LABEL;
3196  e = ast_hashtab_lookup(eroot->peer_label_table, &pattern);
3197  } else {
3198  e = ast_hashtab_lookup(eroot->peer_table, &pattern);
3199  }
3200  if (e) { /* found a valid match */
3201  q->status = STATUS_SUCCESS;
3202  q->foundcontext = context;
3203 #ifdef NEED_DEBUG_HERE
3204  ast_log(LOG_NOTICE,"Returning complete match of exten %s\n", e->exten);
3205 #endif
3206  return e;
3207  }
3208  }
3209  } else { /* the old/current default exten pattern match algorithm */
3210 
3211  /* scan the list trying to match extension and CID */
3212  eroot = NULL;
3213  while ( (eroot = ast_walk_context_extensions(tmp, eroot)) ) {
3214  int match = extension_match_core(eroot->exten, exten, action);
3215  /* 0 on fail, 1 on match, 2 on earlymatch */
3216 
3217  if (!match || (eroot->matchcid && !matchcid(eroot->cidmatch, callerid)))
3218  continue; /* keep trying */
3219  if (match == 2 && action == E_MATCHMORE) {
3220  /* We match an extension ending in '!'.
3221  * The decision in this case is final and is NULL (no match).
3222  */
3223  return NULL;
3224  }
3225  /* found entry, now look for the right priority */
3226  if (q->status < STATUS_NO_PRIORITY)
3228  e = NULL;
3229  if (action == E_FINDLABEL && label ) {
3230  if (q->status < STATUS_NO_LABEL)
3231  q->status = STATUS_NO_LABEL;
3232  e = ast_hashtab_lookup(eroot->peer_label_table, &pattern);
3233  } else {
3234  e = ast_hashtab_lookup(eroot->peer_table, &pattern);
3235  }
3236  if (e) { /* found a valid match */
3237  q->status = STATUS_SUCCESS;
3238  q->foundcontext = context;
3239  return e;
3240  }
3241  }
3242  }
3243 
3244  /* Check alternative switches */
3245  AST_LIST_TRAVERSE(&tmp->alts, sw, list) {
3246  struct ast_switch *asw = pbx_findswitch(sw->name);
3247  ast_switch_f *aswf = NULL;
3248  char *datap;
3249 
3250  if (!asw) {
3251  ast_log(LOG_WARNING, "No such switch '%s'\n", sw->name);
3252  continue;
3253  }
3254 
3255  /* Substitute variables now */
3256  if (sw->eval) {
3257  if (!(tmpdata = ast_str_thread_get(&switch_data, 512))) {
3258  ast_log(LOG_WARNING, "Can't evaluate switch?!\n");
3259  continue;
3260  }
3261  pbx_substitute_variables_helper(chan, sw->data, ast_str_buffer(tmpdata), ast_str_size(tmpdata));
3262  }
3263 
3264  /* equivalent of extension_match_core() at the switch level */
3265  if (action == E_CANMATCH)
3266  aswf = asw->canmatch;
3267  else if (action == E_MATCHMORE)
3268  aswf = asw->matchmore;
3269  else /* action == E_MATCH */
3270  aswf = asw->exists;
3271  datap = sw->eval ? ast_str_buffer(tmpdata) : sw->data;
3272  if (!aswf)
3273  res = 0;
3274  else {
3275  if (chan)
3276  ast_autoservice_start(chan);
3277  res = aswf(chan, context, exten, priority, callerid, datap);
3278  if (chan)
3279  ast_autoservice_stop(chan);
3280  }
3281  if (res) { /* Got a match */
3282  q->swo = asw;
3283  q->data = datap;
3284  q->foundcontext = context;
3285  /* XXX keep status = STATUS_NO_CONTEXT ? */
3286  return NULL;
3287  }
3288  }
3289  q->incstack[q->stacklen++] = tmp->name; /* Setup the stack */
3290  /* Now try any includes we have in this context */
3291  for (i = tmp->includes; i; i = i->next) {
3292  if (include_valid(i)) {
3293  if ((e = pbx_find_extension(chan, bypass, q, i->rname, exten, priority, label, callerid, action))) {
3294 #ifdef NEED_DEBUG_HERE
3295  ast_log(LOG_NOTICE,"Returning recursive match of %s\n", e->exten);
3296 #endif
3297  return e;
3298  }
3299  if (q->swo)
3300  return NULL;
3301  }
3302  }
3303  return NULL;
3304 }
3305 
3306 /*!
3307  * \brief extract offset:length from variable name.
3308  * \return 1 if there is a offset:length part, which is
3309  * trimmed off (values go into variables)
3310  */
3311 static int parse_variable_name(char *var, int *offset, int *length, int *isfunc)
3312 {
3313  int parens = 0;
3314 
3315  *offset = 0;
3316  *length = INT_MAX;
3317  *isfunc = 0;
3318  for (; *var; var++) {
3319  if (*var == '(') {
3320  (*isfunc)++;
3321  parens++;
3322  } else if (*var == ')') {
3323  parens--;
3324  } else if (*var == ':' && parens == 0) {
3325  *var++ = '\0';
3326  sscanf(var, "%30d:%30d", offset, length);
3327  return 1; /* offset:length valid */
3328  }
3329  }
3330  return 0;
3331 }
3332 
3333 /*!
3334  *\brief takes a substring. It is ok to call with value == workspace.
3335  * \param value
3336  * \param offset < 0 means start from the end of the string and set the beginning
3337  * to be that many characters back.
3338  * \param length is the length of the substring, a value less than 0 means to leave
3339  * that many off the end.
3340  * \param workspace
3341  * \param workspace_len
3342  * Always return a copy in workspace.
3343  */
3344 static char *substring(const char *value, int offset, int length, char *workspace, size_t workspace_len)
3345 {
3346  char *ret = workspace;
3347  int lr; /* length of the input string after the copy */
3348 
3349  ast_copy_string(workspace, value, workspace_len); /* always make a copy */
3350 
3351  lr = strlen(ret); /* compute length after copy, so we never go out of the workspace */
3352 
3353  /* Quick check if no need to do anything */
3354  if (offset == 0 && length >= lr) /* take the whole string */
3355  return ret;
3356 
3357  if (offset < 0) { /* translate negative offset into positive ones */
3358  offset = lr + offset;
3359  if (offset < 0) /* If the negative offset was greater than the length of the string, just start at the beginning */
3360  offset = 0;
3361  }
3362 
3363  /* too large offset result in empty string so we know what to return */
3364  if (offset >= lr)
3365  return ret + lr; /* the final '\0' */
3366 
3367  ret += offset; /* move to the start position */
3368  if (length >= 0 && length < lr - offset) /* truncate if necessary */
3369  ret[length] = '\0';
3370  else if (length < 0) {
3371  if (lr > offset - length) /* After we remove from the front and from the rear, is there anything left? */
3372  ret[lr + length - offset] = '\0';
3373  else
3374  ret[0] = '\0';
3375  }
3376 
3377  return ret;
3378 }
3379 
3380 static const char *ast_str_substring(struct ast_str *value, int offset, int length)
3381 {
3382  int lr; /* length of the input string after the copy */
3383 
3384  lr = ast_str_strlen(value); /* compute length after copy, so we never go out of the workspace */
3385 
3386  /* Quick check if no need to do anything */
3387  if (offset == 0 && length >= lr) /* take the whole string */
3388  return ast_str_buffer(value);
3389 
3390  if (offset < 0) { /* translate negative offset into positive ones */
3391  offset = lr + offset;
3392  if (offset < 0) /* If the negative offset was greater than the length of the string, just start at the beginning */
3393  offset = 0;
3394  }
3395 
3396  /* too large offset result in empty string so we know what to return */
3397  if (offset >= lr) {
3398  ast_str_reset(value);
3399  return ast_str_buffer(value);
3400  }
3401 
3402  if (offset > 0) {
3403  /* Go ahead and chop off the beginning */
3404  memmove(ast_str_buffer(value), ast_str_buffer(value) + offset, ast_str_strlen(value) - offset + 1);
3405  lr -= offset;
3406  }
3407 
3408  if (length >= 0 && length < lr) { /* truncate if necessary */
3409  char *tmp = ast_str_buffer(value);
3410  tmp[length] = '\0';
3411  ast_str_update(value);
3412  } else if (length < 0) {
3413  if (lr > -length) { /* After we remove from the front and from the rear, is there anything left? */
3414  char *tmp = ast_str_buffer(value);
3415  tmp[lr + length] = '\0';
3416  ast_str_update(value);
3417  } else {
3418  ast_str_reset(value);
3419  }
3420  } else {
3421  /* Nothing to do, but update the buffer length */
3422  ast_str_update(value);
3423  }
3424 
3425  return ast_str_buffer(value);
3426 }
3427 
3428 /*! \brief Support for Asterisk built-in variables in the dialplan
3429 
3430 \note See also
3431  - \ref AstVar Channel variables
3432  - \ref AstCauses The HANGUPCAUSE variable
3433  */
3434 void pbx_retrieve_variable(struct ast_channel *c, const char *var, char **ret, char *workspace, int workspacelen, struct varshead *headp)
3435 {
3436  struct ast_str *str = ast_str_create(16);
3437  const char *cret;
3438 
3439  cret = ast_str_retrieve_variable(&str, 0, c, headp, var);
3440  ast_copy_string(workspace, ast_str_buffer(str), workspacelen);
3441  *ret = cret ? workspace : NULL;
3442  ast_free(str);
3443 }
3444 
3445 const char *ast_str_retrieve_variable(struct ast_str **str, ssize_t maxlen, struct ast_channel *c, struct varshead *headp, const char *var)
3446 {
3447  const char not_found = '\0';
3448  char *tmpvar;
3449  const char *ret;
3450  const char *s; /* the result */
3451  int offset, length;
3452  int i, need_substring;
3453  struct varshead *places[2] = { headp, &globals }; /* list of places where we may look */
3454  char workspace[20];
3455 
3456  if (c) {
3457  ast_channel_lock(c);
3458  places[0] = &c->varshead;
3459  }
3460  /*
3461  * Make a copy of var because parse_variable_name() modifies the string.
3462  * Then if called directly, we might need to run substring() on the result;
3463  * remember this for later in 'need_substring', 'offset' and 'length'
3464  */
3465  tmpvar = ast_strdupa(var); /* parse_variable_name modifies the string */
3466  need_substring = parse_variable_name(tmpvar, &offset, &length, &i /* ignored */);
3467 
3468  /*
3469  * Look first into predefined variables, then into variable lists.
3470  * Variable 's' points to the result, according to the following rules:
3471  * s == &not_found (set at the beginning) means that we did not find a
3472  * matching variable and need to look into more places.
3473  * If s != &not_found, s is a valid result string as follows:
3474  * s = NULL if the variable does not have a value;
3475  * you typically do this when looking for an unset predefined variable.
3476  * s = workspace if the result has been assembled there;
3477  * typically done when the result is built e.g. with an snprintf(),
3478  * so we don't need to do an additional copy.
3479  * s != workspace in case we have a string, that needs to be copied
3480  * (the ast_copy_string is done once for all at the end).
3481  * Typically done when the result is already available in some string.
3482  */
3483  s = &not_found; /* default value */
3484  if (c) { /* This group requires a valid channel */
3485  /* Names with common parts are looked up a piece at a time using strncmp. */
3486  if (!strncmp(var, "CALL", 4)) {
3487  if (!strncmp(var + 4, "ING", 3)) {
3488  if (!strcmp(var + 7, "PRES")) { /* CALLINGPRES */
3489  ast_str_set(str, maxlen, "%d",
3491  s = ast_str_buffer(*str);
3492  } else if (!strcmp(var + 7, "ANI2")) { /* CALLINGANI2 */
3493  ast_str_set(str, maxlen, "%d", c->caller.ani2);
3494  s = ast_str_buffer(*str);
3495  } else if (!strcmp(var + 7, "TON")) { /* CALLINGTON */
3496  ast_str_set(str, maxlen, "%d", c->caller.id.number.plan);
3497  s = ast_str_buffer(*str);
3498  } else if (!strcmp(var + 7, "TNS")) { /* CALLINGTNS */
3499  ast_str_set(str, maxlen, "%d", c->dialed.transit_network_select);
3500  s = ast_str_buffer(*str);
3501  }
3502  }
3503  } else if (!strcmp(var, "HINT")) {
3504  s = ast_str_get_hint(str, maxlen, NULL, 0, c, c->context, c->exten) ? ast_str_buffer(*str) : NULL;
3505  } else if (!strcmp(var, "HINTNAME")) {
3506  s = ast_str_get_hint(NULL, 0, str, maxlen, c, c->context, c->exten) ? ast_str_buffer(*str) : NULL;
3507  } else if (!strcmp(var, "EXTEN")) {
3508  s = c->exten;
3509  } else if (!strcmp(var, "CONTEXT")) {
3510  s = c->context;
3511  } else if (!strcmp(var, "PRIORITY")) {
3512  ast_str_set(str, maxlen, "%d", c->priority);
3513  s = ast_str_buffer(*str);
3514  } else if (!strcmp(var, "CHANNEL")) {
3515  s = c->name;
3516  } else if (!strcmp(var, "UNIQUEID")) {
3517  s = c->uniqueid;
3518  } else if (!strcmp(var, "HANGUPCAUSE")) {
3519  ast_str_set(str, maxlen, "%d", c->hangupcause);
3520  s = ast_str_buffer(*str);
3521  }
3522  }
3523  if (s == &not_found) { /* look for more */
3524  if (!strcmp(var, "EPOCH")) {
3525  ast_str_set(str, maxlen, "%d", (int) time(NULL));
3526  s = ast_str_buffer(*str);
3527  } else if (!strcmp(var, "SYSTEMNAME")) {
3529  } else if (!strcmp(var, "ENTITYID")) {
3530  ast_eid_to_str(workspace, sizeof(workspace), &ast_eid_default);
3531  s = workspace;
3532  }
3533  }
3534  /* if not found, look into chanvars or global vars */
3535  for (i = 0; s == &not_found && i < ARRAY_LEN(places); i++) {
3536  struct ast_var_t *variables;
3537  if (!places[i])
3538  continue;
3539  if (places[i] == &globals)
3541  AST_LIST_TRAVERSE(places[i], variables, entries) {
3542  if (!strcasecmp(ast_var_name(variables), var)) {
3543  s = ast_var_value(variables);
3544  break;
3545  }
3546  }
3547  if (places[i] == &globals)
3549  }
3550  if (s == &not_found || s == NULL) {
3551  ast_debug(5, "Result of '%s' is NULL\n", var);
3552  ret = NULL;
3553  } else {
3554  ast_debug(5, "Result of '%s' is '%s'\n", var, s);
3555  if (s != ast_str_buffer(*str)) {
3556  ast_str_set(str, maxlen, "%s", s);
3557  }
3558  ret = ast_str_buffer(*str);
3559  if (need_substring) {
3560  ret = ast_str_substring(*str, offset, length);
3561  ast_debug(2, "Final result of '%s' is '%s'\n", var, ret);
3562  }
3563  }
3564 
3565  if (c) {
3566  ast_channel_unlock(c);
3567  }
3568  return ret;
3569 }
3570 
3571 static void exception_store_free(void *data)
3572 {
3573  struct pbx_exception *exception = data;
3574  ast_string_field_free_memory(exception);
3575  ast_free(exception);
3576 }
3577 
3579  .type = "EXCEPTION",
3580  .destroy = exception_store_free,
3581 };
3582 
3583 /*!
3584  * \internal
3585  * \brief Set the PBX to execute the exception extension.
3586  *
3587  * \param chan Channel to raise the exception on.
3588  * \param reason Reason exception is raised.
3589  * \param priority Dialplan priority to set.
3590  *
3591  * \retval 0 on success.
3592  * \retval -1 on error.
3593  */
3594 static int raise_exception(struct ast_channel *chan, const char *reason, int priority)
3595 {
3597  struct pbx_exception *exception = NULL;
3598 
3599  if (!ds) {
3601  if (!ds)
3602  return -1;
3603  if (!(exception = ast_calloc_with_stringfields(1, struct pbx_exception, 128))) {
3604  ast_datastore_free(ds);
3605  return -1;
3606  }
3607  ds->data = exception;
3608  ast_channel_datastore_add(chan, ds);
3609  } else
3610  exception = ds->data;
3611 
3612  ast_string_field_set(exception, reason, reason);
3613  ast_string_field_set(exception, context, chan->context);
3614  ast_string_field_set(exception, exten, chan->exten);
3615  exception->priority = chan->priority;
3616  set_ext_pri(chan, "e", priority);
3617  return 0;
3618 }
3619 
3620 int pbx_builtin_raise_exception(struct ast_channel *chan, const char *reason)
3621 {
3622  /* Priority will become 1, next time through the AUTOLOOP */
3623  return raise_exception(chan, reason, 0);
3624 }
3625 
3626 static int acf_exception_read(struct ast_channel *chan, const char *name, char *data, char *buf, size_t buflen)
3627 {
3629  struct pbx_exception *exception = NULL;
3630  if (!ds || !ds->data)
3631  return -1;
3632  exception = ds->data;
3633  if (!strcasecmp(data, "REASON"))
3634  ast_copy_string(buf, exception->reason, buflen);
3635  else if (!strcasecmp(data, "CONTEXT"))
3636  ast_copy_string(buf, exception->context, buflen);
3637  else if (!strncasecmp(data, "EXTEN", 5))
3638  ast_copy_string(buf, exception->exten, buflen);
3639  else if (!strcasecmp(data, "PRIORITY"))
3640  snprintf(buf, buflen, "%d", exception->priority);
3641  else
3642  return -1;
3643  return 0;
3644 }
3645 
3647  .name = "EXCEPTION",
3648  .read = acf_exception_read,
3649 };
3650 
3651 static char *handle_show_functions(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
3652 {
3653  struct ast_custom_function *acf;
3654  int count_acf = 0;
3655  int like = 0;
3656 
3657  switch (cmd) {
3658  case CLI_INIT:
3659  e->command = "core show functions [like]";
3660  e->usage =
3661  "Usage: core show functions [like <text>]\n"
3662  " List builtin functions, optionally only those matching a given string\n";
3663  return NULL;
3664  case CLI_GENERATE:
3665  return NULL;
3666  }
3667 
3668  if (a->argc == 5 && (!strcmp(a->argv[3], "like")) ) {
3669  like = 1;
3670  } else if (a->argc != 3) {
3671  return CLI_SHOWUSAGE;
3672  }
3673 
3674  ast_cli(a->fd, "%s Custom Functions:\n--------------------------------------------------------------------------------\n", like ? "Matching" : "Installed");
3675 
3677  AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) {
3678  if (!like || strstr(acf->name, a->argv[4])) {
3679  count_acf++;
3680  ast_cli(a->fd, "%-20.20s %-35.35s %s\n",
3681  S_OR(acf->name, ""),
3682  S_OR(acf->syntax, ""),
3683  S_OR(acf->synopsis, ""));
3684  }
3685  }
3687 
3688  ast_cli(a->fd, "%d %scustom functions installed.\n", count_acf, like ? "matching " : "");
3689 
3690  return CLI_SUCCESS;
3691 }
3692 
3693 static char *handle_show_function(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
3694 {
3695  struct ast_custom_function *acf;
3696  /* Maximum number of characters added by terminal coloring is 22 */
3697  char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40], argtitle[40], seealsotitle[40];
3698  char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL, *seealso = NULL;
3699  char stxtitle[40], *syntax = NULL, *arguments = NULL;
3700  int syntax_size, description_size, synopsis_size, arguments_size, seealso_size;
3701  char *ret = NULL;
3702  int which = 0;
3703  int wordlen;
3704 
3705  switch (cmd) {
3706  case CLI_INIT:
3707  e->command = "core show function";
3708  e->usage =
3709  "Usage: core show function <function>\n"
3710  " Describe a particular dialplan function.\n";
3711  return NULL;
3712  case CLI_GENERATE:
3713  wordlen = strlen(a->word);
3714  /* case-insensitive for convenience in this 'complete' function */
3716  AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) {
3717  if (!strncasecmp(a->word, acf->name, wordlen) && ++which > a->n) {
3718  ret = ast_strdup(acf->name);
3719  break;
3720  }
3721  }
3723 
3724  return ret;
3725  }
3726 
3727  if (a->argc < 4) {
3728  return CLI_SHOWUSAGE;
3729  }
3730 
3731  if (!(acf = ast_custom_function_find(a->argv[3]))) {
3732  ast_cli(a->fd, "No function by that name registered.\n");
3733  return CLI_FAILURE;
3734  }
3735 
3736  syntax_size = strlen(S_OR(acf->syntax, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
3737  if (!(syntax = ast_malloc(syntax_size))) {
3738  ast_cli(a->fd, "Memory allocation failure!\n");
3739  return CLI_FAILURE;
3740  }
3741 
3742  snprintf(info, sizeof(info), "\n -= Info about function '%s' =- \n\n", acf->name);
3743  term_color(infotitle, info, COLOR_MAGENTA, 0, sizeof(infotitle));
3744  term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40);
3745  term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40);
3746  term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, 40);
3747  term_color(argtitle, "[Arguments]\n", COLOR_MAGENTA, 0, 40);
3748  term_color(seealsotitle, "[See Also]\n", COLOR_MAGENTA, 0, 40);
3749  term_color(syntax, S_OR(acf->syntax, "Not available"), COLOR_CYAN, 0, syntax_size);
3750 #ifdef AST_XML_DOCS
3751  if (acf->docsrc == AST_XML_DOC) {
3752  arguments = ast_xmldoc_printable(S_OR(acf->arguments, "Not available"), 1);
3753  synopsis = ast_xmldoc_printable(S_OR(acf->synopsis, "Not available"), 1);
3754  description = ast_xmldoc_printable(S_OR(acf->desc, "Not available"), 1);
3755  seealso = ast_xmldoc_printable(S_OR(acf->seealso, "Not available"), 1);
3756  } else
3757 #endif
3758  {
3759  synopsis_size = strlen(S_OR(acf->synopsis, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
3760  synopsis = ast_malloc(synopsis_size);
3761 
3762  description_size = strlen(S_OR(acf->desc, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
3763  description = ast_malloc(description_size);
3764 
3765  arguments_size = strlen(S_OR(acf->arguments, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
3766  arguments = ast_malloc(arguments_size);
3767 
3768  seealso_size = strlen(S_OR(acf->seealso, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
3769  seealso = ast_malloc(seealso_size);
3770 
3771  /* check allocated memory. */
3772  if (!synopsis || !description || !arguments || !seealso) {
3773  ast_free(synopsis);
3774  ast_free(description);
3775  ast_free(arguments);
3776  ast_free(seealso);
3777  ast_free(syntax);
3778  return CLI_FAILURE;
3779  }
3780 
3781  term_color(arguments, S_OR(acf->arguments, "Not available"), COLOR_CYAN, 0, arguments_size);
3782  term_color(synopsis, S_OR(acf->synopsis, "Not available"), COLOR_CYAN, 0, synopsis_size);
3783  term_color(description, S_OR(acf->desc, "Not available"), COLOR_CYAN, 0, description_size);
3784  term_color(seealso, S_OR(acf->seealso, "Not available"), COLOR_CYAN, 0, seealso_size);
3785  }
3786 
3787  ast_cli(a->fd, "%s%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n",
3788  infotitle, syntitle, synopsis, destitle, description,
3789  stxtitle, syntax, argtitle, arguments, seealsotitle, seealso);
3790 
3791  ast_free(arguments);
3792  ast_free(synopsis);
3793  ast_free(description);
3794  ast_free(seealso);
3795  ast_free(syntax);
3796 
3797  return CLI_SUCCESS;
3798 }
3799 
3801 {
3802  struct ast_custom_function *acf = NULL;
3803 
3805  AST_RWLIST_TRAVERSE(&acf_root, acf, acflist) {
3806  if (!strcmp(name, acf->name))
3807  break;
3808  }
3810 
3811  return acf;
3812 }
3813 
3815 {
3816  struct ast_custom_function *cur;
3817  struct ast_custom_escalating_function *cur_escalation;
3818 
3819  if (!acf) {
3820  return -1;
3821  }
3822 
3824  if ((cur = AST_RWLIST_REMOVE(&acf_root, acf, acflist))) {
3825 #ifdef AST_XML_DOCS
3826  if (cur->docsrc == AST_XML_DOC) {
3828  }
3829 #endif
3830  ast_verb(2, "Unregistered custom function %s\n", cur->name);
3831  }
3833 
3834  /* Remove from the escalation list */
3836  AST_RWLIST_TRAVERSE_SAFE_BEGIN(&escalation_root, cur_escalation, list) {
3837  if (cur_escalation->acf == acf) {
3839  ast_free(cur_escalation);
3840  break;
3841  }
3842  }
3845 
3846  return cur ? 0 : -1;
3847 }
3848 
3849 /*!
3850  * \brief Returns true if given custom function escalates privileges on read.
3851  *
3852  * \param acf Custom function to query.
3853  * \return True (non-zero) if reads escalate privileges.
3854  * \return False (zero) if reads just read.
3855  */
3856 static int read_escalates(const struct ast_custom_function *acf) {
3857  int res = 0;
3858  struct ast_custom_escalating_function *cur_escalation;
3859 
3861  AST_RWLIST_TRAVERSE(&escalation_root, cur_escalation, list) {
3862  if (cur_escalation->acf == acf) {
3863  res = cur_escalation->read_escalates;
3864  break;
3865  }
3866  }
3868  return res;
3869 }
3870 
3871 /*!
3872  * \brief Returns true if given custom function escalates privileges on write.
3873  *
3874  * \param acf Custom function to query.
3875  * \return True (non-zero) if writes escalate privileges.
3876  * \return False (zero) if writes just write.
3877  */
3878 static int write_escalates(const struct ast_custom_function *acf) {
3879  int res = 0;
3880  struct ast_custom_escalating_function *cur_escalation;
3881 
3883  AST_RWLIST_TRAVERSE(&escalation_root, cur_escalation, list) {
3884  if (cur_escalation->acf == acf) {
3885  res = cur_escalation->write_escalates;
3886  break;
3887  }
3888  }
3890  return res;
3891 }
3892 
3893 /*! \internal
3894  * \brief Retrieve the XML documentation of a specified ast_custom_function,
3895  * and populate ast_custom_function string fields.
3896  * \param acf ast_custom_function structure with empty 'desc' and 'synopsis'
3897  * but with a function 'name'.
3898  * \retval -1 On error.
3899  * \retval 0 On succes.
3900  */
3902 {
3903 #ifdef AST_XML_DOCS
3904  char *tmpxml;
3905 
3906  /* Let's try to find it in the Documentation XML */
3907  if (!ast_strlen_zero(acf->desc) || !ast_strlen_zero(acf->synopsis)) {
3908  return 0;
3909  }
3910 
3911  if (ast_string_field_init(acf, 128)) {
3912  return -1;
3913  }
3914 
3915  /* load synopsis */
3916  tmpxml = ast_xmldoc_build_synopsis("function", acf->name, ast_module_name(acf->mod));
3917  ast_string_field_set(acf, synopsis, tmpxml);
3918  ast_free(tmpxml);
3919 
3920  /* load description */
3921  tmpxml = ast_xmldoc_build_description("function", acf->name, ast_module_name(acf->mod));
3922  ast_string_field_set(acf, desc, tmpxml);
3923  ast_free(tmpxml);
3924 
3925  /* load syntax */
3926  tmpxml = ast_xmldoc_build_syntax("function", acf->name, ast_module_name(acf->mod));
3927  ast_string_field_set(acf, syntax, tmpxml);
3928  ast_free(tmpxml);
3929 
3930  /* load arguments */
3931  tmpxml = ast_xmldoc_build_arguments("function", acf->name, ast_module_name(acf->mod));
3932  ast_string_field_set(acf, arguments, tmpxml);
3933  ast_free(tmpxml);
3934 
3935  /* load seealso */
3936  tmpxml = ast_xmldoc_build_seealso("function", acf->name, ast_module_name(acf->mod));
3937  ast_string_field_set(acf, seealso, tmpxml);
3938  ast_free(tmpxml);
3939 
3940  acf->docsrc = AST_XML_DOC;
3941 #endif
3942 
3943  return 0;
3944 }
3945 
3947 {
3948  struct ast_custom_function *cur;
3949  char tmps[80];
3950 
3951  if (!acf) {
3952  return -1;
3953  }
3954 
3955  acf->mod = mod;
3956 #ifdef AST_XML_DOCS
3957  acf->docsrc = AST_STATIC_DOC;
3958 #endif
3959 
3960  if (acf_retrieve_docs(acf)) {
3961  return -1;
3962  }
3963 
3965 
3966  AST_RWLIST_TRAVERSE(&acf_root, cur, acflist) {
3967  if (!strcmp(acf->name, cur->name)) {
3968  ast_log(LOG_ERROR, "Function %s already registered.\n", acf->name);
3970  return -1;
3971  }
3972  }
3973 
3974  /* Store in alphabetical order */
3975  AST_RWLIST_TRAVERSE_SAFE_BEGIN(&acf_root, cur, acflist) {
3976  if (strcasecmp(acf->name, cur->name) < 0) {
3977  AST_RWLIST_INSERT_BEFORE_CURRENT(acf, acflist);
3978  break;
3979  }
3980  }
3982 
3983  if (!cur) {
3984  AST_RWLIST_INSERT_TAIL(&acf_root, acf, acflist);
3985  }
3986 
3988 
3989  ast_verb(2, "Registered custom function '%s'\n", term_color(tmps, acf->name, COLOR_BRCYAN, 0, sizeof(tmps)));
3990 
3991  return 0;
3992 }
3993 
3995 {
3996  struct ast_custom_escalating_function *acf_escalation = NULL;
3997  int res;
3998 
3999  res = __ast_custom_function_register(acf, mod);
4000  if (res != 0) {
4001  return -1;
4002  }
4003 
4004  if (escalation == AST_CFE_NONE) {
4005  /* No escalations; no need to do anything else */
4006  return 0;
4007  }
4008 
4009  acf_escalation = ast_calloc(1, sizeof(*acf_escalation));
4010  if (!acf_escalation) {
4012  return -1;
4013  }
4014 
4015  acf_escalation->acf = acf;
4016  switch (escalation) {
4017  case AST_CFE_NONE:
4018  break;
4019  case AST_CFE_READ:
4020  acf_escalation->read_escalates = 1;
4021  break;
4022  case AST_CFE_WRITE:
4023  acf_escalation->write_escalates = 1;
4024  break;
4025  case AST_CFE_BOTH:
4026  acf_escalation->read_escalates = 1;
4027  acf_escalation->write_escalates = 1;
4028  break;
4029  }
4030 
4032  AST_RWLIST_INSERT_TAIL(&escalation_root, acf_escalation, list);
4034 
4035  return 0;
4036 }
4037 
4038 /*! \brief return a pointer to the arguments of the function,
4039  * and terminates the function name with '\\0'
4040  */
4041 static char *func_args(char *function)
4042 {
4043  char *args = strchr(function, '(');
4044 
4045  if (!args) {
4046  ast_log(LOG_WARNING, "Function '%s' doesn't contain parentheses. Assuming null argument.\n", function);
4047  } else {
4048  char *p;
4049  *args++ = '\0';
4050  if ((p = strrchr(args, ')'))) {
4051  *p = '\0';
4052  } else {
4053  ast_log(LOG_WARNING, "Can't find trailing parenthesis for function '%s(%s'?\n", function, args);
4054  }
4055  }
4056  return args;
4057 }
4058 
4059 void pbx_live_dangerously(int new_live_dangerously)
4060 {
4061  if (new_live_dangerously && !live_dangerously) {
4062  ast_log(LOG_WARNING, "Privilege escalation protection disabled!\n"
4063  "See https://wiki.asterisk.org/wiki/x/1gKfAQ for more details.\n");
4064  }
4065 
4066  if (!new_live_dangerously && live_dangerously) {
4067  ast_log(LOG_NOTICE, "Privilege escalation protection enabled.\n");
4068  }
4069  live_dangerously = new_live_dangerously;
4070 }
4071 
4073 {
4074  int *thread_inhibit_escalations;
4075 
4076  thread_inhibit_escalations = ast_threadstorage_get(
4077  &thread_inhibit_escalations_tl, sizeof(*thread_inhibit_escalations));
4078 
4079  if (thread_inhibit_escalations == NULL) {
4080  ast_log(LOG_ERROR, "Error inhibiting privilege escalations for current thread\n");
4081  return -1;
4082  }
4083 
4084  *thread_inhibit_escalations = 1;
4085  return 0;
4086 }
4087 
4088 /*!
4089  * \brief Indicates whether the current thread inhibits the execution of
4090  * dangerous functions.
4091  *
4092  * \return True (non-zero) if dangerous function execution is inhibited.
4093  * \return False (zero) if dangerous function execution is allowed.
4094  */
4096 {
4097  int *thread_inhibit_escalations;
4098 
4099  thread_inhibit_escalations = ast_threadstorage_get(
4100  &thread_inhibit_escalations_tl, sizeof(*thread_inhibit_escalations));
4101 
4102  if (thread_inhibit_escalations == NULL) {
4103  ast_log(LOG_ERROR, "Error checking thread's ability to run dangerous functions\n");
4104  /* On error, assume that we are inhibiting */
4105  return 1;
4106  }
4107 
4108  return *thread_inhibit_escalations;
4109 }
4110 
4111 /*!
4112  * \brief Determines whether execution of a custom function's read function
4113  * is allowed.
4114  *
4115  * \param acfptr Custom function to check
4116  * \return True (non-zero) if reading is allowed.
4117  * \return False (zero) if reading is not allowed.
4118  */
4119 static int is_read_allowed(struct ast_custom_function *acfptr)
4120 {
4121  if (!acfptr) {
4122  return 1;
4123  }
4124 
4125  if (!read_escalates(acfptr)) {
4126  return 1;
4127  }
4128 
4129  if (!thread_inhibits_escalations()) {
4130  return 1;
4131  }
4132 
4133  if (live_dangerously) {
4134  /* Global setting overrides the thread's preference */
4135  ast_debug(2, "Reading %s from a dangerous context\n",
4136  acfptr->name);
4137  return 1;
4138  }
4139 
4140  /* We have no reason to allow this function to execute */
4141  return 0;
4142 }
4143 
4144 /*!
4145  * \brief Determines whether execution of a custom function's write function
4146  * is allowed.
4147  *
4148  * \param acfptr Custom function to check
4149  * \return True (non-zero) if writing is allowed.
4150  * \return False (zero) if writing is not allowed.
4151  */
4152 static int is_write_allowed(struct ast_custom_function *acfptr)
4153 {
4154  if (!acfptr) {
4155  return 1;
4156  }
4157 
4158  if (!write_escalates(acfptr)) {
4159  return 1;
4160  }
4161 
4162  if (!thread_inhibits_escalations()) {
4163  return 1;
4164  }
4165 
4166  if (live_dangerously) {
4167  /* Global setting overrides the thread's preference */
4168  ast_debug(2, "Writing %s from a dangerous context\n",
4169  acfptr->name);
4170  return 1;
4171  }
4172 
4173  /* We have no reason to allow this function to execute */
4174  return 0;
4175 }
4176 
4177 int ast_func_read(struct ast_channel *chan, const char *function, char *workspace, size_t len)
4178 {
4179  char *copy = ast_strdupa(function);
4180  char *args = func_args(copy);
4181  struct ast_custom_function *acfptr = ast_custom_function_find(copy);
4182  int res;
4183  struct ast_module_user *u = NULL;
4184 
4185  if (acfptr == NULL) {
4186  ast_log(LOG_ERROR, "Function %s not registered\n", copy);
4187  } else if (!acfptr->read && !acfptr->read2) {
4188  ast_log(LOG_ERROR, "Function %s cannot be read\n", copy);
4189  } else if (!is_read_allowed(acfptr)) {
4190  ast_log(LOG_ERROR, "Dangerous function %s read blocked\n", copy);
4191  } else if (acfptr->read) {
4192  if (acfptr->mod) {
4193  u = __ast_module_user_add(acfptr->mod, chan);
4194  }
4195  res = acfptr->read(chan, copy, args, workspace, len);
4196  if (acfptr->mod && u) {
4197  __ast_module_user_remove(acfptr->mod, u);
4198  }
4199  return res;
4200  } else {
4201  struct ast_str *str = ast_str_create(16);
4202  if (acfptr->mod) {
4203  u = __ast_module_user_add(acfptr->mod, chan);
4204  }
4205  res = acfptr->read2(chan, copy, args, &str, 0);
4206  if (acfptr->mod && u) {
4207  __ast_module_user_remove(acfptr->mod, u);
4208  }
4209  ast_copy_string(workspace, ast_str_buffer(str), len > ast_str_size(str) ? ast_str_size(str) : len);
4210  ast_free(str);
4211  return res;
4212  }
4213  return -1;
4214 }
4215 
4216 int ast_func_read2(struct ast_channel *chan, const char *function, struct ast_str **str, ssize_t maxlen)
4217 {
4218  char *copy = ast_strdupa(function);
4219  char *args = func_args(copy);
4220  struct ast_custom_function *acfptr = ast_custom_function_find(copy);
4221  int res;
4222  struct ast_module_user *u = NULL;
4223 
4224  if (acfptr == NULL) {
4225  ast_log(LOG_ERROR, "Function %s not registered\n", copy);
4226  } else if (!acfptr->read && !acfptr->read2) {
4227  ast_log(LOG_ERROR, "Function %s cannot be read\n", copy);
4228  } else if (!is_read_allowed(acfptr)) {
4229  ast_log(LOG_ERROR, "Dangerous function %s read blocked\n", copy);
4230  } else {
4231  if (acfptr->mod) {
4232  u = __ast_module_user_add(acfptr->mod, chan);
4233  }
4234  ast_str_reset(*str);
4235  if (acfptr->read2) {
4236  /* ast_str enabled */
4237  res = acfptr->read2(chan, copy, args, str, maxlen);
4238  } else {
4239  /* Legacy function pointer, allocate buffer for result */
4240  int maxsize = ast_str_size(*str);
4241  if (maxlen > -1) {
4242  if (maxlen == 0) {
4243  if (acfptr->read_max) {
4244  maxsize = acfptr->read_max;
4245  } else {
4246  maxsize = VAR_BUF_SIZE;
4247  }
4248  } else {
4249  maxsize = maxlen;
4250  }
4251  ast_str_make_space(str, maxsize);
4252  }
4253  res = acfptr->read(chan, copy, args, ast_str_buffer(*str), maxsize);
4254  }
4255  if (acfptr->mod && u) {
4256  __ast_module_user_remove(acfptr->mod, u);
4257  }
4258  return res;
4259  }
4260  return -1;
4261 }
4262 
4263 int ast_func_write(struct ast_channel *chan, const char *function, const char *value)
4264 {
4265  char *copy = ast_strdupa(function);
4266  char *args = func_args(copy);
4267  struct ast_custom_function *acfptr = ast_custom_function_find(copy);
4268 
4269  if (acfptr == NULL) {
4270  ast_log(LOG_ERROR, "Function %s not registered\n", copy);
4271  } else if (!acfptr->write) {
4272  ast_log(LOG_ERROR, "Function %s cannot be written to\n", copy);
4273  } else if (!is_write_allowed(acfptr)) {
4274  ast_log(LOG_ERROR, "Dangerous function %s write blocked\n", copy);
4275  } else {
4276  int res;
4277  struct ast_module_user *u = NULL;
4278  if (acfptr->mod)
4279  u = __ast_module_user_add(acfptr->mod, chan);
4280  res = acfptr->write(chan, copy, args, value);
4281  if (acfptr->mod && u)
4282  __ast_module_user_remove(acfptr->mod, u);
4283  return res;
4284  }
4285 
4286  return -1;
4287 }
4288 
4289 void ast_str_substitute_variables_full(struct ast_str **buf, ssize_t maxlen, struct ast_channel *c, struct varshead *headp, const char *templ, size_t *used)
4290 {
4291  /* Substitutes variables into buf, based on string templ */
4292  char *cp4 = NULL;
4293  const char *tmp, *whereweare;
4294  int orig_size = 0;
4295  int offset, offset2, isfunction;
4296  const char *nextvar, *nextexp, *nextthing;
4297  const char *vars, *vare;
4298  char *finalvars;
4299  int pos, brackets, needsub, len;
4300  struct ast_str *substr1 = ast_str_create(16), *substr2 = NULL, *substr3 = ast_str_create(16);
4301 
4302  ast_str_reset(*buf);
4303  whereweare = tmp = templ;
4304  while (!ast_strlen_zero(whereweare)) {
4305  /* reset our buffer */
4306  ast_str_reset(substr3);
4307 
4308  /* Assume we're copying the whole remaining string */
4309  pos = strlen(whereweare);
4310  nextvar = NULL;
4311  nextexp = NULL;
4312  nextthing = strchr(whereweare, '$');
4313  if (nextthing) {
4314  switch (nextthing[1]) {
4315  case '{':
4316  nextvar = nextthing;
4317  pos = nextvar - whereweare;
4318  break;
4319  case '[':
4320  nextexp = nextthing;
4321  pos = nextexp - whereweare;
4322  break;
4323  default:
4324  pos = 1;
4325  }
4326  }
4327 
4328  if (pos) {
4329  /* Copy that many bytes */
4330  ast_str_append_substr(buf, maxlen, whereweare, pos);
4331 
4332  templ += pos;
4333  whereweare += pos;
4334  }
4335 
4336  if (nextvar) {
4337  /* We have a variable. Find the start and end, and determine
4338  if we are going to have to recursively call ourselves on the
4339  contents */
4340  vars = vare = nextvar + 2;
4341  brackets = 1;
4342  needsub = 0;
4343 
4344  /* Find the end of it */
4345  while (brackets && *vare) {
4346  if ((vare[0] == '$') && (vare[1] == '{')) {
4347  needsub++;
4348  } else if (vare[0] == '{') {
4349  brackets++;
4350  } else if (vare[0] == '}') {
4351  brackets--;
4352  } else if ((vare[0] == '$') && (vare[1] == '['))
4353  needsub++;
4354  vare++;
4355  }
4356  if (brackets)
4357  ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n");
4358  len = vare - vars - 1;
4359 
4360  /* Skip totally over variable string */
4361  whereweare += (len + 3);
4362 
4363  /* Store variable name (and truncate) */
4364  ast_str_set_substr(&substr1, 0, vars, len);
4365  ast_debug(5, "Evaluating '%s' (from '%s' len %d)\n", ast_str_buffer(substr1), vars, len);
4366 
4367  /* Substitute if necessary */
4368  if (needsub) {
4369  size_t used;
4370  if (!substr2) {
4371  substr2 = ast_str_create(16);
4372  }
4373 
4374  ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), &used);
4375  finalvars = ast_str_buffer(substr2);
4376  } else {
4377  finalvars = ast_str_buffer(substr1);
4378  }
4379 
4380  parse_variable_name(finalvars, &offset, &offset2, &isfunction);
4381  if (isfunction) {
4382  /* Evaluate function */
4383  if (c || !headp) {
4384  cp4 = ast_func_read2(c, finalvars, &substr3, 0) ? NULL : ast_str_buffer(substr3);
4385  } else {
4386  struct varshead old;
4387  struct ast_channel *bogus = ast_dummy_channel_alloc();
4388  if (bogus) {
4389  memcpy(&old, &bogus->varshead, sizeof(old));
4390  memcpy(&bogus->varshead, headp, sizeof(bogus->varshead));
4391  cp4 = ast_func_read2(c, finalvars, &substr3, 0) ? NULL : ast_str_buffer(substr3);
4392  /* Don't deallocate the varshead that was passed in */
4393  memcpy(&bogus->varshead, &old, sizeof(bogus->varshead));
4394  ast_channel_unref(bogus);
4395  } else {
4396  ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution. Function results may be blank.\n");
4397  }
4398  }
4399  ast_debug(2, "Function %s result is '%s'\n", finalvars, cp4 ? cp4 : "(null)");
4400  } else {
4401  /* Retrieve variable value */
4402  ast_str_retrieve_variable(&substr3, 0, c, headp, finalvars);
4403  cp4 = ast_str_buffer(substr3);
4404  }
4405  if (cp4) {
4406  ast_str_substring(substr3, offset, offset2);
4407  ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3));
4408  }
4409  } else if (nextexp) {
4410  /* We have an expression. Find the start and end, and determine
4411  if we are going to have to recursively call ourselves on the
4412  contents */
4413  vars = vare = nextexp + 2;
4414  brackets = 1;
4415  needsub = 0;
4416 
4417  /* Find the end of it */
4418  while (brackets && *vare) {
4419  if ((vare[0] == '$') && (vare[1] == '[')) {
4420  needsub++;
4421  brackets++;
4422  vare++;
4423  } else if (vare[0] == '[') {
4424  brackets++;
4425  } else if (vare[0] == ']') {
4426  brackets--;
4427  } else if ((vare[0] == '$') && (vare[1] == '{')) {
4428  needsub++;
4429  vare++;
4430  }
4431  vare++;
4432  }
4433  if (brackets)
4434  ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n");
4435  len = vare - vars - 1;
4436 
4437  /* Skip totally over expression */
4438  whereweare += (len + 3);
4439 
4440  /* Store variable name (and truncate) */
4441  ast_str_set_substr(&substr1, 0, vars, len);
4442 
4443  /* Substitute if necessary */
4444  if (needsub) {
4445  size_t used;
4446  if (!substr2) {
4447  substr2 = ast_str_create(16);
4448  }
4449 
4450  ast_str_substitute_variables_full(&substr2, 0, c, headp, ast_str_buffer(substr1), &used);
4451  finalvars = ast_str_buffer(substr2);
4452  } else {
4453  finalvars = ast_str_buffer(substr1);
4454  }
4455 
4456  if (ast_str_expr(&substr3, 0, c, finalvars)) {
4457  ast_debug(2, "Expression result is '%s'\n", ast_str_buffer(substr3));
4458  }
4459  ast_str_append(buf, maxlen, "%s", ast_str_buffer(substr3));
4460  }
4461  }
4462  *used = ast_str_strlen(*buf) - orig_size;
4463  ast_free(substr1);
4464  ast_free(substr2);
4465  ast_free(substr3);
4466 }
4467 
4468 void ast_str_substitute_variables(struct ast_str **buf, ssize_t maxlen, struct ast_channel *chan, const char *templ)
4469 {
4470  size_t used;
4471  ast_str_substitute_variables_full(buf, maxlen, chan, NULL, templ, &used);
4472 }
4473 
4474 void ast_str_substitute_variables_varshead(struct ast_str **buf, ssize_t maxlen, struct varshead *headp, const char *templ)
4475 {
4476  size_t used;
4477  ast_str_substitute_variables_full(buf, maxlen, NULL, headp, templ, &used);
4478 }
4479 
4480 void pbx_substitute_variables_helper_full(struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int count, size_t *used)
4481 {
4482  /* Substitutes variables into cp2, based on string cp1, cp2 NO LONGER NEEDS TO BE ZEROED OUT!!!! */
4483  char *cp4 = NULL;
4484  const char *tmp, *whereweare, *orig_cp2 = cp2;
4485  int length, offset, offset2, isfunction;
4486  char *workspace = NULL;
4487  char *ltmp = NULL, *var = NULL;
4488  char *nextvar, *nextexp, *nextthing;
4489  char *vars, *vare;
4490  int pos, brackets, needsub, len;
4491 
4492  *cp2 = 0; /* just in case nothing ends up there */
4493  whereweare=tmp=cp1;
4494  while (!ast_strlen_zero(whereweare) && count) {
4495  /* Assume we're copying the whole remaining string */
4496  pos = strlen(whereweare);
4497  nextvar = NULL;
4498  nextexp = NULL;
4499  nextthing = strchr(whereweare, '$');
4500  if (nextthing) {
4501  switch (nextthing[1]) {
4502  case '{':
4503  nextvar = nextthing;
4504  pos = nextvar - whereweare;
4505  break;
4506  case '[':
4507  nextexp = nextthing;
4508  pos = nextexp - whereweare;
4509  break;
4510  default:
4511  pos = 1;
4512  }
4513  }
4514 
4515  if (pos) {
4516  /* Can't copy more than 'count' bytes */
4517  if (pos > count)
4518  pos = count;
4519 
4520  /* Copy that many bytes */
4521  memcpy(cp2, whereweare, pos);
4522 
4523  count -= pos;
4524  cp2 += pos;
4525  whereweare += pos;
4526  *cp2 = 0;
4527  }
4528 
4529  if (nextvar) {
4530  /* We have a variable. Find the start and end, and determine
4531  if we are going to have to recursively call ourselves on the
4532  contents */
4533  vars = vare = nextvar + 2;
4534  brackets = 1;
4535  needsub = 0;
4536 
4537  /* Find the end of it */
4538  while (brackets && *vare) {
4539  if ((vare[0] == '$') && (vare[1] == '{')) {
4540  needsub++;
4541  } else if (vare[0] == '{') {
4542  brackets++;
4543  } else if (vare[0] == '}') {
4544  brackets--;
4545  } else if ((vare[0] == '$') && (vare[1] == '['))
4546  needsub++;
4547  vare++;
4548  }
4549  if (brackets)
4550  ast_log(LOG_WARNING, "Error in extension logic (missing '}')\n");
4551  len = vare - vars - 1;
4552 
4553  /* Skip totally over variable string */
4554  whereweare += (len + 3);
4555 
4556  if (!var)
4557  var = ast_alloca(VAR_BUF_SIZE);
4558 
4559  /* Store variable name (and truncate) */
4560  ast_copy_string(var, vars, len + 1);
4561 
4562  /* Substitute if necessary */
4563  if (needsub) {
4564  size_t used;
4565  if (!ltmp)
4566  ltmp = ast_alloca(VAR_BUF_SIZE);
4567 
4568  pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &used);
4569  vars = ltmp;
4570  } else {
4571  vars = var;
4572  }
4573 
4574  if (!workspace)
4575  workspace = ast_alloca(VAR_BUF_SIZE);
4576 
4577  workspace[0] = '\0';
4578 
4579  parse_variable_name(vars, &offset, &offset2, &isfunction);
4580  if (isfunction) {
4581  /* Evaluate function */
4582  if (c || !headp)
4583  cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace;
4584  else {
4585  struct varshead old;
4586  struct ast_channel *c = ast_dummy_channel_alloc();
4587  if (c) {
4588  memcpy(&old, &c->varshead, sizeof(old));
4589  memcpy(&c->varshead, headp, sizeof(c->varshead));
4590  cp4 = ast_func_read(c, vars, workspace, VAR_BUF_SIZE) ? NULL : workspace;
4591  /* Don't deallocate the varshead that was passed in */
4592  memcpy(&c->varshead, &old, sizeof(c->varshead));
4593  c = ast_channel_unref(c);
4594  } else {
4595  ast_log(LOG_ERROR, "Unable to allocate bogus channel for variable substitution. Function results may be blank.\n");
4596  }
4597  }
4598  ast_debug(2, "Function %s result is '%s'\n", vars, cp4 ? cp4 : "(null)");
4599  } else {
4600  /* Retrieve variable value */
4601  pbx_retrieve_variable(c, vars, &cp4, workspace, VAR_BUF_SIZE, headp);
4602  }
4603  if (cp4) {
4604  cp4 = substring(cp4, offset, offset2, workspace, VAR_BUF_SIZE);
4605 
4606  length = strlen(cp4);
4607  if (length > count)
4608  length = count;
4609  memcpy(cp2, cp4, length);
4610  count -= length;
4611  cp2 += length;
4612  *cp2 = 0;
4613  }
4614  } else if (nextexp) {
4615  /* We have an expression. Find the start and end, and determine
4616  if we are going to have to recursively call ourselves on the
4617  contents */
4618  vars = vare = nextexp + 2;
4619  brackets = 1;
4620  needsub = 0;
4621 
4622  /* Find the end of it */
4623  while (brackets && *vare) {
4624  if ((vare[0] == '$') && (vare[1] == '[')) {
4625  needsub++;
4626  brackets++;
4627  vare++;
4628  } else if (vare[0] == '[') {
4629  brackets++;
4630  } else if (vare[0] == ']') {
4631  brackets--;
4632  } else if ((vare[0] == '$') && (vare[1] == '{')) {
4633  needsub++;
4634  vare++;
4635  }
4636  vare++;
4637  }
4638  if (brackets)
4639  ast_log(LOG_WARNING, "Error in extension logic (missing ']')\n");
4640  len = vare - vars - 1;
4641 
4642  /* Skip totally over expression */
4643  whereweare += (len + 3);
4644 
4645  if (!var)
4646  var = ast_alloca(VAR_BUF_SIZE);
4647 
4648  /* Store variable name (and truncate) */
4649  ast_copy_string(var, vars, len + 1);
4650 
4651  /* Substitute if necessary */
4652  if (needsub) {
4653  size_t used;
4654  if (!ltmp)
4655  ltmp = ast_alloca(VAR_BUF_SIZE);
4656 
4657  pbx_substitute_variables_helper_full(c, headp, var, ltmp, VAR_BUF_SIZE - 1, &used);
4658  vars = ltmp;
4659  } else {
4660  vars = var;
4661  }
4662 
4663  length = ast_expr(vars, cp2, count, c);
4664 
4665  if (length) {
4666  ast_debug(1, "Expression result is '%s'\n", cp2);
4667  count -= length;
4668  cp2 += length;
4669  *cp2 = 0;
4670  }
4671  }
4672  }
4673  *used = cp2 - orig_cp2;
4674 }
4675 
4676 void pbx_substitute_variables_helper(struct ast_channel *c, const char *cp1, char *cp2, int count)
4677 {
4678  size_t used;
4679  pbx_substitute_variables_helper_full(c, (c) ? &c->varshead : NULL, cp1, cp2, count, &used);
4680 }
4681 
4682 void pbx_substitute_variables_varshead(struct varshead *headp, const char *cp1, char *cp2, int count)
4683 {
4684  size_t used;
4685  pbx_substitute_variables_helper_full(NULL, headp, cp1, cp2, count, &used);
4686 }
4687 
4688 /*!
4689  * \brief The return value depends on the action:
4690  *
4691  * E_MATCH, E_CANMATCH, E_MATCHMORE require a real match,
4692  * and return 0 on failure, -1 on match;
4693  * E_FINDLABEL maps the label to a priority, and returns
4694  * the priority on success, ... XXX
4695  * E_SPAWN, spawn an application,
4696  *
4697  * \retval 0 on success.
4698  * \retval -1 on failure.
4699  *
4700  * \note The channel is auto-serviced in this function, because doing an extension
4701  * match may block for a long time. For example, if the lookup has to use a network
4702  * dialplan switch, such as DUNDi or IAX2, it may take a while. However, the channel
4703  * auto-service code will queue up any important signalling frames to be processed
4704  * after this is done.
4705  */
4706 static int pbx_extension_helper(struct ast_channel *c, struct ast_context *con,
4707  const char *context, const char *exten, int priority,
4708  const char *label, const char *callerid, enum ext_match_t action, int *found, int combined_find_spawn)
4709 {
4710  struct ast_exten *e;
4711  struct ast_app *app;
4712  char *substitute = NULL;
4713  int res;
4714  struct pbx_find_info q = { .stacklen = 0 }; /* the rest is reset in pbx_find_extension */
4715  char passdata[EXT_DATA_SIZE];
4716 
4717  int matching_action = (action == E_MATCH || action == E_CANMATCH || action == E_MATCHMORE);
4718 
4720  if (found)
4721  *found = 0;
4722 
4723  e = pbx_find_extension(c, con, &q, context, exten, priority, label, callerid, action);
4724  if (e) {
4725  if (found)
4726  *found = 1;
4727  if (matching_action) {
4729  return -1; /* success, we found it */
4730  } else if (action == E_FINDLABEL) { /* map the label to a priority */
4731  res = e->priority;
4733  return res; /* the priority we were looking for */
4734  } else { /* spawn */
4735  if (!e->cached_app)
4736  e->cached_app = pbx_findapp(e->app);
4737  app = e->cached_app;
4738  if (ast_strlen_zero(e->data)) {
4739  *passdata = '\0';
4740  } else {
4741  const char *tmp;
4742  if ((!(tmp = strchr(e->data, '$'))) || (!strstr(tmp, "${") && !strstr(tmp, "$["))) {
4743  /* no variables to substitute, copy on through */
4744  ast_copy_string(passdata, e->data, sizeof(passdata));
4745  } else {
4746  /* save e->data on stack for later processing after lock released */
4747  substitute = ast_strdupa(e->data);
4748  }
4749  }
4751  if (!app) {
4752  ast_log(LOG_WARNING, "No application '%s' for extension (%s, %s, %d)\n", e->app, context, exten, priority);
4753  return -1;
4754  }
4755  if (c->context != context)
4756  ast_copy_string(c->context, context, sizeof(c->context));
4757  if (c->exten != exten)
4758  ast_copy_string(c->exten, exten, sizeof(c->exten));
4759  c->priority = priority;
4760  if (substitute) {
4761  pbx_substitute_variables_helper(c, substitute, passdata, sizeof(passdata)-1);
4762  }
4763 #ifdef CHANNEL_TRACE
4764  ast_channel_trace_update(c);
4765 #endif
4766  ast_debug(1, "Launching '%s'\n", app->name);
4767  if (VERBOSITY_ATLEAST(3)) {
4768  char tmp[80], tmp2[80], tmp3[EXT_DATA_SIZE];
4769  ast_verb(3, "Executing [%s@%s:%d] %s(\"%s\", \"%s\") %s\n",
4770  exten, context, priority,
4771  term_color(tmp, app->name, COLOR_BRCYAN, 0, sizeof(tmp)),
4772  term_color(tmp2, c->name, COLOR_BRMAGENTA, 0, sizeof(tmp2)),
4773  term_color(tmp3, passdata, COLOR_BRMAGENTA, 0, sizeof(tmp3)),
4774  "in new stack");
4775  }
4776  manager_event(EVENT_FLAG_DIALPLAN, "Newexten",
4777  "Channel: %s\r\n"
4778  "Context: %s\r\n"
4779  "Extension: %s\r\n"
4780  "Priority: %d\r\n"
4781  "Application: %s\r\n"
4782  "AppData: %s\r\n"
4783  "Uniqueid: %s\r\n",
4784  c->name, c->context, c->exten, c->priority, app->name, passdata, c->uniqueid);
4785  return pbx_exec(c, app, passdata); /* 0 on success, -1 on failure */
4786  }
4787  } else if (q.swo) { /* not found here, but in another switch */
4788  if (found)
4789  *found = 1;
4791  if (matching_action) {
4792  return -1;
4793  } else {
4794  if (!q.swo->exec) {
4795  ast_log(LOG_WARNING, "No execution engine for switch %s\n", q.swo->name);
4796  res = -1;
4797  }
4798  return q.swo->exec(c, q.foundcontext ? q.foundcontext : context, exten, priority, callerid, q.data);
4799  }
4800  } else { /* not found anywhere, see what happened */
4802  /* Using S_OR here because Solaris doesn't like NULL being passed to ast_log */
4803  switch (q.status) {
4804  case STATUS_NO_CONTEXT:
4805  if (!matching_action && !combined_find_spawn)
4806  ast_log(LOG_NOTICE, "Cannot find extension context '%s'\n", S_OR(context, ""));
4807  break;
4808  case STATUS_NO_EXTENSION:
4809  if (!matching_action && !combined_find_spawn)
4810  ast_log(LOG_NOTICE, "Cannot find extension '%s' in context '%s'\n", exten, S_OR(context, ""));
4811  break;
4812  case STATUS_NO_PRIORITY:
4813  if (!matching_action && !combined_find_spawn)
4814  ast_log(LOG_NOTICE, "No such priority %d in extension '%s' in context '%s'\n", priority, exten, S_OR(context, ""));
4815  break;
4816  case STATUS_NO_LABEL:
4817  if (context && !combined_find_spawn)
4818  ast_log(LOG_NOTICE, "No such label '%s' in extension '%s' in context '%s'\n", label, exten, S_OR(context, ""));
4819  break;
4820  default:
4821  ast_debug(1, "Shouldn't happen!\n");
4822  }
4823 
4824  return (matching_action) ? 0 : -1;
4825  }
4826 }
4827 
4828 /*! \brief Find hint for given extension in context */
4829 static struct ast_exten *ast_hint_extension_nolock(struct ast_channel *c, const char *context, const char *exten)
4830 {
4831  struct pbx_find_info q = { .stacklen = 0 }; /* the rest is set in pbx_find_context */
4832  return pbx_find_extension(c, NULL, &q, context, exten, PRIORITY_HINT, NULL, "", E_MATCH);
4833 }
4834 
4835 static struct ast_exten *ast_hint_extension(struct ast_channel *c, const char *context, const char *exten)
4836 {
4837  struct ast_exten *e;
4839  e = ast_hint_extension_nolock(c, context, exten);
4841  return e;
4842 }
4843 
4845 {
4846  switch (devstate) {
4847  case AST_DEVICE_ONHOLD:
4848  return AST_EXTENSION_ONHOLD;
4849  case AST_DEVICE_BUSY:
4850  return AST_EXTENSION_BUSY;
4851  case AST_DEVICE_UNKNOWN:
4852  return AST_EXTENSION_NOT_INUSE;
4854  case AST_DEVICE_INVALID:
4856  case AST_DEVICE_RINGINUSE:
4858  case AST_DEVICE_RINGING:
4859  return AST_EXTENSION_RINGING;
4860  case AST_DEVICE_INUSE:
4861  return AST_EXTENSION_INUSE;
4862  case AST_DEVICE_NOT_INUSE:
4863  return AST_EXTENSION_NOT_INUSE;
4864  case AST_DEVICE_TOTAL: /* not a device state, included for completeness */
4865  break;
4866  }
4867 
4868  return AST_EXTENSION_NOT_INUSE;
4869 }
4870 
4871 static int ast_extension_state3(struct ast_str *hint_app)
4872 {
4873  char *cur;
4874  char *rest;
4875  struct ast_devstate_aggregate agg;
4876 
4877  /* One or more devices separated with a & character */
4878  rest = ast_str_buffer(hint_app);
4879 
4881  while ((cur = strsep(&rest, "&"))) {
4883  }
4884 
4886 }
4887 
4888 /*! \brief Check state of extension by using hints */
4889 static int ast_extension_state2(struct ast_exten *e)
4890 {
4891  struct ast_str *hint_app = ast_str_thread_get(&extensionstate_buf, 32);
4892 
4893  if (!e || !hint_app) {
4894  return -1;
4895  }
4896 
4897  ast_str_set(&hint_app, 0, "%s", ast_get_extension_app(e));
4898  return ast_extension_state3(hint_app);
4899 }
4900 
4901 /*! \brief Return extension_state as string */
4902 const char *ast_extension_state2str(int extension_state)
4903 {
4904  int i;
4905 
4906  for (i = 0; (i < ARRAY_LEN(extension_states)); i++) {
4907  if (extension_states[i].extension_state == extension_state)
4908  return extension_states[i].text;
4909  }
4910  return "Unknown";
4911 }
4912 
4913 /*! \brief Check extension state for an extension by using hint */
4914 int ast_extension_state(struct ast_channel *c, const char *context, const char *exten)
4915 {
4916  struct ast_exten *e;
4917 
4918  if (!(e = ast_hint_extension(c, context, exten))) { /* Do we have a hint for this extension ? */
4919  return -1; /* No hint, return -1 */
4920  }
4921 
4922  if (e->exten[0] == '_') {
4923  /* Create this hint on-the-fly */
4924  ast_add_extension(e->parent->name, 0, exten, e->priority, e->label,
4925  e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr,
4926  e->registrar);
4927  if (!(e = ast_hint_extension(c, context, exten))) {
4928  /* Improbable, but not impossible */
4929  return -1;
4930  }
4931  }
4932 
4933  return ast_extension_state2(e); /* Check all devices in the hint */
4934 }
4935 
4936 static int handle_statechange(void *datap)
4937 {
4938  struct ast_hint *hint;
4939  struct ast_str *hint_app;
4940  struct statechange *sc = datap;
4941  struct ao2_iterator i;
4942  struct ao2_iterator cb_iter;
4943  char context_name[AST_MAX_CONTEXT];
4944  char exten_name[AST_MAX_EXTENSION];
4945 
4946  hint_app = ast_str_create(1024);
4947  if (!hint_app) {
4948  ast_free(sc);
4949  return -1;
4950  }
4951 
4952  ast_mutex_lock(&context_merge_lock);/* Hold off ast_merge_contexts_and_delete */
4953  i = ao2_iterator_init(hints, 0);
4954  for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) {
4955  struct ast_state_cb *state_cb;
4956  char *cur, *parse;
4957  int state;
4958 
4959  ao2_lock(hint);
4960  if (!hint->exten) {
4961  /* The extension has already been destroyed */
4962  ao2_unlock(hint);
4963  continue;
4964  }
4965 
4966  /* Does this hint monitor the device that changed state? */
4967  ast_str_set(&hint_app, 0, "%s", ast_get_extension_app(hint->exten));
4968  parse = ast_str_buffer(hint_app);
4969  while ((cur = strsep(&parse, "&"))) {
4970  if (!strcasecmp(cur, sc->dev)) {
4971  /* The hint monitors the device. */
4972  break;
4973  }
4974  }
4975  if (!cur) {
4976  /* The hint does not monitor the device. */
4977  ao2_unlock(hint);
4978  continue;
4979  }
4980 
4981  /*
4982  * Save off strings in case the hint extension gets destroyed
4983  * while we are notifying the watchers.
4984  */
4985  ast_copy_string(context_name,
4987  sizeof(context_name));
4988  ast_copy_string(exten_name, ast_get_extension_name(hint->exten),
4989  sizeof(exten_name));
4990  ast_str_set(&hint_app, 0, "%s", ast_get_extension_app(hint->exten));
4991  ao2_unlock(hint);
4992 
4993  /*
4994  * Get device state for this hint.
4995  *
4996  * NOTE: We cannot hold any locks while determining the hint
4997  * device state or notifying the watchers without causing a
4998  * deadlock. (conlock, hints, and hint)
4999  */
5000  state = ast_extension_state3(hint_app);
5001  if (state == hint->laststate) {
5002  continue;
5003  }
5004 
5005  /* Device state changed since last check - notify the watchers. */
5006  hint->laststate = state; /* record we saw the change */
5007 
5008  /* For general callbacks */
5009  cb_iter = ao2_iterator_init(statecbs, 0);
5010  for (; (state_cb = ao2_iterator_next(&cb_iter)); ao2_ref(state_cb, -1)) {
5011  state_cb->change_cb(context_name, exten_name, state, state_cb->data);
5012  }
5013  ao2_iterator_destroy(&cb_iter);
5014 
5015  /* For extension callbacks */
5016  cb_iter = ao2_iterator_init(hint->callbacks, 0);
5017  for (; (state_cb = ao2_iterator_next(&cb_iter)); ao2_ref(state_cb, -1)) {
5018  state_cb->change_cb(context_name, exten_name, state, state_cb->data);
5019  }
5020  ao2_iterator_destroy(&cb_iter);
5021  }
5024 
5025  ast_free(hint_app);
5026  ast_free(sc);
5027  return 0;
5028 }
5029 
5030 /*!
5031  * \internal
5032  * \brief Destroy the given state callback object.
5033  *
5034  * \param doomed State callback to destroy.
5035  *
5036  * \return Nothing
5037  */
5038 static void destroy_state_cb(void *doomed)
5039 {
5040  struct ast_state_cb *state_cb = doomed;
5041 
5042  if (state_cb->destroy_cb) {
5043  state_cb->destroy_cb(state_cb->id, state_cb->data);
5044  }
5045 }
5046 
5047 /*! \brief Add watcher for extension states with destructor */
5048 int ast_extension_state_add_destroy(const char *context, const char *exten,
5049  ast_state_cb_type change_cb, ast_state_cb_destroy_type destroy_cb, void *data)
5050 {
5051  struct ast_hint *hint;
5052  struct ast_state_cb *state_cb;
5053  struct ast_exten *e;
5054  int id;
5055 
5056  /* If there's no context and extension: add callback to statecbs list */
5057  if (!context && !exten) {
5058  /* Prevent multiple adds from adding the same change_cb at the same time. */
5059  ao2_lock(statecbs);
5060 
5061  /* Remove any existing change_cb. */
5062  ao2_find(statecbs, change_cb, OBJ_UNLINK | OBJ_NODATA);
5063 
5064  /* Now insert the change_cb */
5065  if (!(state_cb = ao2_alloc(sizeof(*state_cb), destroy_state_cb))) {
5067  return -1;
5068  }
5069  state_cb->id = 0;
5070  state_cb->change_cb = change_cb;
5071  state_cb->destroy_cb = destroy_cb;
5072  state_cb->data = data;
5073  ao2_link(statecbs, state_cb);
5074 
5075  ao2_ref(state_cb, -1);
5077  return 0;
5078  }
5079 
5080  if (!context || !exten)
5081  return -1;
5082 
5083  /* This callback type is for only one hint, so get the hint */
5084  e = ast_hint_extension(NULL, context, exten);
5085  if (!e) {
5086  return -1;
5087  }
5088 
5089  /* If this is a pattern, dynamically create a new extension for this
5090  * particular match. Note that this will only happen once for each
5091  * individual extension, because the pattern will no longer match first.
5092  */
5093  if (e->exten[0] == '_') {
5094  ast_add_extension(e->parent->name, 0, exten, e->priority, e->label,
5095  e->matchcid ? e->cidmatch : NULL, e->app, ast_strdup(e->data), ast_free_ptr,
5096  e->registrar);
5097  e = ast_hint_extension(NULL, context, exten);
5098  if (!e || e->exten[0] == '_') {
5099  return -1;
5100  }
5101  }
5102 
5103  /* Find the hint in the hints container */
5104  ao2_lock(hints);/* Locked to hold off ast_merge_contexts_and_delete */
5105  hint = ao2_find(hints, e, 0);
5106  if (!hint) {
5107  ao2_unlock(hints);
5108  return -1;
5109  }
5110 
5111  /* Now insert the callback in the callback list */
5112  if (!(state_cb = ao2_alloc(sizeof(*state_cb), destroy_state_cb))) {
5113  ao2_ref(hint, -1);
5114  ao2_unlock(hints);
5115  return -1;
5116  }
5117  do {
5118  id = stateid++; /* Unique ID for this callback */
5119  /* Do not allow id to ever be -1 or 0. */
5120  } while (id == -1 || id == 0);
5121  state_cb->id = id;
5122  state_cb->change_cb = change_cb; /* Pointer to callback routine */
5123  state_cb->destroy_cb = destroy_cb;
5124  state_cb->data = data; /* Data for the callback */
5125  ao2_link(hint->callbacks, state_cb);
5126 
5127  ao2_ref(state_cb, -1);
5128  ao2_ref(hint, -1);
5129  ao2_unlock(hints);
5130 
5131  return id;
5132 }
5133 
5134 /*! \brief Add watcher for extension states */
5135 int ast_extension_state_add(const char *context, const char *exten,
5136  ast_state_cb_type change_cb, void *data)
5137 {
5138  return ast_extension_state_add_destroy(context, exten, change_cb, NULL, data);
5139 }
5140 
5141 /*! \brief Remove a watcher from the callback list */
5142 static int find_hint_by_cb_id(void *obj, void *arg, int flags)
5143 {
5144  struct ast_state_cb *state_cb;
5145  const struct ast_hint *hint = obj;
5146  int *id = arg;
5147 
5148  if ((state_cb = ao2_find(hint->callbacks, id, 0))) {
5149  ao2_ref(state_cb, -1);
5150  return CMP_MATCH | CMP_STOP;
5151  }
5152 
5153  return 0;
5154 }
5155 
5156 /*! \brief ast_extension_state_del: Remove a watcher from the callback list */
5158 {
5159  struct ast_state_cb *p_cur;
5160  int ret = -1;
5161 
5162  if (!id) { /* id == 0 is a callback without extension */
5163  if (!change_cb) {
5164  return ret;
5165  }
5166  p_cur = ao2_find(statecbs, change_cb, OBJ_UNLINK);
5167  if (p_cur) {
5168  ret = 0;
5169  ao2_ref(p_cur, -1);
5170  }
5171  } else { /* callback with extension, find the callback based on ID */
5172  struct ast_hint *hint;
5173 
5174  ao2_lock(hints);/* Locked to hold off ast_merge_contexts_and_delete */
5175  hint = ao2_callback(hints, 0, find_hint_by_cb_id, &id);
5176  if (hint) {
5177  p_cur = ao2_find(hint->callbacks, &id, OBJ_UNLINK);
5178  if (p_cur) {
5179  ret = 0;
5180  ao2_ref(p_cur, -1);
5181  }
5182  ao2_ref(hint, -1);
5183  }
5184  ao2_unlock(hints);
5185  }
5186 
5187  return ret;
5188 }
5189 
5190 
5191 static int hint_id_cmp(void *obj, void *arg, int flags)
5192 {
5193  const struct ast_state_cb *cb = obj;
5194  int *id = arg;
5195 
5196  return (cb->id == *id) ? CMP_MATCH | CMP_STOP : 0;
5197 }
5198 
5199 /*!
5200  * \internal
5201  * \brief Destroy the given hint object.
5202  *
5203  * \param obj Hint to destroy.
5204  *
5205  * \return Nothing
5206  */
5207 static void destroy_hint(void *obj)
5208 {
5209  struct ast_hint *hint = obj;
5210 
5211  if (hint->callbacks) {
5212  struct ast_state_cb *state_cb;
5213  const char *context_name;
5214  const char *exten_name;
5215 
5216  if (hint->exten) {
5217  context_name = ast_get_context_name(ast_get_extension_context(hint->exten));
5218  exten_name = ast_get_extension_name(hint->exten);
5219  hint->exten = NULL;
5220  } else {
5221  /* The extension has already been destroyed */
5222  context_name = hint->context_name;
5223  exten_name = hint->exten_name;
5224  }
5225  while ((state_cb = ao2_callback(hint->callbacks, OBJ_UNLINK, NULL, NULL))) {
5226  /* Notify with -1 and remove all callbacks */
5227  /* NOTE: The casts will not be needed for v1.10 and later */
5228  state_cb->change_cb((char *) context_name, (char *) exten_name,
5229  AST_EXTENSION_DEACTIVATED, state_cb->data);
5230  ao2_ref(state_cb, -1);
5231  }
5232  ao2_ref(hint->callbacks, -1);
5233  }
5234 }
5235 
5236 /*! \brief Remove hint from extension */
5237 static int ast_remove_hint(struct ast_exten *e)
5238 {
5239  /* Cleanup the Notifys if hint is removed */
5240  struct ast_hint *hint;
5241 
5242  if (!e) {
5243  return -1;
5244  }
5245 
5246  hint = ao2_find(hints, e, OBJ_UNLINK);
5247  if (!hint) {
5248  return -1;
5249  }
5250 
5251  /*
5252  * The extension is being destroyed so we must save some
5253  * information to notify that the extension is deactivated.
5254  */
5255  ao2_lock(hint);
5258  sizeof(hint->context_name));
5260  sizeof(hint->exten_name));
5261  hint->exten = NULL;
5262  ao2_unlock(hint);
5263 
5264  ao2_ref(hint, -1);
5265 
5266  return 0;
5267 }
5268 
5269 /*! \brief Add hint to hint list, check initial extension state */
5270 static int ast_add_hint(struct ast_exten *e)
5271 {
5272  struct ast_hint *hint_new;
5273  struct ast_hint *hint_found;
5274 
5275  if (!e) {
5276  return -1;
5277  }
5278 
5279  /*
5280  * We must create the hint we wish to add before determining if
5281  * it is already in the hints container to avoid possible
5282  * deadlock when getting the current extension state.
5283  */
5284  hint_new = ao2_alloc(sizeof(*hint_new), destroy_hint);
5285  if (!hint_new) {
5286  return -1;
5287  }
5288 
5289  /* Initialize new hint. */
5290  hint_new->callbacks = ao2_container_alloc(1, NULL, hint_id_cmp);
5291  if (!hint_new->callbacks) {
5292  ao2_ref(hint_new, -1);
5293  return -1;
5294  }
5295  hint_new->exten = e;
5296  if (strstr(e->app, "${") && e->exten[0] == '_') {
5297  hint_new->laststate = AST_DEVICE_INVALID;
5298  } else {
5299  hint_new->laststate = ast_extension_state2(e);
5300  }
5301 
5302  /* Prevent multiple add hints from adding the same hint at the same time. */
5303  ao2_lock(hints);
5304 
5305  /* Search if hint exists, do nothing */
5306  hint_found = ao2_find(hints, e, 0);
5307  if (hint_found) {
5308  ao2_ref(hint_found, -1);
5309  ao2_unlock(hints);
5310  ao2_ref(hint_new, -1);
5311  ast_debug(2, "HINTS: Not re-adding existing hint %s: %s\n",
5313  return -1;
5314  }
5315 
5316  /* Add new hint to the hints container */
5317  ast_debug(2, "HINTS: Adding hint %s: %s\n",
5319  ao2_link(hints, hint_new);
5320 
5321  ao2_unlock(hints);
5322  ao2_ref(hint_new, -1);
5323 
5324  return 0;
5325 }
5326 
5327 /*! \brief Change hint for an extension */
5328 static int ast_change_hint(struct ast_exten *oe, struct ast_exten *ne)
5329 {
5330  struct ast_hint *hint;
5331 
5332  if (!oe || !ne) {
5333  return -1;
5334  }
5335 
5336  ao2_lock(hints);/* Locked to hold off others while we move the hint around. */
5337 
5338  /*
5339  * Unlink the hint from the hints container as the extension
5340  * name (which is the hash value) could change.
5341  */
5342  hint = ao2_find(hints, oe, OBJ_UNLINK);
5343  if (!hint) {
5344  ao2_unlock(hints);
5345  return -1;
5346  }
5347 
5348  /* Update the hint and put it back in the hints container. */
5349  ao2_lock(hint);
5350  hint->exten = ne;
5351  ao2_unlock(hint);
5352  ao2_link(hints, hint);
5353 
5354  ao2_unlock(hints);
5355  ao2_ref(hint, -1);
5356 
5357  return 0;
5358 }
5359 
5360 
5361 /*! \brief Get hint for channel */
5362 int ast_get_hint(char *hint, int hintsize, char *name, int namesize, struct ast_channel *c, const char *context, const char *exten)
5363 {
5364  struct ast_exten *e = ast_hint_extension(c, context, exten);
5365 
5366  if (e) {
5367  if (hint)
5368  ast_copy_string(hint, ast_get_extension_app(e), hintsize);
5369  if (name) {
5370  const char *tmp = ast_get_extension_app_data(e);
5371  if (tmp)
5372  ast_copy_string(name, tmp, namesize);
5373  }
5374  return -1;
5375  }
5376  return 0;
5377 }
5378 
5379 /*! \brief Get hint for channel */
5380 int ast_str_get_hint(struct ast_str **hint, ssize_t hintsize, struct ast_str **name, ssize_t namesize, struct ast_channel *c, const char *context, const char *exten)
5381 {
5382  struct ast_exten *e = ast_hint_extension(c, context, exten);
5383 
5384  if (!e) {
5385  return 0;
5386  }
5387 
5388  if (hint) {
5389  ast_str_set(hint, hintsize, "%s", ast_get_extension_app(e));
5390  }
5391  if (name) {
5392  const char *tmp = ast_get_extension_app_data(e);
5393  if (tmp) {
5394  ast_str_set(name, namesize, "%s", tmp);
5395  }
5396  }
5397  return -1;
5398 }
5399 
5400 int ast_exists_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
5401 {
5402  return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCH, 0, 0);
5403 }
5404 
5405 int ast_findlabel_extension(struct ast_channel *c, const char *context, const char *exten, const char *label, const char *callerid)
5406 {
5407  return pbx_extension_helper(c, NULL, context, exten, 0, label, callerid, E_FINDLABEL, 0, 0);
5408 }
5409 
5410 int ast_findlabel_extension2(struct ast_channel *c, struct ast_context *con, const char *exten, const char *label, const char *callerid)
5411 {
5412  return pbx_extension_helper(c, con, NULL, exten, 0, label, callerid, E_FINDLABEL, 0, 0);
5413 }
5414 
5415 int ast_canmatch_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
5416 {
5417  return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_CANMATCH, 0, 0);
5418 }
5419 
5420 int ast_matchmore_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
5421 {
5422  return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_MATCHMORE, 0, 0);
5423 }
5424 
5425 int ast_spawn_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid, int *found, int combined_find_spawn)
5426 {
5427  return pbx_extension_helper(c, NULL, context, exten, priority, NULL, callerid, E_SPAWN, found, combined_find_spawn);
5428 }
5429 
5430 /*! helper function to set extension and priority */
5431 static void set_ext_pri(struct ast_channel *c, const char *exten, int pri)
5432 {
5433  ast_channel_lock(c);
5434  ast_copy_string(c->exten, exten, sizeof(c->exten));
5435  c->priority = pri;
5436  ast_channel_unlock(c);
5437 }
5438 
5439 /*!
5440  * \brief collect digits from the channel into the buffer.
5441  * \param c, buf, buflen, pos
5442  * \param waittime is in milliseconds
5443  * \retval 0 on timeout or done.
5444  * \retval -1 on error.
5445 */
5446 static int collect_digits(struct ast_channel *c, int waittime, char *buf, int buflen, int pos)
5447 {
5448  int digit;
5449 
5450  buf[pos] = '\0'; /* make sure it is properly terminated */
5451  while (ast_matchmore_extension(c, c->context, buf, 1,
5452  S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
5453  /* As long as we're willing to wait, and as long as it's not defined,
5454  keep reading digits until we can't possibly get a right answer anymore. */
5455  digit = ast_waitfordigit(c, waittime);
5458  } else {
5459  if (!digit) /* No entry */
5460  break;
5461  if (digit < 0) /* Error, maybe a hangup */
5462  return -1;
5463  if (pos < buflen - 1) { /* XXX maybe error otherwise ? */
5464  buf[pos++] = digit;
5465  buf[pos] = '\0';
5466  }
5467  waittime = c->pbx->dtimeoutms;
5468  }
5469  }
5470  return 0;
5471 }
5472 
5474  struct ast_pbx_args *args)
5475 {
5476  int found = 0; /* set if we find at least one match */
5477  int res = 0;
5478  int autoloopflag;
5479  int error = 0; /* set an error conditions */
5480 
5481  /* A little initial setup here */
5482  if (c->pbx) {
5483  ast_log(LOG_WARNING, "%s already has PBX structure??\n", c->name);
5484  /* XXX and now what ? */
5485  ast_free(c->pbx);
5486  }
5487  if (!(c->pbx = ast_calloc(1, sizeof(*c->pbx))))
5488  return -1;
5489  /* Set reasonable defaults */
5490  c->pbx->rtimeoutms = 10000;
5491  c->pbx->dtimeoutms = 5000;
5492 
5493  autoloopflag = ast_test_flag(c, AST_FLAG_IN_AUTOLOOP); /* save value to restore at the end */
5495 
5496  /* Start by trying whatever the channel is set to */
5497  if (!ast_exists_extension(c, c->context, c->exten, c->priority,
5498  S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
5499  /* If not successful fall back to 's' */
5500  ast_verb(2, "Starting %s at %s,%s,%d failed so falling back to exten 's'\n", c->name, c->context, c->exten, c->priority);
5501  /* XXX the original code used the existing priority in the call to
5502  * ast_exists_extension(), and reset it to 1 afterwards.
5503  * I believe the correct thing is to set it to 1 immediately.
5504  */
5505  set_ext_pri(c, "s", 1);
5506  if (!ast_exists_extension(c, c->context, c->exten, c->priority,
5507  S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
5508  /* JK02: And finally back to default if everything else failed */
5509  ast_verb(2, "Starting %s at %s,%s,%d still failed so falling back to context 'default'\n", c->name, c->context, c->exten, c->priority);
5510  ast_copy_string(c->context, "default", sizeof(c->context));
5511  }
5512  }
5513  ast_channel_lock(c);
5514  if (c->cdr) {
5515  /* allow CDR variables that have been collected after channel was created to be visible during call */
5516  ast_cdr_update(c);
5517  }
5518  ast_channel_unlock(c);
5519  for (;;) {
5520  char dst_exten[256]; /* buffer to accumulate digits */
5521  int pos = 0; /* XXX should check bounds */
5522  int digit = 0;
5523  int invalid = 0;
5524  int timeout = 0;
5525 
5526  /* No digits pressed yet */
5527  dst_exten[pos] = '\0';
5528 
5529  /* loop on priorities in this context/exten */
5530  while (!(res = ast_spawn_extension(c, c->context, c->exten, c->priority,
5531  S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL),
5532  &found, 1))) {
5533  if (!ast_check_hangup(c)) {
5534  ++c->priority;
5535  continue;
5536  }
5537 
5538  /* Check softhangup flags. */
5541  continue;
5542  }
5544  if (ast_exists_extension(c, c->context, "T", 1,
5545  S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
5546  set_ext_pri(c, "T", 1);
5547  /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
5548  memset(&c->whentohangup, 0, sizeof(c->whentohangup));
5550  continue;
5551  } else if (ast_exists_extension(c, c->context, "e", 1,
5552  S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
5553  raise_exception(c, "ABSOLUTETIMEOUT", 1);
5554  /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
5555  memset(&c->whentohangup, 0, sizeof(c->whentohangup));
5557  continue;
5558  }
5559 
5560  /* Call timed out with no special extension to jump to. */
5561  error = 1;
5562  break;
5563  }
5564  ast_debug(1, "Extension %s, priority %d returned normally even though call was hung up\n",
5565  c->exten, c->priority);
5566  error = 1;
5567  break;
5568  } /* end while - from here on we can use 'break' to go out */
5569  if (found && res) {
5570  /* Something bad happened, or a hangup has been requested. */
5571  if (strchr("0123456789ABCDEF*#", res)) {
5572  ast_debug(1, "Oooh, got something to jump out with ('%c')!\n", res);
5573  pos = 0;
5574  dst_exten[pos++] = digit = res;
5575  dst_exten[pos] = '\0';
5576  } else if (res == AST_PBX_INCOMPLETE) {
5577  ast_debug(1, "Spawn extension (%s,%s,%d) exited INCOMPLETE on '%s'\n", c->context, c->exten, c->priority, c->name);
5578  ast_verb(2, "Spawn extension (%s, %s, %d) exited INCOMPLETE on '%s'\n", c->context, c->exten, c->priority, c->name);
5579 
5580  /* Don't cycle on incomplete - this will happen if the only extension that matches is our "incomplete" extension */
5581  if (!ast_matchmore_extension(c, c->context, c->exten, 1,
5582  S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
5583  invalid = 1;
5584  } else {
5585  ast_copy_string(dst_exten, c->exten, sizeof(dst_exten));
5586  digit = 1;
5587  pos = strlen(dst_exten);
5588  }
5589  } else {
5590  ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
5591  ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
5592 
5593  if ((res == AST_PBX_ERROR)
5594  && ast_exists_extension(c, c->context, "e", 1,
5595  S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
5596  /* if we are already on the 'e' exten, don't jump to it again */
5597  if (!strcmp(c->exten, "e")) {
5598  ast_verb(2, "Spawn extension (%s, %s, %d) exited ERROR while already on 'e' exten on '%s'\n", c->context, c->exten, c->priority, c->name);
5599  error = 1;
5600  } else {
5601  raise_exception(c, "ERROR", 1);
5602  continue;
5603  }
5604  }
5605 
5608  continue;
5609  }
5611  if (ast_exists_extension(c, c->context, "T", 1,
5612  S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
5613  set_ext_pri(c, "T", 1);
5614  /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
5615  memset(&c->whentohangup, 0, sizeof(c->whentohangup));
5617  continue;
5618  } else if (ast_exists_extension(c, c->context, "e", 1,
5619  S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
5620  raise_exception(c, "ABSOLUTETIMEOUT", 1);
5621  /* If the AbsoluteTimeout is not reset to 0, we'll get an infinite loop */
5622  memset(&c->whentohangup, 0, sizeof(c->whentohangup));
5624  continue;
5625  }
5626  /* Call timed out with no special extension to jump to. */
5627  }
5628  ast_channel_lock(c);
5629  if (c->cdr) {
5630  ast_cdr_update(c);
5631  }
5632  ast_channel_unlock(c);
5633  error = 1;
5634  break;
5635  }
5636  }
5637  if (error)
5638  break;
5639 
5640  /*!\note
5641  * We get here on a failure of some kind: non-existing extension or
5642  * hangup. We have options, here. We can either catch the failure
5643  * and continue, or we can drop out entirely. */
5644 
5645  if (invalid
5646  || (ast_strlen_zero(dst_exten) &&
5647  !ast_exists_extension(c, c->context, c->exten, 1,
5648  S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL)))) {
5649  /*!\note
5650  * If there is no match at priority 1, it is not a valid extension anymore.
5651  * Try to continue at "i" (for invalid) or "e" (for exception) or exit if
5652  * neither exist.
5653  */
5654  if (ast_exists_extension(c, c->context, "i", 1,
5655  S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
5656  ast_verb(3, "Sent into invalid extension '%s' in context '%s' on %s\n", c->exten, c->context, c->name);
5657  pbx_builtin_setvar_helper(c, "INVALID_EXTEN", c->exten);
5658  set_ext_pri(c, "i", 1);
5659  } else if (ast_exists_extension(c, c->context, "e", 1,
5660  S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
5661  raise_exception(c, "INVALID", 1);
5662  } else {
5663  ast_log(LOG_WARNING, "Channel '%s' sent into invalid extension '%s' in context '%s', but no invalid handler\n",
5664  c->name, c->exten, c->context);
5665  error = 1; /* we know what to do with it */
5666  break;
5667  }
5668  } else if (c->_softhangup & AST_SOFTHANGUP_TIMEOUT) {
5669  /* If we get this far with AST_SOFTHANGUP_TIMEOUT, then we know that the "T" extension is next. */
5671  } else { /* keypress received, get more digits for a full extension */
5672  int waittime = 0;
5673  if (digit)
5674  waittime = c->pbx->dtimeoutms;
5675  else if (!autofallthrough)
5676  waittime = c->pbx->rtimeoutms;
5677  if (!waittime) {
5678  const char *status = pbx_builtin_getvar_helper(c, "DIALSTATUS");
5679  if (!status)
5680  status = "UNKNOWN";
5681  ast_verb(3, "Auto fallthrough, channel '%s' status is '%s'\n", c->name, status);
5682  if (!strcasecmp(status, "CONGESTION"))
5683  res = pbx_builtin_congestion(c, "10");
5684  else if (!strcasecmp(status, "CHANUNAVAIL"))
5685  res = pbx_builtin_congestion(c, "10");
5686  else if (!strcasecmp(status, "BUSY"))
5687  res = pbx_builtin_busy(c, "10");
5688  error = 1; /* XXX disable message */
5689  break; /* exit from the 'for' loop */
5690  }
5691 
5692  if (collect_digits(c, waittime, dst_exten, sizeof(dst_exten), pos))
5693  break;
5694  if (res == AST_PBX_INCOMPLETE && ast_strlen_zero(&dst_exten[pos]))
5695  timeout = 1;
5696  if (!timeout
5697  && ast_exists_extension(c, c->context, dst_exten, 1,
5698  S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) { /* Prepare the next cycle */
5699  set_ext_pri(c, dst_exten, 1);
5700  } else {
5701  /* No such extension */
5702  if (!timeout && !ast_strlen_zero(dst_exten)) {
5703  /* An invalid extension */
5704  if (ast_exists_extension(c, c->context, "i", 1,
5705  S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
5706  ast_verb(3, "Invalid extension '%s' in context '%s' on %s\n", dst_exten, c->context, c->name);
5707  pbx_builtin_setvar_helper(c, "INVALID_EXTEN", dst_exten);
5708  set_ext_pri(c, "i", 1);
5709  } else if (ast_exists_extension(c, c->context, "e", 1,
5710  S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
5711  raise_exception(c, "INVALID", 1);
5712  } else {
5714  "Invalid extension '%s', but no rule 'i' or 'e' in context '%s'\n",
5715  dst_exten, c->context);
5716  found = 1; /* XXX disable message */
5717  break;
5718  }
5719  } else {
5720  /* A simple timeout */
5721  if (ast_exists_extension(c, c->context, "t", 1,
5722  S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
5723  ast_verb(3, "Timeout on %s\n", c->name);
5724  set_ext_pri(c, "t", 1);
5725  } else if (ast_exists_extension(c, c->context, "e", 1,
5726  S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
5727  raise_exception(c, "RESPONSETIMEOUT", 1);
5728  } else {
5730  "Timeout, but no rule 't' or 'e' in context '%s'\n",
5731  c->context);
5732  found = 1; /* XXX disable message */
5733  break;
5734  }
5735  }
5736  }
5737  ast_channel_lock(c);
5738  if (c->cdr) {
5739  ast_verb(2, "CDR updated on %s\n",c->name);
5740  ast_cdr_update(c);
5741  }
5742  ast_channel_unlock(c);
5743  }
5744  }
5745 
5746  if (!found && !error) {
5747  ast_log(LOG_WARNING, "Don't know what to do with '%s'\n", c->name);
5748  }
5749 
5750  if (!args || !args->no_hangup_chan) {
5752  }
5753 
5754  if ((!args || !args->no_hangup_chan)
5756  && ast_exists_extension(c, c->context, "h", 1,
5757  S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL))) {
5758  set_ext_pri(c, "h", 1);
5759  if (c->cdr && ast_opt_end_cdr_before_h_exten) {
5760  ast_cdr_end(c->cdr);
5761  }
5762  while ((res = ast_spawn_extension(c, c->context, c->exten, c->priority,
5763  S_COR(c->caller.id.number.valid, c->caller.id.number.str, NULL),
5764  &found, 1)) == 0) {
5765  c->priority++;
5766  }
5767  if (found && res) {
5768  /* Something bad happened, or a hangup has been requested. */
5769  ast_debug(1, "Spawn extension (%s,%s,%d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
5770  ast_verb(2, "Spawn extension (%s, %s, %d) exited non-zero on '%s'\n", c->context, c->exten, c->priority, c->name);
5771  }
5772  }
5773  ast_set2_flag(c, autoloopflag, AST_FLAG_IN_AUTOLOOP);
5774  ast_clear_flag(c, AST_FLAG_BRIDGE_HANGUP_RUN); /* from one round to the next, make sure this gets cleared */
5775  pbx_destroy(c->pbx);
5776  c->pbx = NULL;
5777 
5778  if (!args || !args->no_hangup_chan) {
5779  ast_hangup(c);
5780  }
5781 
5782  return 0;
5783 }
5784 
5785 /*!
5786  * \brief Increase call count for channel
5787  * \retval 0 on success
5788  * \retval non-zero if a configured limit (maxcalls, maxload, minmemfree) was reached
5789 */
5790 static int increase_call_count(const struct ast_channel *c)
5791 {
5792  int failed = 0;
5793  double curloadavg;
5794 #if defined(HAVE_SYSINFO)
5795  long curfreemem;
5796  struct sysinfo sys_info;
5797 #endif
5798 
5800  if (option_maxcalls) {
5801  if (countcalls >= option_maxcalls) {
5802  ast_log(LOG_WARNING, "Maximum call limit of %d calls exceeded by '%s'!\n", option_maxcalls, c->name);
5803  failed = -1;
5804  }
5805  }
5806  if (option_maxload) {
5807  getloadavg(&curloadavg, 1);
5808  if (curloadavg >= option_maxload) {
5809  ast_log(LOG_WARNING, "Maximum loadavg limit of %f load exceeded by '%s' (currently %f)!\n", option_maxload, c->name, curloadavg);
5810  failed = -1;
5811  }
5812  }
5813 #if defined(HAVE_SYSINFO)
5814  if (option_minmemfree) {
5815  if (!sysinfo(&sys_info)) {
5816  /* make sure that the free system memory is above the configured low watermark
5817  * convert the amount of freeram from mem_units to MB */
5818  curfreemem = sys_info.freeram * sys_info.mem_unit;
5819  curfreemem /= 1024 * 1024;
5820  if (curfreemem < option_minmemfree) {
5821  ast_log(LOG_WARNING, "Available system memory (~%ldMB) is below the configured low watermark (%ldMB)\n", curfreemem, option_minmemfree);
5822  failed = -1;
5823  }
5824  }
5825  }
5826 #endif
5827 
5828  if (!failed) {
5829  countcalls++;
5830  totalcalls++;
5831  }
5833 
5834  return failed;
5835 }
5836 
5837 static void decrease_call_count(void)
5838 {
5840  if (countcalls > 0)
5841  countcalls--;
5843 }
5844 
5845 static void destroy_exten(struct ast_exten *e)
5846 {
5847  if (e->priority == PRIORITY_HINT)
5848  ast_remove_hint(e);
5849 
5850  if (e->peer_table)
5852  if (e->peer_label_table)
5854  if (e->datad)
5855  e->datad(e->data);
5856  ast_free(e);
5857 }
5858 
5859 static void *pbx_thread(void *data)
5860 {
5861  /* Oh joyeous kernel, we're a new thread, with nothing to do but
5862  answer this channel and get it going.
5863  */
5864  /* NOTE:
5865  The launcher of this function _MUST_ increment 'countcalls'
5866  before invoking the function; it will be decremented when the
5867  PBX has finished running on the channel
5868  */
5869  struct ast_channel *c = data;
5870 
5871  __ast_pbx_run(c, NULL);
5873 
5874  pthread_exit(NULL);
5875 
5876  return NULL;
5877 }
5878 
5880 {
5881  pthread_t t;
5882 
5883  if (!c) {
5884  ast_log(LOG_WARNING, "Asked to start thread on NULL channel?\n");
5885  return AST_PBX_FAILED;
5886  }
5887 
5889  ast_log(LOG_WARNING, "PBX requires Asterisk to be fully booted\n");
5890  return AST_PBX_FAILED;
5891  }
5892 
5893  if (increase_call_count(c))
5894  return AST_PBX_CALL_LIMIT;
5895 
5896  /* Start a new thread, and get something handling this channel. */
5897  if (ast_pthread_create_detached(&t, NULL, pbx_thread, c)) {
5898  ast_log(LOG_WARNING, "Failed to create new channel thread\n");
5900  return AST_PBX_FAILED;
5901  }
5902 
5903  return AST_PBX_SUCCESS;
5904 }
5905 
5907 {
5908  enum ast_pbx_result res = AST_PBX_SUCCESS;
5909 
5911  ast_log(LOG_WARNING, "PBX requires Asterisk to be fully booted\n");
5912  return AST_PBX_FAILED;
5913  }
5914 
5915  if (increase_call_count(c)) {
5916  return AST_PBX_CALL_LIMIT;
5917  }
5918 
5919  res = __ast_pbx_run(c, args);
5920 
5922 
5923  return res;
5924 }
5925 
5927 {
5928  return ast_pbx_run_args(c, NULL);
5929 }
5930 
5932 {
5933  return countcalls;
5934 }
5935 
5937 {
5938  return totalcalls;
5939 }
5940 
5942 {
5943  int oldval = autofallthrough;
5944  autofallthrough = newval;
5945  return oldval;
5946 }
5947 
5949 {
5950  int oldval = extenpatternmatchnew;
5951  extenpatternmatchnew = newval;
5952  return oldval;
5953 }
5954 
5955 void pbx_set_overrideswitch(const char *newval)
5956 {
5957  if (overrideswitch) {
5959  }
5960  if (!ast_strlen_zero(newval)) {
5961  overrideswitch = ast_strdup(newval);
5962  } else {
5963  overrideswitch = NULL;
5964  }
5965 }
5966 
5967 /*!
5968  * \brief lookup for a context with a given name,
5969  * \retval found context or NULL if not found.
5970  */
5971 static struct ast_context *find_context(const char *context)
5972 {
5973  struct fake_context item;
5974 
5975  ast_copy_string(item.name, context, sizeof(item.name));
5976 
5977  return ast_hashtab_lookup(contexts_table, &item);
5978 }
5979 
5980 /*!
5981  * \brief lookup for a context with a given name,
5982  * \retval with conlock held if found.
5983  * \retval NULL if not found.
5984  */
5985 static struct ast_context *find_context_locked(const char *context)
5986 {
5987  struct ast_context *c;
5988  struct fake_context item;
5989 
5990  ast_copy_string(item.name, context, sizeof(item.name));
5991 
5993  c = ast_hashtab_lookup(contexts_table, &item);
5994  if (!c) {
5996  }
5997 
5998  return c;
5999 }
6000 
6001 /*!
6002  * \brief Remove included contexts.
6003  * This function locks contexts list by &conlist, search for the right context
6004  * structure, leave context list locked and call ast_context_remove_include2
6005  * which removes include, unlock contexts list and return ...
6006  */
6007 int ast_context_remove_include(const char *context, const char *include, const char *registrar)
6008 {
6009  int ret = -1;
6010  struct ast_context *c;
6011 
6012  c = find_context_locked(context);
6013  if (c) {
6014  /* found, remove include from this context ... */
6015  ret = ast_context_remove_include2(c, include, registrar);
6017  }
6018  return ret;
6019 }
6020 
6021 /*!
6022  * \brief Locks context, remove included contexts, unlocks context.
6023  * When we call this function, &conlock lock must be locked, because when
6024  * we giving *con argument, some process can remove/change this context
6025  * and after that there can be segfault.
6026  *
6027  * \retval 0 on success.
6028  * \retval -1 on failure.
6029  */
6030 int ast_context_remove_include2(struct ast_context *con, const char *include, const char *registrar)
6031 {
6032  struct ast_include *i, *pi = NULL;
6033  int ret = -1;
6034 
6035  ast_wrlock_context(con);
6036 
6037  /* find our include */
6038  for (i = con->includes; i; pi = i, i = i->next) {
6039  if (!strcmp(i->name, include) &&
6040  (!registrar || !strcmp(i->registrar, registrar))) {
6041  /* remove from list */
6042  ast_verb(3, "Removing inclusion of context '%s' in context '%s; registrar=%s'\n", include, ast_get_context_name(con), registrar);
6043  if (pi)
6044  pi->next = i->next;
6045  else
6046  con->includes = i->next;
6047  /* free include and return */
6048  ast_destroy_timing(&(i->timing));
6049  ast_free(i);
6050  ret = 0;
6051  break;
6052  }
6053  }
6054 
6055  ast_unlock_context(con);
6056 
6057  return ret;
6058 }
6059 
6060 /*!
6061  * \note This function locks contexts list by &conlist, search for the rigt context
6062  * structure, leave context list locked and call ast_context_remove_switch2
6063  * which removes switch, unlock contexts list and return ...
6064  */
6065 int ast_context_remove_switch(const char *context, const char *sw, const char *data, const char *registrar)
6066 {
6067  int ret = -1; /* default error return */
6068  struct ast_context *c;
6069 
6070  c = find_context_locked(context);
6071  if (c) {
6072  /* remove switch from this context ... */
6073  ret = ast_context_remove_switch2(c, sw, data, registrar);
6075  }
6076  return ret;
6077 }
6078 
6079 /*!
6080  * \brief This function locks given context, removes switch, unlock context and
6081  * return.
6082  * \note When we call this function, &conlock lock must be locked, because when
6083  * we giving *con argument, some process can remove/change this context
6084  * and after that there can be segfault.
6085  *
6086  */
6087 int ast_context_remove_switch2(struct ast_context *con, const char *sw, const char *data, const char *registrar)
6088 {
6089  struct ast_sw *i;
6090  int ret = -1;
6091 
6092  ast_wrlock_context(con);
6093 
6094  /* walk switches */
6095  AST_LIST_TRAVERSE_SAFE_BEGIN(&con->alts, i, list) {
6096  if (!strcmp(i->name, sw) && !strcmp(i->data, data) &&
6097  (!registrar || !strcmp(i->registrar, registrar))) {
6098  /* found, remove from list */
6099  ast_verb(3, "Removing switch '%s' from context '%s; registrar=%s'\n", sw, ast_get_context_name(con), registrar);
6101  ast_free(i); /* free switch and return */
6102  ret = 0;
6103  break;
6104  }
6105  }
6107 
6108  ast_unlock_context(con);
6109 
6110  return ret;
6111 }
6112 
6113 /*! \note This function will lock conlock. */
6114 int ast_context_remove_extension(const char *context, const char *extension, int priority, const char *registrar)
6115 {
6116  return ast_context_remove_extension_callerid(context, extension, priority, NULL, AST_EXT_MATCHCID_ANY, registrar);
6117 }
6118 
6119 int ast_context_remove_extension_callerid(const char *context, const char *extension, int priority, const char *callerid, int matchcallerid, const char *registrar)
6120 {
6121  int ret = -1; /* default error return */
6122  struct ast_context *c;
6123 
6124  c = find_context_locked(context);
6125  if (c) { /* ... remove extension ... */
6126  ret = ast_context_remove_extension_callerid2(c, extension, priority, callerid,
6127  matchcallerid, registrar, 0);
6129  }
6130 
6131  return ret;
6132 }
6133 
6134 /*!
6135  * \brief This functionc locks given context, search for the right extension and
6136  * fires out all peer in this extensions with given priority. If priority
6137  * is set to 0, all peers are removed. After that, unlock context and
6138  * return.
6139  * \note When do you want to call this function, make sure that &conlock is locked,
6140  * because some process can handle with your *con context before you lock
6141  * it.
6142  *
6143  */
6144 int ast_context_remove_extension2(struct ast_context *con, const char *extension, int priority, const char *registrar, int already_locked)
6145 {
6146  return ast_context_remove_extension_callerid2(con, extension, priority, NULL, AST_EXT_MATCHCID_ANY, registrar, already_locked);
6147 }
6148 
6149 int ast_context_remove_extension_callerid2(struct ast_context *con, const char *extension, int priority, const char *callerid, int matchcallerid, const char *registrar, int already_locked)
6150 {
6151  struct ast_exten *exten, *prev_exten = NULL;
6152  struct ast_exten *peer;
6153  struct ast_exten ex, *exten2, *exten3;
6154  char dummy_name[1024];
6155  struct ast_exten *previous_peer = NULL;
6156  struct ast_exten *next_peer = NULL;
6157  int found = 0;
6158 
6159  if (!already_locked)
6160  ast_wrlock_context(con);
6161 
6162 #ifdef NEED_DEBUG
6163  ast_verb(3,"Removing %s/%s/%d%s%s from trees, registrar=%s\n", con->name, extension, priority, matchcallerid ? "/" : "", matchcallerid ? callerid : "", registrar);
6164 #endif
6165 #ifdef CONTEXT_DEBUG
6166  check_contexts(__FILE__, __LINE__);
6167 #endif
6168  /* find this particular extension */
6169  ex.exten = dummy_name;
6170  ex.matchcid = matchcallerid;
6171  ex.cidmatch = callerid;
6172  ast_copy_string(dummy_name, extension, sizeof(dummy_name));
6173  exten = ast_hashtab_lookup(con->root_table, &ex);
6174  if (exten) {
6175  if (priority == 0) {
6176  exten2 = ast_hashtab_remove_this_object(con->root_table, exten);
6177  if (!exten2)
6178  ast_log(LOG_ERROR,"Trying to delete the exten %s from context %s, but could not remove from the root_table\n", extension, con->name);
6179  if (con->pattern_tree) {
6180  struct match_char *x = add_exten_to_pattern_tree(con, exten, 1);
6181 
6182  if (x->exten) { /* this test for safety purposes */
6183  x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */
6184  x->exten = 0; /* get rid of what will become a bad pointer */
6185  } else {
6186  ast_log(LOG_WARNING,"Trying to delete an exten from a context, but the pattern tree node returned isn't a full extension\n");
6187  }
6188  }
6189  } else {
6190  ex.priority = priority;
6191  exten2 = ast_hashtab_lookup(exten->peer_table, &ex);
6192  if (exten2) {
6193  if (exten2->label) { /* if this exten has a label, remove that, too */
6194  exten3 = ast_hashtab_remove_this_object(exten->peer_label_table,exten2);
6195  if (!exten3)
6196  ast_log(LOG_ERROR,"Did not remove this priority label (%d/%s) from the peer_label_table of context %s, extension %s!\n", priority, exten2->label, con->name, exten2->exten);
6197  }
6198 
6199  exten3 = ast_hashtab_remove_this_object(exten->peer_table, exten2);
6200  if (!exten3)
6201  ast_log(LOG_ERROR,"Did not remove this priority (%d) from the peer_table of context %s, extension %s!\n", priority, con->name, exten2->exten);
6202  if (exten2 == exten && exten2->peer) {
6203  exten2 = ast_hashtab_remove_this_object(con->root_table, exten);
6205  }
6206  if (ast_hashtab_size(exten->peer_table) == 0) {
6207  /* well, if the last priority of an exten is to be removed,
6208  then, the extension is removed, too! */
6209  exten3 = ast_hashtab_remove_this_object(con->root_table, exten);
6210  if (!exten3)
6211  ast_log(LOG_ERROR,"Did not remove this exten (%s) from the context root_table (%s) (priority %d)\n", exten->exten, con->name, priority);
6212  if (con->pattern_tree) {
6213  struct match_char *x = add_exten_to_pattern_tree(con, exten, 1);
6214  if (x->exten) { /* this test for safety purposes */
6215  x->deleted = 1; /* with this marked as deleted, it will never show up in the scoreboard, and therefore never be found */
6216  x->exten = 0; /* get rid of what will become a bad pointer */
6217  }
6218  }
6219  }
6220  } else {
6221  ast_log(LOG_ERROR,"Could not find priority %d of exten %s in context %s!\n",
6222  priority, exten->exten, con->name);
6223  }
6224  }
6225  } else {
6226  /* hmmm? this exten is not in this pattern tree? */
6227  ast_log(LOG_WARNING,"Cannot find extension %s in root_table in context %s\n",
6228  extension, con->name);
6229  }
6230 #ifdef NEED_DEBUG
6231  if (con->pattern_tree) {
6232  ast_log(LOG_NOTICE,"match char tree after exten removal:\n");
6233  log_match_char_tree(con->pattern_tree, " ");
6234  }
6235 #endif
6236 
6237  /* scan the extension list to find first matching extension-registrar */
6238  for (exten = con->root; exten; prev_exten = exten, exten = exten->next) {
6239  if (!strcmp(exten->exten, extension) &&
6240  (!registrar || !strcmp(exten->registrar, registrar)) &&
6241  (!matchcallerid || (!ast_strlen_zero(callerid) && !ast_strlen_zero(exten->cidmatch) && !strcmp(exten->cidmatch, callerid)) || (ast_strlen_zero(callerid) && ast_strlen_zero(exten->cidmatch))))
6242  break;
6243  }
6244  if (!exten) {
6245  /* we can't find right extension */
6246  if (!already_locked)
6247  ast_unlock_context(con);
6248  return -1;
6249  }
6250 
6251  /* scan the priority list to remove extension with exten->priority == priority */
6252  for (peer = exten, next_peer = exten->peer ? exten->peer : exten->next;
6253  peer && !strcmp(peer->exten, extension) &&
6254  (!callerid || (!matchcallerid && !peer->matchcid) || (matchcallerid && peer->matchcid && !strcmp(peer->cidmatch, callerid))) ;
6255  peer = next_peer, next_peer = next_peer ? (next_peer->peer ? next_peer->peer : next_peer->next) : NULL) {
6256 
6257  if ((priority == 0 || peer->priority == priority) &&
6258  (!registrar || !strcmp(peer->registrar, registrar) )) {
6259  found = 1;
6260 
6261  /* we are first priority extension? */
6262  if (!previous_peer) {
6263  /*
6264  * We are first in the priority chain, so must update the extension chain.
6265  * The next node is either the next priority or the next extension
6266  */
6267  struct ast_exten *next_node = peer->peer ? peer->peer : peer->next;
6268  if (peer->peer) {
6269  /* move the peer_table and peer_label_table down to the next peer, if
6270  it is there */
6271  peer->peer->peer_table = peer->peer_table;
6272  peer->peer->peer_label_table = peer->peer_label_table;
6273  peer->peer_table = NULL;
6274  peer->peer_label_table = NULL;
6275  }
6276  if (!prev_exten) { /* change the root... */
6277  con->root = next_node;
6278  } else {
6279  prev_exten->next = next_node; /* unlink */
6280  }
6281  if (peer->peer) { /* update the new head of the pri list */
6282  peer->peer->next = peer->next;
6283  }
6284  } else { /* easy, we are not first priority in extension */
6285  previous_peer->peer = peer->peer;
6286  }
6287 
6288 
6289  /* now, free whole priority extension */
6290  destroy_exten(peer);
6291  } else {
6292  previous_peer = peer;
6293  }
6294  }
6295  if (!already_locked)
6296  ast_unlock_context(con);
6297  return found ? 0 : -1;
6298 }
6299 
6300 
6301 /*!
6302  * \note This function locks contexts list by &conlist, searches for the right context
6303  * structure, and locks the macrolock mutex in that context.
6304  * macrolock is used to limit a macro to be executed by one call at a time.
6305  */
6306 int ast_context_lockmacro(const char *context)
6307 {
6308  struct ast_context *c;
6309  int ret = -1;
6310 
6311  c = find_context_locked(context);
6312  if (c) {
6314 
6315  /* if we found context, lock macrolock */
6316  ret = ast_mutex_lock(&c->macrolock);
6317  }
6318 
6319  return ret;
6320 }
6321 
6322 /*!
6323  * \note This function locks contexts list by &conlist, searches for the right context
6324  * structure, and unlocks the macrolock mutex in that context.
6325  * macrolock is used to limit a macro to be executed by one call at a time.
6326  */
6327 int ast_context_unlockmacro(const char *context)
6328 {
6329  struct ast_context *c;
6330  int ret = -1;
6331 
6332  c = find_context_locked(context);
6333  if (c) {
6335 
6336  /* if we found context, unlock macrolock */
6337  ret = ast_mutex_unlock(&c->macrolock);
6338  }
6339 
6340  return ret;
6341 }
6342 
6343 /*! \brief Dynamically register a new dial plan application */
6344 int ast_register_application2(const char *app, int (*execute)(struct ast_channel *, const char *), const char *synopsis, const char *description, void *mod)
6345 {
6346  struct ast_app *tmp, *cur = NULL;
6347  char tmps[80];
6348  int length, res;
6349 #ifdef AST_XML_DOCS
6350  char *tmpxml;
6351 #endif
6352 
6354  AST_RWLIST_TRAVERSE(&apps, tmp, list) {
6355  if (!(res = strcasecmp(app, tmp->name))) {
6356  ast_log(LOG_WARNING, "Already have an application '%s'\n", app);
6358  return -1;
6359  } else if (res < 0)
6360  break;
6361  }
6362 
6363  length = sizeof(*tmp) + strlen(app) + 1;
6364 
6365  if (!(tmp = ast_calloc(1, length))) {
6367  return -1;
6368  }
6369 
6370  if (ast_string_field_init(tmp, 128)) {
6372  ast_free(tmp);
6373  return -1;
6374  }
6375 
6376  strcpy(tmp->name, app);
6377  tmp->execute = execute;
6378  tmp->module = mod;
6379 
6380 #ifdef AST_XML_DOCS
6381  /* Try to lookup the docs in our XML documentation database */
6382  if (ast_strlen_zero(synopsis) && ast_strlen_zero(description)) {
6383  /* load synopsis */
6384  tmpxml = ast_xmldoc_build_synopsis("application", app, ast_module_name(tmp->module));
6385  ast_string_field_set(tmp, synopsis, tmpxml);
6386  ast_free(tmpxml);
6387 
6388  /* load description */
6389  tmpxml = ast_xmldoc_build_description("application", app, ast_module_name(tmp->module));
6390  ast_string_field_set(tmp, description, tmpxml);
6391  ast_free(tmpxml);
6392 
6393  /* load syntax */
6394  tmpxml = ast_xmldoc_build_syntax("application", app, ast_module_name(tmp->module));
6395  ast_string_field_set(tmp, syntax, tmpxml);
6396  ast_free(tmpxml);
6397 
6398  /* load arguments */
6399  tmpxml = ast_xmldoc_build_arguments("application", app, ast_module_name(tmp->module));
6400  ast_string_field_set(tmp, arguments, tmpxml);
6401  ast_free(tmpxml);
6402 
6403  /* load seealso */
6404  tmpxml = ast_xmldoc_build_seealso("application", app, ast_module_name(tmp->module));
6405  ast_string_field_set(tmp, seealso, tmpxml);
6406  ast_free(tmpxml);
6407  tmp->docsrc = AST_XML_DOC;
6408  } else {
6409 #endif
6410  ast_string_field_set(tmp, synopsis, synopsis);
6411  ast_string_field_set(tmp, description, description);
6412 #ifdef AST_XML_DOCS
6413  tmp->docsrc = AST_STATIC_DOC;
6414  }
6415 #endif
6416 
6417  /* Store in alphabetical order */
6418  AST_RWLIST_TRAVERSE_SAFE_BEGIN(&apps, cur, list) {
6419  if (strcasecmp(tmp->name, cur->name) < 0) {
6421  break;
6422  }
6423  }
6425  if (!cur)
6426  AST_RWLIST_INSERT_TAIL(&apps, tmp, list);
6427 
6428  ast_verb(2, "Registered application '%s'\n", term_color(tmps, tmp->name, COLOR_BRCYAN, 0, sizeof(tmps)));
6429 
6431 
6432  return 0;
6433 }
6434 
6435 /*
6436  * Append to the list. We don't have a tail pointer because we need
6437  * to scan the list anyways to check for duplicates during insertion.
6438  */
6440 {
6441  struct ast_switch *tmp;
6442 
6444  AST_RWLIST_TRAVERSE(&switches, tmp, list) {
6445  if (!strcasecmp(tmp->name, sw->name)) {
6447  ast_log(LOG_WARNING, "Switch '%s' already found\n", sw->name);
6448  return -1;
6449  }
6450  }
6451  AST_RWLIST_INSERT_TAIL(&switches, sw, list);
6453 
6454  return 0;
6455 }
6456 
6458 {
6460  AST_RWLIST_REMOVE(&switches, sw, list);
6462 }
6463 
6464 /*
6465  * Help for CLI commands ...
6466  */
6467 
6468 static void print_app_docs(struct ast_app *aa, int fd)
6469 {
6470  /* Maximum number of characters added by terminal coloring is 22 */
6471  char infotitle[64 + AST_MAX_APP + 22], syntitle[40], destitle[40], stxtitle[40], argtitle[40];
6472  char seealsotitle[40];
6473  char info[64 + AST_MAX_APP], *synopsis = NULL, *description = NULL, *syntax = NULL, *arguments = NULL;
6474  char *seealso = NULL;
6475  int syntax_size, synopsis_size, description_size, arguments_size, seealso_size;
6476 
6477  snprintf(info, sizeof(info), "\n -= Info about application '%s' =- \n\n", aa->name);
6478  term_color(infotitle, info, COLOR_MAGENTA, 0, sizeof(infotitle));
6479 
6480  term_color(syntitle, "[Synopsis]\n", COLOR_MAGENTA, 0, 40);
6481  term_color(destitle, "[Description]\n", COLOR_MAGENTA, 0, 40);
6482  term_color(stxtitle, "[Syntax]\n", COLOR_MAGENTA, 0, 40);
6483  term_color(argtitle, "[Arguments]\n", COLOR_MAGENTA, 0, 40);
6484  term_color(seealsotitle, "[See Also]\n", COLOR_MAGENTA, 0, 40);
6485 
6486 #ifdef AST_XML_DOCS
6487  if (aa->docsrc == AST_XML_DOC) {
6488  description = ast_xmldoc_printable(S_OR(aa->description, "Not available"), 1);
6489  arguments = ast_xmldoc_printable(S_OR(aa->arguments, "Not available"), 1);
6490  synopsis = ast_xmldoc_printable(S_OR(aa->synopsis, "Not available"), 1);
6491  seealso = ast_xmldoc_printable(S_OR(aa->seealso, "Not available"), 1);
6492 
6493  if (!synopsis || !description || !arguments || !seealso) {
6494  goto return_cleanup;
6495  }
6496  } else
6497 #endif
6498  {
6499  synopsis_size = strlen(S_OR(aa->synopsis, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
6500  synopsis = ast_malloc(synopsis_size);
6501 
6502  description_size = strlen(S_OR(aa->description, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
6503  description = ast_malloc(description_size);
6504 
6505  arguments_size = strlen(S_OR(aa->arguments, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
6506  arguments = ast_malloc(arguments_size);
6507 
6508  seealso_size = strlen(S_OR(aa->seealso, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
6509  seealso = ast_malloc(seealso_size);
6510 
6511  if (!synopsis || !description || !arguments || !seealso) {
6512  goto return_cleanup;
6513  }
6514 
6515  term_color(synopsis, S_OR(aa->synopsis, "Not available"), COLOR_CYAN, 0, synopsis_size);
6516  term_color(description, S_OR(aa->description, "Not available"), COLOR_CYAN, 0, description_size);
6517  term_color(arguments, S_OR(aa->arguments, "Not available"), COLOR_CYAN, 0, arguments_size);
6518  term_color(seealso, S_OR(aa->seealso, "Not available"), COLOR_CYAN, 0, seealso_size);
6519  }
6520 
6521  /* Handle the syntax the same for both XML and raw docs */
6522  syntax_size = strlen(S_OR(aa->syntax, "Not Available")) + AST_TERM_MAX_ESCAPE_CHARS;
6523  if (!(syntax = ast_malloc(syntax_size))) {
6524  goto return_cleanup;
6525  }
6526  term_color(syntax, S_OR(aa->syntax, "Not available"), COLOR_CYAN, 0, syntax_size);
6527 
6528  ast_cli(fd, "%s%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n\n%s%s\n",
6529  infotitle, syntitle, synopsis, destitle, description,
6530  stxtitle, syntax, argtitle, arguments, seealsotitle, seealso);
6531 
6532 return_cleanup:
6533  ast_free(description);
6534  ast_free(arguments);
6535  ast_free(synopsis);
6536  ast_free(seealso);
6537  ast_free(syntax);
6538 }
6539 
6540 /*
6541  * \brief 'show application' CLI command implementation function...
6542  */
6543 static char *handle_show_application(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
6544 {
6545  struct ast_app *aa;
6546  int app, no_registered_app = 1;
6547 
6548  switch (cmd) {
6549  case CLI_INIT:
6550  e->command = "core show application";
6551  e->usage =
6552  "Usage: core show application <application> [<application> [<application> [...]]]\n"
6553  " Describes a particular application.\n";
6554  return NULL;
6555  case CLI_GENERATE:
6556  /*
6557  * There is a possibility to show informations about more than one
6558  * application at one time. You can type 'show application Dial Echo' and
6559  * you will see informations about these two applications ...
6560  */
6561  return ast_complete_applications(a->line, a->word, a->n);
6562  }
6563 
6564  if (a->argc < 4) {
6565  return CLI_SHOWUSAGE;
6566  }
6567 
6569  AST_RWLIST_TRAVERSE(&apps, aa, list) {
6570  /* Check for each app that was supplied as an argument */
6571  for (app = 3; app < a->argc; app++) {
6572  if (strcasecmp(aa->name, a->argv[app])) {
6573  continue;
6574  }
6575 
6576  /* We found it! */
6577  no_registered_app = 0;
6578 
6579  print_app_docs(aa, a->fd);
6580  }
6581  }
6583 
6584  /* we found at least one app? no? */
6585  if (no_registered_app) {
6586  ast_cli(a->fd, "Your application(s) is (are) not registered\n");
6587  return CLI_FAILURE;
6588  }
6589 
6590  return CLI_SUCCESS;
6591 }
6592 
6593 /*! \brief handle_show_hints: CLI support for listing registered dial plan hints */
6594 static char *handle_show_hints(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
6595 {
6596  struct ast_hint *hint;
6597  int num = 0;
6598  int watchers;
6599  struct ao2_iterator i;
6600 
6601  switch (cmd) {
6602  case CLI_INIT:
6603  e->command = "core show hints";
6604  e->usage =
6605  "Usage: core show hints\n"
6606  " List registered hints.\n"
6607  " Hint details are shown in four columns. In order from left to right, they are:\n"
6608  " 1. Hint extension URI.\n"
6609  " 2. Mapped device state identifiers.\n"
6610  " 3. Current extension state. The aggregate of mapped device states.\n"
6611  " 4. Watchers - number of subscriptions and other entities watching this hint.\n";
6612  return NULL;
6613  case CLI_GENERATE:
6614  return NULL;
6615  }
6616 
6617  if (ao2_container_count(hints) == 0) {
6618  ast_cli(a->fd, "There are no registered dialplan hints\n");
6619  return CLI_SUCCESS;
6620  }
6621  /* ... we have hints ... */
6622  ast_cli(a->fd, "\n -= Registered Asterisk Dial Plan Hints =-\n");
6623 
6624  i = ao2_iterator_init(hints, 0);
6625  for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) {
6626  ao2_lock(hint);
6627  if (!hint->exten) {
6628  /* The extension has already been destroyed */
6629  ao2_unlock(hint);
6630  continue;
6631  }
6632  watchers = ao2_container_count(hint->callbacks);
6633  ast_cli(a->fd, " %20s@%-20.20s: %-20.20s State:%-15.15s Watchers %2d\n",
6637  ast_extension_state2str(hint->laststate), watchers);
6638  ao2_unlock(hint);
6639  num++;
6640  }
6642 
6643  ast_cli(a->fd, "----------------\n");
6644  ast_cli(a->fd, "- %d hints registered\n", num);
6645  return CLI_SUCCESS;
6646 }
6647 
6648 /*! \brief autocomplete for CLI command 'core show hint' */
6649 static char *complete_core_show_hint(const char *line, const char *word, int pos, int state)
6650 {
6651  struct ast_hint *hint;
6652  char *ret = NULL;
6653  int which = 0;
6654  int wordlen;
6655  struct ao2_iterator i;
6656 
6657  if (pos != 3)
6658  return NULL;
6659 
6660  wordlen = strlen(word);
6661 
6662  /* walk through all hints */
6663  i = ao2_iterator_init(hints, 0);
6664  for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) {
6665  ao2_lock(hint);
6666  if (!hint->exten) {
6667  /* The extension has already been destroyed */
6668  ao2_unlock(hint);
6669  continue;
6670  }
6671  if (!strncasecmp(word, ast_get_extension_name(hint->exten), wordlen) && ++which > state) {
6672  ret = ast_strdup(ast_get_extension_name(hint->exten));
6673  ao2_unlock(hint);
6674  ao2_ref(hint, -1);
6675  break;
6676  }
6677  ao2_unlock(hint);
6678  }
6680 
6681  return ret;
6682 }
6683 
6684 /*! \brief handle_show_hint: CLI support for listing registered dial plan hint */
6685 static char *handle_show_hint(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
6686 {
6687  struct ast_hint *hint;
6688  int watchers;
6689  int num = 0, extenlen;
6690  struct ao2_iterator i;
6691 
6692  switch (cmd) {
6693  case CLI_INIT:
6694  e->command = "core show hint";
6695  e->usage =
6696  "Usage: core show hint <exten>\n"
6697  " List registered hint.\n"
6698  " Hint details are shown in four columns. In order from left to right, they are:\n"
6699  " 1. Hint extension URI.\n"
6700  " 2. Mapped device state identifiers.\n"
6701  " 3. Current extension state. The aggregate of mapped device states.\n"
6702  " 4. Watchers - number of subscriptions and other entities watching this hint.\n";
6703 
6704  return NULL;
6705  case CLI_GENERATE:
6706  return complete_core_show_hint(a->line, a->word, a->pos, a->n);
6707  }
6708 
6709  if (a->argc < 4)
6710  return CLI_SHOWUSAGE;
6711 
6712  if (ao2_container_count(hints) == 0) {
6713  ast_cli(a->fd, "There are no registered dialplan hints\n");
6714  return CLI_SUCCESS;
6715  }
6716 
6717  extenlen = strlen(a->argv[3]);
6718  i = ao2_iterator_init(hints, 0);
6719  for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) {
6720  ao2_lock(hint);
6721  if (!hint->exten) {
6722  /* The extension has already been destroyed */
6723  ao2_unlock(hint);
6724  continue;
6725  }
6726  if (!strncasecmp(ast_get_extension_name(hint->exten), a->argv[3], extenlen)) {
6727  watchers = ao2_container_count(hint->callbacks);
6728  ast_cli(a->fd, " %20s@%-20.20s: %-20.20s State:%-15.15s Watchers %2d\n",
6732  ast_extension_state2str(hint->laststate), watchers);
6733  num++;
6734  }
6735  ao2_unlock(hint);
6736  }
6738  if (!num)
6739  ast_cli(a->fd, "No hints matching extension %s\n", a->argv[3]);
6740  else
6741  ast_cli(a->fd, "%d hint%s matching extension %s\n", num, (num!=1 ? "s":""), a->argv[3]);
6742  return CLI_SUCCESS;
6743 }
6744 
6745 
6746 /*! \brief handle_show_switches: CLI support for listing registered dial plan switches */
6747 static char *handle_show_switches(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
6748 {
6749  struct ast_switch *sw;
6750 
6751  switch (cmd) {
6752  case CLI_INIT:
6753  e->command = "core show switches";
6754  e->usage =
6755  "Usage: core show switches\n"
6756  " List registered switches\n";
6757  return NULL;
6758  case CLI_GENERATE:
6759  return NULL;
6760  }
6761 
6763 
6764  if (AST_RWLIST_EMPTY(&switches)) {
6766  ast_cli(a->fd, "There are no registered alternative switches\n");
6767  return CLI_SUCCESS;
6768  }
6769 
6770  ast_cli(a->fd, "\n -= Registered Asterisk Alternative Switches =-\n");
6771  AST_RWLIST_TRAVERSE(&switches, sw, list)
6772  ast_cli(a->fd, "%s: %s\n", sw->name, sw->description);
6773 
6775 
6776  return CLI_SUCCESS;
6777 }
6778 
6779 static char *handle_show_applications(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
6780 {
6781  struct ast_app *aa;
6782  int like = 0, describing = 0;
6783  int total_match = 0; /* Number of matches in like clause */
6784  int total_apps = 0; /* Number of apps registered */
6785  static const char * const choices[] = { "like", "describing", NULL };
6786 
6787  switch (cmd) {
6788  case CLI_INIT:
6789  e->command = "core show applications [like|describing]";
6790  e->usage =
6791  "Usage: core show applications [{like|describing} <text>]\n"
6792  " List applications which are currently available.\n"
6793  " If 'like', <text> will be a substring of the app name\n"
6794  " If 'describing', <text> will be a substring of the description\n";
6795  return NULL;
6796  case CLI_GENERATE:
6797  return (a->pos != 3) ? NULL : ast_cli_complete(a->word, choices, a->n);
6798  }
6799 
6801 
6802  if (AST_RWLIST_EMPTY(&apps)) {
6803  ast_cli(a->fd, "There are no registered applications\n");
6805  return CLI_SUCCESS;
6806  }
6807 
6808  /* core list applications like <keyword> */
6809  if ((a->argc == 5) && (!strcmp(a->argv[3], "like"))) {
6810  like = 1;
6811  } else if ((a->argc > 4) && (!strcmp(a->argv[3], "describing"))) {
6812  describing = 1;
6813  }
6814 
6815  /* core list applications describing <keyword1> [<keyword2>] [...] */
6816  if ((!like) && (!describing)) {
6817  ast_cli(a->fd, " -= Registered Asterisk Applications =-\n");
6818  } else {
6819  ast_cli(a->fd, " -= Matching Asterisk Applications =-\n");
6820  }
6821 
6822  AST_RWLIST_TRAVERSE(&apps, aa, list) {
6823  int printapp = 0;
6824  total_apps++;
6825  if (like) {
6826  if (strcasestr(aa->name, a->argv[4])) {
6827  printapp = 1;
6828  total_match++;
6829  }
6830  } else if (describing) {
6831  if (aa->description) {
6832  /* Match all words on command line */
6833  int i;
6834  printapp = 1;
6835  for (i = 4; i < a->argc; i++) {
6836  if (!strcasestr(aa->description, a->argv[i])) {
6837  printapp = 0;
6838  } else {
6839  total_match++;
6840  }
6841  }
6842  }
6843  } else {
6844  printapp = 1;
6845  }
6846 
6847  if (printapp) {
6848  ast_cli(a->fd," %20s: %s\n", aa->name, aa->synopsis ? aa->synopsis : "<Synopsis not available>");
6849  }
6850  }
6851  if ((!like) && (!describing)) {
6852  ast_cli(a->fd, " -= %d Applications Registered =-\n",total_apps);
6853  } else {
6854  ast_cli(a->fd, " -= %d Applications Matching =-\n",total_match);
6855  }
6856 
6858 
6859  return CLI_SUCCESS;
6860 }
6861 
6862 /*
6863  * 'show dialplan' CLI command implementation functions ...
6864  */
6865 static char *complete_show_dialplan_context(const char *line, const char *word, int pos,
6866  int state)
6867 {
6868  struct ast_context *c = NULL;
6869  char *ret = NULL;
6870  int which = 0;
6871  int wordlen;
6872 
6873  /* we are do completion of [exten@]context on second position only */
6874  if (pos != 2)
6875  return NULL;
6876 
6878 
6879  wordlen = strlen(word);
6880 
6881  /* walk through all contexts and return the n-th match */
6882  while ( (c = ast_walk_contexts(c)) ) {
6883  if (!strncasecmp(word, ast_get_context_name(c), wordlen) && ++which > state) {
6884  ret = ast_strdup(ast_get_context_name(c));
6885  break;
6886  }
6887  }
6888 
6890 
6891  return ret;
6892 }
6893 
6894 /*! \brief Counters for the show dialplan manager command */
6902 };
6903 
6904 /*! \brief helper function to print an extension */
6905 static void print_ext(struct ast_exten *e, char * buf, int buflen)
6906 {
6907  int prio = ast_get_extension_priority(e);
6908  if (prio == PRIORITY_HINT) {
6909  snprintf(buf, buflen, "hint: %s",
6911  } else {
6912  snprintf(buf, buflen, "%d. %s(%s)",
6913  prio, ast_get_extension_app(e),
6915  }
6916 }
6917 
6918 /* XXX not verified */
6919 static int show_dialplan_helper(int fd, const char *context, const char *exten, struct dialplan_counters *dpc, struct ast_include *rinclude, int includecount, const char *includes[])
6920 {
6921  struct ast_context *c = NULL;
6922  int res = 0, old_total_exten = dpc->total_exten;
6923 
6925 
6926  /* walk all contexts ... */
6927  while ( (c = ast_walk_contexts(c)) ) {
6928  struct ast_exten *e;
6929  struct ast_include *i;
6930  struct ast_ignorepat *ip;
6931 #ifndef LOW_MEMORY
6932  char buf[1024], buf2[1024];
6933 #else
6934  char buf[256], buf2[256];
6935 #endif
6936  int context_info_printed = 0;
6937 
6938  if (context && strcmp(ast_get_context_name(c), context))
6939  continue; /* skip this one, name doesn't match */
6940 
6941  dpc->context_existence = 1;
6942 
6943  ast_rdlock_context(c);
6944 
6945  /* are we looking for exten too? if yes, we print context
6946  * only if we find our extension.
6947  * Otherwise print context even if empty ?
6948  * XXX i am not sure how the rinclude is handled.
6949  * I think it ought to go inside.
6950  */
6951  if (!exten) {
6952  dpc->total_context++;
6953  ast_cli(fd, "[ Context '%s' created by '%s' ]\n",
6955  context_info_printed = 1;
6956  }
6957 
6958  /* walk extensions ... */
6959  e = NULL;
6960  while ( (e = ast_walk_context_extensions(c, e)) ) {
6961  struct ast_exten *p;
6962 
6963  if (exten && !ast_extension_match(ast_get_extension_name(e), exten))
6964  continue; /* skip, extension match failed */
6965 
6966  dpc->extension_existence = 1;
6967 
6968  /* may we print context info? */
6969  if (!context_info_printed) {
6970  dpc->total_context++;
6971  if (rinclude) { /* TODO Print more info about rinclude */
6972  ast_cli(fd, "[ Included context '%s' created by '%s' ]\n",
6974  } else {
6975  ast_cli(fd, "[ Context '%s' created by '%s' ]\n",
6977  }
6978  context_info_printed = 1;
6979  }
6980  dpc->total_prio++;
6981 
6982  /* write extension name and first peer */
6983  if (e->matchcid == AST_EXT_MATCHCID_ON)
6984  snprintf(buf, sizeof(buf), "'%s' (CID match '%s') => ", ast_get_extension_name(e), e->cidmatch);
6985  else
6986  snprintf(buf, sizeof(buf), "'%s' =>", ast_get_extension_name(e));
6987 
6988  print_ext(e, buf2, sizeof(buf2));
6989 
6990  ast_cli(fd, " %-17s %-45s [%s]\n", buf, buf2,
6992 
6993  dpc->total_exten++;
6994  /* walk next extension peers */
6995  p = e; /* skip the first one, we already got it */
6996  while ( (p = ast_walk_extension_priorities(e, p)) ) {
6997  const char *el = ast_get_extension_label(p);
6998  dpc->total_prio++;
6999  if (el)
7000  snprintf(buf, sizeof(buf), " [%s]", el);
7001  else
7002  buf[0] = '\0';
7003  print_ext(p, buf2, sizeof(buf2));
7004 
7005  ast_cli(fd," %-17s %-45s [%s]\n", buf, buf2,
7007  }
7008  }
7009 
7010  /* walk included and write info ... */
7011  i = NULL;
7012  while ( (i = ast_walk_context_includes(c, i)) ) {
7013  snprintf(buf, sizeof(buf), "'%s'", ast_get_include_name(i));
7014  if (exten) {
7015  /* Check all includes for the requested extension */
7016  if (includecount >= AST_PBX_MAX_STACK) {
7017  ast_log(LOG_WARNING, "Maximum include depth exceeded!\n");
7018  } else {
7019  int dupe = 0;
7020  int x;
7021  for (x = 0; x < includecount; x++) {
7022  if (!strcasecmp(includes[x], ast_get_include_name(i))) {
7023  dupe++;
7024  break;
7025  }
7026  }
7027  if (!dupe) {
7028  includes[includecount] = ast_get_include_name(i);
7029  show_dialplan_helper(fd, ast_get_include_name(i), exten, dpc, i, includecount + 1, includes);
7030  } else {
7031  ast_log(LOG_WARNING, "Avoiding circular include of %s within %s\n", ast_get_include_name(i), context);
7032  }
7033  }
7034  } else {
7035  ast_cli(fd, " Include => %-45s [%s]\n",
7036  buf, ast_get_include_registrar(i));
7037  }
7038  }
7039 
7040  /* walk ignore patterns and write info ... */
7041  ip = NULL;
7042  while ( (ip = ast_walk_context_ignorepats(c, ip)) ) {
7043  const char *ipname = ast_get_ignorepat_name(ip);
7044  char ignorepat[AST_MAX_EXTENSION];
7045  snprintf(buf, sizeof(buf), "'%s'", ipname);
7046  snprintf(ignorepat, sizeof(ignorepat), "_%s.", ipname);
7047  if (!exten || ast_extension_match(ignorepat, exten)) {
7048  ast_cli(fd, " Ignore pattern => %-45s [%s]\n",
7049  buf, ast_get_ignorepat_registrar(ip));
7050  }
7051  }
7052  if (!rinclude) {
7053  struct ast_sw *sw = NULL;
7054  while ( (sw = ast_walk_context_switches(c, sw)) ) {
7055  snprintf(buf, sizeof(buf), "'%s/%s'",
7056  ast_get_switch_name(sw),
7057  ast_get_switch_data(sw));
7058  ast_cli(fd, " Alt. Switch => %-45s [%s]\n",
7059  buf, ast_get_switch_registrar(sw));
7060  }
7061  }
7062 
7063  ast_unlock_context(c);
7064 
7065  /* if we print something in context, make an empty line */
7066  if (context_info_printed)
7067  ast_cli(fd, "\n");
7068  }
7070 
7071  return (dpc->total_exten == old_total_exten) ? -1 : res;
7072 }
7073 
7074 static int show_debug_helper(int fd, const char *context, const char *exten, struct dialplan_counters *dpc, struct ast_include *rinclude, int includecount, const char *includes[])
7075 {
7076  struct ast_context *c = NULL;
7077  int res = 0, old_total_exten = dpc->total_exten;
7078 
7079  ast_cli(fd,"\n In-mem exten Trie for Fast Extension Pattern Matching:\n\n");
7080 
7081  ast_cli(fd,"\n Explanation: Node Contents Format = <char(s) to match>:<pattern?>:<specif>:[matched extension]\n");
7082  ast_cli(fd, " Where <char(s) to match> is a set of chars, any one of which should match the current character\n");
7083  ast_cli(fd, " <pattern?>: Y if this a pattern match (eg. _XZN[5-7]), N otherwise\n");
7084  ast_cli(fd, " <specif>: an assigned 'exactness' number for this matching char. The lower the number, the more exact the match\n");
7085  ast_cli(fd, " [matched exten]: If all chars matched to this point, which extension this matches. In form: EXTEN:<exten string>\n");
7086  ast_cli(fd, " In general, you match a trie node to a string character, from left to right. All possible matching chars\n");
7087  ast_cli(fd, " are in a string vertically, separated by an unbroken string of '+' characters.\n\n");
7089 
7090  /* walk all contexts ... */
7091  while ( (c = ast_walk_contexts(c)) ) {
7092  int context_info_printed = 0;
7093 
7094  if (context && strcmp(ast_get_context_name(c), context))
7095  continue; /* skip this one, name doesn't match */
7096 
7097  dpc->context_existence = 1;
7098 
7099  if (!c->pattern_tree) {
7100  /* Ignore check_return warning from Coverity for ast_exists_extension below */
7101  ast_exists_extension(NULL, c->name, "s", 1, ""); /* do this to force the trie to built, if it is not already */
7102  }
7103 
7104  ast_rdlock_context(c);
7105 
7106  dpc->total_context++;
7107  ast_cli(fd, "[ Context '%s' created by '%s' ]\n",
7109  context_info_printed = 1;
7110 
7111  if (c->pattern_tree)
7112  {
7113  cli_match_char_tree(c->pattern_tree, " ", fd);
7114  } else {
7115  ast_cli(fd,"\n No Pattern Trie present. Perhaps the context is empty...or there is trouble...\n\n");
7116  }
7117 
7118  ast_unlock_context(c);
7119 
7120  /* if we print something in context, make an empty line */
7121  if (context_info_printed)
7122  ast_cli(fd, "\n");
7123  }
7125 
7126  return (dpc->total_exten == old_total_exten) ? -1 : res;
7127 }
7128 
7129 static char *handle_show_dialplan(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
7130 {
7131  char *exten = NULL, *context = NULL;
7132  /* Variables used for different counters */
7133  struct dialplan_counters counters;
7134  const char *incstack[AST_PBX_MAX_STACK];
7135 
7136  switch (cmd) {
7137  case CLI_INIT:
7138  e->command = "dialplan show";
7139  e->usage =
7140  "Usage: dialplan show [[exten@]context]\n"
7141  " Show dialplan\n";
7142  return NULL;
7143  case CLI_GENERATE:
7144  return complete_show_dialplan_context(a->line, a->word, a->pos, a->n);
7145  }
7146 
7147  memset(&counters, 0, sizeof(counters));
7148 
7149  if (a->argc != 2 && a->argc != 3)
7150  return CLI_SHOWUSAGE;
7151 
7152  /* we obtain [exten@]context? if yes, split them ... */
7153  if (a->argc == 3) {
7154  if (strchr(a->argv[2], '@')) { /* split into exten & context */
7155  context = ast_strdupa(a->argv[2]);
7156  exten = strsep(&context, "@");
7157  /* change empty strings to NULL */
7158  if (ast_strlen_zero(exten))
7159  exten = NULL;
7160  } else { /* no '@' char, only context given */
7161  context = ast_strdupa(a->argv[2]);
7162  }
7163  if (ast_strlen_zero(context))
7164  context = NULL;
7165  }
7166  /* else Show complete dial plan, context and exten are NULL */
7167  show_dialplan_helper(a->fd, context, exten, &counters, NULL, 0, incstack);
7168 
7169  /* check for input failure and throw some error messages */
7170  if (context && !counters.context_existence) {
7171  ast_cli(a->fd, "There is no existence of '%s' context\n", context);
7172  return CLI_FAILURE;
7173  }
7174 
7175  if (exten && !counters.extension_existence) {
7176  if (context)
7177  ast_cli(a->fd, "There is no existence of %s@%s extension\n",
7178  exten, context);
7179  else
7180  ast_cli(a->fd,
7181  "There is no existence of '%s' extension in all contexts\n",
7182  exten);
7183  return CLI_FAILURE;
7184  }
7185 
7186  ast_cli(a->fd,"-= %d %s (%d %s) in %d %s. =-\n",
7187  counters.total_exten, counters.total_exten == 1 ? "extension" : "extensions",
7188  counters.total_prio, counters.total_prio == 1 ? "priority" : "priorities",
7189  counters.total_context, counters.total_context == 1 ? "context" : "contexts");
7190 
7191  /* everything ok */
7192  return CLI_SUCCESS;
7193 }
7194 
7195 /*! \brief Send ack once */
7196 static char *handle_debug_dialplan(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
7197 {
7198  char *exten = NULL, *context = NULL;
7199  /* Variables used for different counters */
7200  struct dialplan_counters counters;
7201  const char *incstack[AST_PBX_MAX_STACK];
7202 
7203  switch (cmd) {
7204  case CLI_INIT:
7205  e->command = "dialplan debug";
7206  e->usage =
7207  "Usage: dialplan debug [context]\n"
7208  " Show dialplan context Trie(s). Usually only useful to folks debugging the deep internals of the fast pattern matcher\n";
7209  return NULL;
7210  case CLI_GENERATE:
7211  return complete_show_dialplan_context(a->line, a->word, a->pos, a->n);
7212  }
7213 
7214  memset(&counters, 0, sizeof(counters));
7215 
7216  if (a->argc != 2 && a->argc != 3)
7217  return CLI_SHOWUSAGE;
7218 
7219  /* we obtain [exten@]context? if yes, split them ... */
7220  /* note: we ignore the exten totally here .... */
7221  if (a->argc == 3) {
7222  if (strchr(a->argv[2], '@')) { /* split into exten & context */
7223  context = ast_strdupa(a->argv[2]);
7224  exten = strsep(&context, "@");
7225  /* change empty strings to NULL */
7226  if (ast_strlen_zero(exten))
7227  exten = NULL;
7228  } else { /* no '@' char, only context given */
7229  context = ast_strdupa(a->argv[2]);
7230  }
7231  if (ast_strlen_zero(context))
7232  context = NULL;
7233  }
7234  /* else Show complete dial plan, context and exten are NULL */
7235  show_debug_helper(a->fd, context, exten, &counters, NULL, 0, incstack);
7236 
7237  /* check for input failure and throw some error messages */
7238  if (context && !counters.context_existence) {
7239  ast_cli(a->fd, "There is no existence of '%s' context\n", context);
7240  return CLI_FAILURE;
7241  }
7242 
7243 
7244  ast_cli(a->fd,"-= %d %s. =-\n",
7245  counters.total_context, counters.total_context == 1 ? "context" : "contexts");
7246 
7247  /* everything ok */
7248  return CLI_SUCCESS;
7249 }
7250 
7251 /*! \brief Send ack once */
7252 static void manager_dpsendack(struct mansession *s, const struct message *m)
7253 {
7254  astman_send_listack(s, m, "DialPlan list will follow", "start");
7255 }
7256 
7257 /*! \brief Show dialplan extensions
7258  * XXX this function is similar but not exactly the same as the CLI's
7259  * show dialplan. Must check whether the difference is intentional or not.
7260  */
7261 static int manager_show_dialplan_helper(struct mansession *s, const struct message *m,
7262  const char *actionidtext, const char *context,
7263  const char *exten, struct dialplan_counters *dpc,
7264  struct ast_include *rinclude)
7265 {
7266  struct ast_context *c;
7267  int res = 0, old_total_exten = dpc->total_exten;
7268 
7269  if (ast_strlen_zero(exten))
7270  exten = NULL;
7271  if (ast_strlen_zero(context))
7272  context = NULL;
7273 
7274  ast_debug(3, "manager_show_dialplan: Context: -%s- Extension: -%s-\n", context, exten);
7275 
7276  /* try to lock contexts */
7277  if (ast_rdlock_contexts()) {
7278  astman_send_error(s, m, "Failed to lock contexts");
7279  ast_log(LOG_WARNING, "Failed to lock contexts list for manager: listdialplan\n");
7280  return -1;
7281  }
7282 
7283  c = NULL; /* walk all contexts ... */
7284  while ( (c = ast_walk_contexts(c)) ) {
7285  struct ast_exten *e;
7286  struct ast_include *i;
7287  struct ast_ignorepat *ip;
7288 
7289  if (context && strcmp(ast_get_context_name(c), context) != 0)
7290  continue; /* not the name we want */
7291 
7292  dpc->context_existence = 1;
7293  dpc->total_context++;
7294 
7295  ast_debug(3, "manager_show_dialplan: Found Context: %s \n", ast_get_context_name(c));
7296 
7297  if (ast_rdlock_context(c)) { /* failed to lock */
7298  ast_debug(3, "manager_show_dialplan: Failed to lock context\n");
7299  continue;
7300  }
7301 
7302  /* XXX note- an empty context is not printed */
7303  e = NULL; /* walk extensions in context */
7304  while ( (e = ast_walk_context_extensions(c, e)) ) {
7305  struct ast_exten *p;
7306 
7307  /* looking for extension? is this our extension? */
7308  if (exten && !ast_extension_match(ast_get_extension_name(e), exten)) {
7309  /* not the one we are looking for, continue */
7310  ast_debug(3, "manager_show_dialplan: Skipping extension %s\n", ast_get_extension_name(e));
7311  continue;
7312  }
7313  ast_debug(3, "manager_show_dialplan: Found Extension: %s \n", ast_get_extension_name(e));
7314 
7315  dpc->extension_existence = 1;
7316 
7317  dpc->total_exten++;
7318 
7319  p = NULL; /* walk next extension peers */
7320  while ( (p = ast_walk_extension_priorities(e, p)) ) {
7321  int prio = ast_get_extension_priority(p);
7322 
7323  dpc->total_prio++;
7324  if (!dpc->total_items++)
7325  manager_dpsendack(s, m);
7326  astman_append(s, "Event: ListDialplan\r\n%s", actionidtext);
7327  astman_append(s, "Context: %s\r\nExtension: %s\r\n", ast_get_context_name(c), ast_get_extension_name(e) );
7328 
7329  /* XXX maybe make this conditional, if p != e ? */
7330  if (ast_get_extension_label(p))
7331  astman_append(s, "ExtensionLabel: %s\r\n", ast_get_extension_label(p));
7332 
7333  if (prio == PRIORITY_HINT) {
7334  astman_append(s, "Priority: hint\r\nApplication: %s\r\n", ast_get_extension_app(p));
7335  } else {
7336  astman_append(s, "Priority: %d\r\nApplication: %s\r\nAppData: %s\r\n", prio, ast_get_extension_app(p), (char *) ast_get_extension_app_data(p));
7337  }
7338  astman_append(s, "Registrar: %s\r\n\r\n", ast_get_extension_registrar(e));
7339  }
7340  }
7341 
7342  i = NULL; /* walk included and write info ... */
7343  while ( (i = ast_walk_context_includes(c, i)) ) {
7344  if (exten) {
7345  /* Check all includes for the requested extension */
7346  manager_show_dialplan_helper(s, m, actionidtext, ast_get_include_name(i), exten, dpc, i);
7347  } else {
7348  if (!dpc->total_items++)
7349  manager_dpsendack(s, m);
7350  astman_append(s, "Event: ListDialplan\r\n%s", actionidtext);
7351  astman_append(s, "Context: %s\r\nIncludeContext: %s\r\nRegistrar: %s\r\n", ast_get_context_name(c), ast_get_include_name(i), ast_get_include_registrar(i));
7352  astman_append(s, "\r\n");
7353  ast_debug(3, "manager_show_dialplan: Found Included context: %s \n", ast_get_include_name(i));
7354  }
7355  }
7356 
7357  ip = NULL; /* walk ignore patterns and write info ... */
7358  while ( (ip = ast_walk_context_ignorepats(c, ip)) ) {
7359  const char *ipname = ast_get_ignorepat_name(ip);
7360  char ignorepat[AST_MAX_EXTENSION];
7361 
7362  snprintf(ignorepat, sizeof(ignorepat), "_%s.", ipname);
7363  if (!exten || ast_extension_match(ignorepat, exten)) {
7364  if (!dpc->total_items++)
7365  manager_dpsendack(s, m);
7366  astman_append(s, "Event: ListDialplan\r\n%s", actionidtext);
7367  astman_append(s, "Context: %s\r\nIgnorePattern: %s\r\nRegistrar: %s\r\n", ast_get_context_name(c), ipname, ast_get_ignorepat_registrar(ip));
7368  astman_append(s, "\r\n");
7369  }
7370  }
7371  if (!rinclude) {
7372  struct ast_sw *sw = NULL;
7373  while ( (sw = ast_walk_context_switches(c, sw)) ) {
7374  if (!dpc->total_items++)
7375  manager_dpsendack(s, m);
7376  astman_append(s, "Event: ListDialplan\r\n%s", actionidtext);
7377  astman_append(s, "Context: %s\r\nSwitch: %s/%s\r\nRegistrar: %s\r\n", ast_get_context_name(c), ast_get_switch_name(sw), ast_get_switch_data(sw), ast_get_switch_registrar(sw));
7378  astman_append(s, "\r\n");
7379  ast_debug(3, "manager_show_dialplan: Found Switch : %s \n", ast_get_switch_name(sw));
7380  }
7381  }
7382 
7383  ast_unlock_context(c);
7384  }
7386 
7387  if (dpc->total_exten == old_total_exten) {
7388  ast_debug(3, "manager_show_dialplan: Found nothing new\n");
7389  /* Nothing new under the sun */
7390  return -1;
7391  } else {
7392  return res;
7393  }
7394 }
7395 
7396 /*! \brief Manager listing of dial plan */
7397 static int manager_show_dialplan(struct mansession *s, const struct message *m)
7398 {
7399  const char *exten, *context;
7400  const char *id = astman_get_header(m, "ActionID");
7401  char idtext[256];
7402 
7403  /* Variables used for different counters */
7404  struct dialplan_counters counters;
7405 
7406  if (!ast_strlen_zero(id))
7407  snprintf(idtext, sizeof(idtext), "ActionID: %s\r\n", id);
7408  else
7409  idtext[0] = '\0';
7410 
7411  memset(&counters, 0, sizeof(counters));
7412 
7413  exten = astman_get_header(m, "Extension");
7414  context = astman_get_header(m, "Context");
7415 
7416  manager_show_dialplan_helper(s, m, idtext, context, exten, &counters, NULL);
7417 
7418  if (!ast_strlen_zero(context) && !counters.context_existence) {
7419  char errorbuf[BUFSIZ];
7420 
7421  snprintf(errorbuf, sizeof(errorbuf), "Did not find context %s", context);
7422  astman_send_error(s, m, errorbuf);
7423  return 0;
7424  }
7425  if (!ast_strlen_zero(exten) && !counters.extension_existence) {
7426  char errorbuf[BUFSIZ];
7427 
7428  if (!ast_strlen_zero(context))
7429  snprintf(errorbuf, sizeof(errorbuf), "Did not find extension %s@%s", exten, context);
7430  else
7431  snprintf(errorbuf, sizeof(errorbuf), "Did not find extension %s in any context", exten);
7432  astman_send_error(s, m, errorbuf);
7433  return 0;
7434  }
7435 
7436  if (!counters.total_items) {
7437  manager_dpsendack(s, m);
7438  }
7439 
7440  astman_append(s, "Event: ShowDialPlanComplete\r\n"
7441  "EventList: Complete\r\n"
7442  "ListItems: %d\r\n"
7443  "ListExtensions: %d\r\n"
7444  "ListPriorities: %d\r\n"
7445  "ListContexts: %d\r\n"
7446  "%s"
7447  "\r\n", counters.total_items, counters.total_exten, counters.total_prio, counters.total_context, idtext);
7448 
7449  /* everything ok */
7450  return 0;
7451 }
7452 
7453 /*! \brief CLI support for listing global variables in a parseable way */
7454 static char *handle_show_globals(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
7455 {
7456  int i = 0;
7457  struct ast_var_t *newvariable;
7458 
7459  switch (cmd) {
7460  case CLI_INIT:
7461  e->command = "dialplan show globals";
7462  e->usage =
7463  "Usage: dialplan show globals\n"
7464  " List current global dialplan variables and their values\n";
7465  return NULL;
7466  case CLI_GENERATE:
7467  return NULL;
7468  }
7469 
7471  AST_LIST_TRAVERSE (&globals, newvariable, entries) {
7472  i++;
7473  ast_cli(a->fd, " %s=%s\n", ast_var_name(newvariable), ast_var_value(newvariable));
7474  }
7476  ast_cli(a->fd, "\n -- %d variable(s)\n", i);
7477 
7478  return CLI_SUCCESS;
7479 }
7480 
7481 #ifdef AST_DEVMODE
7482 static char *handle_show_device2extenstate(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
7483 {
7484  struct ast_devstate_aggregate agg;
7485  int i, j, exten, combined;
7486 
7487  switch (cmd) {
7488  case CLI_INIT:
7489  e->command = "core show device2extenstate";
7490  e->usage =
7491  "Usage: core show device2extenstate\n"
7492  " Lists device state to extension state combinations.\n";
7493  case CLI_GENERATE:
7494  return NULL;
7495  }
7496  for (i = 0; i < AST_DEVICE_TOTAL; i++) {
7497  for (j = 0; j < AST_DEVICE_TOTAL; j++) {
7499  ast_devstate_aggregate_add(&agg, i);
7500  ast_devstate_aggregate_add(&agg, j);
7501  combined = ast_devstate_aggregate_result(&agg);
7502  exten = ast_devstate_to_extenstate(combined);
7503  ast_cli(a->fd, "\n Exten:%14s CombinedDevice:%12s Dev1:%12s Dev2:%12s", ast_extension_state2str(exten), ast_devstate_str(combined), ast_devstate_str(j), ast_devstate_str(i));
7504  }
7505  }
7506  ast_cli(a->fd, "\n");
7507  return CLI_SUCCESS;
7508 }
7509 #endif
7510 
7511 /*! \brief CLI support for listing chanvar's variables in a parseable way */
7512 static char *handle_show_chanvar(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
7513 {
7514  struct ast_channel *chan = NULL;
7515  struct ast_str *vars = ast_str_alloca(BUFSIZ * 4); /* XXX large because we might have lots of channel vars */
7516 
7517  switch (cmd) {
7518  case CLI_INIT:
7519  e->command = "dialplan show chanvar";
7520  e->usage =
7521  "Usage: dialplan show chanvar <channel>\n"
7522  " List current channel variables and their values\n";
7523  return NULL;
7524  case CLI_GENERATE:
7525  return ast_complete_channels(a->line, a->word, a->pos, a->n, 3);
7526  }
7527 
7528  if (a->argc != e->args + 1)
7529  return CLI_SHOWUSAGE;
7530 
7531  if (!(chan = ast_channel_get_by_name(a->argv[e->args]))) {
7532  ast_cli(a->fd, "Channel '%s' not found\n", a->argv[e->args]);
7533  return CLI_FAILURE;
7534  }
7535 
7536  pbx_builtin_serialize_variables(chan, &vars);
7537 
7538  if (ast_str_strlen(vars)) {
7539  ast_cli(a->fd, "\nVariables for channel %s:\n%s\n", a->argv[e->args], ast_str_buffer(vars));
7540  }
7541 
7542  chan = ast_channel_unref(chan);
7543 
7544  return CLI_SUCCESS;
7545 }
7546 
7547 static char *handle_set_global(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
7548 {
7549  switch (cmd) {
7550  case CLI_INIT:
7551  e->command = "dialplan set global";
7552  e->usage =
7553  "Usage: dialplan set global <name> <value>\n"
7554  " Set global dialplan variable <name> to <value>\n";
7555  return NULL;
7556  case CLI_GENERATE:
7557  return NULL;
7558  }
7559 
7560  if (a->argc != e->args + 2)
7561  return CLI_SHOWUSAGE;
7562 
7563  pbx_builtin_setvar_helper(NULL, a->argv[3], a->argv[4]);
7564  ast_cli(a->fd, "\n -- Global variable '%s' set to '%s'\n", a->argv[3], a->argv[4]);
7565 
7566  return CLI_SUCCESS;
7567 }
7568 
7569 static char *handle_set_chanvar(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
7570 {
7571  struct ast_channel *chan;
7572  const char *chan_name, *var_name, *var_value;
7573 
7574  switch (cmd) {
7575  case CLI_INIT:
7576  e->command = "dialplan set chanvar";
7577  e->usage =
7578  "Usage: dialplan set chanvar <channel> <varname> <value>\n"
7579  " Set channel variable <varname> to <value>\n";
7580  return NULL;
7581  case CLI_GENERATE:
7582  return ast_complete_channels(a->line, a->word, a->pos, a->n, 3);
7583  }
7584 
7585  if (a->argc != e->args + 3)
7586  return CLI_SHOWUSAGE;
7587 
7588  chan_name = a->argv[e->args];
7589  var_name = a->argv[e->args + 1];
7590  var_value = a->argv[e->args + 2];
7591 
7592  if (!(chan = ast_channel_get_by_name(chan_name))) {
7593  ast_cli(a->fd, "Channel '%s' not found\n", chan_name);
7594  return CLI_FAILURE;
7595  }
7596 
7597  pbx_builtin_setvar_helper(chan, var_name, var_value);
7598 
7599  chan = ast_channel_unref(chan);
7600 
7601  ast_cli(a->fd, "\n -- Channel variable '%s' set to '%s' for '%s'\n", var_name, var_value, chan_name);
7602 
7603  return CLI_SUCCESS;
7604 }
7605 
7606 static char *handle_set_extenpatternmatchnew(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
7607 {
7608  int oldval = 0;
7609 
7610  switch (cmd) {
7611  case CLI_INIT:
7612  e->command = "dialplan set extenpatternmatchnew true";
7613  e->usage =
7614  "Usage: dialplan set extenpatternmatchnew true|false\n"
7615  " Use the NEW extension pattern matching algorithm, true or false.\n";
7616  return NULL;
7617  case CLI_GENERATE:
7618  return NULL;
7619  }
7620 
7621  if (a->argc != 4)
7622  return CLI_SHOWUSAGE;
7623 
7624  oldval = pbx_set_extenpatternmatchnew(1);
7625 
7626  if (oldval)
7627  ast_cli(a->fd, "\n -- Still using the NEW pattern match algorithm for extension names in the dialplan.\n");
7628  else
7629  ast_cli(a->fd, "\n -- Switched to using the NEW pattern match algorithm for extension names in the dialplan.\n");
7630 
7631  return CLI_SUCCESS;
7632 }
7633 
7634 static char *handle_unset_extenpatternmatchnew(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
7635 {
7636  int oldval = 0;
7637 
7638  switch (cmd) {
7639  case CLI_INIT:
7640  e->command = "dialplan set extenpatternmatchnew false";
7641  e->usage =
7642  "Usage: dialplan set extenpatternmatchnew true|false\n"
7643  " Use the NEW extension pattern matching algorithm, true or false.\n";
7644  return NULL;
7645  case CLI_GENERATE:
7646  return NULL;
7647  }
7648 
7649  if (a->argc != 4)
7650  return CLI_SHOWUSAGE;
7651 
7652  oldval = pbx_set_extenpatternmatchnew(0);
7653 
7654  if (!oldval)
7655  ast_cli(a->fd, "\n -- Still using the OLD pattern match algorithm for extension names in the dialplan.\n");
7656  else
7657  ast_cli(a->fd, "\n -- Switched to using the OLD pattern match algorithm for extension names in the dialplan.\n");
7658 
7659  return CLI_SUCCESS;
7660 }
7661 
7662 /*
7663  * CLI entries for upper commands ...
7664  */
7665 static struct ast_cli_entry pbx_cli[] = {
7666  AST_CLI_DEFINE(handle_show_applications, "Shows registered dialplan applications"),
7667  AST_CLI_DEFINE(handle_show_functions, "Shows registered dialplan functions"),
7668  AST_CLI_DEFINE(handle_show_switches, "Show alternative switches"),
7669  AST_CLI_DEFINE(handle_show_hints, "Show dialplan hints"),
7670  AST_CLI_DEFINE(handle_show_hint, "Show dialplan hint"),
7671  AST_CLI_DEFINE(handle_show_globals, "Show global dialplan variables"),
7672 #ifdef AST_DEVMODE
7673  AST_CLI_DEFINE(handle_show_device2extenstate, "Show expected exten state from multiple device states"),
7674 #endif
7675  AST_CLI_DEFINE(handle_show_chanvar, "Show channel variables"),
7676  AST_CLI_DEFINE(handle_show_function, "Describe a specific dialplan function"),
7677  AST_CLI_DEFINE(handle_show_application, "Describe a specific dialplan application"),
7678  AST_CLI_DEFINE(handle_set_global, "Set global dialplan variable"),
7679  AST_CLI_DEFINE(handle_set_chanvar, "Set a channel variable"),
7680  AST_CLI_DEFINE(handle_show_dialplan, "Show dialplan"),
7681  AST_CLI_DEFINE(handle_debug_dialplan, "Show fast extension pattern matching data structures"),
7682  AST_CLI_DEFINE(handle_unset_extenpatternmatchnew, "Use the Old extension pattern matching algorithm."),
7683  AST_CLI_DEFINE(handle_set_extenpatternmatchnew, "Use the New extension pattern matching algorithm."),
7684 };
7685 
7686 static void unreference_cached_app(struct ast_app *app)
7687 {
7688  struct ast_context *context = NULL;
7689  struct ast_exten *eroot = NULL, *e = NULL;
7690 
7692  while ((context = ast_walk_contexts(context))) {
7693  while ((eroot = ast_walk_context_extensions(context, eroot))) {
7694  while ((e = ast_walk_extension_priorities(eroot, e))) {
7695  if (e->cached_app == app)
7696  e->cached_app = NULL;
7697  }
7698  }
7699  }
7701 
7702  return;
7703 }
7704 
7705 int ast_unregister_application(const char *app)
7706 {
7707  struct ast_app *tmp;
7708 
7710  AST_RWLIST_TRAVERSE_SAFE_BEGIN(&apps, tmp, list) {
7711  if (!strcasecmp(app, tmp->name)) {
7714  ast_verb(2, "Unregistered application '%s'\n", tmp->name);
7716  ast_free(tmp);
7717  break;
7718  }
7719  }
7722 
7723  return tmp ? 0 : -1;
7724 }
7725 
7726 struct ast_context *ast_context_find_or_create(struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *name, const char *registrar)
7727 {
7728  struct ast_context *tmp, **local_contexts;
7729  struct fake_context search;
7730  int length = sizeof(struct ast_context) + strlen(name) + 1;
7731 
7732  if (!contexts_table) {
7733  /* Protect creation of contexts_table from reentrancy. */
7735  if (!contexts_table) {
7741  0);
7742  }
7744  }
7745 
7746  ast_copy_string(search.name, name, sizeof(search.name));
7747  if (!extcontexts) {
7749  local_contexts = &contexts;
7750  tmp = ast_hashtab_lookup(contexts_table, &search);
7752  if (tmp) {
7753  tmp->refcount++;
7754  return tmp;
7755  }
7756  } else { /* local contexts just in a linked list; search there for the new context; slow, linear search, but not frequent */
7757  local_contexts = extcontexts;
7758  tmp = ast_hashtab_lookup(exttable, &search);
7759  if (tmp) {
7760  tmp->refcount++;
7761  return tmp;
7762  }
7763  }
7764 
7765  if ((tmp = ast_calloc(1, length))) {
7766  ast_rwlock_init(&tmp->lock);
7767  ast_mutex_init(&tmp->macrolock);
7768  strcpy(tmp->name, name);
7769  tmp->root = NULL;
7770  tmp->root_table = NULL;
7771  tmp->registrar = ast_strdup(registrar);
7772  tmp->includes = NULL;
7773  tmp->ignorepats = NULL;
7774  tmp->refcount = 1;
7775  } else {
7776  ast_log(LOG_ERROR, "Danger! We failed to allocate a context for %s!\n", name);
7777  return NULL;
7778  }
7779 
7780  if (!extcontexts) {
7782  tmp->next = *local_contexts;
7783  *local_contexts = tmp;
7784  ast_hashtab_insert_safe(contexts_table, tmp); /*put this context into the tree */
7786  ast_debug(1, "Registered context '%s'(%p) in table %p registrar: %s\n", tmp->name, tmp, contexts_table, registrar);
7787  ast_verb(3, "Registered extension context '%s'; registrar: %s\n", tmp->name, registrar);
7788  } else {
7789  tmp->next = *local_contexts;
7790  if (exttable)
7791  ast_hashtab_insert_immediate(exttable, tmp); /*put this context into the tree */
7792 
7793  *local_contexts = tmp;
7794  ast_debug(1, "Registered context '%s'(%p) in local table %p; registrar: %s\n", tmp->name, tmp, exttable, registrar);
7795  ast_verb(3, "Registered extension context '%s'; registrar: %s\n", tmp->name, registrar);
7796  }
7797  return tmp;
7798 }
7799 
7800 void __ast_context_destroy(struct ast_context *list, struct ast_hashtab *contexttab, struct ast_context *con, const char *registrar);
7801 
7802 struct store_hint {
7803  char *context;
7804  char *exten;
7805  AST_LIST_HEAD_NOLOCK(, ast_state_cb) callbacks;
7806  int laststate;
7808  char data[1];
7809 };
7810 
7812 
7813 static void context_merge_incls_swits_igps_other_registrars(struct ast_context *new, struct ast_context *old, const char *registrar)
7814 {
7815  struct ast_include *i;
7816  struct ast_ignorepat *ip;
7817  struct ast_sw *sw;
7818 
7819  ast_verb(3, "merging incls/swits/igpats from old(%s) to new(%s) context, registrar = %s\n", ast_get_context_name(old), ast_get_context_name(new), registrar);
7820  /* copy in the includes, switches, and ignorepats */
7821  /* walk through includes */
7822  for (i = NULL; (i = ast_walk_context_includes(old, i)) ; ) {
7823  if (strcmp(ast_get_include_registrar(i), registrar) == 0)
7824  continue; /* not mine */
7826  }
7827 
7828  /* walk through switches */
7829  for (sw = NULL; (sw = ast_walk_context_switches(old, sw)) ; ) {
7830  if (strcmp(ast_get_switch_registrar(sw), registrar) == 0)
7831  continue; /* not mine */
7833  }
7834 
7835  /* walk thru ignorepats ... */
7836  for (ip = NULL; (ip = ast_walk_context_ignorepats(old, ip)); ) {
7837  if (strcmp(ast_get_ignorepat_registrar(ip), registrar) == 0)
7838  continue; /* not mine */
7840  }
7841 }
7842 
7843 
7844 /* the purpose of this routine is to duplicate a context, with all its substructure,
7845  except for any extens that have a matching registrar */
7846 static void context_merge(struct ast_context **extcontexts, struct ast_hashtab *exttable, struct ast_context *context, const char *registrar)
7847 {
7848  struct ast_context *new = ast_hashtab_lookup(exttable, context); /* is there a match in the new set? */
7849  struct ast_exten *exten_item, *prio_item, *new_exten_item, *new_prio_item;
7850  struct ast_hashtab_iter *exten_iter;
7851  struct ast_hashtab_iter *prio_iter;
7852  int insert_count = 0;
7853  int first = 1;
7854 
7855  /* We'll traverse all the extensions/prios, and see which are not registrar'd with
7856  the current registrar, and copy them to the new context. If the new context does not
7857  exist, we'll create it "on demand". If no items are in this context to copy, then we'll
7858  only create the empty matching context if the old one meets the criteria */
7859 
7860  if (context->root_table) {
7861  exten_iter = ast_hashtab_start_traversal(context->root_table);
7862  while ((exten_item=ast_hashtab_next(exten_iter))) {
7863  if (new) {
7864  new_exten_item = ast_hashtab_lookup(new->root_table, exten_item);
7865  } else {
7866  new_exten_item = NULL;
7867  }
7868  prio_iter = ast_hashtab_start_traversal(exten_item->peer_table);
7869  while ((prio_item=ast_hashtab_next(prio_iter))) {
7870  int res1;
7871  char *dupdstr;
7872 
7873  if (new_exten_item) {
7874  new_prio_item = ast_hashtab_lookup(new_exten_item->peer_table, prio_item);
7875  } else {
7876  new_prio_item = NULL;
7877  }
7878  if (strcmp(prio_item->registrar,registrar) == 0) {
7879  continue;
7880  }
7881  /* make sure the new context exists, so we have somewhere to stick this exten/prio */
7882  if (!new) {
7883  new = ast_context_find_or_create(extcontexts, exttable, context->name, prio_item->registrar); /* a new context created via priority from a different context in the old dialplan, gets its registrar from the prio's registrar */
7884  }
7885 
7886  /* copy in the includes, switches, and ignorepats */
7887  if (first) { /* but, only need to do this once */
7888  context_merge_incls_swits_igps_other_registrars(new, context, registrar);
7889  first = 0;
7890  }
7891 
7892  if (!new) {
7893  ast_log(LOG_ERROR,"Could not allocate a new context for %s in merge_and_delete! Danger!\n", context->name);
7894  ast_hashtab_end_traversal(prio_iter);
7895  ast_hashtab_end_traversal(exten_iter);
7896  return; /* no sense continuing. */
7897  }
7898  /* we will not replace existing entries in the new context with stuff from the old context.
7899  but, if this is because of some sort of registrar conflict, we ought to say something... */
7900 
7901  dupdstr = ast_strdup(prio_item->data);
7902 
7903  res1 = ast_add_extension2(new, 0, prio_item->exten, prio_item->priority, prio_item->label,
7904  prio_item->matchcid ? prio_item->cidmatch : NULL, prio_item->app, dupdstr, prio_item->datad, prio_item->registrar);
7905  if (!res1 && new_exten_item && new_prio_item){
7906  ast_verb(3,"Dropping old dialplan item %s/%s/%d [%s(%s)] (registrar=%s) due to conflict with new dialplan\n",
7907  context->name, prio_item->exten, prio_item->priority, prio_item->app, (char*)prio_item->data, prio_item->registrar);
7908  } else {
7909  /* we do NOT pass the priority data from the old to the new -- we pass a copy of it, so no changes to the current dialplan take place,
7910  and no double frees take place, either! */
7911  insert_count++;
7912  }
7913  }
7914  ast_hashtab_end_traversal(prio_iter);
7915  }
7916  ast_hashtab_end_traversal(exten_iter);
7917  } else if (new) {
7918  /* If the context existed but had no extensions, we still want to merge
7919  * the includes, switches and ignore patterns.
7920  */
7921  context_merge_incls_swits_igps_other_registrars(new, context, registrar);
7922  }
7923 
7924  if (!insert_count && !new && (strcmp(context->registrar, registrar) != 0 ||
7925  (strcmp(context->registrar, registrar) == 0 && context->refcount > 1))) {
7926  /* we could have given it the registrar of the other module who incremented the refcount,
7927  but that's not available, so we give it the registrar we know about */
7928  new = ast_context_find_or_create(extcontexts, exttable, context->name, context->registrar);
7929 
7930  /* copy in the includes, switches, and ignorepats */
7931  context_merge_incls_swits_igps_other_registrars(new, context, registrar);
7932  }
7933 }
7934 
7935 
7936 /* XXX this does not check that multiple contexts are merged */
7937 void ast_merge_contexts_and_delete(struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *registrar)
7938 {
7939  double ft;
7940  struct ast_context *tmp;
7941  struct ast_context *oldcontextslist;
7942  struct ast_hashtab *oldtable;
7943  struct store_hints hints_stored = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
7944  struct store_hints hints_removed = AST_LIST_HEAD_NOLOCK_INIT_VALUE;
7945  struct store_hint *saved_hint;
7946  struct ast_hint *hint;
7947  struct ast_exten *exten;
7948  int length;
7949  struct ast_state_cb *thiscb;
7950  struct ast_hashtab_iter *iter;
7951  struct ao2_iterator i;
7952  struct timeval begintime;
7953  struct timeval writelocktime;
7954  struct timeval endlocktime;
7955  struct timeval enddeltime;
7956 
7957  /*
7958  * It is very important that this function hold the hints
7959  * container lock _and_ the conlock during its operation; not
7960  * only do we need to ensure that the list of contexts and
7961  * extensions does not change, but also that no hint callbacks
7962  * (watchers) are added or removed during the merge/delete
7963  * process
7964  *
7965  * In addition, the locks _must_ be taken in this order, because
7966  * there are already other code paths that use this order
7967  */
7968 
7969  begintime = ast_tvnow();
7970  ast_mutex_lock(&context_merge_lock);/* Serialize ast_merge_contexts_and_delete */
7972 
7973  if (!contexts_table) {
7974  /* Well, that's odd. There are no contexts. */
7975  contexts_table = exttable;
7976  contexts = *extcontexts;
7979  return;
7980  }
7981 
7983  while ((tmp = ast_hashtab_next(iter))) {
7984  context_merge(extcontexts, exttable, tmp, registrar);
7985  }
7987 
7988  ao2_lock(hints);
7989  writelocktime = ast_tvnow();
7990 
7991  /* preserve all watchers for hints */
7993  for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) {
7994  if (ao2_container_count(hint->callbacks)) {
7995  ao2_lock(hint);
7996  if (!hint->exten) {
7997  /* The extension has already been destroyed. (Should never happen here) */
7998  ao2_unlock(hint);
7999  continue;
8000  }
8001 
8002  length = strlen(hint->exten->exten) + strlen(hint->exten->parent->name) + 2
8003  + sizeof(*saved_hint);
8004  if (!(saved_hint = ast_calloc(1, length))) {
8005  ao2_unlock(hint);
8006  continue;
8007  }
8008 
8009  /* This removes all the callbacks from the hint into saved_hint. */
8010  while ((thiscb = ao2_callback(hint->callbacks, OBJ_UNLINK, NULL, NULL))) {
8011  AST_LIST_INSERT_TAIL(&saved_hint->callbacks, thiscb, entry);
8012  /*
8013  * We intentionally do not unref thiscb to account for the
8014  * non-ao2 reference in saved_hint->callbacks
8015  */
8016  }
8017 
8018  saved_hint->laststate = hint->laststate;
8019  saved_hint->context = saved_hint->data;
8020  strcpy(saved_hint->data, hint->exten->parent->name);
8021  saved_hint->exten = saved_hint->data + strlen(saved_hint->context) + 1;
8022  strcpy(saved_hint->exten, hint->exten->exten);
8023  ao2_unlock(hint);
8024  AST_LIST_INSERT_HEAD(&hints_stored, saved_hint, list);
8025  }
8026  }
8028 
8029  /* save the old table and list */
8030  oldtable = contexts_table;
8031  oldcontextslist = contexts;
8032 
8033  /* move in the new table and list */
8034  contexts_table = exttable;
8035  contexts = *extcontexts;
8036 
8037  /*
8038  * Restore the watchers for hints that can be found; notify
8039  * those that cannot be restored.
8040  */
8041  while ((saved_hint = AST_LIST_REMOVE_HEAD(&hints_stored, list))) {
8042  struct pbx_find_info q = { .stacklen = 0 };
8043 
8044  exten = pbx_find_extension(NULL, NULL, &q, saved_hint->context, saved_hint->exten,
8045  PRIORITY_HINT, NULL, "", E_MATCH);
8046  /*
8047  * If this is a pattern, dynamically create a new extension for this
8048  * particular match. Note that this will only happen once for each
8049  * individual extension, because the pattern will no longer match first.
8050  */
8051  if (exten && exten->exten[0] == '_') {
8052  ast_add_extension_nolock(exten->parent->name, 0, saved_hint->exten,
8053  PRIORITY_HINT, NULL, 0, exten->app, ast_strdup(exten->data), ast_free_ptr,
8054  exten->registrar);
8055  /* rwlocks are not recursive locks */
8056  exten = ast_hint_extension_nolock(NULL, saved_hint->context,
8057  saved_hint->exten);
8058  }
8059 
8060  /* Find the hint in the hints container */
8061  hint = exten ? ao2_find(hints, exten, 0) : NULL;
8062  if (!hint) {
8063  /*
8064  * Notify watchers of this removed hint later when we aren't
8065  * encumberd by so many locks.
8066  */
8067  AST_LIST_INSERT_HEAD(&hints_removed, saved_hint, list);
8068  } else {
8069  ao2_lock(hint);
8070  while ((thiscb = AST_LIST_REMOVE_HEAD(&saved_hint->callbacks, entry))) {
8071  ao2_link(hint->callbacks, thiscb);
8072  /* Ref that we added when putting into saved_hint->callbacks */
8073  ao2_ref(thiscb, -1);
8074  }
8075  hint->laststate = saved_hint->laststate;
8076  ao2_unlock(hint);
8077  ao2_ref(hint, -1);
8078  ast_free(saved_hint);
8079  }
8080  }
8081 
8082  ao2_unlock(hints);
8084 
8085  /*
8086  * Notify watchers of all removed hints with the same lock
8087  * environment as handle_statechange().
8088  */
8089  while ((saved_hint = AST_LIST_REMOVE_HEAD(&hints_removed, list))) {
8090  /* this hint has been removed, notify the watchers */
8091  while ((thiscb = AST_LIST_REMOVE_HEAD(&saved_hint->callbacks, entry))) {
8092  thiscb->change_cb(saved_hint->context, saved_hint->exten,
8093  AST_EXTENSION_REMOVED, thiscb->data);
8094  /* Ref that we added when putting into saved_hint->callbacks */
8095  ao2_ref(thiscb, -1);
8096  }
8097  ast_free(saved_hint);
8098  }
8099 
8101  endlocktime = ast_tvnow();
8102 
8103  /*
8104  * The old list and hashtab no longer are relevant, delete them
8105  * while the rest of asterisk is now freely using the new stuff
8106  * instead.
8107  */
8108 
8109  ast_hashtab_destroy(oldtable, NULL);
8110 
8111  for (tmp = oldcontextslist; tmp; ) {
8112  struct ast_context *next; /* next starting point */
8113 
8114  next = tmp->next;
8116  tmp = next;
8117  }
8118  enddeltime = ast_tvnow();
8119 
8120  ft = ast_tvdiff_us(writelocktime, begintime);
8121  ft /= 1000000.0;
8122  ast_verb(3,"Time to scan old dialplan and merge leftovers back into the new: %8.6f sec\n", ft);
8123 
8124  ft = ast_tvdiff_us(endlocktime, writelocktime);
8125  ft /= 1000000.0;
8126  ast_verb(3,"Time to restore hints and swap in new dialplan: %8.6f sec\n", ft);
8127 
8128  ft = ast_tvdiff_us(enddeltime, endlocktime);
8129  ft /= 1000000.0;
8130  ast_verb(3,"Time to delete the old dialplan: %8.6f sec\n", ft);
8131 
8132  ft = ast_tvdiff_us(enddeltime, begintime);
8133  ft /= 1000000.0;
8134  ast_verb(3,"Total time merge_contexts_delete: %8.6f sec\n", ft);
8135 }
8136 
8137 /*
8138  * errno values
8139  * EBUSY - can't lock
8140  * ENOENT - no existence of context
8141  */
8142 int ast_context_add_include(const char *context, const char *include, const char *registrar)
8143 {
8144  int ret = -1;
8145  struct ast_context *c;
8146 
8147  c = find_context_locked(context);
8148  if (c) {
8149  ret = ast_context_add_include2(c, include, registrar);
8151  }
8152  return ret;
8153 }
8154 
8155 /*! \brief Helper for get_range.
8156  * return the index of the matching entry, starting from 1.
8157  * If names is not supplied, try numeric values.
8158  */
8159 static int lookup_name(const char *s, const char * const names[], int max)
8160 {
8161  int i;
8162 
8163  if (names && *s > '9') {
8164  for (i = 0; names[i]; i++) {
8165  if (!strcasecmp(s, names[i])) {
8166  return i;
8167  }
8168  }
8169  }
8170 
8171  /* Allow months and weekdays to be specified as numbers, as well */
8172  if (sscanf(s, "%2d", &i) == 1 && i >= 1 && i <= max) {
8173  /* What the array offset would have been: "1" would be at offset 0 */
8174  return i - 1;
8175  }
8176  return -1; /* error return */
8177 }
8178 
8179 /*! \brief helper function to return a range up to max (7, 12, 31 respectively).
8180  * names, if supplied, is an array of names that should be mapped to numbers.
8181  */
8182 static unsigned get_range(char *src, int max, const char * const names[], const char *msg)
8183 {
8184  int start, end; /* start and ending position */
8185  unsigned int mask = 0;
8186  char *part;
8187 
8188  /* Check for whole range */
8189  if (ast_strlen_zero(src) || !strcmp(src, "*")) {
8190  return (1 << max) - 1;
8191  }
8192 
8193  while ((part = strsep(&src, "&"))) {
8194  /* Get start and ending position */
8195  char *endpart = strchr(part, '-');
8196  if (endpart) {
8197  *endpart++ = '\0';
8198  }
8199  /* Find the start */
8200  if ((start = lookup_name(part, names, max)) < 0) {
8201  ast_log(LOG_WARNING, "Invalid %s '%s', skipping element\n", msg, part);
8202  continue;
8203  }
8204  if (endpart) { /* find end of range */
8205  if ((end = lookup_name(endpart, names, max)) < 0) {
8206  ast_log(LOG_WARNING, "Invalid end %s '%s', skipping element\n", msg, endpart);
8207  continue;
8208  }
8209  } else {
8210  end = start;
8211  }
8212  /* Fill the mask. Remember that ranges are cyclic */
8213  mask |= (1 << end); /* initialize with last element */
8214  while (start != end) {
8215  mask |= (1 << start);
8216  if (++start >= max) {
8217  start = 0;
8218  }
8219  }
8220  }
8221  return mask;
8222 }
8223 
8224 /*! \brief store a bitmask of valid times, one bit each 1 minute */
8225 static void get_timerange(struct ast_timing *i, char *times)
8226 {
8227  char *endpart, *part;
8228  int x;
8229  int st_h, st_m;
8230  int endh, endm;
8231  int minute_start, minute_end;
8232 
8233  /* start disabling all times, fill the fields with 0's, as they may contain garbage */
8234  memset(i->minmask, 0, sizeof(i->minmask));
8235 
8236  /* 1-minute per bit */
8237  /* Star is all times */
8238  if (ast_strlen_zero(times) || !strcmp(times, "*")) {
8239  /* 48, because each hour takes 2 integers; 30 bits each */
8240  for (x = 0; x < 48; x++) {
8241  i->minmask[x] = 0x3fffffff; /* 30 bits */
8242  }
8243  return;
8244  }
8245  /* Otherwise expect a range */
8246  while ((part = strsep(&times, "&"))) {
8247  if (!(endpart = strchr(part, '-'))) {
8248  if (sscanf(part, "%2d:%2d", &st_h, &st_m) != 2 || st_h < 0 || st_h > 23 || st_m < 0 || st_m > 59) {
8249  ast_log(LOG_WARNING, "%s isn't a valid time.\n", part);
8250  continue;
8251  }
8252  i->minmask[st_h * 2 + (st_m >= 30 ? 1 : 0)] |= (1 << (st_m % 30));
8253  continue;
8254  }
8255  *endpart++ = '\0';
8256  /* why skip non digits? Mostly to skip spaces */
8257  while (*endpart && !isdigit(*endpart)) {
8258  endpart++;
8259  }
8260  if (!*endpart) {
8261  ast_log(LOG_WARNING, "Invalid time range starting with '%s-'.\n", part);
8262  continue;
8263  }
8264  if (sscanf(part, "%2d:%2d", &st_h, &st_m) != 2 || st_h < 0 || st_h > 23 || st_m < 0 || st_m > 59) {
8265  ast_log(LOG_WARNING, "'%s' isn't a valid start time.\n", part);
8266  continue;
8267  }
8268  if (sscanf(endpart, "%2d:%2d", &endh, &endm) != 2 || endh < 0 || endh > 23 || endm < 0 || endm > 59) {
8269  ast_log(LOG_WARNING, "'%s' isn't a valid end time.\n", endpart);
8270  continue;
8271  }
8272  minute_start = st_h * 60 + st_m;
8273  minute_end = endh * 60 + endm;
8274  /* Go through the time and enable each appropriate bit */
8275  for (x = minute_start; x != minute_end; x = (x + 1) % (24 * 60)) {
8276  i->minmask[x / 30] |= (1 << (x % 30));
8277  }
8278  /* Do the last one */
8279  i->minmask[x / 30] |= (1 << (x % 30));
8280  }
8281  /* All done */
8282  return;
8283 }
8284 
8285 static const char * const days[] =
8286 {
8287  "sun",
8288  "mon",
8289  "tue",
8290  "wed",
8291  "thu",
8292  "fri",
8293  "sat",
8294  NULL,
8295 };
8296 
8297 static const char * const months[] =
8298 {
8299  "jan",
8300  "feb",
8301  "mar",
8302  "apr",
8303  "may",
8304  "jun",
8305  "jul",
8306  "aug",
8307  "sep",
8308  "oct",
8309  "nov",
8310  "dec",
8311  NULL,
8312 };
8313 
8314 int ast_build_timing(struct ast_timing *i, const char *info_in)
8315 {
8316  char *info;
8317  int j, num_fields, last_sep = -1;
8318 
8319  i->timezone = NULL;
8320 
8321  /* Check for empty just in case */
8322  if (ast_strlen_zero(info_in)) {
8323  return 0;
8324  }
8325 
8326  /* make a copy just in case we were passed a static string */
8327  info = ast_strdupa(info_in);
8328 
8329  /* count the number of fields in the timespec */
8330  for (j = 0, num_fields = 1; info[j] != '\0'; j++) {
8331  if (info[j] == ',') {
8332  last_sep = j;
8333  num_fields++;
8334  }
8335  }
8336 
8337  /* save the timezone, if it is specified */
8338  if (num_fields == 5) {
8339  i->timezone = ast_strdup(info + last_sep + 1);
8340  }
8341 
8342  /* Assume everything except time */
8343  i->monthmask = 0xfff; /* 12 bits */
8344  i->daymask = 0x7fffffffU; /* 31 bits */
8345  i->dowmask = 0x7f; /* 7 bits */
8346  /* on each call, use strsep() to move info to the next argument */
8347  get_timerange(i, strsep(&info, "|,"));
8348  if (info)
8349  i->dowmask = get_range(strsep(&info, "|,"), 7, days, "day of week");
8350  if (info)
8351  i->daymask = get_range(strsep(&info, "|,"), 31, NULL, "day");
8352  if (info)
8353  i->monthmask = get_range(strsep(&info, "|,"), 12, months, "month");
8354  return 1;
8355 }
8356 
8357 int ast_check_timing(const struct ast_timing *i)
8358 {
8359  return ast_check_timing2(i, ast_tvnow());
8360 }
8361 
8362 int ast_check_timing2(const struct ast_timing *i, const struct timeval tv)
8363 {
8364  struct ast_tm tm;
8365 
8366  ast_localtime(&tv, &tm, i->timezone);
8367 
8368  /* If it's not the right month, return */
8369  if (!(i->monthmask & (1 << tm.tm_mon)))
8370  return 0;
8371 
8372  /* If it's not that time of the month.... */
8373  /* Warning, tm_mday has range 1..31! */
8374  if (!(i->daymask & (1 << (tm.tm_mday-1))))
8375  return 0;
8376 
8377  /* If it's not the right day of the week */
8378  if (!(i->dowmask & (1 << tm.tm_wday)))
8379  return 0;
8380 
8381  /* Sanity check the hour just to be safe */
8382  if ((tm.tm_hour < 0) || (tm.tm_hour > 23)) {
8383  ast_log(LOG_WARNING, "Insane time...\n");
8384  return 0;
8385  }
8386 
8387  /* Now the tough part, we calculate if it fits
8388  in the right time based on min/hour */
8389  if (!(i->minmask[tm.tm_hour * 2 + (tm.tm_min >= 30 ? 1 : 0)] & (1 << (tm.tm_min >= 30 ? tm.tm_min - 30 : tm.tm_min))))
8390  return 0;
8391 
8392  /* If we got this far, then we're good */
8393  return 1;
8394 }
8395 
8397 {
8398  if (i->timezone) {
8399  ast_free(i->timezone);
8400  i->timezone = NULL;
8401  }
8402  return 0;
8403 }
8404 /*
8405  * errno values
8406  * ENOMEM - out of memory
8407  * EBUSY - can't lock
8408  * EEXIST - already included
8409  * EINVAL - there is no existence of context for inclusion
8410  */
8411 int ast_context_add_include2(struct ast_context *con, const char *value,
8412  const char *registrar)
8413 {
8414  struct ast_include *new_include;
8415  char *c;
8416  struct ast_include *i, *il = NULL; /* include, include_last */
8417  int length;
8418  char *p;
8419 
8420  length = sizeof(struct ast_include);
8421  length += 2 * (strlen(value) + 1);
8422 
8423  /* allocate new include structure ... */
8424  if (!(new_include = ast_calloc(1, length)))
8425  return -1;
8426  /* Fill in this structure. Use 'p' for assignments, as the fields
8427  * in the structure are 'const char *'
8428  */
8429  p = new_include->stuff;
8430  new_include->name = p;
8431  strcpy(p, value);
8432  p += strlen(value) + 1;
8433  new_include->rname = p;
8434  strcpy(p, value);
8435  /* Strip off timing info, and process if it is there */
8436  if ( (c = strchr(p, ',')) ) {
8437  *c++ = '\0';
8438  new_include->hastime = ast_build_timing(&(new_include->timing), c);
8439  }
8440  new_include->next = NULL;
8441  new_include->registrar = registrar;
8442 
8443  ast_wrlock_context(con);
8444 
8445  /* ... go to last include and check if context is already included too... */
8446  for (i = con->includes; i; i = i->next) {
8447  if (!strcasecmp(i->name, new_include->name)) {
8448  ast_destroy_timing(&(new_include->timing));
8449  ast_free(new_include);
8450  ast_unlock_context(con);
8451  errno = EEXIST;
8452  return -1;
8453  }
8454  il = i;
8455  }
8456 
8457  /* ... include new context into context list, unlock, return */
8458  if (il)
8459  il->next = new_include;
8460  else
8461  con->includes = new_include;
8462  ast_verb(3, "Including context '%s' in context '%s'\n", new_include->name, ast_get_context_name(con));
8463 
8464  ast_unlock_context(con);
8465 
8466  return 0;
8467 }
8468 
8469 /*
8470  * errno values
8471  * EBUSY - can't lock
8472  * ENOENT - no existence of context
8473  */
8474 int ast_context_add_switch(const char *context, const char *sw, const char *data, int eval, const char *registrar)
8475 {
8476  int ret = -1;
8477  struct ast_context *c;
8478 
8479  c = find_context_locked(context);
8480  if (c) { /* found, add switch to this context */
8481  ret = ast_context_add_switch2(c, sw, data, eval, registrar);
8483  }
8484  return ret;
8485 }
8486 
8487 /*
8488  * errno values
8489  * ENOMEM - out of memory
8490  * EBUSY - can't lock
8491  * EEXIST - already included
8492  * EINVAL - there is no existence of context for inclusion
8493  */
8494 int ast_context_add_switch2(struct ast_context *con, const char *value,
8495  const char *data, int eval, const char *registrar)
8496 {
8497  struct ast_sw *new_sw;
8498  struct ast_sw *i;
8499  int length;
8500  char *p;
8501 
8502  length = sizeof(struct ast_sw);
8503  length += strlen(value) + 1;
8504  if (data)
8505  length += strlen(data);
8506  length++;
8507 
8508  /* allocate new sw structure ... */
8509  if (!(new_sw = ast_calloc(1, length)))
8510  return -1;
8511  /* ... fill in this structure ... */
8512  p = new_sw->stuff;
8513  new_sw->name = p;
8514  strcpy(new_sw->name, value);
8515  p += strlen(value) + 1;
8516  new_sw->data = p;
8517  if (data) {
8518  strcpy(new_sw->data, data);
8519  p += strlen(data) + 1;
8520  } else {
8521  strcpy(new_sw->data, "");
8522  p++;
8523  }
8524  new_sw->eval = eval;
8525  new_sw->registrar = registrar;
8526 
8527  /* ... try to lock this context ... */
8528  ast_wrlock_context(con);
8529 
8530  /* ... go to last sw and check if context is already swd too... */
8531  AST_LIST_TRAVERSE(&con->alts, i, list) {
8532  if (!strcasecmp(i->name, new_sw->name) && !strcasecmp(i->data, new_sw->data)) {
8533  ast_free(new_sw);
8534  ast_unlock_context(con);
8535  errno = EEXIST;
8536  return -1;
8537  }
8538  }
8539 
8540  /* ... sw new context into context list, unlock, return */
8541  AST_LIST_INSERT_TAIL(&con->alts, new_sw, list);
8542 
8543  ast_verb(3, "Including switch '%s/%s' in context '%s'\n", new_sw->name, new_sw->data, ast_get_context_name(con));
8544 
8545  ast_unlock_context(con);
8546 
8547  return 0;
8548 }
8549 
8550 /*
8551  * EBUSY - can't lock
8552  * ENOENT - there is not context existence
8553  */
8554 int ast_context_remove_ignorepat(const char *context, const char *ignorepat, const char *registrar)
8555 {
8556  int ret = -1;
8557  struct ast_context *c;
8558 
8559  c = find_context_locked(context);
8560  if (c) {
8561  ret = ast_context_remove_ignorepat2(c, ignorepat, registrar);
8563  }
8564  return ret;
8565 }
8566 
8567 int ast_context_remove_ignorepat2(struct ast_context *con, const char *ignorepat, const char *registrar)
8568 {
8569  struct ast_ignorepat *ip, *ipl = NULL;
8570 
8571  ast_wrlock_context(con);
8572 
8573  for (ip = con->ignorepats; ip; ip = ip->next) {
8574  if (!strcmp(ip->pattern, ignorepat) &&
8575  (!registrar || (registrar == ip->registrar))) {
8576  if (ipl) {
8577  ipl->next = ip->next;
8578  ast_free(ip);
8579  } else {
8580  con->ignorepats = ip->next;
8581  ast_free(ip);
8582  }
8583  ast_unlock_context(con);
8584  return 0;
8585  }
8586  ipl = ip;
8587  }
8588 
8589  ast_unlock_context(con);
8590  errno = EINVAL;
8591  return -1;
8592 }
8593 
8594 /*
8595  * EBUSY - can't lock
8596  * ENOENT - there is no existence of context
8597  */
8598 int ast_context_add_ignorepat(const char *context, const char *value, const char *registrar)
8599 {
8600  int ret = -1;
8601  struct ast_context *c;
8602 
8603  c = find_context_locked(context);
8604  if (c) {
8605  ret = ast_context_add_ignorepat2(c, value, registrar);
8607  }
8608  return ret;
8609 }
8610 
8611 int ast_context_add_ignorepat2(struct ast_context *con, const char *value, const char *registrar)
8612 {
8613  struct ast_ignorepat *ignorepat, *ignorepatc, *ignorepatl = NULL;
8614  int length;
8615  char *pattern;
8616  length = sizeof(struct ast_ignorepat);
8617  length += strlen(value) + 1;
8618  if (!(ignorepat = ast_calloc(1, length)))
8619  return -1;
8620  /* The cast to char * is because we need to write the initial value.
8621  * The field is not supposed to be modified otherwise. Also, gcc 4.2
8622  * sees the cast as dereferencing a type-punned pointer and warns about
8623  * it. This is the workaround (we're telling gcc, yes, that's really
8624  * what we wanted to do).
8625  */
8626  pattern = (char *) ignorepat->pattern;
8627  strcpy(pattern, value);
8628  ignorepat->next = NULL;
8629  ignorepat->registrar = registrar;
8630  ast_wrlock_context(con);
8631  for (ignorepatc = con->ignorepats; ignorepatc; ignorepatc = ignorepatc->next) {
8632  ignorepatl = ignorepatc;
8633  if (!strcasecmp(ignorepatc->pattern, value)) {
8634  /* Already there */
8635  ast_unlock_context(con);
8636  ast_free(ignorepat);
8637  errno = EEXIST;
8638  return -1;
8639  }
8640  }
8641  if (ignorepatl)
8642  ignorepatl->next = ignorepat;
8643  else
8644  con->ignorepats = ignorepat;
8645  ast_unlock_context(con);
8646  return 0;
8647 
8648 }
8649 
8650 int ast_ignore_pattern(const char *context, const char *pattern)
8651 {
8652  struct ast_context *con = ast_context_find(context);
8653 
8654  if (con) {
8655  struct ast_ignorepat *pat;
8656 
8657  for (pat = con->ignorepats; pat; pat = pat->next) {
8658  if (ast_extension_match(pat->pattern, pattern))
8659  return 1;
8660  }
8661  }
8662 
8663  return 0;
8664 }
8665 
8666 /*
8667  * ast_add_extension_nolock -- use only in situations where the conlock is already held
8668  * ENOENT - no existence of context
8669  *
8670  */
8671 static int ast_add_extension_nolock(const char *context, int replace, const char *extension,
8672  int priority, const char *label, const char *callerid,
8673  const char *application, void *data, void (*datad)(void *), const char *registrar)
8674 {
8675  int ret = -1;
8676  struct ast_context *c;
8677 
8678  c = find_context(context);
8679  if (c) {
8680  ret = ast_add_extension2_lockopt(c, replace, extension, priority, label, callerid,
8681  application, data, datad, registrar, 1);
8682  }
8683 
8684  return ret;
8685 }
8686 /*
8687  * EBUSY - can't lock
8688  * ENOENT - no existence of context
8689  *
8690  */
8691 int ast_add_extension(const char *context, int replace, const char *extension,
8692  int priority, const char *label, const char *callerid,
8693  const char *application, void *data, void (*datad)(void *), const char *registrar)
8694 {
8695  int ret = -1;
8696  struct ast_context *c;
8697 
8698  c = find_context_locked(context);
8699  if (c) {
8700  ret = ast_add_extension2(c, replace, extension, priority, label, callerid,
8701  application, data, datad, registrar);
8703  }
8704 
8705  return ret;
8706 }
8707 
8708 int ast_explicit_goto(struct ast_channel *chan, const char *context, const char *exten, int priority)
8709 {
8710  if (!chan)
8711  return -1;
8712 
8713  ast_channel_lock(chan);
8714 
8715  if (!ast_strlen_zero(context))
8716  ast_copy_string(chan->context, context, sizeof(chan->context));
8717  if (!ast_strlen_zero(exten))
8718  ast_copy_string(chan->exten, exten, sizeof(chan->exten));
8719  if (priority > -1) {
8720  chan->priority = priority;
8721  /* see flag description in channel.h for explanation */
8723  chan->priority--;
8724  }
8725 
8726  ast_channel_unlock(chan);
8727 
8728  return 0;
8729 }
8730 
8731 int ast_async_goto(struct ast_channel *chan, const char *context, const char *exten, int priority)
8732 {
8733  int res = 0;
8734  struct ast_channel *tmpchan;
8735  struct {
8736  char *accountcode;
8737  char *exten;
8738  char *context;
8739  char *linkedid;
8740  char *name;
8741  struct ast_cdr *cdr;
8742  int amaflags;
8743  int state;
8744  format_t readformat;
8745  format_t writeformat;
8746  } tmpvars = { 0, };
8747 
8748  ast_channel_lock(chan);
8749  if (chan->pbx) { /* This channel is currently in the PBX */
8750  ast_explicit_goto(chan, context, exten, priority + 1);
8752  ast_channel_unlock(chan);
8753  return res;
8754  }
8755 
8756  /* In order to do it when the channel doesn't really exist within
8757  * the PBX, we have to make a new channel, masquerade, and start the PBX
8758  * at the new location */
8759  tmpvars.accountcode = ast_strdupa(chan->accountcode);
8760  tmpvars.exten = ast_strdupa(chan->exten);
8761  tmpvars.context = ast_strdupa(chan->context);
8762  tmpvars.linkedid = ast_strdupa(chan->linkedid);
8763  tmpvars.name = ast_strdupa(chan->name);
8764  tmpvars.amaflags = chan->amaflags;
8765  tmpvars.state = chan->_state;
8766  tmpvars.writeformat = chan->writeformat;
8767  tmpvars.readformat = chan->readformat;
8768  tmpvars.cdr = chan->cdr ? ast_cdr_dup(chan->cdr) : NULL;
8769 
8770  ast_channel_unlock(chan);
8771 
8772  /* Do not hold any channel locks while calling channel_alloc() since the function
8773  * locks the channel container when linking the new channel in. */
8774  if (!(tmpchan = ast_channel_alloc(0, tmpvars.state, 0, 0, tmpvars.accountcode, tmpvars.exten, tmpvars.context, tmpvars.linkedid, tmpvars.amaflags, "AsyncGoto/%s", tmpvars.name))) {
8775  ast_cdr_discard(tmpvars.cdr);
8776  return -1;
8777  }
8778 
8779  /* copy the cdr info over */
8780  if (tmpvars.cdr) {
8781  ast_cdr_discard(tmpchan->cdr);
8782  tmpchan->cdr = tmpvars.cdr;
8783  tmpvars.cdr = NULL;
8784  }
8785 
8786  /* Make formats okay */
8787  tmpchan->readformat = tmpvars.readformat;
8788  tmpchan->writeformat = tmpvars.writeformat;
8789 
8790  /* Setup proper location. Never hold another channel lock while calling this function. */
8791  ast_explicit_goto(tmpchan, S_OR(context, tmpvars.context), S_OR(exten, tmpvars.exten), priority);
8792 
8793  /* Masquerade into tmp channel */
8794  if (ast_channel_masquerade(tmpchan, chan)) {
8795  /* Failed to set up the masquerade. It's probably chan_local
8796  * in the middle of optimizing itself out. Sad. :( */
8797  ast_hangup(tmpchan);
8798  tmpchan = NULL;
8799  res = -1;
8800  } else {
8801  ast_do_masquerade(tmpchan);
8802  /* Start the PBX going on our stolen channel */
8803  if (ast_pbx_start(tmpchan)) {
8804  ast_log(LOG_WARNING, "Unable to start PBX on %s\n", tmpchan->name);
8805  ast_hangup(tmpchan);
8806  res = -1;
8807  }
8808  }
8809 
8810  return res;
8811 }
8812 
8813 int ast_async_goto_by_name(const char *channame, const char *context, const char *exten, int priority)
8814 {
8815  struct ast_channel *chan;
8816  int res = -1;
8817 
8818  if ((chan = ast_channel_get_by_name(channame))) {
8819  res = ast_async_goto(chan, context, exten, priority);
8820  chan = ast_channel_unref(chan);
8821  }
8822 
8823  return res;
8824 }
8825 
8826 /*! \brief copy a string skipping whitespace */
8827 static int ext_strncpy(char *dst, const char *src, int len)
8828 {
8829  int count = 0;
8830  int insquares = 0;
8831 
8832  while (*src && (count < len - 1)) {
8833  if (*src == '[') {
8834  insquares = 1;
8835  } else if (*src == ']') {
8836  insquares = 0;
8837  } else if (*src == ' ' && !insquares) {
8838  src++;
8839  continue;
8840  }
8841  *dst = *src;
8842  dst++;
8843  src++;
8844  count++;
8845  }
8846  *dst = '\0';
8847 
8848  return count;
8849 }
8850 
8851 /*!
8852  * \brief add the extension in the priority chain.
8853  * \retval 0 on success.
8854  * \retval -1 on failure.
8855 */
8856 static int add_priority(struct ast_context *con, struct ast_exten *tmp,
8857  struct ast_exten *el, struct ast_exten *e, int replace)
8858 {
8859  struct ast_exten *ep;
8860  struct ast_exten *eh=e;
8861  int repeated_label = 0; /* Track if this label is a repeat, assume no. */
8862 
8863  for (ep = NULL; e ; ep = e, e = e->peer) {
8864  if (e->label && tmp->label && e->priority != tmp->priority && !strcmp(e->label, tmp->label)) {
8865  if (strcmp(e->exten, tmp->exten)) {
8867  "Extension '%s' priority %d in '%s', label '%s' already in use at aliased extension '%s' priority %d\n",
8868  tmp->exten, tmp->priority, con->name, tmp->label, e->exten, e->priority);
8869  } else {
8871  "Extension '%s' priority %d in '%s', label '%s' already in use at priority %d\n",
8872  tmp->exten, tmp->priority, con->name, tmp->label, e->priority);
8873  }
8874  repeated_label = 1;
8875  }
8876  if (e->priority >= tmp->priority) {
8877  break;
8878  }
8879  }
8880 
8881  if (repeated_label) { /* Discard the label since it's a repeat. */
8882  tmp->label = NULL;
8883  }
8884 
8885  if (!e) { /* go at the end, and ep is surely set because the list is not empty */
8887 
8888  if (tmp->label) {
8890  }
8891  ep->peer = tmp;
8892  return 0; /* success */
8893  }
8894  if (e->priority == tmp->priority) {
8895  /* Can't have something exactly the same. Is this a
8896  replacement? If so, replace, otherwise, bonk. */
8897  if (!replace) {
8898  if (strcmp(e->exten, tmp->exten)) {
8900  "Unable to register extension '%s' priority %d in '%s', already in use by aliased extension '%s'\n",
8901  tmp->exten, tmp->priority, con->name, e->exten);
8902  } else {
8904  "Unable to register extension '%s' priority %d in '%s', already in use\n",
8905  tmp->exten, tmp->priority, con->name);
8906  }
8907  if (tmp->datad) {
8908  tmp->datad(tmp->data);
8909  /* if you free this, null it out */
8910  tmp->data = NULL;
8911  }
8912 
8913  ast_free(tmp);
8914  return -1;
8915  }
8916  /* we are replacing e, so copy the link fields and then update
8917  * whoever pointed to e to point to us
8918  */
8919  tmp->next = e->next; /* not meaningful if we are not first in the peer list */
8920  tmp->peer = e->peer; /* always meaningful */
8921  if (ep) { /* We're in the peer list, just insert ourselves */
8923 
8924  if (e->label) {
8926  }
8927 
8929  if (tmp->label) {
8931  }
8932 
8933  ep->peer = tmp;
8934  } else if (el) { /* We're the first extension. Take over e's functions */
8935  struct match_char *x = add_exten_to_pattern_tree(con, e, 1);
8936  tmp->peer_table = e->peer_table;
8937  tmp->peer_label_table = e->peer_label_table;
8940  if (e->label) {
8942  }
8943  if (tmp->label) {
8945  }
8946 
8949  el->next = tmp;
8950  /* The pattern trie points to this exten; replace the pointer,
8951  and all will be well */
8952  if (x) { /* if the trie isn't formed yet, don't sweat this */
8953  if (x->exten) { /* this test for safety purposes */
8954  x->exten = tmp; /* replace what would become a bad pointer */
8955  } else {
8956  ast_log(LOG_ERROR,"Trying to delete an exten from a context, but the pattern tree node returned isn't an extension\n");
8957  }
8958  }
8959  } else { /* We're the very first extension. */
8960  struct match_char *x = add_exten_to_pattern_tree(con, e, 1);
8963  tmp->peer_table = e->peer_table;
8964  tmp->peer_label_table = e->peer_label_table;
8967  if (e->label) {
8969  }
8970  if (tmp->label) {
8972  }
8973 
8976  con->root = tmp;
8977  /* The pattern trie points to this exten; replace the pointer,
8978  and all will be well */
8979  if (x) { /* if the trie isn't formed yet; no problem */
8980  if (x->exten) { /* this test for safety purposes */
8981  x->exten = tmp; /* replace what would become a bad pointer */
8982  } else {
8983  ast_log(LOG_ERROR,"Trying to delete an exten from a context, but the pattern tree node returned isn't an extension\n");
8984  }
8985  }
8986  }
8987  if (tmp->priority == PRIORITY_HINT)
8988  ast_change_hint(e,tmp);
8989  /* Destroy the old one */
8990  if (e->datad)
8991  e->datad(e->data);
8992  ast_free(e);
8993  } else { /* Slip ourselves in just before e */
8994  tmp->peer = e;
8995  tmp->next = e->next; /* extension chain, or NULL if e is not the first extension */
8996  if (ep) { /* Easy enough, we're just in the peer list */
8997  if (tmp->label) {
8999  }
9001  ep->peer = tmp;
9002  } else { /* we are the first in some peer list, so link in the ext list */
9003  tmp->peer_table = e->peer_table;
9004  tmp->peer_label_table = e->peer_label_table;
9005  e->peer_table = 0;
9006  e->peer_label_table = 0;
9008  if (tmp->label) {
9010  }
9013  if (el)
9014  el->next = tmp; /* in the middle... */
9015  else
9016  con->root = tmp; /* ... or at the head */
9017  e->next = NULL; /* e is no more at the head, so e->next must be reset */
9018  }
9019  /* And immediately return success. */
9020  if (tmp->priority == PRIORITY_HINT) {
9021  ast_add_hint(tmp);
9022  }
9023  }
9024  return 0;
9025 }
9026 
9027 /*! \brief
9028  * Main interface to add extensions to the list for out context.
9029  *
9030  * We sort extensions in order of matching preference, so that we can
9031  * stop the search as soon as we find a suitable match.
9032  * This ordering also takes care of wildcards such as '.' (meaning
9033  * "one or more of any character") and '!' (which is 'earlymatch',
9034  * meaning "zero or more of any character" but also impacts the
9035  * return value from CANMATCH and EARLYMATCH.
9036  *
9037  * The extension match rules defined in the devmeeting 2006.05.05 are
9038  * quite simple: WE SELECT THE LONGEST MATCH.
9039  * In detail, "longest" means the number of matched characters in
9040  * the extension. In case of ties (e.g. _XXX and 333) in the length
9041  * of a pattern, we give priority to entries with the smallest cardinality
9042  * (e.g, [5-9] comes before [2-8] before the former has only 5 elements,
9043  * while the latter has 7, etc.
9044  * In case of same cardinality, the first element in the range counts.
9045  * If we still have a tie, any final '!' will make this as a possibly
9046  * less specific pattern.
9047  *
9048  * EBUSY - can't lock
9049  * EEXIST - extension with the same priority exist and no replace is set
9050  *
9051  */
9053  int replace, const char *extension, int priority, const char *label, const char *callerid,
9054  const char *application, void *data, void (*datad)(void *),
9055  const char *registrar)
9056 {
9057  return ast_add_extension2_lockopt(con, replace, extension, priority, label, callerid,
9058  application, data, datad, registrar, 1);
9059 }
9060 
9061 /*!
9062  * \brief Same as ast_add_extension2() but controls the context locking.
9063  *
9064  * \details
9065  * Does all the work of ast_add_extension2, but adds an arg to
9066  * determine if context locking should be done.
9067  */
9069  int replace, const char *extension, int priority, const char *label, const char *callerid,
9070  const char *application, void *data, void (*datad)(void *),
9071  const char *registrar, int lock_context)
9072 {
9073  /*
9074  * Sort extensions (or patterns) according to the rules indicated above.
9075  * These are implemented by the function ext_cmp()).
9076  * All priorities for the same ext/pattern/cid are kept in a list,
9077  * using the 'peer' field as a link field..
9078  */
9079  struct ast_exten *tmp, *tmp2, *e, *el = NULL;
9080  int res;
9081  int length;
9082  char *p;
9083  char expand_buf[VAR_BUF_SIZE];
9084  struct ast_exten dummy_exten = {0};
9085  char dummy_name[1024];
9086 
9087  if (ast_strlen_zero(extension)) {
9088  ast_log(LOG_ERROR,"You have to be kidding-- add exten '' to context %s? Figure out a name and call me back. Action ignored.\n",
9089  con->name);
9090  return -1;
9091  }
9092 
9093  /* If we are adding a hint evalulate in variables and global variables */
9094  if (priority == PRIORITY_HINT && strstr(application, "${") && extension[0] != '_') {
9095  struct ast_channel *c = ast_dummy_channel_alloc();
9096 
9097  if (c) {
9098  ast_copy_string(c->exten, extension, sizeof(c->exten));
9099  ast_copy_string(c->context, con->name, sizeof(c->context));
9100  }
9101  pbx_substitute_variables_helper(c, application, expand_buf, sizeof(expand_buf));
9102  application = expand_buf;
9103  if (c) {
9104  ast_channel_unref(c);
9105  }
9106  }
9107 
9108  length = sizeof(struct ast_exten);
9109  length += strlen(extension) + 1;
9110  length += strlen(application) + 1;
9111  if (label)
9112  length += strlen(label) + 1;
9113  if (callerid)
9114  length += strlen(callerid) + 1;
9115  else
9116  length ++; /* just the '\0' */
9117 
9118  /* Be optimistic: Build the extension structure first */
9119  if (!(tmp = ast_calloc(1, length)))
9120  return -1;
9121 
9122  if (ast_strlen_zero(label)) /* let's turn empty labels to a null ptr */
9123  label = 0;
9124 
9125  /* use p as dst in assignments, as the fields are const char * */
9126  p = tmp->stuff;
9127  if (label) {
9128  tmp->label = p;
9129  strcpy(p, label);
9130  p += strlen(label) + 1;
9131  }
9132  tmp->exten = p;
9133  p += ext_strncpy(p, extension, strlen(extension) + 1) + 1;
9134  tmp->priority = priority;
9135  tmp->cidmatch = p; /* but use p for assignments below */
9136 
9137  /* Blank callerid and NULL callerid are two SEPARATE things. Do NOT confuse the two!!! */
9138  if (callerid) {
9139  p += ext_strncpy(p, callerid, strlen(callerid) + 1) + 1;
9141  } else {
9142  *p++ = '\0';
9144  }
9145  tmp->app = p;
9146  strcpy(p, application);
9147  tmp->parent = con;
9148  tmp->data = data;
9149  tmp->datad = datad;
9150  tmp->registrar = registrar;
9151 
9152  if (lock_context) {
9153  ast_wrlock_context(con);
9154  }
9155 
9156  if (con->pattern_tree) { /* usually, on initial load, the pattern_tree isn't formed until the first find_exten; so if we are adding
9157  an extension, and the trie exists, then we need to incrementally add this pattern to it. */
9158  ast_copy_string(dummy_name, extension, sizeof(dummy_name));
9159  dummy_exten.exten = dummy_name;
9160  dummy_exten.matchcid = AST_EXT_MATCHCID_OFF;
9161  dummy_exten.cidmatch = 0;
9162  tmp2 = ast_hashtab_lookup(con->root_table, &dummy_exten);
9163  if (!tmp2) {
9164  /* hmmm, not in the trie; */
9165  add_exten_to_pattern_tree(con, tmp, 0);
9166  ast_hashtab_insert_safe(con->root_table, tmp); /* for the sake of completeness */
9167  }
9168  }
9169  res = 0; /* some compilers will think it is uninitialized otherwise */
9170  for (e = con->root; e; el = e, e = e->next) { /* scan the extension list */
9171  res = ext_cmp(e->exten, tmp->exten);
9172  if (res == 0) { /* extension match, now look at cidmatch */
9174  res = 0;
9175  else if (tmp->matchcid == AST_EXT_MATCHCID_ON && e->matchcid == AST_EXT_MATCHCID_OFF)
9176  res = 1;
9177  else if (e->matchcid == AST_EXT_MATCHCID_ON && tmp->matchcid == AST_EXT_MATCHCID_OFF)
9178  res = -1;
9179  else
9180  res = ext_cmp(e->cidmatch, tmp->cidmatch);
9181  }
9182  if (res >= 0)
9183  break;
9184  }
9185  if (e && res == 0) { /* exact match, insert in the priority chain */
9186  res = add_priority(con, tmp, el, e, replace);
9187  if (lock_context) {
9188  ast_unlock_context(con);
9189  }
9190  if (res < 0) {
9191  errno = EEXIST; /* XXX do we care ? */
9192  return 0; /* XXX should we return -1 maybe ? */
9193  }
9194  } else {
9195  /*
9196  * not an exact match, this is the first entry with this pattern,
9197  * so insert in the main list right before 'e' (if any)
9198  */
9199  tmp->next = e;
9200  if (el) { /* there is another exten already in this context */
9201  el->next = tmp;
9202  tmp->peer_table = ast_hashtab_create(13,
9207  0);
9213  0);
9214  if (label) {
9216  }
9218  } else { /* this is the first exten in this context */
9219  if (!con->root_table)
9220  con->root_table = ast_hashtab_create(27,
9225  0);
9226  con->root = tmp;
9227  con->root->peer_table = ast_hashtab_create(13,
9232  0);
9238  0);
9239  if (label) {
9241  }
9243 
9244  }
9246  if (lock_context) {
9247  ast_unlock_context(con);
9248  }
9249  if (tmp->priority == PRIORITY_HINT) {
9250  ast_add_hint(tmp);
9251  }
9252  }
9253  if (option_debug) {
9254  if (tmp->matchcid == AST_EXT_MATCHCID_ON) {
9255  ast_debug(1, "Added extension '%s' priority %d (CID match '%s') to %s (%p)\n",
9256  tmp->exten, tmp->priority, tmp->cidmatch, con->name, con);
9257  } else {
9258  ast_debug(1, "Added extension '%s' priority %d to %s (%p)\n",
9259  tmp->exten, tmp->priority, con->name, con);
9260  }
9261  }
9262 
9263  if (tmp->matchcid == AST_EXT_MATCHCID_ON) {
9264  ast_verb(3, "Added extension '%s' priority %d (CID match '%s') to %s\n",
9265  tmp->exten, tmp->priority, tmp->cidmatch, con->name);
9266  } else {
9267  ast_verb(3, "Added extension '%s' priority %d to %s\n",
9268  tmp->exten, tmp->priority, con->name);
9269  }
9270 
9271  return 0;
9272 }
9273 
9274 struct async_stat {
9275  pthread_t p;
9277  char context[AST_MAX_CONTEXT];
9278  char exten[AST_MAX_EXTENSION];
9280  int timeout;
9282  char appdata[1024];
9283 };
9284 
9285 static void *async_wait(void *data)
9286 {
9287  struct async_stat *as = data;
9288  struct ast_channel *chan = as->chan;
9289  int timeout = as->timeout;
9290  int res;
9291  struct ast_frame *f;
9292  struct ast_app *app;
9293  struct timeval start = ast_tvnow();
9294  int ms;
9295 
9296  while ((ms = ast_remaining_ms(start, timeout)) &&
9297  chan->_state != AST_STATE_UP) {
9298  res = ast_waitfor(chan, ms);
9299  if (res < 1)
9300  break;
9301 
9302  f = ast_read(chan);
9303  if (!f)
9304  break;
9305  if (f->frametype == AST_FRAME_CONTROL) {
9306  if ((f->subclass.integer == AST_CONTROL_BUSY) ||
9308  ast_frfree(f);
9309  break;
9310  }
9311  }
9312  ast_frfree(f);
9313  }
9314  if (chan->_state == AST_STATE_UP) {
9315  if (!ast_strlen_zero(as->app)) {
9316  app = pbx_findapp(as->app);
9317  if (app) {
9318  ast_verb(3, "Launching %s(%s) on %s\n", as->app, as->appdata, chan->name);
9319  pbx_exec(chan, app, as->appdata);
9320  } else
9321  ast_log(LOG_WARNING, "No such application '%s'\n", as->app);
9322  } else {
9323  if (!ast_strlen_zero(as->context))
9324  ast_copy_string(chan->context, as->context, sizeof(chan->context));
9325  if (!ast_strlen_zero(as->exten))
9326  ast_copy_string(chan->exten, as->exten, sizeof(chan->exten));
9327  if (as->priority > 0)
9328  chan->priority = as->priority;
9329  /* Run the PBX */
9330  if (ast_pbx_run(chan)) {
9331  ast_log(LOG_ERROR, "Failed to start PBX on %s\n", chan->name);
9332  } else {
9333  /* PBX will have taken care of this */
9334  chan = NULL;
9335  }
9336  }
9337  }
9338  ast_free(as);
9339  if (chan)
9340  ast_hangup(chan);
9341  return NULL;
9342 }
9343 
9344 /*!
9345  * \brief Function to post an empty cdr after a spool call fails.
9346  * \note This function posts an empty cdr for a failed spool call
9347 */
9349 {
9350  /* allocate a channel */
9351  struct ast_channel *chan = ast_dummy_channel_alloc();
9352 
9353  if (!chan)
9354  return -1; /* failure */
9355 
9356  chan->cdr = ast_cdr_alloc();
9357  if (!chan->cdr) {
9358  /* allocation of the cdr failed */
9359  chan = ast_channel_unref(chan); /* free the channel */
9360  return -1; /* return failure */
9361  }
9362 
9363  /* allocation of the cdr was successful */
9364  ast_cdr_init(chan->cdr, chan); /* initialize our channel's cdr */
9365  ast_cdr_start(chan->cdr); /* record the start and stop time */
9366  ast_cdr_end(chan->cdr);
9367  ast_cdr_failed(chan->cdr); /* set the status to failed */
9368  ast_cdr_detach(chan->cdr); /* post and free the record */
9369  chan->cdr = NULL;
9370  chan = ast_channel_unref(chan); /* free the channel */
9371 
9372  return 0; /* success */
9373 }
9374 
9375 int ast_pbx_outgoing_exten(const char *type, format_t format, void *data, int timeout, const char *context, const char *exten, int priority, int *reason, int synchronous, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **channel)
9376 {
9377  struct ast_channel *chan;
9378  struct async_stat *as;
9379  int res = -1, cdr_res = -1;
9380  struct outgoing_helper oh;
9381 
9382  if (synchronous) {
9383  oh.context = context;
9384  oh.exten = exten;
9385  oh.priority = priority;
9386  oh.cid_num = cid_num;
9387  oh.cid_name = cid_name;
9388  oh.account = account;
9389  oh.vars = vars;
9390  oh.parent_channel = NULL;
9391 
9392  chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh);
9393  if (channel) {
9394  *channel = chan;
9395  if (chan)
9396  ast_channel_lock(chan);
9397  }
9398  if (chan) {
9399  if (chan->_state == AST_STATE_UP) {
9400  res = 0;
9401  ast_verb(4, "Channel %s was answered.\n", chan->name);
9402 
9403  if (synchronous > 1) {
9404  if (channel)
9405  ast_channel_unlock(chan);
9406  if (ast_pbx_run(chan)) {
9407  ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name);
9408  if (channel)
9409  *channel = NULL;
9410  ast_hangup(chan);
9411  chan = NULL;
9412  res = -1;
9413  }
9414  } else {
9415  if (ast_pbx_start(chan)) {
9416  ast_log(LOG_ERROR, "Unable to start PBX on %s\n", chan->name);
9417  if (channel) {
9418  *channel = NULL;
9419  ast_channel_unlock(chan);
9420  }
9421  ast_hangup(chan);
9422  res = -1;
9423  }
9424  chan = NULL;
9425  }
9426  } else {
9427  ast_verb(4, "Channel %s was never answered.\n", chan->name);
9428 
9429  if (chan->cdr) { /* update the cdr */
9430  /* here we update the status of the call, which sould be busy.
9431  * if that fails then we set the status to failed */
9432  if (ast_cdr_disposition(chan->cdr, chan->hangupcause))
9433  ast_cdr_failed(chan->cdr);
9434  }
9435 
9436  if (channel) {
9437  *channel = NULL;
9438  ast_channel_unlock(chan);
9439  }
9440  ast_hangup(chan);
9441  chan = NULL;
9442  }
9443  }
9444 
9445  if (res < 0) { /* the call failed for some reason */
9446  if (*reason == 0) { /* if the call failed (not busy or no answer)
9447  * update the cdr with the failed message */
9448  cdr_res = ast_pbx_outgoing_cdr_failed();
9449  if (cdr_res != 0) {
9450  res = cdr_res;
9451  goto outgoing_exten_cleanup;
9452  }
9453  }
9454 
9455  /* create a fake channel and execute the "failed" extension (if it exists) within the requested context */
9456  /* check if "failed" exists */
9457  if (ast_exists_extension(chan, context, "failed", 1, NULL)) {
9458  chan = ast_channel_alloc(0, AST_STATE_DOWN, 0, 0, "", "", "", NULL, 0, "OutgoingSpoolFailed");
9459  if (chan) {
9460  char failed_reason[4] = "";
9461  if (!ast_strlen_zero(context))
9462  ast_copy_string(chan->context, context, sizeof(chan->context));
9463  set_ext_pri(chan, "failed", 1);
9464  ast_set_variables(chan, vars);
9465  snprintf(failed_reason, sizeof(failed_reason), "%d", *reason);
9466  pbx_builtin_setvar_helper(chan, "REASON", failed_reason);
9467  if (account)
9468  ast_cdr_setaccount(chan, account);
9469  if (ast_pbx_run(chan)) {
9470  ast_log(LOG_ERROR, "Unable to run PBX on %s\n", chan->name);
9471  ast_hangup(chan);
9472  }
9473  chan = NULL;
9474  }
9475  }
9476  }
9477  } else {
9478  if (!(as = ast_calloc(1, sizeof(*as)))) {
9479  res = -1;
9480  goto outgoing_exten_cleanup;
9481  }
9482  chan = ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name);
9483  if (channel) {
9484  *channel = chan;
9485  if (chan)
9486  ast_channel_lock(chan);
9487  }
9488  if (!chan) {
9489  ast_free(as);
9490  res = -1;
9491  goto outgoing_exten_cleanup;
9492  }
9493  as->chan = chan;
9494  ast_copy_string(as->context, context, sizeof(as->context));
9495  set_ext_pri(as->chan, exten, priority);
9496  as->timeout = timeout;
9497  ast_set_variables(chan, vars);
9498  if (account)
9499  ast_cdr_setaccount(chan, account);
9500  if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) {
9501  ast_log(LOG_WARNING, "Failed to start async wait\n");
9502  ast_free(as);
9503  if (channel) {
9504  *channel = NULL;
9505  ast_channel_unlock(chan);
9506  }
9507  ast_hangup(chan);
9508  res = -1;
9509  goto outgoing_exten_cleanup;
9510  }
9511  res = 0;
9512  }
9513 outgoing_exten_cleanup:
9514  ast_variables_destroy(vars);
9515  return res;
9516 }
9517 
9518 struct app_tmp {
9520  pthread_t t;
9522  AST_STRING_FIELD(app);
9523  AST_STRING_FIELD(data);
9524  );
9525 };
9526 
9527 /*! \brief run the application and free the descriptor once done */
9528 static void *ast_pbx_run_app(void *data)
9529 {
9530  struct app_tmp *tmp = data;
9531  struct ast_app *app;
9532  app = pbx_findapp(tmp->app);
9533  if (app) {
9534  ast_verb(4, "Launching %s(%s) on %s\n", tmp->app, tmp->data, tmp->chan->name);
9535  pbx_exec(tmp->chan, app, tmp->data);
9536  } else
9537  ast_log(LOG_WARNING, "No such application '%s'\n", tmp->app);
9538  ast_hangup(tmp->chan);
9540  ast_free(tmp);
9541  return NULL;
9542 }
9543 
9544 int ast_pbx_outgoing_app(const char *type, format_t format, void *data, int timeout, const char *app, const char *appdata, int *reason, int synchronous, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel)
9545 {
9546  struct ast_channel *chan;
9547  struct app_tmp *tmp;
9548  int res = -1, cdr_res = -1;
9549  struct outgoing_helper oh;
9550 
9551  memset(&oh, 0, sizeof(oh));
9552  oh.vars = vars;
9553  oh.account = account;
9554 
9555  if (locked_channel)
9556  *locked_channel = NULL;
9557  if (ast_strlen_zero(app)) {
9558  res = -1;
9559  goto outgoing_app_cleanup;
9560  }
9561  if (synchronous) {
9562  chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh);
9563  if (chan) {
9564  ast_set_variables(chan, vars);
9565  if (account)
9566  ast_cdr_setaccount(chan, account);
9567  if (chan->_state == AST_STATE_UP) {
9568  res = 0;
9569  ast_verb(4, "Channel %s was answered.\n", chan->name);
9570  tmp = ast_calloc(1, sizeof(*tmp));
9571  if (!tmp || ast_string_field_init(tmp, 252)) {
9572  if (tmp) {
9573  ast_free(tmp);
9574  }
9575  res = -1;
9576  } else {
9577  ast_string_field_set(tmp, app, app);
9578  ast_string_field_set(tmp, data, appdata);
9579  tmp->chan = chan;
9580  if (synchronous > 1) {
9581  if (locked_channel)
9582  ast_channel_unlock(chan);
9583  ast_pbx_run_app(tmp);
9584  } else {
9585  if (locked_channel)
9586  ast_channel_lock(chan);
9587  if (ast_pthread_create_detached(&tmp->t, NULL, ast_pbx_run_app, tmp)) {
9588  ast_log(LOG_WARNING, "Unable to spawn execute thread on %s: %s\n", chan->name, strerror(errno));
9590  ast_free(tmp);
9591  if (locked_channel)
9592  ast_channel_unlock(chan);
9593  ast_hangup(chan);
9594  res = -1;
9595  } else {
9596  if (locked_channel)
9597  *locked_channel = chan;
9598  }
9599  }
9600  }
9601  } else {
9602  ast_verb(4, "Channel %s was never answered.\n", chan->name);
9603  if (chan->cdr) { /* update the cdr */
9604  /* here we update the status of the call, which sould be busy.
9605  * if that fails then we set the status to failed */
9606  if (ast_cdr_disposition(chan->cdr, chan->hangupcause))
9607  ast_cdr_failed(chan->cdr);
9608  }
9609  ast_hangup(chan);
9610  }
9611  }
9612 
9613  if (res < 0) { /* the call failed for some reason */
9614  if (*reason == 0) { /* if the call failed (not busy or no answer)
9615  * update the cdr with the failed message */
9616  cdr_res = ast_pbx_outgoing_cdr_failed();
9617  if (cdr_res != 0) {
9618  res = cdr_res;
9619  goto outgoing_app_cleanup;
9620  }
9621  }
9622  }
9623 
9624  } else {
9625  struct async_stat *as;
9626  if (!(as = ast_calloc(1, sizeof(*as)))) {
9627  res = -1;
9628  goto outgoing_app_cleanup;
9629  }
9630  chan = __ast_request_and_dial(type, format, NULL, data, timeout, reason, cid_num, cid_name, &oh);
9631  if (!chan) {
9632  ast_free(as);
9633  res = -1;
9634  goto outgoing_app_cleanup;
9635  }
9636  as->chan = chan;
9637  ast_copy_string(as->app, app, sizeof(as->app));
9638  if (appdata)
9639  ast_copy_string(as->appdata, appdata, sizeof(as->appdata));
9640  as->timeout = timeout;
9641  ast_set_variables(chan, vars);
9642  if (account)
9643  ast_cdr_setaccount(chan, account);
9644  /* Start a new thread, and get something handling this channel. */
9645  if (locked_channel)
9646  ast_channel_lock(chan);
9647  if (ast_pthread_create_detached(&as->p, NULL, async_wait, as)) {
9648  ast_log(LOG_WARNING, "Failed to start async wait\n");
9649  ast_free(as);
9650  if (locked_channel)
9651  ast_channel_unlock(chan);
9652  ast_hangup(chan);
9653  res = -1;
9654  goto outgoing_app_cleanup;
9655  } else {
9656  if (locked_channel)
9657  *locked_channel = chan;
9658  }
9659  res = 0;
9660  }
9661 outgoing_app_cleanup:
9662  ast_variables_destroy(vars);
9663  return res;
9664 }
9665 
9666 /* this is the guts of destroying a context --
9667  freeing up the structure, traversing and destroying the
9668  extensions, switches, ignorepats, includes, etc. etc. */
9669 
9671 {
9672  struct ast_include *tmpi;
9673  struct ast_sw *sw;
9674  struct ast_exten *e, *el, *en;
9675  struct ast_ignorepat *ipi;
9676  struct ast_context *tmp = con;
9677 
9678  for (tmpi = tmp->includes; tmpi; ) { /* Free includes */
9679  struct ast_include *tmpil = tmpi;
9680  tmpi = tmpi->next;
9681  ast_free(tmpil);
9682  }
9683  for (ipi = tmp->ignorepats; ipi; ) { /* Free ignorepats */
9684  struct ast_ignorepat *ipl = ipi;
9685  ipi = ipi->next;
9686  ast_free(ipl);
9687  }
9688  if (tmp->registrar)
9689  ast_free(tmp->registrar);
9690 
9691  /* destroy the hash tabs */
9692  if (tmp->root_table) {
9694  }
9695  /* and destroy the pattern tree */
9696  if (tmp->pattern_tree)
9698 
9699  while ((sw = AST_LIST_REMOVE_HEAD(&tmp->alts, list)))
9700  ast_free(sw);
9701  for (e = tmp->root; e;) {
9702  for (en = e->peer; en;) {
9703  el = en;
9704  en = en->peer;
9705  destroy_exten(el);
9706  }
9707  el = e;
9708  e = e->next;
9709  destroy_exten(el);
9710  }
9711  tmp->root = NULL;
9712  ast_rwlock_destroy(&tmp->lock);
9714  ast_free(tmp);
9715 }
9716 
9717 
9718 void __ast_context_destroy(struct ast_context *list, struct ast_hashtab *contexttab, struct ast_context *con, const char *registrar)
9719 {
9720  struct ast_context *tmp, *tmpl=NULL;
9721  struct ast_exten *exten_item, *prio_item;
9722 
9723  for (tmp = list; tmp; ) {
9724  struct ast_context *next = NULL; /* next starting point */
9725  /* The following code used to skip forward to the next
9726  context with matching registrar, but this didn't
9727  make sense; individual priorities registrar'd to
9728  the matching registrar could occur in any context! */
9729  ast_debug(1, "Investigate ctx %s %s\n", tmp->name, tmp->registrar);
9730  if (con) {
9731  for (; tmp; tmpl = tmp, tmp = tmp->next) { /* skip to the matching context */
9732  ast_debug(1, "check ctx %s %s\n", tmp->name, tmp->registrar);
9733  if ( !strcasecmp(tmp->name, con->name) ) {
9734  break; /* found it */
9735  }
9736  }
9737  }
9738 
9739  if (!tmp) /* not found, we are done */
9740  break;
9741  ast_wrlock_context(tmp);
9742 
9743  if (registrar) {
9744  /* then search thru and remove any extens that match registrar. */
9745  struct ast_hashtab_iter *exten_iter;
9746  struct ast_hashtab_iter *prio_iter;
9747  struct ast_ignorepat *ip, *ipl = NULL, *ipn = NULL;
9748  struct ast_include *i, *pi = NULL, *ni = NULL;
9749  struct ast_sw *sw = NULL;
9750 
9751  /* remove any ignorepats whose registrar matches */
9752  for (ip = tmp->ignorepats; ip; ip = ipn) {
9753  ipn = ip->next;
9754  if (!strcmp(ip->registrar, registrar)) {
9755  if (ipl) {
9756  ipl->next = ip->next;
9757  ast_free(ip);
9758  continue; /* don't change ipl */
9759  } else {
9760  tmp->ignorepats = ip->next;
9761  ast_free(ip);
9762  continue; /* don't change ipl */
9763  }
9764  }
9765  ipl = ip;
9766  }
9767  /* remove any includes whose registrar matches */
9768  for (i = tmp->includes; i; i = ni) {
9769  ni = i->next;
9770  if (strcmp(i->registrar, registrar) == 0) {
9771  /* remove from list */
9772  if (pi) {
9773  pi->next = i->next;
9774  /* free include */
9775  ast_free(i);
9776  continue; /* don't change pi */
9777  } else {
9778  tmp->includes = i->next;
9779  /* free include */
9780  ast_free(i);
9781  continue; /* don't change pi */
9782  }
9783  }
9784  pi = i;
9785  }
9786  /* remove any switches whose registrar matches */
9787  AST_LIST_TRAVERSE_SAFE_BEGIN(&tmp->alts, sw, list) {
9788  if (strcmp(sw->registrar,registrar) == 0) {
9790  ast_free(sw);
9791  }
9792  }
9794 
9795  if (tmp->root_table) { /* it is entirely possible that the context is EMPTY */
9796  exten_iter = ast_hashtab_start_traversal(tmp->root_table);
9797  while ((exten_item=ast_hashtab_next(exten_iter))) {
9798  int end_traversal = 1;
9799  prio_iter = ast_hashtab_start_traversal(exten_item->peer_table);
9800  while ((prio_item=ast_hashtab_next(prio_iter))) {
9801  char extension[AST_MAX_EXTENSION];
9802  char cidmatch[AST_MAX_EXTENSION];
9803  if (!prio_item->registrar || strcmp(prio_item->registrar, registrar) != 0) {
9804  continue;
9805  }
9806  ast_verb(3, "Remove %s/%s/%d, registrar=%s; con=%s(%p); con->root=%p\n",
9807  tmp->name, prio_item->exten, prio_item->priority, registrar, con? con->name : "<nil>", con, con? con->root_table: NULL);
9808  ast_copy_string(extension, prio_item->exten, sizeof(extension));
9809  if (prio_item->cidmatch) {
9810  ast_copy_string(cidmatch, prio_item->cidmatch, sizeof(cidmatch));
9811  }
9812  end_traversal &= ast_context_remove_extension_callerid2(tmp, extension, prio_item->priority, cidmatch, prio_item->matchcid, NULL, 1);
9813  }
9814  /* Explanation:
9815  * ast_context_remove_extension_callerid2 will destroy the extension that it comes across. This
9816  * destruction includes destroying the exten's peer_table, which we are currently traversing. If
9817  * ast_context_remove_extension_callerid2 ever should return '0' then this means we have destroyed
9818  * the hashtable which we are traversing, and thus calling ast_hashtab_end_traversal will result
9819  * in reading invalid memory. Thus, if we detect that we destroyed the hashtable, then we will simply
9820  * free the iterator
9821  */
9822  if (end_traversal) {
9823  ast_hashtab_end_traversal(prio_iter);
9824  } else {
9825  ast_free(prio_iter);
9826  }
9827  }
9828  ast_hashtab_end_traversal(exten_iter);
9829  }
9830 
9831  /* delete the context if it's registrar matches, is empty, has refcount of 1, */
9832  /* it's not empty, if it has includes, ignorepats, or switches that are registered from
9833  another registrar. It's not empty if there are any extensions */
9834  if (strcmp(tmp->registrar, registrar) == 0 && tmp->refcount < 2 && !tmp->root && !tmp->ignorepats && !tmp->includes && AST_LIST_EMPTY(&tmp->alts)) {
9835  ast_debug(1, "delete ctx %s %s\n", tmp->name, tmp->registrar);
9836  ast_hashtab_remove_this_object(contexttab, tmp);
9837 
9838  next = tmp->next;
9839  if (tmpl)
9840  tmpl->next = next;
9841  else
9842  contexts = next;
9843  /* Okay, now we're safe to let it go -- in a sense, we were
9844  ready to let it go as soon as we locked it. */
9845  ast_unlock_context(tmp);
9847  } else {
9848  ast_debug(1,"Couldn't delete ctx %s/%s; refc=%d; tmp.root=%p\n", tmp->name, tmp->registrar,
9849  tmp->refcount, tmp->root);
9850  ast_unlock_context(tmp);
9851  next = tmp->next;
9852  tmpl = tmp;
9853  }
9854  } else if (con) {
9855  ast_verb(3, "Deleting context %s registrar=%s\n", tmp->name, tmp->registrar);
9856  ast_debug(1, "delete ctx %s %s\n", tmp->name, tmp->registrar);
9857  ast_hashtab_remove_this_object(contexttab, tmp);
9858 
9859  next = tmp->next;
9860  if (tmpl)
9861  tmpl->next = next;
9862  else
9863  contexts = next;
9864  /* Okay, now we're safe to let it go -- in a sense, we were
9865  ready to let it go as soon as we locked it. */
9866  ast_unlock_context(tmp);
9868  }
9869 
9870  /* if we have a specific match, we are done, otherwise continue */
9871  tmp = con ? NULL : next;
9872  }
9873 }
9874 
9875 void ast_context_destroy(struct ast_context *con, const char *registrar)
9876 {
9880 }
9881 
9882 static void wait_for_hangup(struct ast_channel *chan, const void *data)
9883 {
9884  int res;
9885  struct ast_frame *f;
9886  double waitsec;
9887  int waittime;
9888 
9889  if (ast_strlen_zero(data) || (sscanf(data, "%30lg", &waitsec) != 1) || (waitsec < 0))
9890  waitsec = -1;
9891  if (waitsec > -1) {
9892  waittime = waitsec * 1000.0;
9893  ast_safe_sleep(chan, waittime);
9894  } else do {
9895  res = ast_waitfor(chan, -1);
9896  if (res < 0)
9897  return;
9898  f = ast_read(chan);
9899  if (f)
9900  ast_frfree(f);
9901  } while(f);
9902 }
9903 
9904 /*!
9905  * \ingroup applications
9906  */
9907 static int pbx_builtin_proceeding(struct ast_channel *chan, const char *data)
9908 {
9910  return 0;
9911 }
9912 
9913 /*!
9914  * \ingroup applications
9915  */
9916 static int pbx_builtin_progress(struct ast_channel *chan, const char *data)
9917 {
9919  return 0;
9920 }
9921 
9922 /*!
9923  * \ingroup applications
9924  */
9925 static int pbx_builtin_ringing(struct ast_channel *chan, const char *data)
9926 {
9928  return 0;
9929 }
9930 
9931 /*!
9932  * \ingroup applications
9933  */
9934 static int pbx_builtin_busy(struct ast_channel *chan, const char *data)
9935 {
9937  /* Don't change state of an UP channel, just indicate
9938  busy in audio */
9939  if (chan->_state != AST_STATE_UP) {
9941  ast_cdr_busy(chan->cdr);
9942  }
9943  wait_for_hangup(chan, data);
9944  return -1;
9945 }
9946 
9947 /*!
9948  * \ingroup applications
9949  */
9950 static int pbx_builtin_congestion(struct ast_channel *chan, const char *data)
9951 {
9953  /* Don't change state of an UP channel, just indicate
9954  congestion in audio */
9955  if (chan->_state != AST_STATE_UP)
9957  wait_for_hangup(chan, data);
9958  return -1;
9959 }
9960 
9961 /*!
9962  * \ingroup applications
9963  */
9964 static int pbx_builtin_answer(struct ast_channel *chan, const char *data)
9965 {
9966  int delay = 0;
9967  int answer_cdr = 1;
9968  char *parse;
9970  AST_APP_ARG(delay);
9971  AST_APP_ARG(answer_cdr);
9972  );
9973 
9974  if (ast_strlen_zero(data)) {
9975  return __ast_answer(chan, 0, 1);
9976  }
9977 
9978  parse = ast_strdupa(data);
9979 
9980  AST_STANDARD_APP_ARGS(args, parse);
9981 
9982  if (!ast_strlen_zero(args.delay) && (chan->_state != AST_STATE_UP))
9983  delay = atoi(data);
9984 
9985  if (delay < 0) {
9986  delay = 0;
9987  }
9988 
9989  if (!ast_strlen_zero(args.answer_cdr) && !strcasecmp(args.answer_cdr, "nocdr")) {
9990  answer_cdr = 0;
9991  }
9992 
9993  return __ast_answer(chan, delay, answer_cdr);
9994 }
9995 
9996 static int pbx_builtin_incomplete(struct ast_channel *chan, const char *data)
9997 {
9998  const char *options = data;
9999  int answer = 1;
10000 
10001  /* Some channels can receive DTMF in unanswered state; some cannot */
10002  if (!ast_strlen_zero(options) && strchr(options, 'n')) {
10003  answer = 0;
10004  }
10005 
10006  /* If the channel is hungup, stop waiting */
10007  if (ast_check_hangup(chan)) {
10008  return -1;
10009  } else if (chan->_state != AST_STATE_UP && answer) {
10010  __ast_answer(chan, 0, 1);
10011  }
10012 
10014 
10015  return AST_PBX_INCOMPLETE;
10016 }
10017 
10023 });
10024 
10025 /*!
10026  * \ingroup applications
10027  */
10028 static int pbx_builtin_resetcdr(struct ast_channel *chan, const char *data)
10029 {
10030  char *args;
10031  struct ast_flags flags = { 0 };
10032 
10033  if (!ast_strlen_zero(data)) {
10034  args = ast_strdupa(data);
10035  ast_app_parse_options(resetcdr_opts, &flags, NULL, args);
10036  }
10037 
10038  ast_cdr_reset(chan->cdr, &flags);
10039 
10040  return 0;
10041 }
10042 
10043 /*!
10044  * \ingroup applications
10045  */
10046 static int pbx_builtin_setamaflags(struct ast_channel *chan, const char *data)
10047 {
10048  /* Copy the AMA Flags as specified */
10049  ast_channel_lock(chan);
10050  ast_cdr_setamaflags(chan, data ? data : "");
10051  ast_channel_unlock(chan);
10052  return 0;
10053 }
10054 
10055 /*!
10056  * \ingroup applications
10057  */
10058 static int pbx_builtin_hangup(struct ast_channel *chan, const char *data)
10059 {
10060  ast_set_hangupsource(chan, "dialplan/builtin", 0);
10061 
10062  if (!ast_strlen_zero(data)) {
10063  int cause;
10064  char *endptr;
10065 
10066  if ((cause = ast_str2cause(data)) > -1) {
10067  chan->hangupcause = cause;
10068  return -1;
10069  }
10070 
10071  cause = strtol((const char *) data, &endptr, 10);
10072  if (cause != 0 || (data != endptr)) {
10073  chan->hangupcause = cause;
10074  return -1;
10075  }
10076 
10077  ast_log(LOG_WARNING, "Invalid cause given to Hangup(): \"%s\"\n", (char *) data);
10078  }
10079 
10080  if (!chan->hangupcause) {
10082  }
10083 
10084  return -1;
10085 }
10086 
10087 /*!
10088  * \ingroup functions
10089  */
10090 static int testtime_write(struct ast_channel *chan, const char *cmd, char *var, const char *value)
10091 {
10092  struct ast_tm tm;
10093  struct timeval tv;
10094  char *remainder, result[30], timezone[80];
10095 
10096  /* Turn off testing? */
10097  if (!pbx_checkcondition(value)) {
10098  pbx_builtin_setvar_helper(chan, "TESTTIME", NULL);
10099  return 0;
10100  }
10101 
10102  /* Parse specified time */
10103  if (!(remainder = ast_strptime(value, "%Y/%m/%d %H:%M:%S", &tm))) {
10104  return -1;
10105  }
10106  sscanf(remainder, "%79s", timezone);
10107  tv = ast_mktime(&tm, S_OR(timezone, NULL));
10108 
10109  snprintf(result, sizeof(result), "%ld", (long) tv.tv_sec);
10110  pbx_builtin_setvar_helper(chan, "__TESTTIME", result);
10111  return 0;
10112 }
10113 
10115  .name = "TESTTIME",
10116  .write = testtime_write,
10117 };
10118 
10119 /*!
10120  * \ingroup applications
10121  */
10122 static int pbx_builtin_gotoiftime(struct ast_channel *chan, const char *data)
10123 {
10124  char *s, *ts, *branch1, *branch2, *branch;
10125  struct ast_timing timing;
10126  const char *ctime;
10127  struct timeval tv = ast_tvnow();
10128  long timesecs;
10129 
10130  if (!chan) {
10131  ast_log(LOG_WARNING, "GotoIfTime requires a channel on which to operate\n");
10132  return -1;
10133  }
10134 
10135  if (ast_strlen_zero(data)) {
10136  ast_log(LOG_WARNING, "GotoIfTime requires an argument:\n <time range>,<days of week>,<days of month>,<months>[,<timezone>]?'labeliftrue':'labeliffalse'\n");
10137  return -1;
10138  }
10139 
10140  ts = s = ast_strdupa(data);
10141 
10142  ast_channel_lock(chan);
10143  if ((ctime = pbx_builtin_getvar_helper(chan, "TESTTIME")) && sscanf(ctime, "%ld", &timesecs) == 1) {
10144  tv.tv_sec = timesecs;
10145  } else if (ctime) {
10146  ast_log(LOG_WARNING, "Using current time to evaluate\n");
10147  /* Reset when unparseable */
10148  pbx_builtin_setvar_helper(chan, "TESTTIME", NULL);
10149  }
10150  ast_channel_unlock(chan);
10151 
10152  /* Separate the Goto path */
10153  strsep(&ts, "?");
10154  branch1 = strsep(&ts,":");
10155  branch2 = strsep(&ts,"");
10156 
10157  /* struct ast_include include contained garbage here, fixed by zeroing it on get_timerange */
10158  if (ast_build_timing(&timing, s) && ast_check_timing2(&timing, tv)) {
10159  branch = branch1;
10160  } else {
10161  branch = branch2;
10162  }
10163  ast_destroy_timing(&timing);
10164 
10165  if (ast_strlen_zero(branch)) {
10166  ast_debug(1, "Not taking any branch\n");
10167  return 0;
10168  }
10169 
10170  return pbx_builtin_goto(chan, branch);
10171 }
10172 
10173 /*!
10174  * \ingroup applications
10175  */
10176 static int pbx_builtin_execiftime(struct ast_channel *chan, const char *data)
10177 {
10178  char *s, *appname;
10179  struct ast_timing timing;
10180  struct ast_app *app;
10181  static const char * const usage = "ExecIfTime requires an argument:\n <time range>,<days of week>,<days of month>,<months>[,<timezone>]?<appname>[(<appargs>)]";
10182 
10183  if (ast_strlen_zero(data)) {
10184  ast_log(LOG_WARNING, "%s\n", usage);
10185  return -1;
10186  }
10187 
10188  appname = ast_strdupa(data);
10189 
10190  s = strsep(&appname, "?"); /* Separate the timerange and application name/data */
10191  if (!appname) { /* missing application */
10192  ast_log(LOG_WARNING, "%s\n", usage);
10193  return -1;
10194  }
10195 
10196  if (!ast_build_timing(&timing, s)) {
10197  ast_log(LOG_WARNING, "Invalid Time Spec: %s\nCorrect usage: %s\n", s, usage);
10198  ast_destroy_timing(&timing);
10199  return -1;
10200  }
10201 
10202  if (!ast_check_timing(&timing)) { /* outside the valid time window, just return */
10203  ast_destroy_timing(&timing);
10204  return 0;
10205  }
10206  ast_destroy_timing(&timing);
10207 
10208  /* now split appname(appargs) */
10209  if ((s = strchr(appname, '('))) {
10210  char *e;
10211  *s++ = '\0';
10212  if ((e = strrchr(s, ')')))
10213  *e = '\0';
10214  else
10215  ast_log(LOG_WARNING, "Failed to find closing parenthesis\n");
10216  }
10217 
10218 
10219  if ((app = pbx_findapp(appname))) {
10220  return pbx_exec(chan, app, S_OR(s, ""));
10221  } else {
10222  ast_log(LOG_WARNING, "Cannot locate application %s\n", appname);
10223  return -1;
10224  }
10225 }
10226 
10227 /*!
10228  * \ingroup applications
10229  */
10230 static int pbx_builtin_wait(struct ast_channel *chan, const char *data)
10231 {
10232  int ms;
10233 
10234  /* Wait for "n" seconds */
10235  if (!ast_app_parse_timelen(data, &ms, TIMELEN_SECONDS) && ms > 0) {
10236  return ast_safe_sleep(chan, ms);
10237  }
10238  return 0;
10239 }
10240 
10241 /*!
10242  * \ingroup applications
10243  */
10244 static int pbx_builtin_waitexten(struct ast_channel *chan, const char *data)
10245 {
10246  int ms, res;
10247  struct ast_flags flags = {0};
10248  char *opts[1] = { NULL };
10249  char *parse;
10251  AST_APP_ARG(timeout);
10252  AST_APP_ARG(options);
10253  );
10254 
10255  if (!ast_strlen_zero(data)) {
10256  parse = ast_strdupa(data);
10257  AST_STANDARD_APP_ARGS(args, parse);
10258  } else
10259  memset(&args, 0, sizeof(args));
10260 
10261  if (args.options)
10262  ast_app_parse_options(waitexten_opts, &flags, opts, args.options);
10263 
10264  if (ast_test_flag(&flags, WAITEXTEN_MOH) && !opts[0] ) {
10265  ast_log(LOG_WARNING, "The 'm' option has been specified for WaitExten without a class.\n");
10266  } else if (ast_test_flag(&flags, WAITEXTEN_MOH)) {
10267  ast_indicate_data(chan, AST_CONTROL_HOLD, S_OR(opts[0], NULL),
10268  !ast_strlen_zero(opts[0]) ? strlen(opts[0]) + 1 : 0);
10269  } else if (ast_test_flag(&flags, WAITEXTEN_DIALTONE)) {
10270  struct ast_tone_zone_sound *ts = ast_get_indication_tone(chan->zone, "dial");
10271  if (ts) {
10272  ast_playtones_start(chan, 0, ts->data, 0);
10273  ts = ast_tone_zone_sound_unref(ts);
10274  } else {
10275  ast_tonepair_start(chan, 350, 440, 0, 0);
10276  }
10277  }
10278  /* Wait for "n" seconds */
10279  if (!ast_app_parse_timelen(args.timeout, &ms, TIMELEN_SECONDS) && ms > 0) {
10280  /* Yay! */
10281  } else if (chan->pbx) {
10282  ms = chan->pbx->rtimeoutms;
10283  } else {
10284  ms = 10000;
10285  }
10286 
10287  res = ast_waitfordigit(chan, ms);
10288  if (!res) {
10289  if (ast_check_hangup(chan)) {
10290  /* Call is hungup for some reason. */
10291  res = -1;
10292  } else if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 1,
10293  S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
10294  ast_verb(3, "Timeout on %s, continuing...\n", chan->name);
10295  } else if (ast_exists_extension(chan, chan->context, "t", 1,
10296  S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
10297  ast_verb(3, "Timeout on %s, going to 't'\n", chan->name);
10298  set_ext_pri(chan, "t", 0); /* 0 will become 1, next time through the loop */
10299  } else if (ast_exists_extension(chan, chan->context, "e", 1,
10300  S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
10301  raise_exception(chan, "RESPONSETIMEOUT", 0); /* 0 will become 1, next time through the loop */
10302  } else {
10303  ast_log(LOG_WARNING, "Timeout but no rule 't' or 'e' in context '%s'\n",
10304  chan->context);
10305  res = -1;
10306  }
10307  }
10308 
10309  if (ast_test_flag(&flags, WAITEXTEN_MOH))
10311  else if (ast_test_flag(&flags, WAITEXTEN_DIALTONE))
10312  ast_playtones_stop(chan);
10313 
10314  return res;
10315 }
10316 
10317 /*!
10318  * \ingroup applications
10319  */
10320 static int pbx_builtin_background(struct ast_channel *chan, const char *data)
10321 {
10322  int res = 0;
10323  int mres = 0;
10324  struct ast_flags flags = {0};
10325  char *parse, exten[2] = "";
10327  AST_APP_ARG(filename);
10328  AST_APP_ARG(options);
10329  AST_APP_ARG(lang);
10330  AST_APP_ARG(context);
10331  );
10332 
10333  if (ast_strlen_zero(data)) {
10334  ast_log(LOG_WARNING, "Background requires an argument (filename)\n");
10335  return -1;
10336  }
10337 
10338  parse = ast_strdupa(data);
10339 
10340  AST_STANDARD_APP_ARGS(args, parse);
10341 
10342  if (ast_strlen_zero(args.lang))
10343  args.lang = (char *)chan->language; /* XXX this is const */
10344 
10345  if (ast_strlen_zero(args.context)) {
10346  const char *context;
10347  ast_channel_lock(chan);
10348  if ((context = pbx_builtin_getvar_helper(chan, "MACRO_CONTEXT"))) {
10349  args.context = ast_strdupa(context);
10350  } else {
10351  args.context = chan->context;
10352  }
10353  ast_channel_unlock(chan);
10354  }
10355 
10356  if (args.options) {
10357  if (!strcasecmp(args.options, "skip"))
10358  flags.flags = BACKGROUND_SKIP;
10359  else if (!strcasecmp(args.options, "noanswer"))
10360  flags.flags = BACKGROUND_NOANSWER;
10361  else
10362  ast_app_parse_options(background_opts, &flags, NULL, args.options);
10363  }
10364 
10365  /* Answer if need be */
10366  if (chan->_state != AST_STATE_UP) {
10367  if (ast_test_flag(&flags, BACKGROUND_SKIP)) {
10368  goto done;
10369  } else if (!ast_test_flag(&flags, BACKGROUND_NOANSWER)) {
10370  res = ast_answer(chan);
10371  }
10372  }
10373 
10374  if (!res) {
10375  char *back = ast_strip(args.filename);
10376  char *front;
10377 
10378  ast_stopstream(chan); /* Stop anything playing */
10379  /* Stream the list of files */
10380  while (!res && (front = strsep(&back, "&")) ) {
10381  if ( (res = ast_streamfile(chan, front, args.lang)) ) {
10382  ast_log(LOG_WARNING, "ast_streamfile failed on %s for %s\n", chan->name, (char*)data);
10383  res = 0;
10384  mres = 1;
10385  break;
10386  }
10387  if (ast_test_flag(&flags, BACKGROUND_PLAYBACK)) {
10388  res = ast_waitstream(chan, "");
10389  } else if (ast_test_flag(&flags, BACKGROUND_MATCHEXTEN)) {
10390  res = ast_waitstream_exten(chan, args.context);
10391  } else {
10392  res = ast_waitstream(chan, AST_DIGIT_ANY);
10393  }
10394  ast_stopstream(chan);
10395  }
10396  }
10397 
10398  /*
10399  * If the single digit DTMF is an extension in the specified context, then
10400  * go there and signal no DTMF. Otherwise, we should exit with that DTMF.
10401  * If we're in Macro, we'll exit and seek that DTMF as the beginning of an
10402  * extension in the Macro's calling context. If we're not in Macro, then
10403  * we'll simply seek that extension in the calling context. Previously,
10404  * someone complained about the behavior as it related to the interior of a
10405  * Gosub routine, and the fix (#14011) inadvertently broke FreePBX
10406  * (#14940). This change should fix both of these situations, but with the
10407  * possible incompatibility that if a single digit extension does not exist
10408  * (but a longer extension COULD have matched), it would have previously
10409  * gone immediately to the "i" extension, but will now need to wait for a
10410  * timeout.
10411  *
10412  * Later, we had to add a flag to disable this workaround, because AGI
10413  * users can EXEC Background and reasonably expect that the DTMF code will
10414  * be returned (see #16434).
10415  */
10417  && (exten[0] = res)
10418  && ast_canmatch_extension(chan, args.context, exten, 1,
10419  S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))
10420  && !ast_matchmore_extension(chan, args.context, exten, 1,
10421  S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL))) {
10422  snprintf(chan->exten, sizeof(chan->exten), "%c", res);
10423  ast_copy_string(chan->context, args.context, sizeof(chan->context));
10424  chan->priority = 0;
10425  res = 0;
10426  }
10427 done:
10428  pbx_builtin_setvar_helper(chan, "BACKGROUNDSTATUS", mres ? "FAILED" : "SUCCESS");
10429  return res;
10430 }
10431 
10432 /*! Goto
10433  * \ingroup applications
10434  */
10435 static int pbx_builtin_goto(struct ast_channel *chan, const char *data)
10436 {
10437  int res = ast_parseable_goto(chan, data);
10438  if (!res)
10439  ast_verb(3, "Goto (%s,%s,%d)\n", chan->context, chan->exten, chan->priority + 1);
10440  return res;
10441 }
10442 
10443 
10444 int pbx_builtin_serialize_variables(struct ast_channel *chan, struct ast_str **buf)
10445 {
10446  struct ast_var_t *variables;
10447  const char *var, *val;
10448  int total = 0;
10449 
10450  if (!chan)
10451  return 0;
10452 
10453  ast_str_reset(*buf);
10454 
10455  ast_channel_lock(chan);
10456 
10457  AST_LIST_TRAVERSE(&chan->varshead, variables, entries) {
10458  if ((var = ast_var_name(variables)) && (val = ast_var_value(variables))
10459  /* && !ast_strlen_zero(var) && !ast_strlen_zero(val) */
10460  ) {
10461  if (ast_str_append(buf, 0, "%s=%s\n", var, val) < 0) {
10462  ast_log(LOG_ERROR, "Data Buffer Size Exceeded!\n");
10463  break;
10464  } else
10465  total++;
10466  } else
10467  break;
10468  }
10469 
10470  ast_channel_unlock(chan);
10471 
10472  return total;
10473 }
10474 
10475 const char *pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
10476 {
10477  struct ast_var_t *variables;
10478  const char *ret = NULL;
10479  int i;
10480  struct varshead *places[2] = { NULL, &globals };
10481 
10482  if (!name)
10483  return NULL;
10484 
10485  if (chan) {
10486  ast_channel_lock(chan);
10487  places[0] = &chan->varshead;
10488  }
10489 
10490  for (i = 0; i < 2; i++) {
10491  if (!places[i])
10492  continue;
10493  if (places[i] == &globals)
10495  AST_LIST_TRAVERSE(places[i], variables, entries) {
10496  if (!strcmp(name, ast_var_name(variables))) {
10497  ret = ast_var_value(variables);
10498  break;
10499  }
10500  }
10501  if (places[i] == &globals)
10503  if (ret)
10504  break;
10505  }
10506 
10507  if (chan)
10508  ast_channel_unlock(chan);
10509 
10510  return ret;
10511 }
10512 
10513 void pbx_builtin_pushvar_helper(struct ast_channel *chan, const char *name, const char *value)
10514 {
10515  struct ast_var_t *newvariable;
10516  struct varshead *headp;
10517 
10518  if (name[strlen(name)-1] == ')') {
10519  char *function = ast_strdupa(name);
10520 
10521  ast_log(LOG_WARNING, "Cannot push a value onto a function\n");
10522  ast_func_write(chan, function, value);
10523  return;
10524  }
10525 
10526  if (chan) {
10527  ast_channel_lock(chan);
10528  headp = &chan->varshead;
10529  } else {
10531  headp = &globals;
10532  }
10533 
10534  if (value && (newvariable = ast_var_assign(name, value))) {
10535  if (headp == &globals)
10536  ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value);
10537  AST_LIST_INSERT_HEAD(headp, newvariable, entries);
10538  }
10539 
10540  if (chan)
10541  ast_channel_unlock(chan);
10542  else
10544 }
10545 
10546 int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
10547 {
10548  struct ast_var_t *newvariable;
10549  struct varshead *headp;
10550  const char *nametail = name;
10551 
10552  if (name[strlen(name) - 1] == ')') {
10553  char *function = ast_strdupa(name);
10554 
10555  return ast_func_write(chan, function, value);
10556  }
10557 
10558  if (chan) {
10559  ast_channel_lock(chan);
10560  headp = &chan->varshead;
10561  } else {
10563  headp = &globals;
10564  }
10565 
10566  /* For comparison purposes, we have to strip leading underscores */
10567  if (*nametail == '_') {
10568  nametail++;
10569  if (*nametail == '_')
10570  nametail++;
10571  }
10572 
10573  AST_LIST_TRAVERSE_SAFE_BEGIN(headp, newvariable, entries) {
10574  if (strcmp(ast_var_name(newvariable), nametail) == 0) {
10575  /* there is already such a variable, delete it */
10576  AST_LIST_REMOVE_CURRENT(entries);
10577  ast_var_delete(newvariable);
10578  break;
10579  }
10580  }
10582 
10583  if (value && (newvariable = ast_var_assign(name, value))) {
10584  if (headp == &globals)
10585  ast_verb(2, "Setting global variable '%s' to '%s'\n", name, value);
10586  AST_LIST_INSERT_HEAD(headp, newvariable, entries);
10588  "Channel: %s\r\n"
10589  "Variable: %s\r\n"
10590  "Value: %s\r\n"
10591  "Uniqueid: %s\r\n",
10592  chan ? chan->name : "none", name, value,
10593  chan ? chan->uniqueid : "none");
10594  }
10595 
10596  if (chan)
10597  ast_channel_unlock(chan);
10598  else
10600  return 0;
10601 }
10602 
10603 int pbx_builtin_setvar(struct ast_channel *chan, const char *data)
10604 {
10605  char *name, *value, *mydata;
10606 
10607  if (ast_compat_app_set) {
10608  return pbx_builtin_setvar_multiple(chan, data);
10609  }
10610 
10611  if (ast_strlen_zero(data)) {
10612  ast_log(LOG_WARNING, "Set requires one variable name/value pair.\n");
10613  return 0;
10614  }
10615 
10616  mydata = ast_strdupa(data);
10617  name = strsep(&mydata, "=");
10618  value = mydata;
10619  if (!value) {
10620  ast_log(LOG_WARNING, "Set requires an '=' to be a valid assignment.\n");
10621  return 0;
10622  }
10623 
10624  if (strchr(name, ' ')) {
10625  ast_log(LOG_WARNING, "Please avoid unnecessary spaces on variables as it may lead to unexpected results ('%s' set to '%s').\n", name, mydata);
10626  }
10627 
10628  pbx_builtin_setvar_helper(chan, name, value);
10629 
10630  return 0;
10631 }
10632 
10633 int pbx_builtin_setvar_multiple(struct ast_channel *chan, const char *vdata)
10634 {
10635  char *data;
10636  int x;
10638  AST_APP_ARG(pair)[24];
10639  );
10640  AST_DECLARE_APP_ARGS(pair,
10641  AST_APP_ARG(name);
10642  AST_APP_ARG(value);
10643  );
10644 
10645  if (ast_strlen_zero(vdata)) {
10646  ast_log(LOG_WARNING, "MSet requires at least one variable name/value pair.\n");
10647  return 0;
10648  }
10649 
10650  data = ast_strdupa(vdata);
10651  AST_STANDARD_APP_ARGS(args, data);
10652 
10653  for (x = 0; x < args.argc; x++) {
10654  AST_NONSTANDARD_APP_ARGS(pair, args.pair[x], '=');
10655  if (pair.argc == 2) {
10656  pbx_builtin_setvar_helper(chan, pair.name, pair.value);
10657  if (strchr(pair.name, ' '))
10658  ast_log(LOG_WARNING, "Please avoid unnecessary spaces on variables as it may lead to unexpected results ('%s' set to '%s').\n", pair.name, pair.value);
10659  } else if (!chan) {
10660  ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '='\n", pair.name);
10661  } else {
10662  ast_log(LOG_WARNING, "MSet: ignoring entry '%s' with no '=' (in %s@%s:%d\n", pair.name, chan->exten, chan->context, chan->priority);
10663  }
10664  }
10665 
10666  return 0;
10667 }
10668 
10669 int pbx_builtin_importvar(struct ast_channel *chan, const char *data)
10670 {
10671  char *name;
10672  char *value;
10673  char *channel;
10674  char tmp[VAR_BUF_SIZE];
10675  static int deprecation_warning = 0;
10676 
10677  if (ast_strlen_zero(data)) {
10678  ast_log(LOG_WARNING, "Ignoring, since there is no variable to set\n");
10679  return 0;
10680  }
10681  tmp[0] = 0;
10682  if (!deprecation_warning) {
10683  ast_log(LOG_WARNING, "ImportVar is deprecated. Please use Set(varname=${IMPORT(channel,variable)}) instead.\n");
10684  deprecation_warning = 1;
10685  }
10686 
10687  value = ast_strdupa(data);
10688  name = strsep(&value,"=");
10689  channel = strsep(&value,",");
10690  if (channel && value && name) { /*! \todo XXX should do !ast_strlen_zero(..) of the args ? */
10691  struct ast_channel *chan2 = ast_channel_get_by_name(channel);
10692  if (chan2) {
10693  char *s = ast_alloca(strlen(value) + 4);
10694  sprintf(s, "${%s}", value);
10695  pbx_substitute_variables_helper(chan2, s, tmp, sizeof(tmp) - 1);
10696  chan2 = ast_channel_unref(chan2);
10697  }
10698  pbx_builtin_setvar_helper(chan, name, tmp);
10699  }
10700 
10701  return(0);
10702 }
10703 
10704 static int pbx_builtin_noop(struct ast_channel *chan, const char *data)
10705 {
10706  return 0;
10707 }
10708 
10710 {
10711  struct ast_var_t *vardata;
10712 
10714  while ((vardata = AST_LIST_REMOVE_HEAD(&globals, entries)))
10715  ast_var_delete(vardata);
10717 }
10718 
10719 int pbx_checkcondition(const char *condition)
10720 {
10721  int res;
10722  if (ast_strlen_zero(condition)) { /* NULL or empty strings are false */
10723  return 0;
10724  } else if (sscanf(condition, "%30d", &res) == 1) { /* Numbers are evaluated for truth */
10725  return res;
10726  } else { /* Strings are true */
10727  return 1;
10728  }
10729 }
10730 
10731 static int pbx_builtin_gotoif(struct ast_channel *chan, const char *data)
10732 {
10733  char *condition, *branch1, *branch2, *branch;
10734  char *stringp;
10735 
10736  if (ast_strlen_zero(data)) {
10737  ast_log(LOG_WARNING, "Ignoring, since there is no variable to check\n");
10738  return 0;
10739  }
10740 
10741  stringp = ast_strdupa(data);
10742  condition = strsep(&stringp,"?");
10743  branch1 = strsep(&stringp,":");
10744  branch2 = strsep(&stringp,"");
10745  branch = pbx_checkcondition(condition) ? branch1 : branch2;
10746 
10747  if (ast_strlen_zero(branch)) {
10748  ast_debug(1, "Not taking any branch\n");
10749  return 0;
10750  }
10751 
10752  return pbx_builtin_goto(chan, branch);
10753 }
10754 
10755 static int pbx_builtin_saynumber(struct ast_channel *chan, const char *data)
10756 {
10757  char tmp[256];
10758  char *number = tmp;
10759  char *options;
10760 
10761  if (ast_strlen_zero(data)) {
10762  ast_log(LOG_WARNING, "SayNumber requires an argument (number)\n");
10763  return -1;
10764  }
10765  ast_copy_string(tmp, data, sizeof(tmp));
10766  strsep(&number, ",");
10767  options = strsep(&number, ",");
10768  if (options) {
10769  if ( strcasecmp(options, "f") && strcasecmp(options, "m") &&
10770  strcasecmp(options, "c") && strcasecmp(options, "n") ) {
10771  ast_log(LOG_WARNING, "SayNumber gender option is either 'f', 'm', 'c' or 'n'\n");
10772  return -1;
10773  }
10774  }
10775 
10776  if (ast_say_number(chan, atoi(tmp), "", chan->language, options)) {
10777  ast_log(LOG_WARNING, "We were unable to say the number %s, is it too large?\n", tmp);
10778  }
10779 
10780  return 0;
10781 }
10782 
10783 static int pbx_builtin_saydigits(struct ast_channel *chan, const char *data)
10784 {
10785  int res = 0;
10786 
10787  if (data)
10788  res = ast_say_digit_str(chan, data, "", chan->language);
10789  return res;
10790 }
10791 
10792 static int pbx_builtin_saycharacters(struct ast_channel *chan, const char *data)
10793 {
10794  int res = 0;
10795 
10796  if (data)
10797  res = ast_say_character_str(chan, data, "", chan->language);
10798  return res;
10799 }
10800 
10801 static int pbx_builtin_sayphonetic(struct ast_channel *chan, const char *data)
10802 {
10803  int res = 0;
10804 
10805  if (data)
10806  res = ast_say_phonetic_str(chan, data, "", chan->language);
10807  return res;
10808 }
10809 
10810 static int pbx_builtin_saydate(struct ast_channel *chan, const char *data)
10811 {
10812  int res = 0;
10813  char *parse;
10814  int unixdate = 0;
10815  char charascii[2];
10816 
10818  AST_APP_ARG(datestr);
10819  AST_APP_ARG(digits);
10820  );
10821 
10822 
10823  if (ast_strlen_zero(data)) {
10824  ast_log(LOG_WARNING, "SayDate requires an argument (date)\n");
10825  return -1;
10826  }
10827 
10828  if (!(parse = ast_strdupa(data))) {
10829  ast_log(LOG_WARNING, "Memory Error!\n");
10830  return -1;
10831  }
10832 
10833  AST_STANDARD_APP_ARGS(args, parse);
10834 
10835  if (!ast_strlen_zero(args.digits) && (strspn(args.digits, "0123456789*#") != strlen(args.digits))) {
10836  ast_log(LOG_WARNING, "SayDate escape digits must be a subset from '0123456789*#'\n");
10837  args.digits = "";
10838  }
10839 
10840  if (sscanf(args.datestr, "%d", &unixdate) != 1) {
10841  ast_log(LOG_WARNING, "Firt argument to SayDate must be numeric (date)\n");
10842  return -1;
10843  }
10844 
10845  res = ast_say_date(chan, (time_t)unixdate, args.digits, chan->language);
10846  if (res > 0) {
10847  if (isdigit(res) || (res == '*') || (res == '#')) {
10848  snprintf(charascii, 2, "%c", res);
10849  pbx_builtin_setvar_helper(chan, "USER_INPUT", charascii);
10850  res = 0;
10851  } else {
10852  ast_log(LOG_WARNING, "SayDate: invalid return value (%d) detected\n", res);
10853  }
10854  }
10855  return res;
10856 }
10857 
10858 static int pbx_builtin_saytime(struct ast_channel *chan, const char *data)
10859 {
10860  int res = 0;
10861  char *parse;
10862  int secs = 0;
10863  char charascii[2];
10864 
10866  AST_APP_ARG(timestr);
10867  AST_APP_ARG(digits);
10868  );
10869 
10870  if (ast_strlen_zero(data)) {
10871  ast_log(LOG_WARNING, "SayTime requires an argument (time in seconds)\n");
10872  return -1;
10873  }
10874 
10875  if (!(parse = ast_strdupa(data))) {
10876  ast_log(LOG_WARNING, "Memory Error!\n");
10877  return -1;
10878  }
10879 
10880  AST_STANDARD_APP_ARGS(args, parse);
10881 
10882  if (!ast_strlen_zero(args.digits) && (strspn(args.digits, "0123456789*#") != strlen(args.digits))) {
10883  ast_log(LOG_WARNING, "SayTime escape digits must be a subset from '0123456789*#'\n");
10884  args.digits = "";
10885  }
10886 
10887  if (sscanf(args.timestr, "%d", &secs) != 1) {
10888  ast_log(LOG_WARNING, "Firt argument to SayTime must be numeric (time in seconds)\n");
10889  return -1;
10890  }
10891 
10892  res = ast_say_time(chan, (time_t)secs, args.digits, chan->language);
10893  if (res > 0) {
10894  if (isdigit(res) || (res == '*') || (res == '#')) {
10895  snprintf(charascii, 2, "%c", res);
10896  pbx_builtin_setvar_helper(chan, "USER_INPUT", charascii);
10897  res = 0;
10898  } else {
10899  ast_log(LOG_WARNING, "SayTime: invalid return value (%d) detected\n", res);
10900  }
10901  }
10902  return res;
10903 }
10904 
10905 static void device_state_cb(const struct ast_event *event, void *unused)
10906 {
10907  const char *device;
10908  struct statechange *sc;
10909 
10910  device = ast_event_get_ie_str(event, AST_EVENT_IE_DEVICE);
10911  if (ast_strlen_zero(device)) {
10912  ast_log(LOG_ERROR, "Received invalid event that had no device IE\n");
10913  return;
10914  }
10915 
10916  if (!(sc = ast_calloc(1, sizeof(*sc) + strlen(device) + 1)))
10917  return;
10918  strcpy(sc->dev, device);
10919  if (ast_taskprocessor_push(device_state_tps, handle_statechange, sc) < 0) {
10920  ast_free(sc);
10921  }
10922 }
10923 
10924 /*!
10925  * \internal
10926  * \brief Implements the hints data provider.
10927  */
10928 static int hints_data_provider_get(const struct ast_data_search *search,
10929  struct ast_data *data_root)
10930 {
10931  struct ast_data *data_hint;
10932  struct ast_hint *hint;
10933  int watchers;
10934  struct ao2_iterator i;
10935 
10936  if (ao2_container_count(hints) == 0) {
10937  return 0;
10938  }
10939 
10940  i = ao2_iterator_init(hints, 0);
10941  for (; (hint = ao2_iterator_next(&i)); ao2_ref(hint, -1)) {
10942  watchers = ao2_container_count(hint->callbacks);
10943  data_hint = ast_data_add_node(data_root, "hint");
10944  if (!data_hint) {
10945  continue;
10946  }
10947  ast_data_add_str(data_hint, "extension", ast_get_extension_name(hint->exten));
10949  ast_data_add_str(data_hint, "application", ast_get_extension_app(hint->exten));
10950  ast_data_add_str(data_hint, "state", ast_extension_state2str(hint->laststate));
10951  ast_data_add_int(data_hint, "watchers", watchers);
10952 
10953  if (!ast_data_search_match(search, data_hint)) {
10954  ast_data_remove_node(data_root, data_hint);
10955  }
10956  }
10958 
10959  return 0;
10960 }
10961 
10962 static const struct ast_data_handler hints_data_provider = {
10965 };
10966 
10967 static const struct ast_data_entry pbx_data_providers[] = {
10968  AST_DATA_ENTRY("asterisk/core/hints", &hints_data_provider),
10969 };
10970 
10971 /*! \internal \brief Clean up resources on Asterisk shutdown.
10972  * \note Cleans up resources allocated in load_pbx */
10973 static void unload_pbx(void)
10974 {
10975  int x;
10976 
10977  if (device_state_sub) {
10979  }
10980  if (device_state_tps) {
10981  ast_taskprocessor_unreference(device_state_tps);
10982  device_state_tps = NULL;
10983  }
10984 
10985  /* Unregister builtin applications */
10986  for (x = 0; x < ARRAY_LEN(builtins); x++) {
10988  }
10989  ast_manager_unregister("ShowDialPlan");
10993  ast_data_unregister(NULL);
10994 }
10995 
10996 int load_pbx(void)
10997 {
10998  int x;
10999 
11001 
11002  /* Initialize the PBX */
11003  ast_verb(1, "Asterisk PBX Core Initializing\n");
11004  if (!(device_state_tps = ast_taskprocessor_get("pbx-core", 0))) {
11005  ast_log(LOG_WARNING, "failed to create pbx-core taskprocessor\n");
11006  }
11007 
11008  ast_verb(1, "Registering builtin applications:\n");
11013 
11014  /* Register builtin applications */
11015  for (x = 0; x < ARRAY_LEN(builtins); x++) {
11016  ast_verb(1, "[%s]\n", builtins[x].name);
11017  if (ast_register_application2(builtins[x].name, builtins[x].execute, NULL, NULL, NULL)) {
11018  ast_log(LOG_ERROR, "Unable to register builtin application '%s'\n", builtins[x].name);
11019  return -1;
11020  }
11021  }
11022 
11023  /* Register manager application */
11025 
11026  if (!(device_state_sub = ast_event_subscribe(AST_EVENT_DEVICE_STATE, device_state_cb, "pbx Device State Change", NULL,
11027  AST_EVENT_IE_END))) {
11028  return -1;
11029  }
11030 
11031  return 0;
11032 }
11033 
11034 /*
11035  * Lock context list functions ...
11036  */
11038 {
11039  return ast_mutex_lock(&conlock);
11040 }
11041 
11043 {
11044  return ast_mutex_lock(&conlock);
11045 }
11046 
11048 {
11049  return ast_mutex_unlock(&conlock);
11050 }
11051 
11052 /*
11053  * Lock context ...
11054  */
11056 {
11057  return ast_rwlock_wrlock(&con->lock);
11058 }
11059 
11061 {
11062  return ast_rwlock_rdlock(&con->lock);
11063 }
11064 
11066 {
11067  return ast_rwlock_unlock(&con->lock);
11068 }
11069 
11070 /*
11071  * Name functions ...
11072  */
11073 const char *ast_get_context_name(struct ast_context *con)
11074 {
11075  return con ? con->name : NULL;
11076 }
11077 
11079 {
11080  return exten ? exten->parent : NULL;
11081 }
11082 
11083 const char *ast_get_extension_name(struct ast_exten *exten)
11084 {
11085  return exten ? exten->exten : NULL;
11086 }
11087 
11088 const char *ast_get_extension_label(struct ast_exten *exten)
11089 {
11090  return exten ? exten->label : NULL;
11091 }
11092 
11093 const char *ast_get_include_name(struct ast_include *inc)
11094 {
11095  return inc ? inc->name : NULL;
11096 }
11097 
11098 const char *ast_get_ignorepat_name(struct ast_ignorepat *ip)
11099 {
11100  return ip ? ip->pattern : NULL;
11101 }
11102 
11104 {
11105  return exten ? exten->priority : -1;
11106 }
11107 
11108 /*
11109  * Registrar info functions ...
11110  */
11112 {
11113  return c ? c->registrar : NULL;
11114 }
11115 
11117 {
11118  return e ? e->registrar : NULL;
11119 }
11120 
11122 {
11123  return i ? i->registrar : NULL;
11124 }
11125 
11127 {
11128  return ip ? ip->registrar : NULL;
11129 }
11130 
11132 {
11133  return e ? e->matchcid : 0;
11134 }
11135 
11137 {
11138  return e ? e->cidmatch : NULL;
11139 }
11140 
11141 const char *ast_get_extension_app(struct ast_exten *e)
11142 {
11143  return e ? e->app : NULL;
11144 }
11145 
11147 {
11148  return e ? e->data : NULL;
11149 }
11150 
11151 const char *ast_get_switch_name(struct ast_sw *sw)
11152 {
11153  return sw ? sw->name : NULL;
11154 }
11155 
11156 const char *ast_get_switch_data(struct ast_sw *sw)
11157 {
11158  return sw ? sw->data : NULL;
11159 }
11160 
11162 {
11163  return sw->eval;
11164 }
11165 
11166 const char *ast_get_switch_registrar(struct ast_sw *sw)
11167 {
11168  return sw ? sw->registrar : NULL;
11169 }
11170 
11171 /*
11172  * Walking functions ...
11173  */
11175 {
11176  return con ? con->next : contexts;
11177 }
11178 
11180  struct ast_exten *exten)
11181 {
11182  if (!exten)
11183  return con ? con->root : NULL;
11184  else
11185  return exten->next;
11186 }
11187 
11189  struct ast_sw *sw)
11190 {
11191  if (!sw)
11192  return con ? AST_LIST_FIRST(&con->alts) : NULL;
11193  else
11194  return AST_LIST_NEXT(sw, list);
11195 }
11196 
11198  struct ast_exten *priority)
11199 {
11200  return priority ? priority->peer : exten;
11201 }
11202 
11204  struct ast_include *inc)
11205 {
11206  if (!inc)
11207  return con ? con->includes : NULL;
11208  else
11209  return inc->next;
11210 }
11211 
11213  struct ast_ignorepat *ip)
11214 {
11215  if (!ip)
11216  return con ? con->ignorepats : NULL;
11217  else
11218  return ip->next;
11219 }
11220 
11222 {
11223  struct ast_include *inc = NULL;
11224  int res = 0;
11225 
11226  while ( (inc = ast_walk_context_includes(con, inc)) ) {
11227  if (ast_context_find(inc->rname))
11228  continue;
11229 
11230  res = -1;
11231  ast_log(LOG_WARNING, "Context '%s' tries to include nonexistent context '%s'\n",
11232  ast_get_context_name(con), inc->rname);
11233  break;
11234  }
11235 
11236  return res;
11237 }
11238 
11239 
11240 static int __ast_goto_if_exists(struct ast_channel *chan, const char *context, const char *exten, int priority, int async)
11241 {
11242  int (*goto_func)(struct ast_channel *chan, const char *context, const char *exten, int priority);
11243 
11244  if (!chan)
11245  return -2;
11246 
11247  if (context == NULL)
11248  context = chan->context;
11249  if (exten == NULL)
11250  exten = chan->exten;
11251 
11252  goto_func = (async) ? ast_async_goto : ast_explicit_goto;
11253  if (ast_exists_extension(chan, context, exten, priority,
11254  S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL)))
11255  return goto_func(chan, context, exten, priority);
11256  else {
11257  return AST_PBX_GOTO_FAILED;
11258  }
11259 }
11260 
11261 int ast_goto_if_exists(struct ast_channel *chan, const char* context, const char *exten, int priority)
11262 {
11263  return __ast_goto_if_exists(chan, context, exten, priority, 0);
11264 }
11265 
11266 int ast_async_goto_if_exists(struct ast_channel *chan, const char * context, const char *exten, int priority)
11267 {
11268  return __ast_goto_if_exists(chan, context, exten, priority, 1);
11269 }
11270 
11271 static int pbx_parseable_goto(struct ast_channel *chan, const char *goto_string, int async)
11272 {
11273  char *exten, *pri, *context;
11274  char *stringp;
11275  int ipri;
11276  int mode = 0;
11277 
11278  if (ast_strlen_zero(goto_string)) {
11279  ast_log(LOG_WARNING, "Goto requires an argument ([[context,]extension,]priority)\n");
11280  return -1;
11281  }
11282  stringp = ast_strdupa(goto_string);
11283  context = strsep(&stringp, ","); /* guaranteed non-null */
11284  exten = strsep(&stringp, ",");
11285  pri = strsep(&stringp, ",");
11286  if (!exten) { /* Only a priority in this one */
11287  pri = context;
11288  exten = NULL;
11289  context = NULL;
11290  } else if (!pri) { /* Only an extension and priority in this one */
11291  pri = exten;
11292  exten = context;
11293  context = NULL;
11294  }
11295  if (*pri == '+') {
11296  mode = 1;
11297  pri++;
11298  } else if (*pri == '-') {
11299  mode = -1;
11300  pri++;
11301  }
11302  if (sscanf(pri, "%30d", &ipri) != 1) {
11303  ipri = ast_findlabel_extension(chan, context ? context : chan->context,
11304  exten ? exten : chan->exten, pri,
11305  S_COR(chan->caller.id.number.valid, chan->caller.id.number.str, NULL));
11306  if (ipri < 1) {
11307  ast_log(LOG_WARNING, "Priority '%s' must be a number > 0, or valid label\n", pri);
11308  return -1;
11309  } else
11310  mode = 0;
11311  }
11312  /* At this point we have a priority and maybe an extension and a context */
11313 
11314  if (mode)
11315  ipri = chan->priority + (ipri * mode);
11316 
11317  if (async)
11318  ast_async_goto(chan, context, exten, ipri);
11319  else
11320  ast_explicit_goto(chan, context, exten, ipri);
11321 
11322  return 0;
11323 
11324 }
11325 
11326 int ast_parseable_goto(struct ast_channel *chan, const char *goto_string)
11327 {
11328  return pbx_parseable_goto(chan, goto_string, 0);
11329 }
11330 
11331 int ast_async_parseable_goto(struct ast_channel *chan, const char *goto_string)
11332 {
11333  return pbx_parseable_goto(chan, goto_string, 1);
11334 }
11335 
11336 char *ast_complete_applications(const char *line, const char *word, int state)
11337 {
11338  struct ast_app *app = NULL;
11339  int which = 0;
11340  char *ret = NULL;
11341  size_t wordlen = strlen(word);
11342 
11344  AST_RWLIST_TRAVERSE(&apps, app, list) {
11345  if (!strncasecmp(word, app->name, wordlen) && ++which > state) {
11346  ret = ast_strdup(app->name);
11347  break;
11348  }
11349  }
11351 
11352  return ret;
11353 }
11354 
11355 static int hint_hash(const void *obj, const int flags)
11356 {
11357  const struct ast_hint *hint = obj;
11358  const char *exten_name;
11359  int res;
11360 
11361  exten_name = ast_get_extension_name(hint->exten);
11362  if (ast_strlen_zero(exten_name)) {
11363  /*
11364  * If the exten or extension name isn't set, return 0 so that
11365  * the ao2_find() search will start in the first bucket.
11366  */
11367  res = 0;
11368  } else {
11369  res = ast_str_case_hash(exten_name);
11370  }
11371 
11372  return res;
11373 }
11374 
11375 static int hint_cmp(void *obj, void *arg, int flags)
11376 {
11377  const struct ast_hint *hint = obj;
11378  const struct ast_exten *exten = arg;
11379 
11380  return (hint->exten == exten) ? CMP_MATCH | CMP_STOP : 0;
11381 }
11382 
11383 static int statecbs_cmp(void *obj, void *arg, int flags)
11384 {
11385  const struct ast_state_cb *state_cb = obj;
11386  ast_state_cb_type change_cb = arg;
11387 
11388  return (state_cb->change_cb == change_cb) ? CMP_MATCH | CMP_STOP : 0;
11389 }
11390 
11391 static void pbx_shutdown(void)
11392 {
11393  if (hints) {
11394  ao2_ref(hints, -1);
11395  hints = NULL;
11396  }
11397  if (statecbs) {
11398  ao2_ref(statecbs, -1);
11399  statecbs = NULL;
11400  }
11401  if (contexts_table) {
11403  }
11405 }
11406 
11407 int ast_pbx_init(void)
11408 {
11411 
11413 
11414  return (hints && statecbs) ? 0 : -1;
11415 }
int ast_cdr_setamaflags(struct ast_channel *chan, const char *amaflags)
Set AMA flags for channel.
Definition: cdr.c:1042
struct ast_hashtab * root_table
Definition: pbx.c:2959
struct ast_include * ast_walk_context_includes(struct ast_context *con, struct ast_include *inc)
Definition: pbx.c:11203
static void manager_dpsendack(struct mansession *s, const struct message *m)
Send ack once.
Definition: pbx.c:7252
const char * type
Definition: datastore.h:32
ast_include: include= support in extensions.conf
Definition: pbx.c:904
int ast_cdr_disposition(struct ast_cdr *cdr, int cause)
Save the result of the call based on the AST_CAUSE_*.
Definition: cdr.c:790
void pbx_substitute_variables_helper(struct ast_channel *c, const char *cp1, char *cp2, int count)
Definition: pbx.c:4676
#define AST_THREADSTORAGE(name)
Define a thread storage variable.
Definition: threadstorage.h:81
static struct ast_threadstorage extensionstate_buf
Definition: pbx.c:865
int ast_safe_sleep(struct ast_channel *chan, int ms)
Wait for a specified amount of time, looking for hangups.
Definition: channel.c:1916
int ast_hashtab_compare_contexts(const void *ah_a, const void *ah_b)
hashtable functions for contexts
Definition: pbx.c:1136
union ast_frame_subclass subclass
Definition: frame.h:146
struct ast_app * cached_app
Definition: pbx.c:892
int ast_hangup(struct ast_channel *chan)
Hang up a channel.
Definition: channel.c:2804
int ast_unlock_context(struct ast_context *con)
Definition: pbx.c:11065
enum sip_cc_notify_state state
Definition: chan_sip.c:842
Options for ast_pbx_run()
Definition: pbx.h:336
Tone Indication Support.
int( ast_switch_f)(struct ast_channel *chan, const char *context, const char *exten, int priority, const char *callerid, const char *data)
All switch functions have the same interface, so define a type for them.
Definition: pbx.h:124
int hastime
Definition: pbx.c:908
static char accountcode[AST_MAX_ACCOUNT_CODE]
Definition: chan_iax2.c:383
const ast_string_field description
Definition: pbx.c:979
int ast_get_hint(char *hint, int hintsize, char *name, int namesize, struct ast_channel *c, const char *context, const char *exten)
If an extension hint exists, return non-zero.
Definition: pbx.c:5362
#define ast_rwlock_rdlock(a)
Definition: lock.h:201
int ast_matchmore_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Looks to see if adding anything to this extension might match something. (exists ^ canmatch) ...
Definition: pbx.c:5420
#define ast_channel_lock(chan)
Definition: channel.h:2466
int ast_func_read(struct ast_channel *chan, const char *function, char *workspace, size_t len)
executes a read operation on a function
Definition: pbx.c:4177
void __ast_context_destroy(struct ast_context *list, struct ast_hashtab *contexttab, struct ast_context *con, const char *registrar)
Definition: pbx.c:9718
char name[256]
Definition: pbx.c:2968
int64_t ast_mark(int, int start1_stop0)
Definition: asterisk.c:775
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:109
Main Channel structure associated with a channel.
Definition: channel.h:742
int ast_check_timing2(const struct ast_timing *i, const struct timeval tv)
Evaluate a pre-constructed bitmap as to whether a particular time falls within the range specified...
Definition: pbx.c:8362
struct ast_include * includes
Definition: pbx.c:2962
Music on hold handling.
const char * cid_num
Definition: channel.h:1002
#define AST_CLI_DEFINE(fn, txt,...)
Definition: cli.h:191
int ast_context_add_include2(struct ast_context *con, const char *include, const char *registrar)
Add a context include.
Definition: pbx.c:8411
ast_device_state
Device States.
Definition: devicestate.h:51
unsigned int daymask
Definition: pbx.h:142
void ast_cdr_failed(struct ast_cdr *cdr)
Fail a call.
Definition: cdr.c:764
An event.
Definition: event.c:85
char * str
Subscriber phone number (Malloced)
Definition: channel.h:241
int ast_get_extension_priority(struct ast_exten *exten)
Definition: pbx.c:11103
#define AST_APP_OPTION_ARG(option, flagno, argno)
Declares an application option that accepts an argument.
Definition: app.h:732
int ast_streamfile(struct ast_channel *c, const char *filename, const char *preflang)
Streams a file.
Definition: file.c:946
struct ast_exten * root
Definition: pbx.c:2958
Asterisk locking-related definitions:
ast_extension_states
Extension states.
Definition: pbx.h:60
void astman_append(struct mansession *s, const char *fmt,...)
Definition: manager.c:2068
Asterisk main include file. File version handling, generic pbx functions.
ast_exten: An extension The dialplan is saved as a linked list with each context having it&#39;s own link...
Definition: pbx.c:884
#define ao2_link(arg1, arg2)
Definition: astobj2.h:785
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
Definition: linkedlists.h:420
void * ast_hashtab_lookup(struct ast_hashtab *tab, const void *obj)
Lookup this object in the hash table.
Definition: hashtab.c:534
int ao2_container_count(struct ao2_container *c)
Returns the number of elements in a container.
Definition: astobj2.c:470
#define AST_RWLOCK_DEFINE_STATIC(rwlock)
Definition: lock.h:549
int ast_hashtab_newsize_java(struct ast_hashtab *tab)
Create a prime number roughly 2x the current table size.
Definition: hashtab.c:131
#define AST_APP_OPTIONS(holder, options...)
Declares an array of options for an application.
Definition: app.h:712
struct ast_include * next
Definition: pbx.c:910
int ast_context_remove_include(const char *context, const char *include, const char *registrar)
Remove a context include.
Definition: pbx.c:6007
#define ARRAY_LEN(a)
Definition: isdn_lib.c:42
int ast_context_remove_ignorepat(const char *context, const char *ignorepat, const char *registrar)
Definition: pbx.c:8554
The data tree to be returned by the callbacks and managed by functions local to this file...
Definition: data.c:85
static void __ast_internal_context_destroy(struct ast_context *con)
Definition: pbx.c:9670
int refcount
Definition: pbx.c:2965
static int __ast_goto_if_exists(struct ast_channel *chan, const char *context, const char *exten, int priority, int async)
Definition: pbx.c:11240
int ast_active_calls(void)
Retrieve the number of active calls.
Definition: pbx.c:5931
struct ast_party_caller caller
Channel Caller ID information.
Definition: channel.h:804
struct ast_tone_zone * zone
Definition: channel.h:767
void * ast_threadstorage_get(struct ast_threadstorage *ts, size_t init_size)
Retrieve thread storage.
int ast_autoservice_start(struct ast_channel *chan)
Automatically service a channel for us...
Definition: autoservice.c:179
void pbx_builtin_clear_globals(void)
Definition: pbx.c:10709
char * strsep(char **str, const char *delims)
const char * ast_get_extension_registrar(struct ast_exten *e)
Definition: pbx.c:11116
static int amaflags
Definition: chan_iax2.c:386
struct ast_app * pbx_findapp(const char *app)
Look up an application.
Definition: pbx.c:1537
static void unreference_cached_app(struct ast_app *app)
Definition: pbx.c:7686
static int ast_add_hint(struct ast_exten *e)
Add hint to hint list, check initial extension state.
Definition: pbx.c:5270
int priority
Definition: channel.h:841
#define AST_RWLIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a read/write list of specified type, statically initialized...
Definition: linkedlists.h:332
#define EXT_DATA_SIZE
Definition: pbx.c:828
int pbx_exec(struct ast_channel *c, struct ast_app *app, const char *data)
Execute an application.
Definition: pbx.c:1497
const ast_string_field uniqueid
Definition: channel.h:787
static char * handle_debug_dialplan(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Send ack once.
Definition: pbx.c:7196
static int ast_change_hint(struct ast_exten *oe, struct ast_exten *ne)
Change hint for an extension.
Definition: pbx.c:5328
static void exception_store_free(void *data)
Definition: pbx.c:3571
struct ast_include * includes
Definition: pbx.c:961
struct ast_exten * exten
Definition: pbx.c:939
int total_items
Definition: pbx.c:6896
struct ast_channel * chan
Definition: pbx.c:9276
char context[AST_MAX_CONTEXT]
Definition: pbx.c:9277
#define ast_strdup(a)
Definition: astmm.h:109
int ast_channel_masquerade(struct ast_channel *original, struct ast_channel *clone)
Weird function made for call transfers.
Definition: channel.c:6110
CallerID (and other GR30) management and generation Includes code and algorithms from the Zapata libr...
static char * handle_show_applications(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: pbx.c:6779
Definition: ast_expr2.c:325
format_t writeformat
Definition: channel.h:854
int total_exten
Definition: pbx.c:6898
const ast_string_field synopsis
Definition: pbx.c:979
struct ast_channel * parent_channel
Definition: channel.h:1006
#define ast_pthread_create_detached(a, b, c, d)
Definition: utils.h:422
void ast_cdr_reset(struct ast_cdr *cdr, struct ast_flags *flags)
Reset the detail record, optionally posting it first.
Definition: cdr.c:1149
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: utils.h:653
static int ast_extension_state2(struct ast_exten *e)
Check state of extension by using hints.
Definition: pbx.c:4889
#define AST_DIGIT_ANY
Definition: file.h:47
int ast_cli_unregister_multiple(struct ast_cli_entry *e, int len)
Unregister multiple commands.
Definition: cli.c:2177
char * ast_eid_to_str(char *s, int maxlen, struct ast_eid *eid)
Definition: netsock.c:222
static int pbx_builtin_gotoif(struct ast_channel *, const char *)
Definition: pbx.c:10731
#define ast_channel_unref(c)
Decrease channel reference count.
Definition: channel.h:2502
Definition: pbx.c:1301
static int ast_pbx_outgoing_cdr_failed(void)
Function to post an empty cdr after a spool call fails.
Definition: pbx.c:9348
static int pbx_builtin_saydigits(struct ast_channel *, const char *)
Definition: pbx.c:10783
int __ast_custom_function_register_escalating(struct ast_custom_function *acf, enum ast_custom_function_escalation escalation, struct ast_module *mod)
Register a custom function which requires escalated privileges.
Definition: pbx.c:3994
#define ast_set2_flag(p, value, flag)
Definition: utils.h:94
#define ast_test_flag(p, flag)
Definition: utils.h:63
int option_debug
Definition: asterisk.c:182
static char * handle_show_function(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: pbx.c:3693
int __ast_answer(struct ast_channel *chan, unsigned int delay, int cdr_answer)
Answer a channel, with a selectable delay before returning.
Definition: channel.c:2982
Device state management.
int ast_indicate(struct ast_channel *chan, int condition)
Indicates condition of channel.
Definition: channel.c:4393
#define STATUS_NO_PRIORITY
Definition: pbx.c:2997
void ast_cdr_end(struct ast_cdr *cdr)
End a call.
Definition: cdr.c:933
static int pbx_builtin_hangup(struct ast_channel *, const char *)
Definition: pbx.c:10058
static void decrease_call_count(void)
Definition: pbx.c:5837
#define ast_rwlock_destroy(rwlock)
Definition: lock.h:199
Call Event Logging API.
size_t ast_str_size(const struct ast_str *buf)
Returns the current maximum length (without reallocation) of the current buffer.
Definition: strings.h:482
Time-related functions and macros.
const char * ast_var_value(const struct ast_var_t *var)
Definition: chanvars.c:89
int ast_context_lockmacro(const char *macrocontext)
locks the macrolock in the given given context
Definition: pbx.c:6306
static int hint_cmp(void *obj, void *arg, int flags)
Definition: pbx.c:11375
#define BACKGROUND_NOANSWER
Definition: pbx.c:840
static struct ast_hashtab * contexts_table
Definition: pbx.c:1286
int ast_extension_state_del(int id, ast_state_cb_type change_cb)
Deletes a registered state change callback by ID.
Definition: pbx.c:5157
static struct match_char * add_exten_to_pattern_tree(struct ast_context *con, struct ast_exten *e1, int findonly)
Definition: pbx.c:2222
const ast_string_field syntax
Definition: pbx.h:103
pthread_t p
Definition: pbx.c:9275
static void new_find_extension(const char *str, struct scoreboard *score, struct match_char *tree, int length, int spec, const char *callerid, const char *label, enum ext_match_t action)
Definition: pbx.c:1807
struct ast_var_t * ast_var_assign(const char *name, const char *value)
Definition: chanvars.c:41
int ast_func_read2(struct ast_channel *chan, const char *function, struct ast_str **str, ssize_t maxlen)
executes a read operation on a function
Definition: pbx.c:4216
int ast_taskprocessor_push(struct ast_taskprocessor *tps, int(*task_exe)(void *datap), void *datap)
Push a task into the specified taskprocessor queue and signal the taskprocessor thread.
static char * handle_show_chanvar(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
CLI support for listing chanvar&#39;s variables in a parseable way.
Definition: pbx.c:7512
#define AST_RWLIST_WRLOCK(head)
Write locks a list.
Definition: linkedlists.h:51
#define WAITEXTEN_MOH
Definition: pbx.c:851
char context[AST_MAX_CONTEXT]
Definition: channel.h:868
int(* ast_state_cb_type)(char *context, char *id, enum ast_extension_states state, void *data)
Typedef for devicestate and hint callbacks.
Definition: pbx.h:89
const char * ast_var_name(const struct ast_var_t *var)
Definition: chanvars.c:69
#define ao2_iterator_next(arg1)
Definition: astobj2.h:1126
int ast_app_parse_timelen(const char *timestr, int *result, enum ast_timelen defunit)
Common routine to parse time lengths, with optional time unit specifier.
Definition: app.c:2311
#define ast_set_flag(p, flag)
Definition: utils.h:70
static char * substring(const char *value, int offset, int length, char *workspace, size_t workspace_len)
takes a substring. It is ok to call with value == workspace.
Definition: pbx.c:3344
static int pbx_builtin_progress(struct ast_channel *, const char *)
Definition: pbx.c:9916
static int pbx_builtin_gotoiftime(struct ast_channel *, const char *)
Definition: pbx.c:10122
struct ast_channel * __ast_request_and_dial(const char *type, format_t format, const struct ast_channel *requestor, void *data, int timeout, int *reason, const char *cid_num, const char *cid_name, struct outgoing_helper *oh)
Request a channel of a given type, with data as optional information used by the low level module and...
Definition: channel.c:5456
descriptor for a cli entry.
Definition: cli.h:165
const char * rname
Definition: pbx.c:906
const int argc
Definition: cli.h:154
#define LOG_WARNING
Definition: logger.h:144
int ast_cel_report_event(struct ast_channel *chan, enum ast_cel_event_type event_type, const char *userdefevname, const char *extra, struct ast_channel *peer2)
Report a channel event.
Definition: cel.c:645
enum ast_pbx_result ast_pbx_start(struct ast_channel *c)
Create a new thread and start the PBX.
Definition: pbx.c:5879
#define BACKGROUND_PLAYBACK
Definition: pbx.c:842
static int live_dangerously
Set to true (non-zero) to globally allow all dangerous dialplan functions to run. ...
Definition: pbx.c:870
char * ast_str_buffer(const struct ast_str *buf)
Returns the string buffer within the ast_str buf.
Definition: strings.h:497
int ast_extension_cmp(const char *a, const char *b)
Determine if one extension should match before another.
Definition: pbx.c:2713
void __ast_module_user_remove(struct ast_module *, struct ast_module_user *)
Definition: loader.c:231
const char * ast_get_extension_app(struct ast_exten *e)
Definition: pbx.c:11141
struct ast_ignorepat * ignorepats
Definition: pbx.c:962
int ast_add_extension2(struct ast_context *con, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar)
Add an extension to an extension context, this time with an ast_context *.
Definition: pbx.c:9052
int ast_party_id_presentation(const struct ast_party_id *id)
Determine the overall presentation value for the given party.
Definition: channel.c:2151
static void context_merge_incls_swits_igps_other_registrars(struct ast_context *new, struct ast_context *old, const char *registrar)
Definition: pbx.c:7813
#define ao2_callback(c, flags, cb_fn, arg)
Definition: astobj2.h:910
struct ast_taskprocessor * ast_taskprocessor_get(const char *name, enum ast_tps_options create)
Get a reference to a taskprocessor with the specified name and create the taskprocessor if necessary...
struct ast_exten * exten
Hint extension.
Definition: pbx.c:1017
ast_custom_function_escalation
Description of the ways in which a function may escalate privileges.
Definition: pbx.h:1154
#define VERBOSITY_ATLEAST(level)
Definition: logger.h:241
#define COLOR_CYAN
Definition: term.h:59
int ast_app_parse_options(const struct ast_app_option *options, struct ast_flags *flags, char **args, char *optstr)
Parses a string containing application options and sets flags/arguments.
Definition: app.c:2101
const char * registrar
Definition: pbx.c:926
ast_state_cb: An extension state notify register item
Definition: pbx.c:989
#define ast_opt_end_cdr_before_h_exten
Definition: options.h:122
char * ast_complete_applications(const char *line, const char *word, int state)
Command completion for the list of installed applications.
Definition: pbx.c:11336
static int autofallthrough
Definition: pbx.c:1220
static void destroy_hint(void *obj)
Definition: pbx.c:5207
#define AST_RWLIST_UNLOCK(head)
Attempts to unlock a read/write based list.
Definition: linkedlists.h:150
int priority
Definition: pbx.c:9279
char * ast_xmldoc_build_description(const char *type, const char *name, const char *module)
Generate description documentation from XML.
Definition: xmldoc.c:1899
static int stateid
Definition: pbx.c:1305
Generic (perhaps overly so) hashtable implementation Hash Table support in Asterisk.
int ast_cdr_setaccount(struct ast_channel *chan, const char *account)
Set account code, will generate AMI event.
Definition: cdr.c:990
struct ast_tm * ast_localtime(const struct timeval *timep, struct ast_tm *p_tm, const char *zone)
Timezone-independent version of localtime_r(3).
Definition: localtime.c:1570
#define AST_DECLARE_APP_ARGS(name, arglist)
Declare a structure to hold an application&#39;s arguments.
Definition: app.h:572
char exten[AST_MAX_EXTENSION]
Definition: pbx.c:9278
unsigned int flags
Definition: utils.h:201
This entries are for multiple registers.
Definition: data.h:253
static ast_rwlock_t globalslock
Definition: pbx.c:1217
void * ast_hashtab_next(struct ast_hashtab_iter *it)
Gets the next object in the list, advances iter one step returns null on end of traversal.
Definition: hashtab.c:753
static int pbx_builtin_goto(struct ast_channel *, const char *)
Definition: pbx.c:10435
const char pattern[0]
Definition: pbx.c:928
Structure for variables, used for configurations and for channel variables.
Definition: config.h:75
static char * handle_show_hints(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
handle_show_hints: CLI support for listing registered dial plan hints
Definition: pbx.c:6594
static char * handle_show_switches(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
handle_show_switches: CLI support for listing registered dial plan switches
Definition: pbx.c:6747
static int thread_inhibits_escalations(void)
Indicates whether the current thread inhibits the execution of dangerous functions.
Definition: pbx.c:4095
#define var
Definition: ast_expr2f.c:606
void ast_set_variables(struct ast_channel *chan, struct ast_variable *vars)
adds a list of channel variables to a channel
Definition: channel.c:8261
static int testtime_write(struct ast_channel *chan, const char *cmd, char *var, const char *value)
Definition: pbx.c:10090
struct ast_cdr * ast_cdr_dup(struct ast_cdr *cdr)
Duplicate a record.
Definition: cdr.c:213
#define NEW_MATCHER_RECURSE
static int hashtab_compare_extens(const void *ha_a, const void *ah_b)
Definition: pbx.c:1146
static int pbx_builtin_sayphonetic(struct ast_channel *, const char *)
Definition: pbx.c:10801
#define AST_LIST_NEXT(elm, field)
Returns the next entry in the list after the given entry.
Definition: linkedlists.h:438
int pbx_checkcondition(const char *condition)
Evaluate a condition.
Definition: pbx.c:10719
void ast_str_substitute_variables(struct ast_str **buf, ssize_t maxlen, struct ast_channel *chan, const char *templ)
Definition: pbx.c:4468
static struct ast_threadstorage thread_inhibit_escalations_tl
Definition: pbx.c:870
char last_char
Definition: pbx.c:947
struct ast_frame * ast_read(struct ast_channel *chan)
Reads a frame.
Definition: channel.c:4383
static int hint_hash(const void *obj, const int flags)
Definition: pbx.c:11355
int ast_say_digit_str(struct ast_channel *chan, const char *num, const char *ints, const char *lang)
says digits of a string
Definition: channel.c:8415
const ast_string_field desc
Definition: pbx.h:103
enum ast_doc_src docsrc
Definition: pbx.h:104
#define INC_DST_OVERFLOW_CHECK
Definition: cli.h:146
static enum ast_pbx_result __ast_pbx_run(struct ast_channel *c, struct ast_pbx_args *args)
Definition: pbx.c:5473
static EditLine * el
Definition: asterisk.c:222
#define ast_compat_app_set
Definition: options.h:144
char * context
Definition: pbx.c:7803
int ast_ignore_pattern(const char *context, const char *pattern)
Checks to see if a number should be ignored.
Definition: pbx.c:8650
Structure for a data store type.
Definition: datastore.h:31
Configuration File Parser.
int extension_state
Definition: pbx.c:1032
const ast_string_field exten
Definition: pbx.c:1055
int ast_indicate_data(struct ast_channel *chan, int condition, const void *data, size_t datalen)
Indicates condition of channel, with payload.
Definition: channel.c:4447
#define ast_calloc_with_stringfields(n, type, size)
Allocate a structure with embedded stringfields in a single allocation.
Definition: stringfields.h:275
void ast_unregister_switch(struct ast_switch *sw)
Unregister an alternative switch.
Definition: pbx.c:6457
int specificity
Definition: pbx.c:936
const ast_string_field arguments
Definition: pbx.h:103
#define STATUS_NO_EXTENSION
Definition: pbx.c:2996
void * ast_get_extension_app_data(struct ast_exten *e)
Definition: pbx.c:11146
static int is_write_allowed(struct ast_custom_function *acfptr)
Determines whether execution of a custom function&#39;s write function is allowed.
Definition: pbx.c:4152
int ast_str_append(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Append to a thread local dynamic string.
Definition: strings.h:900
int ast_rdlock_contexts(void)
Read locks the context list.
Definition: pbx.c:11042
static struct ast_cli_entry pbx_cli[]
Definition: pbx.c:7665
static int pbx_builtin_proceeding(struct ast_channel *, const char *)
Definition: pbx.c:9907
struct ast_hashtab_iter * ast_hashtab_start_traversal(struct ast_hashtab *tab)
Gives an iterator to hastable.
Definition: hashtab.c:696
static struct ast_threadstorage buf2
static struct match_char * add_pattern_node(struct ast_context *con, struct match_char *current, const struct pattern_node *pattern, int is_pattern, int already, struct match_char **nextcharptr)
Definition: pbx.c:2024
int context_existence
Definition: pbx.c:6900
const char * ast_get_extension_label(struct ast_exten *e)
Definition: pbx.c:11088
static int copy(char *infile, char *outfile)
Utility function to copy a file.
struct timeval ast_tvnow(void)
Returns current timeval. Meant to replace calls to gettimeofday().
Definition: time.h:142
struct match_char * alt_char
Definition: pbx.c:937
#define AST_DECLARE_STRING_FIELDS(field_list)
Declare the fields needed in a structure.
Definition: stringfields.h:235
struct ast_str * ast_str_create(size_t init_len)
Create a malloc&#39;ed dynamic length string.
Definition: strings.h:420
int ast_explicit_goto(struct ast_channel *chan, const char *context, const char *exten, int priority)
Definition: pbx.c:8708
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
Definition: linkedlists.h:449
struct ast_module * mod
Definition: pbx.h:119
#define ast_mutex_lock(a)
Definition: lock.h:155
int ast_wrlock_contexts(void)
Write locks the context list.
Definition: pbx.c:11037
struct ast_cdr * cdr
Definition: channel.h:766
static ast_mutex_t context_merge_lock
Lock to hold off restructuring of hints by ast_merge_contexts_and_delete.
Definition: pbx.c:1299
#define ao2_unlock(a)
Definition: astobj2.h:497
struct ao2_iterator ao2_iterator_init(struct ao2_container *c, int flags)
Create an iterator for a container.
Definition: astobj2.c:818
#define ast_str_alloca(init_len)
Definition: strings.h:608
int ast_context_remove_extension_callerid2(struct ast_context *con, const char *extension, int priority, const char *callerid, int matchcid, const char *registrar, int already_locked)
Definition: pbx.c:6149
const char * registrar
Definition: pbx.c:2964
Structure for a data store object.
Definition: datastore.h:54
struct ast_datastore * ast_channel_datastore_find(struct ast_channel *chan, const struct ast_datastore_info *info, const char *uid)
Find a datastore on a channel.
Definition: channel.c:2604
int ast_context_remove_include2(struct ast_context *con, const char *include, const char *registrar)
Removes an include by an ast_context structure.
Definition: pbx.c:6030
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
Definition: config.c:586
const char * str
Definition: app_jack.c:144
const char * label
Definition: pbx.c:889
Generic File Format Support. Should be included by clients of the file handling routines. File service providers should instead include mod_format.h.
static int hashtab_compare_exten_labels(const void *ah_a, const void *ah_b)
Definition: pbx.c:1181
static int pbx_builtin_setamaflags(struct ast_channel *, const char *)
Definition: pbx.c:10046
static int pbx_builtin_importvar(struct ast_channel *, const char *)
Definition: pbx.c:10669
void ast_playtones_stop(struct ast_channel *chan)
Stop playing tones on a channel.
Definition: indications.c:411
void pbx_builtin_pushvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, without removing any previously set value...
Definition: pbx.c:10513
char * incstack[AST_PBX_MAX_STACK]
Definition: extconf.h:233
const char * data
Definition: channel.h:755
static unsigned int hashtab_hash_labels(const void *obj)
Definition: pbx.c:1210
const char * ast_get_context_registrar(struct ast_context *c)
Definition: pbx.c:11111
const char *const text
Definition: pbx.c:1033
char * ast_xmldoc_build_synopsis(const char *type, const char *name, const char *module)
Generate synopsis documentation from XML.
Definition: xmldoc.c:1894
int value
Definition: syslog.c:39
void ast_cli(int fd, const char *fmt,...)
Definition: cli.c:105
int ast_str_get_hint(struct ast_str **hint, ssize_t hintsize, struct ast_str **name, ssize_t namesize, struct ast_channel *c, const char *context, const char *exten)
If an extension hint exists, return non-zero.
Definition: pbx.c:5380
const ast_string_field linkedid
Definition: channel.h:787
#define LOG_DEBUG
Definition: logger.h:122
#define AST_DATA_ENTRY(__path, __handler)
Definition: data.h:260
#define ast_rwlock_unlock(a)
Definition: lock.h:200
struct ast_hashtab * peer_table
Definition: pbx.c:896
#define EVENT_FLAG_DIALPLAN
Definition: manager.h:82
int ast_unregister_application(const char *app)
Unregister an application.
Definition: pbx.c:7705
int ast_context_add_switch2(struct ast_context *con, const char *sw, const char *data, int eval, const char *registrar)
Adds a switch (first param is a ast_context)
Definition: pbx.c:8494
static struct ao2_container * hints
Definition: pbx.c:1314
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:600
static int pbx_parseable_goto(struct ast_channel *chan, const char *goto_string, int async)
Definition: pbx.c:11271
void ast_free_ptr(void *ptr)
static char cid_num[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:157
char * ast_xmldoc_build_arguments(const char *type, const char *name, const char *module)
Generate the [arguments] tag based on type of node (&#39;application&#39;, &#39;function&#39; or &#39;agi&#39;) and name...
Definition: xmldoc.c:1761
struct ast_channel * chan
Definition: pbx.c:9519
char x[1]
Definition: pbx.c:940
static int acf_retrieve_docs(struct ast_custom_function *acf)
Definition: pbx.c:3901
struct ast_timing timing
Definition: pbx.c:909
void ast_var_delete(struct ast_var_t *var)
Definition: chanvars.c:63
ast_doc_src
From where the documentation come from, this structure is useful for use it inside application/functi...
Definition: xmldoc.h:28
#define ast_verb(level,...)
Definition: logger.h:243
Definition: ael.tab.c:203
int ast_context_add_include(const char *context, const char *include, const char *registrar)
Add a context include.
Definition: pbx.c:8142
static int pbx_builtin_execiftime(struct ast_channel *, const char *)
Definition: pbx.c:10176
const char * appl
Definition: channel.h:754
ast_state_cb_type change_cb
Definition: pbx.c:995
static int ast_add_extension2_lockopt(struct ast_context *con, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar, int lock_context)
Same as ast_add_extension2() but controls the context locking.
Definition: pbx.c:9068
static char * handle_set_extenpatternmatchnew(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: pbx.c:7606
const char * line
Definition: cli.h:156
int ast_hashtab_resize_java(struct ast_hashtab *tab)
Determines if a table resize should occur using the Java algorithm (if the table load factor is 75% o...
Definition: hashtab.c:88
int ast_custom_function_unregister(struct ast_custom_function *acf)
Unregister a custom function.
Definition: pbx.c:3814
int ast_datastore_free(struct ast_datastore *datastore)
Free a data store object.
Definition: datastore.c:65
int timeout
Definition: pbx.c:9280
struct ast_channel * ast_channel_alloc(int needqueue, int state, const char *cid_num, const char *cid_name, const char *acctcode, const char *exten, const char *context, const char *linkedid, const int amaflag, const char *name_fmt,...)
Definition: channel.c:9825
struct ast_variable * vars
Definition: channel.h:1005
int ast_canmatch_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Looks for a valid matching extension.
Definition: pbx.c:5415
static void pbx_destroy(struct ast_pbx *p)
Definition: pbx.c:1573
const char * pbx_builtin_getvar_helper(struct ast_channel *chan, const char *name)
Return a pointer to the value of the corresponding channel variable.
Definition: pbx.c:10475
#define COLOR_BRCYAN
Definition: term.h:60
enum ast_device_state ast_devstate_aggregate_result(struct ast_devstate_aggregate *agg)
Get the aggregate device state result.
Definition: devicestate.c:791
int ast_context_remove_extension(const char *context, const char *extension, int priority, const char *registrar)
Simply remove extension from context.
Definition: pbx.c:6114
static char * handle_show_hint(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
handle_show_hint: CLI support for listing registered dial plan hint
Definition: pbx.c:6685
static struct ast_exten * trie_find_next_match(struct match_char *node)
Definition: pbx.c:1748
static struct ast_datastore_info exception_store_info
Definition: pbx.c:3578
Utility functions.
int args
This gets set in ast_cli_register()
Definition: cli.h:179
static struct cfextension_states extension_states[]
const char * astman_get_header(const struct message *m, char *var)
Get header from mananger transaction.
Definition: manager.c:1860
static struct ast_app_option waitexten_opts[128]
Definition: pbx.c:857
unsigned int monthmask
Definition: pbx.h:141
char * ast_cli_complete(const char *word, const char *const choices[], int pos)
Definition: cli.c:1535
static struct ast_data_handler hints_data_provider
Definition: pbx.c:10962
static int show_dialplan_helper(int fd, const char *context, const char *exten, struct dialplan_counters *dpc, struct ast_include *rinclude, int includecount, const char *includes[])
Definition: pbx.c:6919
const char * ast_config_AST_SYSTEM_NAME
Definition: asterisk.c:273
static char * handle_show_dialplan(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: pbx.c:7129
int matchcid
Definition: pbx.c:886
Number structure.
Definition: app_followme.c:109
ast_mutex_t macrolock
Definition: pbx.c:966
int ast_context_remove_switch(const char *context, const char *sw, const char *data, const char *registrar)
Remove a switch.
Definition: pbx.c:6065
const char * ast_get_switch_name(struct ast_sw *sw)
Definition: pbx.c:11151
#define AST_TERM_MAX_ESCAPE_CHARS
Maximum number of characters needed for a color escape sequence, plus a null char.
Definition: term.h:67
struct ast_context * next
Definition: pbx.c:2961
char stuff[0]
Definition: pbx.c:900
Call Detail Record API.
int ast_str_set(struct ast_str **buf, ssize_t max_len, const char *fmt,...)
Set a dynamic string using variable arguments.
Definition: strings.h:874
struct ast_party_id id
Caller party ID.
Definition: channel.h:370
const char * ast_get_include_name(struct ast_include *include)
Definition: pbx.c:11093
char * timezone
Definition: pbx.h:145
static int lookup_name(const char *s, const char *const names[], int max)
Helper for get_range. return the index of the matching entry, starting from 1. If names is not suppli...
Definition: pbx.c:8159
const char * ast_get_include_registrar(struct ast_include *i)
Definition: pbx.c:11121
#define AST_RWLIST_RDLOCK(head)
Read locks a list.
Definition: linkedlists.h:77
static int raise_exception(struct ast_channel *chan, const char *reason, int priority)
Definition: pbx.c:3594
Definition: pbx.h:179
#define ast_opt_dont_warn
Definition: options.h:121
ast_switch_f * matchmore
Definition: pbx.h:136
SAY_EXTERN int(* ast_say_date)(struct ast_channel *chan, time_t t, const char *ints, const char *lang) SAY_INIT(ast_say_date)
Definition: say.h:164
static int statecbs_cmp(void *obj, void *arg, int flags)
Definition: pbx.c:11383
#define AST_PBX_ERROR
Definition: pbx.h:49
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
int priority
Definition: pbx.c:888
const char * exten
Definition: channel.h:1000
const char * name
Definition: pbx.h:130
#define AST_DATA_HANDLER_VERSION
The Data API structures version.
Definition: data.h:204
static int pbx_builtin_wait(struct ast_channel *, const char *)
Definition: pbx.c:10230
const char * cid_name
Definition: channel.h:1003
ast_sw: Switch statement in extensions.conf
Definition: pbx.c:915
static int ext_cmp(const char *left, const char *right)
Definition: pbx.c:2691
static const char app[]
Definition: app_adsiprog.c:49
#define BACKGROUND_SKIP
Definition: pbx.c:839
General Asterisk PBX channel definitions.
#define ast_data_register_multiple_core(data_entries, entries)
Definition: data.h:379
struct ast_exten * ast_walk_context_extensions(struct ast_context *con, struct ast_exten *priority)
Definition: pbx.c:11179
static int increase_call_count(const struct ast_channel *c)
Increase call count for channel.
Definition: pbx.c:5790
long option_minmemfree
Definition: asterisk.c:187
int pbx_builtin_raise_exception(struct ast_channel *chan, const char *data)
Definition: pbx.c:3620
static ast_mutex_t maxcalllock
Definition: pbx.c:1227
void ast_set_hangupsource(struct ast_channel *chan, const char *source, int force)
Set the source of the hangup in this channel and it&#39;s bridge.
Definition: channel.c:2769
Asterisk file paths, configured in asterisk.conf.
void ast_channel_clear_softhangup(struct ast_channel *chan, int flag)
Clear a set of softhangup flags from a channel.
Definition: channel.c:2707
int ast_str_make_space(struct ast_str **buf, size_t new_len)
Definition: strings.h:588
const char * registrar
Definition: pbx.c:907
const char * data
Definition: extconf.h:237
static int ext_cmp_exten_strlen(const char *str)
Definition: pbx.c:2368
static void create_match_char_tree(struct ast_context *con)
Definition: pbx.c:2321
const ast_string_field reason
Definition: pbx.c:1055
const int fd
Definition: cli.h:153
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:249
int ast_context_add_ignorepat(const char *context, const char *ignorepat, const char *registrar)
Add an ignorepat.
Definition: pbx.c:8598
const char * account
Definition: channel.h:1004
#define ast_manager_register_xml(a, b, c)
Register a manager callback using XML documentation to describe the manager.
Definition: manager.h:172
static int ext_cmp_pattern_pos(const char **p, unsigned char *bitwise)
helper functions to sort extension patterns in the desired way, so that more specific patterns appear...
Definition: pbx.c:2528
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
int id
Definition: pbx.c:991
const int n
Definition: cli.h:159
char * ast_str_append_substr(struct ast_str **buf, ssize_t maxlen, const char *src, size_t maxsrc)
Append a non-NULL terminated substring to the end of a dynamic string.
Definition: strings.h:823
struct sla_ringing_trunk * last
Definition: app_meetme.c:965
Data structure associated with a custom dialplan function.
Definition: pbx.h:95
int priority
Definition: pbx.c:1057
static struct ast_exten * ast_hint_extension(struct ast_channel *c, const char *context, const char *exten)
Definition: pbx.c:4835
enum ast_pbx_result ast_pbx_run_args(struct ast_channel *c, struct ast_pbx_args *args)
Execute the PBX in the current thread.
Definition: pbx.c:5906
struct ast_data * ast_data_add_node(struct ast_data *root, const char *childname)
Add a container child.
Definition: data.c:2317
#define HASH_EXTENHINT_SIZE
Definition: pbx.c:1028
int ast_parseable_goto(struct ast_channel *chan, const char *goto_string)
Definition: pbx.c:11326
#define AST_MAX_EXTENSION
Definition: channel.h:135
an app ends
Definition: cel.h:60
int pbx_set_extenpatternmatchnew(int newval)
Definition: pbx.c:5948
#define AST_RWLIST_TRAVERSE
Definition: linkedlists.h:493
char * ast_strip(char *s)
Strip leading/trailing whitespace from a string.
Definition: strings.h:155
#define AST_CAUSE_NORMAL_CLEARING
Definition: causes.h:105
static struct match_char * already_in_tree(struct match_char *current, char *pat, int is_pattern)
Definition: pbx.c:1962
const char * ast_get_ignorepat_registrar(struct ast_ignorepat *ip)
Definition: pbx.c:11126
static int pbx_builtin_background(struct ast_channel *, const char *)
Definition: pbx.c:10320
#define AST_STRING_FIELD(name)
Declare a string field.
Definition: stringfields.h:220
#define ast_data_unregister(path)
Definition: data.h:394
int tm_mon
Definition: localtime.h:40
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: linkedlists.h:554
static int is_read_allowed(struct ast_custom_function *acfptr)
Determines whether execution of a custom function&#39;s read function is allowed.
Definition: pbx.c:4119
#define ao2_ref(o, delta)
Definition: astobj2.h:472
static struct ast_event_sub * device_state_sub
Subscription for device state change events.
Definition: pbx.c:1225
const char * ast_extension_state2str(int extension_state)
Return string representation of the state of an extension.
Definition: pbx.c:4902
#define S_COR(a, b, c)
returns the equivalent of logic or for strings, with an additional boolean check: second one if not e...
Definition: strings.h:83
int ast_softhangup(struct ast_channel *chan, int reason)
Softly hangup up a channel.
Definition: channel.c:2746
static const char *const months[]
Definition: pbx.c:8297
char * exten
Definition: pbx.c:7804
int ast_register_atexit(void(*func)(void))
Register a function to be executed before Asterisk exits.
Definition: asterisk.c:998
int ast_hashtab_insert_immediate(struct ast_hashtab *tab, const void *obj)
Insert without checking.
Definition: hashtab.c:432
#define ao2_lock(a)
Definition: astobj2.h:488
size_t read_max
Definition: pbx.h:116
const char * ast_get_switch_data(struct ast_sw *sw)
Definition: pbx.c:11156
struct ast_exten * canmatch_exten
Definition: pbx.c:950
static int ext_cmp_pattern(const char *left, const char *right)
Definition: pbx.c:2643
static struct ast_custom_function testtime_function
Definition: pbx.c:10114
#define AST_RWLIST_REMOVE_CURRENT
Definition: linkedlists.h:565
static struct ast_threadstorage switch_data
Definition: pbx.c:864
static struct ast_tone_zone_sound * ast_tone_zone_sound_unref(struct ast_tone_zone_sound *ts)
Release a reference to an ast_tone_zone_sound.
Definition: indications.h:226
char * exten
Definition: pbx.c:885
static int manager_show_dialplan_helper(struct mansession *s, const struct message *m, const char *actionidtext, const char *context, const char *exten, struct dialplan_counters *dpc, struct ast_include *rinclude)
Show dialplan extensions XXX this function is similar but not exactly the same as the CLI&#39;s show dial...
Definition: pbx.c:7261
Definition: pbx.c:1231
#define STATUS_SUCCESS
Definition: pbx.c:2999
char * registrar
Definition: pbx.c:963
static void print_ext(struct ast_exten *e, char *buf, int buflen)
helper function to print an extension
Definition: pbx.c:6905
int ast_extension_state_add_destroy(const char *context, const char *exten, ast_state_cb_type change_cb, ast_state_cb_destroy_type destroy_cb, void *data)
Registers a state change callback with destructor.
Definition: pbx.c:5048
ast_acf_write_fn_t write
Definition: pbx.h:118
A set of macros to manage forward-linked lists.
struct ast_exten * peer
Definition: pbx.c:895
static int show_debug_helper(int fd, const char *context, const char *exten, struct dialplan_counters *dpc, struct ast_include *rinclude, int includecount, const char *includes[])
Definition: pbx.c:7074
void(* datad)(void *)
Definition: pbx.c:894
struct ast_ignorepat * ignorepats
Definition: pbx.c:2963
void ast_str_substitute_variables_full(struct ast_str **buf, ssize_t maxlen, struct ast_channel *c, struct varshead *headp, const char *templ, size_t *used)
Definition: pbx.c:4289
char name[0]
Definition: pbx.c:967
Definition: pbx.c:9518
static void cli_match_char_tree(struct match_char *node, char *prefix, int fd)
Definition: pbx.c:1699
#define AST_RWLIST_INSERT_BEFORE_CURRENT
Definition: linkedlists.h:595
char stuff[0]
Definition: pbx.c:921
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:818
int tm_mday
Definition: localtime.h:39
static int pbx_builtin_saynumber(struct ast_channel *, const char *)
Definition: pbx.c:10755
static void wait_for_hangup(struct ast_channel *chan, const void *data)
Definition: pbx.c:9882
struct ast_ignorepat * ast_walk_context_ignorepats(struct ast_context *con, struct ast_ignorepat *ip)
Definition: pbx.c:11212
int pbx_set_autofallthrough(int newval)
Definition: pbx.c:5941
static ast_mutex_t conlock
Lock for the ast_context list.
Definition: pbx.c:1294
struct ast_hashtab * ast_hashtab_create(int initial_buckets, int(*compare)(const void *a, const void *b), int(*resize)(struct ast_hashtab *), int(*newsize)(struct ast_hashtab *tab), unsigned int(*hash)(const void *obj), int do_locking)
Create the hashtable list.
Definition: hashtab.c:226
const char * ast_get_extension_cidmatch(struct ast_exten *e)
Definition: pbx.c:11136
#define PRIORITY_HINT
Definition: pbx.h:53
int total_specificity
Definition: pbx.c:945
int ast_exists_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid)
Determine whether an extension exists.
Definition: pbx.c:5400
int ast_context_add_ignorepat2(struct ast_context *con, const char *ignorepat, const char *registrar)
Definition: pbx.c:8611
struct ast_context * ast_walk_contexts(struct ast_context *con)
Definition: pbx.c:11174
struct ast_hashtab * peer_label_table
Definition: pbx.c:897
const char * ast_get_context_name(struct ast_context *con)
Definition: pbx.c:11073
static void unload_pbx(void)
Definition: pbx.c:10973
void ast_hashtab_end_traversal(struct ast_hashtab_iter *it)
end the traversal, free the iterator, unlock if necc.
Definition: hashtab.c:746
#define STATUS_NO_LABEL
Definition: pbx.c:2998
char dev[0]
Definition: app_queue.c:1622
Core PBX routines and definitions.
char * ast_strptime(const char *s, const char *format, struct ast_tm *tm)
Special version of strptime(3) which places the answer in the common structure ast_tm. Also, unlike strptime(3), ast_strptime() initializes its memory prior to use.
Definition: localtime.c:2377
int ast_cdr_update(struct ast_channel *chan)
Update CDR on a channel.
Definition: cdr.c:1083
int ast_autoservice_stop(struct ast_channel *chan)
Stop servicing a channel for us...
Definition: autoservice.c:238
ast_pbx_result
The result codes when starting the PBX on a channel with ast_pbx_start.
Definition: pbx.h:299
int ast_check_hangup(struct ast_channel *chan)
Check to see if a channel is needing hang up.
Definition: channel.c:806
#define AST_RWLIST_TRAVERSE_SAFE_BEGIN
Definition: linkedlists.h:542
static int extension_match_core(const char *pattern, const char *data, enum ext_match_t mode)
Definition: pbx.c:2930
The list of nodes with their search requirement.
Definition: data.c:122
static int pbx_builtin_saycharacters(struct ast_channel *, const char *)
Definition: pbx.c:10792
struct ast_module_user * __ast_module_user_add(struct ast_module *, struct ast_channel *)
Definition: loader.c:209
char * term_color(char *outbuf, const char *inbuf, int fgcolor, int bgcolor, int maxout)
Definition: term.c:184
#define COLOR_BRMAGENTA
Definition: term.h:58
ast_switch_f * canmatch
Definition: pbx.h:134
const char *const * argv
Definition: cli.h:155
void ast_devstate_aggregate_add(struct ast_devstate_aggregate *agg, enum ast_device_state state)
Add a device state to the aggregate device state.
Definition: devicestate.c:764
const char * ast_devstate_str(enum ast_device_state devstate) attribute_pure
Convert device state to text string that is easier to parse.
Definition: devicestate.c:239
struct ast_party_dialed dialed
Dialed/Called information.
Definition: channel.h:797
static void pbx_shutdown(void)
Definition: pbx.c:11391
int ast_add_profile(const char *, uint64_t scale)
support for event profiling
Definition: asterisk.c:710
The AMI - Asterisk Manager Interface - is a TCP protocol created to manage Asterisk with third-party ...
#define AST_LIST_HEAD_NOLOCK(name, type)
Defines a structure to be used to hold a list of specified type (with no lock).
Definition: linkedlists.h:224
static const char desc[]
Definition: cdr_radius.c:85
#define AST_PBX_INCOMPLETE
Definition: pbx.h:50
static int pbx_builtin_busy(struct ast_channel *, const char *)
Definition: pbx.c:9934
#define ast_strdupa(s)
duplicate a string in memory from the stack
Definition: utils.h:663
#define AST_RWLIST_EMPTY
Definition: linkedlists.h:451
struct ast_custom_function * ast_custom_function_find(const char *name)
Definition: pbx.c:3800
static unsigned int hashtab_hash_priority(const void *obj)
Definition: pbx.c:1204
Responsible for call detail data.
Definition: cdr.h:82
char context_name[AST_MAX_CONTEXT]
Definition: pbx.c:1020
static void context_merge(struct ast_context **extcontexts, struct ast_hashtab *exttable, struct ast_context *context, const char *registrar)
Definition: pbx.c:7846
void ast_cdr_start(struct ast_cdr *cdr)
Start a call.
Definition: cdr.c:727
ast_rwlock_t lock
Definition: pbx.c:956
int ast_get_switch_eval(struct ast_sw *sw)
Definition: pbx.c:11161
int ast_processed_calls(void)
Retrieve the total number of calls processed through the PBX since last restart.
Definition: pbx.c:5936
static void * pbx_thread(void *data)
Definition: pbx.c:5859
unsigned int dowmask
Definition: pbx.h:143
#define LOG_ERROR
Definition: logger.h:155
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:716
int ast_pbx_outgoing_exten(const char *type, format_t format, void *data, int timeout, const char *context, const char *exten, int priority, int *reason, int sync, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel)
Definition: pbx.c:9375
#define EVENT_FLAG_CONFIG
Definition: manager.h:78
ast_acf_read2_fn_t read2
Definition: pbx.h:114
char stuff[0]
Definition: pbx.c:911
unsigned int minmask[48]
Definition: pbx.h:144
int laststate
Definition: pbx.c:1019
The descriptor of a dynamic string XXX storage will be optimized later if needed We use the ts field ...
Definition: strings.h:364
void ast_str_substitute_variables_varshead(struct ast_str **buf, ssize_t maxlen, struct varshead *headp, const char *templ)
Definition: pbx.c:4474
#define AST_MAX_APP
Definition: pbx.h:39
static int pbx_builtin_incomplete(struct ast_channel *, const char *)
Definition: pbx.c:9996
int64_t format_t
Definition: frame_defs.h:32
const ast_string_field syntax
Definition: pbx.c:979
static struct @350 args
int eval
Definition: pbx.c:919
void * data
Definition: pbx.c:893
int laststate
Definition: pbx.c:7806
#define CLI_SHOWUSAGE
Definition: cli.h:44
void pbx_retrieve_variable(struct ast_channel *c, const char *var, char **ret, char *workspace, int workspacelen, struct varshead *headp)
Retrieve the value of a builtin variable or variable from the channel variable stack.
Definition: pbx.c:3434
void * ast_hashtab_remove_object_via_lookup(struct ast_hashtab *tab, void *obj)
Looks up the object, removes the corresponding bucket.
Definition: hashtab.c:816
void ast_merge_contexts_and_delete(struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *registrar)
Merge the temporary contexts into a global contexts list and delete from the global list the ones tha...
Definition: pbx.c:7937
void ast_data_remove_node(struct ast_data *root, struct ast_data *child)
Remove a node that was added using ast_data_add_.
Definition: data.c:2486
const char * ast_get_switch_registrar(struct ast_sw *sw)
Definition: pbx.c:11166
static int _extension_match_core(const char *pattern, const char *data, enum ext_match_t mode)
Definition: pbx.c:2739
double option_maxload
Definition: asterisk.c:183
int plan
Q.931 Type-Of-Number and Numbering-Plan encoded fields.
Definition: channel.h:243
char * data
Definition: pbx.c:918
static int manager_show_dialplan(struct mansession *s, const struct message *m)
Manager listing of dial plan.
Definition: pbx.c:7397
int ast_check_timing(const struct ast_timing *i)
Evaluate a pre-constructed bitmap as to whether the current time falls within the range specified...
Definition: pbx.c:8357
void(* ast_state_cb_destroy_type)(int id, void *data)
Typedef for devicestate and hint callback removal indication callback.
Definition: pbx.h:92
static int compare_char(const void *a, const void *b)
Definition: pbx.c:1127
int ast_remaining_ms(struct timeval start, int max_ms)
Calculate remaining milliseconds given a starting timestamp and upper bound.
Definition: utils.c:1615
struct ast_exten * ast_walk_extension_priorities(struct ast_exten *exten, struct ast_exten *priority)
Definition: pbx.c:11197
ast_ignorepat: Ignore patterns in dial plan
Definition: pbx.c:925
int ast_unlock_contexts(void)
Unlocks contexts.
Definition: pbx.c:11047
#define ast_rwlock_init(rwlock)
wrapper for rwlock with tracking enabled
Definition: lock.h:190
int ast_findlabel_extension(struct ast_channel *c, const char *context, const char *exten, const char *label, const char *callerid)
Find the priority of an extension that has the specified label.
Definition: pbx.c:5405
Event subscription.
Definition: event.c:124
#define STATUS_NO_CONTEXT
Definition: pbx.c:2995
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
int ani2
Automatic Number Identification 2 (Info Digits)
Definition: channel.h:380
static int acf_exception_read(struct ast_channel *chan, const char *name, char *data, char *buf, size_t buflen)
Definition: pbx.c:3626
void ast_cdr_detach(struct ast_cdr *cdr)
Detaches the detail record for posting (and freeing) either now or at a later time in bulk with other...
Definition: cdr.c:1328
Description of a tone.
Definition: indications.h:36
enum ast_channel_state _state
Definition: channel.h:839
ast_state_cb_destroy_type destroy_cb
Definition: pbx.c:997
struct ast_tone_zone_sound * ast_get_indication_tone(const struct ast_tone_zone *zone, const char *indication)
Locate a tone zone sound.
Definition: indications.c:473
Structure for dial plan hints.
Definition: pbx.c:1010
#define NEW_MATCHER_CHK_MATCH
const char * name
Definition: pbx.c:905
const ast_string_field name
Definition: channel.h:787
int pbx_builtin_setvar_multiple(struct ast_channel *chan, const char *data)
Parse and set multiple channel variables, where the pairs are separated by the &#39;,&#39; character...
Definition: pbx.c:10633
struct sla_ringing_trunk * first
Definition: app_meetme.c:965
#define AST_PBX_MAX_STACK
Definition: extconf.h:223
ast_rwlock_t lock
Definition: pbx.c:2957
void ast_log(int level, const char *file, int line, const char *function, const char *fmt,...)
Used for sending a log message This is the standard logger function. Probably the only way you will i...
Definition: logger.c:1207
ast_switch_f * exec
Definition: pbx.h:135
int _softhangup
Definition: channel.h:832
int ast_context_remove_extension_callerid(const char *context, const char *extension, int priority, const char *callerid, int matchcid, const char *registrar)
Definition: pbx.c:6119
struct ast_sw::@289 list
#define ao2_alloc(data_size, destructor_fn)
Definition: astobj2.h:430
struct ast_datastore * ast_datastore_alloc(const struct ast_datastore_info *info, const char *uid)
Definition: datastore.c:98
const char * ast_get_extension_name(struct ast_exten *exten)
Definition: pbx.c:11083
#define LOG_NOTICE
Definition: logger.h:133
int ast_wrlock_context(struct ast_context *con)
Write locks a given context.
Definition: pbx.c:11055
struct ast_context * next
Definition: pbx.c:960
int ast_goto_if_exists(struct ast_channel *chan, const char *context, const char *exten, int priority)
Definition: pbx.c:11261
static const char *const days[]
Definition: pbx.c:8285
static struct ast_data_entry pbx_data_providers[]
Definition: pbx.c:10967
static int extenpatternmatchnew
Definition: pbx.c:1221
an iterator for traversing the buckets
Definition: hashtab.h:105
static int collect_digits(struct ast_channel *c, int waittime, char *buf, int buflen, int pos)
collect digits from the channel into the buffer.
Definition: pbx.c:5446
static char * synopsis
Definition: func_enum.c:156
const char * description
Definition: pbx.h:131
int ast_softhangup_nolock(struct ast_channel *chan, int reason)
Softly hangup up a channel (no channel lock)
Definition: channel.c:2733
static int totalcalls
Definition: pbx.c:1229
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
Definition: linkedlists.h:409
static int hashtab_compare_exten_numbers(const void *ah_a, const void *ah_b)
Definition: pbx.c:1174
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Definition: linkedlists.h:696
enum ast_extension_states ast_devstate_to_extenstate(enum ast_device_state devstate)
Map devstate to an extension state.
Definition: pbx.c:4844
static int read_escalates(const struct ast_custom_function *acf)
Returns true if given custom function escalates privileges on read.
Definition: pbx.c:3856
char data[1]
Definition: pbx.c:7808
#define ao2_find(arg1, arg2, arg3)
Definition: astobj2.h:964
int ast_destroy_timing(struct ast_timing *i)
Deallocates memory structures associated with a timing bitmap.
Definition: pbx.c:8396
#define ast_channel_unlock(chan)
Definition: channel.h:2467
#define CLI_FAILURE
Definition: cli.h:45
int tm_wday
Definition: localtime.h:42
int errno
static void parse(struct mgcp_request *req)
Definition: chan_mgcp.c:1858
static int matchcid(const char *cidpattern, const char *callerid)
Definition: pbx.c:3001
#define AST_MAX_CONTEXT
Definition: channel.h:136
struct ast_var_t::@158 entries
static char * complete_show_dialplan_context(const char *line, const char *word, int pos, int state)
Definition: pbx.c:6865
#define ast_free(a)
Definition: astmm.h:97
char * command
Definition: cli.h:180
static void destroy_pattern_tree(struct match_char *pattern_tree)
Definition: pbx.c:2344
const char * ast_get_ignorepat_name(struct ast_ignorepat *ip)
Definition: pbx.c:11098
enum ast_doc_src docsrc
Definition: pbx.c:981
static int ext_cmp_exten_partial(const char *left, const char *right)
Definition: pbx.c:2398
void ast_devstate_aggregate_init(struct ast_devstate_aggregate *agg)
Initialize aggregate device state.
Definition: devicestate.c:758
static char * handle_unset_extenpatternmatchnew(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: pbx.c:7634
unsigned int ast_hashtab_hash_contexts(const void *obj)
Definition: pbx.c:1188
static struct ast_context * find_context_locked(const char *context)
lookup for a context with a given name,
Definition: pbx.c:5985
void pbx_live_dangerously(int new_live_dangerously)
Enable/disable the execution of &#39;dangerous&#39; functions from external protocols (AMI, etc.).
Definition: pbx.c:4059
int ast_say_character_str(struct ast_channel *chan, const char *num, const char *ints, const char *lang)
Definition: channel.c:8421
static char * handle_show_functions(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: pbx.c:3651
const char * foundcontext
Definition: extconf.h:238
int ast_register_switch(struct ast_switch *sw)
Register an alternative dialplan switch.
Definition: pbx.c:6439
static int maxsize
int stacklen
Definition: extconf.h:234
static struct ast_format f[]
Definition: format_g726.c:181
int ast_extension_close(const char *pattern, const char *data, int needmore)
Definition: pbx.c:2948
Definition: pbx.c:1303
static char * handle_set_global(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: pbx.c:7547
Asterisk XML Documentation API.
const char * word
Definition: cli.h:157
char app[AST_MAX_EXTENSION]
Definition: pbx.c:9281
int ast_extension_match(const char *pattern, const char *extension)
Determine if a given extension matches a given pattern (in NXX format)
Definition: pbx.c:2943
static int pbx_builtin_answer(struct ast_channel *, const char *)
Definition: pbx.c:9964
void ast_cdr_setapp(struct ast_cdr *cdr, const char *app, const char *data)
Set the last executed application.
Definition: cdr.c:822
static int pbx_builtin_congestion(struct ast_channel *, const char *)
Definition: pbx.c:9950
static int handle_statechange(void *datap)
Definition: pbx.c:4936
const char * registrar
Definition: pbx.c:898
int pbx_builtin_setvar(struct ast_channel *chan, const char *data)
Parse and set a single channel variable, where the name and value are separated with an &#39;=&#39; character...
Definition: pbx.c:10603
unsigned int ast_hashtab_hash_string(const void *obj)
Hashes a string to a number.
Definition: hashtab.c:157
An API for managing task processing threads that can be shared across modules.
char * ast_xmldoc_printable(const char *bwinput, int withcolors)
Colorize and put delimiters (instead of tags) to the xmldoc output.
Definition: xmldoc.c:315
int tm_hour
Definition: localtime.h:38
static char * handle_show_application(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: pbx.c:6543
int ast_async_goto_if_exists(struct ast_channel *chan, const char *context, const char *exten, int priority)
Definition: pbx.c:11266
struct ast_exten * next
Definition: pbx.c:899
static void destroy_state_cb(void *doomed)
Definition: pbx.c:5038
struct pval * find_context(char *name)
Definition: pval.c:1960
int is_pattern
Definition: pbx.c:934
if(yyss+yystacksize-1<=yyssp)
Definition: ast_expr2.c:1874
static const char type[]
Definition: chan_nbs.c:57
static int ast_add_extension_nolock(const char *context, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar)
Definition: pbx.c:8671
void ao2_iterator_destroy(struct ao2_iterator *i)
Destroy a container iterator.
Definition: astobj2.c:833
const ast_string_field synopsis
Definition: pbx.h:103
static struct ast_custom_function exception_function
Definition: pbx.c:3646
Structure used to handle boolean flags.
Definition: utils.h:200
#define BACKGROUND_MATCHEXTEN
Definition: pbx.c:841
#define AST_LIST_HEAD_NOLOCK_INIT_VALUE
Defines initial values for a declaration of AST_LIST_HEAD_NOLOCK.
Definition: linkedlists.h:251
char * ast_xmldoc_build_syntax(const char *type, const char *name, const char *module)
Get the syntax for a specified application or function.
Definition: xmldoc.c:1156
int ast_build_timing(struct ast_timing *i, const char *info)
Construct a timing bitmap, for use in time-based conditionals.
Definition: pbx.c:8314
char * ast_xmldoc_build_seealso(const char *type, const char *name, const char *module)
Parse the &lt;see-also&gt; node content.
Definition: xmldoc.c:1461
#define ast_clear_flag(p, flag)
Definition: utils.h:77
int ast_spawn_extension(struct ast_channel *c, const char *context, const char *exten, int priority, const char *callerid, int *found, int combined_find_spawn)
Launch a new extension (i.e. new stack)
Definition: pbx.c:5425
static int find_hint_by_cb_id(void *obj, void *arg, int flags)
Remove a watcher from the callback list.
Definition: pbx.c:5142
const char * cidmatch
Definition: pbx.c:887
static char cid_name[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:158
#define AST_RWLIST_ENTRY
Definition: linkedlists.h:414
struct match_char * node
Definition: pbx.c:949
static int pbx_builtin_waitexten(struct ast_channel *, const char *)
Definition: pbx.c:10244
int ast_say_phonetic_str(struct ast_channel *chan, const char *num, const char *ints, const char *lang)
Definition: channel.c:8427
const char * usage
Definition: cli.h:171
static int replace(struct ast_channel *chan, const char *cmd, char *data, struct ast_str **buf, ssize_t len)
Definition: func_strings.c:775
int ast_async_parseable_goto(struct ast_channel *chan, const char *goto_string)
Definition: pbx.c:11331
int pbx_builtin_setvar_helper(struct ast_channel *chan, const char *name, const char *value)
Add a variable to the channel variable stack, removing the most recently set value for the same name...
Definition: pbx.c:10546
int ast_str_expr(struct ast_str **str, ssize_t maxlen, struct ast_channel *chan, char *expr)
Evaluate the given expression.
Definition: ast_expr2f.c:2438
#define ast_rwlock_wrlock(a)
Definition: lock.h:202
int ast_waitfordigit(struct ast_channel *c, int ms)
Waits for a digit.
Definition: channel.c:3552
struct match_char * pattern_tree
Definition: pbx.c:2960
struct ast_eid ast_eid_default
Global EID.
Definition: asterisk.c:192
struct ast_sw * ast_walk_context_switches(struct ast_context *con, struct ast_sw *sw)
Definition: pbx.c:11188
struct ast_sw * next
Definition: pbx.c:920
void ast_str_reset(struct ast_str *buf)
Reset the content of a dynamic string. Useful before a series of ast_str_append.
Definition: strings.h:436
unsigned int ast_hashtab_hash_int(const int num)
Definition: hashtab.c:209
#define EVENT_FLAG_REPORTING
Definition: manager.h:80
#define CLI_SUCCESS
Definition: cli.h:43
static int pbx_builtin_ringing(struct ast_channel *, const char *)
Definition: pbx.c:9925
size_t ast_str_strlen(const struct ast_str *buf)
Returns the current length of the string stored within buf.
Definition: strings.h:471
int ast_pbx_init(void)
Definition: pbx.c:11407
void * data
Definition: datastore.h:56
#define AST_RWLIST_INSERT_TAIL
Definition: linkedlists.h:726
int transit_network_select
Transit Network Select.
Definition: channel.h:347
void ast_cdr_discard(struct ast_cdr *cdr)
Discard and free a CDR record.
Definition: cdr.c:488
static void * async_wait(void *data)
Definition: pbx.c:9285
struct ast_flags ast_options
Definition: asterisk.c:178
static struct ast_exten * ast_hint_extension_nolock(struct ast_channel *c, const char *context, const char *exten)
Find hint for given extension in context.
Definition: pbx.c:4829
struct ast_context * parent
Definition: pbx.c:890
static const char * get_pattern_node(struct pattern_node *node, const char *src, int pattern, const char *extenbuf)
Definition: pbx.c:2078
A ast_taskprocessor structure is a singleton by name.
Definition: taskprocessor.c:67
const char * ast_str_retrieve_variable(struct ast_str **buf, ssize_t maxlen, struct ast_channel *chan, struct varshead *headp, const char *var)
Definition: pbx.c:3445
static int pbx_builtin_saydate(struct ast_channel *, const char *)
Definition: pbx.c:10810
static int pbx_builtin_saytime(struct ast_channel *, const char *)
Definition: pbx.c:10858
const char * ast_module_name(const struct ast_module *mod)
Get the name of a module.
Definition: loader.c:104
int ast_waitfor(struct ast_channel *chan, int ms)
Wait for input on a channel.
Definition: channel.c:3539
int ast_add_extension(const char *context, int replace, const char *extension, int priority, const char *label, const char *callerid, const char *application, void *data, void(*datad)(void *), const char *registrar)
Add and extension to an extension context.
Definition: pbx.c:8691
int dtimeoutms
Definition: pbx.h:180
When we need to walk through a container, we use an ao2_iterator to keep track of the current positio...
Definition: astobj2.h:1053
struct ast_channel * ast_request_and_dial(const char *type, format_t format, const struct ast_channel *requestor, void *data, int timeout, int *reason, const char *cid_num, const char *cid_name)
Request a channel of a given type, with data as optional information used by the low level module and...
Definition: channel.c:5650
Structure for rwlock and tracking information.
Definition: lock.h:133
struct timeval ast_mktime(struct ast_tm *const tmp, const char *zone)
Timezone-independent version of mktime(3).
Definition: localtime.c:2185
int ast_say_number(struct ast_channel *chan, int num, const char *ints, const char *lang, const char *options)
says a number
Definition: channel.c:8397
static char * complete_core_show_hint(const char *line, const char *word, int pos, int state)
autocomplete for CLI command &#39;core show hint&#39;
Definition: pbx.c:6649
Standard Command Line Interface.
format_t readformat
Definition: channel.h:853
ast_acf_read_fn_t read
Definition: pbx.h:106
#define ast_calloc(a, b)
Definition: astmm.h:82
const char * app
Definition: pbx.c:891
struct ast_event_sub * ast_event_subscribe(enum ast_event_type event_type, ast_event_cb_t cb, const char *description, void *userdata,...)
Subscribe to events.
Definition: event.c:909
void ast_copy_string(char *dst, const char *src, size_t size)
Size-limited null-terminating string copy.
Definition: strings.h:223
int ast_hashtab_insert_safe(struct ast_hashtab *tab, const void *obj)
Check and insert new object only if it is not there.
Definition: hashtab.c:503
#define ao2_container_alloc(arg1, arg2, arg3)
Definition: astobj2.h:734
void ast_str_update(struct ast_str *buf)
Update the length of the buffer, after using ast_str merely as a buffer.
Definition: strings.h:446
static struct ast_switch * pbx_findswitch(const char *sw)
Definition: pbx.c:1551
int ast_extension_state(struct ast_channel *c, const char *context, const char *exten)
Uses hint and devicestate callback to get the state of an extension.
Definition: pbx.c:4914
#define S_OR(a, b)
returns the equivalent of logic or for strings: first one if not empty, otherwise second one...
Definition: strings.h:77
static void update_scoreboard(struct scoreboard *board, int length, int spec, struct ast_exten *exten, char last, const char *callerid, int deleted, struct match_char *node)
Definition: pbx.c:1652
void * ast_taskprocessor_unreference(struct ast_taskprocessor *tps)
Unreference the specified taskprocessor and its reference count will decrement.
ast_app: A registered application
Definition: pbx.c:971
ext_match_t
Definition: extconf.h:215
Extra information for an ast_custom_function holding privilege escalation information. Kept in a separate structure for ABI compatibility.
Definition: pbx.c:1237
static void * ast_pbx_run_app(void *data)
run the application and free the descriptor once done
Definition: pbx.c:9528
static int countcalls
Definition: pbx.c:1228
int ast_cli_register_multiple(struct ast_cli_entry *e, int len)
Register multiple commands.
Definition: cli.c:2167
const int pos
Definition: cli.h:158
const char * context
Definition: channel.h:999
int ast_waitstream(struct ast_channel *c, const char *breakon)
Waits for a stream to stop or digit to be pressed.
Definition: file.c:1343
struct ast_context::@290 alts
static struct ast_context * local_contexts
Definition: pbx_config.c:60
#define AST_PBX_GOTO_FAILED
Definition: pbx.h:41
int ast_setstate(struct ast_channel *chan, enum ast_channel_state)
Change the state of a channel.
Definition: channel.c:7119
int refcount
Definition: pbx.c:964
int ast_async_goto(struct ast_channel *chan, const char *context, const char *exten, int priority)
Set the channel to next execute the specified dialplan location.
Definition: pbx.c:8731
int ast_answer(struct ast_channel *chan)
Answer a channel.
Definition: channel.c:3086
int total_prio
Definition: pbx.c:6899
static char * overrideswitch
Definition: pbx.c:1222
Application convenience functions, designed to give consistent look and feel to Asterisk apps...
void pbx_set_overrideswitch(const char *newval)
Definition: pbx.c:5955
int ast_thread_inhibit_escalations(void)
Inhibit (in the current thread) the execution of dialplan functions which cause privilege escalations...
Definition: pbx.c:4072
enum ast_pbx_result ast_pbx_run(struct ast_channel *c)
Execute the PBX in the current thread.
Definition: pbx.c:5926
static unsigned int hashtab_hash_extens(const void *obj)
Definition: pbx.c:1194
static int add_priority(struct ast_context *con, struct ast_exten *tmp, struct ast_exten *el, struct ast_exten *e, int replace)
add the extension in the priority chain.
Definition: pbx.c:8856
static int parse_variable_name(char *var, int *offset, int *length, int *isfunc)
extract offset:length from variable name.
Definition: pbx.c:3311
static struct ao2_container * statecbs
Definition: pbx.c:1316
const ast_string_field accountcode
Definition: channel.h:787
int ast_context_remove_extension2(struct ast_context *con, const char *extension, int priority, const char *registrar, int already_locked)
This functionc locks given context, search for the right extension and fires out all peer in this ext...
Definition: pbx.c:6144
static void print_app_docs(struct ast_app *aa, int fd)
Definition: pbx.c:6468
char * ast_complete_channels(const char *line, const char *word, int pos, int state, int rpos)
Command completion for the list of active channels.
Definition: cli.c:1547
Data structure associated with a single frame of data.
Definition: frame.h:142
const ast_string_field seealso
Definition: pbx.c:979
int __ast_custom_function_register(struct ast_custom_function *acf, struct ast_module *mod)
Register a custom function.
Definition: pbx.c:3946
int hangupcause
Definition: channel.h:849
Internal Asterisk hangup causes.
static int total
Definition: res_adsi.c:967
void ast_context_destroy(struct ast_context *con, const char *registrar)
Destroy a context (matches the specified context (or ANY context if NULL)
Definition: pbx.c:9875
static int ast_remove_hint(struct ast_exten *e)
Remove hint from extension.
Definition: pbx.c:5237
static struct ast_taskprocessor * device_state_tps
Definition: pbx.c:862
struct ast_switch * swo
Definition: extconf.h:236
static int include_valid(struct ast_include *i)
Definition: pbx.c:1565
int ast_register_application2(const char *app, int(*execute)(struct ast_channel *, const char *), const char *synopsis, const char *description, void *mod)
Register an application.
Definition: pbx.c:6344
You shouldn&#39;t care about the contents of this struct.
Definition: devicestate.h:265
struct ast_hashtab * root_table
Definition: pbx.c:958
const char * registrar
Definition: pbx.c:917
Counters for the show dialplan manager command.
Definition: pbx.c:6895
pthread_t t
Definition: pbx.c:9520
int ast_playtones_start(struct ast_channel *chan, int vol, const char *tonelist, int interruptible)
Start playing a list of tones on a channel.
Definition: indications.c:319
int canmatch
Definition: pbx.c:948
static struct ast_app_option background_opts[128]
Definition: pbx.c:849
static struct ast_context * contexts
Definition: pbx.c:1285
#define WAITEXTEN_DIALTONE
Definition: pbx.c:852
static char * handle_set_chanvar(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
Definition: pbx.c:7569
#define AST_RWLIST_REMOVE
Definition: linkedlists.h:870
ast_switch_f * exists
Definition: pbx.h:133
const char * name
Definition: pbx.h:96
int ast_tonepair_start(struct ast_channel *chan, int freq1, int freq2, int duration, int vol)
Definition: channel.c:7951
char * ast_str_set_substr(struct ast_str **buf, ssize_t maxlen, const char *src, size_t maxsrc)
Set a dynamic string to a non-NULL terminated substring.
Definition: strings.h:816
Handy terminal functions for vt* terms.
struct timeval tv
struct timeval whentohangup
Definition: channel.h:789
int64_t ast_tvdiff_us(struct timeval end, struct timeval start)
Computes the difference (in microseconds) between two struct timeval instances.
Definition: time.h:70
const char * data
Description of a tone.
Definition: indications.h:53
void pbx_substitute_variables_helper_full(struct ast_channel *c, struct varshead *headp, const char *cp1, char *cp2, int cp2_size, size_t *used)
Definition: pbx.c:4480
enum queue_result id
Definition: app_queue.c:1090
#define AST_APP_ARG(name)
Define an application argument.
Definition: app.h:555
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:528
int ast_context_verify_includes(struct ast_context *con)
Verifies includes in an ast_contect structure.
Definition: pbx.c:11221
enum ast_frame_type frametype
Definition: frame.h:144
int ast_str2cause(const char *name) attribute_pure
Convert the string form of a cause code to a number.
Definition: channel.c:993
struct store_hint::@294 callbacks
static char * handle_show_globals(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
CLI support for listing global variables in a parseable way.
Definition: pbx.c:7454
#define ast_mutex_init(pmutex)
Definition: lock.h:152
struct ast_exten * pbx_find_extension(struct ast_channel *chan, struct ast_context *bypass, struct pbx_find_info *q, const char *context, const char *exten, int priority, const char *label, const char *callerid, enum ext_match_t action)
Definition: pbx.c:3013
static int ext_cmp_exten(const char *left, const char *right)
Definition: pbx.c:2441
#define ast_frfree(fr)
Definition: frame.h:583
int total_length
Definition: pbx.c:946
struct ast_str * ast_str_thread_get(struct ast_threadstorage *ts, size_t init_len)
Retrieve a thread locally stored dynamic string.
Definition: strings.h:669
#define AST_STANDARD_APP_ARGS(args, parse)
Performs the &#39;standard&#39; argument separation process for an application.
Definition: app.h:604
static struct ast_app_option resetcdr_opts[128]
Definition: pbx.c:10023
struct match_char * next_char
Definition: pbx.c:938
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:107
#define ast_mutex_destroy(a)
Definition: lock.h:154
int ast_pbx_outgoing_app(const char *type, format_t format, void *data, int timeout, const char *app, const char *appdata, int *reason, int sync, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel)
Definition: pbx.c:9544
int(* execute)(struct ast_channel *chan, const char *data)
Definition: pbx.c:972
an app starts
Definition: cel.h:58
SAY_EXTERN int(* ast_say_time)(struct ast_channel *chan, time_t t, const char *ints, const char *lang) SAY_INIT(ast_say_time)
Definition: say.h:162
struct ast_context * ast_context_find_or_create(struct ast_context **extcontexts, struct ast_hashtab *exttable, const char *name, const char *registrar)
Register a new context or find an existing one.
Definition: pbx.c:7726
int ast_extension_state_add(const char *context, const char *exten, ast_state_cb_type change_cb, void *data)
Registers a state change callback.
Definition: pbx.c:5135
int ast_context_add_switch(const char *context, const char *sw, const char *data, int eval, const char *registrar)
Add a switch.
Definition: pbx.c:8474
static int pbx_extension_helper(struct ast_channel *c, struct ast_context *con, const char *context, const char *exten, int priority, const char *label, const char *callerid, enum ext_match_t action, int *found, int combined_find_spawn)
The return value depends on the action:
Definition: pbx.c:4706
static int pbx_builtin_noop(struct ast_channel *, const char *)
Definition: pbx.c:10704
const char * ast_event_get_ie_str(const struct ast_event *event, enum ast_event_ie_type ie_type)
Get the value of an information element that has a string payload.
Definition: event.c:1102
struct ast_exten * exten
Definition: pbx.c:951
#define AST_NONSTANDARD_APP_ARGS(args, parse, sep)
Performs the &#39;nonstandard&#39; argument separation process for an application.
Definition: app.h:619
static int write_escalates(const struct ast_custom_function *acf)
Returns true if given custom function escalates privileges on write.
Definition: pbx.c:3878
struct ast_channel * ast_dummy_channel_alloc(void)
Create a fake channel structure.
Definition: channel.c:1391
const ast_string_field seealso
Definition: pbx.h:103
static void device_state_cb(const struct ast_event *event, void *unused)
Definition: pbx.c:10905
static struct varshead globals
Definition: pbx.c:1218
static int hints_data_provider_get(const struct ast_data_search *search, struct ast_data *data_root)
Definition: pbx.c:10928
Say numbers and dates (maybe words one day too)
static int pbx_builtin_resetcdr(struct ast_channel *, const char *)
Definition: pbx.c:10028
#define manager_event(category, event, contents,...)
External routines may send asterisk manager events this way.
Definition: manager.h:219
static void set_ext_pri(struct ast_channel *c, const char *exten, int pri)
Definition: pbx.c:5431
char * name
Definition: pbx.c:916
struct ast_channel * ast_channel_get_by_name(const char *name)
Find a channel by name.
Definition: channel.c:1803
static int ext_strncpy(char *dst, const char *src, int len)
copy a string skipping whitespace
Definition: pbx.c:8827
int ast_get_extension_matchcid(struct ast_exten *e)
Definition: pbx.c:11131
#define ast_malloc(a)
Definition: astmm.h:91
struct ast_data * ast_data_add_str(struct ast_data *root, const char *childname, const char *string)
Add a string node type.
Definition: data.c:2401
void astman_send_error(struct mansession *s, const struct message *m, char *error)
Send error in manager transaction.
Definition: manager.c:2130
Asterisk module definitions.
const ast_string_field context
Definition: pbx.c:1055
unsigned int no_hangup_chan
Definition: pbx.h:343
char * strcasestr(const char *, const char *)
void * data
Definition: pbx.c:993
int ast_findlabel_extension2(struct ast_channel *c, struct ast_context *con, const char *exten, const char *label, const char *callerid)
Find the priority of an extension that has the specified label.
Definition: pbx.c:5410
int ast_hashtab_size(struct ast_hashtab *tab)
Returns the number of elements stored in the hashtab.
Definition: hashtab.c:625
int amaflags
Definition: channel.h:843
int ast_context_remove_switch2(struct ast_context *con, const char *sw, const char *data, const char *registrar)
This function locks given context, removes switch, unlock context and return.
Definition: pbx.c:6087
static char * func_args(char *function)
return a pointer to the arguments of the function, and terminates the function name with &#39;\0&#39; ...
Definition: pbx.c:4041
void ast_hashtab_get_stats(struct ast_hashtab *tab, int *biggest_bucket_size, int *resize_count, int *num_objects, int *num_buckets)
Returns key stats for the table.
Definition: hashtab.c:611
char exten_name[AST_MAX_EXTENSION]
Definition: pbx.c:1021
Device Name Used by AST_EVENT_DEVICE_STATE_CHANGE Payload type: STR.
Definition: event_defs.h:107
static snd_pcm_format_t format
Definition: chan_alsa.c:93
static int ast_extension_state3(struct ast_str *hint_app)
Definition: pbx.c:4871
int ast_func_write(struct ast_channel *chan, const char *function, const char *value)
executes a write operation on a function
Definition: pbx.c:4263
int option_maxcalls
Definition: asterisk.c:184
static int match(struct sockaddr_in *sin, unsigned short callno, unsigned short dcallno, const struct chan_iax2_pvt *cur, int check_dcallno)
Definition: chan_iax2.c:2069
int ast_channel_datastore_add(struct ast_channel *chan, struct ast_datastore *datastore)
Add a datastore to a channel.
Definition: channel.c:2590
static unsigned get_range(char *src, int max, const char *const names[], const char *msg)
helper function to return a range up to max (7, 12, 31 respectively). names, if supplied, is an array of names that should be mapped to numbers.
Definition: pbx.c:8182
int specif
Definition: pbx.c:2019
struct ast_data * ast_data_add_int(struct ast_data *root, const char *childname, int value)
Add an integer node type.
Definition: data.c:2322
static struct pbx_builtin builtins[]
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:253
struct ast_event_sub * ast_event_unsubscribe(struct ast_event_sub *event_sub)
Un-subscribe from events.
Definition: event.c:987
int total_context
Definition: pbx.c:6897
ast_context: An extension context
Definition: pbx.c:955
int ast_context_remove_ignorepat2(struct ast_context *con, const char *ignorepat, const char *registrar)
Definition: pbx.c:8567
int ast_expr(char *expr, char *buf, int length, struct ast_channel *chan)
Evaluate the given expression.
Definition: ast_expr2f.c:2396
unsigned char valid
TRUE if the number information is valid/present.
Definition: channel.h:247
static int hint_id_cmp(void *obj, void *arg, int flags)
Definition: pbx.c:5191
int load_pbx(void)
Definition: pbx.c:10996
struct ao2_container * callbacks
Definition: pbx.c:1018
int getloadavg(double *list, int nelem)
const ast_string_field data
Definition: pbx.c:9524
int ast_context_unlockmacro(const char *macrocontext)
Unlocks the macrolock in the given context.
Definition: pbx.c:6327
int ast_cdr_init(struct ast_cdr *cdr, struct ast_channel *chan)
Initialize based on a channel.
Definition: cdr.c:897
int ast_data_search_match(const struct ast_data_search *search, struct ast_data *data)
Check the current generated node to know if it matches the search condition.
Definition: data.c:1458
struct varshead varshead
Definition: channel.h:817
#define AST_RWLIST_TRAVERSE_SAFE_END
Definition: linkedlists.h:602
int extension_existence
Definition: pbx.c:6901
const ast_string_field language
Definition: channel.h:787
uint32_t version
Structure version.
Definition: data.h:247
struct ast_ignorepat * next
Definition: pbx.c:927
struct ast_context * ast_context_find(const char *name)
Find a context.
Definition: pbx.c:2971
struct ast_cdr * ast_cdr_alloc(void)
Allocate a CDR record.
Definition: cdr.c:499
const ast_string_field app
Definition: pbx.c:9524
int ast_do_masquerade(struct ast_channel *chan)
Start masquerading a channel.
Definition: channel.c:6546
char exten[AST_MAX_EXTENSION]
Definition: channel.h:869
#define AST_MUTEX_DEFINE_STATIC(mutex)
Definition: lock.h:526
struct ast_exten * root
Definition: pbx.c:957
int ast_stopstream(struct ast_channel *c)
Stops a stream.
Definition: file.c:128
int ast_async_goto_by_name(const char *chan, const char *context, const char *exten, int priority)
Set the channel to next execute the specified dialplan location.
Definition: pbx.c:8813
int tm_min
Definition: localtime.h:37
Structure for mutex and tracking information.
Definition: lock.h:121
char buf[256]
Definition: pbx.c:2021
void pbx_substitute_variables_varshead(struct varshead *headp, const char *cp1, char *cp2, int count)
Definition: pbx.c:4682
static force_inline int attribute_pure ast_str_case_hash(const char *str)
Compute a hash value on a case-insensitive string.
Definition: strings.h:989
Declaration of builtin applications.
Definition: pbx.c:1247
struct match_char * pattern_tree
Definition: pbx.c:959
The structure of the node handler.
Definition: data.h:245
int ast_manager_unregister(char *action)
Unregister a registered manager command.
Definition: manager.c:5355
static const char * ast_str_substring(struct ast_str *value, int offset, int length)
Definition: pbx.c:3380
jack_status_t status
Definition: app_jack.c:143
struct ast_context * ast_get_extension_context(struct ast_exten *exten)
Definition: pbx.c:11078
#define ASTERISK_FILE_VERSION(file, version)
Register/unregister a source code file with the core.
Definition: asterisk.h:180
#define COLOR_MAGENTA
Definition: term.h:57
int ast_rdlock_context(struct ast_context *con)
Read locks a given context.
Definition: pbx.c:11060
#define BITS_PER
#define AST_APP_OPTION(option, flagno)
Declares an application option that does not accept an argument.
Definition: app.h:721
#define ast_mutex_unlock(a)
Definition: lock.h:156
#define VAR_BUF_SIZE
Definition: pbx.c:833
static struct ast_exten * get_canmatch_exten(struct match_char *node)
Definition: pbx.c:1729
int ast_waitstream_exten(struct ast_channel *c, const char *context)
Waits for a stream to stop or digit matching a valid one digit exten to be pressed.
Definition: file.c:1354
struct ast_pbx * pbx
Definition: channel.h:761
static uint16_t t1
Definition: res_pktccops.c:159
int pbx_builtin_serialize_variables(struct ast_channel *chan, struct ast_str **buf)
Create a human-readable string, specifying all variables and their corresponding values.
Definition: pbx.c:10444
static char prefix[MAX_PREFIX]
Definition: http.c:107
static void destroy_exten(struct ast_exten *e)
Definition: pbx.c:5845
const ast_string_field arguments
Definition: pbx.c:979
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:344
int rtimeoutms
Definition: pbx.h:181
int deleted
Definition: pbx.c:935
match_char: forms a syntax tree for quick matching of extension patterns
Definition: pbx.c:932
void astman_send_listack(struct mansession *s, const struct message *m, char *msg, char *listflag)
Send ack in manager list transaction.
Definition: manager.c:2145
void ast_cdr_busy(struct ast_cdr *cdr)
Busy a call.
Definition: cdr.c:753
char appdata[1024]
Definition: pbx.c:9282
void ast_hashtab_destroy(struct ast_hashtab *tab, void(*objdestroyfunc)(void *obj))
This func will free the hash table and all its memory.
Definition: hashtab.c:388
static void insert_in_next_chars_alt_char_list(struct match_char **parent_ptr, struct match_char *node)
Definition: pbx.c:1983
struct ast_party_number number
Subscriber phone number.
Definition: channel.h:292
static void get_timerange(struct ast_timing *i, char *times)
store a bitmask of valid times, one bit each 1 minute
Definition: pbx.c:8225
void * ast_hashtab_remove_this_object(struct ast_hashtab *tab, void *obj)
Hash the object and then compare ptrs in bucket list instead of calling the compare routine...
Definition: hashtab.c:859