Use find_user for existsmailbox
[asterisk/asterisk.git] / apps / app_zapras.c
1 /*
2  * Asterisk -- A telephony toolkit for Linux.
3  *
4  * Execute an ISDN RAS
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 <asterisk/lock.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/options.h>
21 #include <sys/ioctl.h>
22 #include <sys/wait.h>
23 #include <sys/signal.h>
24
25 #include <stdlib.h>
26 #include <unistd.h>
27 #include <string.h>
28 #include <stdlib.h>
29 #include <errno.h>
30 #include <stdio.h>
31 #include <fcntl.h>
32
33 #include <pthread.h>
34
35 /* Need some zaptel help here */
36 #include <linux/zaptel.h>
37
38 static char *tdesc = "Zap RAS Application";
39
40 static char *app = "ZapRAS";
41
42 static char *synopsis = "Executes Zaptel ISDN RAS application";
43
44 static char *descrip =
45 "  ZapRAS(args): Executes a RAS server using pppd on the given channel.\n"
46 "The channel must be a clear channel (i.e. PRI source) and a Zaptel\n"
47 "channel to be able to use this function (No modem emulation is included).\n"
48 "Your pppd must be patched to be zaptel aware. Arguments should be\n"
49 "separated by | characters.  Always returns -1.\n";
50
51 STANDARD_LOCAL_USER;
52
53 LOCAL_USER_DECL;
54
55 #define PPP_MAX_ARGS    32
56 #define PPP_EXEC        "/usr/sbin/pppd"
57
58 static pid_t spawn_ras(struct ast_channel *chan, char *args)
59 {
60         pid_t pid;
61         int x;  
62         char *c;
63
64         char *argv[PPP_MAX_ARGS];
65         int argc = 0;
66         char *stringp=NULL;
67
68         /* Start by forking */
69         pid = fork();
70         if (pid)
71                 return pid;
72
73         /* Execute RAS on File handles */
74         dup2(chan->fds[0], STDIN_FILENO);
75
76         /* Close other file descriptors */
77         for (x=STDERR_FILENO + 1;x<1024;x++) 
78                 close(x);
79
80         /* Restore original signal handlers */
81         for (x=0;x<NSIG;x++)
82                 signal(x, SIG_DFL);
83
84         /* Reset all arguments */
85         memset(argv, 0, sizeof(argv));
86
87         /* First argument is executable, followed by standard
88            arguments for zaptel PPP */
89         argv[argc++] = PPP_EXEC;
90         argv[argc++] = "nodetach";
91
92         /* And all the other arguments */
93         stringp=args;
94         c = strsep(&stringp, "|");
95         while(c && strlen(c) && (argc < (PPP_MAX_ARGS - 4))) {
96                 argv[argc++] = c;
97                 c = strsep(&stringp, "|");
98         }
99
100         argv[argc++] = "plugin";
101         argv[argc++] = "zaptel.so";
102         argv[argc++] = "stdin";
103
104 #if 0
105         for (x=0;x<argc;x++) {
106                 fprintf(stderr, "Arg %d: %s\n", x, argv[x]);
107         }
108 #endif
109
110         /* Finally launch PPP */
111         execv(PPP_EXEC, argv);
112         fprintf(stderr, "Failed to exec PPPD!\n");
113         exit(1);
114 }
115
116 static void run_ras(struct ast_channel *chan, char *args)
117 {
118         pid_t pid;
119         int status;
120         int res;
121         int signalled = 0;
122         struct zt_bufferinfo bi;
123         int x;
124
125         pid = spawn_ras(chan, args);
126         if (pid < 0) {
127                 ast_log(LOG_WARNING, "Failed to spawn RAS\n");
128         } else {
129                 for (;;) {
130                         res = wait4(pid, &status, WNOHANG, NULL);
131                         if (!res) {
132                                 /* Check for hangup */
133                                 if (chan->_softhangup && !signalled) {
134                                         ast_log(LOG_DEBUG, "Channel '%s' hungup.  Signalling RAS at %d to die...\n", chan->name, pid);
135                                         kill(pid, SIGTERM);
136                                         signalled=1;
137                                 }
138                                 /* Try again */
139                                 sleep(1);
140                                 continue;
141                         }
142                         if (res < 0) {
143                                 ast_log(LOG_WARNING, "wait4 returned %d: %s\n", res, strerror(errno));
144                         }
145                         if (option_verbose > 2) {
146                                 if (WIFEXITED(status)) {
147                                         ast_verbose(VERBOSE_PREFIX_3 "RAS on %s terminated with status %d\n", chan->name, WEXITSTATUS(status));
148                                 } else if (WIFSIGNALED(status)) {
149                                         ast_verbose(VERBOSE_PREFIX_3 "RAS on %s terminated with signal %d\n", 
150                                                  chan->name, WTERMSIG(status));
151                                 } else {
152                                         ast_verbose(VERBOSE_PREFIX_3 "RAS on %s terminated weirdly.\n", chan->name);
153                                 }
154                         }
155                         /* Throw back into audio mode */
156                         x = 1;
157                         ioctl(chan->fds[0], ZT_AUDIOMODE, &x);
158
159                         /* Double check buffering too */
160                         res = ioctl(chan->fds[0], ZT_GET_BUFINFO, &bi);
161                         if (!res) {
162                                 /* XXX This is ZAP_BLOCKSIZE XXX */
163                                 bi.bufsize = 204;
164                                 bi.txbufpolicy = ZT_POLICY_IMMEDIATE;
165                                 bi.rxbufpolicy = ZT_POLICY_IMMEDIATE;
166                                 bi.numbufs = 4;
167                                 res = ioctl(chan->fds[0], ZT_SET_BUFINFO, &bi);
168                                 if (res < 0) {
169                                         ast_log(LOG_WARNING, "Unable to set buffer policy on channel %s\n", chan->name);
170                                 }
171                         } else
172                                 ast_log(LOG_WARNING, "Unable to check buffer policy on channel %s\n", chan->name);
173                         break;
174                 }
175         }
176 }
177
178 static int zapras_exec(struct ast_channel *chan, void *data)
179 {
180         int res=-1;
181         char args[256];
182         struct localuser *u;
183         ZT_PARAMS ztp;
184
185         if (!data) 
186                 data = "";
187         LOCAL_USER_ADD(u);
188         strncpy(args, data, sizeof(args) - 1);
189         /* Answer the channel if it's not up */
190         if (chan->_state != AST_STATE_UP)
191                 ast_answer(chan);
192         if (strcasecmp(chan->type, "Zap")) {
193                 /* If it's not a zap channel, we're done.  Wait a couple of
194                    seconds and then hangup... */
195                 if (option_verbose > 1)
196                         ast_verbose(VERBOSE_PREFIX_2 "Channel %s is not a Zap channel\n", chan->name);
197                 sleep(2);
198         } else {
199                 memset(&ztp, 0, sizeof(ztp));
200                 if (ioctl(chan->fds[0], ZT_GET_PARAMS, &ztp)) {
201                         ast_log(LOG_WARNING, "Unable to get zaptel parameters\n");
202                 } else if (ztp.sigtype != ZT_SIG_CLEAR) {
203                         if (option_verbose > 1)
204                                 ast_verbose(VERBOSE_PREFIX_2 "Channel %s is not a clear channel\n", chan->name);
205                 } else {
206                         /* Everything should be okay.  Run PPP. */
207                         if (option_verbose > 2)
208                                 ast_verbose(VERBOSE_PREFIX_3 "Starting RAS on %s\n", chan->name);
209                         /* Execute RAS */
210                         run_ras(chan, args);
211                 }
212         }
213         LOCAL_USER_REMOVE(u);
214         return res;
215 }
216
217 int unload_module(void)
218 {
219         STANDARD_HANGUP_LOCALUSERS;
220         return ast_unregister_application(app);
221 }
222
223 int load_module(void)
224 {
225         return ast_register_application(app, zapras_exec, synopsis, descrip);
226 }
227
228 char *description(void)
229 {
230         return tdesc;
231 }
232
233 int usecount(void)
234 {
235         int res;
236         STANDARD_USECOUNT(res);
237         return res;
238 }
239
240 char *key()
241 {
242         return ASTERISK_GPL_KEY;
243 }