static char rcsid[] = "@(#)$Id: fstate.c,v 1.3 2006/05/30 16:33:21 hurtta Exp $";
/******************************************************************************
* The Elm (ME+) Mail System - $Revision: 1.3 $ $State: Exp $
*
* Author: Kari Hurtta <hurtta+elm@posti.FMI.FI>
* or Kari Hurtta <elm@elmme-mailer.org>
******************************************************************************
* Some minor part of code based on code utils/readmsg.c
* That code was following copyright:
*
* The Elm Mail System
*
* Copyright (c) 1988-1992 USENET Community Trust
* Copyright (c) 1986,1987 Dave Taylor
*****************************************************************************/
#include "def_readmsg.h"
DEBUG_VAR(Debug,__FILE__,"readmsg");
#include <errno.h>
#ifndef ANSI_C
extern int errno;
#endif
static struct folder_state fstate; /* information from external state file */
static int have_fstate_called = 0;
int have_fstate()
{
zero_ldstate(&fstate);
have_fstate_called = 1;
if (load_folder_state_file(&fstate) != 0)
return -1;
return fstate.storage != NULL;
}
#if ANSI_C
#define S_(x) static x;
#else
#define S_(x)
#endif
struct fstate_data {
FILE ** fp_vec;
int fp_vec_len;
struct msgdata {
int fpnum;
long offset;
long content_len;
struct header_rec *entry;
} * messages;
int messages_len;
};
S_(init_folder_handler_f init_fstate_handler)
static void init_fstate_handler P_((struct folder_handler *H));
static void init_fstate_handler(H)
struct folder_handler *H;
{
H->d.fstate = safe_malloc(sizeof (* H->d.fstate));
/* bzero is defined hdrs/defs.h */
bzero((void *)H->d.fstate,sizeof (* H->d.fstate));
H->d.fstate->fp_vec = NULL;
H->d.fstate->fp_vec_len = 0;
H->d.fstate->messages = NULL;
H->d.fstate->messages_len = 0;
}
S_(free_folder_handler_f free_fstate_handler)
static void free_fstate_handler P_((struct folder_handler *H));
static void free_fstate_handler(H)
struct folder_handler *H;
{
if (H->d.fstate->fp_vec) {
int i;
for ( i = 0; i < H->d.fstate->fp_vec_len; i++) {
if (H->d.fstate->fp_vec[i]) {
fclose(H->d.fstate->fp_vec[i]);
H->d.fstate->fp_vec[i] = NULL;
}
}
free(H->d.fstate->fp_vec);
H->d.fstate->fp_vec = NULL;
}
H->d.fstate->fp_vec_len = 0;
if (H->d.fstate->messages) {
int i;
for (i = 0; i < H->d.fstate->messages_len; i++) {
if (H->d.fstate->messages[i].entry)
free_header_helper(& (H->d.fstate->messages[i].entry));
}
free(H->d.fstate->messages);
H->d.fstate->messages = NULL;
}
H->d.fstate->messages_len = 0;
free(H->d.fstate);
H->d.fstate = NULL;
}
static void parser_helper1 P_((struct msgdata *X, FILE *F));
static void parser_helper1(X, F)
struct msgdata *X;
FILE *F;
{
long content_start;
struct header_rec * entry = X->entry;
header_list_ptr hdrs = file_read_headers(F,0);
read_folder_headers_helper(entry,hdrs);
mime_parse_helper(entry,hdrs);
content_start = ftell(F);
start_body_helper(entry,content_start,hdrs);
delete_headers(&hdrs);
}
long separator_helper(entry,errret,print_separator,env_buffer,F)
struct header_rec * entry;
enum message_error *errret;
int print_separator;
char **env_buffer;
FILE * F;
{
char buf[LONG_STRING];
int buf_len;
int first_line = 0;
long ZZ;
while (0 < (buf_len = mail_gets(buf,sizeof(buf),F))) {
DPRINT(Debug,15,(&Debug,
"separator_helper: len=%d, got: %s\n",
buf_len,buf));
#ifdef MMDF
if (0 == strcmp(buf,MSG_SEPARATOR)) {
first_line = 0;
if (print_separator)
fputs(buf,stdout);
continue;
}
#endif
if (0 == strncmp(buf,"From ",5)) {
first_line = 0;
if (! real_from(buf, entry)) {
*errret = error_start;
return -1;
}
if (print_separator)
fputs(buf,stdout);
if (env_buffer)
*env_buffer = strmcat(*env_buffer,buf);
continue;
}
if (!first_line && first_word_nc(buf, ">From")) {
if (print_separator)
fputs(buf,stdout);
if (env_buffer)
*env_buffer = strmcat(*env_buffer,buf);
continue;
}
break;
}
if (first_line) {
*errret = error_start;
return -1;
}
ZZ = ftell(F) - buf_len;
return ZZ;
}
S_(give_message_from_folder_f give_message_from_fstate)
static FILE * give_message_from_fstate P_((struct folder_handler *folder,
int idx,
long *content_length,
enum message_error *errret,
int print_separator,
char **env_buffer,
struct header_rec **entryret));
static FILE * give_message_from_fstate(folder,idx,content_length,
errret,print_separator,env_buffer,
entryret)
struct folder_handler *folder;
int idx;
long *content_length;
enum message_error *errret;
int print_separator;
char **env_buffer;
struct header_rec **entryret;
{
FILE *ret;
struct fstate_data * fst = folder->d.fstate;
long offset;
int need_parse = 0;
long ZZ;
if (idx < 0 || idx >= folder->num_messages ||
idx >= fst->messages_len)
panic("READMSG PANIC",__FILE__,__LINE__,"give_message_from_fstate",
"Bad index",0);
*errret = error_none;
offset = fst->messages[idx].offset;
if (-1 == offset)
return NULL;
if (-1 == fst->messages[idx].fpnum)
return NULL;
if (fst->messages[idx].fpnum < 0 ||
fst->messages[idx].fpnum >= fst->fp_vec_len)
panic("READMSG PANIC",__FILE__,__LINE__,"give_message_from_fstate",
"Bad fpnum",0);
ret = fst->fp_vec[fst->messages[idx].fpnum];
if (!ret)
return NULL;
if (fseek(ret, offset, SEEK_SET) == -1) {
int err = errno;
DPRINT(Debug,1,(&Debug,
"give_message_from_fstate: Couldn't seek folder to offset %ld Errno %s (%s)\n",
offset,
error_description(err)));
*errret = error_seek;
return NULL;
}
*content_length = fst->messages[idx].content_len;
if (! fst->messages[idx].entry) {
fst->messages[idx].entry = malloc_header_helper();
need_parse = 1;
fst->messages[idx].entry->offset = offset;
fst->messages[idx].entry->header_charset = display_charset;
fst->messages[idx].entry->content_length =
fst->messages[idx].content_len;
DPRINT(Debug,10,(&Debug,
"-- content_len=%ld\n",
fst->messages[idx].content_len));
}
ZZ = separator_helper(need_parse ? fst->messages[idx].entry : NULL,
errret,
print_separator,env_buffer,ret);
if (-1 == ZZ)
return NULL;
DPRINT(Debug,9,(&Debug,
"give_message_from_fstate: beginning of headers=%ld\n",ZZ));
if (fseek(ret, ZZ, SEEK_SET) == -1) {
int err = errno;
DPRINT(Debug,1,(&Debug,
"give_message_from_fstate: Couldn't seek folder to offset %ld Errno %s (%s)\n",
ZZ,
error_description(err)));
*errret = error_seek;
return NULL;
}
if (need_parse) {
fst->messages[idx].entry->mime_rec.begin_offset = ZZ;
parser_helper1(& (fst->messages[idx]),ret);
if (fseek(ret, ZZ, SEEK_SET) == -1) {
int err = errno;
DPRINT(Debug,1,(&Debug,
"give_message_from_fstate: Couldn't seek folder to offset %ld Errno %s (%s)\n",
ZZ,
error_description(err)));
*errret = error_seek;
return NULL;
}
}
if (entryret)
*entryret = fst->messages[idx].entry;
return ret;
}
S_(parse_folder_handler_f parse_folder_fstate)
static int parse_folder_fstate P_((struct folder_handler *H));
static int parse_folder_fstate(H)
struct folder_handler *H;
{
return 1;
}
static struct folder_routines FSTATE = {
FOLDER_ROUTINES_magic,
init_fstate_handler,
free_fstate_handler,
give_message_from_fstate,
parse_folder_fstate
};
struct folder_handler * open_fstate()
{
struct folder_handler *ret = NULL;
FILE **fp_vec = NULL;
int i;
if (! have_fstate_called) {
if (have_fstate() < 1)
return NULL;
}
if (fstate.storage_len < 1)
return NULL;
fp_vec = safe_malloc ( fstate.storage_len * sizeof (fp_vec[0]));
/* We ignores unopenable storages now */
for (i = 0; i < fstate.storage_len; i++) {
fp_vec[i] = NULL;
if (fstate.storage[i].folder_name)
fp_vec[i] = fopen(fstate.storage[i].folder_name,"r");
}
ret = malloc_folder_handler(&FSTATE);
ret->d.fstate->fp_vec = fp_vec;
ret->d.fstate->fp_vec_len = fstate.storage_len;
ret->num_messages = fstate.view_len;
if (fstate.view_len > 0) {
ret->d.fstate->messages =
safe_malloc(fstate.view_len *
sizeof ( ret->d.fstate->messages[0]));
ret->d.fstate->messages_len = fstate.view_len;
for (i = 0; i < fstate.view_len; i++) {
int mbx = fstate.view[i].mailbox_number;
int idx = fstate.view[i].index;
ret->d.fstate->messages[i].fpnum = -1; /* Invalid */
ret->d.fstate->messages[i].offset = 0L;
ret->d.fstate->messages[i].content_len = 0L;
ret->d.fstate->messages[i].entry = NULL;
if (mbx >= 0 && mbx < fstate.storage_len &&
idx >= 0 && idx < fstate.storage[mbx].num_mssgs &&
fstate.storage[mbx].mssgs[idx].idx >= 0) {
ret->d.fstate->messages[i].fpnum = mbx;
ret->d.fstate->messages[i].offset =
fstate.storage[mbx].mssgs[idx].idx;
ret->d.fstate->messages[i].content_len =
fstate.storage[mbx].mssgs[idx].cl;
}
}
}
return ret;
}
int process_fstate_print(hdr_display_level, do_page_breaks, do_raw_output)
enum hdr_disp_level hdr_display_level;
int do_page_breaks;
int do_raw_output;
{
struct folder_handler * folder = open_fstate();
int i;
int ret = 1;
if (! folder)
return 0;
/* num_sel numbers are starting from 1 ... */
for (i = 0 ; i < fstate.num_sel ; i++) {
if (!print_number_message(folder,fstate.sel_list[i],
hdr_display_level,
do_page_breaks,
do_raw_output))
ret = 0;
}
free_folder_handler(&folder);
return ret;
}
/*
* Local Variables:
* mode:c
* c-basic-offset:4
* buffer-file-coding-system: iso-8859-1
* End:
*/
syntax highlighted by Code2HTML, v. 0.9.1