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