Metropoli BBS
VIEWER: body.c MODE: TEXT (ASCII)
#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);
}
[ RETURN TO DIRECTORY ]