Fri Nov 12 12:06:57 2010

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 "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"
Include dependency graph for pbx_spool.c:

Go to the source code of this file.

Data Structures

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, char *fn, FILE *f)
static void * attempt_thread (void *data)
static void free_outgoing (struct outgoing *o)
static int init_outgoing (struct outgoing *o)
static void launch_service (struct outgoing *o)
static int load_module (void)
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.
static void safe_append (struct outgoing *o, time_t now, char *s)
static int scan_service (char *fn, time_t now, time_t atime)
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_DEFAULT , .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 = "0901e4e500243c855563a2d78b0c03e4" , .load = load_module, .unload = unload_module, }
static struct ast_module_infoast_module_info = &__mod_info
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 50 of file pbx_spool.c.

00050      {
00051    /*! Always delete the call file after a call succeeds or the
00052     * maximum number of retries is exceeded, even if the
00053     * modification time of the call file is in the future.
00054     */
00055    SPOOL_FLAG_ALWAYS_DELETE = (1 << 0),
00056    /* Don't unlink the call file after processing, move in qdonedir */
00057    SPOOL_FLAG_ARCHIVE = (1 << 1)
00058 };


Function Documentation

static void __reg_module ( void   )  [static]

Definition at line 532 of file pbx_spool.c.

static void __unreg_module ( void   )  [static]

Definition at line 532 of file pbx_spool.c.

static int apply_outgoing ( struct outgoing o,
char *  fn,
FILE *  f 
) [static]

Definition at line 110 of file pbx_spool.c.

References outgoing::app, app, ast_callerid_split(), ast_log(), ast_parse_allow_disallow(), ast_set2_flag, ast_string_field_set, ast_strlen_zero(), ast_true(), ast_variable_new(), buf, outgoing::callingpid, cid_name, cid_num, context, outgoing::dest, outgoing::exten, exten, 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, outgoing::tech, var, outgoing::vars, and outgoing::waittime.

Referenced by scan_service().

