Documentation fixes (bug #3170)
[asterisk/asterisk.git] / apps / app_chanisavail.c
1 /*
2  * Asterisk -- A telephony toolkit for Linux.
3  *
4  * Check if Channel is Available
5  * 
6  * Copyright (C) 2003-2004, Digium, Inc.
7  *
8  * Mark Spencer <markster@digium.com>
9  * James Golovich <james@gnuinter.net>
10  *
11  * This program is free software, distributed under the terms of
12  * the GNU General Public License
13  *
14  */
15
16 #include <asterisk/lock.h>
17 #include <asterisk/file.h>
18 #include <asterisk/logger.h>
19 #include <asterisk/channel.h>
20 #include <asterisk/pbx.h>
21 #include <asterisk/module.h>
22 #include <asterisk/app.h>
23 #include <stdlib.h>
24 #include <unistd.h>
25 #include <errno.h>
26 #include <string.h>
27 #include <stdlib.h>
28 #include <sys/ioctl.h>
29
30 static char *tdesc = "Check if channel is available";
31
32 static char *app = "ChanIsAvail";
33
34 static char *synopsis = "Check if channel is available";
35
36 static char *descrip = 
37 "  ChanIsAvail(Technology/resource[&Technology2/resource2...][|option]): \n"
38 "Checks is any of the requested channels are available.  If none\n"
39 "of the requested channels are available the new priority will be\n"
40 "n+101 (unless such a priority does not exist or on error, in which\n"
41 "case ChanIsAvail will return -1).\n"
42 "If any of the requested channels are available, the next priority will be n+1,\n"
43 "the channel variable ${AVAILCHAN} will be set to the name of the available channel\n"
44 "and the ChanIsAvail app will return 0.\n"
45 "${AVAILORIGCHAN} is the canonical channel name that was used to create the channel.\n"
46 "${AVAILSTATUS} is the status code for the channel.\n"
47 "If the option 's' is specified (state), will consider channel unavailable\n"
48 "when the channel is in use at all, even if it can take another call.\n";
49
50 STANDARD_LOCAL_USER;
51
52 LOCAL_USER_DECL;
53
54 static int chanavail_exec(struct ast_channel *chan, void *data)
55 {
56         int res=-1, inuse=-1, option_state=0;
57         int status;
58         struct localuser *u;
59         char info[512], tmp[512], trychan[512], *peers, *tech, *number, *rest, *cur, *options, *stringp;
60         struct ast_channel *tempchan;
61
62         if (!data) {
63                 ast_log(LOG_WARNING, "ChanIsAvail requires an argument (Zap/1&Zap/2)\n");
64                 return -1;
65         }
66         LOCAL_USER_ADD(u);
67
68         strncpy(info, (char *)data, sizeof(info)-1);
69         stringp = info;
70         strsep(&stringp, "|");
71         options = strsep(&stringp, "|");
72         if (options && *options == 's');
73                 option_state = 1;
74         peers = info;
75         if (peers) {
76                 cur = peers;
77                 do {
78                         /* remember where to start next time */
79                         rest = strchr(cur, '&');
80                         if (rest) {
81                                 *rest = 0;
82                                 rest++;
83                         }
84                         tech = cur;
85                         number = strchr(tech, '/');
86                         if (!number) {
87                                 ast_log(LOG_WARNING, "ChanIsAvail argument takes format ([technology]/[device])\n");
88                                 return -1;
89                         }
90                         *number = '\0';
91                         number++;
92                         
93                         if (option_state) {
94                                 /* If the pbx says in use then don't bother trying further.
95                                    This is to permit testing if someone's on a call, even if the 
96                                    channel can permit more calls (ie callwaiting, sip calls, etc).  */
97                                
98                                 snprintf(trychan, sizeof(trychan), "%s/%s",cur,number);
99                                 status = inuse = ast_device_state(trychan);
100                         }
101                         if ((inuse < 1) && (tempchan = ast_request(tech, chan->nativeformats, number, &status))) {
102                                         pbx_builtin_setvar_helper(chan, "AVAILCHAN", tempchan->name);
103                                         /* Store the originally used channel too */
104                                         snprintf(tmp, sizeof(tmp), "%s/%s", tech, number);
105                                         pbx_builtin_setvar_helper(chan, "AVAILORIGCHAN", tmp);
106                                         snprintf(tmp, sizeof(tmp), "%d", status);
107                                         pbx_builtin_setvar_helper(chan, "AVAILSTATUS", tmp);
108                                         ast_hangup(tempchan);
109                                         tempchan = NULL;
110                                         res = 1;
111                                         break;
112                         } else {
113                                 snprintf(tmp, sizeof(tmp), "%d", status);
114                                 pbx_builtin_setvar_helper(chan, "AVAILSTATUS", tmp);
115                         }
116                         cur = rest;
117                 } while (cur);
118         }
119         if (res < 1) {
120                 pbx_builtin_setvar_helper(chan, "AVAILCHAN", "");
121                 pbx_builtin_setvar_helper(chan, "AVAILORIGCHAN", "");
122                 if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 101, chan->cid.cid_num))
123                         chan->priority+=100;
124                 else
125                         return -1;
126         }
127
128         LOCAL_USER_REMOVE(u);
129         return 0;
130 }
131
132 int unload_module(void)
133 {
134         STANDARD_HANGUP_LOCALUSERS;
135         return ast_unregister_application(app);
136 }
137
138 int load_module(void)
139 {
140         return ast_register_application(app, chanavail_exec, synopsis, descrip);
141 }
142
143 char *description(void)
144 {
145         return tdesc;
146 }
147
148 int usecount(void)
149 {
150         int res;
151         STANDARD_USECOUNT(res);
152         return res;
153 }
154
155 char *key()
156 {
157         return ASTERISK_GPL_KEY;
158 }