#include "asterisk.h"
#include <sys/stat.h>
#include <errno.h>
#include <time.h>
#include <utime.h>
#include <stdlib.h>
#include <unistd.h>
#include <dirent.h>
#include <string.h>
#include <stdio.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/options.h"
#include "asterisk/utils.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 | AST_MODFLAG_BUILDSUM, .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 = "f450f61f60e761b3aa089ebed76ca8a5" , .load = load_module, .unload = unload_module, } |
static const struct ast_module_info * | ast_module_info = &__mod_info |
static char | qdir [255] |
static char | qdonedir [255] |
Definition in file pbx_spool.c.
anonymous enum |
Definition at line 57 of file pbx_spool.c.
00057 { 00058 /*! Always delete the call file after a call succeeds or the 00059 * maximum number of retries is exceeded, even if the 00060 * modification time of the call file is in the future. 00061 */ 00062 SPOOL_FLAG_ALWAYS_DELETE = (1 << 0), 00063 /* Don't unlink the call file after processing, move in qdonedir */ 00064 SPOOL_FLAG_ARCHIVE = (1 << 1) 00065 };
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 130 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(), 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, sla_ringing_trunk::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().
00131 { 00132 char buf[256]; 00133 char *c, *c2; 00134 int lineno = 0; 00135 struct ast_variable *var, *last = o->vars; 00136 00137 while (last && last->next) { 00138 last = last->next; 00139 } 00140 00141 while(fgets(buf, sizeof(buf), f)) { 00142 lineno++; 00143 /* Trim comments */ 00144 c = buf; 00145 while ((c = strchr(c, '#'))) { 00146 if ((c == buf) || (*(c-1) == ' ') || (*(c-1) == '\t')) 00147 *c = '\0'; 00148 else 00149 c++; 00150 } 00151 00152 c = buf; 00153 while ((c = strchr(c, ';'))) { 00154 if ((c > buf) && (c[-1] == '\\')) { 00155 memmove(c - 1, c, strlen(c) + 1); 00156 c++; 00157 } else { 00158 *c = '\0'; 00159 break; 00160 } 00161 } 00162 00163 /* Trim trailing white space */ 00164 while(!ast_strlen_zero(buf) && buf[strlen(buf) - 1] < 33) 00165 buf[strlen(buf) - 1] = '\0'; 00166 if (!ast_strlen_zero(buf)) { 00167 c = strchr(buf, ':'); 00168 if (c) { 00169 *c = '\0'; 00170 c++; 00171 while ((*c) && (*c < 33)) 00172 c++; 00173 #if 0 00174 printf("'%s' is '%s' at line %d\n", buf, c, lineno); 00175 #endif 00176 if (!strcasecmp(buf, "channel")) { 00177 ast_copy_string(o->tech, c, sizeof(o->tech)); 00178 if ((c2 = strchr(o->tech, '/'))) { 00179 *c2 = '\0'; 00180 c2++; 00181 ast_copy_string(o->dest, c2, sizeof(o->dest)); 00182 } else { 00183 ast_log(LOG_NOTICE, "Channel should be in form Tech/Dest at line %d of %s\n", lineno, fn); 00184 o->tech[0] = '\0'; 00185 } 00186 } else if (!strcasecmp(buf, "callerid")) { 00187 ast_callerid_split(c, o->cid_name, sizeof(o->cid_name), o->cid_num, sizeof(o->cid_num)); 00188 } else if (!strcasecmp(buf, "application")) { 00189 ast_copy_string(o->app, c, sizeof(o->app)); 00190 } else if (!strcasecmp(buf, "data")) { 00191 ast_copy_string(o->data, c, sizeof(o->data)); 00192 } else if (!strcasecmp(buf, "maxretries")) { 00193 if (sscanf(c, "%d", &o->maxretries) != 1) { 00194 ast_log(LOG_WARNING, "Invalid max retries at line %d of %s\n", lineno, fn); 00195 o->maxretries = 0; 00196 } 00197 } else if (!strcasecmp(buf, "codecs")) { 00198 ast_parse_allow_disallow(NULL, &o->format, c, 1); 00199 } else if (!strcasecmp(buf, "context")) { 00200 ast_copy_string(o->context, c, sizeof(o->context)); 00201 } else if (!strcasecmp(buf, "extension")) { 00202 ast_copy_string(o->exten, c, sizeof(o->exten)); 00203 } else if (!strcasecmp(buf, "priority")) { 00204 if ((sscanf(c, "%d", &o->priority) != 1) || (o->priority < 1)) { 00205 ast_log(LOG_WARNING, "Invalid priority at line %d of %s\n", lineno, fn); 00206 o->priority = 1; 00207 } 00208 } else if (!strcasecmp(buf, "retrytime")) { 00209 if ((sscanf(c, "%d", &o->retrytime) != 1) || (o->retrytime < 1)) { 00210 ast_log(LOG_WARNING, "Invalid retrytime at line %d of %s\n", lineno, fn); 00211 o->retrytime = 300; 00212 } 00213 } else if (!strcasecmp(buf, "waittime")) { 00214 if ((sscanf(c, "%d", &o->waittime) != 1) || (o->waittime < 1)) { 00215 ast_log(LOG_WARNING, "Invalid waittime at line %d of %s\n", lineno, fn); 00216 o->waittime = 45; 00217 } 00218 } else if (!strcasecmp(buf, "retry")) { 00219 o->retries++; 00220 } else if (!strcasecmp(buf, "startretry")) { 00221 if (sscanf(c, "%ld", &o->callingpid) != 1) { 00222 ast_log(LOG_WARNING, "Unable to retrieve calling PID!\n"); 00223 o->callingpid = 0; 00224 } 00225 } else if (!strcasecmp(buf, "endretry") || !strcasecmp(buf, "abortretry")) { 00226 o->callingpid = 0; 00227 o->retries++; 00228 } else if (!strcasecmp(buf, "delayedretry")) { 00229 } else if (!strcasecmp(buf, "setvar") || !strcasecmp(buf, "set")) { 00230 c2 = c; 00231 strsep(&c2, "="); 00232 if (c2) { 00233 var = ast_variable_new(c, c2); 00234 if (var) { 00235 /* Always insert at the end, because some people want to treat the spool file as a script */ 00236 if (last) { 00237 last->next = var; 00238 } else { 00239 o->vars = var; 00240 } 00241 last = var; 00242 } 00243 } else 00244 ast_log(LOG_WARNING, "Malformed \"%s\" argument. Should be \"%s: variable=value\"\n", buf, buf); 00245 } else if (!strcasecmp(buf, "account")) { 00246 ast_copy_string(o->account, c, sizeof(o->account)); 00247 } else if (!strcasecmp(buf, "alwaysdelete")) { 00248 ast_set2_flag(&o->options, ast_true(c), SPOOL_FLAG_ALWAYS_DELETE); 00249 } else if (!strcasecmp(buf, "archive")) { 00250 ast_set2_flag(&o->options, ast_true(c), SPOOL_FLAG_ARCHIVE); 00251 } else { 00252 ast_log(LOG_WARNING, "Unknown keyword '%s' at line %d of %s\n", buf, lineno, fn); 00253 } 00254 } else 00255 ast_log(LOG_NOTICE, "Syntax error at line %d of %s\n", lineno, fn); 00256 } 00257 } 00258 ast_copy_string(o->fn, fn, sizeof(o->fn)); 00259 if (ast_strlen_zero(o->tech) || ast_strlen_zero(o->dest) || (ast_strlen_zero(o->app) && ast_strlen_zero(o->exten))) { 00260 ast_log(LOG_WARNING, "At least one of app or extension must be specified, along with tech and dest in file %s\n", fn); 00261 return -1; 00262 } 00263 return 0; 00264 }
static void* attempt_thread | ( | void * | data | ) | [static] |
Definition at line 342 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_verbose(), outgoing::cid_name, outgoing::cid_num, outgoing::context, outgoing::data, outgoing::dest, outgoing::exten, outgoing::format, free_outgoing(), LOG_EVENT, LOG_NOTICE, outgoing::maxretries, option_verbose, outgoing::priority, remove_from_queue(), outgoing::retries, safe_append(), outgoing::tech, outgoing::vars, VERBOSE_PREFIX_3, and outgoing::waittime.
Referenced by launch_service().
00343 { 00344 struct outgoing *o = data; 00345 int res, reason; 00346 if (!ast_strlen_zero(o->app)) { 00347 if (option_verbose > 2) 00348 ast_verbose(VERBOSE_PREFIX_3 "Attempting call on %s/%s for application %s(%s) (Retry %d)\n", o->tech, o->dest, o->app, o->data, o->retries); 00349 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); 00350 } else { 00351 if (option_verbose > 2) 00352 ast_verbose(VERBOSE_PREFIX_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); 00353 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); 00354 } 00355 if (res) { 00356 ast_log(LOG_NOTICE, "Call failed to go through, reason (%d) %s\n", reason, ast_channel_reason2str(reason)); 00357 if (o->retries >= o->maxretries + 1) { 00358 /* Max retries exceeded */ 00359 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" : ""); 00360 remove_from_queue(o, "Expired"); 00361 } else { 00362 /* Notate that the call is still active */ 00363 safe_append(o, time(NULL), "EndRetry"); 00364 } 00365 } else { 00366 ast_log(LOG_NOTICE, "Call completed to %s/%s\n", o->tech, o->dest); 00367 ast_log(LOG_EVENT, "Queued call to %s/%s completed\n", o->tech, o->dest); 00368 remove_from_queue(o, "Completed"); 00369 } 00370 free_outgoing(o); 00371 return NULL; 00372 }
static void free_outgoing | ( | struct outgoing * | o | ) | [static] |
Definition at line 125 of file pbx_spool.c.
References free.
Referenced by attempt_thread(), launch_service(), and scan_service().
00126 { 00127 free(o); 00128 }
static void init_outgoing | ( | struct outgoing * | o | ) | [static] |
Definition at line 115 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().
00116 { 00117 memset(o, 0, sizeof(struct outgoing)); 00118 o->priority = 1; 00119 o->retrytime = 300; 00120 o->waittime = 45; 00121 o->format = AST_FORMAT_SLINEAR; 00122 ast_set_flag(&o->options, SPOOL_FLAG_ALWAYS_DELETE); 00123 }
static void launch_service | ( | struct outgoing * | o | ) | [static] |
Definition at line 374 of file pbx_spool.c.
References ast_log(), ast_pthread_create, attempt_thread(), free_outgoing(), LOG_WARNING, and t.
Referenced by scan_service().
00375 { 00376 pthread_t t; 00377 pthread_attr_t attr; 00378 int ret; 00379 pthread_attr_init(&attr); 00380 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 00381 if ((ret = ast_pthread_create(&t,&attr,attempt_thread, o)) != 0) { 00382 ast_log(LOG_WARNING, "Unable to create thread :( (returned error: %d)\n", ret); 00383 free_outgoing(o); 00384 } 00385 pthread_attr_destroy(&attr); 00386 }
static int load_module | ( | void | ) | [static] |
Definition at line 511 of file pbx_spool.c.
References ast_config_AST_SPOOL_DIR, ast_log(), ast_pthread_create_background, errno, LOG_WARNING, scan_thread(), and thread.
00512 { 00513 pthread_t thread; 00514 pthread_attr_t attr; 00515 int ret; 00516 snprintf(qdir, sizeof(qdir), "%s/%s", ast_config_AST_SPOOL_DIR, "outgoing"); 00517 if (mkdir(qdir, 0700) && (errno != EEXIST)) { 00518 ast_log(LOG_WARNING, "Unable to create queue directory %s -- outgoing spool disabled\n", qdir); 00519 return 0; 00520 } 00521 snprintf(qdonedir, sizeof(qdir), "%s/%s", ast_config_AST_SPOOL_DIR, "outgoing_done"); 00522 pthread_attr_init(&attr); 00523 pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); 00524 if ((ret = ast_pthread_create_background(&thread,&attr,scan_thread, NULL)) != 0) { 00525 ast_log(LOG_WARNING, "Unable to create thread :( (returned error: %d)\n", ret); 00526 return -1; 00527 } 00528 pthread_attr_destroy(&attr); 00529 return 0; 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.
o | the pointer to outgoing struct | |
status | the exit status of the call. Can be "Completed", "Failed" or "Expired" |
Definition at line 293 of file pbx_spool.c.
References ast_log(), ast_test_flag, errno, f, outgoing::fn, LOG_WARNING, outgoing::options, SPOOL_FLAG_ALWAYS_DELETE, and SPOOL_FLAG_ARCHIVE.
00294 { 00295 int fd; 00296 FILE *f; 00297 char newfn[256]; 00298 const char *bname; 00299 00300 if (!ast_test_flag(&o->options, SPOOL_FLAG_ALWAYS_DELETE)) { 00301 struct stat current_file_status; 00302 00303 if (!stat(o->fn, ¤t_file_status)) 00304 if (time(NULL) < current_file_status.st_mtime) 00305 return 0; 00306 } 00307 00308 if (!ast_test_flag(&o->options, SPOOL_FLAG_ARCHIVE)) { 00309 unlink(o->fn); 00310 return 0; 00311 } 00312 if (mkdir(qdonedir, 0700) && (errno != EEXIST)) { 00313 ast_log(LOG_WARNING, "Unable to create queue directory %s -- outgoing spool archiving disabled\n", qdonedir); 00314 unlink(o->fn); 00315 return -1; 00316 } 00317 fd = open(o->fn, O_WRONLY|O_APPEND); 00318 if (fd > -1) { 00319 f = fdopen(fd, "a"); 00320 if (f) { 00321 fprintf(f, "Status: %s\n", status); 00322 fclose(f); 00323 } else 00324 close(fd); 00325 } 00326 00327 bname = strrchr(o->fn,'/'); 00328 if (bname == NULL) 00329 bname = o->fn; 00330 else 00331 bname++; 00332 snprintf(newfn, sizeof(newfn), "%s/%s", qdonedir, bname); 00333 /* a existing call file the archive dir is overwritten */ 00334 unlink(newfn); 00335 if (rename(o->fn, newfn) != 0) { 00336 unlink(o->fn); 00337 return -1; 00338 } else 00339 return 0; 00340 }
static void safe_append | ( | struct outgoing * | o, | |
time_t | now, | |||
char * | s | |||
) | [static] |
Definition at line 266 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().
00267 { 00268 int fd; 00269 FILE *f; 00270 struct utimbuf tbuf; 00271 fd = open(o->fn, O_WRONLY|O_APPEND); 00272 if (fd > -1) { 00273 f = fdopen(fd, "a"); 00274 if (f) { 00275 fprintf(f, "\n%s: %ld %d (%ld)\n", s, (long)ast_mainpid, o->retries, (long) now); 00276 fclose(f); 00277 } else 00278 close(fd); 00279 /* Update the file time */ 00280 tbuf.actime = now; 00281 tbuf.modtime = now + o->retrytime; 00282 if (utime(o->fn, &tbuf)) 00283 ast_log(LOG_WARNING, "Unable to set utime on %s: %s\n", o->fn, strerror(errno)); 00284 } 00285 }
static int scan_service | ( | char * | fn, | |
time_t | now, | |||
time_t | atime | |||
) | [static] |
Definition at line 388 of file pbx_spool.c.
References apply_outgoing(), ast_log(), ast_mainpid, errno, f, free_outgoing(), init_outgoing(), launch_service(), LOG_DEBUG, LOG_EVENT, LOG_WARNING, malloc, remove_from_queue(), and safe_append().
Referenced by scan_thread().
00389 { 00390 struct outgoing *o; 00391 FILE *f; 00392 o = malloc(sizeof(struct outgoing)); 00393 if (o) { 00394 init_outgoing(o); 00395 f = fopen(fn, "r+"); 00396 if (f) { 00397 if (!apply_outgoing(o, fn, f)) { 00398 #if 0 00399 printf("Filename: %s, Retries: %d, max: %d\n", fn, o->retries, o->maxretries); 00400 #endif 00401 fclose(f); 00402 if (o->retries <= o->maxretries) { 00403 now += o->retrytime; 00404 if (o->callingpid && (o->callingpid == ast_mainpid)) { 00405 safe_append(o, time(NULL), "DelayedRetry"); 00406 ast_log(LOG_DEBUG, "Delaying retry since we're currently running '%s'\n", o->fn); 00407 free_outgoing(o); 00408 } else { 00409 /* Increment retries */ 00410 o->retries++; 00411 /* If someone else was calling, they're presumably gone now 00412 so abort their retry and continue as we were... */ 00413 if (o->callingpid) 00414 safe_append(o, time(NULL), "AbortRetry"); 00415 00416 safe_append(o, now, "StartRetry"); 00417 launch_service(o); 00418 } 00419 return now; 00420 } else { 00421 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" : ""); 00422 free_outgoing(o); 00423 remove_from_queue(o, "Expired"); 00424 return 0; 00425 } 00426 } else { 00427 free_outgoing(o); 00428 ast_log(LOG_WARNING, "Invalid file contents in %s, deleting\n", fn); 00429 fclose(f); 00430 remove_from_queue(o, "Failed"); 00431 } 00432 } else { 00433 free_outgoing(o); 00434 ast_log(LOG_WARNING, "Unable to open %s: %s, deleting\n", fn, strerror(errno)); 00435 remove_from_queue(o, "Failed"); 00436 } 00437 } else 00438 ast_log(LOG_WARNING, "Out of memory :(\n"); 00439 return -1; 00440 }
static void* scan_thread | ( | void * | unused | ) | [static] |
Definition at line 442 of file pbx_spool.c.
References ast_fully_booted, ast_log(), errno, last, LOG_WARNING, and scan_service().
Referenced by load_module().
00443 { 00444 struct stat st; 00445 DIR *dir; 00446 struct dirent *de; 00447 char fn[256]; 00448 int res; 00449 time_t last = 0, next = 0, now; 00450 struct timespec ts = { .tv_sec = 1 }; 00451 00452 while (!ast_fully_booted) { 00453 nanosleep(&ts, NULL); 00454 } 00455 00456 for(;;) { 00457 /* Wait a sec */ 00458 nanosleep(&ts, NULL); 00459 time(&now); 00460 if (!stat(qdir, &st)) { 00461 if ((st.st_mtime != last) || (next && (now > next))) { 00462 #if 0 00463 printf("atime: %ld, mtime: %ld, ctime: %ld\n", st.st_atime, st.st_mtime, st.st_ctime); 00464 printf("Ooh, something changed / timeout\n"); 00465 #endif 00466 next = 0; 00467 last = st.st_mtime; 00468 dir = opendir(qdir); 00469 if (dir) { 00470 while((de = readdir(dir))) { 00471 snprintf(fn, sizeof(fn), "%s/%s", qdir, de->d_name); 00472 if (!stat(fn, &st)) { 00473 if (S_ISREG(st.st_mode)) { 00474 if (st.st_mtime <= now) { 00475 res = scan_service(fn, now, st.st_atime); 00476 if (res > 0) { 00477 /* Update next service time */ 00478 if (!next || (res < next)) { 00479 next = res; 00480 } 00481 } else if (res) { 00482 ast_log(LOG_WARNING, "Failed to scan service '%s'\n", fn); 00483 } else if (!next) { 00484 /* Expired entry: must recheck on the next go-around */ 00485 next = st.st_mtime; 00486 } 00487 } else { 00488 /* Update "next" update if necessary */ 00489 if (!next || (st.st_mtime < next)) 00490 next = st.st_mtime; 00491 } 00492 } 00493 } else 00494 ast_log(LOG_WARNING, "Unable to stat %s: %s\n", fn, strerror(errno)); 00495 } 00496 closedir(dir); 00497 } else 00498 ast_log(LOG_WARNING, "Unable to open directory %s: %s\n", qdir, strerror(errno)); 00499 } 00500 } else 00501 ast_log(LOG_WARNING, "Unable to stat %s\n", qdir); 00502 } 00503 return NULL; 00504 }
static int unload_module | ( | void | ) | [static] |
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_DEFAULT | AST_MODFLAG_BUILDSUM, .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 = "f450f61f60e761b3aa089ebed76ca8a5" , .load = load_module, .unload = unload_module, } [static] |
Definition at line 532 of file pbx_spool.c.
const struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 532 of file pbx_spool.c.
char qdir[255] [static] |
Definition at line 67 of file pbx_spool.c.
char qdonedir[255] [static] |
Definition at line 68 of file pbx_spool.c.