00111 {
00112    char buf[256];
00113    char *c, *c2;
00114    int lineno = 0;
00115    struct ast_variable *var, *last = o->vars;
00116 
00117    while (last && last->next) {
00118       last = last->next;
00119    }
00120 
00121    while(fgets(buf, sizeof(buf), f)) {
00122       lineno++;
00123       /* Trim comments */
00124       c = buf;
00125       while ((c = strchr(c, '#'))) {
00126          if ((c == buf) || (*(c-1) == ' ') || (*(c-1) == '\t'))
00127             *c = '\0';
00128          else
00129             c++;
00130       }
00131 
00132       c = buf;
00133       while ((c = strchr(c, ';'))) {
00134          if ((c > buf) && (c[-1] == '\\')) {
00135             memmove(c - 1, c, strlen(c) + 1);
00136             c++;
00137          } else {
00138             *c = '\0';
00139             break;
00140          }
00141       }
00142 
00143       /* Trim trailing white space */
00144       while(!ast_strlen_zero(buf) && buf[strlen(buf) - 1] < 33)
00145          buf[strlen(buf) - 1] = '\0';
00146       if (!ast_strlen_zero(buf)) {
00147          c = strchr(buf, ':');
00148          if (c) {
00149             *c = '\0';
00150             c++;
00151             while ((*c) && (*c < 33))
00152                c++;
00153 #if 0
00154             printf("'%s' is '%s' at line %d\n", buf, c, lineno);
00155 #endif
00156             if (!strcasecmp(buf, "channel")) {
00157                if ((c2 = strchr(c, '/'))) {
00158                   *c2 = '\0';
00159                   c2++;
00160                   ast_string_field_set(o, tech, c);
00161                   ast_string_field_set(o, dest, c2);
00162                } else {
00163                   ast_log(LOG_NOTICE, "Channel should be in form Tech/Dest at line %d of %s\n", lineno, fn);
00164                }
00165             } else if (!strcasecmp(buf, "callerid")) {
00166                char cid_name[80] = {0}, cid_num[80] = {0};
00167                ast_callerid_split(c, cid_name, sizeof(cid_name), cid_num, sizeof(cid_num));
00168                ast_string_field_set(o, cid_num, cid_num);
00169                ast_string_field_set(o, cid_name, cid_name);
00170             } else if (!strcasecmp(buf, "application")) {
00171                ast_string_field_set(o, app, c);
00172             } else if (!strcasecmp(buf, "data")) {
00173                ast_string_field_set(o, data, c);
00174             } else if (!strcasecmp(buf, "maxretries")) {
00175                if (sscanf(c, "%30d", &o->maxretries) != 1) {
00176                   ast_log(LOG_WARNING, "Invalid max retries at line %d of %s\n", lineno, fn);
00177                   o->maxretries = 0;
00178                }
00179             } else if (!strcasecmp(buf, "codecs")) {
00180                ast_parse_allow_disallow(NULL, &o->format, c, 1);
00181             } else if (!strcasecmp(buf, "context")) {
00182                ast_string_field_set(o, context, c);
00183             } else if (!strcasecmp(buf, "extension")) {
00184                ast_string_field_set(o, exten, c);
00185             } else if (!strcasecmp(buf, "priority")) {
00186                if ((sscanf(c, "%30d", &o->priority) != 1) || (o->priority < 1)) {
00187                   ast_log(LOG_WARNING, "Invalid priority at line %d of %s\n", lineno, fn);
00188                   o->priority = 1;
00189                }
00190             } else if (!strcasecmp(buf, "retrytime")) {
00191                if ((sscanf(c, "%30d", &o->retrytime) != 1) || (o->retrytime < 1)) {
00192                   ast_log(LOG_WARNING, "Invalid retrytime at line %d of %s\n", lineno, fn);
00193                   o->retrytime = 300;
00194                }
00195             } else if (!strcasecmp(buf, "waittime")) {
00196                if ((sscanf(c, "%30d", &o->waittime) != 1) || (o->waittime < 1)) {
00197                   ast_log(LOG_WARNING, "Invalid waittime at line %d of %s\n", lineno, fn);
00198                   o->waittime = 45;
00199                }
00200             } else if (!strcasecmp(buf, "retry")) {
00201                o->retries++;
00202             } else if (!strcasecmp(buf, "startretry")) {
00203                if (sscanf(c, "%30ld", &o->callingpid) != 1) {
00204                   ast_log(LOG_WARNING, "Unable to retrieve calling PID!\n");
00205                   o->callingpid = 0;
00206                }
00207             } else if (!strcasecmp(buf, "endretry") || !strcasecmp(buf, "abortretry")) {
00208                o->callingpid = 0;
00209                o->retries++;
00210             } else if (!strcasecmp(buf, "delayedretry")) {
00211             } else if (!strcasecmp(buf, "setvar") || !strcasecmp(buf, "set")) {
00212                c2 = c;
00213                strsep(&c2, "=");
00214                if (c2) {
00215                   var = ast_variable_new(c, c2, fn);
00216                   if (var) {
00217                      /* Always insert at the end, because some people want to treat the spool file as a script */
00218                      if (last) {
00219                         last->next = var;
00220                      } else {
00221                         o->vars = var;
00222                      }
00223                      last = var;
00224                   }
00225                } else
00226                   ast_log(LOG_WARNING, "Malformed \"%s\" argument.  Should be \"%s: variable=value\"\n", buf, buf);
00227             } else if (!strcasecmp(buf, "account")) {
00228                ast_string_field_set(o, account, c);
00229             } else if (!strcasecmp(buf, "alwaysdelete")) {
00230                ast_set2_flag(&o->options, ast_true(c), SPOOL_FLAG_ALWAYS_DELETE);
00231             } else if (!strcasecmp(buf, "archive")) {
00232                ast_set2_flag(&o->options, ast_true(c), SPOOL_FLAG_ARCHIVE);
00233             } else {
00234                ast_log(LOG_WARNING, "Unknown keyword '%s' at line %d of %s\n", buf, lineno, fn);
00235             }
00236          } else
00237             ast_log(LOG_NOTICE, "Syntax error at line %d of %s\n", lineno, fn);
00238       }
00239    }
00240    ast_string_field_set(o, fn, fn);
00241    if (ast_strlen_zero(o->tech) || ast_strlen_zero(o->dest) || (ast_strlen_zero(o->app) && ast_strlen_zero(o->exten))) {
00242       ast_log(LOG_WARNING, "At least one of app or extension must be specified, along with tech and dest in file %s\n", fn);
00243       return -1;
00244    }
00245    return 0;
00246 }

static void* attempt_thread ( void *  data  )  [static]

