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
char * strsep(char **str, const char *delims)
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)
#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)
static void queue_file(const char *filename, time_t when)
static char qdonedir[255]
static void * attempt_thread(void *data)
@ SPOOL_FLAG_ALWAYS_DELETE
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 *attribute_pure 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::@455 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)