1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304
|
/*
* uncatfile.c Unconcatenates a file with multiple digests.
* Copyright (c) 1994-1998 by Christopher Heng. All rights reserved.
* You may not remove any of the copyright notices and/or conditions for use
* and distribution. See COPYING for additional conditions for use and
* distribution.
*
* $Id: uncatfile.c,v 2.4 1998/03/30 13:18:26 chris Released $
*/
#include "sysdep.h"
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#if defined(UNIX)
#include <unistd.h>
#include <sys/wait.h>
#endif
#if defined(MSDOS) || defined(WIN32)
#include <io.h> /* unlink(), mktemp() for VC++ */
#include <process.h> /* spawnl() */
#if defined(__BORLANDC__)
#include <dir.h> /* mktemp() */
#elif defined(__WATCOMC__) && (__WATCOMC__ < 1100)
/* Watcom C 10.6 and below does not have mktemp(). You'll not */
/* only have to declare it, you'll need to supply one too. */
extern char * mktemp( char * template );
#endif
#endif
#include "cftables.h"
#include "splitdigest.h"
#include "version.h"
/* macros */
#define CONTENTLENHDR "Content-Length: " /* content-length header */
/* local variables */
static char tempfilename[TEMPFILELEN]; /* temporary filename */
static int tempisused ; /* flag that temp filename is opened */
static char targetname[MAXFILELEN] = "dummy"; /* target file name */
static char buffer[MAXBUFFERLEN]; /* buffer for line */
static FILE * outfile ; /* output file pointer */
static char fromfield[] = FROMFIELD ; /* beginning of next mail msg */
/* local functions */
static void compressfile ( char * file );
static int getline ( char * buffer, int maxlen, FILE * fp );
static void putline ( char * buffer, FILE *fp );
static int iscontentlen ( char * buffer );
/* does the dirty job of splitting the file */
void uncatfile ( FILE * infile )
{
int gotheader, notfirst ;
int inhdr ;
char endstring[MAXBUFFERLEN];
char savedfrom[MAXBUFFERLEN];
cftable_t * cfp ;
fpos_t lastpos ;
char * s;
while (!feof(infile)) {
tempisused = 0 ; /* assume no temporary file */
/* open the file (if required) and place the FILE * into */
/* outfile */
if (pipe_output) {
/* put all output into stdout */
outfile = stdout ;
}
else if (output_filename != NULL) {
/* if we are to put all output into a file specified at */
/* the command line, open that file for append, creating */
/* it if it does not exists. */
if ((outfile = fopen( output_filename, APPENDMODE ))
== NULL) {
fprintf( stderr, "%s: unable to open %s.\n",
pgmname, output_filename );
return ;
}
}
else {
/* open output file to a temp name - warning: the file is */
/* created in the current directory so that it can be */
/* simply renamed to the final file name - so that we */
/* don't need to worry about linking across different file */
/* systems and what not. (I told you this was a primitive */
/* program!) */
strcpy ( tempfilename, TEMPLATE );
if (mktemp( tempfilename ) == NULL) {
fprintf( stderr, "%s: cannot generate temporary file"
"name. Aborting.\n", pgmname );
exit(EXIT_FAILURE); /* quite unlikely to happen, right? */
/* (Warning: infile still open - exit() will close it) */
}
/* open the output file */
if ( (outfile = fopen ( tempfilename, WRITEMODE )) == NULL ) {
fprintf( stderr, "%s: cannot open temporary file %s. "
"Skipped.\n", pgmname, tempfilename );
return ; /* return and better luck next time! */
}
tempisused = 1; /* flag that temporary file is opened */
}
/* keep reading lines to find the digest name from the header*/
gotheader = notfirst = 0 ;
inhdr = 1; /* flag that we're in the header of the email */
while (getline(buffer, MAXBUFFERLEN, infile)) {
/* WARNING: the following code is duplicated later as well. */
/* Should consider putting this into a function! */
if (!strcmp( buffer, "\n" ))
inhdr = 0; /* end of headers - blank line */
/* write the buffer to output file unless: 1) we need to */
/* kill the Content-Length header; 2) we're currently */
/* processing a mail header; *AND* 3) the header matches */
/* a Content-Length header */
if (!kill_contentlen || !inhdr || !iscontentlen( buffer ))
putline( buffer, outfile );
if (!notfirst) {
strcpy (savedfrom, buffer); /* save the "From " line*/
notfirst = 1;
}
if (isheader( buffer, targetname, endstring, &cfp )) {
/* found header */
gotheader = 1;
break ; /* break out */
}
}
if (!gotheader) { /* if no header it's either an error or eof */
fprintf(stderr, "%s: Unexpected end-of-file in %s.\n",
pgmname, infilename );
goto errreturn ;
}
/* now read and copy till the hdrsep is encountered */
while (getline(buffer, MAXBUFFERLEN, infile)) {
if (!strcmp( buffer, "\n" ))
inhdr = 0; /* end of headers - blank line */
if (ishdrsep( buffer, cfp )) {
putline( savedfrom, outfile);
getline(buffer, MAXBUFFERLEN, infile);
/* get rid of blank line */
break ;
}
/* WARNING: the following code is duplicated above. */
/* should consider putting this into a function! */
/* write the buffer to output file unless: 1) we */
/* need to kill the Content-Length header; */
/* 2) we're currently processing a mail header; */
/* *AND* 3) the header matches a Content-Length */
/* header */
else if (!kill_contentlen || !inhdr ||
!iscontentlen( buffer ))
putline( buffer, outfile );
}
/* at this point, we assume all mail headers have been processed */
/* (ie after the hdrsep is encountered) and so we don't bother */
/* to check for any more Content-Length headers */
/* now read and copy till msgsep or end of digest marker */
while (getline(buffer, MAXBUFFERLEN, infile)) {
if (ismsgsep( buffer, cfp )) {
putline( savedfrom, outfile ); /* output "From " hdr*/
getline(buffer, MAXBUFFERLEN, infile);
/* get rid of blank line */
continue ;
}
else putline( buffer, outfile ); /* output line */
s = buffer + (strlen(buffer)-1);
if (*s == '\n')
*s = '\0'; /* get rid of new line */
if (isend( buffer, endstring )) {
if (fgetpos( infile, &lastpos )) {/*for repositioning*/
getposerr: fprintf(stderr, "%s: Error reading %s.\n",
pgmname, infilename );
goto errreturn ;
}
/* just copy till next mail message */
while (getline(buffer, MAXBUFFERLEN, infile)) {
/* compare before we write so we won't */
/* overshoot in writing */
if (!strncmp(buffer, fromfield, sizeof(fromfield)-1)) {
/* oops, overshot. Reposition */
fsetpos( infile, &lastpos );
break ;
}
/* copy */
putline( buffer, outfile);
/* get current position for repositioning */
if (fgetpos( infile, &lastpos ))
goto getposerr; /* sorry, another goto! */
}
break ; /* finished for now */
} /* end of isend() */
} /* end of while - read till msgsep or end of digest markers */
/* now we got to close the files and rename the output file */
tempisused = 0; /* flag to prevent cleanuponsig() deleting */
if (!pipe_output) {
fclose(outfile); /* tempfile */
if (output_filename == NULL)
rename( tempfilename, targetname );
if (compression) /* if compression is needed */
compressfile(targetname);
}
} /* while (!feof(infile)) */
return;
errreturn: /* clean up on error */
tempisused = 0;
if (!pipe_output) {
fclose( outfile );
if (output_filename == NULL)
unlink( tempfilename );
}
return ;
}
/* does the real cleanup - called by cleanuponsig() and the atexit function */
void realcleanup( void )
{
if (tempisused) { /* if temp file opened */
fclose( outfile );
unlink ( tempfilename ); /* just trying to be tidy, old chap */
tempisused = 0; /* flag done in case we get called twice */
}
return ;
}
#if defined(UNIX)
/* compress file name specified */
static void compressfile ( char * file )
{
int childpid ; /* child process id */
if ( (childpid = fork()) == 0 ) { /* child */
if ( execl( DEFCOMPRESS, DEFCOMPRESS, COMPRESSARG, file,
NULL ) == -1 ) {
fprintf( stderr, "%s: Cannot execute %s.\n",
pgmname, DEFCOMPRESS );
exit(EXIT_FAILURE);
}
}
else if (childpid == -1) { /* error from fork() */
fprintf( stderr, "%s: Cannot fork (not enough memory).\n",
pgmname );
return ; /* just return */
}
else waitpid ( childpid, NULL, 0 ); /* wait for child to complete */
return ;
}
#elif defined(MSDOS) || defined(WIN32)
/* compress file name specified */
static void compressfile ( char * file )
{
if (spawnl( P_WAIT, DEFCOMPRESS, DEFCOMPRESS, COMPRESSARG, file,
NULL ) != 0)
fprintf( stderr, "%s: Cannot execute %s.\n", pgmname, DEFCOMPRESS );
return ;
}
#endif
/* get line from input file */
static int getline( char * buffer, int maxlen, FILE * infile )
{
if (fgets( buffer, maxlen, infile ) == NULL) {
if (ferror(infile) ) {
fprintf( stderr, "%s: error reading %s.\n",
pgmname, infilename );
exit( EXIT_FAILURE );
}
return 0 ;
}
return 1;
}
/* put a line into the output file */
static void putline ( char * buffer, FILE * outfp )
{
if (fputs( buffer, outfp ) == EOF) {
fprintf( stderr, "%s: error writing %s.\n",
pgmname, tempfilename ); /* always write to tempfile */
exit( EXIT_FAILURE );
}
return ;
}
/* check if the start of the buffer matches the Content-Length header */
static int iscontentlen ( char * buffer )
{
if (!strncmp ( buffer, CONTENTLENHDR, sizeof(CONTENTLENHDR)-1 ))
return 1 ;
return 0;
}
|