Thu Jul 9 13:41:28 2009

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 = "068e67f60f50dd9ee86464c05884a49d" , .load = load_module, .unload = unload_module, }
static const 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 533 of file pbx_spool.c.

static void __unreg_module ( void   )  [static]

Definition at line 533 of file pbx_spool.c.

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

Definition at line 122 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, ast_event_ref::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().

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

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

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

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

static void free_outgoing ( struct outgoing o  )  [static]

Definition at line 117 of file pbx_spool.c.

References ast_free.

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

00118 {
00119    ast_free(o);
00120 }

static void init_outgoing ( struct outgoing o  )  [static]

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

00109 {
00110    o->priority = 1;
00111    o->retrytime = 300;
00112    o->waittime = 45;
00113    o->format = AST_FORMAT_SLINEAR;
00114    ast_set_flag(&o->options, SPOOL_FLAG_ALWAYS_DELETE);
00115 }

static void launch_service ( struct outgoing o  )  [static]

Definition at line 365 of file pbx_spool.c.

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

Referenced by scan_service().

00366 {
00367    pthread_t t;
00368    int ret;
00369 
00370    if ((ret = ast_pthread_create_detached(&t, NULL, attempt_thread, o))) {
00371       ast_log(LOG_WARNING, "Unable to create thread :( (returned error: %d)\n", ret);
00372       free_outgoing(o);
00373    }
00374 }

static int load_module ( void   )  [static]

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

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

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

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

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

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

00259 {
00260    int fd;
00261    FILE *f;
00262    struct utimbuf tbuf;
00263 
00264    if ((fd = open(o->fn, O_WRONLY | O_APPEND)) < 0)
00265       return;
00266 
00267    if ((f = fdopen(fd, "a"))) {
00268       fprintf(f, "\n%s: %ld %d (%ld)\n", s, (long)ast_mainpid, o->retries, (long) now);
00269       fclose(f);
00270    } else
00271       close(fd);
00272 
00273    /* Update the file time */
00274    tbuf.actime = now;
00275    tbuf.modtime = now + o->retrytime;
00276    if (utime(o->fn, &tbuf))
00277       ast_log(LOG_WARNING, "Unable to set utime on %s: %s\n", o->fn, strerror(errno));
00278 }

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

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

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

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

Definition at line 437 of file pbx_spool.c.

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

Referenced by load_module().

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

static int unload_module ( void   )  [static]

Definition at line 509 of file pbx_spool.c.

00510 {
00511    return -1;
00512 }


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

Definition at line 533 of file pbx_spool.c.

const struct ast_module_info* ast_module_info = &__mod_info [static]

Definition at line 533 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 Thu Jul 9 13:41:28 2009 for Asterisk - the Open Source PBX by  doxygen 1.4.7