features_config: Ignore parkinglots in features.conf instead of failing to load
[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="3000">
46                                         <synopsis>Milliseconds allowed between digit presses when dialing a transfer destination</synopsis>
47                                 </configOption>
48                                 <configOption name="atxfernoanswertimeout" default="15000">
49                                         <synopsis>Milliseconds 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="10000">
66                                         <synopsis>Milliseconds 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              3000
359 #define DEFAULT_NOANSWER_TIMEOUT_ATTENDED_TRANSFER  15000
360 #define DEFAULT_ATXFER_DROP_CALL                    0
361 #define DEFAULT_ATXFER_LOOP_DELAY                   10000
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->applicationmap);
626         ao2_cleanup(cfg->featuregroups);
627 }
628
629 static void featuremap_config_destructor(void *obj)
630 {
631         struct ast_featuremap_config *cfg = obj;
632
633         ast_string_field_free_memory(cfg);
634 }
635
636 static void global_config_destructor(void *obj)
637 {
638         struct features_global_config *cfg = obj;
639
640         ao2_cleanup(cfg->general);
641         ao2_cleanup(cfg->xfer);
642         ao2_cleanup(cfg->pickup);
643 }
644
645 static void general_destructor(void *obj)
646 {
647         struct ast_features_general_config *cfg = obj;
648
649         ast_string_field_free_memory(cfg);
650 }
651
652 static void xfer_destructor(void *obj)
653 {
654         struct ast_features_xfer_config *cfg = obj;
655
656         ast_string_field_free_memory(cfg);
657 }
658
659 static void pickup_destructor(void *obj)
660 {
661         struct ast_features_pickup_config *cfg = obj;
662
663         ast_string_field_free_memory(cfg);
664 }
665
666 static struct features_global_config *global_config_alloc(void)
667 {
668         RAII_VAR(struct features_global_config *, cfg, NULL, ao2_cleanup);
669
670         cfg = ao2_alloc(sizeof(*cfg), global_config_destructor);
671         if (!cfg) {
672                 return NULL;
673         }
674
675         cfg->general = ao2_alloc(sizeof(*cfg->general), general_destructor);
676         if (!cfg->general || ast_string_field_init(cfg->general, 32)) {
677                 return NULL;
678         }
679
680         cfg->xfer = ao2_alloc(sizeof(*cfg->xfer), xfer_destructor);
681         if (!cfg->xfer || ast_string_field_init(cfg->xfer, 32)) {
682                 return NULL;
683         }
684
685         cfg->pickup = ao2_alloc(sizeof(*cfg->pickup), pickup_destructor);
686         if (!cfg->pickup || ast_string_field_init(cfg->pickup, 32)) {
687                 return NULL;
688         }
689
690         ao2_ref(cfg, +1);
691         return cfg;
692 }
693
694 static struct ao2_container *applicationmap_alloc(int replace_duplicates)
695 {
696         return ao2_container_alloc_list(AO2_ALLOC_OPT_LOCK_NOLOCK,
697                 replace_duplicates ? AO2_CONTAINER_ALLOC_OPT_DUPS_REPLACE : AO2_CONTAINER_ALLOC_OPT_DUPS_ALLOW,
698                 applicationmap_sort, NULL);
699 }
700
701 /*!
702  * \internal
703  * \brief Allocate the major configuration structure
704  *
705  * The parameter is used to determine if the applicationmap and featuregroup
706  * structures should be allocated. We only want to allocate these structures for
707  * the global features_config structure. For the datastores on channels, we don't
708  * need to allocate these structures because they are not used.
709  *
710  * \param allocate_applicationmap See previous explanation
711  * \retval NULL Failed to alloate configuration
712  * \retval non-NULL Allocated configuration
713  */
714 static struct features_config *__features_config_alloc(int allocate_applicationmap)
715 {
716         RAII_VAR(struct features_config *, cfg, NULL, ao2_cleanup);
717
718         cfg = ao2_alloc(sizeof(*cfg), features_config_destructor);
719         if (!cfg) {
720                 return NULL;
721         }
722
723         cfg->global = global_config_alloc();;
724         if (!cfg->global) {
725                 return NULL;
726         }
727
728         cfg->featuremap = ao2_alloc(sizeof(*cfg->featuremap), featuremap_config_destructor);
729         if (!cfg->featuremap || ast_string_field_init(cfg->featuremap, 32)) {
730                 return NULL;
731         }
732
733         cfg->parkinglots = ao2_alloc(sizeof(*cfg->parkinglots), NULL);
734         if (!cfg->parkinglots) {
735                 return NULL;
736         }
737
738         if (allocate_applicationmap) {
739                 cfg->applicationmap = applicationmap_alloc(1);
740                 if (!cfg->applicationmap) {
741                         return NULL;
742                 }
743
744                 cfg->featuregroups = ao2_container_alloc_options(AO2_ALLOC_OPT_LOCK_NOLOCK, 11, featuregroup_hash,
745                         featuregroup_cmp);
746                 if (!cfg->featuregroups) {
747                         return NULL;
748                 }
749         }
750
751         ao2_ref(cfg, +1);
752         return cfg;
753
754 }
755
756 static void *features_config_alloc(void)
757 {
758         return __features_config_alloc(1);
759 }
760
761 static void general_copy(struct ast_features_general_config *dest, const struct ast_features_general_config *src)
762 {
763         ast_string_fields_copy(dest, src);
764         dest->featuredigittimeout = src->featuredigittimeout;
765 }
766
767 static void xfer_copy(struct ast_features_xfer_config *dest, const struct ast_features_xfer_config *src)
768 {
769         ast_string_fields_copy(dest, src);
770         dest->transferdigittimeout = src->transferdigittimeout;
771         dest->atxfernoanswertimeout = src->atxfernoanswertimeout;
772         dest->atxferloopdelay = src->atxferloopdelay;
773         dest->atxfercallbackretries = src->atxfercallbackretries;
774         dest->atxferdropcall = src->atxferdropcall;
775 }
776
777 static void pickup_copy(struct ast_features_pickup_config *dest, const struct ast_features_pickup_config *src)
778 {
779         ast_string_fields_copy(dest, src);
780 }
781
782 static void global_copy(struct features_global_config *dest, const struct features_global_config *src)
783 {
784         general_copy(dest->general, src->general);
785         xfer_copy(dest->xfer, src->xfer);
786         pickup_copy(dest->pickup, src->pickup);
787 }
788
789 static void featuremap_copy(struct ast_featuremap_config *dest, const struct ast_featuremap_config *src)
790 {
791         ast_string_fields_copy(dest, src);
792 }
793
794 static void features_copy(struct features_config *dest, const struct features_config *src)
795 {
796         global_copy(dest->global, src->global);
797         featuremap_copy(dest->featuremap, src->featuremap);
798
799         /* applicationmap and featuregroups are purposely not copied. A channel's applicationmap
800          * is produced on the fly when ast_get_chan_applicationmap() is called
801          */
802 }
803
804 static struct features_config *features_config_dup(const struct features_config *orig)
805 {
806         struct features_config *dup;
807
808         dup = __features_config_alloc(0);
809         if (!dup) {
810                 return NULL;
811         }
812
813         features_copy(dup, orig);
814
815         return dup;
816 }
817
818 static int general_set(struct ast_features_general_config *general, const char *name,
819                 const char *value)
820 {
821         int res = 0;
822
823         if (!strcasecmp(name, "featuredigittimeout")) {
824                 res = ast_parse_arg(value, PARSE_INT32, &general->featuredigittimeout);
825         } else if (!strcasecmp(name, "courtesytone")) {
826                 ast_string_field_set(general, courtesytone, value);
827         } else if (!strcasecmp(name, "recordingfailsound")) {
828                 ast_string_field_set(general, recordingfailsound, value);
829         } else {
830                 /* Unrecognized option */
831                 res = -1;
832         }
833
834         return res;
835 }
836
837 static int general_get(struct ast_features_general_config *general, const char *field,
838                 char *buf, size_t len)
839 {
840         int res = 0;
841
842         if (!strcasecmp(field, "featuredigittimeout")) {
843                 snprintf(buf, len, "%u", general->featuredigittimeout);
844         } else if (!strcasecmp(field, "courtesytone")) {
845                 ast_copy_string(buf, general->courtesytone, len);
846         } else if (!strcasecmp(field, "recordingfailsound")) {
847                 ast_copy_string(buf, general->recordingfailsound, len);
848         } else {
849                 /* Unrecognized option */
850                 res = -1;
851         }
852
853         return res;
854 }
855
856 static int xfer_set(struct ast_features_xfer_config *xfer, const char *name,
857                 const char *value)
858 {
859         int res = 0;
860
861         if (!strcasecmp(name, "transferdigittimeout")) {
862                 res = ast_parse_arg(value, PARSE_INT32, &xfer->transferdigittimeout);
863         } else if (!strcasecmp(name, "atxfernoanswertimeout")) {
864                 res = ast_parse_arg(value, PARSE_INT32, &xfer->atxfernoanswertimeout);
865         } else if (!strcasecmp(name, "atxferloopdelay")) {
866                 res = ast_parse_arg(value, PARSE_INT32, &xfer->atxferloopdelay);
867         } else if (!strcasecmp(name, "atxfercallbackretries")) {
868                 res = ast_parse_arg(value, PARSE_INT32, &xfer->atxfercallbackretries);
869         } else if (!strcasecmp(name, "atxferdropcall")) {
870                 xfer->atxferdropcall = ast_true(value);
871         } else if (!strcasecmp(name, "xfersound")) {
872                 ast_string_field_set(xfer, xfersound, value);
873         } else if (!strcasecmp(name, "xferfailsound")) {
874                 ast_string_field_set(xfer, xferfailsound, value);
875         } else if (!strcasecmp(name, "atxferabort")) {
876                 ast_string_field_set(xfer, atxferabort, value);
877         } else if (!strcasecmp(name, "atxfercomplete")) {
878                 ast_string_field_set(xfer, atxfercomplete, value);
879         } else if (!strcasecmp(name, "atxferthreeway")) {
880                 ast_string_field_set(xfer, atxferthreeway, value);
881         } else if (!strcasecmp(name, "atxferswap")) {
882                 ast_string_field_set(xfer, atxferswap, value);
883         } else {
884                 /* Unrecognized option */
885                 res = -1;
886         }
887
888         return res;
889 }
890
891 static int xfer_get(struct ast_features_xfer_config *xfer, const char *field,
892                 char *buf, size_t len)
893 {
894         int res = 0;
895
896         if (!strcasecmp(field, "transferdigittimeout")) {
897                 snprintf(buf, len, "%u", xfer->transferdigittimeout);
898         } else if (!strcasecmp(field, "atxfernoanswertimeout")) {
899                 snprintf(buf, len, "%u", xfer->atxfernoanswertimeout);
900         } else if (!strcasecmp(field, "atxferloopdelay")) {
901                 snprintf(buf, len, "%u", xfer->atxferloopdelay);
902         } else if (!strcasecmp(field, "atxfercallbackretries")) {
903                 snprintf(buf, len, "%u", xfer->atxfercallbackretries);
904         } else if (!strcasecmp(field, "atxferdropcall")) {
905                 snprintf(buf, len, "%u", xfer->atxferdropcall);
906         } else if (!strcasecmp(field, "xfersound")) {
907                 ast_copy_string(buf, xfer->xfersound, len);
908         } else if (!strcasecmp(field, "xferfailsound")) {
909                 ast_copy_string(buf, xfer->xferfailsound, len);
910         } else if (!strcasecmp(field, "atxferabort")) {
911                 ast_copy_string(buf, xfer->atxferabort, len);
912         } else if (!strcasecmp(field, "atxfercomplete")) {
913                 ast_copy_string(buf, xfer->atxfercomplete, len);
914         } else if (!strcasecmp(field, "atxferthreeway")) {
915                 ast_copy_string(buf, xfer->atxferthreeway, len);
916         } else if (!strcasecmp(field, "atxferswap")) {
917                 ast_copy_string(buf, xfer->atxferswap, len);
918         } else {
919                 /* Unrecognized option */
920                 res = -1;
921         }
922
923         return res;
924 }
925
926 static int pickup_set(struct ast_features_pickup_config *pickup, const char *name,
927                 const char *value)
928 {
929         int res = 0;
930
931         if (!strcasecmp(name, "pickupsound")) {
932                 ast_string_field_set(pickup, pickupsound, value);
933         } else if (!strcasecmp(name, "pickupfailsound")) {
934                 ast_string_field_set(pickup, pickupfailsound, value);
935         } else if (!strcasecmp(name, "pickupexten")) {
936                 ast_string_field_set(pickup, pickupexten, value);
937         } else {
938                 /* Unrecognized option */
939                 res = -1;
940         }
941
942         return res;
943 }
944
945 static int pickup_get(struct ast_features_pickup_config *pickup, const char *field,
946                 char *buf, size_t len)
947 {
948         int res = 0;
949
950         if (!strcasecmp(field, "pickupsound")) {
951                 ast_copy_string(buf, pickup->pickupsound, len);
952         } else if (!strcasecmp(field, "pickupfailsound")) {
953                 ast_copy_string(buf, pickup->pickupfailsound, len);
954         } else if (!strcasecmp(field, "pickupexten")) {
955                 ast_copy_string(buf, pickup->pickupexten, len);
956         } else {
957                 /* Unrecognized option */
958                 res = -1;
959         }
960
961         return res;
962 }
963
964 static int featuremap_set(struct ast_featuremap_config *featuremap, const char *name,
965                 const char *value)
966 {
967         int res = 0;
968
969         if (!strcasecmp(name, "blindxfer")) {
970                 ast_string_field_set(featuremap, blindxfer, value);
971         } else if (!strcasecmp(name, "disconnect")) {
972                 ast_string_field_set(featuremap, disconnect, value);
973         } else if (!strcasecmp(name, "automon")) {
974                 ast_string_field_set(featuremap, automon, value);
975         } else if (!strcasecmp(name, "atxfer")) {
976                 ast_string_field_set(featuremap, atxfer, value);
977         } else if (!strcasecmp(name, "automixmon")) {
978                 ast_string_field_set(featuremap, automixmon, value);
979         } else if (!strcasecmp(name, "parkcall")) {
980                 ast_string_field_set(featuremap, parkcall, value);
981         } else {
982                 /* Unrecognized option */
983                 res = -1;
984         }
985
986         return res;
987 }
988
989 static int featuremap_get(struct ast_featuremap_config *featuremap, const char *field,
990                 char *buf, size_t len)
991 {
992         int res = 0;
993
994         if (!strcasecmp(field, "blindxfer")) {
995                 ast_copy_string(buf, featuremap->blindxfer, len);
996         } else if (!strcasecmp(field, "disconnect")) {
997                 ast_copy_string(buf, featuremap->disconnect, len);
998         } else if (!strcasecmp(field, "automon")) {
999                 ast_copy_string(buf, featuremap->automon, len);
1000         } else if (!strcasecmp(field, "atxfer")) {
1001                 ast_copy_string(buf, featuremap->atxfer, len);
1002         } else if (!strcasecmp(field, "automixmon")) {
1003                 ast_copy_string(buf, featuremap->automixmon, len);
1004         } else if (!strcasecmp(field, "parkcall")) {
1005                 ast_copy_string(buf, featuremap->parkcall, len);
1006         } else {
1007                 /* Unrecognized option */
1008                 res = -1;
1009         }
1010
1011         return res;
1012 }
1013
1014 static void feature_ds_destroy(void *data)
1015 {
1016         struct features_config *cfg = data;
1017         ao2_cleanup(cfg);
1018 }
1019
1020 static void *feature_ds_duplicate(void *data)
1021 {
1022         struct features_config *old_cfg = data;
1023
1024         return features_config_dup(old_cfg);
1025 }
1026
1027 static const struct ast_datastore_info feature_ds_info = {
1028         .type = "FEATURE",
1029         .destroy = feature_ds_destroy,
1030         .duplicate = feature_ds_duplicate,
1031 };
1032
1033 /*!
1034  * \internal
1035  * \brief Find or create feature datastore on a channel
1036  *
1037  * \pre chan is locked
1038  *
1039  * \return the data on the FEATURE datastore, or NULL on error
1040  */
1041 static struct features_config *get_feature_ds(struct ast_channel *chan)
1042 {
1043         RAII_VAR(struct features_config *, orig, NULL, ao2_cleanup);
1044         struct features_config *cfg;
1045         struct ast_datastore *ds;
1046
1047         if ((ds = ast_channel_datastore_find(chan, &feature_ds_info, NULL))) {
1048                 cfg = ds->data;
1049                 ao2_ref(cfg, +1);
1050                 return cfg;
1051         }
1052
1053         orig = ao2_global_obj_ref(globals);
1054         if (!orig) {
1055                 return NULL;
1056         }
1057
1058         cfg = features_config_dup(orig);
1059         if (!cfg) {
1060                 return NULL;
1061         }
1062
1063         if (!(ds = ast_datastore_alloc(&feature_ds_info, NULL))) {
1064                 ao2_cleanup(cfg);
1065                 return NULL;
1066         }
1067
1068         /* Give the datastore a reference to the config */
1069         ao2_ref(cfg, +1);
1070         ds->data = cfg;
1071
1072         ast_channel_datastore_add(chan, ds);
1073
1074         return cfg;
1075 }
1076
1077 static struct ast_datastore *get_feature_chan_ds(struct ast_channel *chan)
1078 {
1079         struct ast_datastore *ds;
1080
1081         if (!(ds = ast_channel_datastore_find(chan, &feature_ds_info, NULL))) {
1082                 /* Hasn't been created yet.  Trigger creation. */
1083                 RAII_VAR(struct features_config *, cfg, get_feature_ds(chan), ao2_cleanup);
1084                 ds = ast_channel_datastore_find(chan, &feature_ds_info, NULL);
1085         }
1086
1087         return ds;
1088 }
1089
1090 struct ast_features_general_config *ast_get_chan_features_general_config(struct ast_channel *chan)
1091 {
1092         RAII_VAR(struct features_config *, cfg, NULL, ao2_cleanup);
1093
1094         if (chan) {
1095                 cfg = get_feature_ds(chan);
1096         } else {
1097                 cfg = ao2_global_obj_ref(globals);
1098         }
1099
1100         if (!cfg) {
1101                 return NULL;
1102         }
1103
1104         ast_assert(cfg->global && cfg->global->general);
1105
1106         ao2_ref(cfg->global->general, +1);
1107         return cfg->global->general;
1108 }
1109
1110 struct ast_features_xfer_config *ast_get_chan_features_xfer_config(struct ast_channel *chan)
1111 {
1112         RAII_VAR(struct features_config *, cfg, NULL, ao2_cleanup);
1113
1114         if (chan) {
1115                 cfg = get_feature_ds(chan);
1116         } else {
1117                 cfg = ao2_global_obj_ref(globals);
1118         }
1119
1120         if (!cfg) {
1121                 return NULL;
1122         }
1123
1124         ast_assert(cfg->global && cfg->global->xfer);
1125
1126         ao2_ref(cfg->global->xfer, +1);
1127         return cfg->global->xfer;
1128 }
1129
1130 struct ast_features_pickup_config *ast_get_chan_features_pickup_config(struct ast_channel *chan)
1131 {
1132         RAII_VAR(struct features_config *, cfg, NULL, ao2_cleanup);
1133
1134         if (chan) {
1135                 cfg = get_feature_ds(chan);
1136         } else {
1137                 cfg = ao2_global_obj_ref(globals);
1138         }
1139
1140         if (!cfg) {
1141                 return NULL;
1142         }
1143
1144         ast_assert(cfg->global && cfg->global->pickup);
1145
1146         ao2_ref(cfg->global->pickup, +1);
1147         return cfg->global->pickup;
1148 }
1149
1150 struct ast_featuremap_config *ast_get_chan_featuremap_config(struct ast_channel *chan)
1151 {
1152         RAII_VAR(struct features_config *, cfg, NULL, ao2_cleanup);
1153
1154         if (chan) {
1155                 cfg = get_feature_ds(chan);
1156         } else {
1157                 cfg = ao2_global_obj_ref(globals);
1158         }
1159
1160         if (!cfg) {
1161                 return NULL;
1162         }
1163
1164         ast_assert(cfg->featuremap != NULL);
1165
1166         ao2_ref(cfg->featuremap, +1);
1167         return cfg->featuremap;
1168 }
1169
1170 int ast_get_builtin_feature(struct ast_channel *chan, const char *feature, char *buf, size_t len)
1171 {
1172         RAII_VAR(struct features_config *, cfg, NULL, ao2_cleanup);
1173
1174         if (chan) {
1175                 cfg = get_feature_ds(chan);
1176         } else {
1177                 cfg = ao2_global_obj_ref(globals);
1178         }
1179
1180         if (!cfg) {
1181                 return -1;
1182         }
1183
1184         return featuremap_get(cfg->featuremap, feature, buf, len);
1185 }
1186
1187 int ast_get_feature(struct ast_channel *chan, const char *feature, char *buf, size_t len)
1188 {
1189         RAII_VAR(struct ao2_container *, applicationmap, NULL, ao2_cleanup);
1190         RAII_VAR(struct ast_applicationmap_item *, item, NULL, ao2_cleanup);
1191
1192         if (!ast_get_builtin_feature(chan, feature, buf, len)) {
1193                 return 0;
1194         }
1195
1196         /* Dang, must be in the application map */
1197         applicationmap = ast_get_chan_applicationmap(chan);
1198         if (!applicationmap) {
1199                 return -1;
1200         }
1201
1202         item = ao2_find(applicationmap, feature, OBJ_KEY);
1203         if (!item) {
1204                 return -1;
1205         }
1206
1207         ast_copy_string(buf, item->dtmf, len);
1208         return 0;
1209 }
1210
1211 static struct ast_applicationmap_item *applicationmap_item_alloc(const char *name,
1212                 const char *app, const char *app_data, const char *moh_class, const char *dtmf,
1213                 unsigned int activate_on_self)
1214 {
1215         struct ast_applicationmap_item *item;
1216
1217         item = ao2_alloc(sizeof(*item), ast_applicationmap_item_destructor);
1218
1219         if (!item || ast_string_field_init(item, 64)) {
1220                 return NULL;
1221         }
1222
1223         ast_string_field_set(item, name, name);
1224         ast_string_field_set(item, app, app);
1225         ast_string_field_set(item, app_data, app_data);
1226         ast_string_field_set(item, moh_class, moh_class);
1227         ast_copy_string(item->dtmf, dtmf, sizeof(item->dtmf));
1228         item->activate_on_self = activate_on_self;
1229
1230         return item;
1231 }
1232
1233 static int add_item(void *obj, void *arg, int flags)
1234 {
1235         struct featuregroup_item *fg_item = obj;
1236         struct ao2_container *applicationmap = arg;
1237         RAII_VAR(struct ast_applicationmap_item *, appmap_item, NULL, ao2_cleanup);
1238
1239         /* If there's no DTMF override, then we can just link
1240          * the applicationmap item directly. Otherwise, we need
1241          * to create a copy with the DTMF override in place and
1242          * link that instead
1243          */
1244         if (ast_strlen_zero(fg_item->dtmf_override)) {
1245                 ao2_ref(fg_item->appmap_item, +1);
1246                 appmap_item = fg_item->appmap_item;
1247         } else {
1248                 appmap_item = applicationmap_item_alloc(fg_item->appmap_item_name,
1249                                 fg_item->appmap_item->app, fg_item->appmap_item->app_data,
1250                                 fg_item->appmap_item->moh_class, fg_item->dtmf_override,
1251                                 fg_item->appmap_item->activate_on_self);
1252         }
1253
1254         if (!appmap_item) {
1255                 return 0;
1256         }
1257
1258         ao2_link(applicationmap, appmap_item);
1259         return 0;
1260 }
1261
1262 struct ao2_container *ast_get_chan_applicationmap(struct ast_channel *chan)
1263 {
1264         RAII_VAR(struct features_config *, cfg, ao2_global_obj_ref(globals), ao2_cleanup);
1265         struct ao2_container *applicationmap;
1266         char *group_names;
1267         char *name;
1268
1269         if (!cfg) {
1270                 return NULL;
1271         }
1272
1273         if (!chan) {
1274                 if (!cfg->applicationmap || ao2_container_count(cfg->applicationmap) == 0) {
1275                         return NULL;
1276                 }
1277                 ao2_ref(cfg->applicationmap, +1);
1278                 return cfg->applicationmap;
1279         }
1280
1281         group_names = ast_strdupa(S_OR(pbx_builtin_getvar_helper(chan, "DYNAMIC_FEATURES"), ""));
1282         if (ast_strlen_zero(group_names)) {
1283                 return NULL;
1284         }
1285
1286         applicationmap = applicationmap_alloc(0);
1287         if (!applicationmap) {
1288                 return NULL;
1289         }
1290
1291         while ((name = strsep(&group_names, "#"))) {
1292                 RAII_VAR(struct featuregroup *, group, ao2_find(cfg->featuregroups, name, OBJ_KEY), ao2_cleanup);
1293
1294                 if (!group) {
1295                         RAII_VAR(struct ast_applicationmap_item *, item, ao2_find(cfg->applicationmap, name, OBJ_KEY), ao2_cleanup);
1296
1297                         if (item) {
1298                                 ao2_link(applicationmap, item);
1299                         } else {
1300                                 ast_log(LOG_WARNING, "Unknown DYNAMIC_FEATURES item '%s' on channel %s.\n",
1301                                         name, ast_channel_name(chan));
1302                         }
1303                 } else {
1304                         ao2_callback(group->items, 0, add_item, applicationmap);
1305                 }
1306         }
1307
1308         if (ao2_container_count(applicationmap) == 0) {
1309                 ao2_cleanup(applicationmap);
1310                 return NULL;
1311         }
1312
1313         return applicationmap;
1314 }
1315
1316 static int applicationmap_handler(const struct aco_option *opt,
1317                 struct ast_variable *var, void *obj)
1318 {
1319         RAII_VAR(struct ast_applicationmap_item *, item, NULL, ao2_cleanup);
1320         struct ao2_container *applicationmap = obj;
1321         AST_DECLARE_APP_ARGS(args,
1322                 AST_APP_ARG(dtmf);
1323                 AST_APP_ARG(activate_on);
1324                 AST_APP_ARG(app);
1325                 AST_APP_ARG(app_data);
1326                 AST_APP_ARG(moh_class);
1327         );
1328         char *parse = ast_strdupa(var->value);
1329         char *slash;
1330         char *paren;
1331         unsigned int activate_on_self;
1332
1333         AST_STANDARD_APP_ARGS(args, parse);
1334
1335         if (ast_strlen_zero(args.dtmf) ||
1336                         ast_strlen_zero(args.activate_on) ||
1337                         ast_strlen_zero(args.app)) {
1338                 ast_log(LOG_WARNING, "Invalid applicationmap syntax for '%s'. Missing required argument\n", var->name);
1339                 return -1;
1340         }
1341
1342         /* features.conf used to have an "activated_by" portion
1343          * in addition to activate_on. Get rid of whatever may be
1344          * there
1345          */
1346         slash = strchr(args.activate_on, '/');
1347         if (slash) {
1348                 *slash = '\0';
1349         }
1350
1351         /* Two syntaxes allowed for applicationmap:
1352          * Old: foo = *1,self,NoOp,Boo!,default
1353          * New: foo = *1,self,NoOp(Boo!),default
1354          *
1355          * We need to handle both
1356          */
1357         paren = strchr(args.app, '(');
1358         if (paren) {
1359                 /* New syntax */
1360                 char *close_paren;
1361
1362                 args.moh_class = args.app_data;
1363                 *paren++ = '\0';
1364                 close_paren = strrchr(paren, ')');
1365                 if (close_paren) {
1366                         *close_paren = '\0';
1367                 }
1368                 args.app_data = paren;
1369
1370                 /* Re-check that the application is not empty */
1371                 if (ast_strlen_zero(args.app)) {
1372                         ast_log(LOG_WARNING, "Applicationmap item '%s' does not contain an application name.\n", var->name);
1373                         return -1;
1374                 }
1375         } else if (strchr(args.app_data, '"')) {
1376                 args.app_data = ast_strip_quoted(args.app_data, "\"", "\"");
1377         }
1378
1379         /* Allow caller and callee to be specified for backwards compatibility */
1380         if (!strcasecmp(args.activate_on, "self") || !strcasecmp(args.activate_on, "caller")) {
1381                 activate_on_self = 1;
1382         } else if (!strcasecmp(args.activate_on, "peer") || !strcasecmp(args.activate_on, "callee")) {
1383                 activate_on_self = 0;
1384         } else {
1385                 ast_log(LOG_WARNING, "Invalid 'activate_on' value %s for applicationmap item %s\n",
1386                         args.activate_on, var->name);
1387                 return -1;
1388         }
1389
1390         ast_debug(1, "Allocating applicationmap item: dtmf = %s, app = %s, app_data = %s, moh_class = %s\n",
1391                         args.dtmf, args.app, args.app_data, args.moh_class);
1392
1393         item = applicationmap_item_alloc(var->name, args.app, args.app_data,
1394                         args.moh_class, args.dtmf, activate_on_self);
1395
1396         if (!item) {
1397                 return -1;
1398         }
1399
1400         if (!ao2_link(applicationmap, item)) {
1401                 return -1;
1402         }
1403
1404         return 0;
1405 }
1406
1407 static int featuregroup_handler(const struct aco_option *opt,
1408                 struct ast_variable *var, void *obj)
1409 {
1410         RAII_VAR(struct featuregroup_item *, item, NULL, ao2_cleanup);
1411         struct featuregroup *group = obj;
1412
1413         item = ao2_alloc(sizeof(*item), featuregroup_item_destructor);
1414         if (!item || ast_string_field_init(item, 32)) {
1415                 return -1;
1416         }
1417
1418         ast_string_field_set(item, appmap_item_name, var->name);
1419         ast_string_field_set(item, dtmf_override, var->value);
1420
1421         if (!ao2_link(group->items, item)) {
1422                 return -1;
1423         }
1424
1425         /* We wait to look up the application map item in the preapply callback */
1426
1427         return 0;
1428 }
1429
1430 static int general_handler(const struct aco_option *opt,
1431                 struct ast_variable *var, void *obj)
1432 {
1433         struct features_global_config *global = obj;
1434         struct ast_features_general_config *general = global->general;
1435
1436         return general_set(general, var->name, var->value);
1437 }
1438
1439 static int xfer_handler(const struct aco_option *opt,
1440                 struct ast_variable *var, void *obj)
1441 {
1442         struct features_global_config *global = obj;
1443         struct ast_features_xfer_config *xfer = global->xfer;
1444
1445         return xfer_set(xfer, var->name, var->value);
1446 }
1447
1448 static int pickup_handler(const struct aco_option *opt,
1449                 struct ast_variable *var, void *obj)
1450 {
1451         struct features_global_config *global = obj;
1452         struct ast_features_pickup_config *pickup = global->pickup;
1453
1454         return pickup_set(pickup, var->name, var->value);
1455 }
1456
1457 static int parking_warning = 0;
1458 static int unsupported_handler(const struct aco_option *opt,
1459                 struct ast_variable *var, void *obj)
1460 {
1461         if (!parking_warning) {
1462                 ast_log(LOG_WARNING, "Parkinglots are no longer configurable in features.conf; "
1463                         "parking is now handled by res_parking.conf\n");
1464                 parking_warning = 1;
1465         }
1466         ast_log(LOG_WARNING, "The option '%s' is no longer configurable in features.conf.\n", var->name);
1467         return 0;
1468 }
1469
1470 static int featuremap_handler(const struct aco_option *opt,
1471                 struct ast_variable *var, void *obj)
1472 {
1473         struct ast_featuremap_config *featuremap = obj;
1474
1475         return featuremap_set(featuremap, var->name, var->value);
1476 }
1477
1478 static int check_featuregroup_item(void *obj, void *arg, void *data, int flags)
1479 {
1480         struct ast_applicationmap_item *appmap_item;
1481         struct featuregroup_item *fg_item = obj;
1482         int *err = arg;
1483         struct ao2_container *applicationmap = data;
1484
1485         appmap_item = ao2_find(applicationmap, fg_item->appmap_item_name, OBJ_KEY);
1486         if (!appmap_item) {
1487                 *err = 1;
1488                 return CMP_STOP;
1489         }
1490
1491         fg_item->appmap_item = appmap_item;
1492
1493         return 0;
1494 }
1495
1496 static int check_featuregroup(void *obj, void *arg, void *data, int flags)
1497 {
1498         struct featuregroup *group = obj;
1499         int *err = arg;
1500
1501         ao2_callback_data(group->items, 0, check_featuregroup_item, arg, data);
1502
1503         if (*err) {
1504                 ast_log(LOG_WARNING, "Featuregroup %s refers to non-existent applicationmap item\n",
1505                                 group->name);
1506         }
1507
1508         return *err ? CMP_STOP : 0;
1509 }
1510
1511 static int features_pre_apply_config(void);
1512
1513 CONFIG_INFO_CORE("features", cfg_info, globals, features_config_alloc,
1514         .files = ACO_FILES(&features_conf),
1515         .pre_apply_config = features_pre_apply_config,
1516 );
1517
1518 static int features_pre_apply_config(void)
1519 {
1520         struct features_config *cfg = aco_pending_config(&cfg_info);
1521         int err = 0;
1522
1523         /* Now that the entire config has been processed, we can check that the featuregroup
1524          * items refer to actual applicationmap items.
1525          */
1526
1527         ao2_callback_data(cfg->featuregroups, 0, check_featuregroup, &err, cfg->applicationmap);
1528
1529         return err;
1530 }
1531
1532 static int feature_read(struct ast_channel *chan, const char *cmd, char *data,
1533                char *buf, size_t len)
1534 {
1535         int res;
1536         RAII_VAR(struct features_config *, cfg, NULL, ao2_cleanup);
1537         SCOPED_CHANNELLOCK(lock, chan);
1538
1539         if (!strcasecmp(data, "inherit")) {
1540                 struct ast_datastore *ds = get_feature_chan_ds(chan);
1541                 unsigned int inherit = ds ? ds->inheritance : 0;
1542
1543                 snprintf(buf, len, "%s", inherit ? "yes" : "no");
1544                 return 0;
1545         }
1546
1547         cfg = get_feature_ds(chan);
1548         if (!cfg) {
1549                 return -1;
1550         }
1551
1552         res = general_get(cfg->global->general, data, buf, len) &&
1553                 xfer_get(cfg->global->xfer, data, buf, len) &&
1554                 pickup_get(cfg->global->pickup, data, buf, len);
1555
1556         if (res) {
1557                 ast_log(LOG_WARNING, "Invalid argument '%s' to FEATURE()\n", data);
1558         }
1559
1560         return res;
1561 }
1562
1563 static int feature_write(struct ast_channel *chan, const char *cmd, char *data,
1564                 const char *value)
1565 {
1566         int res;
1567         RAII_VAR(struct features_config *, cfg, NULL, ao2_cleanup);
1568         SCOPED_CHANNELLOCK(lock, chan);
1569
1570         if (!strcasecmp(data, "inherit")) {
1571                 struct ast_datastore *ds = get_feature_chan_ds(chan);
1572                 if (ds) {
1573                         ds->inheritance = ast_true(value) ? DATASTORE_INHERIT_FOREVER : 0;
1574                 }
1575                 return 0;
1576         }
1577
1578         if (!(cfg = get_feature_ds(chan))) {
1579                 return -1;
1580         }
1581
1582         res = general_set(cfg->global->general, data, value) &&
1583                 xfer_set(cfg->global->xfer, data, value) &&
1584                 pickup_set(cfg->global->pickup, data, value);
1585
1586         if (res) {
1587                 ast_log(LOG_WARNING, "Invalid argument '%s' to FEATURE()\n", data);
1588         }
1589
1590         return res;
1591 }
1592
1593 static int featuremap_read(struct ast_channel *chan, const char *cmd, char *data,
1594                char *buf, size_t len)
1595 {
1596         int res;
1597         SCOPED_CHANNELLOCK(lock, chan);
1598
1599         res = ast_get_builtin_feature(chan, data, buf, len);
1600
1601         if (res) {
1602                 ast_log(LOG_WARNING, "Invalid argument '%s' to FEATUREMAP()\n", data);
1603         }
1604
1605         return res;
1606 }
1607
1608 static int featuremap_write(struct ast_channel *chan, const char *cmd, char *data,
1609                 const char *value)
1610 {
1611         int res;
1612         RAII_VAR(struct features_config *, cfg, NULL, ao2_cleanup);
1613         SCOPED_CHANNELLOCK(lock, chan);
1614
1615         if (!(cfg = get_feature_ds(chan))) {
1616                 return -1;
1617         }
1618
1619         res = featuremap_set(cfg->featuremap, data, value);
1620         if (res) {
1621                 ast_log(LOG_WARNING, "Invalid argument '%s' to FEATUREMAP()\n", data);
1622                 return -1;
1623         }
1624
1625         return 0;
1626 }
1627
1628 static struct ast_custom_function feature_function = {
1629         .name = "FEATURE",
1630         .read = feature_read,
1631         .write = feature_write
1632 };
1633
1634 static struct ast_custom_function featuremap_function = {
1635         .name = "FEATUREMAP",
1636         .read = featuremap_read,
1637         .write = featuremap_write
1638 };
1639
1640 static int load_config(void)
1641 {
1642         if (aco_info_init(&cfg_info)) {
1643                 ast_log(LOG_ERROR, "Unable to initialize configuration info for features\n");
1644                 return -1;
1645         }
1646
1647         aco_option_register_custom(&cfg_info, "featuredigittimeout", ACO_EXACT, global_options,
1648                         __stringify(DEFAULT_FEATURE_DIGIT_TIMEOUT), general_handler, 0);
1649         aco_option_register_custom(&cfg_info, "recordingfailsound", ACO_EXACT, global_options,
1650                         DEFAULT_RECORDING_FAIL_SOUND, general_handler, 0);
1651         aco_option_register_custom(&cfg_info, "courtesytone", ACO_EXACT, global_options,
1652                         DEFAULT_COURTESY_TONE, general_handler, 0);
1653
1654         aco_option_register_custom(&cfg_info, "transferdigittimeout", ACO_EXACT, global_options,
1655                         __stringify(DEFAULT_TRANSFER_DIGIT_TIMEOUT), xfer_handler, 0)
1656         aco_option_register_custom(&cfg_info, "atxfernoanswertimeout", ACO_EXACT, global_options,
1657                         __stringify(DEFAULT_NOANSWER_TIMEOUT_ATTENDED_TRANSFER), xfer_handler, 0);
1658         aco_option_register_custom(&cfg_info, "atxferdropcall", ACO_EXACT, global_options,
1659                         __stringify(DEFAULT_ATXFER_DROP_CALL), xfer_handler, 0);
1660         aco_option_register_custom(&cfg_info, "atxferloopdelay", ACO_EXACT, global_options,
1661                         __stringify(DEFAULT_ATXFER_LOOP_DELAY), xfer_handler, 0);
1662         aco_option_register_custom(&cfg_info, "atxfercallbackretries", ACO_EXACT, global_options,
1663                         __stringify(DEFAULT_ATXFER_CALLBACK_RETRIES), xfer_handler, 0);
1664         aco_option_register_custom(&cfg_info, "xfersound", ACO_EXACT, global_options,
1665                         DEFAULT_XFERSOUND, xfer_handler, 0);
1666         aco_option_register_custom(&cfg_info, "xferfailsound", ACO_EXACT, global_options,
1667                         DEFAULT_XFERFAILSOUND, xfer_handler, 0);
1668         aco_option_register_custom(&cfg_info, "atxferabort", ACO_EXACT, global_options,
1669                         DEFAULT_ATXFER_ABORT, xfer_handler, 0);
1670         aco_option_register_custom(&cfg_info, "atxfercomplete", ACO_EXACT, global_options,
1671                         DEFAULT_ATXFER_COMPLETE, xfer_handler, 0);
1672         aco_option_register_custom(&cfg_info, "atxferthreeway", ACO_EXACT, global_options,
1673                         DEFAULT_ATXFER_THREEWAY, xfer_handler, 0);
1674         aco_option_register_custom(&cfg_info, "atxferswap", ACO_EXACT, global_options,
1675                         DEFAULT_ATXFER_SWAP, xfer_handler, 0);
1676
1677         aco_option_register_custom(&cfg_info, "pickupexten", ACO_EXACT, global_options,
1678                         DEFAULT_PICKUPEXTEN, pickup_handler, 0);
1679         aco_option_register_custom(&cfg_info, "pickupsound", ACO_EXACT, global_options,
1680                         DEFAULT_PICKUPSOUND, pickup_handler, 0);
1681         aco_option_register_custom(&cfg_info, "pickupfailsound", ACO_EXACT, global_options,
1682                         DEFAULT_PICKUPFAILSOUND, pickup_handler, 0);
1683
1684         aco_option_register_custom_nodoc(&cfg_info, "context", ACO_EXACT, global_options,
1685                         "", unsupported_handler, 0);
1686         aco_option_register_custom_nodoc(&cfg_info, "parkext", ACO_EXACT, global_options,
1687                         "", unsupported_handler, 0);
1688         aco_option_register_custom_nodoc(&cfg_info, "parkext_exclusive", ACO_EXACT, global_options,
1689                         "", unsupported_handler, 0);
1690         aco_option_register_custom_nodoc(&cfg_info, "parkinghints", ACO_EXACT, global_options,
1691                         "", unsupported_handler, 0);
1692         aco_option_register_custom_nodoc(&cfg_info, "parkedmusicclass", ACO_EXACT, global_options,
1693                         "", unsupported_handler, 0);
1694         aco_option_register_custom_nodoc(&cfg_info, "parkingtime", ACO_EXACT, global_options,
1695                         "", unsupported_handler, 0);
1696         aco_option_register_custom_nodoc(&cfg_info, "parkpos", ACO_EXACT, global_options,
1697                         "", unsupported_handler, 0);
1698         aco_option_register_custom_nodoc(&cfg_info, "findslot", ACO_EXACT, global_options,
1699                         "", unsupported_handler, 0);
1700         aco_option_register_custom_nodoc(&cfg_info, "parkedcalltransfers", ACO_EXACT, global_options,
1701                         "", unsupported_handler, 0);
1702         aco_option_register_custom_nodoc(&cfg_info, "parkedcallreparking", ACO_EXACT, global_options,
1703                         "", unsupported_handler, 0);
1704         aco_option_register_custom_nodoc(&cfg_info, "parkedcallhangup", ACO_EXACT, global_options,
1705                         "", unsupported_handler, 0);
1706         aco_option_register_custom_nodoc(&cfg_info, "parkedcallrecording", ACO_EXACT, global_options,
1707                         "", unsupported_handler, 0);
1708         aco_option_register_custom_nodoc(&cfg_info, "comebackcontext", ACO_EXACT, global_options,
1709                         "", unsupported_handler, 0);
1710         aco_option_register_custom_nodoc(&cfg_info, "comebacktoorigin", ACO_EXACT, global_options,
1711                         "", unsupported_handler, 0);
1712         aco_option_register_custom_nodoc(&cfg_info, "comebackdialtime", ACO_EXACT, global_options,
1713                         "", unsupported_handler, 0);
1714         aco_option_register_custom_nodoc(&cfg_info, "parkeddynamic", ACO_EXACT, global_options,
1715                         "", unsupported_handler, 0);
1716         aco_option_register_custom_nodoc(&cfg_info, "adsipark", ACO_EXACT, global_options,
1717                         "", unsupported_handler, 0);
1718
1719         aco_option_register_custom(&cfg_info, "blindxfer", ACO_EXACT, featuremap_options,
1720                         DEFAULT_FEATUREMAP_BLINDXFER, featuremap_handler, 0);
1721         aco_option_register_custom(&cfg_info, "disconnect", ACO_EXACT, featuremap_options,
1722                         DEFAULT_FEATUREMAP_DISCONNECT, featuremap_handler, 0);
1723         aco_option_register_custom(&cfg_info, "automon", ACO_EXACT, featuremap_options,
1724                         DEFAULT_FEATUREMAP_AUTOMON, featuremap_handler, 0);
1725         aco_option_register_custom(&cfg_info, "atxfer", ACO_EXACT, featuremap_options,
1726                         DEFAULT_FEATUREMAP_ATXFER, featuremap_handler, 0);
1727         aco_option_register_custom(&cfg_info, "parkcall", ACO_EXACT, featuremap_options,
1728                         DEFAULT_FEATUREMAP_PARKCALL, featuremap_handler, 0);
1729         aco_option_register_custom(&cfg_info, "automixmon", ACO_EXACT, featuremap_options,
1730                         DEFAULT_FEATUREMAP_AUTOMIXMON, featuremap_handler, 0);
1731
1732         aco_option_register_custom(&cfg_info, "^.*$", ACO_REGEX, applicationmap_options,
1733                         "", applicationmap_handler, 0);
1734
1735         aco_option_register_custom(&cfg_info, "^.*$", ACO_REGEX, featuregroup_options,
1736                         "", featuregroup_handler, 0);
1737
1738         aco_option_register_custom_nodoc(&cfg_info, "^.*$", ACO_REGEX, parkinglot_options,
1739                         "", unsupported_handler, 0);
1740
1741         if (aco_process_config(&cfg_info, 0) == ACO_PROCESS_ERROR) {
1742                 RAII_VAR(struct features_config *, features_cfg, __features_config_alloc(0), ao2_cleanup);
1743
1744                 if (aco_set_defaults(&global_option, "general", features_cfg->global) ||
1745                         aco_set_defaults(&featuremap_option, "featuremap", features_cfg->featuremap)) {
1746                         ast_log(LOG_ERROR, "Failed to load features.conf and failed to initialize defaults.\n");
1747                         return -1;
1748                 }
1749
1750                 ast_log(LOG_NOTICE, "Could not load features config; using defaults\n");
1751                 ao2_global_obj_replace(globals, features_cfg);
1752         }
1753
1754         return 0;
1755 }
1756
1757 static int print_featuregroup(void *obj, void *arg, int flags)
1758 {
1759         struct featuregroup_item *item = obj;
1760         struct ast_cli_args *a = arg;
1761
1762         ast_cli(a->fd, "===> --> %s (%s)\n", item->appmap_item_name,
1763                         S_OR(item->dtmf_override, item->appmap_item->dtmf));
1764
1765         return 0;
1766 }
1767
1768 static int print_featuregroups(void *obj, void *arg, int flags)
1769 {
1770         struct featuregroup *group = obj;
1771         struct ast_cli_args *a = arg;
1772
1773         ast_cli(a->fd, "===> Group: %s\n", group->name);
1774
1775         ao2_callback(group->items, 0, print_featuregroup, a);
1776         return 0;
1777 }
1778
1779 #define HFS_FORMAT "%-25s %-7s %-7s\n"
1780
1781 static int print_applicationmap(void *obj, void *arg, int flags)
1782 {
1783         struct ast_applicationmap_item *item = obj;
1784         struct ast_cli_args *a = arg;
1785
1786         ast_cli(a->fd, HFS_FORMAT, item->name, "no def", item->dtmf);
1787         return 0;
1788 }
1789
1790 /*!
1791  * \brief CLI command to list configured features
1792  * \param e
1793  * \param cmd
1794  * \param a
1795  *
1796  * \retval CLI_SUCCESS on success.
1797  * \retval NULL when tab completion is used.
1798  */
1799 static char *handle_feature_show(struct ast_cli_entry *e, int cmd, struct ast_cli_args *a)
1800 {
1801         RAII_VAR(struct features_config *, cfg, NULL, ao2_cleanup);
1802
1803         switch (cmd) {
1804
1805         case CLI_INIT:
1806                 e->command = "features show";
1807                 e->usage =
1808                         "Usage: features show\n"
1809                         "       Lists configured features\n";
1810                 return NULL;
1811         case CLI_GENERATE:
1812                 return NULL;
1813         }
1814
1815         cfg = ao2_global_obj_ref(globals);
1816
1817         ast_cli(a->fd, HFS_FORMAT, "Builtin Feature", "Default", "Current");
1818         ast_cli(a->fd, HFS_FORMAT, "---------------", "-------", "-------");
1819
1820         ast_cli(a->fd, HFS_FORMAT, "Pickup", DEFAULT_PICKUPEXTEN, cfg->global->pickup->pickupexten);
1821         ast_cli(a->fd, HFS_FORMAT, "Blind Transfer", DEFAULT_FEATUREMAP_BLINDXFER, cfg->featuremap->blindxfer);
1822         ast_cli(a->fd, HFS_FORMAT, "Attended Transfer", DEFAULT_FEATUREMAP_ATXFER, cfg->featuremap->atxfer);
1823         ast_cli(a->fd, HFS_FORMAT, "One Touch Monitor", DEFAULT_FEATUREMAP_AUTOMON, cfg->featuremap->automon);
1824         ast_cli(a->fd, HFS_FORMAT, "Disconnect Call", DEFAULT_FEATUREMAP_DISCONNECT, cfg->featuremap->disconnect);
1825         ast_cli(a->fd, HFS_FORMAT, "Park Call", DEFAULT_FEATUREMAP_PARKCALL, cfg->featuremap->parkcall);
1826         ast_cli(a->fd, HFS_FORMAT, "One Touch MixMonitor", DEFAULT_FEATUREMAP_AUTOMIXMON, cfg->featuremap->automixmon);
1827
1828         ast_cli(a->fd, "\n");
1829         ast_cli(a->fd, HFS_FORMAT, "Dynamic Feature", "Default", "Current");
1830         ast_cli(a->fd, HFS_FORMAT, "---------------", "-------", "-------");
1831         if (!cfg->applicationmap || ao2_container_count(cfg->applicationmap) == 0) {
1832                 ast_cli(a->fd, "(none)\n");
1833         } else {
1834                 ao2_callback(cfg->applicationmap, 0, print_applicationmap, a);
1835         }
1836
1837         ast_cli(a->fd, "\nFeature Groups:\n");
1838         ast_cli(a->fd, "---------------\n");
1839         if (!cfg->featuregroups || ao2_container_count(cfg->featuregroups) == 0) {
1840                 ast_cli(a->fd, "(none)\n");
1841         } else {
1842                 ao2_callback(cfg->featuregroups, 0, print_featuregroups, a);
1843         }
1844
1845         ast_cli(a->fd, "\n");
1846
1847         return CLI_SUCCESS;
1848 }
1849
1850 static struct ast_cli_entry cli_features_config[] = {
1851         AST_CLI_DEFINE(handle_feature_show, "Lists configured features"),
1852 };
1853
1854 void ast_features_config_shutdown(void)
1855 {
1856         ast_custom_function_unregister(&featuremap_function);
1857         ast_custom_function_unregister(&feature_function);
1858         ast_cli_unregister_multiple(cli_features_config, ARRAY_LEN(cli_features_config));
1859         aco_info_destroy(&cfg_info);
1860         ao2_global_obj_release(globals);
1861 }
1862
1863 int ast_features_config_reload(void)
1864 {
1865         if (aco_process_config(&cfg_info, 1) == ACO_PROCESS_ERROR) {
1866                 return -1;
1867         }
1868         return 0;
1869 }
1870
1871 int ast_features_config_init(void)
1872 {
1873         int res;
1874
1875         res = load_config();
1876         res |= __ast_custom_function_register(&feature_function, NULL);
1877         res |= __ast_custom_function_register(&featuremap_function, NULL);
1878         res |= ast_cli_register_multiple(cli_features_config, ARRAY_LEN(cli_features_config));
1879
1880         if (res) {
1881                 ast_features_config_shutdown();
1882         }
1883
1884         return res;
1885 }