You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
bforce/source/bforce/outb_sysqueue.c

303 lines
7.3 KiB
C

/*
* binkleyforce -- unix FTN mailer project
*
* Copyright (c) 1998-2000 Alexander Belkin, 2:5020/1398.11
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* $Id$
*/
#include "includes.h"
#include "confread.h"
#include "logger.h"
#include "util.h"
#include "outbound.h"
/*
* Will call this function than add new entry to the queue
*/
int (*sysqueue_add_callback)(s_sysentry *) = NULL;
/*
* Will call this function than remove entry from the queue
*/
int (*sysqueue_rem_callback)(s_sysentry *) = NULL;
/*
* Set this to disable mail/files size count
*/
bool sysqueue_dont_count_sizes = FALSE;
/*
* Return TRUE if 'chk' entry must be before 'max' in the queue
*/
static bool out_sysqueue_sort_comp(s_sysentry *max, s_sysentry *chk, int opts)
{
if( opts & QUEUE_SORT_ADDRESS )
{
if( opts & QUEUE_SORT_REVERSE )
return !ftn_addrcomp_logic(max->node.addr, ADDR_LT, chk->node.addr);
else
return !ftn_addrcomp_logic(max->node.addr, ADDR_GT, chk->node.addr);
}
else if( opts & QUEUE_SORT_SIZE )
{
size_t size_max = max->netmail_size + max->arcmail_size
+ max->request_size + max->files_size;
size_t size_chk = chk->netmail_size + chk->arcmail_size
+ chk->request_size + chk->files_size;
if( opts & QUEUE_SORT_REVERSE )
return size_max > size_chk;
else
return size_max < size_chk;
}
return FALSE;
}
void out_sysqueue_sort(s_sysqueue *q, int opts)
{
int i, j, max;
s_sysentry tmp;
if( q->sysnum < 2 ) return;
for( i = 0; i < q->sysnum - 1; i++ )
{
for( max = i, j = i + 1; j < q->sysnum; j++ )
if( out_sysqueue_sort_comp(&q->systab[max], &q->systab[j], opts) )
max = j;
if( max > i )
{
tmp = q->systab[max];
q->systab[max] = q->systab[i];
q->systab[i] = tmp;
}
}
}
void out_reset_sysqueue(s_sysqueue *q)
{
int i;
for( i = 0; i < q->sysnum; i++ )
{
q->systab[i].netmail_size = 0;
q->systab[i].request_size = 0;
q->systab[i].arcmail_size = 0;
q->systab[i].files_size = 0;
q->systab[i].flavors = 0;
q->systab[i].types = 0;
}
}
void out_remove_from_sysqueue(s_sysqueue *q, int pos)
{
ASSERT(q && pos >= 0 && pos < q->sysnum);
if( sysqueue_rem_callback )
(void)sysqueue_rem_callback(&q->systab[pos]);
if( q->sysnum > 1 )
{
memmove(&q->systab[pos], &q->systab[pos + 1],
sizeof(s_sysentry)*(q->sysnum - pos - 1));
q->systab = xrealloc(q->systab,
sizeof(s_sysentry)*(q->sysnum - 1));
--q->sysnum;
}
else
{
free(q->systab);
q->systab = NULL;
q->sysnum = 0;
}
}
/*
* Return pointer to entry in systems list for address addr
*/
static s_sysentry *out_getsysentry(s_sysqueue *q, s_faddr addr)
{
int i;
for( i = 0; i < q->sysnum; i++ )
if( ftn_addrcomp(q->systab[i].node.addr, addr) == 0 )
return &q->systab[i];
/* Add new entry for new address */
q->systab = (s_sysentry*)xrealloc(q->systab, sizeof(s_sysentry)*(q->sysnum+1));
memset(&q->systab[q->sysnum], '\0', sizeof(s_sysentry));
q->systab[q->sysnum].node.addr = addr;
if( sysqueue_add_callback )
(void)sysqueue_add_callback(&q->systab[i]);
return &q->systab[q->sysnum++];
}
/* ------------------------------------------------------------------------- */
/* Handle each file $fi found in outbound. Usually it called by outbound */
/* scanner.. Pointer to result information will be stored at dst */
/* ------------------------------------------------------------------------- */
int out_handle_sysqueue(s_outbound_callback_data *callback)
{
s_sysentry *sentry;
int type;
int flavor;
ASSERT(callback);
ASSERT(callback->path);
ASSERT(callback->dest);
DEB((D_OUTBOUND, "out_handle_sysqueue: process file \"%s\"",
callback->path));
if( callback->type != OUTB_TYPE_FBOX )
{
int i;
const char *p_ext = strrchr(callback->path, '.');
if( !p_ext )
return -1;
for( i = 0; outtab[i].ext && strcasecmp(p_ext, outtab[i].ext); i++ );
if( !outtab[i].ext )
return -1;
type = outtab[i].type;
flavor = outtab[i].flavor;
}
else
{
type = TYPE_FILEBOX;
if( callback->flavor != -1 )
flavor = callback->flavor;
else
flavor = FLAVOR_HOLD;
}
/* Try to found existing entry for this address */
if( (sentry = out_getsysentry((s_sysqueue*)callback->dest,
callback->addr)) == NULL )
return -1;
if( type == TYPE_NETMAIL || type == TYPE_REQUEST || type == TYPE_FILEBOX )
{
struct stat st;
sentry->flavors |= flavor;
sentry->types |= type;
if( !sysqueue_dont_count_sizes )
{
if( stat(callback->path, &st) == 0 )
{
/* Update mail age */
if( st.st_mtime > sentry->mailage )
sentry->mailage = st.st_mtime;
/* Update mail size */
if( type & TYPE_NETMAIL )
sentry->netmail_size += st.st_size;
else if( type & TYPE_ARCMAIL )
sentry->arcmail_size += st.st_size;
else if( type & TYPE_REQUEST )
sentry->request_size += st.st_size;
else
sentry->files_size += st.st_size;
}
else
logerr("can't stat file \"%s\"", callback->path);
}
}
else if( type == TYPE_FLOFILE )
{
sentry->flavors |= flavor;
if( !sysqueue_dont_count_sizes )
{
s_FLO *FLO;
if( (FLO = flo_open(callback->path, "r")) == NULL )
{
logerr("can't open flo \"%s\"", callback->path);
return -1;
}
while( flo_next(FLO) == 0 )
{
struct stat st;
if( stat(FLO->att_path, &st) == 0 )
{
/* Update mail age */
if( st.st_mtime > sentry->mailage )
sentry->mailage = st.st_mtime;
/* Update mail size */
if( out_filetype(FLO->att_path) & TYPE_ARCMAIL )
sentry->arcmail_size += st.st_size;
else
sentry->files_size += st.st_size;
}
}
flo_close(FLO);
}
}
else
log("skipping file of unknown type \"%s\"", callback->path);
return 0;
}
void deinit_sysqueue(s_sysqueue *q)
{
if( q->systab ) free(q->systab);
memset(q, '\0', sizeof(s_sysqueue));
}
#ifdef DEBUG
void log_sysqueue(const s_sysqueue *q)
{
char abuf[BF_MAXADDRSTR+1];
char tmp[256] = "";
int i;
DEB((D_OUTBOUND, "log_sysqueue: BEGIN"));
for( i = 0; i < q->sysnum; i++ )
{
DEB((D_OUTBOUND, "log_sysqueue: address %s", ftn_addrstr(abuf, q->systab[i].node.addr)));
tmp[0] = '\0';
if( q->systab[i].flavors & FLAVOR_IMMED ) strcat(tmp, "Immediate,");
if( q->systab[i].flavors & FLAVOR_CRASH ) strcat(tmp, "Crash,");
if( q->systab[i].flavors & FLAVOR_NORMAL ) strcat(tmp, "Normal,");
if( q->systab[i].flavors & FLAVOR_HOLD ) strcat(tmp, "Hold,");
if( tmp[0] ) tmp[strlen(tmp)-1] = '\0';
DEB((D_OUTBOUND, "log_sysqueue: \tflavors: \"%s\"", tmp));
tmp[0] = '\0';
if( q->systab[i].types & TYPE_NETMAIL ) strcat(tmp, "netmail,");
if( q->systab[i].types & TYPE_FLOFILE ) strcat(tmp, "flofile,");
if( q->systab[i].types & TYPE_ARCMAIL ) strcat(tmp, "arcmail,");
if( q->systab[i].types & TYPE_REQUEST ) strcat(tmp, "request,");
if( q->systab[i].types & TYPE_FILEECHO ) strcat(tmp, "fileecho,");
if( q->systab[i].types & TYPE_FILEBOX ) strcat(tmp, "filebox,");
if( q->systab[i].types & TYPE_FROMFLO ) strcat(tmp, "fromflo,");
if( tmp[0] ) tmp[strlen(tmp)-1] = '\0';
DEB((D_OUTBOUND, "log_sysqueue: \ttypes: \"%s\"", tmp));
}
DEB((D_OUTBOUND, "log_sysqueue: END"));
}
#endif