Definition at line 325 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::format, free_outgoing(), LOG_EVENT, LOG_NOTICE, outgoing::maxretries, outgoing::priority, remove_from_queue(), outgoing::retries, safe_append(), outgoing::tech, outgoing::vars, and outgoing::waittime.

Referenced by launch_service().

00326 {
00327    struct outgoing *o = data;
00328    int res, reason;
00329    if (!ast_strlen_zero(o->app)) {
00330       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);
00331       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);
00332       o->vars = NULL;
00333    } else {
00334       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);
00335       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);
00336       o->vars = NULL;
00337    }
00338    if (res) {
00339       ast_log(LOG_NOTICE, "Call failed to go through, reason (%d) %s\n", reason, ast_channel_reason2str(reason));
00340       if (o->retries >= o->maxretries + 1) {
00341          /* Max retries exceeded */
00342          ast_log(LOG_EVENT, "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" : "");
00343          remove_from_queue(o, "Expired");
00344       } else {
00345          /* Notate that the call is still active */
00346          safe_append(o, time(NULL), "EndRetry");
00347       }
00348    } else {
00349       ast_log(LOG_NOTICE, "Call completed to %s/%s\n", o->tech, o->dest);
00350       ast_log(LOG_EVENT, "Queued call to %s/%s completed\n", o->tech, o->dest);
00351       remove_from_queue(o, "Completed");
00352    }
00353    free_outgoing(o);
00354    return NULL;
00355 }

static void free_outgoing ( struct outgoing o  )  [static]

Definition at line 101 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(), and scan_service().

00102 {
00103    if (o->vars) {
00104       ast_variables_destroy(o->vars);
00105    }
00106    ast_string_field_free_memory(o);
00107    ast_free(o);
00108 }

static int init_outgoing ( struct outgoing o  )  [static]

Definition at line 88 of file pbx_spool.c.

References AST_FORMAT_SLINEAR, ast_set_flag, ast_string_field_init, outgoing::format, outgoing::options, outgoing::priority, outgoing::retrytime, SPOOL_FLAG_ALWAYS_DELETE, and outgoing::waittime.

Referenced by scan_service().

00089 {
00090    o->priority = 1;
00091    o->retrytime = 300;
00092    o->waittime = 45;
00093    o->format = AST_FORMAT_SLINEAR;
00094    ast_set_flag(&o->options, SPOOL_FLAG_ALWAYS_DELETE);
00095    if (ast_string_field_init(o, 128)) {
00096       return -1;
00097    }
00098    return 0;
00099 }

static void launch_service ( struct outgoing o  )  [static]

Definition at line 357 of file pbx_spool.c.

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

Referenced by scan_service().

00358 {
00359    pthread_t t;
00360    int ret;
00361 
00362    if ((ret = ast_pthread_create_detached(&t, NULL, attempt_thread, o))) {
00363       ast_log(LOG_WARNING, "Unable to create thread :( (returned error: %d)\n", ret);
00364       free_outgoing(o);
00365    }
00366 }

static int load_module ( void   )  [static]

Definition at line 513 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.

00514 {
00515    pthread_t thread;
00516    int ret;
00517    snprintf(qdir, sizeof(qdir), "%s/%s", ast_config_AST_SPOOL_DIR, "outgoing");
00518    if (ast_mkdir(qdir, 0777)) {
00519       ast_log(LOG_WARNING, "Unable to create queue directory %s -- outgoing spool disabled\n", qdir);
00520       return AST_MODULE_LOAD_DECLINE;
00521    }
00522    snprintf(qdonedir, sizeof(qdir), "%s/%s", ast_config_AST_SPOOL_DIR, "outgoing_done");
00523 
00524    if ((ret = ast_pthread_create_detached_background(&thread, NULL, scan_thread, NULL))) {
00525       ast_log(LOG_WARNING, "Unable to create thread :( (returned error: %d)\n", ret);
00526       return AST_MODULE_LOAD_FAILURE;
00527    }
00528 
00529    return AST_MODULE_LOAD_SUCCESS;
00530 }

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:
o the pointer to outgoing struct
status the exit status of the call. Can be "Completed", "Failed" or "Expired"

Definition at line 276 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().

