static char rcsid[] = "@(#)$Id: state.c,v 1.20 2006/06/04 07:26:49 hurtta Exp $"; /****************************************************************************** * The Elm (ME+) Mail System - $Revision: 1.20 $ $State: Exp $ * * Modified by: Kari Hurtta * (was hurtta+elm@ozone.FMI.FI) * * Initially written by: Michael Elkins , 1995 *****************************************************************************/ #include "headers.h" #include "state_imp.h" DEBUG_VAR(Debug,__FILE__,"misc"); DEBUG_VAR(DebugIO,__FILE__,"stateio"); static void state_panic P_((char *,int,char *, char *)); /* Prototype */ static void state_panic(f,ln,pr,ms) char * f; int ln; char *pr; char *ms; { panic("STATE PANIC",f,ln,pr,ms,0); } static CONST unsigned char *cs2us P_((const char *str)); static CONST unsigned char *cs2us(str) CONST char *str; { return (CONST unsigned char *)str; } static char *us2s P_((unsigned char *str)); static char *us2s(str) unsigned char *str; { return (char *)str; } static void init_si_file P_((in_state_t *)); /* Prototype */ static void init_si_file(s) in_state_t *s; { s->magic = STATE_in_file; s->u.file.fpin = NULL; } void in_state_clear (s,m) in_state_t *s; int m; { s->magic = 0; /* Not initilized yet */ switch(m) { case STATE_in_file: init_si_file(s); break; default: state_panic(__FILE__,__LINE__,"in_state_clear","Bad magic number"); } } static void dest_si_file P_((in_state_t *)); /* Prototype */ static void dest_si_file(s) in_state_t *s; { if (s->magic != STATE_in_file) state_panic(__FILE__,__LINE__,"dest_si_file","Bad magic number"); s->u.file.fpin = NULL; } void in_state_destroy (s) in_state_t *s; { DPRINT(DebugIO,30,(&DebugIO, "in_state_destroy(s=%p) -- magic=%d\n", s,s->magic)); switch(s->magic) { case STATE_in_file: dest_si_file(s); break; default: state_panic(__FILE__,__LINE__,"in_state_destroy","Bad magic number"); } s->magic = 0; /* State destroyed */ } void set_in_state_file (F, s) FILE *F; in_state_t *s; { if (s->magic != STATE_in_file) state_panic(__FILE__,__LINE__,"set_in_state_file","Bad magic number"); if (s->u.file.fpin) state_panic(__FILE__,__LINE__,"set_in_state_file","Already called"); s->u.file.fpin = F; } int in_state_seekable (s) in_state_t *s; { switch(s->magic) { case STATE_in_file: return 1; default: state_panic(__FILE__,__LINE__,"in_state_seekable","Bad magic number"); } return 0; } int in_state_fseek (s,pos) in_state_t *s; long pos; { if (s->magic != STATE_in_file) state_panic(__FILE__,__LINE__,"in_state_fseek","Bad magic number"); if (s->u.file.fpin == NULL) state_panic(__FILE__,__LINE__,"in_state_fseek","NULL file pointer"); return fseek(s->u.file.fpin,pos,SEEK_SET); } long in_state_ftell (s) in_state_t *s; { if (s->magic != STATE_in_file) state_panic(__FILE__,__LINE__,"in_state_ftell","Bad magic number"); if (s->u.file.fpin == NULL) state_panic(__FILE__,__LINE__,"in_state_ftell","NULL file pointer"); return ftell(s->u.file.fpin); } static int getc_si_file P_((in_state_t *)); /* Prototype */ static int getc_si_file(s) in_state_t *s; { if (s->magic != STATE_in_file) state_panic(__FILE__,__LINE__,"getc_si_file","Bad magic number"); if (s->u.file.fpin == NULL) state_panic(__FILE__,__LINE__,"getc_si_file","NULL filepointer"); return fgetc (s->u.file.fpin); } int state_getc (s) in_state_t *s; { int r = EOF; DPRINT(DebugIO,30,(&DebugIO, "state_getc(s=%p) -- magic=%d\n", s,s->magic)); switch(s->magic) { case STATE_in_file: r = getc_si_file(s); break; default: state_panic(__FILE__,__LINE__,"state_getc","Bad magic number"); } DPRINT(DebugIO,30,(&DebugIO, "state_getc=%d\n", r)); return r; } static int ungetc_si_file P_((int,in_state_t *)); /* Prototype */ static int ungetc_si_file (c,s) int c; in_state_t *s; { if (s->magic != STATE_in_file) state_panic(__FILE__,__LINE__,"ungetc_si_file","Bad magic number"); if (s->u.file.fpin == NULL) state_panic(__FILE__,__LINE__,"umgetc_si_file","NULL filepointer"); return ungetc(c,s->u.file.fpin); } int state_ungetc (c,s) int c; in_state_t *s; { int r = EOF; DPRINT(DebugIO,30,(&DebugIO, "state_ungetc(s=%p) -- magic=%d\n", s,s->magic)); switch(s->magic) { case STATE_in_file: r = ungetc_si_file(c,s); break; default: state_panic(__FILE__,__LINE__,"state_ungetc","Bad magic number"); } DPRINT(DebugIO,30,(&DebugIO, "state_ungetc=%d\n", r)); return r; } static char *gets_si_file P_((char *, int, in_state_t *)); static char *gets_si_file (dest, length, s) char *dest; int length; in_state_t *s; { if (s->magic != STATE_in_file) state_panic(__FILE__,__LINE__,"gets_si_file","Bad magic number"); if (s->u.file.fpin == NULL) state_panic(__FILE__,__LINE__,"gets_si_file","NULL filepointer"); return (fgets (dest, length, s->u.file.fpin)); } static int getl_si_file P_((char *, int, in_state_t *)); static int getl_si_file (dest, length, s) char *dest; int length; in_state_t *s; { if (s->magic != STATE_in_file) state_panic(__FILE__,__LINE__,"getl_si_file","Bad magic number"); if (s->u.file.fpin == NULL) state_panic(__FILE__,__LINE__,"getl_si_file","NULL filepointer"); return (mail_gets (dest, length, s->u.file.fpin)); } char *state_gets (dest, length, s) char *dest; int length; in_state_t *s; { char * r = NULL; DPRINT(DebugIO,30,(&DebugIO, "state_gets(s=%p) -- magic=%d\n", s,s->magic)); switch(s->magic) { case STATE_in_file: r = gets_si_file(dest,length,s); break; default: state_panic(__FILE__,__LINE__,"state_gets","Bad magic number"); } DPRINT(DebugIO,30,(&DebugIO, "state_gets=%p\n", r)); return r; } int state_getl (dest, length, s) char *dest; int length; in_state_t *s; { int r = 0; DPRINT(DebugIO,30,(&DebugIO, "state_getl(s=%p) -- magic=%d\n", s,s->magic)); switch(s->magic) { case STATE_in_file: r = getl_si_file(dest,length,s); break; default: state_panic(__FILE__,__LINE__,"state_getl","Bad magic number"); } DPRINT(DebugIO,30,(&DebugIO, "state_getl=%d\n", r)); return r; } static void init_so_file P_((out_state_t *)); /* Prototype */ static void init_so_file(s) out_state_t *s; { s->magic = STATE_out_file; s->u.file.fpout = NULL; } static void init_so_buffer P_((out_state_t *)); /* Prototype */ static void init_so_buffer(s) out_state_t *s; { s->magic = STATE_out_buffer; s->u.buffer = NULL; } static struct out_state_type ** out_state_registered = NULL; static int out_state_registered_count = 0; /* This only registers pointer, struct is not copied */ void register_state_out_type(T) struct out_state_type *T; { if (STATE_out_magic != T->magic) state_panic(__FILE__,__LINE__,"register_state_out_type", "Bad magic number"); out_state_registered = safe_realloc(out_state_registered, (out_state_registered_count +1) * sizeof (out_state_registered[0])); out_state_registered[out_state_registered_count++] = T; } static void init_so_external P_((out_state_t *s, int m)); /* Prototype */ static void init_so_external(s,m) out_state_t *s; int m; { int i; for (i = 0; i < out_state_registered_count; i++) { if (out_state_registered[i]->register_code == m) { s->external_type = out_state_registered[i]; s->magic = STATE_out_extern; break; } } if (i >= out_state_registered_count) state_panic(__FILE__,__LINE__,"init_so_external","Bad magic number"); if (STATE_out_magic != s->external_type->magic) state_panic(__FILE__,__LINE__,"init_so_external","Bad func magic number"); s->external_type->ex_init_so_it(s); } void out_state_clear (s,m) out_state_t *s; int m; { static charset_t default_vector[2]; default_vector[0] = display_charset; default_vector[1] = NULL; bzero((void *)s,sizeof (*s)); s->magic = 0; /* Not initilized yet */ s->displaying = 0; s->EOLN_is_CRLF = 0; /* EOLN is \n */ s->prefix = NULL; s->filter = NULL; s->display_charset = default_vector; s->filter_line = NULL; s->external_type = NULL; s->u.dummy = NULL; switch(m) { case STATE_out_file: init_so_file(s); break; case STATE_out_buffer: init_so_buffer(s); break; default: init_so_external(s,m); } } static void dest_so_file P_((out_state_t *)); /* Prototype */ static void dest_so_file(s) out_state_t *s; { if (s->magic != STATE_out_file) state_panic(__FILE__,__LINE__,"dest_so_file","Bad magic number"); s->u.file.fpout = NULL; } static void dest_so_buffer P_((out_state_t *)); /* Prototype */ static void dest_so_buffer(s) out_state_t *s; { if (s->magic != STATE_out_buffer) state_panic(__FILE__,__LINE__,"dest_so_buffer","Bad magic number"); s->u.buffer = NULL; } int out_state_seekable(s) out_state_t *s; { int r = 0; DPRINT(DebugIO,30,(&DebugIO, "out_state_seekable(s=%p) -- magic=%d\n", s,s->magic)); switch(s->magic) { case STATE_out_file: r = 1; break; case STATE_out_buffer: r = 0; break; case STATE_out_extern: if (STATE_out_magic != s->external_type->magic) state_panic(__FILE__,__LINE__,"out_state_seekable","Bad func magic number"); r = s->external_type->ex_seekable_so_it(s); break; default: state_panic(__FILE__,__LINE__, "out_state_seekable","Bad magic number"); } DPRINT(DebugIO,30,(&DebugIO, "out_state_seekable=%d\n", r)); return r; } static void flush_filter P_((out_state_t *s, int munge_eoln)); /* Returns NULL if no available ... */ FILE *out_state_FILE(s) out_state_t *s; { FILE * r = NULL; DPRINT(DebugIO,30,(&DebugIO, "out_state_FILE(s=%p) -- magic=%d\n", s,s->magic)); if (s->filter_line) flush_filter(s,0); switch(s->magic) { case STATE_out_file: r = s->u.file.fpout; break; case STATE_out_buffer: r = NULL; break; case STATE_out_extern: if (STATE_out_magic != s->external_type->magic) state_panic(__FILE__,__LINE__,"out_state_FILE","Bad func magic number"); r = s->external_type->ex_FILE_so_it(s); break; default: state_panic(__FILE__,__LINE__, "out_state_FILE","Bad magic number"); } SIGDPRINT(DebugIO,30,(&DebugIO, "out_state_FILE=%p\n", r)); return r; } int out_state_fseek(s,pos) out_state_t *s; long pos; { int r = -1; DPRINT(DebugIO,30,(&DebugIO, "out_state_fseek(s=%p,pos=%ld) -- magic=%d\n", s,s->magic,pos)); if (s->filter_line) flush_filter(s,0); switch (s->magic) { case STATE_out_file: if (!s->u.file.fpout) state_panic(__FILE__,__LINE__,"out_state_fseek", "NULL file pointer"); r = fseek(s->u.file.fpout,pos,SEEK_SET); break; case STATE_out_extern: if (STATE_out_magic != s->external_type->magic) state_panic(__FILE__,__LINE__,"out_state_seek","Bad func magic number"); r = s->external_type->ex_seek_so_it(s,pos); break; default: state_panic(__FILE__,__LINE__,"out_state_fseek","Bad magic number"); } DPRINT(DebugIO,30,(&DebugIO, "out_state_fseek=%d\n", r)); return r; } long out_state_ftell (s) out_state_t *s; { long r = -1; DPRINT(DebugIO,30,(&DebugIO, "out_state_ftell(s=%p) -- magic=%d\n", s,s->magic)); if (s->filter_line) flush_filter(s,0); switch(s->magic) { case STATE_out_file: if (!s->u.file.fpout) state_panic(__FILE__,__LINE__,"out_state_ftell", "NULL file pointer"); r = ftell(s->u.file.fpout); break; case STATE_out_extern: if (STATE_out_magic != s->external_type->magic) state_panic(__FILE__,__LINE__,"out_state_ftell","Bad func magic number"); r = s->external_type->ex_ftell_so_it(s); break; default: state_panic(__FILE__,__LINE__,"out_state_ftell","Bad magic number"); } DPRINT(DebugIO,30,(&DebugIO, "out_state_ftell=%ld\n", r)); return r; } void out_state_destroy (s) out_state_t *s; { DPRINT(DebugIO,30,(&DebugIO, "out_state_destroy(s=%p) -- magic=%d\n", s,s->magic)); if (s->filter_line) flush_filter(s,0); switch(s->magic) { case STATE_out_file: dest_so_file(s); break; case STATE_out_buffer: dest_so_buffer(s); break; case STATE_out_extern: if (STATE_out_magic != s->external_type->magic) state_panic(__FILE__,__LINE__,"out_state_destroy","Bad func magic number"); s->external_type->ex_dest_so_it(s); break; default: state_panic(__FILE__,__LINE__,"out_state_destroy","Bad magic number"); } s->displaying = 0; s->prefix = NULL; s->filter = NULL; s->display_charset = NULL; if (s->filter_line) free_string(&(s->filter_line)); s->external_type = NULL; s->magic = 0; /* No longer initialized */ } /* STATE_out_buffer */ extern void set_out_state_sbuffer(buffer,s) struct stringbuffer *buffer; out_state_t *s; { if (s->magic != STATE_out_buffer) state_panic(__FILE__,__LINE__,"set_out_state_sbuffer", "Bad magic number"); if (s->u.buffer != NULL) state_panic(__FILE__,__LINE__,"set_out_state_sbuffer", "Already called"); s->u.buffer = buffer; } void set_out_state_file (file,s) FILE * file; out_state_t *s; { if (s->magic != STATE_out_file) state_panic(__FILE__,__LINE__,"set_out_state_file","Bad magic number"); if (s->u.file.fpout != NULL) state_panic(__FILE__,__LINE__,"set_out_state_file","Already called"); s->u.file.fpout = file; } static int putc_so_file P_((out_state_t *, int)); /* Prototype */ static int putc_so_file(s,ch) out_state_t *s; int ch; { if (s->magic != STATE_out_file) state_panic(__FILE__,__LINE__,"putc_so_file","Bad magic number"); if (s->u.file.fpout == NULL) state_panic(__FILE__,__LINE__,"putc_so_file","NULL file pointer"); return (fputc (ch, s->u.file.fpout)); } static void convert_filter P_((out_state_t *s)); static void convert_filter(s) out_state_t *s; { if (s->filter && s->filter != s->filter_line->string_type) { struct string * X = convert_string(s->filter,s->filter_line,0); DPRINT(Debug,10,(&Debug, "Changing charset of current line from charset %s to charset %s\n", s->filter_line->string_type->MIME_name ? s->filter_line->string_type->MIME_name : "", s->filter->MIME_name ? s->filter->MIME_name : "")); free_string(& (s->filter_line)); s->filter_line = X; } } int state_putc (ch, s) int ch; /* unsigned char assumed */ out_state_t *s; { int use_filter = 0; DPRINT(DebugIO,30,(&DebugIO, "state_putc(ch=%d,s=%p) -- magic=%d\n", ch,s,s->magic)); if (s->magic == STATE_out_extern) { if (STATE_out_magic != s->external_type->magic) state_panic(__FILE__,__LINE__,"flush_filter", "Bad func magic number"); use_filter = s->external_type->ex_policy_so_it(s, state_policy_putc_use_filter); } if (s->filter_line || s->filter || s->magic == STATE_out_buffer || use_filter) { int r; if (!s->filter_line) { if (!s->filter) { /* STATE_out_dir also requires s->display_charset[0] -- value RAW_BUFFER indicates raw copying ... */ s->filter_line = new_string(s->display_charset[0]); } else s->filter_line = new_string(s->filter); } else convert_filter(s); r = add_streambyte_to_string(s->filter_line,ch); if (!r) { uint16 BAD = UNICODE_BAD_CHAR; DPRINT(Debug,10,(&Debug, "state_putc: failed to add byte %d to charset %s\n", ch, s->filter_line->string_type->MIME_name ? s->filter_line->string_type->MIME_name : "")); /* Indicate bad character */ add_unicode_to_string(s->filter_line,1,&BAD); } if ('\n' == ch) { flush_filter(s,0); } DPRINT(DebugIO,30,(&DebugIO, "state_putc=%d (filter)\n", r ? 1 : EOF)); return r ? 1 : EOF; } else { int r = EOF; switch(s->magic) { case STATE_out_file: r = putc_so_file(s,ch); break; case STATE_out_extern: if (STATE_out_magic != s->external_type->magic) state_panic(__FILE__,__LINE__,"state_putc", "Bad func magic number"); r = s->external_type->ex_putc_so_it(s,ch); break; default: state_panic(__FILE__,__LINE__,"state_putc","Bad magic number"); } DPRINT(DebugIO,30,(&DebugIO, "state_putc=%d\n", r)); return r; } } static int put_so_file P_((out_state_t *, const char *,int)); /* Prototype */ static int put_so_file(s,string,len) out_state_t *s; CONST char *string; int len; { if (s->magic != STATE_out_file) state_panic(__FILE__,__LINE__,"put_so_file","Bad magic number"); if (s->u.file.fpout == NULL) state_panic(__FILE__,__LINE__,"put_so_file","NULL file pointer"); return fwrite (string, 1, len, s->u.file.fpout); } int state_put (string, len, s) CONST char *string; int len; out_state_t *s; { int use_filter = 0; DPRINT(DebugIO,30,(&DebugIO, "state_put(string=%p,len=%d,s=%p) -- magic=%d\n", string,len,s,s->magic)); if (s->magic == STATE_out_extern) { if (STATE_out_magic != s->external_type->magic) state_panic(__FILE__,__LINE__,"state_put", "Bad func magic number"); use_filter = s->external_type->ex_policy_so_it(s, state_policy_putc_use_filter); } if (s->filter_line || s->filter || s->magic == STATE_out_buffer || use_filter) { int i, first = 0; for (i = 0; i < len; i++) { if ('\n' == string[i]) { int r; int errors = 0; if (!s->filter_line) { if (!s->filter) { /* STATE_out_dir also requires s->display_charset[0] -- value RAW_BUFFER indicates raw copying ... */ s->filter_line = new_string(s->display_charset[0]); } else s->filter_line = new_string(s->filter); } else convert_filter(s); r = add_streambytes_to_string(s->filter_line, i-first+1,cs2us(string+first), &errors); if (r < i-first+1) { DPRINT(Debug,10,(&Debug, "state_put: failed to add all streambytes to string (r=%d != %d=len), ret=%d, charset %s\n", r,i-first+1,first + r, s->filter_line->string_type->MIME_name ? s->filter_line->string_type->MIME_name : "")); flush_filter(s, 0); return first + r; /* FAILURE */ } if (errors) { DPRINT(Debug,10,(&Debug, "state_put: %d errors\n", errors)); } flush_filter(s, 0); first = i+1; } } if (first < len) { int r; int errors = 0; if (!s->filter_line) { if (!s->filter) { /* STATE_out_dir also requires s->display_charset[0] -- value RAW_BUFFER indicates raw copying ... */ s->filter_line = new_string(s->display_charset[0]); } else s->filter_line = new_string(s->filter); } else convert_filter(s); r = add_streambytes_to_string(s->filter_line, len-first,cs2us(string+first), &errors); if (r < len-first) { DPRINT(Debug,10,(&Debug, "state_put: failed to add all streambytes to string (r=%d != %d=len), ret=%d\n", r,len-first,first + r)); DPRINT(DebugIO,30,(&DebugIO, "state_put=%d (filter -- FAILURE)\n", first + r)); return first + r; /* FAILURE */ } if (errors) { DPRINT(Debug,10,(&Debug, "state_put: %d errors\n", errors)); } } DPRINT(DebugIO,30,(&DebugIO, "state_put=%d (filter)\n", len)); return len; } else { int r = EOF; switch(s->magic) { case STATE_out_file: r = put_so_file(s,string,len); break; case STATE_out_extern: if (STATE_out_magic != s->external_type->magic) state_panic(__FILE__,__LINE__,"state_put", "Bad func magic number"); r = s->external_type->ex_put_so_it(s,string,len); break; default: state_panic(__FILE__,__LINE__,"state_put","Bad magic number"); } DPRINT(DebugIO,30,(&DebugIO, "state_put=%d\n", r)); return r; } } /* convert one line -- *len is assumed to point end of line */ void state_convert_EOLN(buffer,len,buffer_size,st) char *buffer; int *len; int buffer_size; out_state_t *st; { int buf_len = *len; if (st->EOLN_is_CRLF) { if (buf_len > 0 && buffer[buf_len - 1] == '\n' && (buf_len < 1 || buffer[buf_len - 2] != '\r')) { if (buf_len < buffer_size -2) { buffer[buf_len - 1] = '\r'; buffer[buf_len] = '\n'; buffer[buf_len+1] = '\0'; buf_len++; DPRINT(Debug,25,(&Debug, "state_convert_EOLN: '%.10s'... LF -> CRLF\n", buffer)); } else { DPRINT(Debug,2,(&Debug, "state_convert_EOLN: '%.10s'... No space (size=%d, len=%d) for LF -> CRLF conversion\n", buffer,buffer_size,buf_len)); } } } else { /* Take care of CRLF => LF conversion */ if (buf_len > 1 && buffer[buf_len - 1] == '\n' && buffer[buf_len - 2] == '\r') { buffer[buf_len - 2] = '\n'; buffer[buf_len - 1] = '\0'; buf_len--; DPRINT(Debug,25,(&Debug, "state_convert_EOLN: '%.10s'... CRLF -> LF\n", buffer)); } } if (*len != buf_len) { DPRINT(Debug,25,(&Debug, "state_convert_EOLN- len=%d -> %d\n", *len,buf_len)); } *len = buf_len; } int state_printf P_((out_state_t *s, const char * format, const char *msg, ...)); int state_printf ( #if ANSI_C out_state_t *s, CONST char * format, CONST char *msg, ... #else s, format, msg, va_alist #endif ) #if !ANSI_C out_state_t *s; CONST char * format; CONST char *msg; va_dcl #endif { int ret = 0; va_list vl; int t = strlen(format); char * t1 = strchr(format,'\n'); /* elm_vmessage uses display_charset -- if buffers 'display_charset' is different we can not use elm_vmessage */ int need_conversion = s->display_charset[0] != display_charset; int use_filter = 0; DPRINT(DebugIO,30,(&DebugIO, "state_printf(s=%p,...) -- magic=%d\n", s,s->magic)); if (need_conversion) { DPRINT(DebugIO,10,(&DebugIO, "state_printf: Conversion needed: display charset (buffer)=%s (real)=%s\n", s->display_charset[0]->MIME_name ? s->display_charset[0]->MIME_name : "", display_charset->MIME_name ? display_charset->MIME_name : "")); } if (t1 && t1 != &(format[t-1])) state_panic(__FILE__,__LINE__,"state_printf", "Embedded newlines are not supported"); Va_start(vl, msg); /* defined in defs.h */ if (s->magic == STATE_out_extern) { if (STATE_out_magic != s->external_type->magic) state_panic(__FILE__,__LINE__,"state_printf", "Bad func magic number"); use_filter = s->external_type->ex_policy_so_it(s, state_policy_putc_use_filter); } if (need_conversion || s->filter_line || s->filter || s->magic == STATE_out_buffer || use_filter) { struct string * temp = elm_smessage(-1,format,msg,vl); ret = string_len(temp); if (!s->filter_line) { if (!s->filter) { if (use_filter /* FIXME */ || need_conversion) { /* STATE_out_dir also requires s->display_charset[0] -- value RAW_BUFFER indicates raw copying ... */ s->filter_line = convert_string(s->display_charset[0], temp,0); free_string(&temp); } else s->filter_line = temp; } else { s->filter_line = convert_string(s->filter,temp,0); free_string(&temp); } } else { struct string * temp2 = cat_strings(s->filter_line, temp,0); free_string(&(s->filter_line)); if (!s->filter) { if (use_filter /* FIXME */) { /* STATE_out_dir also requires s->display_charset[0] -- value RAW_BUFFER indicates raw copying ... */ s->filter_line = convert_string(RAW_BUFFER,temp2,0); free_string(&temp2); } else s->filter_line = temp2; } else { s->filter_line = convert_string(s->filter,temp2,0); free_string(&temp2); } free_string(&temp); } if (t1) flush_filter(s, 1 /* do LF <=> CRLF conversion */); } else { char * str = elm_vmessage(-1,format,msg,vl); int len = strlen(str); if (t1) { int size = len + 4; str = safe_realloc(str,size); /* Take care of CRLF => LF conversion or LF -> CRLF conversion */ state_convert_EOLN(str,&len,size,s); } switch(s->magic) { case STATE_out_file: ret = put_so_file(s,str,len); break; case STATE_out_extern: if (STATE_out_magic != s->external_type->magic) state_panic(__FILE__,__LINE__,"state_printf", "Bad func magic number"); ret = s->external_type->ex_put_so_it(s,str,len); break; default: state_panic(__FILE__,__LINE__,"state_printf", "Bad magic number"); } free(str); } va_end(vl); DPRINT(DebugIO,30,(&DebugIO, "state_printf=%d\n", ret)); return ret; } static void flush_filter(s, munge_eoln) out_state_t *s; int munge_eoln; { if (s->magic == STATE_out_buffer) { int len = string_len(s->filter_line); if (len > 0) { /* Remove LF from end */ uint16 c = give_unicode_from_string(s->filter_line,len-1); struct string * t; int X = 0; if (0x000A == c) { len--; if (len > 0) { /* And CR (ie. CRLF) from end */ uint16 c = give_unicode_from_string(s->filter_line,len-1); if (0x000D == c) len--; } } t = clip_from_string(s->filter_line,&X,len); add_line_to_stringbuffer(s->u.buffer,t); free_string(&t); } else add_line_to_stringbuffer(s->u.buffer,s->filter_line); } else if (s->magic == STATE_out_extern) { int flush_via_put; if (STATE_out_magic != s->external_type->magic) state_panic(__FILE__,__LINE__,"flush_filter", "Bad func magic number"); flush_via_put = s->external_type->ex_policy_so_it(s, state_policy_flush_via_put); if (flush_via_put) goto via_put; s->external_type->ex_flush_filter_so_it(s,munge_eoln); } else { char *s1; int l; /* s->display_charset[0] is either display_charset (internal pager) * or system_charset (external pager) */ struct string * tmp; via_put: tmp = convert_string(s->display_charset[0], s->filter_line,0); /* Can't ask just printable characters because we need NLs also ... */ s1 = us2s(stream_from_string(tmp,0,NULL)); l = strlen(s1); if (munge_eoln) { int size = l + 4; s1 = safe_realloc(s1,size); /* Take care of CRLF => LF conversion or LF -> CRLF conversion */ state_convert_EOLN(s1,&l,size,s); } switch(s->magic) { case STATE_out_file: put_so_file(s,s1,l); break; case STATE_out_extern: if (STATE_out_magic != s->external_type->magic) state_panic(__FILE__,__LINE__,"flush_filter", "Bad func magic number"); s->external_type->ex_put_so_it(s,s1,l); break; default: state_panic(__FILE__,__LINE__,"flush_filter", "Bad magic number"); } free(s1); free_string(&tmp); } free_string(&(s->filter_line)); } int state_puts (string, state) CONST char *string; out_state_t *state; { return state_put(string,strlen(string),state); } void state_nlputs(string,state) char *string; out_state_t *state; { int i; int last_start = 0; for (i = 0; string[i]; i++) { switch (string[i]) { case '\n': if (last_start < i) { int x = i; if ('\r' == string[x-1]) x--; if (last_start < x) { state_put(string + last_start, x - last_start, state); } } if (state->EOLN_is_CRLF) state_puts("\r\n",state); else state_puts("\n",state); last_start = i+1; break; } } /* Print rest of data in case there is no \n on end ... */ if (last_start < i) { state_put(string + last_start, i - last_start, state); } } /* Return 1 if is copy succeed */ int state_copy(infile,outfile) in_state_t *infile; out_state_t *outfile; { int ok = 1; while (ok) { int ch = state_getc(infile); if (EOF == ch) break; if (EOF == state_putc(ch,outfile)) ok = 0; } return ok; } /* Return 1 if is copy succeed, return -1 on unexpected EOF */ int state_copy_range(infile,outfile, bytes) in_state_t *infile; out_state_t *outfile; int bytes; { int ok = 1; int copied = 0; while (copied < bytes && ok) { int ch = state_getc(infile); if (EOF == ch) { /* Unexpected EOF */ ok = -1; break; } if (EOF == state_putc(ch,outfile)) ok = 0; } return ok; } /* * Local Variables: * mode:c * c-basic-offset:4 * buffer-file-coding-system: iso-8859-1 * End: */