Wed Jan 8 2020 09:50:17

Asterisk developer's documentation


pbx_spool.c File Reference

Full-featured outgoing call spool support. More...

#include "asterisk.h"
#include <sys/stat.h>
#include <time.h>
#include <utime.h>
#include <dirent.h>
#include <sys/inotify.h>
#include "asterisk/paths.h"
#include "asterisk/lock.h"
#include "asterisk/file.h"
#include "asterisk/logger.h"
#include "asterisk/channel.h"
#include "asterisk/callerid.h"
#include "asterisk/pbx.h"
#include "asterisk/module.h"
#include "asterisk/utils.h"
#include "asterisk/options.h"

Go to the source code of this file.

Data Structures

struct  createlist
 
struct  direntry
 
struct  dirlist
 
struct  openlist
 
struct  outgoing
 

Enumerations

enum  { SPOOL_FLAG_ALWAYS_DELETE = (1 << 0), SPOOL_FLAG_ARCHIVE = (1 << 1) }
 

Functions

static void __reg_module (void)
 
static void __unreg_module (void)
 
static int apply_outgoing (struct outgoing *o, FILE *f)
 
static void * attempt_thread (void *data)
 
static void free_outgoing (struct outgoing *o)
 
static void launch_service (struct outgoing *o)
 
static int load_module (void)
 
static struct outgoingnew_outgoing (const char *fn)
 
static void queue_created_files (void)
 
static void queue_file (const char *filename, time_t when)
 
static void queue_file_create (const char *filename)
 
static void queue_file_open (const char *filename)
 
static void queue_file_write (const char *filename)
 
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. More...
 
static void safe_append (struct outgoing *o, time_t now, char *s)
 
static int scan_service (const char *fn, time_t now)
 
static void * scan_thread (void *unused)
 
static int unload_module (void)
 

Variables

static struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Outgoing Spool Support" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, }
 
static struct ast_module_infoast_module_info = &__mod_info
 
static struct createlist createlist = { .first = NULL, .last = NULL, }
 
static struct dirlist dirlist = { .first = NULL, .last = NULL, .lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } , }
 
static struct openlist openlist = { .first = NULL, .last = NULL, }
 
static char qdir [255]
 
static char qdonedir [255]
 

Detailed Description

Full-featured outgoing call spool support.

Definition in file pbx_spool.c.

Enumeration Type Documentation

anonymous enum
Enumerator
SPOOL_FLAG_ALWAYS_DELETE 

Always delete the call file after a call succeeds or the maximum number of retries is exceeded, even if the modification time of the call file is in the future.

SPOOL_FLAG_ARCHIVE 

Definition at line 62 of file pbx_spool.c.

62  {
63  /*! Always delete the call file after a call succeeds or the
64  * maximum number of retries is exceeded, even if the
65  * modification time of the call file is in the future.
66  */
67  SPOOL_FLAG_ALWAYS_DELETE = (1 << 0),
68  /* Don't unlink the call file after processing, move in qdonedir */
69  SPOOL_FLAG_ARCHIVE = (1 << 1),
70 };

Function Documentation

static void __reg_module ( void  )
static

Definition at line 893 of file pbx_spool.c.

static void __unreg_module ( void  )
static

Definition at line 893 of file pbx_spool.c.

static int apply_outgoing ( struct outgoing o,
FILE *  f 
)
static

Definition at line 147 of file pbx_spool.c.

References app, outgoing::app, ast_callerid_split(), ast_log(), ast_parse_allow_disallow(), ast_set2_flag, ast_skip_blanks(), ast_string_field_set, ast_strlen_zero(), ast_trim_blanks(), ast_true(), ast_variable_new(), outgoing::callingpid, cid_name, cid_num, context, outgoing::dest, outgoing::exten, exten, outgoing::fn, outgoing::format, last, LOG_NOTICE, LOG_WARNING, outgoing::maxretries, ast_variable::next, outgoing::options, outgoing::priority, outgoing::retries, outgoing::retrytime, SPOOL_FLAG_ALWAYS_DELETE, SPOOL_FLAG_ARCHIVE, strsep(), outgoing::tech, var, outgoing::vars, and outgoing::waittime.

Referenced by scan_service().

