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