00277 {
00278    int fd;
00279    FILE *f;
00280    char newfn[256];
00281    const char *bname;
00282 
00283    if (!ast_test_flag(&o->options, SPOOL_FLAG_ALWAYS_DELETE)) {
00284       struct stat current_file_status;
00285 
00286       if (!stat(o->fn, &current_file_status)) {
00287          if (time(NULL) < current_file_status.st_mtime)
00288             return 0;
00289       }
00290    }
00291 
00292    if (!ast_test_flag(&o->options, SPOOL_FLAG_ARCHIVE)) {
00293       unlink(o->fn);
00294       return 0;
00295    }
00296 
00297    if (ast_mkdir(qdonedir, 0777)) {
00298       ast_log(LOG_WARNING, "Unable to create queue directory %s -- outgoing spool archiving disabled\n", qdonedir);
00299       unlink(o->fn);
00300       return -1;
00301    }
00302 
00303    if ((fd = open(o->fn, O_WRONLY | O_APPEND))) {
00304       if ((f = fdopen(fd, "a"))) {
00305          fprintf(f, "Status: %s\n", status);
00306          fclose(f);
00307       } else
00308          close(fd);
00309    }
00310 
00311    if (!(bname = strrchr(o->fn, '/')))
00312       bname = o->fn;
00313    else
00314       bname++; 
00315    snprintf(newfn, sizeof(newfn), "%s/%s", qdonedir, bname);
00316    /* a existing call file the archive dir is overwritten */
00317    unlink(newfn);
00318    if (rename(o->fn, newfn) != 0) {
00319       unlink(o->fn);
00320       return -1;
00321    } else
00322       return 0;
00323 }

static void safe_append ( struct outgoing o,
time_t  now,
char *  s 
) [static]

Definition at line 248 of file pbx_spool.c.

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

Referenced by attempt_thread(), and scan_service().

00249 {
00250    int fd;
00251    FILE *f;
00252    struct utimbuf tbuf;
00253 
00254    if ((fd = open(o->fn, O_WRONLY | O_APPEND)) < 0)
00255       return;
00256 
00257    if ((f = fdopen(fd, "a"))) {
00258       fprintf(f, "\n%s: %ld %d (%ld)\n", s, (long)ast_mainpid, o->retries, (long) now);
00259       fclose(f);
00260    } else
00261       close(fd);
00262 
00263    /* Update the file time */
00264    tbuf.actime = now;
00265    tbuf.modtime = now + o->retrytime;
00266    if (utime(o->fn, &tbuf))
00267       ast_log(LOG_WARNING, "Unable to set utime on %s: %s\n", o->fn, strerror(errno));
00268 }

static int scan_service ( char *  fn,
time_t  now,
time_t  atime 
) [static]

Definition at line 368 of file pbx_spool.c.

References apply_outgoing(), ast_calloc, ast_free, ast_log(), ast_mainpid, outgoing::callingpid, outgoing::dest, errno, f, outgoing::fn, free_outgoing(), init_outgoing(), launch_service(), LOG_DEBUG, LOG_EVENT, LOG_WARNING, outgoing::maxretries, remove_from_queue(), outgoing::retries, outgoing::retrytime, safe_append(), and outgoing::tech.

Referenced by scan_thread().

00369 {
00370    struct outgoing *o = NULL;
00371    FILE *f;
00372    int res = 0;
00373 
00374    if (!(o = ast_calloc(1, sizeof(*o)))) {
00375       ast_log(LOG_WARNING, "Out of memory ;(\n");
00376       return -1;
00377    }
00378    
00379    if (init_outgoing(o)) {
00380       /* No need to call free_outgoing here since we know the failure
00381        * was to allocate string fields and no variables have been allocated
00382        * yet.
00383        */
00384       ast_free(o);
00385       return -1;
00386    }
00387 
00388    /* Attempt to open the file */
00389    if (!(f = fopen(fn, "r+"))) {
00390       remove_from_queue(o, "Failed");
00391       free_outgoing(o);
00392       ast_log(LOG_WARNING, "Unable to open %s: %s, deleting\n", fn, strerror(errno));
00393       return -1;
00394    }
00395 
00396    /* Read in and verify the contents */
00397    if (apply_outgoing(o, fn, f)) {
00398       remove_from_queue(o, "Failed");
00399       free_outgoing(o);
00400       ast_log(LOG_WARNING, "Invalid file contents in %s, deleting\n", fn);
00401       fclose(f);
00402       return -1;
00403    }
00404    
00405 #if 0
00406    printf("Filename: %s, Retries: %d, max: %d\n", fn, o->retries, o->maxretries);
00407 #endif
00408    fclose(f);
00409    if (o->retries <= o->maxretries) {
00410       now += o->retrytime;
00411       if (o->callingpid && (o->callingpid == ast_mainpid)) {
00412          safe_append(o, time(NULL), "DelayedRetry");
00413          ast_log(LOG_DEBUG, "Delaying retry since we're currently running '%s'\n", o->fn);
00414          free_outgoing(o);
00415       } else {
00416          /* Increment retries */
00417          o->retries++;
00418          /* If someone else was calling, they're presumably gone now
00419             so abort their retry and continue as we were... */
00420          if (o->callingpid)
00421             safe_append(o, time(NULL), "AbortRetry");
00422          
00423          safe_append(o, now, "StartRetry");
00424          launch_service(o);
00425       }
00426       res = now;
00427    } else {
00428       ast_log(LOG_EVENT, "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" : "");
00429       remove_from_queue(o, "Expired");
00430       free_outgoing(o);
00431    }
00432 
00433    return res;
00434 }

