Wed Jan 8 2020 09:49:39

Asterisk developer's documentation


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