148 {
149  char buf[256];
150  char *c, *c2;
151  int lineno = 0;
152  struct ast_variable *var, *last = o->vars;
153 
154  while (last && last->next) {
155  last = last->next;
156  }
157 
158  while(fgets(buf, sizeof(buf), f)) {
159  lineno++;
160  /* Trim comments */
161  c = buf;
162  while ((c = strchr(c, '#'))) {
163  if ((c == buf) || (*(c-1) == ' ') || (*(c-1) == '\t'))
164  *c = '\0';
165  else
166  c++;
167  }
168 
169  c = buf;
170  while ((c = strchr(c, ';'))) {
171  if ((c > buf) && (c[-1] == '\\')) {
172  memmove(c - 1, c, strlen(c) + 1);
173  c++;
174  } else {
175  *c = '\0';
176  break;
177  }
178  }
179 
180  /* Trim trailing white space */
181  ast_trim_blanks(buf);
182  if (ast_strlen_zero(buf)) {
183  continue;
184  }
185  c = strchr(buf, ':');
186  if (!c) {
187  ast_log(LOG_NOTICE, "Syntax error at line %d of %s\n", lineno, o->fn);
188  continue;
189  }
190  *c = '\0';
191  c = ast_skip_blanks(c + 1);
192 #if 0
193  printf("'%s' is '%s' at line %d\n", buf, c, lineno);
194 #endif
195  if (!strcasecmp(buf, "channel")) {
196  if ((c2 = strchr(c, '/'))) {
197  *c2 = '\0';
198  c2++;
199  ast_string_field_set(o, tech, c);
200  ast_string_field_set(o, dest, c2);
201  } else {
202  ast_log(LOG_NOTICE, "Channel should be in form Tech/Dest at line %d of %s\n", lineno, o->fn);
203  }
204  } else if (!strcasecmp(buf, "callerid")) {
205  char cid_name[80] = {0}, cid_num[80] = {0};
206  ast_callerid_split(c, cid_name, sizeof(cid_name), cid_num, sizeof(cid_num));
208  ast_string_field_set(o, cid_name, cid_name);
209  } else if (!strcasecmp(buf, "application")) {
210  ast_string_field_set(o, app, c);
211  } else if (!strcasecmp(buf, "data")) {
212  ast_string_field_set(o, data, c);
213  } else if (!strcasecmp(buf, "maxretries")) {
214  if (sscanf(c, "%30d", &o->maxretries) != 1) {
215  ast_log(LOG_WARNING, "Invalid max retries at line %d of %s\n", lineno, o->fn);
216  o->maxretries = 0;
217  }
218  } else if (!strcasecmp(buf, "codecs")) {
219  ast_parse_allow_disallow(NULL, &o->format, c, 1);
220  } else if (!strcasecmp(buf, "context")) {
222  } else if (!strcasecmp(buf, "extension")) {
224  } else if (!strcasecmp(buf, "priority")) {
225  if ((sscanf(c, "%30d", &o->priority) != 1) || (o->priority < 1)) {
226  ast_log(LOG_WARNING, "Invalid priority at line %d of %s\n", lineno, o->fn);
227  o->priority = 1;
228  }
229  } else if (!strcasecmp(buf, "retrytime")) {
230  if ((sscanf(c, "%30d", &o->retrytime) != 1) || (o->retrytime < 1)) {
231  ast_log(LOG_WARNING, "Invalid retrytime at line %d of %s\n", lineno, o->fn);
232  o->retrytime = 300;
233  }
234  } else if (!strcasecmp(buf, "waittime")) {
235  if ((sscanf(c, "%30d", &o->waittime) != 1) || (o->waittime < 1)) {
236  ast_log(LOG_WARNING, "Invalid waittime at line %d of %s\n", lineno, o->fn);
237  o->waittime = 45;
238  }
239  } else if (!strcasecmp(buf, "retry")) {
240  o->retries++;
241  } else if (!strcasecmp(buf, "startretry")) {
242  if (sscanf(c, "%30ld", &o->callingpid) != 1) {
243  ast_log(LOG_WARNING, "Unable to retrieve calling PID!\n");
244  o->callingpid = 0;
245  }
246  } else if (!strcasecmp(buf, "endretry") || !strcasecmp(buf, "abortretry")) {
247  o->callingpid = 0;
248  o->retries++;
249  } else if (!strcasecmp(buf, "delayedretry")) {
250  } else if (!strcasecmp(buf, "setvar") || !strcasecmp(buf, "set")) {
251  c2 = c;
252  strsep(&c2, "=");
253  if (c2) {
254  var = ast_variable_new(c, c2, o->fn);
255  if (var) {
256  /* Always insert at the end, because some people want to treat the spool file as a script */
257  if (last) {
258  last->next = var;
259  } else {
260  o->vars = var;
261  }
262  last = var;
263  }
264  } else
265  ast_log(LOG_WARNING, "Malformed \"%s\" argument. Should be \"%s: variable=value\"\n", buf, buf);
266  } else if (!strcasecmp(buf, "account")) {
267  ast_string_field_set(o, account, c);
268  } else if (!strcasecmp(buf, "alwaysdelete")) {
270  } else if (!strcasecmp(buf, "archive")) {
272  } else {
273  ast_log(LOG_WARNING, "Unknown keyword '%s' at line %d of %s\n", buf, lineno, o->fn);
274  }
275  }
277  ast_log(LOG_WARNING, "At least one of app or extension must be specified, along with tech and dest in file %s\n", o->fn);
278  return -1;
279  }
280  return 0;
281 }
static char exten[AST_MAX_EXTENSION]
Definition: chan_alsa.c:109
char * strsep(char **str, const char *delims)
int ast_callerid_split(const char *src, char *name, int namelen, char *num, int numlen)
Definition: callerid.c:1093
#define ast_set2_flag(p, value, flag)
Definition: utils.h:94
#define LOG_WARNING
Definition: logger.h:144
int maxretries
Definition: pbx_spool.c:77
int priority
Definition: pbx_spool.c:94
int waittime
Definition: pbx_spool.c:79
Structure for variables, used for configurations and for channel variables.
Definition: config.h:75
#define var
Definition: ast_expr2f.c:606
const ast_string_field app
Definition: pbx_spool.c:93
int retries
Definition: pbx_spool.c:76
static char cid_num[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:157
const ast_string_field exten
Definition: pbx_spool.c:93
static const char app[]
Definition: app_adsiprog.c:49
struct ast_variable * vars
Definition: pbx_spool.c:95
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
struct sla_ringing_trunk * last
Definition: app_meetme.c:965
struct ast_flags options
Definition: pbx_spool.c:97
int attribute_pure ast_true(const char *val)
Make sure something is true. Determine if a string containing a boolean value is &quot;true&quot;. This function checks to see whether a string passed to it is an indication of an &quot;true&quot; value. It checks to see if the string is &quot;yes&quot;, &quot;true&quot;, &quot;y&quot;, &quot;t&quot;, &quot;on&quot; or &quot;1&quot;.
Definition: utils.c:1533
int retrytime
Definition: pbx_spool.c:78
char * ast_skip_blanks(const char *str)
Gets a pointer to the first non-whitespace character in a string.
Definition: strings.h:97
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
char * ast_trim_blanks(char *str)
Trims trailing whitespace characters from a string.
Definition: strings.h:122
static struct ast_format f[]
Definition: format_g726.c:181
const ast_string_field fn
Definition: pbx_spool.c:93
static char cid_name[AST_MAX_EXTENSION]
Definition: chan_mgcp.c:158
const ast_string_field dest
Definition: pbx_spool.c:93
const ast_string_field tech
Definition: pbx_spool.c:93
long callingpid
Definition: pbx_spool.c:80
struct ast_variable * next
Definition: config.h:82
static char context[AST_MAX_CONTEXT]
Definition: chan_alsa.c:107
format_t format
Definition: pbx_spool.c:81
struct ast_variable * ast_variable_new(const char *name, const char *value, const char *filename)
Definition: config.c:278
int ast_parse_allow_disallow(struct ast_codec_pref *pref, format_t *mask, const char *list, int allowing)
Parse an &quot;allow&quot; or &quot;deny&quot; line in a channel or device configuration and update the capabilities mask...
Definition: frame.c:1272
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:344
static void* attempt_thread ( void *  data)
static

Definition at line 358 of file pbx_spool.c.

References outgoing::account, outgoing::app, ast_channel_reason2str(), ast_log(), ast_pbx_outgoing_app(), ast_pbx_outgoing_exten(), ast_strlen_zero(), ast_verb, outgoing::cid_name, outgoing::cid_num, outgoing::context, outgoing::data, outgoing::dest, outgoing::exten, outgoing::fn, outgoing::format, free_outgoing(), LOG_NOTICE, outgoing::maxretries, outgoing::priority, queue_file(), remove_from_queue(), outgoing::retries, outgoing::retrytime, safe_append(), outgoing::tech, outgoing::vars, and outgoing::waittime.

Referenced by launch_service().

359 {
360  struct outgoing *o = data;
361  int res, reason;
362  if (!ast_strlen_zero(o->app)) {
363  ast_verb(3, "Attempting call on %s/%s for application %s(%s) (Retry %d)\n", o->tech, o->dest, o->app, o->data, o->retries);
364  res = ast_pbx_outgoing_app(o->tech, o->format, (void *) o->dest, o->waittime * 1000, o->app, o->data, &reason, 2 /* wait to finish */, o->cid_num, o->cid_name, o->vars, o->account, NULL);
365  o->vars = NULL;
366  } else {
367  ast_verb(3, "Attempting call on %s/%s for %s@%s:%d (Retry %d)\n", o->tech, o->dest, o->exten, o->context,o->priority, o->retries);
368  res = ast_pbx_outgoing_exten(o->tech, o->format, (void *) o->dest, o->waittime * 1000, o->context, o->exten, o->priority, &reason, 2 /* wait to finish */, o->cid_num, o->cid_name, o->vars, o->account, NULL);
369  o->vars = NULL;
370  }
371  if (res) {
372  ast_log(LOG_NOTICE, "Call failed to go through, reason (%d) %s\n", reason, ast_channel_reason2str(reason));
373  if (o->retries >= o->maxretries + 1) {
374  /* Max retries exceeded */
375  ast_log(LOG_NOTICE, "Queued call to %s/%s expired without completion after %d attempt%s\n", o->tech, o->dest, o->retries - 1, ((o->retries - 1) != 1) ? "s" : "");
376  remove_from_queue(o, "Expired");
377  } else {
378  /* Notate that the call is still active */
379  safe_append(o, time(NULL), "EndRetry");
380 #if defined(HAVE_INOTIFY) || defined(HAVE_KQUEUE)
381  queue_file(o->fn, time(NULL) + o->retrytime);
382 #endif
383  }
384  } else {
385  ast_log(LOG_NOTICE, "Call completed to %s/%s\n", o->tech, o->dest);
386  remove_from_queue(o, "Completed");
387  }
388  free_outgoing(o);
389  return NULL;
390 }
const ast_string_field cid_name
Definition: pbx_spool.c:93
int maxretries
Definition: pbx_spool.c:77
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.
Definition: pbx_spool.c:307
int priority
Definition: pbx_spool.c:94
int waittime
Definition: pbx_spool.c:79
const ast_string_field cid_num
Definition: pbx_spool.c:93
const ast_string_field app
Definition: pbx_spool.c:93
int retries
Definition: pbx_spool.c:76
static void free_outgoing(struct outgoing *o)
Definition: pbx_spool.c:104
const ast_string_field context
Definition: pbx_spool.c:93
#define ast_verb(level,...)
Definition: logger.h:243
const ast_string_field exten
Definition: pbx_spool.c:93
static void queue_file(const char *filename, time_t when)
Definition: pbx_spool.c:488
const ast_string_field data
Definition: pbx_spool.c:93
struct ast_variable * vars
Definition: pbx_spool.c:95
const ast_string_field account
Definition: pbx_spool.c:93
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
int ast_pbx_outgoing_exten(const char *type, format_t format, void *data, int timeout, const char *context, const char *exten, int priority, int *reason, int sync, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel)
Definition: pbx.c:9375
int retrytime
Definition: pbx_spool.c:78
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
const ast_string_field fn
Definition: pbx_spool.c:93
const ast_string_field dest
Definition: pbx_spool.c:93
const ast_string_field tech
Definition: pbx_spool.c:93
static void safe_append(struct outgoing *o, time_t now, char *s)
Definition: pbx_spool.c:283
const char * ast_channel_reason2str(int reason)
return an english explanation of the code returned thru __ast_request_and_dial&#39;s &#39;outstate&#39; argument ...
Definition: channel.c:5313
int ast_pbx_outgoing_app(const char *type, format_t format, void *data, int timeout, const char *app, const char *appdata, int *reason, int sync, const char *cid_num, const char *cid_name, struct ast_variable *vars, const char *account, struct ast_channel **locked_channel)
Definition: pbx.c:9544
format_t format
Definition: pbx_spool.c:81
static void free_outgoing ( struct outgoing o)
static

Definition at line 104 of file pbx_spool.c.

References ast_free, ast_string_field_free_memory, ast_variables_destroy(), and outgoing::vars.

Referenced by attempt_thread(), launch_service(), new_outgoing(), and scan_service().

105 {
106  if (o->vars) {
108  }
110  ast_free(o);
111 }
void ast_variables_destroy(struct ast_variable *var)
Free variable list.
Definition: config.c:586
struct ast_variable * vars
Definition: pbx_spool.c:95
#define ast_free(a)
Definition: astmm.h:97
#define ast_string_field_free_memory(x)
free all memory - to be called before destroying the object
Definition: stringfields.h:253
static void launch_service ( struct outgoing o)
static

Definition at line 392 of file pbx_spool.c.

References ast_log(), ast_pthread_create_detached, attempt_thread(), free_outgoing(), and LOG_WARNING.

Referenced by scan_service().

393 {
394  pthread_t t;
395  int ret;
396 
397  if ((ret = ast_pthread_create_detached(&t, NULL, attempt_thread, o))) {
398  ast_log(LOG_WARNING, "Unable to create thread :( (returned error: %d)\n", ret);
399  free_outgoing(o);
400  }
401 }
#define ast_pthread_create_detached(a, b, c, d)
Definition: utils.h:422
#define LOG_WARNING
Definition: logger.h:144
static void * attempt_thread(void *data)
Definition: pbx_spool.c:358
static void free_outgoing(struct outgoing *o)
Definition: pbx_spool.c:104
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
static int load_module ( void  )
static

Definition at line 874 of file pbx_spool.c.

References ast_config_AST_SPOOL_DIR, ast_log(), ast_mkdir(), AST_MODULE_LOAD_DECLINE, AST_MODULE_LOAD_FAILURE, AST_MODULE_LOAD_SUCCESS, ast_pthread_create_detached_background, LOG_WARNING, scan_thread(), and thread.

875 {
876  pthread_t thread;
877  int ret;
878  snprintf(qdir, sizeof(qdir), "%s/%s", ast_config_AST_SPOOL_DIR, "outgoing");
879  if (ast_mkdir(qdir, 0777)) {
880  ast_log(LOG_WARNING, "Unable to create queue directory %s -- outgoing spool disabled\n", qdir);
882  }
883  snprintf(qdonedir, sizeof(qdir), "%s/%s", ast_config_AST_SPOOL_DIR, "outgoing_done");
884 
885  if ((ret = ast_pthread_create_detached_background(&thread, NULL, scan_thread, NULL))) {
886  ast_log(LOG_WARNING, "Unable to create thread :( (returned error: %d)\n", ret);
888  }
889 
891 }
pthread_t thread
Definition: app_meetme.c:962
static char qdonedir[255]
Definition: pbx_spool.c:73
#define LOG_WARNING
Definition: logger.h:144
static char qdir[255]
Definition: pbx_spool.c:72
#define ast_pthread_create_detached_background(a, b, c, d)
Definition: utils.h:431
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
const char * ast_config_AST_SPOOL_DIR
Definition: asterisk.c:259
static void * scan_thread(void *unused)
Definition: pbx_spool.c:618
int ast_mkdir(const char *path, int mode)
Recursively create directory path.
Definition: utils.c:2151
static struct outgoing* new_outgoing ( const char *  fn)
static

Definition at line 113 of file pbx_spool.c.

References ast_calloc, AST_FORMAT_SLINEAR, ast_free, ast_set_flag, ast_string_field_init, ast_string_field_set, ast_strlen_zero(), outgoing::fn, outgoing::format, free_outgoing(), outgoing::options, outgoing::priority, outgoing::retrytime, SPOOL_FLAG_ALWAYS_DELETE, and outgoing::waittime.

Referenced by scan_service().

114 {
115  struct outgoing *o;
116 
117  o = ast_calloc(1, sizeof(*o));
118  if (!o) {
119  return NULL;
120  }
121 
122  /* Initialize the new object. */
123  o->priority = 1;
124  o->retrytime = 300;
125  o->waittime = 45;
128  if (ast_string_field_init(o, 128)) {
129  /*
130  * No need to call free_outgoing here since the failure was to
131  * allocate string fields and no variables have been allocated
132  * yet.
133  */
134  ast_free(o);
135  return NULL;
136  }
138  if (ast_strlen_zero(o->fn)) {
139  /* String field set failed. Since this string is important we must fail. */
140  free_outgoing(o);
141  return NULL;
142  }
143 
144  return o;
145 }
#define ast_set_flag(p, flag)
Definition: utils.h:70
int priority
Definition: pbx_spool.c:94
int waittime
Definition: pbx_spool.c:79
static void free_outgoing(struct outgoing *o)
Definition: pbx_spool.c:104
#define ast_string_field_init(x, size)
Initialize a field pool and fields.
Definition: stringfields.h:249
static force_inline int attribute_pure ast_strlen_zero(const char *s)
Definition: strings.h:63
struct ast_flags options
Definition: pbx_spool.c:97
int retrytime
Definition: pbx_spool.c:78
#define ast_free(a)
Definition: astmm.h:97
const ast_string_field fn
Definition: pbx_spool.c:93
#define AST_FORMAT_SLINEAR
Definition: frame.h:254
#define ast_calloc(a, b)
Definition: astmm.h:82
format_t format
Definition: pbx_spool.c:81
#define ast_string_field_set(x, field, data)
Set a field to a simple string value.
Definition: stringfields.h:344
static void queue_created_files ( void  )
static

Definition at line 585 of file pbx_spool.c.

References ast_free, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, direntry::mtime, direntry::name, and queue_file().

Referenced by scan_thread().

586 {
587  struct direntry *cur;
588  time_t now = time(NULL);
589 
591  if (cur->mtime > now) {
592  break;
593  }
594 
596  queue_file(cur->name, 0);
597  ast_free(cur);
598  }
600 }
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:600
static void queue_file(const char *filename, time_t when)
Definition: pbx_spool.c:488
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: linkedlists.h:554
char name[0]
Definition: pbx_spool.c:477
#define ast_free(a)
Definition: astmm.h:97
struct direntry::@320 list
time_t mtime
Definition: pbx_spool.c:476
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:528
static void queue_file ( const char *  filename,
time_t  when 
)
static

