Version 0.1.9 from FTP
[asterisk/asterisk.git] / apps / app_agi.c
1 /*
2  * Asterisk -- A telephony toolkit for Linux.
3  *
4  * Asterisk Gateway Interface
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/file.h>
15 #include <asterisk/logger.h>
16 #include <asterisk/channel.h>
17 #include <asterisk/pbx.h>
18 #include <asterisk/module.h>
19 #include <math.h>
20 #include <stdlib.h>
21 #include <unistd.h>
22 #include <string.h>
23 #include <stdlib.h>
24 #include <sys/signal.h>
25 #include <sys/time.h>
26 #include <asterisk/cli.h>
27 #include <asterisk/logger.h>
28 #include <asterisk/options.h>
29 #include <asterisk/image.h>
30 #include <asterisk/say.h>
31 #include "../asterisk.h"
32
33 #include <pthread.h>
34
35 #define MAX_ARGS 128
36
37 /* Recycle some stuff from the CLI interface */
38 #define fdprintf ast_cli
39
40 typedef struct agi_command {
41         /* Null terminated list of the words of the command */
42         char *cmda[AST_MAX_CMD_LEN];
43         /* Handler for the command (fd for output, # of arguments, argument list). 
44             Returns RESULT_SHOWUSAGE for improper arguments */
45         int (*handler)(struct ast_channel *chan, int fd, int argc, char *argv[]);
46         /* Summary of the command (< 60 characters) */
47         char *summary;
48         /* Detailed usage information */
49         char *usage;
50 } agi_command;
51
52 static char *tdesc = "Asterisk Gateway Interface (AGI)";
53
54 static char *app = "AGI";
55
56 static char *synopsis = "Executes an AGI compliant application";
57
58 static char *descrip =
59 "  AGI(command|args): Executes an Asterisk Gateway Interface compliant\n"
60 "program on a channel.   AGI allows Asterisk to launch external programs\n"
61 "written in any language to control a telephony channel, play audio,\n"
62 "read DTMF digits, etc. by communicating with the AGI protocol on stdin\n"
63 "and stdout.  Returns -1 on hangup or if application requested hangup, or\n"
64 "0 on non-hangup exit.\n";
65
66 STANDARD_LOCAL_USER;
67
68 LOCAL_USER_DECL;
69
70 #define TONE_BLOCK_SIZE 200
71
72 static float loudness = 8192.0;
73
74 unsigned char linear2ulaw(short sample);
75 static void make_tone_block(unsigned char *data, float f1, int *x);
76
77 static void make_tone_block(unsigned char *data, float f1, int *x)
78 {
79 int     i;
80 float   val;
81
82         for(i = 0; i < TONE_BLOCK_SIZE; i++)
83         {
84                 val = loudness * sin((f1 * 2.0 * M_PI * (*x)++)/8000.0);
85                 data[i] = linear2ulaw((int)val);
86          }              
87           /* wrap back around from 8000 */
88         if (*x >= 8000) *x = 0;
89         return;
90 }
91
92 static int launch_script(char *script, char *args, int *fds, int *opid)
93 {
94         char tmp[256];
95         int pid;
96         int toast[2];
97         int fromast[2];
98         int x;
99         if (script[0] != '/') {
100                 snprintf(tmp, sizeof(tmp), "%s/%s", AST_AGI_DIR, script);
101                 script = tmp;
102         }
103         if (pipe(toast)) {
104                 ast_log(LOG_WARNING, "Unable to create toast pipe: %s\n",strerror(errno));
105                 return -1;
106         }
107         if (pipe(fromast)) {
108                 ast_log(LOG_WARNING, "unable to create fromast pipe: %s\n", strerror(errno));
109                 close(toast[0]);
110                 close(toast[1]);
111                 return -1;
112         }
113         pid = fork();
114         if (pid < 0) {
115                 ast_log(LOG_WARNING, "Failed to fork(): %s\n", strerror(errno));
116                 return -1;
117         }
118         if (!pid) {
119                 /* Redirect stdin and out */
120                 dup2(fromast[0], STDIN_FILENO);
121                 dup2(toast[1], STDOUT_FILENO);
122                 /* Close everything but stdin/out/error */
123                 for (x=STDERR_FILENO + 1;x<1024;x++) 
124                         close(x);
125                 /* Execute script */
126                 execl(script, script, args, NULL);
127                 ast_log(LOG_WARNING, "Failed to execute '%s': %s\n", script, strerror(errno));
128                 exit(1);
129         }
130         if (option_verbose > 2) 
131                 ast_verbose(VERBOSE_PREFIX_3 "Launched AGI Script %s\n", script);
132         fds[0] = toast[0];
133         fds[1] = fromast[1];
134         /* close what we're not using in the parent */
135         close(toast[1]);
136         close(fromast[0]);
137         *opid = pid;
138         return 0;
139                 
140 }
141
142 static void setup_env(struct ast_channel *chan, char *request, int fd)
143 {
144         /* Print initial environment, with agi_request always being the first
145            thing */
146         fdprintf(fd, "agi_request: %s\n", request);
147         fdprintf(fd, "agi_channel: %s\n", chan->name);
148         fdprintf(fd, "agi_language: %s\n", chan->language);
149         fdprintf(fd, "agi_type: %s\n", chan->type);
150
151         /* ANI/DNIS */
152         fdprintf(fd, "agi_callerid: %s\n", chan->callerid ? chan->callerid : "");
153         fdprintf(fd, "agi_dnid: %s\n", chan->dnid ? chan->dnid : "");
154
155         /* Context information */
156         fdprintf(fd, "agi_context: %s\n", chan->context);
157         fdprintf(fd, "agi_extension: %s\n", chan->exten);
158         fdprintf(fd, "agi_priority: %d\n", chan->priority);
159
160         /* End with empty return */
161         fdprintf(fd, "\n");
162 }
163
164 static int handle_waitfordigit(struct ast_channel *chan, int fd, int argc, char *argv[])
165 {
166         int res;
167         int to;
168         if (argc != 4)
169                 return RESULT_SHOWUSAGE;
170         if (sscanf(argv[3], "%i", &to) != 1)
171                 return RESULT_SHOWUSAGE;
172         res = ast_waitfordigit(chan, to);
173         fdprintf(fd, "200 result=%d\n", res);
174         if (res >= 0)
175                 return RESULT_SUCCESS;
176         else
177                 return RESULT_FAILURE;
178 }
179
180 static int handle_sendtext(struct ast_channel *chan, int fd, int argc, char *argv[])
181 {
182         int res;
183         if (argc != 3)
184                 return RESULT_SHOWUSAGE;
185         res = ast_sendtext(chan, argv[2]);
186         fdprintf(fd, "200 result=%d\n", res);
187         if (res >= 0)
188                 return RESULT_SUCCESS;
189         else
190                 return RESULT_FAILURE;
191 }
192
193 static int handle_sendimage(struct ast_channel *chan, int fd, int argc, char *argv[])
194 {
195         int res;
196         if (argc != 3)
197                 return RESULT_SHOWUSAGE;
198         res = ast_send_image(chan, argv[2]);
199         if (!chan->softhangup)
200                 res = 0;
201         fdprintf(fd, "200 result=%d\n", res);
202         if (res >= 0)
203                 return RESULT_SUCCESS;
204         else
205                 return RESULT_FAILURE;
206 }
207
208 static int handle_streamfile(struct ast_channel *chan, int fd, int argc, char *argv[])
209 {
210         int res;
211         if (argc != 4)
212                 return RESULT_SHOWUSAGE;
213         res = ast_streamfile(chan, argv[2],chan->language);
214         if (res) {
215                 fdprintf(fd, "200 result=%d\n", res);
216                 if (res >= 0)
217                         return RESULT_SHOWUSAGE;
218                 else
219                         return RESULT_FAILURE;
220         }
221         res = ast_waitstream(chan, argv[3]);
222         
223         fdprintf(fd, "200 result=%d\n", res);
224         if (res >= 0)
225                 return RESULT_SUCCESS;
226         else
227                 return RESULT_FAILURE;
228 }
229
230 static int handle_saynumber(struct ast_channel *chan, int fd, int argc, char *argv[])
231 {
232         int res;
233         int num;
234         if (argc != 4)
235                 return RESULT_SHOWUSAGE;
236         if (sscanf(argv[2], "%i", &num) != 1)
237                 return RESULT_SHOWUSAGE;
238         res = ast_say_number(chan, num, chan->language);
239         fdprintf(fd, "200 result=%d\n", res);
240         if (res >= 0)
241                 return RESULT_SUCCESS;
242         else
243                 return RESULT_FAILURE;
244 }
245
246 int ast_app_getdata(struct ast_channel *c, char *prompt, char *s, int maxlen, int timeout);
247
248 static int handle_getdata(struct ast_channel *chan, int fd, int argc, char *argv[])
249 {
250         int res;
251         char data[50];
252         int max;
253         int timeout;
254
255         if (argc < 3)
256                 return RESULT_SHOWUSAGE;
257         if (argc >= 4) timeout = atoi(argv[3]); else timeout = 0;
258         if (argc >= 5) max = atoi(argv[4]); else max = 50;
259         res = ast_app_getdata(chan, argv[2], data, max, timeout);
260         if (res == 1)
261                 fdprintf(fd, "200 result=%s (timeout)\n", data);
262         else
263                 fdprintf(fd, "200 result=%s\n", data);
264         if (res >= 0)
265                 return RESULT_SUCCESS;
266         else
267                 return RESULT_FAILURE;
268 }
269
270 static int handle_setcontext(struct ast_channel *chan, int fd, int argc, char *argv[])
271 {
272
273         if (argc != 3)
274                 return RESULT_SHOWUSAGE;
275         strncpy(chan->context, argv[2], sizeof(chan->context));
276         fdprintf(fd, "200 result=0\n");
277         return RESULT_SUCCESS;
278 }
279         
280 static int handle_setextension(struct ast_channel *chan, int fd, int argc, char **argv)
281 {
282         if (argc != 3)
283                 return RESULT_SHOWUSAGE;
284         strncpy(chan->exten, argv[2], sizeof(chan->exten));
285         fdprintf(fd, "200 result=0\n");
286         return RESULT_SUCCESS;
287 }
288
289 static int handle_setpriority(struct ast_channel *chan, int fd, int argc, char **argv)
290 {
291         int pri;
292         if (argc != 3)
293                 return RESULT_SHOWUSAGE;        
294         if (sscanf(argv[2], "%i", &pri) != 1)
295                 return RESULT_SHOWUSAGE;
296         chan->priority = pri - 1;
297         fdprintf(fd, "200 result=0\n");
298         return RESULT_SUCCESS;
299 }
300                 
301 static int ms_diff(struct timeval *tv1, struct timeval *tv2)
302 {
303 int     ms;
304         
305         ms = (tv1->tv_sec - tv2->tv_sec) * 1000;
306         ms += (tv1->tv_usec - tv2->tv_usec) / 1000;
307         return(ms);
308 }
309
310 static int handle_recordfile(struct ast_channel *chan, int fd, int argc, char *argv[])
311 {
312         struct ast_filestream *fs;
313         struct ast_frame *f,wf;
314         struct timeval tv, start, lastout, now, notime = { 0,0 } ;
315         fd_set readfds;
316         unsigned char tone_block[TONE_BLOCK_SIZE];
317         int res = -1;
318         int ms,i,j;
319
320         if (argc < 6)
321                 return RESULT_SHOWUSAGE;
322         if (sscanf(argv[5], "%i", &ms) != 1)
323                 return RESULT_SHOWUSAGE;
324
325         if (argc > 6) { /* if to beep */
326                 i = 0;
327                 lastout.tv_sec = lastout.tv_usec = 0;
328                 for(j = 0; j < 13; j++)
329                    {
330                         do gettimeofday(&now,NULL);
331                         while (lastout.tv_sec && 
332                                 (ms_diff(&now,&lastout) < 25));
333                         lastout.tv_sec = now.tv_sec;
334                         lastout.tv_usec = now.tv_usec;
335                         wf.frametype = AST_FRAME_VOICE;
336                         wf.subclass = AST_FORMAT_ULAW;
337                         wf.offset = AST_FRIENDLY_OFFSET;
338                         wf.mallocd = 0;
339                         wf.data = tone_block;
340                         wf.datalen = TONE_BLOCK_SIZE;                           
341                         /* make this tone block */
342                         make_tone_block(tone_block,1000.0,&i);
343                         wf.timelen = wf.datalen / 8;
344                         if (ast_write(chan, &wf)) {
345                                 fdprintf(fd, "200 result=%d (hangup)\n", 0);
346                                 return RESULT_FAILURE;
347                         }
348                         FD_ZERO(&readfds);
349                         FD_SET(chan->fds[0],&readfds);
350                           /* if no read avail, do send again */
351                         if (select(chan->fds[0] + 1,&readfds,NULL,
352                                 NULL,&notime) < 1) continue;
353                         f = ast_read(chan);
354                         if (!f) {
355                                 fdprintf(fd, "200 result=%d (hangup)\n", 0);
356                                 return RESULT_FAILURE;
357                         }
358                         switch(f->frametype) {
359                         case AST_FRAME_DTMF:
360                                 if (strchr(argv[4], f->subclass)) {
361                                         /* This is an interrupting chracter */
362                                         fdprintf(fd, "200 result=%d (dtmf)\n", f->subclass);
363                                         ast_frfree(f);
364                                         return RESULT_SUCCESS;
365                                 }
366                                 break;
367                         case AST_FRAME_VOICE:
368                                 break;  /* throw it away */
369                         }
370                         ast_frfree(f);
371                    }
372                   /* suck in 5 voice frames to make up for echo of beep, etc */
373                 for(i = 0; i < 5; i++) {
374                         f = ast_read(chan);
375                         if (!f) {
376                                 fdprintf(fd, "200 result=%d (hangup)\n", 0);
377                                 return RESULT_FAILURE;
378                         }
379                         switch(f->frametype) {
380                         case AST_FRAME_DTMF:
381                                 if (strchr(argv[4], f->subclass)) {
382                                         /* This is an interrupting chracter */
383                                         fdprintf(fd, "200 result=%d (dtmf)\n", f->subclass);
384                                         ast_frfree(f);
385                                         return RESULT_SUCCESS;
386                                 }
387                                 break;
388                         case AST_FRAME_VOICE:
389                                 break;  /* throw it away */
390                         }
391                         ast_frfree(f);
392                 }
393
394         }
395
396         fs = ast_writefile(argv[2], argv[3], NULL, O_CREAT | O_TRUNC | O_WRONLY, 0, 0644);
397         if (!fs) {
398                 fdprintf(fd, "200 result=%d (writefile)\n", res);
399                 return RESULT_FAILURE;
400         }
401         gettimeofday(&start, NULL);
402         gettimeofday(&tv, NULL);
403         while ((ms < 0) || (((tv.tv_sec - start.tv_sec) * 1000 + (tv.tv_usec - start.tv_usec)/1000) < ms)) {
404                 res = ast_waitfor(chan, -1);
405                 if (res < 0) {
406                         ast_closestream(fs);
407                         fdprintf(fd, "200 result=%d (waitfor)\n", res);
408                         return RESULT_FAILURE;
409                 }
410                 f = ast_read(chan);
411                 if (!f) {
412                         fdprintf(fd, "200 result=%d (hangup)\n", 0);
413                         ast_closestream(fs);
414                         return RESULT_FAILURE;
415                 }
416                 switch(f->frametype) {
417                 case AST_FRAME_DTMF:
418                         if (strchr(argv[4], f->subclass)) {
419                                 /* This is an interrupting chracter */
420                                 fdprintf(fd, "200 result=%d (dtmf)\n", f->subclass);
421                                 ast_closestream(fs);
422                                 ast_frfree(f);
423                                 return RESULT_SUCCESS;
424                         }
425                         break;
426                 case AST_FRAME_VOICE:
427                         ast_writestream(fs, f);
428                         break;
429                 };
430                 ast_frfree(f);
431                 gettimeofday(&tv, NULL);
432         }
433         fdprintf(fd, "200 result=%d (timeout)\n", 0);
434         ast_closestream(fs);
435         return RESULT_SUCCESS;
436 }
437
438 static char usage_waitfordigit[] = 
439 " Usage: WAIT FOR DIGIT <timeout>\n"
440 "        Waits up to 'timeout' seconds for channel to receive a DTMF digit.\n"
441 " Returns -1 on channel failure, 0 if no digit is received in the timeout, or\n"
442 " the numerical value of the ascii of the digit if one is received.  Use -1\n"
443 " for the timeout value if you desire the call to block indefinitely.\n";
444
445 static char usage_sendtext[] =
446 " Usage: SEND TEXT \"<text to send>\"\n"
447 "        Sends the given text on a channel.  Most channels do not support the\n"
448 " transmission of text.  Returns 0 if text is sent, or if the channel does not\n"
449 " support text transmission.  Returns -1 only on error/hangup.  Text\n"
450 " consisting of greater than one word should be placed in quotes since the\n"
451 " command only accepts a single argument.\n";
452
453 static char usage_sendimage[] =
454 " Usage: SEND IMAGE <image>\n"
455 "        Sends the given image on a channel.  Most channels do not support the\n"
456 " transmission of images.  Returns 0 if image is sent, or if the channel does not\n"
457 " support image transmission.  Returns -1 only on error/hangup.  Image names\n"
458 " should not include extensions.\n";
459
460 static char usage_streamfile[] =
461 " Usage: STREAM FILE <filename> <escape digits>\n"
462 "        Send the given file, allowing playback to be interrupted by the given\n"
463 " digits, if any.  Use double quotes for the digits if you wish none to be\n"
464 " permitted.  Returns 0 if playback completes without a digit being pressed, or\n"
465 " the ASCII numerical value of the digit if one was pressed, or -1 on error or\n"
466 " if the channel was disconnected.  Remember, the file extension must not be\n"
467 " included in the filename.\n";
468
469 static char usage_saynumber[] =
470 " Usage: SAY NUMBER <number> <escape digits>\n"
471 "        Say a given number, returning early if any of the given DTMF digits\n"
472 " are received on the channel.  Returns 0 if playback completes without a digit\n"
473 " being pressed, or the ASCII numerical value of the digit if one was pressed or\n"
474 " -1 on error/hangup.\n";
475
476 static char usage_getdata[] =
477 " Usage: GET DATA <file to be streamed> [timeout] [max digits]\n"
478 "        Stream the given file, and recieve DTMF data. Returns the digits recieved\n"
479 "from the channel at the other end.\n";
480
481 static char usage_setcontext[] =
482 " Usage: SET CONTEXT <desired context>\n"
483 "        Sets the context for continuation upon exiting the application.\n";
484
485 static char usage_setextension[] =
486 " Usage: SET EXTENSION <new extension>\n"
487 "        Changes the extension for continuation upon exiting the application.\n";
488
489 static char usage_setpriority[] =
490 " Usage: SET PRIORITY <num>\n"
491 "        Changes the priority for continuation upon exiting the application.\n";
492
493 static char usage_recordfile[] =
494 " Usage: RECORD FILE <filename> <format> <escape digits> <timeout> [BEEP]\n"
495 "        Record to a file until a given dtmf digit in the sequence is received\n"
496 " Returns -1 on hangup or error.  The format will specify what kind of file\n"
497 " will be recorded.  The timeout is the maximum record time in milliseconds, or\n"
498 " -1 for no timeout\n";
499
500 agi_command commands[] = {
501         { { "wait", "for", "digit", NULL }, handle_waitfordigit, "Waits for a digit to be pressed", usage_waitfordigit },
502         { { "send", "text", NULL }, handle_sendtext, "Sends text to channels supporting it", usage_sendtext },
503         { { "stream", "file", NULL }, handle_streamfile, "Sends audio file on channel", usage_streamfile },
504         { { "send", "image", NULL }, handle_sendimage, "Sends images to channels supporting it", usage_sendimage },
505         { { "say", "number", NULL }, handle_saynumber, "Says a given number", usage_saynumber },
506         { { "get", "data", NULL }, handle_getdata, "Gets data on a channel", usage_getdata },
507         { { "set", "context", NULL }, handle_setcontext, "Sets channel context", usage_setcontext },
508         { { "set", "extension", NULL }, handle_setextension, "Changes channel extension", usage_setextension },
509         { { "set", "priority", NULL }, handle_setpriority, "Prioritizes the channel", usage_setpriority },
510         { { "record", "file", NULL }, handle_recordfile, "Records to a given file", usage_recordfile }
511 };
512
513 static agi_command *find_command(char *cmds[])
514 {
515         int x;
516         int y;
517         int match;
518         for (x=0;x < sizeof(commands) / sizeof(commands[0]);x++) {
519                 /* start optimistic */
520                 match = 1;
521                 for (y=0;match && cmds[y]; y++) {
522                         /* If there are no more words in the command (and we're looking for
523                            an exact match) or there is a difference between the two words,
524                            then this is not a match */
525                         if (!commands[x].cmda[y])
526                                 break;
527                         if (strcasecmp(commands[x].cmda[y], cmds[y]))
528                                 match = 0;
529                 }
530                 /* If more words are needed to complete the command then this is not
531                    a candidate (unless we're looking for a really inexact answer  */
532                 if (commands[x].cmda[y])
533                         match = 0;
534                 if (match)
535                         return &commands[x];
536         }
537         return NULL;
538 }
539
540
541 static int parse_args(char *s, int *max, char *argv[])
542 {
543         int x=0;
544         int quoted=0;
545         int escaped=0;
546         int whitespace=1;
547         char *cur;
548
549         cur = s;
550         while(*s) {
551                 switch(*s) {
552                 case '"':
553                         /* If it's escaped, put a literal quote */
554                         if (escaped) 
555                                 goto normal;
556                         else 
557                                 quoted = !quoted;
558                         if (quoted && whitespace) {
559                                 /* If we're starting a quote, coming off white space start a new word, too */
560                                 argv[x++] = cur;
561                                 whitespace=0;
562                         }
563                         escaped = 0;
564                 break;
565                 case ' ':
566                 case '\t':
567                         if (!quoted && !escaped) {
568                                 /* If we're not quoted, mark this as whitespace, and
569                                    end the previous argument */
570                                 whitespace = 1;
571                                 *(cur++) = '\0';
572                         } else
573                                 /* Otherwise, just treat it as anything else */ 
574                                 goto normal;
575                         break;
576                 case '\\':
577                         /* If we're escaped, print a literal, otherwise enable escaping */
578                         if (escaped) {
579                                 goto normal;
580                         } else {
581                                 escaped=1;
582                         }
583                         break;
584                 default:
585 normal:
586                         if (whitespace) {
587                                 if (x >= MAX_ARGS -1) {
588                                         ast_log(LOG_WARNING, "Too many arguments, truncating\n");
589                                         break;
590                                 }
591                                 /* Coming off of whitespace, start the next argument */
592                                 argv[x++] = cur;
593                                 whitespace=0;
594                         }
595                         *(cur++) = *s;
596                         escaped=0;
597                 }
598                 s++;
599         }
600         /* Null terminate */
601         *(cur++) = '\0';
602         argv[x] = NULL;
603         *max = x;
604         return 0;
605 }
606
607 static int agi_handle_command(struct ast_channel *chan, int fd, char *buf)
608 {
609         char *argv[MAX_ARGS];
610         int argc = 0;
611         int res;
612         agi_command *c;
613         argc = MAX_ARGS;
614         parse_args(buf, &argc, argv);
615 #if     0
616         { int x;
617         for (x=0;x<argc;x++) 
618                 fprintf(stderr, "Got Arg%d: %s\n", x, argv[x]); }
619 #endif
620         c = find_command(argv);
621         if (c) {
622                 res = c->handler(chan, fd, argc, argv);
623                 switch(res) {
624                 case RESULT_SHOWUSAGE:
625                         fdprintf(fd, "520-Invalid command syntax.  Proper usage follows:\n");
626                         fdprintf(fd, c->usage);
627                         fdprintf(fd, "520 End of proper usage.\n");
628                         break;
629                 case RESULT_FAILURE:
630                         /* They've already given the failure.  We've been hung up on so handle this
631                            appropriately */
632                         return -1;
633                 }
634         } else {
635                 fdprintf(fd, "510 Invalid or unknown command\n");
636         }
637         return 0;
638 }
639
640 static int run_agi(struct ast_channel *chan, char *request, int *fds, int pid)
641 {
642         struct ast_channel *c;
643         int outfd;
644         int ms;
645         int returnstatus = 0;
646         struct ast_frame *f;
647         char buf[2048];
648         FILE *readf;
649         if (!(readf = fdopen(fds[0], "r"))) {
650                 ast_log(LOG_WARNING, "Unable to fdopen file descriptor\n");
651                 kill(pid, SIGHUP);
652                 return -1;
653         }
654         setlinebuf(readf);
655         setup_env(chan, request, fds[1]);
656         for (;;) {
657                 ms = -1;
658                 c = ast_waitfor_nandfds(&chan, 1, &fds[0], 1, NULL, &outfd, &ms);
659                 if (c) {
660                         /* Idle the channel until we get a command */
661                         f = ast_read(c);
662                         if (!f) {
663                                 ast_log(LOG_DEBUG, "%s hungup\n", chan->name);
664                                 returnstatus = -1;
665                                 break;
666                         } else {
667                                 ast_frfree(f);
668                         }
669                 } else if (outfd > -1) {
670                         if (!fgets(buf, sizeof(buf), readf)) {
671                                 /* Program terminated */
672                                 if (returnstatus)
673                                         returnstatus = -1;
674                                 if (option_verbose > 2) 
675                                         ast_verbose(VERBOSE_PREFIX_3 "AGI Script %s completed, returning %d\n", request, returnstatus);
676                                 /* No need to kill the pid anymore, since they closed us */
677                                 pid = -1;
678                                 break;
679                         }
680                         returnstatus |= agi_handle_command(chan, fds[1], buf);
681                         /* If the handle_command returns -1, we need to stop */
682                         if (returnstatus < 0) {
683                                 break;
684                         }
685                 } else {
686                         ast_log(LOG_WARNING, "No channel, no fd?\n");
687                         returnstatus = -1;
688                         break;
689                 }
690         }
691         /* Notify process */
692         if (pid > -1)
693                 kill(pid, SIGHUP);
694         fclose(readf);
695         return returnstatus;
696 }
697
698 static int agi_exec(struct ast_channel *chan, void *data)
699 {
700         int res=0;
701         struct localuser *u;
702         char *args,*ringy;
703         char tmp[256];
704         int fds[2];
705         int pid;
706         if (!data || !strlen(data)) {
707                 ast_log(LOG_WARNING, "AGI requires an argument (script)\n");
708                 return -1;
709         }
710
711
712         strncpy(tmp, data, sizeof(tmp));
713         strtok(tmp, "|");
714         args = strtok(NULL, "|");
715         ringy = strtok(NULL,"|");
716         if (!args)
717                 args = "";
718         LOCAL_USER_ADD(u);
719          /* Answer if need be */
720         if (chan->state != AST_STATE_UP) {
721                 if (ringy) { /* if for ringing first */
722                         /* a little ringy-dingy first */
723                         ast_indicate(chan, AST_CONTROL_RINGING);  
724                         sleep(3); 
725                 }
726                 if (ast_answer(chan)) {
727                         LOCAL_USER_REMOVE(u);
728                         return -1;
729                 }
730         }
731         res = launch_script(tmp, args, fds, &pid);
732         if (!res) {
733                 res = run_agi(chan, tmp, fds, pid);
734                 close(fds[0]);
735                 close(fds[1]);
736         }
737         LOCAL_USER_REMOVE(u);
738         return res;
739 }
740
741 int unload_module(void)
742 {
743         STANDARD_HANGUP_LOCALUSERS;
744         return ast_unregister_application(app);
745 }
746
747 int load_module(void)
748 {
749         return ast_register_application(app, agi_exec, synopsis, descrip);
750 }
751
752 char *description(void)
753 {
754         return tdesc;
755 }
756
757 int usecount(void)
758 {
759         int res;
760         STANDARD_USECOUNT(res);
761         return res;
762 }
763
764 char *key()
765 {
766         return ASTERISK_GPL_KEY;
767 }
768
769 #define CLIP 32635
770 #define BIAS 0x84
771
772 unsigned char
773 linear2ulaw(sample)
774 short sample; {
775   static int exp_lut[256] = {0,0,1,1,2,2,2,2,3,3,3,3,3,3,3,3,
776                              4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,4,
777                              5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
778                              5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,5,
779                              6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
780                              6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
781                              6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
782                              6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,6,
783                              7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
784                              7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
785                              7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
786                              7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
787                              7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
788                              7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
789                              7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,
790                              7,7,7,7,7,7,7,7,7,7,7,7,7,7,7,7};
791   int sign, exponent, mantissa;
792   unsigned char ulawbyte;
793  
794   /* Get the sample into sign-magnitude. */
795   sign = (sample >> 8) & 0x80;          /* set aside the sign */
796   if (sign != 0) sample = -sample;              /* get magnitude */
797   if (sample > CLIP) sample = CLIP;             /* clip the magnitude */
798  
799   /* Convert from 16 bit linear to ulaw. */
800   sample = sample + BIAS;
801   exponent = exp_lut[(sample >> 7) & 0xFF];
802   mantissa = (sample >> (exponent + 3)) & 0x0F;
803   ulawbyte = ~(sign | (exponent << 4) | mantissa);
804 #ifdef ZEROTRAP
805   if (ulawbyte == 0) ulawbyte = 0x02;   /* optional CCITT trap */
806 #endif
807  
808   return(ulawbyte);
809 }