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 * or Kari Hurtta ****************************************************************************** * 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 #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: */