#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, const 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 (const char *fn, time_t now) |
| 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_LOAD_ORDER , .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 = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, } |
| 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 |
| 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 62 of file pbx_spool.c.
00062 { 00063 /*! Always delete the call file after a call succeeds or the 00064 * maximum number of retries is exceeded, even if the 00065 * modification time of the call file is in the future. 00066 */ 00067 SPOOL_FLAG_ALWAYS_DELETE = (1 << 0), 00068 /* Don't unlink the call file after processing, move in qdonedir */ 00069 SPOOL_FLAG_ARCHIVE = (1 << 1), 00070 };
| static void __reg_module | ( | void | ) | [static] |
Definition at line 854 of file pbx_spool.c.
| static void __unreg_module | ( | void | ) | [static] |
Definition at line 854 of file pbx_spool.c.
| static int apply_outgoing | ( | struct outgoing * | o, | |
| const char * | fn, | |||
| FILE * | f | |||
| ) | [static] |
Definition at line 133 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(), outgoing::callingpid, outgoing::capabilities, cid_name, cid_num, context, outgoing::dest, outgoing::exten, exten, 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, strsep(), 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 if ((c2 = strchr(c, '/'))) { 00181 *c2 = '\0'; 00182 c2++; 00183 ast_string_field_set(o, tech, c); 00184 ast_string_field_set(o, dest, c2); 00185 } else { 00186 ast_log(LOG_NOTICE, "Channel should be in form Tech/Dest at line %d of %s\n", lineno, fn); 00187 } 00188 } else if (!strcasecmp(buf, "callerid")) { 00189 char cid_name[80] = {0}, cid_num[80] = {0}; 00190 ast_callerid_split(c, cid_name, sizeof(cid_name), cid_num, sizeof(cid_num)); 00191 ast_string_field_set(o, cid_num, cid_num); 00192 ast_string_field_set(o, cid_name, cid_name); 00193 } else if (!strcasecmp(buf, "application")) { 00194 ast_string_field_set(o, app, c); 00195 } else if (!strcasecmp(buf, "data")) { 00196 ast_string_field_set(o, data, c); 00197 } else if (!strcasecmp(buf, "maxretries")) { 00198 if (sscanf(c, "%30d", &o->maxretries) != 1) { 00199 ast_log(LOG_WARNING, "Invalid max retries at line %d of %s\n", lineno, fn); 00200 o->maxretries = 0; 00201 } 00202 } else if (!strcasecmp(buf, "codecs")) { 00203 ast_parse_allow_disallow(NULL, o->capabilities, c, 1); 00204 } else if (!strcasecmp(buf, "context")) { 00205 ast_string_field_set(o, context, c); 00206 } else if (!strcasecmp(buf, "extension")) { 00207 ast_string_field_set(o, exten, c); 00208 } else if (!strcasecmp(buf, "priority")) { 00209 if ((sscanf(c, "%30d", &o->priority) != 1) || (o->priority < 1)) { 00210 ast_log(LOG_WARNING, "Invalid priority at line %d of %s\n", lineno, fn); 00211 o->priority = 1; 00212 } 00213 } else if (!strcasecmp(buf, "retrytime")) { 00214 if ((sscanf(c, "%30d", &o->retrytime) != 1) || (o->retrytime < 1)) { 00215 ast_log(LOG_WARNING, "Invalid retrytime at line %d of %s\n", lineno, fn); 00216 o->retrytime = 300; 00217 } 00218 } else if (!strcasecmp(buf, "waittime")) { 00219 if ((sscanf(c, "%30d", &o->waittime) != 1) || (o->waittime < 1)) { 00220 ast_log(LOG_WARNING, "Invalid waittime at line %d of %s\n", lineno, fn); 00221 o->waittime = 45; 00222 } 00223 } else if (!strcasecmp(buf, "retry")) { 00224 o->retries++; 00225 } else if (!strcasecmp(buf, "startretry")) { 00226 if (sscanf(c, "%30ld", &o->callingpid) != 1) { 00227 ast_log(LOG_WARNING, "Unable to retrieve calling PID!\n"); 00228 o->callingpid = 0; 00229 } 00230 } else if (!strcasecmp(buf, "endretry") || !strcasecmp(buf, "abortretry")) { 00231 o->callingpid = 0; 00232 o->retries++; 00233 } else if (!strcasecmp(buf, "delayedretry")) { 00234 } else if (!strcasecmp(buf, "setvar") || !strcasecmp(buf, "set")) { 00235 c2 = c; 00236 strsep(&c2, "="); 00237 if (c2) { 00238 var = ast_variable_new(c, c2, fn); 00239 if (var) { 00240 /* Always insert at the end, because some people want to treat the spool file as a script */ 00241 if (last) { 00242 last->next = var; 00243 } else { 00244 o->vars = var; 00245 } 00246 last = var; 00247 } 00248 } else 00249 ast_log(LOG_WARNING, "Malformed \"%s\" argument. Should be \"%s: variable=value\"\n", buf, buf); 00250 } else if (!strcasecmp(buf, "account")) { 00251 ast_string_field_set(o, account, c); 00252 } else if (!strcasecmp(buf, "alwaysdelete")) { 00253 ast_set2_flag(&o->options, ast_true(c), SPOOL_FLAG_ALWAYS_DELETE); 00254 } else if (!strcasecmp(buf, "archive")) { 00255 ast_set2_flag(&o->options, ast_true(c), SPOOL_FLAG_ARCHIVE); 00256 } else { 00257 ast_log(LOG_WARNING, "Unknown keyword '%s' at line %d of %s\n", buf, lineno, fn); 00258 } 00259 } else 00260 ast_log(LOG_NOTICE, "Syntax error at line %d of %s\n", lineno, fn); 00261 } 00262 } 00263 ast_string_field_set(o, fn, fn); 00264 if (ast_strlen_zero(o->tech) || ast_strlen_zero(o->dest) || (ast_strlen_zero(o->app) && ast_strlen_zero(o->exten))) { 00265 ast_log(LOG_WARNING, "At least one of app or extension must be specified, along with tech and dest in file %s\n", fn); 00266 return -1; 00267 } 00268 return 0; 00269 }
| static void* attempt_thread | ( | void * | data | ) | [static] |
Definition at line 346 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::capabilities, outgoing::cid_name, outgoing::cid_num, outgoing::context, outgoing::data, outgoing::dest, outgoing::exten, outgoing::fn, free_outgoing(), LOG_NOTICE, outgoing::maxretries, outgoing::priority, remove_from_queue(), outgoing::retries, outgoing::retrytime, safe_append(), outgoing::tech, outgoing::vars, and outgoing::waittime.
Referenced by launch_service().
00347 { 00348 struct outgoing *o = data; 00349 int res, reason; 00350 if (!ast_strlen_zero(o->app)) { 00351 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); 00352 res = ast_pbx_outgoing_app(o->tech, o->capabilities, o->dest, o->waittime * 1000, 00353 o->app, o->data, &reason, 2 /* wait to finish */, o->cid_num, o->cid_name, 00354 o->vars, o->account, NULL); 00355 o->vars = NULL; 00356 } else { 00357 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); 00358 res = ast_pbx_outgoing_exten(o->tech, o->capabilities, o->dest, 00359 o->waittime * 1000, o->context, o->exten, o->priority, &reason, 00360 2 /* wait to finish */, o->cid_num, o->cid_name, o->vars, o->account, NULL); 00361 o->vars = NULL; 00362 } 00363 if (res) { 00364 ast_log(LOG_NOTICE, "Call failed to go through, reason (%d) %s\n", reason, ast_channel_reason2str(reason)); 00365 if (o->retries >= o->maxretries + 1) { 00366 /* Max retries exceeded */ 00367 ast_log(LOG_NOTICE, "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" : ""); 00368 remove_from_queue(o, "Expired"); 00369 } else { 00370 /* Notate that the call is still active */ 00371 safe_append(o, time(NULL), "EndRetry"); 00372 #if defined(HAVE_INOTIFY) || defined(HAVE_KQUEUE) 00373 queue_file(o->fn, time(NULL) + o->retrytime); 00374 #endif 00375 } 00376 } else { 00377 ast_log(LOG_NOTICE, "Call completed to %s/%s\n", o->tech, o->dest); 00378 remove_from_queue(o, "Completed"); 00379 } 00380 free_outgoing(o); 00381 return NULL; 00382 }
| static void free_outgoing | ( | struct outgoing * | o | ) | [static] |
Definition at line 123 of file pbx_spool.c.
References ast_format_cap_destroy(), ast_free, ast_string_field_free_memory, ast_variables_destroy(), outgoing::capabilities, and outgoing::vars.
Referenced by attempt_thread(), launch_service(), and scan_service().
00124 { 00125 if (o->vars) { 00126 ast_variables_destroy(o->vars); 00127 } 00128 ast_string_field_free_memory(o); 00129 o->capabilities = ast_format_cap_destroy(o->capabilities); 00130 ast_free(o); 00131 }
| static int init_outgoing | ( | struct outgoing * | o | ) | [static] |
Definition at line 104 of file pbx_spool.c.
References ast_format_cap_add(), ast_format_cap_alloc_nolock(), ast_format_set(), AST_FORMAT_SLINEAR, ast_set_flag, ast_string_field_init, outgoing::capabilities, outgoing::options, outgoing::priority, outgoing::retrytime, SPOOL_FLAG_ALWAYS_DELETE, and outgoing::waittime.
Referenced by scan_service().
00105 { 00106 struct ast_format tmpfmt; 00107 o->priority = 1; 00108 o->retrytime = 300; 00109 o->waittime = 45; 00110 00111 if (!(o->capabilities = ast_format_cap_alloc_nolock())) { 00112 return -1; 00113 } 00114 ast_format_cap_add(o->capabilities, ast_format_set(&tmpfmt, AST_FORMAT_SLINEAR, 0)); 00115 00116 ast_set_flag(&o->options, SPOOL_FLAG_ALWAYS_DELETE); 00117 if (ast_string_field_init(o, 128)) { 00118 return -1; 00119 } 00120 return 0; 00121 }
| static void launch_service | ( | struct outgoing * | o | ) | [static] |
Definition at line 384 of file pbx_spool.c.
References ast_log(), ast_pthread_create_detached, attempt_thread(), free_outgoing(), and LOG_WARNING.
Referenced by scan_service().
00385 { 00386 pthread_t t; 00387 int ret; 00388 00389 if ((ret = ast_pthread_create_detached(&t, NULL, attempt_thread, o))) { 00390 ast_log(LOG_WARNING, "Unable to create thread :( (returned error: %d)\n", ret); 00391 free_outgoing(o); 00392 } 00393 }
| static int load_module | ( | void | ) | [static] |
Definition at line 835 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.
00836 { 00837 pthread_t thread; 00838 int ret; 00839 snprintf(qdir, sizeof(qdir), "%s/%s", ast_config_AST_SPOOL_DIR, "outgoing"); 00840 if (ast_mkdir(qdir, 0777)) { 00841 ast_log(LOG_WARNING, "Unable to create queue directory %s -- outgoing spool disabled\n", qdir); 00842 return AST_MODULE_LOAD_DECLINE; 00843 } 00844 snprintf(qdonedir, sizeof(qdir), "%s/%s", ast_config_AST_SPOOL_DIR, "outgoing_done"); 00845 00846 if ((ret = ast_pthread_create_detached_background(&thread, NULL, scan_thread, NULL))) { 00847 ast_log(LOG_WARNING, "Unable to create thread :( (returned error: %d)\n", ret); 00848 return AST_MODULE_LOAD_FAILURE; 00849 } 00850 00851 return AST_MODULE_LOAD_SUCCESS; 00852 }
| 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 295 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.
00296 { 00297 FILE *f; 00298 char newfn[256]; 00299 const char *bname; 00300 00301 if (!ast_test_flag(&o->options, SPOOL_FLAG_ALWAYS_DELETE)) { 00302 struct stat current_file_status; 00303 00304 if (!stat(o->fn, ¤t_file_status)) { 00305 if (time(NULL) < current_file_status.st_mtime) { 00306 return 0; 00307 } 00308 } 00309 } 00310 00311 if (!ast_test_flag(&o->options, SPOOL_FLAG_ARCHIVE)) { 00312 unlink(o->fn); 00313 return 0; 00314 } 00315 00316 if (ast_mkdir(qdonedir, 0777)) { 00317 ast_log(LOG_WARNING, "Unable to create queue directory %s -- outgoing spool archiving disabled\n", qdonedir); 00318 unlink(o->fn); 00319 return -1; 00320 } 00321 00322 if (!(bname = strrchr(o->fn, '/'))) { 00323 bname = o->fn; 00324 } else { 00325 bname++; 00326 } 00327 00328 snprintf(newfn, sizeof(newfn), "%s/%s", qdonedir, bname); 00329 /* a existing call file the archive dir is overwritten */ 00330 unlink(newfn); 00331 if (rename(o->fn, newfn) != 0) { 00332 unlink(o->fn); 00333 return -1; 00334 } 00335 00336 /* Only append to the file AFTER we move it out of the watched directory, 00337 * otherwise the fclose() causes another event for inotify(7) */ 00338 if ((f = fopen(newfn, "a"))) { 00339 fprintf(f, "Status: %s\n", status); 00340 fclose(f); 00341 } 00342 00343 return 0; 00344 }
| static void safe_append | ( | struct outgoing * | o, | |
| time_t | now, | |||
| char * | s | |||
| ) | [static] |
Definition at line 271 of file pbx_spool.c.
References ast_debug, ast_log(), ast_mainpid, outgoing::dest, errno, f, outgoing::fn, LOG_WARNING, outgoing::retries, outgoing::retrytime, and outgoing::tech.
Referenced by attempt_thread(), and scan_service().
00272 { 00273 FILE *f; 00274 struct utimbuf tbuf = { .actime = now, .modtime = now + o->retrytime }; 00275 00276 ast_debug(1, "Outgoing %s/%s: %s\n", o->tech, o->dest, s); 00277 00278 if ((f = fopen(o->fn, "a"))) { 00279 fprintf(f, "\n%s: %ld %d (%ld)\n", s, (long)ast_mainpid, o->retries, (long) now); 00280 fclose(f); 00281 } 00282 00283 /* Update the file time */ 00284 if (utime(o->fn, &tbuf)) { 00285 ast_log(LOG_WARNING, "Unable to set utime on %s: %s\n", o->fn, strerror(errno)); 00286 } 00287 }
| static int scan_service | ( | const char * | fn, | |
| time_t | now | |||
| ) | [static] |
Definition at line 396 of file pbx_spool.c.
References apply_outgoing(), ast_calloc, ast_debug, ast_free, ast_log(), ast_mainpid, outgoing::callingpid, outgoing::dest, errno, f, outgoing::fn, free_outgoing(), init_outgoing(), launch_service(), LOG_NOTICE, LOG_WARNING, outgoing::maxretries, remove_from_queue(), outgoing::retries, outgoing::retrytime, safe_append(), and outgoing::tech.
Referenced by scan_thread().
00397 { 00398 struct outgoing *o = NULL; 00399 FILE *f; 00400 int res = 0; 00401 00402 if (!(o = ast_calloc(1, sizeof(*o)))) { 00403 ast_log(LOG_WARNING, "Out of memory ;(\n"); 00404 return -1; 00405 } 00406 00407 if (init_outgoing(o)) { 00408 /* No need to call free_outgoing here since we know the failure 00409 * was to allocate string fields and no variables have been allocated 00410 * yet. 00411 */ 00412 ast_free(o); 00413 return -1; 00414 } 00415 00416 /* Attempt to open the file */ 00417 if (!(f = fopen(fn, "r"))) { 00418 remove_from_queue(o, "Failed"); 00419 free_outgoing(o); 00420 #if !defined(HAVE_INOTIFY) && !defined(HAVE_KQUEUE) 00421 ast_log(LOG_WARNING, "Unable to open %s: %s, deleting\n", fn, strerror(errno)); 00422 #endif 00423 return -1; 00424 } 00425 00426 /* Read in and verify the contents */ 00427 if (apply_outgoing(o, fn, f)) { 00428 remove_from_queue(o, "Failed"); 00429 free_outgoing(o); 00430 ast_log(LOG_WARNING, "Invalid file contents in %s, deleting\n", fn); 00431 fclose(f); 00432 return -1; 00433 } 00434 00435 #if 0 00436 printf("Filename: %s, Retries: %d, max: %d\n", fn, o->retries, o->maxretries); 00437 #endif 00438 fclose(f); 00439 if (o->retries <= o->maxretries) { 00440 now += o->retrytime; 00441 if (o->callingpid && (o->callingpid == ast_mainpid)) { 00442 safe_append(o, time(NULL), "DelayedRetry"); 00443 ast_debug(1, "Delaying retry since we're currently running '%s'\n", o->fn); 00444 free_outgoing(o); 00445 } else { 00446 /* Increment retries */ 00447 o->retries++; 00448 /* If someone else was calling, they're presumably gone now 00449 so abort their retry and continue as we were... */ 00450 if (o->callingpid) 00451 safe_append(o, time(NULL), "AbortRetry"); 00452 00453 safe_append(o, now, "StartRetry"); 00454 launch_service(o); 00455 } 00456 res = now; 00457 } else { 00458 ast_log(LOG_NOTICE, "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" : ""); 00459 remove_from_queue(o, "Expired"); 00460 free_outgoing(o); 00461 } 00462 00463 return res; 00464 }
| static void* scan_thread | ( | void * | unused | ) | [static] |
Definition at line 757 of file pbx_spool.c.
References ast_fully_booted, ast_log(), errno, last, LOG_WARNING, and scan_service().
Referenced by load_module().
00758 { 00759 struct stat st; 00760 DIR *dir; 00761 struct dirent *de; 00762 char fn[256]; 00763 int res; 00764 time_t last = 0, next = 0, now; 00765 struct timespec ts = { .tv_sec = 1 }; 00766 00767 while (!ast_fully_booted) { 00768 nanosleep(&ts, NULL); 00769 } 00770 00771 for(;;) { 00772 /* Wait a sec */ 00773 nanosleep(&ts, NULL); 00774 time(&now); 00775 00776 if (stat(qdir, &st)) { 00777 ast_log(LOG_WARNING, "Unable to stat %s\n", qdir); 00778 continue; 00779 } 00780 00781 /* Make sure it is time for us to execute our check */ 00782 if ((st.st_mtime == last) && (next && (next > now))) 00783 continue; 00784 00785 #if 0 00786 printf("atime: %ld, mtime: %ld, ctime: %ld\n", st.st_atime, st.st_mtime, st.st_ctime); 00787 printf("Ooh, something changed / timeout\n"); 00788 #endif 00789 next = 0; 00790 last = st.st_mtime; 00791 00792 if (!(dir = opendir(qdir))) { 00793 ast_log(LOG_WARNING, "Unable to open directory %s: %s\n", qdir, strerror(errno)); 00794 continue; 00795 } 00796 00797 while ((de = readdir(dir))) { 00798 snprintf(fn, sizeof(fn), "%s/%s", qdir, de->d_name); 00799 if (stat(fn, &st)) { 00800 ast_log(LOG_WARNING, "Unable to stat %s: %s\n", fn, strerror(errno)); 00801 continue; 00802 } 00803 if (!S_ISREG(st.st_mode)) 00804 continue; 00805 if (st.st_mtime <= now) { 00806 res = scan_service(fn, now); 00807 if (res > 0) { 00808 /* Update next service time */ 00809 if (!next || (res < next)) { 00810 next = res; 00811 } 00812 } else if (res) { 00813 ast_log(LOG_WARNING, "Failed to scan service '%s'\n", fn); 00814 } else if (!next) { 00815 /* Expired entry: must recheck on the next go-around */ 00816 next = st.st_mtime; 00817 } 00818 } else { 00819 /* Update "next" update if necessary */ 00820 if (!next || (st.st_mtime < next)) 00821 next = st.st_mtime; 00822 } 00823 } 00824 closedir(dir); 00825 } 00826 return NULL; 00827 }
| static int unload_module | ( | void | ) | [static] |
struct ast_module_info __mod_info = { .name = AST_MODULE, .flags = AST_MODFLAG_LOAD_ORDER , .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 = AST_BUILDOPT_SUM, .load = load_module, .unload = unload_module, .load_pri = AST_MODPRI_DEFAULT, } [static] |
Definition at line 854 of file pbx_spool.c.
struct ast_module_info* ast_module_info = &__mod_info [static] |
Definition at line 854 of file pbx_spool.c.
char qdir[255] [static] |
Definition at line 72 of file pbx_spool.c.
char qdonedir[255] [static] |
Definition at line 73 of file pbx_spool.c.
1.5.6