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