static void* scan_thread ( void *  unused  )  [static]

Definition at line 436 of file pbx_spool.c.

References ast_fully_booted, ast_log(), dir, errno, last, LOG_WARNING, and scan_service().

Referenced by load_module().

00437 {
00438    struct stat st;
00439    DIR *dir;
00440    struct dirent *de;
00441    char fn[256];
00442    int res;
00443    time_t last = 0, next = 0, now;
00444    struct timespec ts = { .tv_sec = 1 };
00445   
00446    while (!ast_fully_booted) {
00447       nanosleep(&ts, NULL);
00448    }
00449 
00450    for(;;) {
00451       /* Wait a sec */
00452       nanosleep(&ts, NULL);
00453       time(&now);
00454 
00455       if (stat(qdir, &st)) {
00456          ast_log(LOG_WARNING, "Unable to stat %s\n", qdir);
00457          continue;
00458       }
00459 
00460       /* Make sure it is time for us to execute our check */
00461       if ((st.st_mtime == last) && (next && (next > now)))
00462          continue;
00463       
00464 #if 0
00465       printf("atime: %ld, mtime: %ld, ctime: %ld\n", st.st_atime, st.st_mtime, st.st_ctime);
00466       printf("Ooh, something changed / timeout\n");
00467 #endif
00468       next = 0;
00469       last = st.st_mtime;
00470 
00471       if (!(dir = opendir(qdir))) {
00472          ast_log(LOG_WARNING, "Unable to open directory %s: %s\n", qdir, strerror(errno));
00473          continue;
00474       }
00475 
00476       while ((de = readdir(dir))) {
00477          snprintf(fn, sizeof(fn), "%s/%s", qdir, de->d_name);
00478          if (stat(fn, &st)) {
00479             ast_log(LOG_WARNING, "Unable to stat %s: %s\n", fn, strerror(errno));
00480             continue;
00481          }
00482          if (!S_ISREG(st.st_mode))
00483             continue;
00484          if (st.st_mtime <= now) {
00485             res = scan_service(fn, now, st.st_atime);
00486             if (res > 0) {
00487                /* Update next service time */
00488                if (!next || (res < next)) {
00489                   next = res;
00490                }
00491             } else if (res) {
00492                ast_log(LOG_WARNING, "Failed to scan service '%s'\n", fn);
00493             } else if (!next) {
00494                /* Expired entry: must recheck on the next go-around */
00495                next = st.st_mtime;
00496             }
00497          } else {
00498             /* Update "next" update if necessary */
00499             if (!next || (st.st_mtime < next))
00500                next = st.st_mtime;
00501          }
00502       }
00503       closedir(dir);
00504    }
00505    return NULL;
00506 }

static int unload_module ( void   )  [static]

Definition at line 508 of file pbx_spool.c.

00509 {
00510    return -1;
00511 }


Variable Documentation

struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT , .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 = "0901e4e500243c855563a2d78b0c03e4" , .load = load_module, .unload = unload_module, } [static]

Definition at line 532 of file pbx_spool.c.

Definition at line 532 of file pbx_spool.c.

char qdir[255] [static]

Definition at line 60 of file pbx_spool.c.

char qdonedir[255] [static]

Definition at line 61 of file pbx_spool.c.


Generated by  doxygen 1.6.2