Wed Aug 18 22:34:30 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"

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 void 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 = "a9c98e5d177805051735cb5b0b16b0a0" , .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 524 of file pbx_spool.c.

static void __unreg_module ( void   )  [static]

Definition at line 524 of file pbx_spool.c.

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

Definition at line 111 of file pbx_spool.c.

References outgoing::account, outgoing::app, ast_callerid_split(), ast_copy_string(), ast_log(), ast_parse_allow_disallow(), ast_set2_flag, ast_strlen_zero(), ast_true(), ast_variable_new(), buf, outgoing::callingpid, outgoing::cid_name, outgoing::cid_num, outgoing::context, outgoing::data, outgoing::dest, outgoing::exten, outgoing::fn, outgoing::format, last, LOG_NOTICE, LOG_WARNING, outgoing::maxretries, devstate_change::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().

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

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

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

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

static void free_outgoing ( struct outgoing o  )  [static]

Definition at line 103 of file pbx_spool.c.

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

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

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

static void init_outgoing ( struct outgoing o  )  [static]

Definition at line 94 of file pbx_spool.c.

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

Referenced by scan_service().

00095 {
00096    o->priority = 1;
00097    o->retrytime = 300;
00098    o->waittime = 45;
00099    o->format = AST_FORMAT_SLINEAR;
00100    ast_set_flag(&o->options, SPOOL_FLAG_ALWAYS_DELETE);
00101 }

static void launch_service ( struct outgoing o  )  [static]

Definition at line 356 of file pbx_spool.c.

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

Referenced by scan_service().

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

static int load_module ( void   )  [static]

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

00506 {
00507    pthread_t thread;
00508    int ret;
00509    snprintf(qdir, sizeof(qdir), "%s/%s", ast_config_AST_SPOOL_DIR, "outgoing");
00510    if (ast_mkdir(qdir, 0777)) {
00511       ast_log(LOG_WARNING, "Unable to create queue directory %s -- outgoing spool disabled\n", qdir);
00512       return AST_MODULE_LOAD_DECLINE;
00513    }
00514    snprintf(qdonedir, sizeof(qdir), "%s/%s", ast_config_AST_SPOOL_DIR, "outgoing_done");
00515 
00516    if ((ret = ast_pthread_create_detached_background(&thread, NULL, scan_thread, NULL))) {
00517       ast_log(LOG_WARNING, "Unable to create thread :( (returned error: %d)\n", ret);
00518       return AST_MODULE_LOAD_FAILURE;
00519    }
00520 
00521    return AST_MODULE_LOAD_SUCCESS;
00522 }

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 275 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.

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

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

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

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

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

Definition at line 367 of file pbx_spool.c.

References apply_outgoing(), ast_calloc, ast_log(), ast_mainpid, errno, f, free_outgoing(), init_outgoing(), launch_service(), LOG_DEBUG, LOG_EVENT, LOG_WARNING, remove_from_queue(), and safe_append().

Referenced by scan_thread().

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

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

Definition at line 428 of file pbx_spool.c.

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

Referenced by load_module().

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

static int unload_module ( void   )  [static]

Definition at line 500 of file pbx_spool.c.

00501 {
00502    return -1;
00503 }


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 = "a9c98e5d177805051735cb5b0b16b0a0" , .load = load_module, .unload = unload_module, } [static]

Definition at line 524 of file pbx_spool.c.

struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 524 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 on Wed Aug 18 22:34:30 2010 for Asterisk - the Open Source PBX by  doxygen 1.4.7