Definition at line 488 of file pbx_spool.c.

References ast_alloca, ast_calloc, AST_LIST_EMPTY, AST_LIST_INSERT_BEFORE_CURRENT, AST_LIST_INSERT_HEAD, AST_LIST_INSERT_TAIL, AST_LIST_LOCK, AST_LIST_TRAVERSE, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, AST_LIST_UNLOCK, ast_log(), errno, LOG_WARNING, direntry::mtime, direntry::name, and scan_service().

Referenced by attempt_thread(), queue_created_files(), queue_file_write(), and scan_thread().

489 {
490  struct stat st;
491  struct direntry *cur, *new;
492  int res;
493  time_t now = time(NULL);
494 
495  if (!strchr(filename, '/')) {
496  char *fn = ast_alloca(strlen(qdir) + strlen(filename) + 2);
497  sprintf(fn, "%s/%s", qdir, filename); /* SAFE */
498  filename = fn;
499  }
500 
501  if (when == 0) {
502  if (stat(filename, &st)) {
503  ast_log(LOG_WARNING, "Unable to stat %s: %s\n", filename, strerror(errno));
504  return;
505  }
506 
507  if (!S_ISREG(st.st_mode)) {
508  return;
509  }
510 
511  when = st.st_mtime;
512  }
513 
514  /* Need to check the existing list in order to avoid duplicates. */
516  AST_LIST_TRAVERSE(&dirlist, cur, list) {
517  if (cur->mtime == when && !strcmp(filename, cur->name)) {
519  return;
520  }
521  }
522 
523  if ((res = when) > now || (res = scan_service(filename, now)) > 0) {
524  if (!(new = ast_calloc(1, sizeof(*new) + strlen(filename) + 1))) {
526  return;
527  }
528  new->mtime = res;
529  strcpy(new->name, filename);
530  /* List is ordered by mtime */
531  if (AST_LIST_EMPTY(&dirlist)) {
533  } else {
534  int found = 0;
536  if (cur->mtime > new->mtime) {
538  found = 1;
539  break;
540  }
541  }
543  if (!found) {
545  }
546  }
547  }
549 }
static int scan_service(const char *fn, time_t now)
Definition: pbx_spool.c:404
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
#define ast_alloca(size)
call __builtin_alloca to ensure we get gcc builtin semantics
Definition: utils.h:653
#define LOG_WARNING
Definition: logger.h:144
static char qdir[255]
Definition: pbx_spool.c:72
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
Definition: linkedlists.h:449
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:600
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:716
char name[0]
Definition: pbx_spool.c:477
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 AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
#define AST_LIST_INSERT_HEAD(head, elm, field)
Inserts a list entry at the head of a list.
Definition: linkedlists.h:696
int errno
struct direntry::@320 list
time_t mtime
Definition: pbx_spool.c:476
#define ast_calloc(a, b)
Definition: astmm.h:82
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:528
#define AST_LIST_INSERT_BEFORE_CURRENT(elm, field)
Inserts a list entry before the current entry during a traversal.
Definition: linkedlists.h:584
static void queue_file_create ( const char *  filename)
static

