#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_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 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 };
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.
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, ¤t_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] |
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.