channel: Clear channel flag in error branch.
[asterisk/asterisk.git] / funcs / func_extstate.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 2007, Digium, Inc.
5  *
6  * Modified from func_devstate.c by Russell Bryant <russell@digium.com> 
7  * Adam Gundy <adam@starsilk.net>
8
9  * See http://www.asterisk.org for more information about
10  * the Asterisk project. Please do not directly contact
11  * any of the maintainers of this project for assistance;
12  * the project provides a web site, mailing lists and IRC
13  * channels for your use.
14  *
15  * This program is free software, distributed under the terms of
16  * the GNU General Public License Version 2. See the LICENSE file
17  * at the top of the source tree.
18  */
19
20 /*! \file
21  *
22  * \brief Get the state of a hinted extension for dialplan control
23  *
24  * \author Adam Gundy <adam@starsilk.net> 
25  *
26  * \ingroup functions
27  */
28
29 /*** MODULEINFO
30         <support_level>core</support_level>
31  ***/
32
33 #include "asterisk.h"
34
35 #include "asterisk/module.h"
36 #include "asterisk/channel.h"
37 #include "asterisk/pbx.h"
38 #include "asterisk/utils.h"
39 #include "asterisk/devicestate.h"
40
41 /*** DOCUMENTATION
42         <function name="EXTENSION_STATE" language="en_US">
43                 <synopsis>
44                         Get an extension's state.
45                 </synopsis>     
46                 <syntax argsep="@">
47                         <parameter name="extension" required="true" />
48                         <parameter name="context">
49                                 <para>If it is not specified defaults to <literal>default</literal>.</para>
50                         </parameter>
51                 </syntax>
52                 <description>
53                         <para>The EXTENSION_STATE function can be used to retrieve the state from any
54                         hinted extension. For example:</para>
55                         <para>NoOp(1234@default has state ${EXTENSION_STATE(1234)})</para>
56                         <para>NoOp(4567@home has state ${EXTENSION_STATE(4567@home)})</para>
57                         <para>The possible values returned by this function are:</para>
58                         <para>UNKNOWN | NOT_INUSE | INUSE | BUSY | INVALID | UNAVAILABLE | RINGING |
59                         RINGINUSE | HOLDINUSE | ONHOLD</para>
60                 </description>
61         </function>
62  ***/
63
64 static const char *ast_extstate_str(int state)
65 {
66         const char *res = "UNKNOWN";
67
68         switch (state) {
69         case AST_EXTENSION_NOT_INUSE:
70                 res = "NOT_INUSE";
71                 break;
72         case AST_EXTENSION_INUSE:
73                 res = "INUSE";
74                 break;
75         case AST_EXTENSION_BUSY:
76                 res = "BUSY";
77                 break;
78         case AST_EXTENSION_UNAVAILABLE:
79                 res = "UNAVAILABLE";
80                 break;
81         case AST_EXTENSION_RINGING:
82                 res = "RINGING";
83                 break;
84         case AST_EXTENSION_INUSE | AST_EXTENSION_RINGING:
85                 res = "RINGINUSE";
86                 break;
87         case AST_EXTENSION_INUSE | AST_EXTENSION_ONHOLD:
88                 res = "HOLDINUSE";
89                 break;
90         case AST_EXTENSION_ONHOLD:
91                 res = "ONHOLD";
92                 break;
93         }
94
95         return res;
96 }
97
98 static int extstate_read(struct ast_channel *chan, const char *cmd, char *data,
99         char *buf, size_t len)
100 {
101         char *exten, *context;
102
103         if (ast_strlen_zero(data)) {
104                 ast_log(LOG_WARNING, "EXTENSION_STATE requires an extension\n");
105                 return -1;
106         }
107
108         context = exten = data;
109         strsep(&context, "@");
110         if (ast_strlen_zero(context))
111                 context = "default";
112
113         if (ast_strlen_zero(exten)) {
114                 ast_log(LOG_WARNING, "EXTENSION_STATE requires an extension\n");
115                 return -1;
116         }
117
118         ast_copy_string(buf, 
119                 ast_extstate_str(ast_extension_state(chan, context, exten)), len);
120
121         return 0;
122 }
123
124 static struct ast_custom_function extstate_function = {
125         .name = "EXTENSION_STATE",
126         .read = extstate_read,
127         .read_max = 12,
128 };
129
130 static int unload_module(void)
131 {
132         int res;
133
134         res = ast_custom_function_unregister(&extstate_function);
135
136         return res;
137 }
138
139 static int load_module(void)
140 {
141         int res;
142
143         res = ast_custom_function_register(&extstate_function);
144
145         return res ? AST_MODULE_LOAD_DECLINE : AST_MODULE_LOAD_SUCCESS;
146 }
147
148 AST_MODULE_INFO_STANDARD(ASTERISK_GPL_KEY, "Gets an extension's state in the dialplan");