Definition at line 552 of file pbx_spool.c.

References ast_calloc, AST_LIST_INSERT_TAIL, AST_LIST_TRAVERSE, direntry::mtime, and direntry::name.

Referenced by scan_thread().

553 {
554  struct direntry *cur;
555 
557  if (!strcmp(cur->name, filename)) {
558  return;
559  }
560  }
561 
562  if (!(cur = ast_calloc(1, sizeof(*cur) + strlen(filename) + 1))) {
563  return;
564  }
565  strcpy(cur->name, filename);
566  /* We'll handle this file unless an IN_OPEN event occurs within 2 seconds */
567  cur->mtime = time(NULL) + 2;
569 }
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:716
char name[0]
Definition: pbx_spool.c:477
#define AST_LIST_TRAVERSE(head, var, field)
Loops over (traverses) the entries in a list.
Definition: linkedlists.h:490
struct direntry::@320 list
time_t mtime
Definition: pbx_spool.c:476
#define ast_calloc(a, b)
Definition: astmm.h:82
static void queue_file_open ( const char *  filename)
static

Definition at line 571 of file pbx_spool.c.

References AST_LIST_INSERT_TAIL, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, and direntry::name.

Referenced by scan_thread().

572 {
573  struct direntry *cur;
574 
576  if (!strcmp(cur->name, filename)) {
579  break;
580  }
581  }
583 }
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:600
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: linkedlists.h:554
#define AST_LIST_INSERT_TAIL(head, elm, field)
Appends a list entry to the tail of a list.
Definition: linkedlists.h:716
char name[0]
Definition: pbx_spool.c:477
struct direntry::@320 list
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:528
static void queue_file_write ( const char *  filename)
static

