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