36#include <sys/inotify.h>
37#elif defined(HAVE_KQUEUE)
102#if defined(HAVE_INOTIFY) || defined(HAVE_KQUEUE)
111static void queue_file(
const char *filename, time_t when);
183 while ((
c = strchr(
c,
'#'))) {
184 if ((
c == line) || (*(
c-1) ==
' ') || (*(
c-1) ==
'\t')) {
192 while ((
c = strchr(
c,
';'))) {
193 if ((
c > line) && (
c[-1] ==
'\\')) {
194 memmove(
c - 1,
c, strlen(
c) + 1);
206 c = strchr(line,
':');
214 printf(
"'%s' is '%s' at line %d\n", line,
c,
lineno);
216 if (!strcasecmp(line,
"channel")) {
218 if ((c2 = strchr(
c,
'/'))) {
226 }
else if (!strcasecmp(line,
"callerid")) {
227 char cid_name[80] = {0}, cid_num[80] = {0};
231 }
else if (!strcasecmp(line,
"application")) {
233 }
else if (!strcasecmp(line,
"data")) {
235 }
else if (!strcasecmp(line,
"maxretries")) {
240 }
else if (!strcasecmp(line,
"codecs")) {
242 }
else if (!strcasecmp(line,
"context")) {
244 }
else if (!strcasecmp(line,
"extension")) {
246 }
else if (!strcasecmp(line,
"priority")) {
251 }
else if (!strcasecmp(line,
"retrytime")) {
256 }
else if (!strcasecmp(line,
"waittime")) {
261 }
else if (!strcasecmp(line,
"retry")) {
263 }
else if (!strcasecmp(line,
"startretry")) {
268 }
else if (!strcasecmp(line,
"endretry") || !strcasecmp(line,
"abortretry")) {
271 }
else if (!strcasecmp(line,
"delayedretry")) {
272 }
else if (!strcasecmp(line,
"setvar") || !strcasecmp(line,
"set")) {
279 ast_log(
LOG_WARNING,
"Malformed \"%s\" argument. Should be \"%s: variable=value\"\n", line, line);
281 }
else if (!strcasecmp(line,
"account")) {
283 }
else if (!strcasecmp(line,
"alwaysdelete")) {
285 }
else if (!strcasecmp(line,
"archive")) {
287 }
else if (!strcasecmp(line,
"early_media")) {
294#define LINE_BUFFER_SIZE 1024
301 while (fgets(
buf,
sizeof(
buf), f)) {
306 if (
buf[
len - 1] ==
'\n' || feof(f)) {
316 while (fgets(
buf,
sizeof(
buf), f)) {
318 if (
buf[
len - 1] ==
'\n' || feof(f)) {
328 "along with tech and dest in file %s\n", o->
fn);
342 struct utimbuf tbuf = { .actime = now, .modtime = now + o->
retrytime };
346 if ((f = fopen(o->
fn,
"a"))) {
352 if (utime(o->
fn, &tbuf)) {
369#if defined(HAVE_INOTIFY) || defined(HAVE_KQUEUE)
374 struct stat current_file_status;
376 if (!stat(o->
fn, ¤t_file_status)) {
377 if (time(
NULL) < current_file_status.st_mtime) {
383#if defined(HAVE_INOTIFY) || defined(HAVE_KQUEUE)
386 if (!strcmp(cur->
name, o->
fn)) {
407 if (!(bname = strrchr(o->
fn,
'/'))) {
413 snprintf(newfn,
sizeof(newfn),
"%s/%s",
qdonedir, bname);
416 if (rename(o->
fn, newfn) != 0) {
423 if ((f = fopen(newfn,
"a"))) {
424 fprintf(f,
"Status: %s\n",
status);
458#if defined(HAVE_INOTIFY) || defined(HAVE_KQUEUE)
494 f = fopen(o->
fn,
"r");
496#if defined(HAVE_INOTIFY) || defined(HAVE_KQUEUE)
528 ast_debug(1,
"Delaying retry since we're currently running '%s'\n", o->
fn);
544 ast_log(
LOG_NOTICE,
"Queued call to %s/%s expired without completion after %d attempt%s\n",
552#if defined(HAVE_INOTIFY)
558#if defined(HAVE_INOTIFY) || defined(HAVE_KQUEUE)
565 time_t now = time(
NULL);
567 if (!strchr(filename,
'/')) {
569 sprintf(fn,
"%s/%s",
qdir, filename);
574 if (stat(filename, &st)) {
579 if (!S_ISREG(st.st_mode)) {
589 if (cur->
mtime == when && !strcmp(filename, cur->
name)) {
595 if ((res = when) > now || (res =
scan_service(filename, now)) > 0) {
596 if (!(
new =
ast_calloc(1,
sizeof(*
new) + strlen(filename) + 1))) {
601 strcpy(new->name, filename);
608 if (cur->
mtime > new->mtime) {
629 if (!strcmp(cur->
name, filename)) {
634 if (!(cur =
ast_calloc(1,
sizeof(*cur) + strlen(filename) + 1))) {
637 strcpy(cur->
name, filename);
648 if (!strcmp(cur->
name, filename)) {
660 time_t now = time(
NULL);
663 if (cur->
mtime > now) {
679 if (!strcmp(cur->
name, filename)) {
695 struct timespec ts = { .tv_sec = 1 };
699 struct inotify_event *iev;
700 char buf[8192] __attribute__((aligned (
sizeof(
int))));
701 struct pollfd pfd = { .fd =
inotify_fd, .events = POLLIN };
703 struct timespec nowait = { .tv_sec = 0, .tv_nsec = 1 };
711 nanosleep(&ts,
NULL);
726 inotify_add_watch(
inotify_fd,
qdir, IN_CREATE | IN_OPEN | IN_CLOSE_WRITE | IN_MOVED_TO);
730 if (!(dir = opendir(
qdir))) {
736 EV_SET(&kev, dirfd(dir), EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_CLEAR, NOTE_WRITE, 0,
NULL);
742 while ((de = readdir(dir))) {
761 int waittime =
next == INT_MAX ? -1 : (
next - now) * 1000;
766 if ((res = poll(&pfd, 1, waittime)) > 0 && (stage = 1) &&
770 for (iev = (
void *)
buf; res >=
sizeof(*iev); iev = (
struct inotify_event *) (((
char *) iev) +
len)) {
787 if (iev->mask & IN_CREATE) {
789 }
else if (iev->mask & IN_OPEN) {
791 }
else if (iev->mask & IN_CLOSE_WRITE) {
793 }
else if (iev->mask & IN_MOVED_TO) {
796 ast_log(
LOG_ERROR,
"Unexpected event %d for file '%s'\n", (
int) iev->mask, iev->name);
799 len =
sizeof(*iev) + iev->len;
802 }
else if (res < 0 &&
errno != EINTR &&
errno != EAGAIN) {
803 ast_debug(1,
"Got an error back from %s(2): %s\n", stage ?
"read" :
"poll", strerror(
errno));
811 if (next == INT_MAX) {
814 struct timespec ts2 = { .tv_sec = (
unsigned long int)(next - now), .tv_nsec = 0 };
817 if ((num_events < 0) || (
event.flags == EV_ERROR)) {
820 }
else if (num_events == 0) {
826 while ((de = readdir(dir))) {
858 struct timespec ts = { .tv_sec = 1 };
861 nanosleep(&ts,
NULL);
866 nanosleep(&ts,
NULL);
869 if (stat(
qdir, &st)) {
875 if (!force_poll && st.st_mtime ==
last && (!next || now < next)) {
884 printf(
"atime: %ld, mtime: %ld, ctime: %ld\n", st.st_atime, st.st_mtime, st.st_ctime);
885 printf(
"Ooh, something changed / timeout\n");
888 if (!(dir = opendir(
qdir))) {
899 force_poll = (st.st_mtime == now);
903 while ((de = readdir(dir))) {
904 snprintf(fn,
sizeof(fn),
"%s/%s",
qdir, de->d_name);
909 if (!S_ISREG(st.st_mode)) {
913 if (st.st_mtime <= now) {
917 if (!next || res < next) {
929 if (!next || st.st_mtime < next) {
struct sla_ringing_trunk * last
Asterisk main include file. File version handling, generic pbx functions.
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
#define ast_calloc(num, len)
A wrapper for calloc()
CallerID (and other GR30) management and generation Includes code and algorithms from the Zapata libr...
int ast_callerid_split(const char *src, char *name, int namelen, char *num, int numlen)
General Asterisk PBX channel definitions.
const char * ast_channel_reason2str(int reason)
return an english explanation of the code returned thru __ast_request_and_dial's 'outstate' argument
Generic File Format Support. Should be included by clients of the file handling routines....
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
char * strsep(char **str, const char *delims)
#define ast_variable_new(name, value, filename)
#define ast_variable_list_append(head, new_var)
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
Support for logging to various files, console and syslog Configuration in file logger....
#define ast_debug(level,...)
Log a DEBUG message.
#define ast_verb(level,...)
#define AST_LIST_HEAD_STATIC(name, type)
Defines a structure to be used to hold a list of specified type, statically initialized.
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
#define AST_LIST_HEAD_NOLOCK_STATIC(name, type)
Defines a structure to be used to hold a list of specified type, statically initialized.
#define AST_LIST_ENTRY(type)
Declare a forward link structure inside a list entry.
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
#define AST_LIST_INSERT_BEFORE_CURRENT(elm, field)
Inserts a list entry before the current entry during a traversal.
#define AST_LIST_LOCK(head)
Locks a list.
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
Asterisk locking-related definitions:
Asterisk module definitions.
#define AST_MODULE_INFO_STANDARD(keystr, desc)
#define ASTERISK_GPL_KEY
The text the key() function should return.
@ AST_MODULE_LOAD_FAILURE
Module could not be loaded properly.
@ AST_MODULE_LOAD_SUCCESS
@ AST_MODULE_LOAD_DECLINE
Module has failed to load, may be in an inconsistent state.
Options provided by main asterisk program.
Asterisk file paths, configured in asterisk.conf.
const char * ast_config_AST_SPOOL_DIR
Core PBX routines and definitions.
@ AST_OUTGOING_WAIT_COMPLETE
int ast_pbx_outgoing_app(const char *type, struct ast_format_cap *cap, const char *addr, int timeout, const char *app, const char *appdata, int *reason, int synchronous, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel, const struct ast_assigned_ids *assignedids)
Synchronously or asynchronously make an outbound call and execute an application on the channel.
int ast_pbx_outgoing_exten(const char *type, struct ast_format_cap *cap, const char *addr, int timeout, const char *context, const char *exten, int priority, int *reason, int synchronous, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel, int early_media, const struct ast_assigned_ids *assignedids)
Synchronously or asynchronously make an outbound call and send it to a particular extension.
static void append_variable(struct outgoing *o, const char *name, const char *value)
static void queue_file_write(const char *filename)
static void free_outgoing(struct outgoing *o)
static struct outgoing * new_outgoing(const char *fn)
static void safe_append(struct outgoing *o, time_t now, char *s)
static void queue_file_create(const char *filename)
static void launch_service(struct outgoing *o)
static void * scan_thread(void *unused)
@ SPOOL_FLAG_ALWAYS_DELETE
static void queue_file(const char *filename, time_t when)
static char qdonedir[255]
static void * attempt_thread(void *data)
static int load_module(void)
static void queue_file_open(const char *filename)
static int unload_module(void)
static int scan_service(const char *fn, time_t now)
static void parse_line(char *line, unsigned int lineno, struct outgoing *o)
static void queue_created_files(void)
static int apply_outgoing(struct outgoing *o, FILE *f)
static int remove_from_queue(struct outgoing *o, const char *status)
Remove a call file from the outgoing queue optionally moving it in the archive dir.
#define AST_DECLARE_STRING_FIELDS(field_list)
Declare the fields needed in a structure.
#define AST_STRING_FIELD(name)
Declare a string field.
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is "true"....
static force_inline int attribute_pure ast_strlen_zero(const char *s)
char * ast_trim_blanks(char *str)
Trims trailing whitespace characters from a string.
char * ast_skip_blanks(const char *str)
Gets a pointer to the first non-whitespace character in a string.
Structure used to handle boolean flags.
Structure for variables, used for configurations and for channel variables.
struct direntry::@420 list
struct ast_format_cap * capabilities
struct ast_variable * vars
const ast_string_field cid_num
const ast_string_field fn
const ast_string_field account
const ast_string_field tech
const ast_string_field app
const ast_string_field data
const ast_string_field context
const ast_string_field exten
const ast_string_field cid_name
const ast_string_field dest
Time-related functions and macros.
#define ast_test_flag(p, flag)
#define ast_set2_flag(p, value, flag)
int ast_mkdir(const char *path, int mode)
Recursively create directory path.
#define ast_pthread_create_detached(a, b, c, d)
#define ast_pthread_create_detached_background(a, b, c, d)
#define ast_set_flag(p, flag)