Definition at line 602 of file pbx_spool.c.

References ast_free, AST_LIST_REMOVE_CURRENT, AST_LIST_TRAVERSE_SAFE_BEGIN, AST_LIST_TRAVERSE_SAFE_END, direntry::name, and queue_file().

Referenced by scan_thread().

603 {
604  struct direntry *cur;
605  /* Only queue entries where an IN_CREATE preceded the IN_CLOSE_WRITE */
607  if (!strcmp(cur->name, filename)) {
609  ast_free(cur);
610  queue_file(filename, 0);
611  break;
612  }
613  }
615 }
#define AST_LIST_TRAVERSE_SAFE_END
Closes a safe loop traversal block.
Definition: linkedlists.h:600
static void queue_file(const char *filename, time_t when)
Definition: pbx_spool.c:488
#define AST_LIST_REMOVE_CURRENT(field)
Removes the current entry from a list during a traversal.
Definition: linkedlists.h:554
char name[0]
Definition: pbx_spool.c:477
#define ast_free(a)
Definition: astmm.h:97
struct direntry::@320 list
#define AST_LIST_TRAVERSE_SAFE_BEGIN(head, var, field)
Loops safely over (traverses) the entries in a list.
Definition: linkedlists.h:528
static int remove_from_queue ( struct outgoing o,
const char *  status 
)
static

Remove a call file from the outgoing queue optionally moving it in the archive dir.

Parameters
othe pointer to outgoing struct
statusthe exit status of the call. Can be "Completed", "Failed" or "Expired"

Definition at line 307 of file pbx_spool.c.

