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