Merged revisions 172438 via svnmerge from
[asterisk/asterisk.git] / main / app.c
1 /*
2  * Asterisk -- An open source telephony toolkit.
3  *
4  * Copyright (C) 1999 - 2005, Digium, Inc.
5  *
6  * Mark Spencer <markster@digium.com>
7  *
8  * See http://www.asterisk.org for more information about
9  * the Asterisk project. Please do not directly contact
10  * any of the maintainers of this project for assistance;
11  * the project provides a web site, mailing lists and IRC
12  * channels for your use.
13  *
14  * This program is free software, distributed under the terms of
15  * the GNU General Public License Version 2. See the LICENSE file
16  * at the top of the source tree.
17  */
18
19 /*! \file
20  *
21  * \brief Convenient Application Routines
22  *
23  * \author Mark Spencer <markster@digium.com> 
24  */
25
26 #include "asterisk.h"
27
28 ASTERISK_FILE_VERSION(__FILE__, "$Revision$")
29
30 #ifdef HAVE_SYS_STAT_H
31 #include <sys/stat.h>
32 #endif
33 #include <regex.h>
34 #include <sys/file.h> /* added this to allow to compile, sorry! */
35 #include <signal.h>
36 #include <sys/time.h>       /* for getrlimit(2) */
37 #include <sys/resource.h>   /* for getrlimit(2) */
38 #include <stdlib.h>         /* for closefrom(3) */
39 #ifdef HAVE_CAP
40 #include <sys/capability.h>
41 #endif /* HAVE_CAP */
42
43 #include "asterisk/paths.h"     /* use ast_config_AST_DATA_DIR */
44 #include "asterisk/channel.h"
45 #include "asterisk/pbx.h"
46 #include "asterisk/file.h"
47 #include "asterisk/app.h"
48 #include "asterisk/dsp.h"
49 #include "asterisk/utils.h"
50 #include "asterisk/lock.h"
51 #include "asterisk/indications.h"
52 #include "asterisk/linkedlists.h"
53 #include "asterisk/threadstorage.h"
54
55 AST_THREADSTORAGE_PUBLIC(global_app_buf);
56
57
58 #define MAX_OTHER_FORMATS 10
59
60 static AST_RWLIST_HEAD_STATIC(groups, ast_group_info);
61
62 /*!
63  * \brief This function presents a dialtone and reads an extension into 'collect' 
64  * which must be a pointer to a **pre-initialized** array of char having a 
65  * size of 'size' suitable for writing to.  It will collect no more than the smaller 
66  * of 'maxlen' or 'size' minus the original strlen() of collect digits.
67  * \param chan struct.
68  * \param context 
69  * \param collect 
70  * \param size 
71  * \param maxlen
72  * \param timeout timeout in seconds
73  *
74  * \return 0 if extension does not exist, 1 if extension exists
75 */
76 int ast_app_dtget(struct ast_channel *chan, const char *context, char *collect, size_t size, int maxlen, int timeout) 
77 {
78         struct tone_zone_sound *ts;
79         int res = 0, x = 0;
80
81         if (maxlen > size)
82                 maxlen = size;
83         
84         if (!timeout && chan->pbx)
85                 timeout = chan->pbx->dtimeoutms / 1000.0;
86         else if (!timeout)
87                 timeout = 5;
88
89         if ((ts = ast_get_indication_tone(chan->zone, "dial")) && ts->data[0])
90                 res = ast_playtones_start(chan, 0, ts->data, 0);
91         else 
92                 ast_log(LOG_NOTICE, "Huh....? no dial for indications?\n");
93         
94         for (x = strlen(collect); x < maxlen; ) {
95                 res = ast_waitfordigit(chan, timeout);
96                 if (!ast_ignore_pattern(context, collect))
97                         ast_playtones_stop(chan);
98                 if (res < 1)
99                         break;
100                 if (res == '#')
101                         break;
102                 collect[x++] = res;
103                 if (!ast_matchmore_extension(chan, context, collect, 1, chan->cid.cid_num))
104                         break;
105         }
106
107         if (res >= 0)
108                 res = ast_exists_extension(chan, context, collect, 1, chan->cid.cid_num) ? 1 : 0;
109
110         return res;
111 }
112
113 /*!
114  * \brief ast_app_getdata
115  * \param c The channel to read from
116  * \param prompt The file to stream to the channel
117  * \param s The string to read in to.  Must be at least the size of your length
118  * \param maxlen How many digits to read (maximum)
119  * \param timeout set timeout to 0 for "standard" timeouts. Set timeout to -1 for 
120  *      "ludicrous time" (essentially never times out) */
121 int ast_app_getdata(struct ast_channel *c, const char *prompt, char *s, int maxlen, int timeout)
122 {
123         int res = 0, to, fto;
124         char *front, *filename;
125
126         /* XXX Merge with full version? XXX */
127         
128         if (maxlen)
129                 s[0] = '\0';
130
131         if (!prompt)
132                 prompt = "";
133
134         filename = ast_strdupa(prompt);
135         while ((front = strsep(&filename, "&"))) {
136                 if (!ast_strlen_zero(front)) {
137                         res = ast_streamfile(c, front, c->language);
138                         if (res)
139                                 continue;
140                 }
141                 if (ast_strlen_zero(filename)) {
142                         /* set timeouts for the last prompt */
143                         fto = c->pbx ? c->pbx->rtimeoutms : 6000;
144                         to = c->pbx ? c->pbx->dtimeoutms : 2000;
145
146                         if (timeout > 0) 
147                                 fto = to = timeout;
148                         if (timeout < 0) 
149                                 fto = to = 1000000000;
150                 } else {
151                         /* there is more than one prompt, so
152                            get rid of the long timeout between 
153                            prompts, and make it 50ms */
154                         fto = 50;
155                         to = c->pbx ? c->pbx->dtimeoutms : 2000;
156                 }
157                 res = ast_readstring(c, s, maxlen, to, fto, "#");
158                 if (!ast_strlen_zero(s))
159                         return res;
160         }
161         
162         return res;
163 }
164
165 /* The lock type used by ast_lock_path() / ast_unlock_path() */
166 static enum AST_LOCK_TYPE ast_lock_type = AST_LOCK_TYPE_LOCKFILE;
167
168 int ast_app_getdata_full(struct ast_channel *c, char *prompt, char *s, int maxlen, int timeout, int audiofd, int ctrlfd)
169 {
170         int res, to = 2000, fto = 6000;
171
172         if (!ast_strlen_zero(prompt)) {
173                 res = ast_streamfile(c, prompt, c->language);
174                 if (res < 0)
175                         return res;
176         }
177         
178         if (timeout > 0) 
179                 fto = to = timeout;
180         if (timeout < 0) 
181                 fto = to = 1000000000;
182
183         res = ast_readstring_full(c, s, maxlen, to, fto, "#", audiofd, ctrlfd);
184
185         return res;
186 }
187
188 static int (*ast_has_voicemail_func)(const char *mailbox, const char *folder) = NULL;
189 static int (*ast_inboxcount_func)(const char *mailbox, int *newmsgs, int *oldmsgs) = NULL;
190 static int (*ast_inboxcount2_func)(const char *mailbox, int *urgentmsgs, int *newmsgs, int *oldmsgs) = NULL;
191 static int (*ast_sayname_func)(struct ast_channel *chan, const char *mailbox, const char *context) = NULL;
192 static int (*ast_messagecount_func)(const char *context, const char *mailbox, const char *folder) = NULL;
193
194 void ast_install_vm_functions(int (*has_voicemail_func)(const char *mailbox, const char *folder),
195                               int (*inboxcount_func)(const char *mailbox, int *newmsgs, int *oldmsgs),
196                               int (*inboxcount2_func)(const char *mailbox, int *urgentmsgs, int *newmsgs, int *oldmsgs),
197                               int (*messagecount_func)(const char *context, const char *mailbox, const char *folder),
198                               int (*sayname_func)(struct ast_channel *chan, const char *mailbox, const char *context))
199 {
200         ast_has_voicemail_func = has_voicemail_func;
201         ast_inboxcount_func = inboxcount_func;
202         ast_inboxcount2_func = inboxcount2_func;
203         ast_messagecount_func = messagecount_func;
204         ast_sayname_func = sayname_func;
205 }
206
207 void ast_uninstall_vm_functions(void)
208 {
209         ast_has_voicemail_func = NULL;
210         ast_inboxcount_func = NULL;
211         ast_inboxcount2_func = NULL;
212         ast_messagecount_func = NULL;
213         ast_sayname_func = NULL;
214 }
215
216 int ast_app_has_voicemail(const char *mailbox, const char *folder)
217 {
218         static int warned = 0;
219         if (ast_has_voicemail_func)
220                 return ast_has_voicemail_func(mailbox, folder);
221
222         if (!warned) {
223                 ast_verb(3, "Message check requested for mailbox %s/folder %s but voicemail not loaded.\n", mailbox, folder ? folder : "INBOX");
224                 warned++;
225         }
226         return 0;
227 }
228
229
230 int ast_app_inboxcount(const char *mailbox, int *newmsgs, int *oldmsgs)
231 {
232         static int warned = 0;
233         if (newmsgs) {
234                 *newmsgs = 0;
235         }
236         if (oldmsgs) {
237                 *oldmsgs = 0;
238         }
239         if (ast_inboxcount_func) {
240                 return ast_inboxcount_func(mailbox, newmsgs, oldmsgs);
241         }
242
243         if (!warned) {
244                 warned++;
245                 ast_verb(3, "Message count requested for mailbox %s but voicemail not loaded.\n", mailbox);
246         }
247
248         return 0;
249 }
250
251 int ast_app_inboxcount2(const char *mailbox, int *urgentmsgs, int *newmsgs, int *oldmsgs)
252 {
253         static int warned = 0;
254         if (newmsgs) {
255                 *newmsgs = 0;
256         }
257         if (oldmsgs) {
258                 *oldmsgs = 0;
259         }
260         if (urgentmsgs) {
261                 *urgentmsgs = 0;
262         }
263         if (ast_inboxcount_func) {
264                 return ast_inboxcount2_func(mailbox, urgentmsgs, newmsgs, oldmsgs);
265         }
266
267         if (!warned) {
268                 warned++;
269                 ast_verb(3, "Message count requested for mailbox %s but voicemail not loaded.\n", mailbox);
270         }
271
272         return 0;
273 }
274
275 int ast_app_sayname(struct ast_channel *chan, const char *mailbox, const char *context)
276 {
277         if (ast_sayname_func)
278                 return ast_sayname_func(chan, mailbox, context);
279         return -1;
280 }
281
282 int ast_app_messagecount(const char *context, const char *mailbox, const char *folder)
283 {
284         static int warned = 0;
285         if (ast_messagecount_func)
286                 return ast_messagecount_func(context, mailbox, folder);
287
288         if (!warned) {
289                 warned++;
290                 ast_verb(3, "Message count requested for mailbox %s@%s/%s but voicemail not loaded.\n", mailbox, context, folder);
291         }
292
293         return 0;
294 }
295
296 int ast_dtmf_stream(struct ast_channel *chan, struct ast_channel *peer, const char *digits, int between, unsigned int duration) 
297 {
298         const char *ptr;
299         int res = 0;
300         struct ast_silence_generator *silgen = NULL;
301
302         if (!between)
303                 between = 100;
304
305         if (peer)
306                 res = ast_autoservice_start(peer);
307
308         if (!res)
309                 res = ast_waitfor(chan, 100);
310
311         /* ast_waitfor will return the number of remaining ms on success */
312         if (res < 0) {
313                 if (peer) {
314                         ast_autoservice_stop(peer);
315                 }
316                 return res;
317         }
318
319         if (ast_opt_transmit_silence) {
320                 silgen = ast_channel_start_silence_generator(chan);
321         }
322
323         for (ptr = digits; *ptr; ptr++) {
324                 if (*ptr == 'w') {
325                         /* 'w' -- wait half a second */
326                         if ((res = ast_safe_sleep(chan, 500)))
327                                 break;
328                 } else if (strchr("0123456789*#abcdfABCDF", *ptr)) {
329                         /* Character represents valid DTMF */
330                         if (*ptr == 'f' || *ptr == 'F') {
331                                 /* ignore return values if not supported by channel */
332                                 ast_indicate(chan, AST_CONTROL_FLASH);
333                         } else
334                                 ast_senddigit(chan, *ptr, duration);
335                         /* pause between digits */
336                         if ((res = ast_safe_sleep(chan, between)))
337                                 break;
338                 } else
339                         ast_log(LOG_WARNING, "Illegal DTMF character '%c' in string. (0-9*#aAbBcCdD allowed)\n", *ptr);
340         }
341
342         if (peer) {
343                 /* Stop autoservice on the peer channel, but don't overwrite any error condition 
344                    that has occurred previously while acting on the primary channel */
345                 if (ast_autoservice_stop(peer) && !res)
346                         res = -1;
347         }
348
349         if (silgen) {
350                 ast_channel_stop_silence_generator(chan, silgen);
351         }
352
353         return res;
354 }
355
356 struct linear_state {
357         int fd;
358         int autoclose;
359         int allowoverride;
360         int origwfmt;
361 };
362
363 static void linear_release(struct ast_channel *chan, void *params)
364 {
365         struct linear_state *ls = params;
366         
367         if (ls->origwfmt && ast_set_write_format(chan, ls->origwfmt))
368                 ast_log(LOG_WARNING, "Unable to restore channel '%s' to format '%d'\n", chan->name, ls->origwfmt);
369
370         if (ls->autoclose)
371                 close(ls->fd);
372
373         ast_free(params);
374 }
375
376 static int linear_generator(struct ast_channel *chan, void *data, int len, int samples)
377 {
378         short buf[2048 + AST_FRIENDLY_OFFSET / 2];
379         struct linear_state *ls = data;
380         struct ast_frame f = {
381                 .frametype = AST_FRAME_VOICE,
382                 .subclass = AST_FORMAT_SLINEAR,
383                 .data.ptr = buf + AST_FRIENDLY_OFFSET / 2,
384                 .offset = AST_FRIENDLY_OFFSET,
385         };
386         int res;
387
388         len = samples * 2;
389         if (len > sizeof(buf) - AST_FRIENDLY_OFFSET) {
390                 ast_log(LOG_WARNING, "Can't generate %d bytes of data!\n" , len);
391                 len = sizeof(buf) - AST_FRIENDLY_OFFSET;
392         }
393         res = read(ls->fd, buf + AST_FRIENDLY_OFFSET/2, len);
394         if (res > 0) {
395                 f.datalen = res;
396                 f.samples = res / 2;
397                 ast_write(chan, &f);
398                 if (res == len)
399                         return 0;
400         }
401         return -1;
402 }
403
404 static void *linear_alloc(struct ast_channel *chan, void *params)
405 {
406         struct linear_state *ls = params;
407
408         if (!params)
409                 return NULL;
410
411         /* In this case, params is already malloc'd */
412         if (ls->allowoverride)
413                 ast_set_flag(chan, AST_FLAG_WRITE_INT);
414         else
415                 ast_clear_flag(chan, AST_FLAG_WRITE_INT);
416
417         ls->origwfmt = chan->writeformat;
418
419         if (ast_set_write_format(chan, AST_FORMAT_SLINEAR)) {
420                 ast_log(LOG_WARNING, "Unable to set '%s' to linear format (write)\n", chan->name);
421                 ast_free(ls);
422                 ls = params = NULL;
423         }
424
425         return params;
426 }
427
428 static struct ast_generator linearstream = 
429 {
430         alloc: linear_alloc,
431         release: linear_release,
432         generate: linear_generator,
433 };
434
435 int ast_linear_stream(struct ast_channel *chan, const char *filename, int fd, int allowoverride)
436 {
437         struct linear_state *lin;
438         char tmpf[256];
439         int res = -1;
440         int autoclose = 0;
441         if (fd < 0) {
442                 if (ast_strlen_zero(filename))
443                         return -1;
444                 autoclose = 1;
445                 if (filename[0] == '/') 
446                         ast_copy_string(tmpf, filename, sizeof(tmpf));
447                 else
448                         snprintf(tmpf, sizeof(tmpf), "%s/%s/%s", ast_config_AST_DATA_DIR, "sounds", filename);
449                 if ((fd = open(tmpf, O_RDONLY)) < 0) {
450                         ast_log(LOG_WARNING, "Unable to open file '%s': %s\n", tmpf, strerror(errno));
451                         return -1;
452                 }
453         }
454         if ((lin = ast_calloc(1, sizeof(*lin)))) {
455                 lin->fd = fd;
456                 lin->allowoverride = allowoverride;
457                 lin->autoclose = autoclose;
458                 res = ast_activate_generator(chan, &linearstream, lin);
459         }
460         return res;
461 }
462
463 int ast_control_streamfile(struct ast_channel *chan, const char *file,
464                            const char *fwd, const char *rev,
465                            const char *stop, const char *suspend,
466                            const char *restart, int skipms, long *offsetms) 
467 {
468         char *breaks = NULL;
469         char *end = NULL;
470         int blen = 2;
471         int res;
472         long pause_restart_point = 0;
473         long offset = 0;
474
475         if (offsetms) 
476                 offset = *offsetms * 8; /* XXX Assumes 8kHz */
477
478         if (stop)
479                 blen += strlen(stop);
480         if (suspend)
481                 blen += strlen(suspend);
482         if (restart)
483                 blen += strlen(restart);
484
485         if (blen > 2) {
486                 breaks = alloca(blen + 1);
487                 breaks[0] = '\0';
488                 if (stop)
489                         strcat(breaks, stop);
490                 if (suspend)
491                         strcat(breaks, suspend);
492                 if (restart)
493                         strcat(breaks, restart);
494         }
495         if (chan->_state != AST_STATE_UP)
496                 res = ast_answer(chan);
497
498         if (file) {
499                 if ((end = strchr(file, ':'))) {
500                         if (!strcasecmp(end, ":end")) {
501                                 *end = '\0';
502                                 end++;
503                         }
504                 }
505         }
506
507         for (;;) {
508                 ast_stopstream(chan);
509                 res = ast_streamfile(chan, file, chan->language);
510                 if (!res) {
511                         if (pause_restart_point) {
512                                 ast_seekstream(chan->stream, pause_restart_point, SEEK_SET);
513                                 pause_restart_point = 0;
514                         }
515                         else if (end || offset < 0) {
516                                 if (offset == -8) 
517                                         offset = 0;
518                                 ast_verb(3, "ControlPlayback seek to offset %ld from end\n", offset);
519
520                                 ast_seekstream(chan->stream, offset, SEEK_END);
521                                 end = NULL;
522                                 offset = 0;
523                         } else if (offset) {
524                                 ast_verb(3, "ControlPlayback seek to offset %ld\n", offset);
525                                 ast_seekstream(chan->stream, offset, SEEK_SET);
526                                 offset = 0;
527                         };
528                         res = ast_waitstream_fr(chan, breaks, fwd, rev, skipms);
529                 }
530
531                 if (res < 1)
532                         break;
533
534                 /* We go at next loop if we got the restart char */
535                 if (restart && strchr(restart, res)) {
536                         ast_debug(1, "we'll restart the stream here at next loop\n");
537                         pause_restart_point = 0;
538                         continue;
539                 }
540
541                 if (suspend && strchr(suspend, res)) {
542                         pause_restart_point = ast_tellstream(chan->stream);
543                         for (;;) {
544                                 ast_stopstream(chan);
545                                 res = ast_waitfordigit(chan, 1000);
546                                 if (!res)
547                                         continue;
548                                 else if (res == -1 || strchr(suspend, res) || (stop && strchr(stop, res)))
549                                         break;
550                         }
551                         if (res == *suspend) {
552                                 res = 0;
553                                 continue;
554                         }
555                 }
556
557                 if (res == -1)
558                         break;
559
560                 /* if we get one of our stop chars, return it to the calling function */
561                 if (stop && strchr(stop, res))
562                         break;
563         }
564
565         if (pause_restart_point) {
566                 offset = pause_restart_point;
567         } else {
568                 if (chan->stream) {
569                         offset = ast_tellstream(chan->stream);
570                 } else {
571                         offset = -8;  /* indicate end of file */
572                 }
573         }
574
575         if (offsetms) 
576                 *offsetms = offset / 8; /* samples --> ms ... XXX Assumes 8 kHz */
577
578         /* If we are returning a digit cast it as char */
579         if (res > 0 || chan->stream)
580                 res = (char)res;
581
582         ast_stopstream(chan);
583
584         return res;
585 }
586
587 int ast_play_and_wait(struct ast_channel *chan, const char *fn)
588 {
589         int d = 0;
590
591         if ((d = ast_streamfile(chan, fn, chan->language)))
592                 return d;
593
594         d = ast_waitstream(chan, AST_DIGIT_ANY);
595
596         ast_stopstream(chan);
597
598         return d;
599 }
600
601 static int global_silence_threshold = 128;
602 static int global_maxsilence = 0;
603
604 /*! Optionally play a sound file or a beep, then record audio and video from the channel.
605  * \param chan Channel to playback to/record from.
606  * \param playfile Filename of sound to play before recording begins.
607  * \param recordfile Filename to record to.
608  * \param maxtime Maximum length of recording (in milliseconds).
609  * \param fmt Format(s) to record message in. Multiple formats may be specified by separating them with a '|'.
610  * \param duration Where to store actual length of the recorded message (in milliseconds).
611  * \param beep Whether to play a beep before starting to record.
612  * \param silencethreshold 
613  * \param maxsilence Length of silence that will end a recording (in milliseconds).
614  * \param path Optional filesystem path to unlock.
615  * \param prepend If true, prepend the recorded audio to an existing file.
616  * \param acceptdtmf DTMF digits that will end the recording.
617  * \param canceldtmf DTMF digits that will cancel the recording.
618  */
619
620 static int __ast_play_and_record(struct ast_channel *chan, const char *playfile, const char *recordfile, int maxtime, const char *fmt, int *duration, int beep, int silencethreshold, int maxsilence, const char *path, int prepend, const char *acceptdtmf, const char *canceldtmf)
621 {
622         int d = 0;
623         char *fmts;
624         char comment[256];
625         int x, fmtcnt = 1, res = -1, outmsg = 0;
626         struct ast_filestream *others[MAX_OTHER_FORMATS];
627         char *sfmt[MAX_OTHER_FORMATS];
628         char *stringp = NULL;
629         time_t start, end;
630         struct ast_dsp *sildet = NULL;   /* silence detector dsp */
631         int totalsilence = 0;
632         int rfmt = 0;
633         struct ast_silence_generator *silgen = NULL;
634         char prependfile[80];
635
636         if (silencethreshold < 0)
637                 silencethreshold = global_silence_threshold;
638
639         if (maxsilence < 0)
640                 maxsilence = global_maxsilence;
641
642         /* barf if no pointer passed to store duration in */
643         if (!duration) {
644                 ast_log(LOG_WARNING, "Error play_and_record called without duration pointer\n");
645                 return -1;
646         }
647
648         ast_debug(1, "play_and_record: %s, %s, '%s'\n", playfile ? playfile : "<None>", recordfile, fmt);
649         snprintf(comment, sizeof(comment), "Playing %s, Recording to: %s on %s\n", playfile ? playfile : "<None>", recordfile, chan->name);
650
651         if (playfile || beep) {
652                 if (!beep)
653                         d = ast_play_and_wait(chan, playfile);
654                 if (d > -1)
655                         d = ast_stream_and_wait(chan, "beep", "");
656                 if (d < 0)
657                         return -1;
658         }
659
660         if (prepend) {
661                 ast_copy_string(prependfile, recordfile, sizeof(prependfile));  
662                 strncat(prependfile, "-prepend", sizeof(prependfile) - strlen(prependfile) - 1);
663         }
664
665         fmts = ast_strdupa(fmt);
666
667         stringp = fmts;
668         strsep(&stringp, "|");
669         ast_debug(1, "Recording Formats: sfmts=%s\n", fmts);
670         sfmt[0] = ast_strdupa(fmts);
671
672         while ((fmt = strsep(&stringp, "|"))) {
673                 if (fmtcnt > MAX_OTHER_FORMATS - 1) {
674                         ast_log(LOG_WARNING, "Please increase MAX_OTHER_FORMATS in app.c\n");
675                         break;
676                 }
677                 sfmt[fmtcnt++] = ast_strdupa(fmt);
678         }
679
680         end = start = time(NULL);  /* pre-initialize end to be same as start in case we never get into loop */
681         for (x = 0; x < fmtcnt; x++) {
682                 others[x] = ast_writefile(prepend ? prependfile : recordfile, sfmt[x], comment, O_TRUNC, 0, AST_FILE_MODE);
683                 ast_verb(3, "x=%d, open writing:  %s format: %s, %p\n", x, prepend ? prependfile : recordfile, sfmt[x], others[x]);
684
685                 if (!others[x])
686                         break;
687         }
688
689         if (path)
690                 ast_unlock_path(path);
691
692         if (maxsilence > 0) {
693                 sildet = ast_dsp_new(); /* Create the silence detector */
694                 if (!sildet) {
695                         ast_log(LOG_WARNING, "Unable to create silence detector :(\n");
696                         return -1;
697                 }
698                 ast_dsp_set_threshold(sildet, silencethreshold);
699                 rfmt = chan->readformat;
700                 res = ast_set_read_format(chan, AST_FORMAT_SLINEAR);
701                 if (res < 0) {
702                         ast_log(LOG_WARNING, "Unable to set to linear mode, giving up\n");
703                         ast_dsp_free(sildet);
704                         return -1;
705                 }
706         }
707
708         if (!prepend) {
709                 /* Request a video update */
710                 ast_indicate(chan, AST_CONTROL_VIDUPDATE);
711
712                 if (ast_opt_transmit_silence)
713                         silgen = ast_channel_start_silence_generator(chan);
714         }
715
716         if (x == fmtcnt) {
717                 /* Loop forever, writing the packets we read to the writer(s), until
718                    we read a digit or get a hangup */
719                 struct ast_frame *f;
720                 for (;;) {
721                         res = ast_waitfor(chan, 2000);
722                         if (!res) {
723                                 ast_debug(1, "One waitfor failed, trying another\n");
724                                 /* Try one more time in case of masq */
725                                 res = ast_waitfor(chan, 2000);
726                                 if (!res) {
727                                         ast_log(LOG_WARNING, "No audio available on %s??\n", chan->name);
728                                         res = -1;
729                                 }
730                         }
731
732                         if (res < 0) {
733                                 f = NULL;
734                                 break;
735                         }
736                         f = ast_read(chan);
737                         if (!f)
738                                 break;
739                         if (f->frametype == AST_FRAME_VOICE) {
740                                 /* write each format */
741                                 for (x = 0; x < fmtcnt; x++) {
742                                         if (prepend && !others[x])
743                                                 break;
744                                         res = ast_writestream(others[x], f);
745                                 }
746
747                                 /* Silence Detection */
748                                 if (maxsilence > 0) {
749                                         int dspsilence = 0;
750                                         ast_dsp_silence(sildet, f, &dspsilence);
751                                         if (dspsilence)
752                                                 totalsilence = dspsilence;
753                                         else
754                                                 totalsilence = 0;
755
756                                         if (totalsilence > maxsilence) {
757                                                 /* Ended happily with silence */
758                                                 ast_verb(3, "Recording automatically stopped after a silence of %d seconds\n", totalsilence/1000);
759                                                 res = 'S';
760                                                 outmsg = 2;
761                                                 break;
762                                         }
763                                 }
764                                 /* Exit on any error */
765                                 if (res) {
766                                         ast_log(LOG_WARNING, "Error writing frame\n");
767                                         break;
768                                 }
769                         } else if (f->frametype == AST_FRAME_VIDEO) {
770                                 /* Write only once */
771                                 ast_writestream(others[0], f);
772                         } else if (f->frametype == AST_FRAME_DTMF) {
773                                 if (prepend) {
774                                 /* stop recording with any digit */
775                                         ast_verb(3, "User ended message by pressing %c\n", f->subclass);
776                                         res = 't';
777                                         outmsg = 2;
778                                         break;
779                                 }
780                                 if (strchr(acceptdtmf, f->subclass)) {
781                                         ast_verb(3, "User ended message by pressing %c\n", f->subclass);
782                                         res = f->subclass;
783                                         outmsg = 2;
784                                         break;
785                                 }
786                                 if (strchr(canceldtmf, f->subclass)) {
787                                         ast_verb(3, "User cancelled message by pressing %c\n", f->subclass);
788                                         res = f->subclass;
789                                         outmsg = 0;
790                                         break;
791                                 }
792                         }
793                         if (maxtime) {
794                                 end = time(NULL);
795                                 if (maxtime < (end - start)) {
796                                         ast_verb(3, "Took too long, cutting it short...\n");
797                                         res = 't';
798                                         outmsg = 2;
799                                         break;
800                                 }
801                         }
802                         ast_frfree(f);
803                 }
804                 if (!f) {
805                         ast_verb(3, "User hung up\n");
806                         res = -1;
807                         outmsg = 1;
808                 } else {
809                         ast_frfree(f);
810                 }
811         } else {
812                 ast_log(LOG_WARNING, "Error creating writestream '%s', format '%s'\n", recordfile, sfmt[x]);
813         }
814
815         if (!prepend) {
816                 if (silgen)
817                         ast_channel_stop_silence_generator(chan, silgen);
818         }
819
820         /*!\note
821          * Instead of asking how much time passed (end - start), calculate the number
822          * of seconds of audio which actually went into the file.  This fixes a
823          * problem where audio is stopped up on the network and never gets to us.
824          *
825          * Note that we still want to use the number of seconds passed for the max
826          * message, otherwise we could get a situation where this stream is never
827          * closed (which would create a resource leak).
828          */
829         *duration = others[0] ? ast_tellstream(others[0]) / 8000 : 0;
830
831         if (!prepend) {
832                 for (x = 0; x < fmtcnt; x++) {
833                         if (!others[x])
834                                 break;
835                         /*!\note
836                          * If we ended with silence, trim all but the first 200ms of silence
837                          * off the recording.  However, if we ended with '#', we don't want
838                          * to trim ANY part of the recording.
839                          */
840                         if (res > 0 && totalsilence)
841                                 ast_stream_rewind(others[x], totalsilence - 200);
842                         ast_truncstream(others[x]);
843                         ast_closestream(others[x]);
844                 }
845         }
846
847         if (prepend && outmsg) {
848                 struct ast_filestream *realfiles[MAX_OTHER_FORMATS];
849                 struct ast_frame *fr;
850
851                 for (x = 0; x < fmtcnt; x++) {
852                         snprintf(comment, sizeof(comment), "Opening the real file %s.%s\n", recordfile, sfmt[x]);
853                         realfiles[x] = ast_readfile(recordfile, sfmt[x], comment, O_RDONLY, 0, 0);
854                         if (!others[x] || !realfiles[x])
855                                 break;
856                         /*!\note Same logic as above. */
857                         if (totalsilence)
858                                 ast_stream_rewind(others[x], totalsilence - 200);
859                         ast_truncstream(others[x]);
860                         /* add the original file too */
861                         while ((fr = ast_readframe(realfiles[x]))) {
862                                 ast_writestream(others[x], fr);
863                                 ast_frfree(fr);
864                         }
865                         ast_closestream(others[x]);
866                         ast_closestream(realfiles[x]);
867                         ast_filerename(prependfile, recordfile, sfmt[x]);
868                         ast_verb(4, "Recording Format: sfmts=%s, prependfile %s, recordfile %s\n", sfmt[x], prependfile, recordfile);
869                         ast_filedelete(prependfile, sfmt[x]);
870                 }
871         }
872         if (rfmt && ast_set_read_format(chan, rfmt)) {
873                 ast_log(LOG_WARNING, "Unable to restore format %s to channel '%s'\n", ast_getformatname(rfmt), chan->name);
874         }
875         if (outmsg == 2) {
876                 ast_stream_and_wait(chan, "auth-thankyou", "");
877         }
878         if (sildet)
879                 ast_dsp_free(sildet);
880         return res;
881 }
882
883 static char default_acceptdtmf[] = "#";
884 static char default_canceldtmf[] = "";
885
886 int ast_play_and_record_full(struct ast_channel *chan, const char *playfile, const char *recordfile, int maxtime, const char *fmt, int *duration, int silencethreshold, int maxsilence, const char *path, const char *acceptdtmf, const char *canceldtmf)
887 {
888         return __ast_play_and_record(chan, playfile, recordfile, maxtime, fmt, duration, 0, silencethreshold, maxsilence, path, 0, S_OR(acceptdtmf, default_acceptdtmf), S_OR(canceldtmf, default_canceldtmf));
889 }
890
891 int ast_play_and_record(struct ast_channel *chan, const char *playfile, const char *recordfile, int maxtime, const char *fmt, int *duration, int silencethreshold, int maxsilence, const char *path)
892 {
893         return __ast_play_and_record(chan, playfile, recordfile, maxtime, fmt, duration, 0, silencethreshold, maxsilence, path, 0, default_acceptdtmf, default_canceldtmf);
894 }
895
896 int ast_play_and_prepend(struct ast_channel *chan, char *playfile, char *recordfile, int maxtime, char *fmt, int *duration, int beep, int silencethreshold, int maxsilence)
897 {
898         return __ast_play_and_record(chan, playfile, recordfile, maxtime, fmt, duration, beep, silencethreshold, maxsilence, NULL, 1, default_acceptdtmf, default_canceldtmf);
899 }
900
901 /* Channel group core functions */
902
903 int ast_app_group_split_group(const char *data, char *group, int group_max, char *category, int category_max)
904 {
905         int res = 0;
906         char tmp[256];
907         char *grp = NULL, *cat = NULL;
908
909         if (!ast_strlen_zero(data)) {
910                 ast_copy_string(tmp, data, sizeof(tmp));
911                 grp = tmp;
912                 cat = strchr(tmp, '@');
913                 if (cat) {
914                         *cat = '\0';
915                         cat++;
916                 }
917         }
918
919         if (!ast_strlen_zero(grp))
920                 ast_copy_string(group, grp, group_max);
921         else
922                 *group = '\0';
923
924         if (!ast_strlen_zero(cat))
925                 ast_copy_string(category, cat, category_max);
926
927         return res;
928 }
929
930 int ast_app_group_set_channel(struct ast_channel *chan, const char *data)
931 {
932         int res = 0;
933         char group[80] = "", category[80] = "";
934         struct ast_group_info *gi = NULL;
935         size_t len = 0;
936         
937         if (ast_app_group_split_group(data, group, sizeof(group), category, sizeof(category)))
938                 return -1;
939         
940         /* Calculate memory we will need if this is new */
941         len = sizeof(*gi) + strlen(group) + 1;
942         if (!ast_strlen_zero(category))
943                 len += strlen(category) + 1;
944         
945         AST_RWLIST_WRLOCK(&groups);
946         AST_RWLIST_TRAVERSE_SAFE_BEGIN(&groups, gi, list) {
947                 if ((gi->chan == chan) && ((ast_strlen_zero(category) && ast_strlen_zero(gi->category)) || (!ast_strlen_zero(gi->category) && !strcasecmp(gi->category, category)))) {
948                         AST_RWLIST_REMOVE_CURRENT(list);
949                         free(gi);
950                         break;
951                 }
952         }
953         AST_RWLIST_TRAVERSE_SAFE_END;
954
955         if (ast_strlen_zero(group)) {
956                 /* Enable unsetting the group */
957         } else if ((gi = calloc(1, len))) {
958                 gi->chan = chan;
959                 gi->group = (char *) gi + sizeof(*gi);
960                 strcpy(gi->group, group);
961                 if (!ast_strlen_zero(category)) {
962                         gi->category = (char *) gi + sizeof(*gi) + strlen(group) + 1;
963                         strcpy(gi->category, category);
964                 }
965                 AST_RWLIST_INSERT_TAIL(&groups, gi, list);
966         } else {
967                 res = -1;
968         }
969         
970         AST_RWLIST_UNLOCK(&groups);
971         
972         return res;
973 }
974
975 int ast_app_group_get_count(const char *group, const char *category)
976 {
977         struct ast_group_info *gi = NULL;
978         int count = 0;
979
980         if (ast_strlen_zero(group))
981                 return 0;
982         
983         AST_RWLIST_RDLOCK(&groups);
984         AST_RWLIST_TRAVERSE(&groups, gi, list) {
985                 if (!strcasecmp(gi->group, group) && (ast_strlen_zero(category) || (!ast_strlen_zero(gi->category) && !strcasecmp(gi->category, category))))
986                         count++;
987         }
988         AST_RWLIST_UNLOCK(&groups);
989
990         return count;
991 }
992
993 int ast_app_group_match_get_count(const char *groupmatch, const char *category)
994 {
995         struct ast_group_info *gi = NULL;
996         regex_t regexbuf;
997         int count = 0;
998
999         if (ast_strlen_zero(groupmatch))
1000                 return 0;
1001
1002         /* if regex compilation fails, return zero matches */
1003         if (regcomp(&regexbuf, groupmatch, REG_EXTENDED | REG_NOSUB))
1004                 return 0;
1005
1006         AST_RWLIST_RDLOCK(&groups);
1007         AST_RWLIST_TRAVERSE(&groups, gi, list) {
1008                 if (!regexec(&regexbuf, gi->group, 0, NULL, 0) && (ast_strlen_zero(category) || (!ast_strlen_zero(gi->category) && !strcasecmp(gi->category, category))))
1009                         count++;
1010         }
1011         AST_RWLIST_UNLOCK(&groups);
1012
1013         regfree(&regexbuf);
1014
1015         return count;
1016 }
1017
1018 int ast_app_group_update(struct ast_channel *old, struct ast_channel *new)
1019 {
1020         struct ast_group_info *gi = NULL;
1021
1022         AST_RWLIST_WRLOCK(&groups);
1023         AST_RWLIST_TRAVERSE_SAFE_BEGIN(&groups, gi, list) {
1024                 if (gi->chan == old) {
1025                         gi->chan = new;
1026                 } else if (gi->chan == new) {
1027                         AST_RWLIST_REMOVE_CURRENT(list);
1028                         ast_free(gi);
1029                 }
1030         }
1031         AST_RWLIST_TRAVERSE_SAFE_END
1032         AST_RWLIST_UNLOCK(&groups);
1033
1034         return 0;
1035 }
1036
1037 int ast_app_group_discard(struct ast_channel *chan)
1038 {
1039         struct ast_group_info *gi = NULL;
1040         
1041         AST_RWLIST_WRLOCK(&groups);
1042         AST_RWLIST_TRAVERSE_SAFE_BEGIN(&groups, gi, list) {
1043                 if (gi->chan == chan) {
1044                         AST_RWLIST_REMOVE_CURRENT(list);
1045                         ast_free(gi);
1046                 }
1047         }
1048         AST_RWLIST_TRAVERSE_SAFE_END;
1049         AST_RWLIST_UNLOCK(&groups);
1050         
1051         return 0;
1052 }
1053
1054 int ast_app_group_list_wrlock(void)
1055 {
1056         return AST_RWLIST_WRLOCK(&groups);
1057 }
1058
1059 int ast_app_group_list_rdlock(void)
1060 {
1061         return AST_RWLIST_RDLOCK(&groups);
1062 }
1063
1064 struct ast_group_info *ast_app_group_list_head(void)
1065 {
1066         return AST_RWLIST_FIRST(&groups);
1067 }
1068
1069 int ast_app_group_list_unlock(void)
1070 {
1071         return AST_RWLIST_UNLOCK(&groups);
1072 }
1073
1074 unsigned int ast_app_separate_args(char *buf, char delim, char **array, int arraylen)
1075 {
1076         int argc;
1077         char *scan, *wasdelim = NULL;
1078         int paren = 0, quote = 0;
1079
1080         if (!buf || !array || !arraylen)
1081                 return 0;
1082
1083         memset(array, 0, arraylen * sizeof(*array));
1084
1085         scan = buf;
1086
1087         for (argc = 0; *scan && (argc < arraylen - 1); argc++) {
1088                 array[argc] = scan;
1089                 for (; *scan; scan++) {
1090                         if (*scan == '(')
1091                                 paren++;
1092                         else if (*scan == ')') {
1093                                 if (paren)
1094                                         paren--;
1095                         } else if (*scan == '"' && delim != '"') {
1096                                 quote = quote ? 0 : 1;
1097                                 /* Remove quote character from argument */
1098                                 memmove(scan, scan + 1, strlen(scan));
1099                                 scan--;
1100                         } else if (*scan == '\\') {
1101                                 /* Literal character, don't parse */
1102                                 memmove(scan, scan + 1, strlen(scan));
1103                         } else if ((*scan == delim) && !paren && !quote) {
1104                                 wasdelim = scan;
1105                                 *scan++ = '\0';
1106                                 break;
1107                         }
1108                 }
1109         }
1110
1111         /* If the last character in the original string was the delimiter, then
1112          * there is one additional argument. */
1113         if (*scan || (scan > buf && (scan - 1) == wasdelim)) {
1114                 array[argc++] = scan;
1115         }
1116
1117         return argc;
1118 }
1119
1120 static enum AST_LOCK_RESULT ast_lock_path_lockfile(const char *path)
1121 {
1122         char *s;
1123         char *fs;
1124         int res;
1125         int fd;
1126         int lp = strlen(path);
1127         time_t start;
1128
1129         s = alloca(lp + 10); 
1130         fs = alloca(lp + 20);
1131
1132         snprintf(fs, strlen(path) + 19, "%s/.lock-%08lx", path, ast_random());
1133         fd = open(fs, O_WRONLY | O_CREAT | O_EXCL, AST_FILE_MODE);
1134         if (fd < 0) {
1135                 ast_log(LOG_ERROR, "Unable to create lock file '%s': %s\n", path, strerror(errno));
1136                 return AST_LOCK_PATH_NOT_FOUND;
1137         }
1138         close(fd);
1139
1140         snprintf(s, strlen(path) + 9, "%s/.lock", path);
1141         start = time(NULL);
1142         while (((res = link(fs, s)) < 0) && (errno == EEXIST) && (time(NULL) - start < 5))
1143                 usleep(1);
1144
1145         unlink(fs);
1146
1147         if (res) {
1148                 ast_log(LOG_WARNING, "Failed to lock path '%s': %s\n", path, strerror(errno));
1149                 return AST_LOCK_TIMEOUT;
1150         } else {
1151                 ast_debug(1, "Locked path '%s'\n", path);
1152                 return AST_LOCK_SUCCESS;
1153         }
1154 }
1155
1156 static int ast_unlock_path_lockfile(const char *path)
1157 {
1158         char *s;
1159         int res;
1160
1161         s = alloca(strlen(path) + 10);
1162
1163         snprintf(s, strlen(path) + 9, "%s/%s", path, ".lock");
1164
1165         if ((res = unlink(s)))
1166                 ast_log(LOG_ERROR, "Could not unlock path '%s': %s\n", path, strerror(errno));
1167         else {
1168                 ast_debug(1, "Unlocked path '%s'\n", path);
1169         }
1170
1171         return res;
1172 }
1173
1174 struct path_lock {
1175         AST_LIST_ENTRY(path_lock) le;
1176         int fd;
1177         char *path;
1178 };
1179
1180 static AST_LIST_HEAD_STATIC(path_lock_list, path_lock);
1181
1182 static void path_lock_destroy(struct path_lock *obj)
1183 {
1184         if (obj->fd >= 0)
1185                 close(obj->fd);
1186         if (obj->path)
1187                 free(obj->path);
1188         free(obj);
1189 }
1190
1191 static enum AST_LOCK_RESULT ast_lock_path_flock(const char *path)
1192 {
1193         char *fs;
1194         int res;
1195         int fd;
1196         time_t start;
1197         struct path_lock *pl;
1198         struct stat st, ost;
1199
1200         fs = alloca(strlen(path) + 20);
1201
1202         snprintf(fs, strlen(path) + 19, "%s/lock", path);
1203         if (lstat(fs, &st) == 0) {
1204                 if ((st.st_mode & S_IFMT) == S_IFLNK) {
1205                         ast_log(LOG_WARNING, "Unable to create lock file "
1206                                         "'%s': it's already a symbolic link\n",
1207                                         fs);
1208                         return AST_LOCK_FAILURE;
1209                 }
1210                 if (st.st_nlink > 1) {
1211                         ast_log(LOG_WARNING, "Unable to create lock file "
1212                                         "'%s': %u hard links exist\n",
1213                                         fs, (unsigned int) st.st_nlink);
1214                         return AST_LOCK_FAILURE;
1215                 }
1216         }
1217         fd = open(fs, O_WRONLY | O_CREAT, 0600);
1218         if (fd < 0) {
1219                 ast_log(LOG_WARNING, "Unable to create lock file '%s': %s\n",
1220                                 fs, strerror(errno));
1221                 return AST_LOCK_PATH_NOT_FOUND;
1222         }
1223         pl = ast_calloc(1, sizeof(*pl));
1224         if (!pl) {
1225                 /* We don't unlink the lock file here, on the possibility that
1226                  * someone else created it - better to leave a little mess
1227                  * than create a big one by destroying someone else's lock
1228                  * and causing something to be corrupted.
1229                  */
1230                 close(fd);
1231                 return AST_LOCK_FAILURE;
1232         }
1233         pl->fd = fd;
1234         pl->path = strdup(path);
1235
1236         time(&start);
1237         while ((
1238                 #ifdef SOLARIS
1239                 (res = fcntl(pl->fd, F_SETLK, fcntl(pl->fd, F_GETFL) | O_NONBLOCK)) < 0) &&
1240                 #else
1241                 (res = flock(pl->fd, LOCK_EX | LOCK_NB)) < 0) &&
1242                 #endif
1243                         (errno == EWOULDBLOCK) && 
1244                         (time(NULL) - start < 5))
1245                 usleep(1000);
1246         if (res) {
1247                 ast_log(LOG_WARNING, "Failed to lock path '%s': %s\n",
1248                                 path, strerror(errno));
1249                 /* No unlinking of lock done, since we tried and failed to
1250                  * flock() it.
1251                  */
1252                 path_lock_destroy(pl);
1253                 return AST_LOCK_TIMEOUT;
1254         }
1255
1256         /* Check for the race where the file is recreated or deleted out from
1257          * underneath us.
1258          */
1259         if (lstat(fs, &st) != 0 && fstat(pl->fd, &ost) != 0 &&
1260                         st.st_dev != ost.st_dev &&
1261                         st.st_ino != ost.st_ino) {
1262                 ast_log(LOG_WARNING, "Unable to create lock file '%s': "
1263                                 "file changed underneath us\n", fs);
1264                 path_lock_destroy(pl);
1265                 return AST_LOCK_FAILURE;
1266         }
1267
1268         /* Success: file created, flocked, and is the one we started with */
1269         AST_LIST_LOCK(&path_lock_list);
1270         AST_LIST_INSERT_TAIL(&path_lock_list, pl, le);
1271         AST_LIST_UNLOCK(&path_lock_list);
1272
1273         ast_debug(1, "Locked path '%s'\n", path);
1274
1275         return AST_LOCK_SUCCESS;
1276 }
1277
1278 static int ast_unlock_path_flock(const char *path)
1279 {
1280         char *s;
1281         struct path_lock *p;
1282
1283         s = alloca(strlen(path) + 20);
1284
1285         AST_LIST_LOCK(&path_lock_list);
1286         AST_LIST_TRAVERSE_SAFE_BEGIN(&path_lock_list, p, le) {
1287                 if (!strcmp(p->path, path)) {
1288                         AST_LIST_REMOVE_CURRENT(le);
1289                         break;
1290                 }
1291         }
1292         AST_LIST_TRAVERSE_SAFE_END;
1293         AST_LIST_UNLOCK(&path_lock_list);
1294
1295         if (p) {
1296                 snprintf(s, strlen(path) + 19, "%s/lock", path);
1297                 unlink(s);
1298                 path_lock_destroy(p);
1299                 ast_log(LOG_DEBUG, "Unlocked path '%s'\n", path);
1300         } else
1301                 ast_log(LOG_DEBUG, "Failed to unlock path '%s': "
1302                                 "lock not found\n", path);
1303
1304         return 0;
1305 }
1306
1307 void ast_set_lock_type(enum AST_LOCK_TYPE type)
1308 {
1309         ast_lock_type = type;
1310 }
1311
1312 enum AST_LOCK_RESULT ast_lock_path(const char *path)
1313 {
1314         enum AST_LOCK_RESULT r = AST_LOCK_FAILURE;
1315
1316         switch (ast_lock_type) {
1317         case AST_LOCK_TYPE_LOCKFILE:
1318                 r = ast_lock_path_lockfile(path);
1319                 break;
1320         case AST_LOCK_TYPE_FLOCK:
1321                 r = ast_lock_path_flock(path);
1322                 break;
1323         }
1324
1325         return r;
1326 }
1327
1328 int ast_unlock_path(const char *path)
1329 {
1330         int r = 0;
1331
1332         switch (ast_lock_type) {
1333         case AST_LOCK_TYPE_LOCKFILE:
1334                 r = ast_unlock_path_lockfile(path);
1335                 break;
1336         case AST_LOCK_TYPE_FLOCK:
1337                 r = ast_unlock_path_flock(path);
1338                 break;
1339         }
1340
1341         return r;
1342 }
1343
1344 int ast_record_review(struct ast_channel *chan, const char *playfile, const char *recordfile, int maxtime, const char *fmt, int *duration, const char *path) 
1345 {
1346         int silencethreshold; 
1347         int maxsilence = 0;
1348         int res = 0;
1349         int cmd = 0;
1350         int max_attempts = 3;
1351         int attempts = 0;
1352         int recorded = 0;
1353         int message_exists = 0;
1354         /* Note that urgent and private are for flagging messages as such in the future */
1355
1356         /* barf if no pointer passed to store duration in */
1357         if (!duration) {
1358                 ast_log(LOG_WARNING, "Error ast_record_review called without duration pointer\n");
1359                 return -1;
1360         }
1361
1362         cmd = '3';       /* Want to start by recording */
1363
1364         silencethreshold = ast_dsp_get_threshold_from_settings(THRESHOLD_SILENCE);
1365
1366         while ((cmd >= 0) && (cmd != 't')) {
1367                 switch (cmd) {
1368                 case '1':
1369                         if (!message_exists) {
1370                                 /* In this case, 1 is to record a message */
1371                                 cmd = '3';
1372                                 break;
1373                         } else {
1374                                 ast_stream_and_wait(chan, "vm-msgsaved", "");
1375                                 cmd = 't';
1376                                 return res;
1377                         }
1378                 case '2':
1379                         /* Review */
1380                         ast_verb(3, "Reviewing the recording\n");
1381                         cmd = ast_stream_and_wait(chan, recordfile, AST_DIGIT_ANY);
1382                         break;
1383                 case '3':
1384                         message_exists = 0;
1385                         /* Record */
1386                         if (recorded == 1)
1387                                 ast_verb(3, "Re-recording\n");
1388                         else    
1389                                 ast_verb(3, "Recording\n");
1390                         recorded = 1;
1391                         cmd = ast_play_and_record(chan, playfile, recordfile, maxtime, fmt, duration, silencethreshold, maxsilence, path);
1392                         if (cmd == -1) {
1393                         /* User has hung up, no options to give */
1394                                 return cmd;
1395                         }
1396                         if (cmd == '0') {
1397                                 break;
1398                         } else if (cmd == '*') {
1399                                 break;
1400                         } 
1401                         else {
1402                                 /* If all is well, a message exists */
1403                                 message_exists = 1;
1404                                 cmd = 0;
1405                         }
1406                         break;
1407                 case '4':
1408                 case '5':
1409                 case '6':
1410                 case '7':
1411                 case '8':
1412                 case '9':
1413                 case '*':
1414                 case '#':
1415                         cmd = ast_play_and_wait(chan, "vm-sorry");
1416                         break;
1417                 default:
1418                         if (message_exists) {
1419                                 cmd = ast_play_and_wait(chan, "vm-review");
1420                         }
1421                         else {
1422                                 cmd = ast_play_and_wait(chan, "vm-torerecord");
1423                                 if (!cmd)
1424                                         cmd = ast_waitfordigit(chan, 600);
1425                         }
1426                         
1427                         if (!cmd)
1428                                 cmd = ast_waitfordigit(chan, 6000);
1429                         if (!cmd) {
1430                                 attempts++;
1431                         }
1432                         if (attempts > max_attempts) {
1433                                 cmd = 't';
1434                         }
1435                 }
1436         }
1437         if (cmd == 't')
1438                 cmd = 0;
1439         return cmd;
1440 }
1441
1442 #define RES_UPONE (1 << 16)
1443 #define RES_EXIT  (1 << 17)
1444 #define RES_REPEAT (1 << 18)
1445 #define RES_RESTART ((1 << 19) | RES_REPEAT)
1446
1447 static int ast_ivr_menu_run_internal(struct ast_channel *chan, struct ast_ivr_menu *menu, void *cbdata);
1448
1449 static int ivr_dispatch(struct ast_channel *chan, struct ast_ivr_option *option, char *exten, void *cbdata)
1450 {
1451         int res;
1452         int (*ivr_func)(struct ast_channel *, void *);
1453         char *c;
1454         char *n;
1455         
1456         switch (option->action) {
1457         case AST_ACTION_UPONE:
1458                 return RES_UPONE;
1459         case AST_ACTION_EXIT:
1460                 return RES_EXIT | (((unsigned long)(option->adata)) & 0xffff);
1461         case AST_ACTION_REPEAT:
1462                 return RES_REPEAT | (((unsigned long)(option->adata)) & 0xffff);
1463         case AST_ACTION_RESTART:
1464                 return RES_RESTART ;
1465         case AST_ACTION_NOOP:
1466                 return 0;
1467         case AST_ACTION_BACKGROUND:
1468                 res = ast_stream_and_wait(chan, (char *)option->adata, AST_DIGIT_ANY);
1469                 if (res < 0) {
1470                         ast_log(LOG_NOTICE, "Unable to find file '%s'!\n", (char *)option->adata);
1471                         res = 0;
1472                 }
1473                 return res;
1474         case AST_ACTION_PLAYBACK:
1475                 res = ast_stream_and_wait(chan, (char *)option->adata, "");
1476                 if (res < 0) {
1477                         ast_log(LOG_NOTICE, "Unable to find file '%s'!\n", (char *)option->adata);
1478                         res = 0;
1479                 }
1480                 return res;
1481         case AST_ACTION_MENU:
1482                 res = ast_ivr_menu_run_internal(chan, (struct ast_ivr_menu *)option->adata, cbdata);
1483                 /* Do not pass entry errors back up, treat as though it was an "UPONE" */
1484                 if (res == -2)
1485                         res = 0;
1486                 return res;
1487         case AST_ACTION_WAITOPTION:
1488                 res = ast_waitfordigit(chan, chan->pbx ? chan->pbx->rtimeoutms : 10000);
1489                 if (!res)
1490                         return 't';
1491                 return res;
1492         case AST_ACTION_CALLBACK:
1493                 ivr_func = option->adata;
1494                 res = ivr_func(chan, cbdata);
1495                 return res;
1496         case AST_ACTION_TRANSFER:
1497                 res = ast_parseable_goto(chan, option->adata);
1498                 return 0;
1499         case AST_ACTION_PLAYLIST:
1500         case AST_ACTION_BACKLIST:
1501                 res = 0;
1502                 c = ast_strdupa(option->adata);
1503                 while ((n = strsep(&c, ";"))) {
1504                         if ((res = ast_stream_and_wait(chan, n,
1505                                         (option->action == AST_ACTION_BACKLIST) ? AST_DIGIT_ANY : "")))
1506                                 break;
1507                 }
1508                 ast_stopstream(chan);
1509                 return res;
1510         default:
1511                 ast_log(LOG_NOTICE, "Unknown dispatch function %d, ignoring!\n", option->action);
1512                 return 0;
1513         };
1514         return -1;
1515 }
1516
1517 static int option_exists(struct ast_ivr_menu *menu, char *option)
1518 {
1519         int x;
1520         for (x = 0; menu->options[x].option; x++)
1521                 if (!strcasecmp(menu->options[x].option, option))
1522                         return x;
1523         return -1;
1524 }
1525
1526 static int option_matchmore(struct ast_ivr_menu *menu, char *option)
1527 {
1528         int x;
1529         for (x = 0; menu->options[x].option; x++)
1530                 if ((!strncasecmp(menu->options[x].option, option, strlen(option))) && 
1531                                 (menu->options[x].option[strlen(option)]))
1532                         return x;
1533         return -1;
1534 }
1535
1536 static int read_newoption(struct ast_channel *chan, struct ast_ivr_menu *menu, char *exten, int maxexten)
1537 {
1538         int res = 0;
1539         int ms;
1540         while (option_matchmore(menu, exten)) {
1541                 ms = chan->pbx ? chan->pbx->dtimeoutms : 5000;
1542                 if (strlen(exten) >= maxexten - 1) 
1543                         break;
1544                 res = ast_waitfordigit(chan, ms);
1545                 if (res < 1)
1546                         break;
1547                 exten[strlen(exten) + 1] = '\0';
1548                 exten[strlen(exten)] = res;
1549         }
1550         return res > 0 ? 0 : res;
1551 }
1552
1553 static int ast_ivr_menu_run_internal(struct ast_channel *chan, struct ast_ivr_menu *menu, void *cbdata)
1554 {
1555         /* Execute an IVR menu structure */
1556         int res = 0;
1557         int pos = 0;
1558         int retries = 0;
1559         char exten[AST_MAX_EXTENSION] = "s";
1560         if (option_exists(menu, "s") < 0) {
1561                 strcpy(exten, "g");
1562                 if (option_exists(menu, "g") < 0) {
1563                         ast_log(LOG_WARNING, "No 's' nor 'g' extension in menu '%s'!\n", menu->title);
1564                         return -1;
1565                 }
1566         }
1567         while (!res) {
1568                 while (menu->options[pos].option) {
1569                         if (!strcasecmp(menu->options[pos].option, exten)) {
1570                                 res = ivr_dispatch(chan, menu->options + pos, exten, cbdata);
1571                                 ast_debug(1, "IVR Dispatch of '%s' (pos %d) yields %d\n", exten, pos, res);
1572                                 if (res < 0)
1573                                         break;
1574                                 else if (res & RES_UPONE)
1575                                         return 0;
1576                                 else if (res & RES_EXIT)
1577                                         return res;
1578                                 else if (res & RES_REPEAT) {
1579                                         int maxretries = res & 0xffff;
1580                                         if ((res & RES_RESTART) == RES_RESTART) {
1581                                                 retries = 0;
1582                                         } else
1583                                                 retries++;
1584                                         if (!maxretries)
1585                                                 maxretries = 3;
1586                                         if ((maxretries > 0) && (retries >= maxretries)) {
1587                                                 ast_debug(1, "Max retries %d exceeded\n", maxretries);
1588                                                 return -2;
1589                                         } else {
1590                                                 if (option_exists(menu, "g") > -1) 
1591                                                         strcpy(exten, "g");
1592                                                 else if (option_exists(menu, "s") > -1)
1593                                                         strcpy(exten, "s");
1594                                         }
1595                                         pos = 0;
1596                                         continue;
1597                                 } else if (res && strchr(AST_DIGIT_ANY, res)) {
1598                                         ast_debug(1, "Got start of extension, %c\n", res);
1599                                         exten[1] = '\0';
1600                                         exten[0] = res;
1601                                         if ((res = read_newoption(chan, menu, exten, sizeof(exten))))
1602                                                 break;
1603                                         if (option_exists(menu, exten) < 0) {
1604                                                 if (option_exists(menu, "i")) {
1605                                                         ast_debug(1, "Invalid extension entered, going to 'i'!\n");
1606                                                         strcpy(exten, "i");
1607                                                         pos = 0;
1608                                                         continue;
1609                                                 } else {
1610                                                         ast_debug(1, "Aborting on invalid entry, with no 'i' option!\n");
1611                                                         res = -2;
1612                                                         break;
1613                                                 }
1614                                         } else {
1615                                                 ast_debug(1, "New existing extension: %s\n", exten);
1616                                                 pos = 0;
1617                                                 continue;
1618                                         }
1619                                 }
1620                         }
1621                         pos++;
1622                 }
1623                 ast_debug(1, "Stopping option '%s', res is %d\n", exten, res);
1624                 pos = 0;
1625                 if (!strcasecmp(exten, "s"))
1626                         strcpy(exten, "g");
1627                 else
1628                         break;
1629         }
1630         return res;
1631 }
1632
1633 int ast_ivr_menu_run(struct ast_channel *chan, struct ast_ivr_menu *menu, void *cbdata)
1634 {
1635         int res = ast_ivr_menu_run_internal(chan, menu, cbdata);
1636         /* Hide internal coding */
1637         return res > 0 ? 0 : res;
1638 }
1639         
1640 char *ast_read_textfile(const char *filename)
1641 {
1642         int fd, count = 0, res;
1643         char *output = NULL;
1644         struct stat filesize;
1645
1646         if (stat(filename, &filesize) == -1) {
1647                 ast_log(LOG_WARNING, "Error can't stat %s\n", filename);
1648                 return NULL;
1649         }
1650
1651         count = filesize.st_size + 1;
1652
1653         if ((fd = open(filename, O_RDONLY)) < 0) {
1654                 ast_log(LOG_WARNING, "Cannot open file '%s' for reading: %s\n", filename, strerror(errno));
1655                 return NULL;
1656         }
1657
1658         if ((output = ast_malloc(count))) {
1659                 res = read(fd, output, count - 1);
1660                 if (res == count - 1) {
1661                         output[res] = '\0';
1662                 } else {
1663                         ast_log(LOG_WARNING, "Short read of %s (%d of %d): %s\n", filename, res, count - 1, strerror(errno));
1664                         ast_free(output);
1665                         output = NULL;
1666                 }
1667         }
1668
1669         close(fd);
1670
1671         return output;
1672 }
1673
1674 int ast_app_parse_options(const struct ast_app_option *options, struct ast_flags *flags, char **args, char *optstr)
1675 {
1676         char *s, *arg;
1677         int curarg, res = 0;
1678         unsigned int argloc;
1679
1680         ast_clear_flag(flags, AST_FLAGS_ALL);
1681
1682         if (!optstr)
1683                 return 0;
1684
1685         s = optstr;
1686         while (*s) {
1687                 curarg = *s++ & 0x7f;   /* the array (in app.h) has 128 entries */
1688                 argloc = options[curarg].arg_index;
1689                 if (*s == '(') {
1690                         /* Has argument */
1691                         arg = ++s;
1692                         if ((s = strchr(s, ')'))) {
1693                                 if (argloc)
1694                                         args[argloc - 1] = arg;
1695                                 *s++ = '\0';
1696                         } else {
1697                                 ast_log(LOG_WARNING, "Missing closing parenthesis for argument '%c' in string '%s'\n", curarg, arg);
1698                                 res = -1;
1699                                 break;
1700                         }
1701                 } else if (argloc) {
1702                         args[argloc - 1] = "";
1703                 }
1704                 ast_set_flag(flags, options[curarg].flag);
1705         }
1706
1707         return res;
1708 }
1709
1710 /* the following function will probably only be used in app_dial, until app_dial is reorganized to
1711    better handle the large number of options it provides. After it is, you need to get rid of this variant 
1712    -- unless, of course, someone else digs up some use for large flag fields. */
1713
1714 int ast_app_parse_options64(const struct ast_app_option *options, struct ast_flags64 *flags, char **args, char *optstr)
1715 {
1716         char *s, *arg;
1717         int curarg, res = 0;
1718         unsigned int argloc;
1719
1720         flags->flags = 0;
1721         
1722         if (!optstr)
1723                 return 0;
1724
1725         s = optstr;
1726         while (*s) {
1727                 curarg = *s++ & 0x7f;   /* the array (in app.h) has 128 entries */
1728                 ast_set_flag64(flags, options[curarg].flag);
1729                 argloc = options[curarg].arg_index;
1730                 if (*s == '(') {
1731                         /* Has argument */
1732                         arg = ++s;
1733                         if ((s = strchr(s, ')'))) {
1734                                 if (argloc)
1735                                         args[argloc - 1] = arg;
1736                                 *s++ = '\0';
1737                         } else {
1738                                 ast_log(LOG_WARNING, "Missing closing parenthesis for argument '%c' in string '%s'\n", curarg, arg);
1739                                 res = -1;
1740                                 break;
1741                         }
1742                 } else if (argloc) {
1743                         args[argloc - 1] = NULL;
1744                 }
1745         }
1746
1747         return res;
1748 }
1749
1750 void ast_app_options2str64(const struct ast_app_option *options, struct ast_flags64 *flags, char *buf, size_t len)
1751 {
1752         unsigned int i, found = 0;
1753         for (i = 32; i < 128 && found < len; i++) {
1754                 if (ast_test_flag64(flags, options[i].flag)) {
1755                         buf[found++] = i;
1756                 }
1757         }
1758         buf[found] = '\0';
1759 }
1760
1761 int ast_get_encoded_char(const char *stream, char *result, size_t *consumed)
1762 {
1763         int i;
1764         *consumed = 1;
1765         *result = 0;
1766         if (ast_strlen_zero(stream)) {
1767                 *consumed = 0;
1768                 return -1;
1769         }
1770
1771         if (*stream == '\\') {
1772                 *consumed = 2;
1773                 switch (*(stream + 1)) {
1774                 case 'n':
1775                         *result = '\n';
1776                         break;
1777                 case 'r':
1778                         *result = '\r';
1779                         break;
1780                 case 't':
1781                         *result = '\t';
1782                         break;
1783                 case 'x':
1784                         /* Hexadecimal */
1785                         if (strchr("0123456789ABCDEFabcdef", *(stream + 2)) && *(stream + 2) != '\0') {
1786                                 *consumed = 3;
1787                                 if (*(stream + 2) <= '9')
1788                                         *result = *(stream + 2) - '0';
1789                                 else if (*(stream + 2) <= 'F')
1790                                         *result = *(stream + 2) - 'A' + 10;
1791                                 else
1792                                         *result = *(stream + 2) - 'a' + 10;
1793                         } else {
1794                                 ast_log(LOG_ERROR, "Illegal character '%c' in hexadecimal string\n", *(stream + 2));
1795                                 return -1;
1796                         }
1797
1798                         if (strchr("0123456789ABCDEFabcdef", *(stream + 3)) && *(stream + 3) != '\0') {
1799                                 *consumed = 4;
1800                                 *result <<= 4;
1801                                 if (*(stream + 3) <= '9')
1802                                         *result += *(stream + 3) - '0';
1803                                 else if (*(stream + 3) <= 'F')
1804                                         *result += *(stream + 3) - 'A' + 10;
1805                                 else
1806                                         *result += *(stream + 3) - 'a' + 10;
1807                         }
1808                         break;
1809                 case '0':
1810                         /* Octal */
1811                         *consumed = 2;
1812                         for (i = 2; ; i++) {
1813                                 if (strchr("01234567", *(stream + i)) && *(stream + i) != '\0') {
1814                                         (*consumed)++;
1815                                         ast_debug(5, "result was %d, ", *result);
1816                                         *result <<= 3;
1817                                         *result += *(stream + i) - '0';
1818                                         ast_debug(5, "is now %d\n", *result);
1819                                 } else
1820                                         break;
1821                         }
1822                         break;
1823                 default:
1824                         *result = *(stream + 1);
1825                 }
1826         } else {
1827                 *result = *stream;
1828                 *consumed = 1;
1829         }
1830         return 0;
1831 }
1832
1833 char *ast_get_encoded_str(const char *stream, char *result, size_t result_size)
1834 {
1835         char *cur = result;
1836         size_t consumed;
1837
1838         while (cur < result + result_size - 1 && !ast_get_encoded_char(stream, cur, &consumed)) {
1839                 cur++;
1840                 stream += consumed;
1841         }
1842         *cur = '\0';
1843         return result;
1844 }
1845
1846 void ast_close_fds_above_n(int n)
1847 {
1848 #ifdef HAVE_CLOSEFROM
1849         closefrom(n + 1);
1850 #else
1851         int x, null;
1852         struct rlimit rl;
1853         getrlimit(RLIMIT_NOFILE, &rl);
1854         null = open("/dev/null", O_RDONLY);
1855         for (x = n + 1; x < rl.rlim_max; x++) {
1856                 if (x != null) {
1857                         /* Side effect of dup2 is that it closes any existing fd without error.
1858                          * This prevents valgrind and other debugging tools from sending up
1859                          * false error reports. */
1860                         while (dup2(null, x) < 0 && errno == EINTR);
1861                         close(x);
1862                 }
1863         }
1864         close(null);
1865 #endif
1866 }
1867
1868 int ast_safe_fork(int stop_reaper)
1869 {
1870         sigset_t signal_set, old_set;
1871         int pid;
1872
1873         /* Don't let the default signal handler for children reap our status */
1874         if (stop_reaper) {
1875                 ast_replace_sigchld();
1876         }
1877
1878         sigfillset(&signal_set);
1879         pthread_sigmask(SIG_BLOCK, &signal_set, &old_set);
1880
1881         pid = fork();
1882
1883         if (pid != 0) {
1884                 /* Fork failed or parent */
1885                 pthread_sigmask(SIG_SETMASK, &old_set, NULL);
1886                 return pid;
1887         } else {
1888                 /* Child */
1889 #ifdef HAVE_CAP
1890                 cap_t cap = cap_from_text("cap_net_admin-eip");
1891
1892                 if (cap_set_proc(cap)) {
1893                         ast_log(LOG_WARNING, "Unable to remove capabilities.\n");
1894                 }
1895                 cap_free(cap);
1896 #endif
1897
1898                 /* Before we unblock our signals, return our trapped signals back to the defaults */
1899                 signal(SIGHUP, SIG_DFL);
1900                 signal(SIGCHLD, SIG_DFL);
1901                 signal(SIGINT, SIG_DFL);
1902                 signal(SIGURG, SIG_DFL);
1903                 signal(SIGTERM, SIG_DFL);
1904                 signal(SIGPIPE, SIG_DFL);
1905                 signal(SIGXFSZ, SIG_DFL);
1906
1907                 /* unblock important signal handlers */
1908                 if (pthread_sigmask(SIG_UNBLOCK, &signal_set, NULL)) {
1909                         ast_log(LOG_WARNING, "unable to unblock signals: %s\n", strerror(errno));
1910                         _exit(1);
1911                 }
1912
1913                 return pid;
1914         }
1915 }
1916
1917 void ast_safe_fork_cleanup(void)
1918 {
1919         ast_unreplace_sigchld();
1920 }
1921