Fix minor doc issue (bug #4145)
[asterisk/asterisk.git] / pbx / pbx_wilcalu.c
1 /** @file pbx_wilcalu.c 
2  *
3  * Asterisk -- A telephony toolkit for Linux.
4  *
5  * Trivial application to playback a sound file
6  * 
7  * Copyright (C) 1999, Mark Spencer
8  *
9  * Mark Spencer <markster@digium.com>
10  *
11  * This program is free software, distributed under the terms of
12  * the GNU General Public License
13
14  *  Autodialer for Asterisk 
15  *  Redirect dialstring thru fifo "/var/run/autodial.ctl"
16  *  Format of string is :
17  *  "tech/tele,filename&" ie. "tor1/23,file&"
18  */
19  
20 #include "asterisk/lock.h"
21 #include "asterisk/file.h"
22 #include "asterisk/logger.h"
23 #include "asterisk/channel.h"
24 #include "asterisk/pbx.h"
25 #include "asterisk/module.h"
26 #include "asterisk/translate.h"
27 #include "asterisk/options.h"
28 #include "asterisk/utils.h"
29 #include <unistd.h>
30 #include <string.h>
31 #include <stdlib.h>
32 #include <sys/types.h>
33 #include <sys/stat.h>
34 #include <errno.h>
35 #include "astconf.h"
36
37
38 /* Globals */
39 const   char dialfile[255];
40 static  char *tdesc = "Wil Cal U (Auto Dialer)";
41 static  pthread_t autodialer_thread;
42 static  char buf[257];
43 static  char lastbuf[257]; /* contains last partial buffer */
44 static  char sendbuf[257];
45 STANDARD_LOCAL_USER;
46 LOCAL_USER_DECL;
47
48 /* prototype */
49 static void *dialstring(void *string);
50
51 /*  types */
52 struct alarm_data {
53         time_t  alarm_time;
54         int     snooze_len;
55         void    *dialstr;
56 };
57
58 static void *autodial(void *ignore)
59 {
60         pthread_t dialstring_thread;
61         char * sendbufptr=sendbuf;
62         int fd=open(dialfile,O_RDONLY|O_NONBLOCK);
63         int flags = fcntl(fd, F_GETFL);
64         struct pollfd fds[1];
65
66         fcntl(fd, F_SETFL, flags & ~O_NONBLOCK);
67         if (option_debug)
68                 ast_log(LOG_DEBUG, "Entered Wil-Calu fd=%d\n",fd);
69         if(fd<0) {
70                 ast_log(LOG_WARNING, "Autodial: Unable to open file\n");
71                 pthread_exit(NULL);
72         }
73         memset(buf,0,257);
74         memset(lastbuf,0,257);
75         memset(sendbuf,0,257);
76         while(1){
77                 ssize_t bytes;
78                 void *pass;
79
80                 memset(buf,0,257);
81                 fds[0].fd = fd;
82                 fds[0].events = POLLIN;
83                 poll(fds, 1, -1);
84                 bytes=read(fd,buf,256);
85
86                 if(bytes>0){
87                         int x;
88                         buf[(int)bytes]=0;
89                         ast_log(LOG_DEBUG, "WilCalu : Read Buf %s\n",buf);
90                         sendbufptr=sendbuf;
91                         for(x=0; lastbuf[x]!=0 && x<257; x++);
92                         if(x) {
93                                 memcpy(sendbuf, lastbuf, x);
94                                 sendbufptr+=x;
95                                 memset(lastbuf, 0, 257);
96                         }
97                         /* Process bytes read */
98                         for(x=0; x<bytes; x++){
99                                 /* if & then string is complete */
100                                 if(buf[x]=='&'){
101                                         if(NULL!=(pass=(void *)strdup(sendbuf))){
102                                                 ast_pthread_create(&dialstring_thread, NULL, dialstring, pass);
103                                                 sendbufptr=sendbuf;
104                                                 memset(sendbuf, 0, 257);
105                                         }
106                                         else {
107                                                 perror("Autodial: Strdup failed");
108                                                 close(fd);
109                                                 pthread_exit(NULL);
110                                         }
111                                 } else {
112                                         if(buf[x]=='\n')
113                                                 continue;
114                                         *sendbufptr=buf[x];
115                                         sendbufptr++;
116                                         *sendbufptr=0;
117                                 }
118                         }
119                         if(sendbufptr!=sendbuf)
120                                 memcpy(lastbuf, sendbuf, sendbufptr-sendbuf+1);
121                 }
122         }
123         close(fd);
124         pthread_exit(NULL);
125         return NULL;
126 }
127
128 static void *snooze_alarm(void *pass)
129 {
130         pthread_t dialstring_thread;
131         struct alarm_data *data = (struct alarm_data *) pass;
132
133         sleep(data->snooze_len);
134         ast_pthread_create(&dialstring_thread, NULL, dialstring, data->dialstr);
135         /* dialstring will free data->dialstr */
136         free(pass);
137         pthread_exit(NULL);
138         return NULL;
139 }
140
141 static void  set_snooze_alarm(char *dialstr, int snooze_len)
142 {
143         pthread_t snooze_alarm_thread;
144         struct alarm_data *pass;
145
146         ast_log(LOG_DEBUG, "Answered: Snooze Requested\n");
147         if (NULL==(pass=malloc(sizeof(struct alarm_data)))){
148                 perror("snooze_alarm: data");
149                 pthread_exit(NULL);
150         }
151         if (NULL==(pass->dialstr=(void *)strdup(dialstr))){
152                 free(pass);
153                 perror("snooze_alarm: dialstr");
154                 pthread_exit(NULL);
155         }
156         pass->snooze_len=snooze_len;
157         ast_pthread_create(&snooze_alarm_thread,NULL,snooze_alarm,pass);
158 }
159                         
160 static void *dialstring(void *string)
161 {
162         struct ast_channel *channel;
163         char *bufptr,*destptr;
164         int  ms=10000;          /* ms affects number of rings */
165         int  cnt=0,first;
166         char tech[256];
167         char tele[256];
168         char filename[256];
169         int  answered=0;
170
171         for(first=0, bufptr=(char *)string, destptr=tech; *bufptr&&cnt<256; cnt++){
172                 if(*bufptr=='/' && !first) {
173                         *destptr=0;
174                         destptr=tele;
175                         first=1;
176                 }
177                 else if(*bufptr==',') {
178                         *destptr=0;
179                         destptr=filename;
180                 } else {
181                         *destptr=*bufptr;
182                         destptr++;
183                 }
184                 bufptr++;
185         } 
186         *destptr=0;
187         ast_log(LOG_DEBUG, "Printing string arg: %s Eos\n", (char *)string);
188         if(strlen(tech)+strlen(tele)+strlen(filename) > 256) {
189                 ast_log(LOG_ERROR, "Autodial:Error string too long\n");
190                 free(string);
191                 pthread_exit(NULL);
192         }
193         ast_log(LOG_DEBUG, "Autodial Tech %s(%d) Tele %s(%d) Filename %s(%d)\n",tech, (int)strlen(tech), tele, (int)strlen(tele), filename, (int)strlen(filename));
194
195         channel=ast_request(tech,AST_FORMAT_SLINEAR,tele);
196         if(channel!=NULL){
197                 ast_call(channel,tele,10000);
198         } else {
199                 ast_log(LOG_ERROR, "Autodial:Sorry unable to obtain channel\n");
200                 free(string);
201                 pthread_exit(NULL);
202         }
203         if(channel->_state==AST_STATE_UP)
204                 ast_log(LOG_DEBUG, "Autodial:Line is Up\n");
205         while(ms>0){
206                 struct ast_frame *f;
207
208                 ms=ast_waitfor(channel,ms);
209                 f=ast_read(channel);
210                 if(!f){
211                         ast_log(LOG_DEBUG, "Autodial:Hung Up\n");
212                         break;
213                 }
214                 if (f->frametype==AST_FRAME_CONTROL) {
215                         if (f->subclass==AST_CONTROL_ANSWER) {
216                                 ast_log(LOG_DEBUG, "Autodial:Phone Answered\n");
217                                 if (channel->_state==AST_STATE_UP) {
218                                         char res;
219
220                                         ast_streamfile(channel,filename,0);
221                                         /* Press Five for snooze */
222                                         res=ast_waitstream(channel, "37");
223                                         if(res=='3'){
224                                                 answered=1;
225                                                 set_snooze_alarm((char *)string,60);
226                                                 ast_streamfile(channel,"demo-thanks",0);
227                                                 ast_waitstream(channel, "");
228                                         }
229                                         else if(res=='7'){
230                                                 answered=1;
231                                                 ast_streamfile(channel,"demo-thanks",0);
232                                                 ast_waitstream(channel, "");
233                                         }
234                                         ast_stopstream(channel);
235                                         ms=0;
236                                 }
237                         }
238                         else if (f->subclass==AST_CONTROL_RINGING)
239                                 ast_log(LOG_DEBUG, "Autodial:Phone Ringing end\n");
240                 }
241                 ast_frfree(f);
242         }
243         if(!answered)
244                 set_snooze_alarm((char *) string, 5);
245         free(string);
246         ast_hangup(channel);
247         ast_log(LOG_DEBUG, "Autodial:Hung up channel\n");
248         pthread_exit(NULL);
249         return NULL;
250 }
251
252 int unload_module(void)
253 {
254         STANDARD_HANGUP_LOCALUSERS;
255         unlink(dialfile);
256         return 0;
257 }
258
259 int load_module(void)
260 {
261         int val;
262
263         snprintf((char *)dialfile, sizeof(dialfile), "%s/%s", ast_config_AST_RUN_DIR, "autodial.ctl");
264         if((val=mkfifo(dialfile, 0700))) {
265                 if(errno!=EEXIST){
266                         ast_log(LOG_ERROR, "Error:%d Creating Autodial FIFO\n",errno);
267                         return 0;
268                 }
269         }
270         ast_pthread_create(&autodialer_thread, NULL, autodial, NULL);
271         return 0;
272 }
273
274 char *description(void)
275 {
276         return tdesc;
277 }
278
279 int usecount(void)
280 {
281         int res;
282         STANDARD_USECOUNT(res);
283         return res;
284 }
285
286 char *key()
287 {
288         return ASTERISK_GPL_KEY;
289 }