References ast_log(), ast_mkdir(), ast_test_flag, f, outgoing::fn, LOG_WARNING, outgoing::options, SPOOL_FLAG_ALWAYS_DELETE, and SPOOL_FLAG_ARCHIVE.

Referenced by attempt_thread(), and scan_service().

308 {
309  FILE *f;
310  char newfn[256];
311  const char *bname;
312 
314  struct stat current_file_status;
315 
316  if (!stat(o->fn, &current_file_status)) {
317  if (time(NULL) < current_file_status.st_mtime) {
318  return 0;
319  }
320  }
321  }
322 
324  unlink(o->fn);
325  return 0;
326  }
327 
328  if (ast_mkdir(qdonedir, 0777)) {
329  ast_log(LOG_WARNING, "Unable to create queue directory %s -- outgoing spool archiving disabled\n", qdonedir);
330  unlink(o->fn);
331  return -1;
332  }
333 
334  if (!(bname = strrchr(o->fn, '/'))) {
335  bname = o->fn;
336  } else {
337  bname++;
338  }
339 
340  snprintf(newfn, sizeof(newfn), "%s/%s", qdonedir, bname);
341  /* If there is already a call file with the name in the archive dir, it will be overwritten. */
342  unlink(newfn);
343  if (rename(o->fn, newfn) != 0) {
344  unlink(o->fn);
345  return -1;
346  }
347 
348  /* Only append to the file AFTER we move it out of the watched directory,
349  * otherwise the fclose() causes another event for inotify(7) */
350  if ((f = fopen(newfn, "a"))) {
351  fprintf(f, "Status: %s\n", status);
352  fclose(f);
353  }
354 
355  return 0;
356 }
static char qdonedir[255]
Definition: pbx_spool.c:73
#define ast_test_flag(p, flag)
Definition: utils.h:63
#define LOG_WARNING
Definition: logger.h:144
struct ast_flags options
Definition: pbx_spool.c:97
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
static struct ast_format f[]
Definition: format_g726.c:181
const ast_string_field fn
Definition: pbx_spool.c:93
jack_status_t status
Definition: app_jack.c:143
int ast_mkdir(const char *path, int mode)
Recursively create directory path.
Definition: utils.c:2151
static void safe_append ( struct outgoing o,
time_t  now,
char *  s 
)
static

Definition at line 283 of file pbx_spool.c.

References ast_debug, ast_log(), ast_mainpid, outgoing::dest, errno, f, outgoing::fn, LOG_WARNING, outgoing::retries, outgoing::retrytime, and outgoing::tech.

Referenced by attempt_thread(), and scan_service().

284 {
285  FILE *f;
286  struct utimbuf tbuf = { .actime = now, .modtime = now + o->retrytime };
287 
288  ast_debug(1, "Outgoing %s/%s: %s\n", o->tech, o->dest, s);
289 
290  if ((f = fopen(o->fn, "a"))) {
291  fprintf(f, "\n%s: %ld %d (%ld)\n", s, (long)ast_mainpid, o->retries, (long) now);
292  fclose(f);
293  }
294 
295  /* Update the file time */
296  if (utime(o->fn, &tbuf)) {
297  ast_log(LOG_WARNING, "Unable to set utime on %s: %s\n", o->fn, strerror(errno));
298  }
299 }
#define LOG_WARNING
Definition: logger.h:144
int retries
Definition: pbx_spool.c:76
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
int retrytime
Definition: pbx_spool.c:78
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
int errno
static struct ast_format f[]
Definition: format_g726.c:181
const ast_string_field fn
Definition: pbx_spool.c:93
const ast_string_field dest
Definition: pbx_spool.c:93
const ast_string_field tech
Definition: pbx_spool.c:93
pid_t ast_mainpid
Definition: asterisk.c:199
static int scan_service ( const char *  fn,
time_t  now 
)
static
Todo:
XXX There is some odd delayed duplicate servicing of call files going on. We need to suppress the error message if the file does not exist as a result.

Definition at line 404 of file pbx_spool.c.

References apply_outgoing(), ast_debug, ast_log(), ast_mainpid, outgoing::callingpid, outgoing::dest, errno, f, outgoing::fn, free_outgoing(), launch_service(), LOG_DEBUG, LOG_NOTICE, LOG_WARNING, outgoing::maxretries, new_outgoing(), remove_from_queue(), outgoing::retries, outgoing::retrytime, safe_append(), and outgoing::tech.

Referenced by queue_file().

