File: uncatfile.c

package info (click to toggle)
splitdigest 2.4-4
  • links: PTS
  • area: main
  • in suites: woody
  • size: 144 kB
  • ctags: 135
  • sloc: ansic: 798; makefile: 104
file content (304 lines) | stat: -rw-r--r-- 9,615 bytes parent folder | download | duplicates (4)
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;
}