#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <lprintf.h>
#include <chanlib.h>
/************************************************************************/
/* */
/************************************************************************/
static size_t read_body(FILE *fp, char *buf, size_t bufsiz, int *nlines, long *nbytes)
{
size_t cc;
char *cp;
while((bufsiz > 0) && (fgets(buf, bufsiz + 2, fp) != NULL)) {
cc = strlen(buf);
if(cc < bufsiz)
bufsiz -= cc;
else
bufsiz = 0;
cp = buf + cc - 1;
if(cc > 1 && *(cp - 1) == '\r') {
*cp-- = '\0';
*cp = '\n';
cc--;
}
if(*cp == '\n') {
buf += cc;
*nbytes += cc;
(*nlines)++;
}
else
bufsiz = 0;
}
return(bufsiz);
}
/************************************************************************/
/* */
/************************************************************************/
int append_temp(FILE *fp, char *name, char *buf, size_t bufsiz)
{
int r = 0;
int cc;
FILE *ft;
if((ft = fopen(name, "rb")) != NULL) {
while((cc = fread(buf, 1, bufsiz, ft)) != 0)
fwrite(buf, 1, cc, fp);
fclose(ft);
r = 1;
}
else
lperror(name);
return(r);
}
/************************************************************************/
/* copy_body */
/* */
/* Reads an article's body from fpin and counts the number of lines. */
/* Then it writes a last header line "Lines:", an empty line and the */
/* article's body to fpout. */
/* */
/* If the size of the article body fits in the memory buffer, then */
/* this procedures works without a temporary disk file. */
/* */
/************************************************************************/
long copy_body(FILE *fpout, FILE *fpin, long body_size)
{
long rv = 0;
size_t bufsiz = 32767;
size_t left = bufsiz;
int nlines = 0;
char *buf = malloc(bufsiz);
char *line = buf;
FILE *fp;
int cc;
char *cp;
if(body_size) {
if((body_size + 2) < (long)bufsiz) {
left = read_body(fpin, buf, (size_t)body_size, &nlines, &rv);
rv += fprintf(fpout, "Lines: %u\n\n", nlines);
fputs(buf, fpout);
}
else {
char *tempname = tempnam(NULL, "ART");
long left4read = body_size;
if((fp = fopen(tempname, "wb")) != NULL) {
while(left4read > 0 &&
fgets(buf, (size_t)min(left4read + 2, (long)bufsiz), fpin)) {
cc = strlen(buf);
cp = buf + cc - 1;
if(cc > 1 && *(cp - 1) == '\r') {
*cp-- = '\0';
*cp = '\n';
cc--;
}
fputs(buf, fp);
rv += cc;
left4read -= cc;
nlines++;
}
fclose(fp);
if(body_size != rv)
lprintf("Given %ld bytes, read %ld bytes\n", body_size, rv);
rv += fprintf(fpout, "Lines: %u\n\n", nlines);
append_temp(fpout, tempname, buf, bufsiz);
if(unlink(tempname))
lperror(tempname);
}
else
lperror(tempname);
free(tempname);
}
}
else {
/*
* Try to read the article into memory first
*/
left = read_body(fpin, buf, bufsiz - 2, &nlines, &rv);
/*
* If the article doesn't fit into our memory buffer
* then create a temporary file.
*/
if(!left) {
char *tempname = tempnam(NULL, "ART");
if((fp = fopen(tempname, "wb")) != NULL) {
fputs(buf, fp);
while(fgets(buf, bufsiz, fpin)) {
cc = strlen(buf);
cp = buf + cc - 1;
if(cc > 1 && *(cp - 1) == '\r') {
*cp-- = '\0';
*cp = '\n';
cc--;
}
fputs(buf, fp);
rv += cc;
nlines++;
}
fclose(fp);
rv += fprintf(fpout, "Lines: %u\n\n", nlines);
append_temp(fpout, tempname, buf, bufsiz);
if(unlink(tempname))
lperror(tempname);
}
else
lperror(tempname);
free(tempname);
}
else {
rv += fprintf(fpout, "Lines: %u\n\n", nlines);
fputs(buf, fpout);
}
}
free(buf);
return(rv);
}