static char rcsid[] = "@(#)$Id: sb_file.c,v 1.12 2006/04/09 07:37:07 hurtta Exp $";
/******************************************************************************
* The Elm (ME+) Mail System - $Revision: 1.12 $ $State: Exp $
*
* Author: Kari Hurtta <hurtta+elm@posti.FMI.FI> (was hurtta+elm@ozone.FMI.FI)
*****************************************************************************/
#include "headers.h"
#include "s_me.h"
#include "sb_imp.h"
#include <errno.h>
#ifndef ANSI_C
extern int errno;
#endif
DEBUG_VAR(Debug,__FILE__,"charset");
static unsigned char *s2us P_((char *str));
static unsigned char *s2us(str)
char *str;
{
return (unsigned char *)str;
}
static char *us2s P_((unsigned char *str));
static char *us2s(str)
unsigned char *str;
{
return (char *)str;
}
static int sb_init_file P_((struct stringbuffer *buffer));
static int sb_init_file(buffer)
struct stringbuffer *buffer;
{
static int count = 0;
int i;
char *tmp;
tmp = give_dt_estr_as_str(&temp_dir_e,"tmpdir");
if (!tmp)
tmp = "/tmp/";
buffer->p->a.file.offset_count = 0;
buffer->p->a.file.offsets = NULL;
buffer->p->a.file.filename = NULL;
buffer->p->a.file.fh = NULL;
for (i = 0; i < 10; i++) {
count++;
buffer->p->a.file.filename = elm_message(FRM("%selmsb-%d-%d"),
tmp, getpid (),
count);
buffer->p->a.file.fh = safeopen_rdwr(buffer->p->a.file.filename);
if (!buffer->p->a.file.fh) {
int err = errno;
DPRINT(Debug,25,(&Debug,
"stringbuffer: safeopen_rdwr: %s: %s (errno %d)\n",
buffer->p->a.file.filename,
error_description(err),err));
free(buffer->p->a.file.filename);
buffer->p->a.file.filename = NULL;
} else
break;
}
if (!buffer->p->a.file.fh)
return 0;
unlink (buffer->p->a.file.filename);
DPRINT(Debug,1,(&Debug,
"stringbuffer: using temp file (%s)\n",
buffer->p->a.file.filename));
return 1;
}
static void sb_free_file P_((struct stringbuffer *buffer));
static void sb_free_file(buffer)
struct stringbuffer *buffer;
{
if (buffer->p->a.file.fh) {
fclose(buffer->p->a.file.fh);
buffer->p->a.file.fh = NULL;
}
if (buffer->p->a.file.filename) {
free(buffer->p->a.file.filename);
buffer->p->a.file.filename = NULL;
}
if (buffer->p->a.file.offsets) {
free(buffer->p->a.file.offsets);
buffer->p->a.file.offsets = NULL;
}
buffer->p->a.file.offset_count = 0;
}
static void sb_add_line_to_file P_((struct stringbuffer *buffer,
const struct string *string));
static void sb_add_line_to_file(buffer,string)
struct stringbuffer *buffer;
CONST struct string *string;
{
int ptr = buffer->p->a.file.offset_count;
if (fseek(buffer->p->a.file.fh,0,SEEK_END) != 0) {
int err = errno;
DPRINT(Debug,1,(&Debug,
"stringbuffer: fseek (flush) failure: %s: %s (errno %d)\n",
buffer->p->a.file.filename,
error_description(err),err));
return;
}
buffer->p->a.file.offsets =
safe_realloc(buffer->p->a.file.offsets,
(buffer->p->a.file.offset_count +1) *
sizeof (long));
buffer->p->a.file.offsets[ptr] = ftell(buffer->p->a.file.fh);
buffer->p->a.file.offset_count++;
if (string->string_type-> MIME_name) {
char * s = us2s(stream_from_string(string,0,NULL));
int l1 = strlen(s);
int l2 = strlen(string->string_type->MIME_name);
fprintf(buffer->p->a.file.fh,"%d:%d:",l2,l1);
/* Include ending \0 to string */
fwrite(string->string_type-> MIME_name,1,l2+1,
buffer->p->a.file.fh);
/* Include ending \0 to string */
fwrite(s,1,l1+1,buffer->p->a.file.fh);
free(s);
} else {
/* No charset name available ... */
struct string *str = convert_string(system_charset,string,0);
char * s = us2s(stream_from_string(str,0,NULL));
int l1 = strlen(s);
fprintf(buffer->p->a.file.fh,":%d:",l1);
fputc('\0',buffer->p->a.file.fh); /* Terminaing \0 of null charset */
/* Include ending \0 to string */
fwrite(s,1,l1+1,buffer->p->a.file.fh);
free(s);
free_string(&str);
}
}
static int sb_linecount_file P_((const struct stringbuffer *ptr));
static int sb_linecount_file(ptr)
CONST struct stringbuffer *ptr;
{
return ptr->p->a.file.offset_count;
}
static struct string *sb_get_line_from_file P_((const struct
stringbuffer *buffer,
int ptr));
static struct string *sb_get_line_from_file(buffer,ptr)
CONST struct stringbuffer *buffer;
int ptr;
{
int setlen = 0;
int strlen = 0;
char * bigs = NULL;
charset_t sn = system_charset;
struct string * res = NULL;
int c;
if (ptr < 0 || ptr >= buffer->p->a.file.offset_count)
panic("STRINGBUFFER PANIC",__FILE__,__LINE__,"sb_get_line_from_file",
"Bad index",0);
if (0 != fseek(buffer->p->a.file.fh,buffer->p->a.file.offsets[ptr],
SEEK_SET)) {
int err = errno;
DPRINT(Debug,1,(&Debug,
"stringbuffer: fseek (flush) failure: %s: %s (errno %d)\n",
buffer->p->a.file.filename,
error_description(err),err));
panic("STRINGBUFFER PANIC",__FILE__,__LINE__,"sb_get_line_from_file",
"Failed to flush or seek file",0);
}
c = fgetc(buffer->p->a.file.fh);
while (c >= '0' && c <= '9') {
setlen = setlen * 10 + c - '0';
c = fgetc(buffer->p->a.file.fh);
}
if (':' != c) {
panic("STRINGBUFFER PANIC",__FILE__,__LINE__,"sb_get_line_from_file",
"Bad data read from file",0);
}
c = fgetc(buffer->p->a.file.fh);
while (c >= '0' && c <= '9') {
strlen = strlen * 10 + c - '0';
c = fgetc(buffer->p->a.file.fh);
}
if (':' != c) {
panic("STRINGBUFFER PANIC",__FILE__,__LINE__,"sb_get_line_from_file",
"Bad data read from file",0);
}
bigs = safe_malloc(setlen+1+strlen+1);
if (fread(bigs,1,setlen+1+strlen+1,buffer->p->a.file.fh) !=
setlen+1+strlen+1) {
panic("STRINGBUFFER PANIC",__FILE__,__LINE__,"sb_get_line_from_file",
"Read error or short data read from file",0);
}
if (bigs[setlen] != '\0' ||
bigs[setlen+1+strlen] != '\0') {
panic("STRINGBUFFER PANIC",__FILE__,__LINE__,"sb_get_line_from_file",
"Bad data read from file",0);
}
if (setlen != 0) {
sn = MIME_name_to_charset(bigs,0);
if (!sn) {
DPRINT(Debug,1,(&Debug,
"stringbuffer: Charset '%s' is not knows (impossible?)\n",
bigs));
panic("STRINGBUFFER PANIC",__FILE__,__LINE__,
"sb_get_line_from_file",
"Bad charset read from file",0);
}
}
res = new_string2(sn,s2us(&(bigs[setlen+1])));
free(bigs);
return res;
}
struct sb_type sb_in_file = {
sb_init_file,
sb_free_file,
sb_add_line_to_file,
sb_linecount_file,
sb_get_line_from_file
};
/*
* Local Variables:
* mode:c
* c-basic-offset:4
* buffer-file-coding-system: iso-8859-1
* End:
*/
syntax highlighted by Code2HTML, v. 0.9.1