app_dial: Allow macro/gosub pre-bridge execution to occur on priorities
[asterisk/asterisk.git] / main / features_config.c
1 /*
2 * Asterisk -- An open source telephony toolkit.
3 *
4 * Copyright (C) 2013, Digium, Inc.
5 *
6 * Mark Michelson <mmichelson@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 #include "asterisk.h"
20
21 #include "asterisk/features_config.h"
22 #include "asterisk/config_options.h"
23 #include "asterisk/datastore.h"
24 #include "asterisk/channel.h"
25 #include "asterisk/pbx.h"
26 #include "asterisk/app.h"
27 #include "asterisk/cli.h"
28
29 /*** DOCUMENTATION
30         <configInfo name="features" language="en_US">
31                 <synopsis>Features Configuration</synopsis>
32                 <configFile name="features.conf">
33                         <configObject name="globals">
34                                 <synopsis>
35                                 </synopsis>
36                                 <configOption name="featuredigittimeout" default="1000">
37                                         <synopsis>Milliseconds allowed between digit presses when entering a feature code.</synopsis>
38                                 </configOption>
39                                 <configOption name="courtesytone">
40                                         <synopsis>Sound to play when automon or automixmon is activated</synopsis>
41                                 </configOption>
42                                 <configOption name="recordingfailsound">
43                                         <synopsis>Sound to play when automon or automixmon is attempted but fails to start</synopsis>
44                                 </configOption>
45                                 <configOption name="transferdigittimeout" default="3">
46                                         <synopsis>Seconds allowed between digit presses when dialing a transfer destination</synopsis>
47                                 </configOption>
48                                 <configOption name="atxfernoanswertimeout" default="15">
49                                         <synopsis>Seconds to wait for attended transfer destination to answer</synopsis>
50                                 </configOption>
51                                 <configOption name="atxferdropcall" default="no">
52                                         <synopsis>Hang up the call entirely if the attended transfer fails</synopsis>
53                                         <description>
54                                                 <para>When this option is set to <literal>no</literal>, then Asterisk will attempt to
55                                                 re-call the transferrer if the call to the transfer target fails. If the call to the
56                                                 transferrer fails, then Asterisk will wait <replaceable>atxferloopdelay</replaceable>
57                                                 milliseconds and then attempt to dial the transfer target again. This process will
58                                                 repeat until <replaceable>atxfercallbackretries</replaceable> attempts to re-call
59                                                 the transferrer have occurred.</para>
60                                                 <para>When this option is set to <literal>yes</literal>, then Asterisk will not attempt
61                                                 to re-call the transferrer if the call to the transfer target fails. Asterisk will instead
62                                                 hang up all channels involved in the transfer.</para>
63                                         </description>
64                                 </configOption>
65                                 <configOption name="atxferloopdelay" default="10">
66                                         <synopsis>Seconds to wait between attempts to re-dial transfer destination</synopsis>
67                                         <see-also><ref type="configOption">atxferdropcall</ref></see-also>
68                                 </configOption>
69                                 <configOption name="atxfercallbackretries" default="2">
70                                         <synopsis>Number of times to re-attempt dialing a transfer destination</synopsis>
71                                         <see-also><ref type="configOption">atxferdropcall</ref></see-also>
72                                 </configOption>
73                                 <configOption name="xfersound" default="beep">
74                                         <synopsis>Sound to play to during transfer and transfer-like operations.</synopsis>
75                                         <description>
76                                                 <para>This sound will play to the transferrer and transfer target channels when
77                                                 an attended transfer completes. This sound is also played to channels when performing
78                                                 an AMI <literal>Bridge</literal> action.</para>
79                                         </description>
80                                 </configOption>
81                                 <configOption name="xferfailsound" default="beeperr">
82                                         <synopsis>Sound to play to a transferee when a transfer fails</synopsis>
83                                 </configOption>
84                                 <configOption name="atxferabort" default="*1">
85                                         <synopsis>Digits to dial to abort an attended transfer attempt</synopsis>
86                                         <description>
87                                                 <para>This option is only available to the transferrer during an attended
88                                                 transfer operation. Aborting a transfer results in the transfer being cancelled and
89                                                 the original parties in the call being re-bridged.</para>
90                                         </description>
91                                 </configOption>
92                                 <configOption name="atxfercomplete" default="*2">
93                                         <synopsis>Digits to dial to complete an attended transfer</synopsis>
94                                         <description>
95                                                 <para>This option is only available to the transferrer during an attended
96                                                 transfer operation. Completing the transfer with a DTMF sequence is functionally
97                                                 equivalent to hanging up the transferrer channel during an attended transfer. The
98                                                 result is that the transfer target and transferees are bridged.</para>
99                                         </description>
100                                 </configOption>
101                                 <configOption name="atxferthreeway" default="*3">
102                                         <synopsis>Digits to dial to change an attended transfer into a three-way call</synopsis>
103                                         <description>
104                                                 <para>This option is only available to the transferrer during an attended
105                                                 transfer operation. Pressing this DTMF sequence will result in the transferrer,
106                                                 the transferees, and the transfer target all being in a single bridge together.</para>
107                                         </description>
108                                 </configOption>
109                                 <configOption name="atxferswap" default="*4">
110                                         <synopsis>Digits to dial to toggle who the transferrer is currently bridged to during an attended transfer</synopsis>
111                                         <description>
112                                                 <para>This option is only available to the transferrer during an attended
113                                                 transfer operation. Pressing this DTMF sequence will result in the transferrer swapping
114                                                 which party he is bridged with. For instance, if the transferrer is currently bridged with
115                                                 the transfer target, then pressing this DTMF sequence will cause the transferrer to be
116                                                 bridged with the transferees.</para>
117                                         </description>
118                                 </configOption>
119                                 <configOption name="pickupexten" default="*8">
120                                         <synopsis>Digits used for picking up ringing calls</synopsis>
121                                         <description>
122                                                 <para>In order for the pickup attempt to be successful, the party attempting to
123                                                 pick up the call must either have a <replaceable>namedpickupgroup</replaceable> in
124                                                 common with a ringing party's <replaceable>namedcallgroup</replaceable> or must
125                                                 have a <replaceable>pickupgroup</replaceable> in common with a ringing party's
126                                                 <replaceable>callgroup</replaceable>.</para>
127                                         </description>
128                                 </configOption>
129                                 <configOption name="pickupsound">
130                                         <synopsis>Sound to play to picker when a call is picked up</synopsis>
131                                 </configOption>
132                                 <configOption name="pickupfailsound">
133                                         <synopsis>Sound to play to picker when a call cannot be picked up</synopsis>
134                                 </configOption>
135                         </configObject>
136                         <configObject name="featuremap">
137                                 <synopsis>DTMF options that can be triggered during bridged calls</synopsis>
138                                 <configOption name="atxfer">
139                                         <synopsis>DTMF sequence to initiate an attended transfer</synopsis>
140                                         <description>
141                                                 <para>The transferee parties will be placed on hold and the
142                                                 transferrer may dial an extension to reach a transfer target. During an
143                                                 attended transfer, the transferrer may consult with the transfer target
144                                                 before completing the transfer. Once the transferrer has hung up or pressed
145                                                 the <replaceable>atxfercomplete</replaceable> DTMF sequence, then the transferees
146                                                 and transfer target will be bridged.</para>
147                                         </description>
148                                 </configOption>
149                                 <configOption name="blindxfer" default="#">
150                                         <synopsis>DTMF sequence to initiate a blind transfer</synopsis>
151                                         <description>
152                                                 <para>The transferee parties will be placed on hold and the
153                                                 transferrer may dial an extension to reach a transfer target. During a
154                                                 blind transfer, as soon as the transfer target is dialed, the transferrer
155                                                 is hung up.</para>
156                                         </description>
157                                 </configOption>
158                                 <configOption name="disconnect" default="*">
159                                         <synopsis>DTMF sequence to disconnect the current call</synopsis>
160                                         <description>
161                                                 <para>Entering this DTMF sequence will cause the bridge to end, no
162                                                 matter the number of parties present</para>
163                                         </description>
164                                 </configOption>
165                                 <configOption name="parkcall">
166                                         <synopsis>DTMF sequence to park a call</synopsis>
167                                         <description>
168                                                 <para>The parking lot used to park the call is determined by using either the
169                                                 <replaceable>PARKINGLOT</replaceable> channel variable or a configured value on
170                                                 the channel (provided by the channel driver) if the variable is not present. If
171                                                 no configured value on the channel is present, then <literal>"default"</literal>
172                                                 is used. The call is parked in the next available space in the parking lot.</para>
173                                         </description>
174                                 </configOption>
175                                 <configOption name="automon">
176                                         <synopsis>DTMF sequence to start or stop monitoring a call</synopsis>
177                                         <description>
178                                                 <para>This will cause the channel that pressed the DTMF sequence
179                                                 to be monitored by the <literal>Monitor</literal> application. The
180                                                 format for the recording is determined by the <replaceable>TOUCH_MONITOR_FORMAT</replaceable>
181                                                 channel variable. If this variable is not specified, then <literal>wav</literal> is the
182                                                 default. The filename is constructed in the following manner:</para>
183
184                                                 <para>    prefix-timestamp-filename</para>
185
186                                                 <para>where prefix is either the value of the <replaceable>TOUCH_MONITOR_PREFIX</replaceable>
187                                                 channel variable or <literal>auto</literal> if the variable is not set. The timestamp
188                                                 is a UNIX timestamp. The filename is either the value of the <replaceable>TOUCH_MONITOR</replaceable>
189                                                 channel variable or the callerID of the channels if the variable is not set.</para>
190                                         </description>
191                                 </configOption>
192                                 <configOption name="automixmon">
193                                         <synopsis>DTMF sequence to start or stop mixmonitoring a call </synopsis>
194                                         <description>
195                                                 <para>Operation of the automixmon is similar to the <literal> automon </literal>
196                                                 feature, with the following exceptions:
197                                                         <replaceable>TOUCH_MIXMONITOR</replaceable> is used in place of <replaceable>TOUCH_MONITOR</replaceable>
198                                                         <replaceable>TOUCH_MIXMONITOR_FORMAT</replaceable> is used in place of <replaceable>TOUCH_MIXMONITOR</replaceable>
199                                                         There is no equivalent for <replaceable>TOUCH_MONITOR_PREFIX</replaceable>. <literal>"auto"</literal> is always how the filename begins.</para>
200                                         </description>
201                                         <see-also><ref type="configOption">automon</ref></see-also>
202                                 </configOption>
203                         </configObject>
204                         <configObject name="applicationmap">
205                                 <synopsis>Section for defining custom feature invocations during a call</synopsis>
206                                 <description>
207                                         <para>The applicationmap is an area where new custom features can be created. Items
208                                         defined in the applicationmap are not automatically accessible to bridged parties. Access
209                                         to the individual items is controled using the <replaceable>DYNAMIC_FEATURES</replaceable> channel variable.
210                                         The <replaceable>DYNAMIC_FEATURES</replaceable> is a <literal>#</literal> separated list of
211                                         either applicationmap item names or featuregroup names.</para>
212                                 </description>
213                                 <configOption name="^.*$" regex="true">
214                                         <synopsis>A custom feature to invoke during a bridged call</synopsis>
215                                         <description>
216                                                 <para>Each item listed here is a comma-separated list of parameters that determine
217                                                 how a feature may be invoked during a call</para>
218                                                 <para>    Example:</para>
219                                                 <para>    eggs = *5,self,Playback(hello-world),default</para>
220                                                 <para>This would create a feature called <literal>eggs</literal> that could be invoked
221                                                 during a call by pressing the <literal>*5</literal>. The party that presses the DTMF
222                                                 sequence would then trigger the <literal>Playback</literal> application to play the
223                                                 <literal>hello-world</literal> file. The application invocation would happen on the
224                                                 party that pressed the DTMF sequence since <literal>self</literal> is specified. The
225                                                 other parties in the bridge would hear the <literal>default</literal> music on hold
226                                                 class during the playback.</para>
227                                                 <para>In addition to the syntax outlined in this documentation, a backwards-compatible alternative
228                                                 is also allowed. The following applicationmap lines are functionally identical:</para>
229                                                 <para>    eggs = *5,self,Playback(hello-world),default</para>
230                                                 <para>    eggs = *5,self,Playback,hello-world,default</para>
231                                                 <para>    eggs = *5,self,Playback,"hello-world",default</para>
232                                         </description>
233                                         <syntax argsep=",">
234                                                 <parameter name="dtmf" required="true">
235                                                         <para>The DTMF sequence used to trigger the option</para>
236                                                 </parameter>
237                                                 <parameter name="activate_on" required="true">
238                                                         <para>The party that the feature will be invoked on</para>
239                                                         <optionlist>
240                                                                 <option name="self"><para>Feature is invoked on party that presses the DTMF sequence</para></option>
241                                                                 <option name="peer"><para>Feature is invoked on other parties in the bridge</para></option>
242                                                         </optionlist>
243                                                 </parameter>
244                                                 <parameter name="app" required="true">
245                                                         <para>The dialplan application to run when the DTMF sequence is pressed</para>
246                                                         <argument name="app_args" required="false">
247                                                                 <para>The arguments to the dialplan application to run</para>
248                                                         </argument>
249                                                 </parameter>
250                                                 <parameter name="moh_class" required="false">
251                                                         <para>Music on hold class to play to bridge participants that are not the target of the application invocation</para>
252                                                 </parameter>
253                                         </syntax>
254                                 </configOption>
255                         </configObject>
256                         <configObject name="featuregroup">
257                                 <synopsis>Groupings of items from the applicationmap</synopsis>
258                                 <description>
259                                         <para>Feature groups allow for multiple applicationmap items to be
260                                         grouped together. Like with individual applicationmap items, feature groups
261                                         can be part of the <replaceable>DYNAMIC_FEATURES</replaceable> channel variable.
262                                         In addition to creating groupings, the feature group section allows for the
263                                         DTMF sequence used to invoke an applicationmap item to be overridden with
264                                         a different sequence.</para>
265                                 </description>
266                                 <configOption name="^.*$" regex="true">
267                                         <synopsis>Applicationmap item to place in the feature group</synopsis>
268                                         <description>
269                                                 <para>Each item here must be a name of an item in the applicationmap. The
270                                                 argument may either be a new DTMF sequence to use for the item or it
271                                                 may be left blank in order to use the DTMF sequence specified in the
272                                                 applicationmap. For example:</para>
273                                                 <para>  eggs => *1</para>
274                                                 <para>  bacon =></para>
275                                                 <para>would result in the applicationmap items <literal>eggs</literal> and
276                                                 <literal>bacon</literal> being in the featuregroup. The former would have its
277                                                 default DTMF trigger overridden with <literal>*1</literal> and the latter would
278                                                 have the DTMF value specified in the applicationmap.</para>
279                                         </description>
280                                 </configOption>
281                         </configObject>
282                 </configFile>
283         </configInfo>
284         <function name="FEATURE" language="en_US">
285                 <synopsis>
286                         Get or set a feature option on a channel.
287                 </synopsis>
288                 <syntax>
289                         <parameter name="option_name" required="true">
290                                 <para>The allowed values are:</para>
291                                 <enumlist>
292                                         <enum name="inherit"><para>Inherit feature settings made in FEATURE or FEATUREMAP to child channels.</para></enum>
293                                         <enum name="featuredigittimeout"><para><xi:include xpointer="xpointer(/docs/configInfo[@name='features']/configFile[@name='features.conf']/configObject[@name='globals']/configOption[@name='featuredigittimeout']/synopsis/text())" /></para></enum>
294                                         <enum name="transferdigittimeout"><para><xi:include xpointer="xpointer(/docs/configInfo[@name='features']/configFile[@name='features.conf']/configObject[@name='globals']/configOption[@name='transferdigittimeout']/synopsis/text())" /></para></enum>
295                                         <enum name="atxfernoanswertimeout"><para><xi:include xpointer="xpointer(/docs/configInfo[@name='features']/configFile[@name='features.conf']/configObject[@name='globals']/configOption[@name='atxfernoanswertimeout']/synopsis/text())" /></para></enum>
296                                         <enum name="atxferdropcall"><para><xi:include xpointer="xpointer(/docs/configInfo[@name='features']/configFile[@name='features.conf']/configObject[@name='globals']/configOption[@name='atxferdropcall']/synopsis/text())" /></para></enum>
297                                         <enum name="atxferloopdelay"><para><xi:include xpointer="xpointer(/docs/configInfo[@name='features']/configFile[@name='features.conf']/configObject[@name='globals']/configOption[@name='atxferloopdelay']/synopsis/text())" /></para></enum>
298                                         <enum name="atxfercallbackretries"><para><xi:include xpointer="xpointer(/docs/configInfo[@name='features']/configFile[@name='features.conf']/configObject[@name='globals']/configOption[@name='atxfercallbackretries']/synopsis/text())" /></para></enum>
299                                         <enum name="xfersound"><para><xi:include xpointer="xpointer(/docs/configInfo[@name='features']/configFile[@name='features.conf']/configObject[@name='globals']/configOption[@name='xfersound']/synopsis/text())" /></para></enum>
300                                         <enum name="xferfailsound"><para><xi:include xpointer="xpointer(/docs/configInfo[@name='features']/configFile[@name='features.conf']/configObject[@name='globals']/configOption[@name='xferfailsound']/synopsis/text())" /></para></enum>
301                                         <enum name="atxferabort"><para><xi:include xpointer="xpointer(/docs/configInfo[@name='features']/configFile[@name='features.conf']/configObject[@name='globals']/configOption[@name='atxferabort']/synopsis/text())" /></para></enum>
302                                         <enum name="atxfercomplete"><para><xi:include xpointer="xpointer(/docs/configInfo[@name='features']/configFile[@name='features.conf']/configObject[@name='globals']/configOption[@name='atxfercomplete']/synopsis/text())" /></para></enum>
303                                         <enum name="atxferthreeway"><para><xi:include xpointer="xpointer(/docs/configInfo[@name='features']/configFile[@name='features.conf']/configObject[@name='globals']/configOption[@name='atxferthreeway']/synopsis/text())" /></para></enum>
304                                         <enum name="pickupexten"><para><xi:include xpointer="xpointer(/docs/configInfo[@name='features']/configFile[@name='features.conf']/configObject[@name='globals']/configOption[@name='pickupexten']/synopsis/text())" /></para></enum>
305                                         <enum name="pickupsound"><para><xi:include xpointer="xpointer(/docs/configInfo[@name='features']/configFile[@name='features.conf']/configObject[@name='globals']/configOption[@name='pickupsound']/synopsis/text())" /></para></enum>
306                                         <enum name="pickupfailsound"><para><xi:include xpointer="xpointer(/docs/configInfo[@name='features']/configFile[@name='features.conf']/configObject[@name='globals']/configOption[@name='pickupfailsound']/synopsis/text())" /></para></enum>
307                                         <enum name="courtesytone"><para><xi:include xpointer="xpointer(/docs/configInfo[@name='features']/configFile[@name='features.conf']/configObject[@name='globals']/configOption[@name='courtesytone']/synopsis/text())" /></para></enum>
308                                         <enum name="recordingfailsound"><para><xi:include xpointer="xpointer(/docs/configInfo[@name='features']/configFile[@name='features.conf']/configObject[@name='globals']/configOption[@name='recordingfailsound']/synopsis/text())" /></para></enum>
309                                 </enumlist>
310                         </parameter>
311                 </syntax>
312                 <description>
313                         <para>When this function is used as a read, it will get the current
314                         value of the specified feature option for this channel.  It will be
315                         the value of this option configured in features.conf if a channel specific
316                         value has not been set.  This function can also be used to set a channel
317                         specific value for the supported feature options.</para>
318                 </description>
319                 <see-also>
320                         <ref type="function">FEATUREMAP</ref>
321                 </see-also>
322         </function>
323         <function name="FEATUREMAP" language="en_US">
324                 <synopsis>
325                         Get or set a feature map to a given value on a specific channel.
326                 </synopsis>
327                 <syntax>
328                         <parameter name="feature_name" required="true">
329                                 <para>The allowed values are:</para>
330                                 <enumlist>
331                                         <enum name="atxfer"><para>Attended Transfer</para></enum>
332                                         <enum name="blindxfer"><para>Blind Transfer</para></enum>
333                                         <enum name="automon"><para>Auto Monitor</para></enum>
334                                         <enum name="disconnect"><para>Call Disconnect</para></enum>
335                                         <enum name="parkcall"><para>Park Call</para></enum>
336                                         <enum name="automixmon"><para>Auto MixMonitor</para></enum>
337                                 </enumlist>
338                         </parameter>
339                 </syntax>
340                 <description>
341                         <para>When this function is used as a read, it will get the current
342                         digit sequence mapped to the specified feature for this channel.  This
343                         value will be the one configured in features.conf if a channel specific
344                         value has not been set.  This function can also be used to set a channel
345                         specific value for a feature mapping.</para>
346                 </description>
347                 <see-also>
348                         <ref type="function">FEATURE</ref>
349                 </see-also>
350         </function>
351  ***/
352 /*! Default general options */
353 #define DEFAULT_FEATURE_DIGIT_TIMEOUT               1000
354 #define DEFAULT_COURTESY_TONE                       ""
355 #define DEFAULT_RECORDING_FAIL_SOUND                ""
356
357 /*! Default xfer options */
358 #define DEFAULT_TRANSFER_DIGIT_TIMEOUT              3
359 #define DEFAULT_NOANSWER_TIMEOUT_ATTENDED_TRANSFER  15
360 #define DEFAULT_ATXFER_DROP_CALL                    0
361 #define DEFAULT_ATXFER_LOOP_DELAY                   10
362 #define DEFAULT_ATXFER_CALLBACK_RETRIES             2
363 #define DEFAULT_XFERSOUND                           "beep"
364 #define DEFAULT_XFERFAILSOUND                       "beeperr"
365 #define DEFAULT_ATXFER_ABORT                        "*1"
366 #define DEFAULT_ATXFER_COMPLETE                     "*2"
367 #define DEFAULT_ATXFER_THREEWAY                     "*3"
368 #define DEFAULT_ATXFER_SWAP                         "*4"
369
370 /*! Default pickup options */
371 #define DEFAULT_PICKUPEXTEN                         "*8"
372 #define DEFAULT_PICKUPSOUND                         ""
373 #define DEFAULT_PICKUPFAILSOUND                     ""
374
375 /*! Default featuremap options */
376 #define DEFAULT_FEATUREMAP_BLINDXFER                "#"
377 #define DEFAULT_FEATUREMAP_DISCONNECT               "*"
378 #define DEFAULT_FEATUREMAP_AUTOMON                  ""
379 #define DEFAULT_FEATUREMAP_ATXFER                   ""
380 #define DEFAULT_FEATUREMAP_PARKCALL                 ""
381 #define DEFAULT_FEATUREMAP_AUTOMIXMON               ""
382
383 /*!
384  * \brief Configuration from the "general" section of features.conf
385  */
386 struct features_global_config {
387         struct ast_features_general_config *general;
388         struct ast_features_xfer_config *xfer;
389         struct ast_features_pickup_config *pickup;
390 };
391
392 static void ast_applicationmap_item_destructor(void *obj)
393 {
394         struct ast_applicationmap_item *item = obj;
395
396         ast_string_field_free_memory(item);
397 }
398
399 static int applicationmap_sort(const void *obj, const void *arg, int flags)
400 {
401         const struct ast_applicationmap_item *item1 = obj;
402         const struct ast_applicationmap_item *item2;
403         const char *key2;
404
405         switch(flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) {
406         case OBJ_KEY:
407                 key2 = arg;
408                 return strcasecmp(item1->name, key2);
409         case OBJ_PARTIAL_KEY:
410                 key2 = arg;
411                 return strncasecmp(item1->name, key2, strlen(key2));
412         default:
413         case OBJ_POINTER:
414                 item2 = arg;
415                 return strcasecmp(item1->name, item2->name);
416         }
417 }
418
419 /*!
420  * \brief Entry in the container of featuregroups
421  */
422 struct featuregroup_item {
423         AST_DECLARE_STRING_FIELDS(
424                 /*! The name of the applicationmap item that we are referring to */
425                 AST_STRING_FIELD(appmap_item_name);
426                 /*! Custom DTMF override to use instead of the default for the applicationmap item */
427                 AST_STRING_FIELD(dtmf_override);
428         );
429         /*! The applicationmap item that is being referred to */
430         struct ast_applicationmap_item *appmap_item;
431 };
432
433 static void featuregroup_item_destructor(void *obj)
434 {
435         struct featuregroup_item *item = obj;
436
437         ast_string_field_free_memory(item);
438         ao2_cleanup(item->appmap_item);
439 }
440
441 static int group_item_sort(const void *obj, const void *arg, int flags)
442 {
443         const struct featuregroup_item *item1 = obj;
444         const struct featuregroup_item *item2;
445         const char *key2;
446
447         switch(flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) {
448         case OBJ_KEY:
449                 key2 = arg;
450                 return strcasecmp(item1->appmap_item_name, key2);
451         case OBJ_PARTIAL_KEY:
452                 key2 = arg;
453                 return strncasecmp(item1->appmap_item_name, key2, strlen(key2));
454         case OBJ_POINTER:
455                 item2 = arg;
456                 return strcasecmp(item1->appmap_item_name, item2->appmap_item_name);
457         default:
458                 return CMP_STOP;
459         }
460 }
461
462 /*!
463  * \brief Featuregroup representation
464  */
465 struct featuregroup {
466         /*! The name of the featuregroup */
467         const char *name;
468         /*! A container of featuregroup_items */
469         struct ao2_container *items;
470 };
471
472 static int featuregroup_hash(const void *obj, int flags)
473 {
474         const struct featuregroup *group;
475         const char *key;
476
477         switch (flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) {
478         case OBJ_KEY:
479                 key = obj;
480                 return ast_str_case_hash(key);
481         case OBJ_PARTIAL_KEY:
482                 ast_assert(0);
483                 return 0;
484         case OBJ_POINTER:
485         default:
486                 group = obj;
487                 return ast_str_case_hash(group->name);
488         }
489 }
490
491 static int featuregroup_cmp(void *obj, void *arg, int flags)
492 {
493         struct featuregroup *group1 = obj;
494         struct featuregroup *group2;
495         const char *key2;
496
497         switch(flags & (OBJ_POINTER | OBJ_KEY | OBJ_PARTIAL_KEY)) {
498         case OBJ_KEY:
499                 key2 = arg;
500                 return strcasecmp(group1->name, key2) ? 0 : CMP_MATCH;
501         case OBJ_PARTIAL_KEY:
502                 key2 = arg;
503                 return strncasecmp(group1->name, key2, strlen(key2)) ? 0 : CMP_MATCH;
504         case OBJ_POINTER:
505                 group2 = arg;
506                 return strcasecmp(group1->name, group2->name) ? 0 : CMP_MATCH;
507         default:
508                 return CMP_STOP;
509         }
510 }
511
512 static void *featuregroup_find(struct ao2_container *group_container, const char *category)
513 {
514         return ao2_find(group_container, category, OBJ_KEY);
515 }
516
517 static void featuregroup_destructor(void *obj)
518 {
519         struct featuregroup *group = obj;
520
521         ast_free((char *) group->name);
522         ao2_cleanup(group->items);
523 }
524
525 static void *featuregroup_alloc(const char *cat)
526 {
527         struct featuregroup *group;
528
529         group = ao2_alloc(sizeof(*group), featuregroup_destructor);
530         if (!group) {
531                 return NULL;
532         }
533
534         group->name = ast_strdup(cat);
535         if (!group->name) {
536                 ao2_cleanup(group);
537                 return NULL;
538         }
539
540         group->items = ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_NOLOCK,
541                 AO2_CONTAINER_ALLOC_OPT_DUPS_REPLACE, group_item_sort, NULL);
542         if (!group->items) {
543                 ao2_cleanup(group);
544                 return NULL;
545         }
546
547         return group;
548 }
549
550 /* Used for deprecated parking configuration */
551 struct dummy_config {
552         char dummy;
553 };
554
555 struct features_config {
556         struct features_global_config *global;
557         struct ast_featuremap_config *featuremap;
558         struct dummy_config *parkinglots;
559         struct ao2_container *applicationmap;
560         struct ao2_container *featuregroups;
561 };
562
563 static struct aco_type global_option = {
564         .type = ACO_GLOBAL,
565         .name = "globals",
566         .category_match = ACO_WHITELIST,
567         .category = "^general$",
568         .item_offset = offsetof(struct features_config, global),
569 };
570
571 static struct aco_type featuremap_option = {
572         .type = ACO_GLOBAL,
573         .name = "featuremap",
574         .category_match = ACO_WHITELIST,
575         .category = "^featuremap$",
576         .item_offset = offsetof(struct features_config, featuremap),
577 };
578
579 static struct aco_type applicationmap_option = {
580         .type = ACO_GLOBAL,
581         .name = "applicationmap",
582         .category_match = ACO_WHITELIST,
583         .category = "^applicationmap$",
584         .item_offset = offsetof(struct features_config, applicationmap),
585 };
586
587 static struct aco_type featuregroup_option = {
588         .type = ACO_ITEM,
589         .name = "featuregroup",
590         .category_match = ACO_BLACKLIST,
591         .category = "^(general|featuremap|applicationmap|parkinglot_.*)$",
592         .item_offset = offsetof(struct features_config, featuregroups),
593         .item_alloc = featuregroup_alloc,
594         .item_find = featuregroup_find,
595 };
596
597 static struct aco_type parkinglot_option = {
598         .type = ACO_GLOBAL,
599         .name = "parkinglot",
600         .category_match = ACO_WHITELIST,
601         .category = "^parkinglot_.*$",
602         .item_offset = offsetof(struct features_config, parkinglots),
603         .hidden = 1,
604 };
605
606 static struct aco_type *global_options[] = ACO_TYPES(&global_option);
607 static struct aco_type *featuremap_options[] = ACO_TYPES(&featuremap_option);
608 static struct aco_type *applicationmap_options[] = ACO_TYPES(&applicationmap_option);
609 static struct aco_type *featuregroup_options[] = ACO_TYPES(&featuregroup_option);
610 static struct aco_type *parkinglot_options[] = ACO_TYPES(&parkinglot_option);
611
612 static struct aco_file features_conf = {
613         .filename = "features.conf",
614         .types = ACO_TYPES(&global_option, &featuremap_option, &applicationmap_option, &featuregroup_option, &parkinglot_option),
615 };
616
617 AO2_GLOBAL_OBJ_STATIC(globals);
618
619 static void features_config_destructor(void *obj)
620 {
621         struct features_config *cfg = obj;
622
623         ao2_cleanup(cfg->global);
624         ao2_cleanup(cfg->featuremap);
625         ao2_cleanup(cfg->parkinglots);
626         ao2_cleanup(cfg->applicationmap);
627         ao2_cleanup(cfg->featuregroups);
628 }
629
630 static void featuremap_config_destructor(void *obj)
631 {
632         struct ast_featuremap_config *cfg = obj;
633
634         ast_string_field_free_memory(cfg);
635 }
636
637 static void global_config_destructor(void *obj)
638 {
639         struct features_global_config *cfg = obj;
640
641         ao2_cleanup(cfg->general);
642         ao2_cleanup(cfg->xfer);
643         ao2_cleanup(cfg->pickup);
644 }
645
646 static void general_destructor(void *obj)
647 {
648         struct ast_features_general_config *cfg = obj;
649
650         ast_string_field_free_memory(cfg);
651 }
652
653 static void xfer_destructor(void *obj)
654 {
655         struct ast_features_xfer_config *cfg = obj;
656
657         ast_string_field_free_memory(cfg);
658 }
659
660 static void pickup_destructor(void *obj)
661 {
662         struct ast_features_pickup_config *cfg = obj;
663
664         ast_string_field_free_memory(cfg);
665 }
666
667 static struct features_global_config *global_config_alloc(void)
668 {
669         RAII_VAR(struct features_global_config *, cfg, NULL, ao2_cleanup);
670
671         cfg = ao2_alloc(sizeof(*cfg), global_config_destructor);
672         if (!cfg) {
673                 return NULL;
674         }
675
676         cfg->general = ao2_alloc(sizeof(*cfg->general), general_destructor);
677         if (!cfg->general || ast_string_field_init(cfg->general, 32)) {
678                 return NULL;
679         }
680
681         cfg->xfer = ao2_alloc(sizeof(*cfg->xfer), xfer_destructor);
682         if (!cfg->xfer || ast_string_field_init(cfg->xfer, 32)) {
683                 return NULL;
684         }
685
686         cfg->pickup = ao2_alloc(sizeof(*cfg->pickup), pickup_destructor);
687         if (!cfg->pickup || ast_string_field_init(cfg->pickup, 32)) {
688                 return NULL;
689         }
690
691         ao2_ref(cfg, +1);
692         return cfg;
693 }
694
695 static struct ao2_container *applicationmap_alloc(int replace_duplicates)
696 {
697         return ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_NOLOCK,
698                 replace_duplicates ? AO2_CONTAINER_ALLOC_OPT_DUPS_REPLACE : AO2_CONTAINER_ALLOC_OPT_DUPS_ALLOW,
699                 applicationmap_sort, NULL);
700 }
701
702 /*!
703  * \internal
704  * \brief Allocate the major configuration structure
705  *
706  * The parameter is used to determine if the applicationmap and featuregroup
707  * structures should be allocated. We only want to allocate these structures for
708  * the global features_config structure. For the datastores on channels, we don't
709  * need to allocate these structures because they are not used.
710  *
711  * \param allocate_applicationmap See previous explanation
712  * \retval NULL Failed to alloate configuration
713  * \retval non-NULL Allocated configuration
714  */
715 static struct features_config *__features_config_alloc(int allocate_applicationmap)
716 {
717         RAII_VAR(struct features_config *, cfg, NULL, ao2_cleanup);
718
719         cfg = ao2_alloc(sizeof(*cfg), features_config_destructor);
720         if (!cfg) {
721                 return NULL;
722         }
723
724         cfg->global = global_config_alloc();
725         if (!cfg->global) {
726                 return NULL;
727         }
728
729         cfg->featuremap = ao2_alloc(sizeof(*cfg->featuremap), featuremap_config_destructor);
730         if (!cfg->featuremap || ast_string_field_init(cfg->featuremap, 32)) {
731                 return NULL;
732         }
733
734         cfg->parkinglots = ao2_alloc(sizeof(*cfg->parkinglots), NULL);
735         if (!cfg->parkinglots) {
736                 return NULL;
737         }
738
739         if (allocate_applicationmap) {
740                 cfg->applicationmap = applicationmap_alloc(1);
741                 if (!cfg->applicationmap) {
742                         return NULL;
743                 }
744
745                 cfg->featuregroups = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_NOLOCK, 11, featuregroup_hash,
746                         featuregroup_cmp);
747                 if (!cfg->featuregroups) {
748                         return NULL;
749                 }
750         }
751
752         ao2_ref(cfg, +1);
753         return cfg;
754
755 }
756
757 static void *features_config_alloc(void)
758 {
759         return __features_config_alloc(1);
760 }
761
762 static void general_copy(struct ast_features_general_config *dest, const struct ast_features_general_config *src)
763 {
764         ast_string_fields_copy(dest, src);
765         dest->featuredigittimeout = src->featuredigittimeout;
766 }
767
768 static void xfer_copy(struct ast_features_xfer_config *dest, const struct ast_features_xfer_config *src)
769 {
770         ast_string_fields_copy(dest, src);
771         dest->transferdigittimeout = src->transferdigittimeout;
772         dest->atxfernoanswertimeout = src->atxfernoanswertimeout;
773         dest->atxferloopdelay = src->atxferloopdelay;
774         dest->atxfercallbackretries = src->atxfercallbackretries;
775         dest->atxferdropcall = src->atxferdropcall;
776 }
777
778 static void pickup_copy(struct ast_features_pickup_config *dest, const struct ast_features_pickup_config *src)
779 {
780         ast_string_fields_copy(dest, src);
781 }
782
783 static void global_copy(struct features_global_config *dest, const struct features_global_config *src)
784 {
785         general_copy(dest->general, src->general);
786         xfer_copy(dest->xfer, src->xfer);
787         pickup_copy(dest->pickup, src->pickup);
788 }
789
790 static void featuremap_copy(struct ast_featuremap_config *dest, const struct ast_featuremap_config *src)
791 {
792         ast_string_fields_copy(dest, src);
793 }
794
795 static void features_copy(struct features_config *dest, const struct features_config *src)
796 {
797         global_copy(dest->global, src->global);
798         featuremap_copy(dest->featuremap, src->featuremap);
799
800         /* applicationmap and featuregroups are purposely not copied. A channel's applicationmap
801          * is produced on the fly when ast_get_chan_applicationmap() is called
802          */
803 }
804
805 static struct features_config *features_config_dup(const struct features_config *orig)
806 {
807         struct features_config *dup;
808
809         dup = __features_config_alloc(0);
810         if (!dup) {
811                 return NULL;
812         }
813
814         features_copy(dup, orig);
815
816         return dup;
817 }
818
819 static int general_set(struct ast_features_general_config *general, const char *name,
820                 const char *value)
821 {
822         int res = 0;
823
824         if (!strcasecmp(name, "featuredigittimeout")) {
825                 res = ast_parse_arg(value, PARSE_INT32, &general->featuredigittimeout);
826         } else if (!strcasecmp(name, "courtesytone")) {
827                 ast_string_field_set(general, courtesytone, value);
828         } else if (!strcasecmp(name, "recordingfailsound")) {
829                 ast_string_field_set(general, recordingfailsound, value);
830         } else {
831                 /* Unrecognized option */
832                 res = -1;
833         }
834
835         return res;
836 }
837
838 static int general_get(struct ast_features_general_config *general, const char *field,
839                 char *buf, size_t len)
840 {
841         int res = 0;
842
843         if (!strcasecmp(field, "featuredigittimeout")) {
844                 snprintf(buf, len, "%u", general->featuredigittimeout);
845         } else if (!strcasecmp(field, "courtesytone")) {
846                 ast_copy_string(buf, general->courtesytone, len);
847         } else if (!strcasecmp(field, "recordingfailsound")) {
848                 ast_copy_string(buf, general->recordingfailsound, len);
849         } else {
850                 /* Unrecognized option */
851                 res = -1;
852         }
853
854         return res;
855 }
856
857 static int xfer_set(struct ast_features_xfer_config *xfer, const char *name,
858                 const char *value)
859 {
860         int res = 0;
861
862         if (!strcasecmp(name, "transferdigittimeout")) {
863                 res = ast_parse_arg(value, PARSE_INT32, &xfer->transferdigittimeout);
864         } else if (!strcasecmp(name, "atxfernoanswertimeout")) {
865                 res = ast_parse_arg(value, PARSE_INT32, &xfer->atxfernoanswertimeout);
866         } else if (!strcasecmp(name, "atxferloopdelay")) {
867                 res = ast_parse_arg(value, PARSE_INT32, &xfer->atxferloopdelay);
868         } else if (!strcasecmp(name, "atxfercallbackretries")) {
869                 res = ast_parse_arg(value, PARSE_INT32, &xfer->atxfercallbackretries);
870         } else if (!strcasecmp(name, "atxferdropcall")) {
871                 xfer->atxferdropcall = ast_true(value);
872         } else if (!strcasecmp(name, "xfersound")) {
873                 ast_string_field_set(xfer, xfersound, value);
874         } else if (!strcasecmp(name, "xferfailsound")) {
875                 ast_string_field_set(xfer, xferfailsound, value);
876         } else if (!strcasecmp(name, "atxferabort")) {
877                 ast_string_field_set(xfer, atxferabort, value);
878         } else if (!strcasecmp(name, "atxfercomplete")) {
879                 ast_string_field_set(xfer, atxfercomplete, value);
880         } else if (!strcasecmp(name, "atxferthreeway")) {
881                 ast_string_field_set(xfer, atxferthreeway, value);
882         } else if (!strcasecmp(name, "atxferswap")) {
883                 ast_string_field_set(xfer, atxferswap, value);
884         } else {
885                 /* Unrecognized option */
886                 res = -1;
887         }
888
889         return res;
890 }
891
892 static int xfer_get(struct ast_features_xfer_config *xfer, const char *field,
893                 char *buf, size_t len)
894 {
895         int res = 0;
896
897         if (!strcasecmp(field, "transferdigittimeout")) {
898                 snprintf(buf, len, "%u", xfer->transferdigittimeout);
899         } else if (!strcasecmp(field, "atxfernoanswertimeout")) {
900                 snprintf(buf, len, "%u", xfer->atxfernoanswertimeout);
901         } else if (!strcasecmp(field, "atxferloopdelay")) {
902                 snprintf(buf, len, "%u", xfer->atxferloopdelay);
903         } else if (!strcasecmp(field, "atxfercallbackretries")) {
904                 snprintf(buf, len, "%u", xfer->atxfercallbackretries);
905         } else if (!strcasecmp(field, "atxferdropcall")) {
906                 snprintf(buf, len, "%u", xfer->atxferdropcall);
907         } else if (!strcasecmp(field, "xfersound")) {
908                 ast_copy_string(buf, xfer->xfersound, len);
909         } else if (!strcasecmp(field, "xferfailsound")) {
910                 ast_copy_string(buf, xfer->xferfailsound, len);
911         } else if (!strcasecmp(field, "atxferabort")) {
912                 ast_copy_string(buf, xfer->atxferabort, len);
913         } else if (!strcasecmp(field, "atxfercomplete")) {
914                 ast_copy_string(buf, xfer->atxfercomplete, len);
915         } else if (!strcasecmp(field, "atxferthreeway")) {
916                 ast_copy_string(buf, xfer->atxferthreeway, len);
917         } else if (!strcasecmp(field, "atxferswap")) {
918                 ast_copy_string(buf, xfer->atxferswap, len);
919         } else {
920                 /* Unrecognized option */
921                 res = -1;
922         }
923
924         return res;
925 }
926
927 static int pickup_set(struct ast_features_pickup_config *pickup, const char *name,
928                 const char *value)
929 {
930         int res = 0;
931
932         if (!strcasecmp(name, "pickupsound")) {
933                 ast_string_field_set(pickup, pickupsound, value);
934         } else if (!strcasecmp(name, "pickupfailsound")) {
935                 ast_string_field_set(pickup, pickupfailsound, value);
936         } else if (!strcasecmp(name, "pickupexten")) {
937                 ast_string_field_set(pickup, pickupexten, value);
938         } else {
939                 /* Unrecognized option */
940                 res = -1;
941         }
942
943         return res;
944 }
945
946 static int pickup_get(struct ast_features_pickup_config *pickup, const char *field,
947                 char *buf, size_t len)
948 {
949         int res = 0;
950
951         if (!strcasecmp(field, "pickupsound")) {
952                 ast_copy_string(buf, pickup->pickupsound, len);
953         } else if (!strcasecmp(field, "pickupfailsound")) {
954                 ast_copy_string(buf, pickup->pickupfailsound, len);
955         } else if (!strcasecmp(field, "pickupexten")) {
956                 ast_copy_string(buf, pickup->pickupexten, len);
957         } else {
958                 /* Unrecognized option */
959                 res = -1;
960         }
961
962         return res;
963 }
964
965 static int featuremap_set(struct ast_featuremap_config *featuremap, const char *name,
966                 const char *value)
967 {
968         int res = 0;
969
970         if (!strcasecmp(name, "blindxfer")) {
971                 ast_string_field_set(featuremap, blindxfer, value);
972         } else if (!strcasecmp(name, "disconnect")) {
973                 ast_string_field_set(featuremap, disconnect, value);
974         } else if (!strcasecmp(name, "automon")) {
975                 ast_string_field_set(featuremap, automon, value);
976         } else if (!strcasecmp(name, "atxfer")) {
977                 ast_string_field_set(featuremap, atxfer, value);
978         } else if (!strcasecmp(name, "automixmon")) {
979                 ast_string_field_set(featuremap, automixmon, value);
980         } else if (!strcasecmp(name, "parkcall")) {
981                 ast_string_field_set(featuremap, parkcall, value);
982         } else {
983                 /* Unrecognized option */
984                 res = -1;
985         }
986
987         return res;
988 }
989
990 static int featuremap_get(struct ast_featuremap_config *featuremap, const char *field,
991                 char *buf, size_t len)
992 {
993         int res = 0;
994
995         if (!strcasecmp(field, "blindxfer")) {
996                 ast_copy_string(buf, featuremap->blindxfer, len);
997         } else if (!strcasecmp(field, "disconnect")) {
998                 ast_copy_string(buf, featuremap->disconnect, len);
999         } else if (!strcasecmp(field, "automon")) {
1000                 ast_copy_string(buf, featuremap->automon, len);
1001         } else if (!strcasecmp(field, "atxfer")) {
1002                 ast_copy_string(buf, featuremap->atxfer, len);
1003         } else if (!strcasecmp(field, "automixmon")) {
1004                 ast_copy_string(buf, featuremap->automixmon, len);
1005         } else if (!strcasecmp(field, "parkcall")) {
1006                 ast_copy_string(buf, featuremap->parkcall, len);
1007         } else {
1008                 /* Unrecognized option */
1009                 res = -1;
1010         }
1011
1012         return res;
1013 }
1014
1015 static void feature_ds_destroy(void *data)
1016 {
1017         struct features_config *cfg = data;
1018         ao2_cleanup(cfg);
1019 }
1020
1021 static void *feature_ds_duplicate(void *data)
1022 {
1023         struct features_config *old_cfg = data;
1024
1025         return features_config_dup(old_cfg);
1026 }
1027
1028 static const struct ast_datastore_info feature_ds_info = {
1029         .type = "FEATURE",
1030         .destroy = feature_ds_destroy,
1031         .duplicate = feature_ds_duplicate,
1032 };
1033
1034 /*!
1035  * \internal
1036  * \brief Find or create feature datastore on a channel
1037  *
1038  * \pre chan is locked
1039  *
1040  * \return the data on the FEATURE datastore, or NULL on error
1041  */
1042 static struct features_config *get_feature_ds(struct ast_channel *chan)
1043 {
1044         RAII_VAR(struct features_config *, orig, NULL, ao2_cleanup);
1045         struct features_config *cfg;
1046         struct ast_datastore *ds;
1047
1048         if ((ds = ast_channel_datastore_find(chan, &feature_ds_info, NULL))) {
1049                 cfg = ds->data;
1050                 ao2_ref(cfg, +1);
1051                 return cfg;
1052         }
1053
1054         orig = ao2_global_obj_ref(globals);
1055         if (!orig) {
1056                 return NULL;
1057         }
1058
1059         cfg = features_config_dup(orig);
1060         if (!cfg) {
1061                 return NULL;
1062         }
1063
1064         if (!(ds = ast_datastore_alloc(&feature_ds_info, NULL))) {
1065                 ao2_cleanup(cfg);
1066                 return NULL;
1067         }
1068
1069         /* Give the datastore a reference to the config */
1070         ao2_ref(cfg, +1);
1071         ds->data = cfg;
1072
1073         ast_channel_datastore_add(chan, ds);
1074
1075         return cfg;
1076 }
1077
1078 static struct ast_datastore *get_feature_chan_ds(struct ast_channel *chan)
1079 {
1080         struct ast_datastore *ds;
1081
1082         if (!(ds = ast_channel_datastore_find(chan, &feature_ds_info, NULL))) {
1083                 /* Hasn't been created yet.  Trigger creation. */
1084                 RAII_VAR(struct features_config *, cfg, get_feature_ds(chan), ao2_cleanup);
1085                 ds = ast_channel_datastore_find(chan, &feature_ds_info, NULL);
1086         }
1087
1088         return ds;
1089 }
1090
1091 struct ast_features_general_config *ast_get_chan_features_general_config(struct ast_channel *chan)
1092 {
1093         RAII_VAR(struct features_config *, cfg, NULL, ao2_cleanup);
1094
1095         if (chan) {
1096                 cfg = get_feature_ds(chan);
1097         } else {
1098                 cfg = ao2_global_obj_ref(globals);
1099         }
1100
1101         if (!cfg) {
1102                 return NULL;
1103         }
1104
1105         ast_assert(cfg->global && cfg->global->general);
1106
1107         ao2_ref(cfg->global->general, +1);
1108         return cfg->global->general;
1109 }
1110
1111 struct ast_features_xfer_config *ast_get_chan_features_xfer_config(struct ast_channel *chan)
1112 {
1113         RAII_VAR(struct features_config *, cfg, NULL, ao2_cleanup);
1114
1115         if (chan) {
1116                 cfg = get_feature_ds(chan);
1117         } else {
1118                 cfg = ao2_global_obj_ref(globals);
1119         }
1120
1121         if (!cfg) {
1122                 return NULL;
1123         }
1124
1125         ast_assert(cfg->global && cfg->global->xfer);
1126
1127         ao2_ref(cfg->global->xfer, +1);
1128         return cfg->global->xfer;
1129 }
1130
1131 struct ast_features_pickup_config *ast_get_chan_features_pickup_config(struct ast_channel *chan)
1132 {
1133         RAII_VAR(struct features_config *, cfg, NULL, ao2_cleanup);
1134
1135         if (chan) {
1136                 cfg = get_feature_ds(chan);
1137         } else {
1138                 cfg = ao2_global_obj_ref(globals);
1139         }
1140
1141         if (!cfg) {
1142                 return NULL;
1143         }
1144
1145         ast_assert(cfg->global && cfg->global->pickup);
1146
1147         ao2_ref(cfg->global->pickup, +1);
1148         return cfg->global->pickup;
1149 }
1150
1151 struct ast_featuremap_config *ast_get_chan_featuremap_config(struct ast_channel *chan)
1152 {
1153         RAII_VAR(struct features_config *, cfg, NULL, ao2_cleanup);
1154
1155         if (chan) {
1156                 cfg = get_feature_ds(chan);
1157         } else {
1158                 cfg = ao2_global_obj_ref(globals);
1159         }
1160
1161         if (!cfg) {
1162                 return NULL;
1163         }
1164
1165         ast_assert(cfg->featuremap != NULL);
1166
1167         ao2_ref(cfg->featuremap, +1);
1168         return cfg->featuremap;
1169 }
1170
1171 int ast_get_builtin_feature(struct ast_channel *chan, const char *feature, char *buf, size_t len)
1172 {
1173         RAII_VAR(struct features_config *, cfg, NULL, ao2_cleanup);
1174
1175         if (chan) {
1176                 cfg = get_feature_ds(chan);
1177         } else {
1178                 cfg = ao2_global_obj_ref(globals);
1179         }
1180
1181         if (!cfg) {
1182                 return -1;
1183         }
1184
1185         return featuremap_get(cfg->featuremap, feature, buf, len);
1186 }
1187
1188 int ast_get_feature(struct ast_channel *chan, const char *feature, char *buf, size_t len)
1189 {
1190         RAII_VAR(struct ao2_container *, applicationmap, NULL, ao2_cleanup);
1191         RAII_VAR(struct ast_applicationmap_item *, item, NULL, ao2_cleanup);
1192
1193         if (!ast_get_builtin_feature(chan, feature, buf, len)) {
1194                 return 0;
1195         }
1196
1197         /* Dang, must be in the application map */
1198         applicationmap = ast_get_chan_applicationmap(chan);
1199         if (!applicationmap) {
1200                 return -1;
1201         }
1202
1203         item = ao2_find(applicationmap, feature, OBJ_KEY);
1204         if (!item) {
1205                 return -1;
1206         }
1207
1208         ast_copy_string(buf, item->dtmf, len);
1209         return 0;
1210 }
1211
1212 static struct ast_applicationmap_item *applicationmap_item_alloc(const char *name,
1213                 const char *app, const char *app_data, const char *moh_class, const char *dtmf,
1214                 unsigned int activate_on_self)
1215 {
1216         struct ast_applicationmap_item *item;
1217
1218         item = ao2_alloc(sizeof(*item), ast_applicationmap_item_destructor);
1219
1220         if (!item || ast_string_field_init(item, 64)) {
1221                 return NULL;
1222         }
1223
1224         ast_string_field_set(item, name, name);
1225         ast_string_field_set(item, app, app);
1226         ast_string_field_set(item, app_data, app_data);
1227         ast_string_field_set(item, moh_class, moh_class);
1228         ast_copy_string(item->dtmf, dtmf, sizeof(item->dtmf));
1229         item->activate_on_self = activate_on_self;
1230
1231         return item;
1232 }
1233
1234 static int add_item(void *obj, void *arg, int flags)
1235 {
1236         struct featuregroup_item *fg_item = obj;
1237         struct ao2_container *applicationmap = arg;
1238         RAII_VAR(struct ast_applicationmap_item *, appmap_item, NULL, ao2_cleanup);
1239
1240         /* If there's no DTMF override, then we can just link
1241          * the applicationmap item directly. Otherwise, we need
1242          * to create a copy with the DTMF override in place and
1243          * link that instead
1244          */
1245         if (ast_strlen_zero(fg_item->dtmf_override)) {
1246                 ao2_ref(fg_item->appmap_item, +1);
1247                 appmap_item = fg_item->appmap_item;
1248         } else {
1249                 appmap_item = applicationmap_item_alloc(fg_item->appmap_item_name,
1250                                 fg_item->appmap_item->app, fg_item->appmap_item->app_data,
1251                                 fg_item->appmap_item->moh_class, fg_item->dtmf_override,
1252                                 fg_item->appmap_item->activate_on_self);
1253         }
1254
1255         if (!appmap_item) {
1256                 return 0;
1257         }
1258
1259         ao2_link(applicationmap, appmap_item);
1260         return 0;
1261 }
1262
1263 struct ao2_container *ast_get_chan_applicationmap(struct ast_channel *chan)
1264 {
1265         RAII_VAR(struct features_config *, cfg, ao2_global_obj_ref(globals), ao2_cleanup);
1266         struct ao2_container *applicationmap;
1267         char *group_names;
1268         char *name;
1269
1270         if (!cfg) {
1271                 return NULL;
1272         }
1273
1274         if (!chan) {
1275                 if (!cfg->applicationmap || ao2_container_count(cfg->applicationmap) == 0) {
1276                         return NULL;
1277                 }
1278                 ao2_ref(cfg->applicationmap, +1);
1279                 return cfg->applicationmap;
1280         }
1281
1282         group_names = ast_strdupa(S_OR(pbx_builtin_getvar_helper(chan, "DYNAMIC_FEATURES"), ""));
1283         if (ast_strlen_zero(group_names)) {
1284                 return NULL;
1285         }
1286
1287         applicationmap = applicationmap_alloc(0);
1288         if (!applicationmap) {
1289                 return NULL;
1290         }
1291
1292         while ((name = strsep(&group_names, "#"))) {
1293                 RAII_VAR(struct featuregroup *, group, ao2_find(cfg->featuregroups, name, OBJ_KEY), ao2_cleanup);
1294
1295                 if (!group) {
1296                         RAII_VAR(struct ast_applicationmap_item *, item, ao2_find(cfg->applicationmap, name, OBJ_KEY), ao2_cleanup);
1297
1298                         if (item) {
1299                                 ao2_link(applicationmap, item);
1300                         } else {
1301                                 ast_log(LOG_WARNING, "Unknown DYNAMIC_FEATURES item '%s' on channel %s.\n",
1302                                         name, ast_channel_name(chan));
1303                         }
1304                 } else {
1305                         ao2_callback(group->items, 0, add_item, applicationmap);
1306                 }
1307         }
1308
1309         if (ao2_container_count(applicationmap) == 0) {
1310                 ao2_cleanup(applicationmap);
1311                 return NULL;
1312         }
1313
1314         return applicationmap;
1315 }
1316
1317 static int applicationmap_handler(const struct aco_option *opt,
1318                 struct ast_variable *var, void *obj)
1319 {
1320         RAII_VAR(struct ast_applicationmap_item *, item, NULL, ao2_cleanup);
1321         struct ao2_container *applicationmap = obj;
1322         AST_DECLARE_APP_ARGS(args,
1323                 AST_APP_ARG(dtmf);
1324                 AST_APP_ARG(activate_on);
1325                 AST_APP_ARG(app);
1326                 AST_APP_ARG(app_data);
1327                 AST_APP_ARG(moh_class);
1328         );
1329         char *parse = ast_strdupa(var->value);
1330         char *slash;
1331         char *paren;
1332         unsigned int activate_on_self;
1333
1334         AST_STANDARD_APP_ARGS(args, parse);
1335
1336         if (ast_strlen_zero(args.dtmf) ||
1337                         ast_strlen_zero(args.activate_on) ||
1338                         ast_strlen_zero(args.app)) {
1339                 ast_log(LOG_WARNING, "Invalid applicationmap syntax for '%s'. Missing required argument\n", var->name);
1340                 return -1;
1341         }
1342
1343         /* features.conf used to have an "activated_by" portion
1344          * in addition to activate_on. Get rid of whatever may be
1345          * there
1346          */
1347         slash = strchr(args.activate_on, '/');
1348         if (slash) {
1349                 *slash = '\0';
1350         }
1351
1352         /* Some applications do not require arguments. */
1353         if (!args.app_data) {
1354                 args.app_data = "";
1355         }
1356
1357         /* Two syntaxes allowed for applicationmap:
1358          * Old: foo = *1,self,NoOp,Boo!,default
1359          * New: foo = *1,self,NoOp(Boo!),default
1360          *
1361          * We need to handle both
1362          */
1363         paren = strchr(args.app, '(');
1364         if (paren) {
1365                 /* New syntax */
1366                 char *close_paren;
1367
1368                 args.moh_class = args.app_data;
1369                 *paren++ = '\0';
1370                 close_paren = strrchr(paren, ')');
1371                 if (close_paren) {
1372                         *close_paren = '\0';
1373                 }
1374                 args.app_data = paren;
1375
1376                 /* Re-check that the application is not empty */
1377                 if (ast_strlen_zero(args.app)) {
1378                         ast_log(LOG_WARNING, "Applicationmap item '%s' does not contain an application name.\n", var->name);
1379                         return -1;
1380                 }
1381         } else if (strchr(args.app_data, '"')) {
1382                 args.app_data = ast_strip_quoted(args.app_data, "\"", "\"");
1383         }
1384
1385         /* Allow caller and callee to be specified for backwards compatibility */
1386         if (!strcasecmp(args.activate_on, "self") || !strcasecmp(args.activate_on, "caller")) {
1387                 activate_on_self = 1;
1388         } else if (!strcasecmp(args.activate_on, "peer") || !strcasecmp(args.activate_on, "callee")) {
1389                 activate_on_self = 0;
1390         } else {
1391                 ast_log(LOG_WARNING, "Invalid 'activate_on' value %s for applicationmap item %s\n",
1392                         args.activate_on, var->name);
1393                 return -1;
1394         }
1395
1396         ast_debug(1, "Allocating applicationmap item: dtmf = %s, app = %s, app_data = %s, moh_class = %s\n",
1397                         args.dtmf, args.app, args.app_data, args.moh_class);
1398
1399         item = applicationmap_item_alloc(var->name, args.app, args.app_data,
1400                         args.moh_class, args.dtmf, activate_on_self);
1401
1402         if (!item) {
1403                 return -1;
1404         }
1405
1406         if (!ao2_link(applicationmap, item)) {
1407                 return -1;
1408         }
1409
1410         return 0;
1411 }
1412
1413 static int featuregroup_handler(const struct aco_option *opt,
1414                 struct ast_variable *var, void *obj)
1415 {
1416         RAII_VAR(struct featuregroup_item *, item, NULL, ao2_cleanup);
1417         struct featuregroup *group = obj;
1418
1419         item = ao2_alloc(sizeof(*item), featuregroup_item_destructor);
1420         if (!item || ast_string_field_init(item, 32)) {
1421                 return -1;
1422         }
1423
1424         ast_string_field_set(item, appmap_item_name, var->name);
1425         ast_string_field_set(item, dtmf_override, var->value);
1426
1427         if (!ao2_link(group->items, item)) {
1428                 return -1;
1429         }
1430
1431         /* We wait to look up the application map item in the preapply callback */
1432
1433         return 0;
1434 }
1435
1436 static int general_handler(const struct aco_option *opt,
1437                 struct ast_variable *var, void *obj)
1438 {
1439         struct features_global_config *global = obj;
1440         struct ast_features_general_config *general = global->general;
1441
1442         return general_set(general, var->name, var->value);
1443 }
1444
1445 static int xfer_handler(const struct aco_option *opt,
1446                 struct ast_variable *var, void *obj)
1447 {
1448         struct features_global_config *global = obj;
1449         struct ast_features_xfer_config *xfer = global->xfer;
1450
1451         return xfer_set(xfer, var->name, var->value);
1452 }
1453
1454 static int pickup_handler(const struct aco_option *opt,
1455                 struct ast_variable *var, void *obj)
1456 {
1457         struct features_global_config *global = obj;
1458         struct ast_features_pickup_config *pickup = global->pickup;
1459
1460         return pickup_set(pickup, var->name, var->value);
1461 }
1462
1463 static int parking_warning = 0;
1464 static int unsupported_handler(const struct aco_option *opt,
1465                 struct ast_variable *var, void *obj)
1466 {
1467         if (!parking_warning) {
1468                 ast_log(LOG_WARNING, "Parkinglots are no longer configurable in features.conf; "
1469                         "parking is now handled by res_parking.conf\n");
1470                 parking_warning = 1;
1471         }
1472         ast_log(LOG_WARNING, "The option '%s' is no longer configurable in features.conf.\n", var->name);
1473         return 0;
1474 }
1475
1476 static int featuremap_handler(const struct aco_option *opt,
1477                 struct ast_variable *var, void *obj)
1478 {
1479         struct ast_featuremap_config *featuremap = obj;
1480
1481         return featuremap_set(featuremap, var->name, var->value);
1482 }
1483
1484 static int check_featuregroup_item(void *obj, void *arg, void *data, int flags)
1485 {
1486         struct ast_applicationmap_item *appmap_item;
1487         struct featuregroup_item *fg_item = obj;
1488         int *err = arg;
1489         struct ao2_container *applicationmap = data;
1490
1491         appmap_item = ao2_find(applicationmap, fg_item->appmap_item_name, OBJ_KEY);
1492         if (!appmap_item) {
1493                 *err = 1;
1494                 return CMP_STOP;
1495         }
1496
1497         fg_item->appmap_item = appmap_item;
1498
1499         return 0;
1500 }
1501
1502 static int check_featuregroup(void *obj, void *arg, void *data, int flags)
1503 {
1504         struct featuregroup *group = obj;
1505         int *err = arg;
1506
1507         ao2_callback_data(group->items, 0, check_featuregroup_item, arg, data);
1508
1509         if (*err) {
1510                 ast_log(LOG_WARNING, "Featuregroup %s refers to non-existent applicationmap item\n",
1511                                 group->name);
1512         }
1513
1514         return *err ? CMP_STOP : 0;
1515 }
1516
1517 static int features_pre_apply_config(void);
1518
1519 CONFIG_INFO_CORE("features", cfg_info, globals, features_config_alloc,
1520         .files = ACO_FILES(&features_conf),
1521         .pre_apply_config = features_pre_apply_config,
1522 );
1523
1524 static int features_pre_apply_config(void)
1525 {
1526         struct features_config *cfg = aco_pending_config(&cfg_info);
1527         int err = 0;
1528
1529         /* Now that the entire config has been processed, we can check that the featuregroup
1530          * items refer to actual applicationmap items.
1531          */
1532
1533         ao2_callback_data(cfg->featuregroups, 0, check_featuregroup, &err, cfg->applicationmap);
1534
1535         return err;
1536 }
1537
1538 static int feature_read(struct ast_channel *chan, const char *cmd, char *data,
1539                char *buf, size_t len)
1540 {
1541         int res;
1542         RAII_VAR(struct features_config *, cfg, NULL, ao2_cleanup);
1543         SCOPED_CHANNELLOCK(lock, chan);
1544
1545         if (!strcasecmp(data, "inherit")) {
1546                 struct ast_datastore *ds = get_feature_chan_ds(chan);
1547                 unsigned int inherit = ds ? ds->inheritance : 0;
1548
1549                 snprintf(buf, len, "%s", inherit ? "yes" : "no");
1550                 return 0;
1551         }
1552
1553         cfg = get_feature_ds(chan);
1554         if (!cfg) {
1555                 return -1;
1556         }
1557
1558         res = general_get(cfg->global->general, data, buf, len) &&
1559                 xfer_get(cfg->global->xfer, data, buf, len) &&
1560                 pickup_get(cfg->global->pickup, data, buf, len);
1561
1562         if (res) {
1563                 ast_log(LOG_WARNING, "Invalid argument '%s' to FEATURE()\n", data);
1564         }
1565
1566         return res;
1567 }
1568
1569 static int feature_write(struct ast_channel *chan, const char *cmd, char *data,
1570                 const char *value)
1571 {
1572         int res;
1573         RAII_VAR(struct features_config *, cfg, NULL, ao2_cleanup);
1574         SCOPED_CHANNELLOCK(lock, chan);
1575
1576         if (!strcasecmp(data, "inherit")) {
1577                 struct ast_datastore *ds = get_feature_chan_ds(chan);
1578                 if (ds) {
1579                         ds->inheritance = ast_true(value) ? DATASTORE_INHERIT_FOREVER : 0;
1580                 }
1581                 return 0;
1582         }
1583
1584         if (!(cfg = get_feature_ds(chan))) {
1585                 return -1;
1586         }
1587
1588         res = general_set(cfg->global->general, data, value) &&
1589                 xfer_set(cfg->global->xfer, data, value) &&
1590                 pickup_set(cfg->global->pickup, data, value);
1591
1592         if (res) {
1593                 ast_log(LOG_WARNING, "Invalid argument '%s' to FEATURE()\n", data);
1594         }
1595
1596         return res;
1597 }
1598
1599 static int featuremap_read(struct ast_channel *chan, const char *cmd, char *data,
1600                char *buf, size_t len)
1601 {
1602         int res;
1603         SCOPED_CHANNELLOCK(lock, chan);
1604
1605         res = ast_get_builtin_feature(chan, data, buf, len);
1606
1607         if (res) {
1608                 ast_log(LOG_WARNING, "Invalid argument '%s' to FEATUREMAP()\n", data);
1609         }
1610
1611         return res;
1612 }
1613
1614 static int featuremap_write(struct ast_channel *chan, const char *cmd, char *data,
1615                 const char *value)
1616 {
1617         int res;
1618         RAII_VAR(struct features_config *, cfg, NULL, ao2_cleanup);
1619         SCOPED_CHANNELLOCK(lock, chan);
1620
1621         if (!(cfg = get_feature_ds(chan))) {
1622                 return -1;
1623         }
1624
1625         res = featuremap_set(cfg->featuremap, data, value);
1626         if (res) {
1627                 ast_log(LOG_WARNING, "Invalid argument '%s' to FEATUREMAP()\n", data);
1628                 return -1;
1629         }
1630
1631         return 0;
1632 }
1633
1634 static struct ast_custom_function feature_function = {
1635         .name = "FEATURE",
1636         .read = feature_read,
1637         .write = feature_write
1638 };
1639
1640 static struct ast_custom_function featuremap_function = {
1641         .name = "FEATUREMAP",
1642         .read = featuremap_read,
1643         .write = featuremap_write
1644 };
1645
1646 static int load_config(void)
1647 {
1648         if (aco_info_init(&cfg_info)) {
1649                 ast_log(LOG_ERROR, "Unable to initialize configuration info for features\n");
1650                 return -1;
1651         }
1652
1653         aco_option_register_custom(&cfg_info, "featuredigittimeout", ACO_EXACT, global_options,
1654                         __stringify(DEFAULT_FEATURE_DIGIT_TIMEOUT), general_handler, 0);
1655         aco_option_register_custom(&cfg_info, "recordingfailsound", ACO_EXACT, global_options,
1656                         DEFAULT_RECORDING_FAIL_SOUND, general_handler, 0);
1657         aco_option_register_custom(&cfg_info, "courtesytone", ACO_EXACT, global_options,
1658                         DEFAULT_COURTESY_TONE, general_handler, 0);
1659
1660         aco_option_register_custom(&cfg_info, "transferdigittimeout", ACO_EXACT, global_options,
1661                         __stringify(DEFAULT_TRANSFER_DIGIT_TIMEOUT), xfer_handler, 0)
1662         aco_option_register_custom(&cfg_info, "atxfernoanswertimeout", ACO_EXACT, global_options,
1663                         __stringify(DEFAULT_NOANSWER_TIMEOUT_ATTENDED_TRANSFER), xfer_handler, 0);
1664         aco_option_register_custom(&cfg_info, "atxferdropcall", ACO_EXACT, global_options,
1665                         __stringify(DEFAULT_ATXFER_DROP_CALL), xfer_handler, 0);
1666         aco_option_register_custom(&cfg_info, "atxferloopdelay", ACO_EXACT, global_options,
1667                         __stringify(DEFAULT_ATXFER_LOOP_DELAY), xfer_handler, 0);
1668         aco_option_register_custom(&cfg_info, "atxfercallbackretries", ACO_EXACT, global_options,
1669                         __stringify(DEFAULT_ATXFER_CALLBACK_RETRIES), xfer_handler, 0);
1670         aco_option_register_custom(&cfg_info, "xfersound", ACO_EXACT, global_options,
1671                         DEFAULT_XFERSOUND, xfer_handler, 0);
1672         aco_option_register_custom(&cfg_info, "xferfailsound", ACO_EXACT, global_options,
1673                         DEFAULT_XFERFAILSOUND, xfer_handler, 0);
1674         aco_option_register_custom(&cfg_info, "atxferabort", ACO_EXACT, global_options,
1675                         DEFAULT_ATXFER_ABORT, xfer_handler, 0);
1676         aco_option_register_custom(&cfg_info, "atxfercomplete", ACO_EXACT, global_options,
1677                         DEFAULT_ATXFER_COMPLETE, xfer_handler, 0);
1678         aco_option_register_custom(&cfg_info, "atxferthreeway", ACO_EXACT, global_options,
1679                         DEFAULT_ATXFER_THREEWAY, xfer_handler, 0);
1680         aco_option_register_custom(&cfg_info, "atxferswap", ACO_EXACT, global_options,
1681                         DEFAULT_ATXFER_SWAP, xfer_handler, 0);
1682
1683         aco_option_register_custom(&cfg_info, "pickupexten", ACO_EXACT, global_options,
1684                         DEFAULT_PICKUPEXTEN, pickup_handler, 0);
1685         aco_option_register_custom(&cfg_info, "pickupsound", ACO_EXACT, global_options,
1686                         DEFAULT_PICKUPSOUND, pickup_handler, 0);
1687         aco_option_register_custom(&cfg_info, "pickupfailsound", ACO_EXACT, global_options,
1688                         DEFAULT_PICKUPFAILSOUND, pickup_handler, 0);
1689
1690         aco_option_register_custom_nodoc(&cfg_info, "context", ACO_EXACT, global_options,
1691                         "", unsupported_handler, 0);
1692         aco_option_register_custom_nodoc(&cfg_info, "parkext", ACO_EXACT, global_options,
1693                         "", unsupported_handler, 0);
1694         aco_option_register_custom_nodoc(&cfg_info, "parkext_exclusive", ACO_EXACT, global_options,
1695                         "", unsupported_handler, 0);
1696         aco_option_register_custom_nodoc(&cfg_info, "parkinghints", ACO_EXACT, global_options,
1697                         "", unsupported_handler, 0);
1698         aco_option_register_custom_nodoc(&cfg_info, "parkedmusicclass", ACO_EXACT, global_options,
1699                         "", unsupported_handler, 0);
1700         aco_option_register_custom_nodoc(&cfg_info, "parkingtime", ACO_EXACT, global_options,
1701                         "", unsupported_handler, 0);
1702         aco_option_register_custom_nodoc(&cfg_info, "parkpos", ACO_EXACT, global_options,
1703                         "", unsupported_handler, 0);
1704         aco_option_register_custom_nodoc(&cfg_info, "findslot", ACO_EXACT, global_options,
1705                         "", unsupported_handler, 0);
1706         aco_option_register_custom_nodoc(&cfg_info, "parkedcalltransfers", ACO_EXACT, global_options,
1707                         "", unsupported_handler, 0);
1708         aco_option_register_custom_nodoc(&cfg_info, "parkedcallreparking", ACO_EXACT, global_options,
1709                         "", unsupported_handler, 0);
1710         aco_option_register_custom_nodoc(&cfg_info, "parkedcallhangup", ACO_EXACT, global_options,
1711                         "", unsupported_handler, 0);
1712         aco_option_register_custom_nodoc(&cfg_info, "parkedcallrecording", ACO_EXACT, global_options,
1713                         "", unsupported_handler, 0);
1714         aco_option_register_custom_nodoc(&cfg_info, "comebackcontext", ACO_EXACT, global_options,
1715                         "", unsupported_handler, 0);
1716         aco_option_register_custom_nodoc(&cfg_info, "comebacktoorigin", ACO_EXACT, global_options,
1717                         "", unsupported_handler, 0);
1718         aco_option_register_custom_nodoc(&cfg_info, "comebackdialtime", ACO_EXACT, global_options,
1719                         "", unsupported_handler, 0);
1720         aco_option_register_custom_nodoc(&cfg_info, "parkeddynamic", ACO_EXACT, global_options,
1721                         "", unsupported_handler, 0);
1722         aco_option_register_custom_nodoc(&cfg_info, "adsipark", ACO_EXACT, global_options,
1723                         "", unsupported_handler, 0);
1724
1725         aco_option_register_custom(&cfg_info, "blindxfer", ACO_EXACT, featuremap_options,
1726                         DEFAULT_FEATUREMAP_BLINDXFER, featuremap_handler, 0);
1727         aco_option_register_custom(&cfg_info, "disconnect", ACO_EXACT, featuremap_options,
1728                         DEFAULT_FEATUREMAP_DISCONNECT, featuremap_handler, 0);
1729         aco_option_register_custom(&cfg_info, "automon", ACO_EXACT, featuremap_options,
1730                         DEFAULT_FEATUREMAP_AUTOMON, featuremap_handler, 0);
1731         aco_option_register_custom(&cfg_info, "atxfer", ACO_EXACT, featuremap_options,
1732                         DEFAULT_FEATUREMAP_ATXFER, featuremap_handler, 0);
1733         aco_option_register_custom(&cfg_info, "parkcall", ACO_EXACT, featuremap_options,
1734                         DEFAULT_FEATUREMAP_PARKCALL, featuremap_handler, 0);
1735         aco_option_register_custom(&cfg_info, "automixmon", ACO_EXACT, featuremap_options,
1736                         DEFAULT_FEATUREMAP_AUTOMIXMON, featuremap_handler, 0);
1737
1738         aco_option_register_custom(&cfg_info, "^.*$", ACO_REGEX, applicationmap_options,
1739                         "", applicationmap_handler, 0);
1740
1741         aco_option_register_custom(&cfg_info, "^.*$", ACO_REGEX, featuregroup_options,
1742                         "", featuregroup_handler, 0);
1743
1744         aco_option_register_custom_nodoc(&cfg_info, "^.*$", ACO_REGEX, parkinglot_options,
1745                         "", unsupported_handler, 0);
1746
1747         if (aco_process_config(&cfg_info, 0) == ACO_PROCESS_ERROR) {
1748                 RAII_VAR(struct features_config *, features_cfg, __features_config_alloc(0), ao2_cleanup);
1749
1750                 if (aco_set_defaults(&global_option, "general", features_cfg->global) ||
1751                         aco_set_defaults(&featuremap_option, "featuremap", features_cfg->featuremap)) {
1752                         ast_log(LOG_ERROR, "Failed to load features.conf and failed to initialize defaults.\n");
1753                         return -1;
1754                 }
1755
1756                 ast_log(LOG_NOTICE, "Could not load features config; using defaults\n");
1757                 ao2_global_obj_replace_unref(globals, features_cfg);
1758         }
1759
1760         return 0;
1761 }
1762
1763 static int print_featuregroup(void *obj, void *arg, int flags)
1764 {
1765         struct featuregroup_item *item = obj;
1766         struct ast_cli_args *a = arg;
1767
1768         ast_cli(a->fd, "===> --> %s (%s)\n", item->appmap_item_name,
1769                         S_OR(item->dtmf_override, item->appmap_item->dtmf));
1770
1771         return 0;
1772 }
1773
1774 static int print_featuregroups(void *obj, void *arg, int flags)
1775 {
1776         struct featuregroup *group = obj;
1777         struct ast_cli_args *a = arg;
1778
1779         ast_cli(a->fd, "===> Group: %s\n", group->name);
1780
1781         ao2_callback(group->items, 0, print_featuregroup, a);
1782         return 0;
1783 }
1784
1785 #define HFS_FORMAT "%-25s %-7s %-7s\n"
1786
1787 static int print_applicationmap(void *obj, void *arg, int flags)
1788 {
1789         struct ast_applicationmap_item *item = obj;
1790         struct ast_cli_args *a = arg;
1791
1792         ast_cli(a->fd, HFS_FORMAT, item->name, "no def", item->dtmf);
1793         return 0;
1794 }
1795
1796 /*!
1797  * \brief CLI command to list configured features
1798  * \param e
1799  * \param cmd
1800  * \param a
1801  *
1802  * \retval CLI_SUCCESS on success.
1803  * \retval NULL when tab completion is used.
1804  */
1805 static char *handle_feature_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1806 {
1807         RAII_VAR(struct features_config *, cfg, NULL, ao2_cleanup);
1808
1809         switch (cmd) {
1810
1811         case CLI_INIT:
1812                 e->command = "features show";
1813                 e->usage =
1814                         "Usage: features show\n"
1815                         "       Lists configured features\n";
1816                 return NULL;
1817         case CLI_GENERATE:
1818                 return NULL;
1819         }
1820
1821         cfg = ao2_global_obj_ref(globals);
1822
1823         ast_cli(a->fd, HFS_FORMAT, "Builtin Feature", "Default", "Current");
1824         ast_cli(a->fd, HFS_FORMAT, "---------------", "-------", "-------");
1825
1826         ast_cli(a->fd, HFS_FORMAT, "Pickup", DEFAULT_PICKUPEXTEN, cfg->global->pickup->pickupexten);
1827         ast_cli(a->fd, HFS_FORMAT, "Blind Transfer", DEFAULT_FEATUREMAP_BLINDXFER, cfg->featuremap->blindxfer);
1828         ast_cli(a->fd, HFS_FORMAT, "Attended Transfer", DEFAULT_FEATUREMAP_ATXFER, cfg->featuremap->atxfer);
1829         ast_cli(a->fd, HFS_FORMAT, "One Touch Monitor", DEFAULT_FEATUREMAP_AUTOMON, cfg->featuremap->automon);
1830         ast_cli(a->fd, HFS_FORMAT, "Disconnect Call", DEFAULT_FEATUREMAP_DISCONNECT, cfg->featuremap->disconnect);
1831         ast_cli(a->fd, HFS_FORMAT, "Park Call", DEFAULT_FEATUREMAP_PARKCALL, cfg->featuremap->parkcall);
1832         ast_cli(a->fd, HFS_FORMAT, "One Touch MixMonitor", DEFAULT_FEATUREMAP_AUTOMIXMON, cfg->featuremap->automixmon);
1833
1834         ast_cli(a->fd, "\n");
1835         ast_cli(a->fd, HFS_FORMAT, "Dynamic Feature", "Default", "Current");
1836         ast_cli(a->fd, HFS_FORMAT, "---------------", "-------", "-------");
1837         if (!cfg->applicationmap || ao2_container_count(cfg->applicationmap) == 0) {
1838                 ast_cli(a->fd, "(none)\n");
1839         } else {
1840                 ao2_callback(cfg->applicationmap, 0, print_applicationmap, a);
1841         }
1842
1843         ast_cli(a->fd, "\nFeature Groups:\n");
1844         ast_cli(a->fd, "---------------\n");
1845         if (!cfg->featuregroups || ao2_container_count(cfg->featuregroups) == 0) {
1846                 ast_cli(a->fd, "(none)\n");
1847         } else {
1848                 ao2_callback(cfg->featuregroups, 0, print_featuregroups, a);
1849         }
1850
1851         ast_cli(a->fd, "\n");
1852
1853         return CLI_SUCCESS;
1854 }
1855
1856 static struct ast_cli_entry cli_features_config[] = {
1857         AST_CLI_DEFINE(handle_feature_show, "Lists configured features"),
1858 };
1859
1860 void ast_features_config_shutdown(void)
1861 {
1862         ast_custom_function_unregister(&featuremap_function);
1863         ast_custom_function_unregister(&feature_function);
1864         ast_cli_unregister_multiple(cli_features_config, ARRAY_LEN(cli_features_config));
1865         aco_info_destroy(&cfg_info);
1866         ao2_global_obj_release(globals);
1867 }
1868
1869 int ast_features_config_reload(void)
1870 {
1871         /* Rearm the parking config options have moved warning. */
1872         parking_warning = 0;
1873
1874         if (aco_process_config(&cfg_info, 1) == ACO_PROCESS_ERROR) {
1875                 return -1;
1876         }
1877         return 0;
1878 }
1879
1880 int ast_features_config_init(void)
1881 {
1882         int res;
1883
1884         res = load_config();
1885         res |= __ast_custom_function_register(&feature_function, NULL);
1886         res |= __ast_custom_function_register(&featuremap_function, NULL);
1887         res |= ast_cli_register_multiple(cli_features_config, ARRAY_LEN(cli_features_config));
1888
1889         if (res) {
1890                 ast_features_config_shutdown();
1891         }
1892
1893         return res;
1894 }