405 {
406  struct outgoing *o;
407  FILE *f;
408  int res;
409 
410  o = new_outgoing(fn);
411  if (!o) {
412  return -1;
413  }
414 
415  /* Attempt to open the file */
416  f = fopen(o->fn, "r");
417  if (!f) {
418 #if defined(HAVE_INOTIFY) || defined(HAVE_KQUEUE)
419  /*!
420  * \todo XXX There is some odd delayed duplicate servicing of
421  * call files going on. We need to suppress the error message
422  * if the file does not exist as a result.
423  */
424  if (errno != ENOENT)
425 #endif
426  {
427  ast_log(LOG_WARNING, "Unable to open %s: '%s'(%d), deleting\n",
428  o->fn, strerror(errno), (int) errno);
429  }
430  remove_from_queue(o, "Failed");
431  free_outgoing(o);
432  return -1;
433  }
434 
435  /* Read in and verify the contents */
436  res = apply_outgoing(o, f);
437  fclose(f);
438  if (res) {
439  ast_log(LOG_WARNING, "Invalid file contents in %s, deleting\n", o->fn);
440  remove_from_queue(o, "Failed");
441  free_outgoing(o);
442  return -1;
443  }
444 
445  ast_debug(1, "Filename: %s, Retries: %d, max: %d\n", o->fn, o->retries, o->maxretries);
446  if (o->retries <= o->maxretries) {
447  now += o->retrytime;
448  if (o->callingpid && (o->callingpid == ast_mainpid)) {
449  safe_append(o, time(NULL), "DelayedRetry");
450  ast_log(LOG_DEBUG, "Delaying retry since we're currently running '%s'\n", o->fn);
451  free_outgoing(o);
452  } else {
453  /* Increment retries */
454  o->retries++;
455  /* If someone else was calling, they're presumably gone now
456  so abort their retry and continue as we were... */
457  if (o->callingpid)
458  safe_append(o, time(NULL), "AbortRetry");
459 
460  safe_append(o, now, "StartRetry");
461  launch_service(o);
462  }
463  return now;
464  }
465 
466  ast_log(LOG_NOTICE, "Queued call to %s/%s expired without completion after %d attempt%s\n",
467  o->tech, o->dest, o->retries - 1, ((o->retries - 1) != 1) ? "s" : "");
468  remove_from_queue(o, "Expired");
469  free_outgoing(o);
470  return 0;
471 }
static struct outgoing * new_outgoing(const char *fn)
Definition: pbx_spool.c:113
static int apply_outgoing(struct outgoing *o, FILE *f)
Definition: pbx_spool.c:147
#define LOG_WARNING
Definition: logger.h:144
int maxretries
Definition: pbx_spool.c:77
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.
Definition: pbx_spool.c:307
int retries
Definition: pbx_spool.c:76
static void free_outgoing(struct outgoing *o)
Definition: pbx_spool.c:104
#define LOG_DEBUG
Definition: logger.h:122
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
static void launch_service(struct outgoing *o)
Definition: pbx_spool.c:392
int retrytime
Definition: pbx_spool.c:78
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 errno
static struct ast_format f[]
Definition: format_g726.c:181
const ast_string_field fn
Definition: pbx_spool.c:93
const ast_string_field dest
Definition: pbx_spool.c:93
const ast_string_field tech
Definition: pbx_spool.c:93
long callingpid
Definition: pbx_spool.c:80
pid_t ast_mainpid
Definition: asterisk.c:199
static void safe_append(struct outgoing *o, time_t now, char *s)
Definition: pbx_spool.c:283
static void* scan_thread ( void *  unused)
static

Definition at line 618 of file pbx_spool.c.

References ast_debug, ast_free, ast_fully_booted, AST_LIST_EMPTY, AST_LIST_FIRST, AST_LIST_LOCK, AST_LIST_REMOVE_HEAD, AST_LIST_UNLOCK, ast_log(), errno, HAVE_INOTIFY, inotify_fd, len(), LOG_ERROR, direntry::mtime, direntry::name, direntry::next, queue_created_files(), queue_file(), queue_file_create(), queue_file_open(), and queue_file_write().

Referenced by load_module().

