Allow softhangup to work on partial matches if requested (bug #3261)
[asterisk/asterisk.git] / apps / app_softhangup.c
1 /*
2  * Asterisk -- A telephony toolkit for Linux.
3  *
4  * SoftHangup application
5  * 
6  * Copyright (C) 1999, Mark Spencer
7  *
8  * Mark Spencer <markster@linux-support.net>
9  *
10  * This program is free software, distributed under the terms of
11  * the GNU General Public License
12  */
13
14 #include <sys/types.h>
15 #include <asterisk/file.h>
16 #include <asterisk/logger.h>
17 #include <asterisk/channel.h>
18 #include <asterisk/pbx.h>
19 #include <asterisk/module.h>
20 #include <asterisk/lock.h>
21 #include <stdlib.h>
22 #include <unistd.h>
23 #include <string.h>
24 #include <stdlib.h>
25
26 static char *synopsis = "Soft Hangup Application";
27
28 static char *tdesc = "Hangs up the requested channel";
29
30 static char *desc = "  SoftHangup(Technology/resource|options)\n"
31 "Hangs up the requested channel.  Always returns 0\n"
32 "- 'options' may contain the following letter:\n"
33 "     'a' : hang up all channels on a specified device instead of a single resource\n";
34
35 static char *app = "SoftHangup";
36
37 STANDARD_LOCAL_USER;
38
39 LOCAL_USER_DECL;
40
41 static int softhangup_exec(struct ast_channel *chan, void *data)
42 {
43         struct localuser *u;
44         struct ast_channel *c=NULL;
45         char *options, *cut, *cdata, *match;
46         char name[AST_CHANNEL_NAME] = "";
47         int all = 0;
48
49         if (!data) {
50                 ast_log(LOG_WARNING, "SoftHangup requires an argument (Technology/resource)\n");
51                 return 0;
52         }
53         
54         cdata = ast_strdupa(data);
55         match = strsep(&cdata, "|");
56         options = strsep(&cdata, "|");
57         all = options && strchr(options,'a');
58         LOCAL_USER_ADD(u);
59         c = ast_channel_walk_locked(NULL);
60         while (c) {
61                 strncpy(name, c->name, sizeof(name)-1);
62                 ast_mutex_unlock(&c->lock);
63                 if (all) {
64                         /* CAPI is set up like CAPI[foo/bar]/clcnt */ 
65                         if (!strcmp(c->type,"CAPI")) 
66                                 cut = strrchr(name,'/');
67                         /* Basically everything else is Foo/Bar-Z */
68                         else
69                                 cut = strchr(name,'-');
70                         /* Get rid of what we've cut */
71                         if (cut)
72                                 *cut = 0;
73                 }
74                 if (!strcasecmp(name, match)) {
75                         ast_log(LOG_WARNING, "Soft hanging %s up.\n",c->name);
76                         ast_softhangup(c, AST_SOFTHANGUP_EXPLICIT);
77                         if(!all)
78                                 break;
79                 }
80                 c = ast_channel_walk_locked(c);
81         }
82         LOCAL_USER_REMOVE(u);
83
84         return 0;
85 }
86
87 int unload_module(void)
88 {
89         STANDARD_HANGUP_LOCALUSERS;
90         return ast_unregister_application(app);
91 }
92
93 int load_module(void)
94 {
95         return ast_register_application(app, softhangup_exec, synopsis, desc);
96 }
97
98 char *description(void)
99 {
100         return tdesc;
101 }
102
103 int usecount(void)
104 {
105         int res;
106         STANDARD_USECOUNT(res);
107         return res;
108 }
109
110 char *key()
111 {
112         return ASTERISK_GPL_KEY;
113 }