#include <unistd.h>
#include <stdio.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <sys/types.h>
#include <pthread.h>
#include <time.h>
#include <dlfcn.h>
#include <sys/time.h>
#include <time.h>
#include <syslog.h>
#include "../pfqlib.h"
#include "pfqlib_priv.h"
#include "../config.h"
#include "../pfregex.h"
#include "../pfqmessage.h"
#include "../backends/pfq_backend.h"
#define LOGLEVEL LOG_USER | LOG_ERR
#define PFQ_SONAME "0"
int dig_suspend;
#define TH_UNINITIALIZED -1
#define TH_RUNNABLE 0
#define TH_STOPRQ 1
#define TH_STOPPED 2
int thread_control;
int tmp_sort_sense;
// Compare callbacks for qsort
int msg_compare_from ( const void *m1, const void *m2 ) {
return tmp_sort_sense * strcmp ( ((struct msg_t*)m1)->from, ((struct msg_t*)m2)->from );
}
int msg_compare_to ( const void *m1, const void *m2 ) {
return tmp_sort_sense * strcmp ( ((struct msg_t*)m1)->to, ((struct msg_t*)m2)->to );
}
int msg_compare_subject ( const void *m1, const void *m2 ) {
return tmp_sort_sense * strcmp ( ((struct msg_t*)m1)->subj, ((struct msg_t*)m2)->subj );
}
struct pfql_status_t* pfql_getstatus( struct pfql_context_t *ctx ) {
return &ctx->pfql_status;
}
struct pfql_conf_t* pfql_getconf( struct pfql_context_t *ctx) {
return &ctx->pfql_conf;
}
const char* pfql_version() {
return PFQL_VERSION;
}
const char* pfql_queue_name( struct pfql_context_t *ctx, int i) {
return ctx->pfqbe_queue_name(i);
}
void pfql_queue_sort ( struct pfql_context_t *ctx ) {
tmp_sort_sense = ctx->pfql_status.sort_sense;
if ( ctx->pfql_status.sort_field==PFQL_SORT_FROM )
qsort ( ctx->queue, ctx->NUMMSG, sizeof(struct msg_t), msg_compare_from );
if ( ctx->pfql_status.sort_field==PFQL_SORT_TO )
qsort ( ctx->queue, ctx->NUMMSG, sizeof(struct msg_t), msg_compare_to );
if ( ctx->pfql_status.sort_field==PFQL_SORT_SUBJECT )
qsort ( ctx->queue, ctx->NUMMSG, sizeof(struct msg_t), msg_compare_subject );
}
time_t pfql_queue_last_changed( struct pfql_context_t *ctx ) {
return ctx->queue_last_changed;
}
int pfql_backend_apiversion( struct pfql_context_t *ctx ) {
return ctx->pfqbe_apiversion();
}
const char* pfql_backend_id( struct pfql_context_t *ctx ) {
return ctx->pfqbe_id();
}
const char* pfql_backend_version( struct pfql_context_t *ctx ) {
return ctx->pfqbe_version();
}
int pfql_retr_status( struct pfql_context_t *ctx, const char *id ) {
return ctx->pfqbe_retr_status(id);
}
int pfql_retr_headers( struct pfql_context_t *ctx, const char *id ) {
return ctx->pfqbe_retr_headers(id);
}
int pfql_retr_body( struct pfql_context_t *ctx, const char *id, void* buf, size_t t) {
int res;
res = ctx->pfqbe_retr_body(id,buf,t);
if ( res != PFBE_MSGNOTEX )
return res;
else
return PFQL_MSGNOTEX;
}
int pfql_msg_getpos( struct pfql_context_t *ctx, const char* id) {
int i;
if ( !ctx->NUMMSG )
return PFQL_MSGNOTEX;
for ( i=0; i<ctx->NUMMSG; i++ ) {
if ( !strcmp(id, ctx->queue[i].id ) )
return i;
}
return PFQL_MSGNOTEX;
}
int pfql_num_msg( struct pfql_context_t *ctx ) {
return ctx->NUMMSG;
}
int pfql_num_tag( struct pfql_context_t *ctx ) {
return ctx->NUMTAG;
}
void pfql_msg_tag( struct pfql_context_t *ctx, const char* id) {
int i;
i = pfql_msg_getpos(ctx,id);
if ( i==-1 )
return;
if ( !ctx->queue[i].tagged ) {
ctx->queue[i].tagged = 1;
ctx->NUMTAG++;
}
}
void pfql_msg_untag( struct pfql_context_t *ctx, const char* id) {
int i;
i = pfql_msg_getpos(ctx,id);
if ( i==-1 )
return;
if ( ctx->queue[i].tagged ) {
ctx->queue[i].tagged = 0;
ctx->NUMTAG--;
}
}
void pfql_msg_toggletag( struct pfql_context_t *ctx, const char* id) {
int i;
i = pfql_msg_getpos(ctx,id);
if ( i==-1 )
return;
if ( ctx->queue[i].tagged )
pfql_msg_untag(ctx,id);
else
pfql_msg_tag(ctx,id);
}
int pfql_msg_istagged( struct pfql_context_t *ctx, const char* id) {
int i;
i = pfql_msg_getpos(ctx, id);
if ( i==-1 )
return 0;
return ctx->queue[i].tagged;
}
struct msg_t *pfql_msg_at( struct pfql_context_t *ctx, int i) {
if ( i<ctx->NUMMSG )
return &ctx->queue[i];
else
return NULL;
}
struct msg_t *pfql_msg( struct pfql_context_t *ctx, const char* id) {
int i;
i = pfql_msg_getpos(ctx, id);
if ( i==-1 )
return NULL;
else
return &ctx->queue[i];
}
// Threaded loop
void* queue_fill_thread(void *arg) {
int NUMMSG_NEW;
int i;
int b;
struct pfql_context_t *ctx = (struct pfql_context_t*)arg;
while ( thread_control == TH_RUNNABLE ) {
ctx->pfql_status.queue_status = PFQL_Q_FILLING;
if ( !dig_suspend && ctx->pfql_status.do_scan ) {
if ( dig_limit )
dig_start = time(NULL);
NUMMSG_NEW = ctx->pfqbe_fill_queue();
b = 0;
if ( NUMMSG_NEW != ctx->NUMMSG )
b = 1;
ctx->NUMMSG = NUMMSG_NEW;
for ( i=0; i<NUMMSG_NEW; i++ ) {
if ( ctx->queue_thread[i].changed ) {
memcpy ( ctx->queue[i].id, ctx->queue_thread[i].id, sizeof(ctx->queue[i].id) );
memcpy ( ctx->queue[i].path, ctx->queue_thread[i].path, sizeof(ctx->queue[i].path) );
ctx->queue[i].hcached = 0;
ctx->queue[i].scached = 0;
ctx->queue[i].tagged = 0;
b = 1;
if ( ctx->pfql_status.sort_field )
pfql_retr_headers ( ctx, ctx->queue[i].id );
}
}
if ( b )
ctx->queue_last_changed = time(NULL);
ctx->dig_lastqueue = ctx->pfql_status.cur_queue;
}
if ( ctx->pfql_status.sort_field!=PFQL_SORT_UNSORTED ) {
ctx->pfql_status.queue_status = PFQL_Q_SORTING;
pfql_queue_sort ( ctx );
ctx->pfql_status.queue_status = PFQL_Q_IDLE;
}
sleep ( ctx->pfql_conf.scan_delay );
}
pthread_mutex_unlock ( &ctx->qfill_mutex );
thread_control = TH_STOPPED;
pthread_exit(NULL);
}
// Launches the dig thread
int queue_fill_start(struct pfql_context_t* ctx) {
if ( pthread_mutex_trylock(&ctx->qfill_mutex)!=0 )
return PFQL_ERROR;
thread_control = TH_RUNNABLE;
pthread_create ( &ctx->qfill_thread, NULL, queue_fill_thread, ctx );
return PFQL_OK;
}
// Stops the dig thread
int queue_fill_stop() {
if ( thread_control != TH_UNINITIALIZED )
thread_control = TH_STOPRQ;
while ( thread_control != TH_STOPPED && thread_control != TH_UNINITIALIZED )
usleep ( 200000 );
return 0;
}
// Performs an action on the message
void msg_action_do ( struct pfql_context_t *ctx, const char* id, int act ) {
switch ( act ) {
case MSG_DELETE:
ctx->pfqbe_message_delete ( id );
break;
case MSG_HOLD:
ctx->pfqbe_message_hold ( id );
break;
case MSG_RELEASE:
ctx->pfqbe_message_release ( id );
break;
case MSG_REQUEUE:
ctx->pfqbe_message_requeue ( id );
break;
default:
return;
}
}
// Tags all messages
void pfql_tag_all( struct pfql_context_t *ctx ) {
int i;
for ( i=0; i<ctx->NUMMSG; i++ )
ctx->queue[i].tagged = TRUE;
ctx->NUMTAG = ctx->NUMMSG;
}
// Resets tag flag on all messages
void pfql_tag_none( struct pfql_context_t *ctx ) {
int i;
for ( i=0; i<ctx->NUMMSG; i++ )
ctx->queue[i].tagged = FALSE;
ctx->pfql_status.wrk_tagged = FALSE;
ctx->NUMTAG = 0;
}
// Reset the cache flag of the messages
void msg_cachereset( struct pfql_context_t *ctx ) {
int i;
for ( i=0; i<ctx->NUMMSG; i++ )
ctx->queue[i].hcached = 0;
}
// Wrapper
void pfql_msg_action ( struct pfql_context_t *ctx, const char *id, int act ) {
int i;
if ( (ctx->pfql_status.wrk_tagged) || (ctx->pfql_status.auto_wrk_tagged && ctx->NUMTAG) ) {
dig_suspend = 1;
for ( i = 0; i<ctx->NUMMSG; i++ ) {
if ( ctx->queue[i].tagged )
msg_action_do ( ctx, ctx->queue[i].id, act );
}
pfql_tag_none(ctx);
dig_suspend = 0;
} else {
i = pfql_msg_getpos(ctx,id);
if ( i==-1 )
return;
msg_action_do ( ctx, ctx->queue[i].id, act );
}
return;
}
// Clears the queue
void queue_reset( struct pfql_context_t *ctx ) {
memset ( ctx->queue, 0, sizeof(struct msg_t)*ctx->pfql_conf.msg_max );
}
int pfql_num_queues( struct pfql_context_t *ctx ) {
return ctx->pfqbe_queue_count();
}
// Changes the current queue
int pfql_set_queue( struct pfql_context_t *ctx, int q ) {
if ( q >= ctx->pfqbe_queue_count() )
return PFQL_ERROR;
ctx->pfql_status.cur_queue = q;
ctx->NUMTAG = 0;
ctx->pfql_status.wrk_tagged = FALSE;
queue_reset(ctx);
ctx->queue_last_changed = time(NULL);
ctx->pfqbe_set_queue ( q );
// Ensure that a scan is made before proceeding, loop 1/5 sec
while ( ctx->dig_lastqueue != ctx->pfql_status.cur_queue ) { usleep ( 200000 ); };
return PFQL_OK;
}
// Search for a message; returns -1 if not found
int msg_match( struct pfql_context_t *ctx, int reset, int direction) {
int i, res;
static int pos;
if ( reset )
pos = -1;
if ( direction==0 )
pos++;
else
pos--;
if ( pos<0 )
return -1;
res = 0;
if ( direction==0 ) {
for ( i=pos; i<ctx->NUMMSG; i++ ) {
ctx->pfqbe_retr_headers ( ctx->queue[i].id );
if ( ( (ctx->search_mode & SM_FROM) && regexec(ctx->regexp,ctx->queue[i].from,res,NULL,0)==0 ) ||
( (ctx->search_mode & SM_TO) && regexec(ctx->regexp,ctx->queue[i].to ,res,NULL,0)==0 ) ||
( (ctx->search_mode & SM_SUBJ) && regexec(ctx->regexp,ctx->queue[i].subj,res,NULL,0)==0 ) ) {
pos = i;
return i;
}
}
} else {
for ( i=pos; i>=0; i-- ) {
ctx->pfqbe_retr_headers ( ctx->queue[i].id );
if ( ( (ctx->search_mode & SM_FROM) && regexec(ctx->regexp,ctx->queue[i].from,res,NULL,0)==0 ) ||
( (ctx->search_mode & SM_TO) && regexec(ctx->regexp,ctx->queue[i].to ,res,NULL,0)==0 ) ||
( (ctx->search_mode & SM_SUBJ) && regexec(ctx->regexp,ctx->queue[i].subj,res,NULL,0)==0 ) ) {
pos = i;
return i;
}
}
}
return -1;
}
int pfql_msg_search( struct pfql_context_t *ctx, const char* regexps) {
int res;
res = regcomp ( ctx->regexp, regexps, 0 );
if ( !res )
return msg_match(ctx,1,0);
else
return PFQL_INVREGEXP;
}
int pfql_msg_searchnext( struct pfql_context_t *ctx, const char* regexps) {
int res;
res = regcomp ( ctx->regexp, regexps, 0 );
if ( !res )
return msg_match(ctx,0,0);
else
return PFQL_INVREGEXP;
}
int pfql_msg_searchprev( struct pfql_context_t *ctx, const char* regexps) {
int res;
res = regcomp ( ctx->regexp, regexps, 0 );
if ( !res )
return msg_match(ctx,0,1);
else
return PFQL_INVREGEXP;
}
void pfql_msg_searchandtag ( struct pfql_context_t *ctx, const char* regexps) {
int res;
res = regcomp ( ctx->regexp, regexps, 0 );
if ( !res ) {
res = msg_match(ctx,1,0);
while ( res != -1 ) {
ctx->queue[res].tagged = 1;
ctx->NUMTAG++;
res = pfql_msg_searchnext(ctx,regexps);
}
}
}
// Toggle envelope usage for from/to
void pfql_toggle_envelope(struct pfql_context_t *ctx) {
if ( !(ctx->pfqbe_get_caps() & BECAPS_MSG_ENVELOPE) )
return;
ctx->pfql_status.use_envelope = !ctx->pfql_status.use_envelope;
msg_cachereset(ctx);
ctx->pfqbe_use_envelope ( ctx->pfql_status.use_envelope );
}
int be_load ( struct pfql_context_t *ctx, const char* be ) {
char buf[BUF_SIZE];
if ( strlen(ctx->pfql_conf.backends_path) )
sprintf ( buf, "%s/libpfq_%s.so.%s", ctx->pfql_conf.backends_path, be, PFQ_SONAME );
else
sprintf ( buf, "%s/libpfq_%s.so.%s", PFBEDIR, be, PFQ_SONAME );
ctx->beptr = dlopen ( buf, RTLD_LAZY );
if ( !ctx->beptr ) {
syslog ( LOGLEVEL, "%s", dlerror() );
// Try 'pfqueue' subdir
if ( strlen(ctx->pfql_conf.backends_path) )
sprintf ( buf, "%s/pfqueue/libpfq_%s.so", ctx->pfql_conf.backends_path, be );
else
sprintf ( buf, "pfqueue/libpfq_%s.so", be );
ctx->beptr = dlopen ( buf, RTLD_LAZY );
}
if ( !ctx->beptr ) {
syslog ( LOGLEVEL, "%s", dlerror() );
return PFQL_BENOTFOUND;
}
ctx->pfqbe_apiversion = dlsym( ctx->beptr, "pfb_apiversion" );
if ( !ctx->pfqbe_apiversion )
return PFQL_BEMISSINGSYM;
if ( ctx->pfqbe_apiversion()!=3 )
return PFQL_BEWRONGAPI;
ctx->pfqbe_init = dlsym( ctx->beptr, "pfb_init" );
if ( !ctx->pfqbe_init )
return PFQL_BEMISSINGSYM;
ctx->pfqbe_close = dlsym( ctx->beptr, "pfb_close" );
if ( !ctx->pfqbe_close )
return PFQL_BEMISSINGSYM;
ctx->pfqbe_id = dlsym( ctx->beptr, "pfb_id" );
if ( !ctx->pfqbe_id )
return PFQL_BEMISSINGSYM;
ctx->pfqbe_version = dlsym( ctx->beptr, "pfb_version" );
if ( !ctx->pfqbe_version )
return PFQL_BEMISSINGSYM;
ctx->pfqbe_setup = dlsym( ctx->beptr, "pfb_setup" );
if ( !ctx->pfqbe_setup )
return PFQL_BEMISSINGSYM;
ctx->pfqbe_fill_queue = dlsym( ctx->beptr, "pfb_fill_queue" );
if ( !ctx->pfqbe_fill_queue )
return PFQL_BEMISSINGSYM;
ctx->pfqbe_retr_headers = dlsym( ctx->beptr, "pfb_retr_headers" );
if ( !ctx->pfqbe_retr_headers )
return PFQL_BEMISSINGSYM;
ctx->pfqbe_retr_status = dlsym( ctx->beptr, "pfb_retr_status" );
if ( !ctx->pfqbe_retr_status )
return PFQL_BEMISSINGSYM;
ctx->pfqbe_retr_body = dlsym( ctx->beptr, "pfb_retr_body" );
if ( !ctx->pfqbe_retr_body )
return PFQL_BEMISSINGSYM;
ctx->pfqbe_message_delete = dlsym( ctx->beptr, "pfb_message_delete" );
if ( !ctx->pfqbe_message_delete )
return PFQL_BEMISSINGSYM;
ctx->pfqbe_message_hold = dlsym( ctx->beptr, "pfb_message_hold" );
if ( !ctx->pfqbe_message_hold )
return PFQL_BEMISSINGSYM;
ctx->pfqbe_message_release = dlsym( ctx->beptr, "pfb_message_release" );
if ( !ctx->pfqbe_message_release )
return PFQL_BEMISSINGSYM;
ctx->pfqbe_message_requeue = dlsym( ctx->beptr, "pfb_message_requeue" );
if ( !ctx->pfqbe_message_requeue )
return PFQL_BEMISSINGSYM;
ctx->pfqbe_set_queue = dlsym( ctx->beptr, "pfb_set_queue" );
if ( !ctx->pfqbe_set_queue )
return PFQL_BEMISSINGSYM;
ctx->pfqbe_use_envelope = dlsym( ctx->beptr, "pfb_use_envelope" );
if ( !ctx->pfqbe_use_envelope )
return PFQL_BEMISSINGSYM;
ctx->pfqbe_get_caps = dlsym( ctx->beptr, "pfb_get_caps" );
if ( !ctx->pfqbe_get_caps )
return PFQL_BEMISSINGSYM;
ctx->pfqbe_queue_name = dlsym( ctx->beptr, "pfb_queue_name" );
if ( !ctx->pfqbe_queue_name )
return PFQL_BEMISSINGSYM;
ctx->pfqbe_queue_count = dlsym( ctx->beptr, "pfb_queue_count" );
if ( !ctx->pfqbe_queue_count )
return PFQL_BEMISSINGSYM;
ctx->pfqbe_getconf = dlsym( ctx->beptr, "pfb_getconf" );
if ( !ctx->pfqbe_queue_count )
return PFQL_BEMISSINGSYM;
return PFQL_OK;
}
int be_try ( struct pfql_context_t *ctx, const char *b ) {
int res;
res = be_load ( ctx, b );
if ( res )
return PFQL_ERROR;
res = ctx->pfqbe_init ();
if ( res )
return PFQL_ERROR;
ctx->pfqbe_getconf()->msg_max = ctx->pfql_conf.msg_max;
ctx->pfqbe_getconf()->scan_limit = ctx->pfql_conf.scan_limit;
res = ctx->pfqbe_setup(ctx->queue, ctx->queue_thread);
if ( res )
return PFQL_ERROR;
ctx->pfqbe_close(ctx);
return PFQL_OK;
}
int pfql_context_create ( struct pfql_context_t **ctx ) {
*ctx = malloc(sizeof(struct pfql_context_t));
if ( !ctx )
return PFQL_MALLOC;
else
return PFQL_OK;
}
int pfql_init(struct pfql_context_t *ctx) {
/* Defaults */
ctx->pfql_conf.max_char = 200;
ctx->pfql_conf.initial_queue = 0;
sprintf ( ctx->pfql_conf.backends_path, "%c", 0 );
sprintf ( ctx->pfql_conf.backend_name, "autodetect" );
ctx->pfql_conf.msg_max = 200;
ctx->pfql_conf.scan_limit = 0;
ctx->pfql_conf.scan_delay = 1;
sprintf ( ctx->pfql_conf.remote_host, "%c", 0 );
ctx->pfql_conf.remote_port = 20000;
ctx->pfql_status.wrk_tagged = 0;
ctx->pfql_status.auto_wrk_tagged = 0;
ctx->pfql_status.ask_confirm = 1;
ctx->pfql_status.do_scan = 1;
ctx->pfql_status.use_envelope = 0;
ctx->pfql_status.use_colors = 1;
ctx->pfql_status.cur_queue = 0;
ctx->pfql_status.sort_field = PFQL_SORT_UNSORTED;
ctx->pfql_status.sort_sense = PFQL_SORT_ASC;
ctx->beptr = 0;
ctx->queue = 0;
ctx->queue_thread = 0;
ctx->regexp = 0;
ctx->NUMTAG = 0;
return PFQL_OK;
}
void pfql_backend_setconfig(struct pfql_context_t *ctx, const char* c) {
strcpy ( ctx->pfqbe_getconf()->config_path, c );
}
void pfql_backend_setcommand(struct pfql_context_t *ctx, const char* c) {
strcpy ( ctx->pfqbe_getconf()->command_path, c );
}
int pfql_start(struct pfql_context_t *ctx) {
int res;
thread_control = TH_UNINITIALIZED;
/* Alloc resources */
ctx->regexp = (regex_t*) malloc (sizeof(regex_t));
if ( !ctx->regexp ) {
syslog ( LOGLEVEL, "pfqlib: sorry, cannot malloc for %d for the regex!", sizeof(regex_t) );
return PFQL_MALLOC;
}
res = regcomp ( ctx->regexp, "*", 0 );
ctx->queue = (struct msg_t*)malloc(sizeof(struct msg_t)*ctx->pfql_conf.msg_max);
if ( !ctx->queue ) {
regfree ( ctx->regexp );
syslog ( LOGLEVEL, "pfqlib: sorry, cannot malloc for %d elements (queue)!", ctx->pfql_conf.msg_max );
return PFQL_MALLOC;
}
ctx->beptr = 0;
ctx->queue_thread = (struct be_msg_t*)malloc(sizeof(struct be_msg_t)*ctx->pfql_conf.msg_max);
if ( !ctx->queue_thread ) {
regfree ( ctx->regexp );
free ( ctx->queue );
syslog ( LOGLEVEL, "pfqlib: sorry, cannot malloc for %d elements (queue_thread)!", ctx->pfql_conf.msg_max );
return PFQL_MALLOC;
}
if ( !strcmp ( ctx->pfql_conf.backend_name, "autodetect" ) ) {
// Try to autodetect backend
strcpy ( ctx->pfql_conf.backend_name, "exim" );
res = be_try ( ctx, ctx->pfql_conf.backend_name );
if ( res!=PFQL_OK ) {
strcpy ( ctx->pfql_conf.backend_name, "postfix2" );
res = be_try ( ctx, ctx->pfql_conf.backend_name );
}
if ( res!=PFQL_OK ) {
strcpy ( ctx->pfql_conf.backend_name, "postfix1" );
res = be_try ( ctx, ctx->pfql_conf.backend_name );
}
if ( res!=PFQL_OK ) {
syslog ( LOGLEVEL, "pfqlib: cannot autodetect suitable backend, try -b and/or -B option" );
ctx->beptr = 0;
return PFQL_NOBE;
}
}
switch ( be_load ( ctx, ctx->pfql_conf.backend_name ) ) {
case PFQL_BENOTFOUND:
syslog ( LOGLEVEL, "pfqlib: backend not found!" );
ctx->beptr = 0;
return PFQL_BENOTFOUND;
case PFQL_BEMISSINGSYM:
syslog ( LOGLEVEL, "pfqlib: backend not valid (missing symbols)!" );
ctx->beptr = 0;
return PFQL_BEMISSINGSYM;
}
strcpy ( ctx->pfqbe_getconf()->host, ctx->pfql_conf.remote_host );
ctx->pfqbe_getconf()->port = ctx->pfql_conf.remote_port;
if ( ctx->pfqbe_init()!=PFBE_OK ) {
syslog ( LOGLEVEL, "pfqlib: %s backend failed to init!", ctx->pfql_conf.backend_name );
ctx->beptr = 0;
return PFQL_BEINIT;
}
strcpy ( ctx->pfqbe_getconf()->config_path, ctx->pfql_conf.backend_config );
strcpy ( ctx->pfqbe_getconf()->command_path,ctx->pfql_conf.backend_progs );
ctx->pfqbe_getconf()->msg_max = ctx->pfql_conf.msg_max;
ctx->pfqbe_getconf()->scan_limit = ctx->pfql_conf.scan_limit;
if ( ctx->pfqbe_setup( ctx->queue, ctx->queue_thread )!=PFBE_OK ) {
syslog ( LOGLEVEL, "pfqlib: %s backend failed to setup!", ctx->pfql_conf.backend_name );
ctx->beptr = 0;
return PFQL_BEINIT;
}
ctx->dig_lastqueue = -1;
queue_fill_start( ctx );
pfql_set_queue ( ctx, ctx->pfql_conf.initial_queue );
return PFQL_OK;
}
int pfql_context_destroy(struct pfql_context_t *ctx) {
pthread_mutex_destroy ( &ctx->qfill_mutex );
queue_fill_stop(ctx);
if (ctx->beptr) {
ctx->pfqbe_close(ctx);
dlclose (ctx->beptr);
}
if ( ctx->queue )
free ( ctx->queue );
if ( ctx->queue_thread )
free ( ctx->queue_thread );
if ( ctx->regexp )
regfree ( ctx->regexp );
return PFQL_OK;
}
int pfql_dump ( struct pfql_context_t *ctx, const char *fname ) {
return PFQL_OK;
}
syntax highlighted by Code2HTML, v. 0.9.1