619 {
620  DIR *dir;
621  struct dirent *de;
622  time_t now;
623  struct timespec ts = { .tv_sec = 1 };
624 #ifdef HAVE_INOTIFY
625  ssize_t res;
626  int inotify_fd = inotify_init();
627  struct inotify_event *iev;
628  char buf[8192] __attribute__((aligned (sizeof(int))));
629  struct pollfd pfd = { .fd = inotify_fd, .events = POLLIN };
630 #else
631  struct timespec nowait = { .tv_sec = 0, .tv_nsec = 1 };
632  int inotify_fd = kqueue();
633  struct kevent kev;
634  struct kevent event;
635 #endif
636  struct direntry *cur;
637 
638  while (!ast_fully_booted) {
639  nanosleep(&ts, NULL);
640  }
641 
642  if (inotify_fd < 0) {
643  ast_log(LOG_ERROR, "Unable to initialize "
644 #ifdef HAVE_INOTIFY
645  "inotify(7)"
646 #else
647  "kqueue(2)"
648 #endif
649  "\n");
650  return NULL;
651  }
652 
653 #ifdef HAVE_INOTIFY
654  inotify_add_watch(inotify_fd, qdir, IN_CREATE | IN_OPEN | IN_CLOSE_WRITE | IN_MOVED_TO);
655 #endif
656 
657  /* First, run through the directory and clear existing entries */
658  if (!(dir = opendir(qdir))) {
659  ast_log(LOG_ERROR, "Unable to open directory %s: %s\n", qdir, strerror(errno));
660  return NULL;
661  }
662 
663 #ifndef HAVE_INOTIFY
664  EV_SET(&kev, dirfd(dir), EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_CLEAR, NOTE_WRITE, 0, NULL);
665  if (kevent(inotify_fd, &kev, 1, &event, 1, &nowait) < 0 && errno != 0) {
666  ast_log(LOG_ERROR, "Unable to watch directory %s: %s\n", qdir, strerror(errno));
667  }
668 #endif
669  now = time(NULL);
670  while ((de = readdir(dir))) {
671  queue_file(de->d_name, 0);
672  }
673 
674 #ifdef HAVE_INOTIFY
675  /* Directory needs to remain open for kqueue(2) */
676  closedir(dir);
677 #endif
678 
679  /* Wait for either a) next timestamp to occur, or b) a change to happen */
680  for (;/* ever */;) {
681  time_t next = AST_LIST_EMPTY(&dirlist) ? INT_MAX : AST_LIST_FIRST(&dirlist)->mtime;
682 
683  time(&now);
684  if (next > now) {
685 #ifdef HAVE_INOTIFY
686  int stage = 0;
687  /* Convert from seconds to milliseconds, unless there's nothing
688  * in the queue already, in which case, we wait forever. */
689  int waittime = next == INT_MAX ? -1 : (next - now) * 1000;
690  if (!AST_LIST_EMPTY(&createlist)) {
691  waittime = 1000;
692  }
693  /* When a file arrives, add it to the queue, in mtime order. */
694  if ((res = poll(&pfd, 1, waittime)) > 0 && (stage = 1) &&
695  (res = read(inotify_fd, &buf, sizeof(buf))) >= sizeof(*iev)) {
696  ssize_t len = 0;
697  /* File(s) added to directory, add them to my list */
698  for (iev = (void *) buf; res >= sizeof(*iev); iev = (struct inotify_event *) (((char *) iev) + len)) {
699  /* For an IN_MOVED_TO event, simply process the file. However, if
700  * we get an IN_CREATE event it *might* be an open(O_CREAT) or it
701  * might be a hardlink (like smsq does, since rename() might
702  * overwrite an existing file). So we have to see if we get a
703  * subsequent IN_OPEN event on the same file. If we do, keep it
704  * on the openlist and wait for the corresponding IN_CLOSE_WRITE.
705  * If we *don't* see an IN_OPEN event, then it was a hard link so
706  * it can be processed immediately.
707  *
708  * Unfortunately, although open(O_CREAT) is an atomic file system
709  * operation, the inotify subsystem doesn't give it to us in a
710  * single event with both IN_CREATE|IN_OPEN set. It's two separate
711  * events, and the kernel doesn't even give them to us at the same
712  * time. We can read() from inotify_fd after the IN_CREATE event,
713  * and get *nothing* from it. The IN_OPEN arrives only later! So
714  * we have a very short timeout of 2 seconds. */
715  if (iev->mask & IN_CREATE) {
716  queue_file_create(iev->name);
717  } else if (iev->mask & IN_OPEN) {
718  queue_file_open(iev->name);
719  } else if (iev->mask & IN_CLOSE_WRITE) {
720  queue_file_write(iev->name);
721  } else if (iev->mask & IN_MOVED_TO) {
722  queue_file(iev->name, 0);
723  } else {
724  ast_log(LOG_ERROR, "Unexpected event %d for file '%s'\n", (int) iev->mask, iev->name);
725  }
726 
727  len = sizeof(*iev) + iev->len;
728  res -= len;
729  }
730  } else if (res < 0 && errno != EINTR && errno != EAGAIN) {
731  ast_debug(1, "Got an error back from %s(2): %s\n", stage ? "read" : "poll", strerror(errno));
732  }
733  time(&now);
734  }
736 #else
737  int num_events;
738  /* If queue empty then wait forever */
739  if (next == INT_MAX) {
740  num_events = kevent(inotify_fd, &kev, 1, &event, 1, NULL);
741  } else {
742  struct timespec ts2 = { .tv_sec = (unsigned long int)(next - now), .tv_nsec = 0 };
743  num_events = kevent(inotify_fd, &kev, 1, &event, 1, &ts2);
744  }
745  if ((num_events < 0) || (event.flags == EV_ERROR)) {
746  ast_debug(10, "KEvent error %s\n", strerror(errno));
747  continue;
748  } else if (num_events == 0) {
749  /* Interrupt or timeout, restart calculations */
750  continue;
751  } else {
752  /* Directory changed, rescan */
753  rewinddir(dir);
754  while ((de = readdir(dir))) {
755  queue_file(de->d_name, 0);
756  }
757  }
758  time(&now);
759  }
760 #endif
761 
762  /* Empty the list of all entries ready to be processed */
764  while (!AST_LIST_EMPTY(&dirlist) && AST_LIST_FIRST(&dirlist)->mtime <= now) {
765  cur = AST_LIST_REMOVE_HEAD(&dirlist, list);
766  queue_file(cur->name, cur->mtime);
767  ast_free(cur);
768  }
770  }
771  return NULL;
772 }
#define AST_LIST_LOCK(head)
Locks a list.
Definition: linkedlists.h:39
static void queue_created_files(void)
Definition: pbx_spool.c:585
#define AST_LIST_FIRST(head)
Returns the first entry contained in a list.
Definition: linkedlists.h:420
static char qdir[255]
Definition: pbx_spool.c:72
#define AST_LIST_UNLOCK(head)
Attempts to unlock a list.
Definition: linkedlists.h:139
#define HAVE_INOTIFY
Definition: autoconfig.h:342
#define AST_LIST_EMPTY(head)
Checks whether the specified list contains any entries.
Definition: linkedlists.h:449
static void queue_file_write(const char *filename)
Definition: pbx_spool.c:602
static void queue_file(const char *filename, time_t when)
Definition: pbx_spool.c:488
#define ast_debug(level,...)
Log a DEBUG message.
Definition: logger.h:236
static int inotify_fd
Definition: localtime.c:270
#define ast_fully_booted
Definition: options.h:113
#define AST_LIST_REMOVE_HEAD(head, field)
Removes and returns the head entry from a list.
Definition: linkedlists.h:818
struct direntry * next
Definition: pbx_spool.c:475
#define LOG_ERROR
Definition: logger.h:155
static int len(struct ast_channel *chan, const char *cmd, char *data, char *buf, size_t buflen)
char name[0]
Definition: pbx_spool.c:477
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
int errno
#define ast_free(a)
Definition: astmm.h:97
time_t mtime
Definition: pbx_spool.c:476
static void queue_file_create(const char *filename)
Definition: pbx_spool.c:552
static void queue_file_open(const char *filename)
Definition: pbx_spool.c:571
static int unload_module ( void  )
static

Definition at line 869 of file pbx_spool.c.

870 {
871  return -1;
872 }

Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .description = "Outgoing Spool Support" , .key = "This paragraph is copyright (c) 2006 by Digium, Inc. \In order for your module to load, it must return this \key via a function called \"key\". Any code which \includes this paragraph must be licensed under the GNU \General Public License version 2 or later (at your \option). In addition to Digium's general reservations \of rights, Digium expressly reserves the right to \allow other parties to license this paragraph under \different terms. Any use of Digium, Inc. trademarks or \logos (including \"Asterisk\" or \"Digium\") without \express written permission of Digium, Inc. is prohibited.\n" , .buildopt_sum = "ac1f6a56484a8820659555499174e588" , .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, }
static

Definition at line 893 of file pbx_spool.c.

Definition at line 893 of file pbx_spool.c.

struct createlist createlist = { .first = NULL, .last = NULL, }
static
struct dirlist dirlist = { .first = NULL, .last = NULL, .lock = { PTHREAD_RECURSIVE_MUTEX_INITIALIZER_NP , NULL, 1 } , }
static
struct openlist openlist = { .first = NULL, .last = NULL, }
static
char qdir[255]
static

Definition at line 72 of file pbx_spool.c.

char qdonedir[255]
static

Definition at line 73 of file pbx_spool.c.