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