home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The World of Computer Software
/
World_Of_Computer_Software-02-387-Vol-3of3.iso
/
b
/
bmh02src.zip
/
BUFFER.C
< prev
next >
Wrap
C/C++ Source or Header
|
1992-08-16
|
9KB
|
363 lines
/*
buffer.c : Copyright Paul Healy, EI9GL, 1992.
A file is opened in binary mode and dumped to a buffer (in its entirety
if the buffer is big enough). Two pointers are retured to the buffer in
order to let clients walk through the buffer.
It is up the client routines to call refill if the end of the buffer is
reached. 'getstring' will automatically call refill if needed.
The mail is locked while dumping to the buffer. If the size of the mailfile
changes between loading and subsequent refills, then
920527 : Created.
*/
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <io.h>
#include <alloc.h>
#include <ctype.h>
#include <string.h>
#include "rc.h"
#include "lock.h"
#include "buffer.h"
#include "misc.h"
#include "header.h"
#include "current.h"
static unsigned BufSize = 0;
static char *Buffer = NULL, Finished = -1, *FileName = NULL, *LockFile = NULL;
static struct stat Stat;
static long Where = -1l;
void
freebuf(void)
{
/*
BufSize = 0;
if (Buffer != NULL) {
free(Buffer);
Buffer = NULL;
}
else
fprintf(stderr, "freebuf: freeing buffer before allocating it\n");
*/
if (FileName != NULL) {
free(FileName);
FileName = NULL;
}
if (LockFile != NULL) {
free(LockFile);
LockFile = NULL;
}
Finished = -1;
Where = -1L;
}
static int
fill(char **start, char **end, struct stat *statbuf)
{
int handle, result;
if ( (LockFile != NULL) && (bm_lock(LockFile) == -1) ) {
fprintf(stderr, "fill: can't lock %s\n", LockFile);
return -1;
}
if ( (handle = open (FileName, O_RDONLY | O_BINARY)) == -1) {
bm_unlock(LockFile);
/*
fprintf(stderr, "fill: can't open %s\n", FileName);
*/
return -1;
}
if ( (Where != -1l) && (lseek(handle, Where, SEEK_SET) == -1L) ) {
fprintf(stderr, "fill: can't seek %s\n", FileName);
close(handle);
bm_unlock(LockFile);
return -1;
}
/*
* read returns an integer, but since we may be asking for more
* bytes that a 16 bit signed int can hold, the cast to unsigned
* further on is required.
*/
if ( (result = read(handle, Buffer+1, BufSize)) == -1 ) {
fprintf(stderr, "fill: error reading %s\n", FileName);
close(handle);
bm_unlock(LockFile);
return -1;
}
*start = Buffer+1;
*end = *start + (unsigned) result;
**end = 'F'; /* Optimization for searching */
/*
printf("fill: %u bytes read\n", result);
*/
(void) fstat(handle, statbuf); /* Record create time and size */
if ( (Finished = eof(handle)) == 0);
Where = tell(handle);
close(handle);
return bm_unlock(LockFile);
}
int
loadbuf(char *s, char **start, char **end, char *lockfile)
{
if (BufSize == 0)
BufSize = atol(getrc(bufsize));
if ( (Buffer == NULL) && ( (Buffer = (char *) malloc(BufSize+2)) == NULL ) ) {
fprintf(stderr, "loadbuf: no room\n");
return -1;
}
Buffer[0] = '\n'; /* Ensure that a 'From' at the start of the file is */
/* recognised by starting the buffer with a new line */
if ( ( FileName=strdup(s) ) == NULL) {
fprintf(stderr, "loadbuf: no room\n");
return -1;
}
if ( (lockfile != NULL) && ( (LockFile = strdup(lockfile)) == NULL ) ) {
fprintf(stderr, "loadbuf: no room\n");
return -1;
}
/*
printf("loadbuf: bufsize=%u, file=%s\n", BufSize, FileName);
*/
return fill(start, end, &Stat);
}
int
loadmail(char *prog, char *folder, char **start, char **end)
{
char file[256], lock[256];
sprintf(file, "%s/%s%s", getrc(maildir), folder, EXT);
sprintf(lock, "%s/%s", getrc(maildir), folder);
if ( loadbuf(file, start, end, lock) == -1) {
fprintf(stderr, "%s: can't load %s\n", prog, file);
return -1;
}
return 0;
}
int
refill(char **start, char **end)
{
struct stat statbuf;
int result;
if (Finished != 0) /* 1 for not eof, and -1 for error condition */
return 1;
Buffer[0] = Buffer[BufSize-1]; /* refill will only be call on previously */
/* full buffers */
result = fill(start, end, &statbuf);
if ( statbuf.st_size != Stat.st_size ) {
fprintf(stderr, "bm: %s has been updated (%ld, %ld)\n", FileName,
statbuf.st_size, Stat.st_size);
return -2;
}
else
return result;
}
long
filesize(void)
{
return FileName == NULL ? -1L : Stat.st_size;
}
char *
getstring(char **start, char **end, char *s, int max)
{
char *p = *start, *e = *end;
if (Finished && (p == e) )
return NULL;
do {
while ( p < e ) {
#ifdef MSDOS
if ( (*s = *p++) == '\r') /* dispose of extra msdos line marker */
continue;
#endif
if (*s == '\n') {
*s = '\0';
break;
}
max--;
if (max == 0) {
*(s+1) = '\0';
break;
}
s++;
}
}
while ( (p == e) && (refill(&p, &e) == 0) );
*start = p;
*end = e;
return s;
}
/*
* General purpose buffer processing. Designed to replace the existing
* misc. versions all over the place.
*
* Can be called in three different ways:
* 1. wantall = 1: call 'fn' for every msg (note that fn can return
* immediately and let walk process the rest of a msg)
* 2. wantall = 0, argv = NULL: 'fn' will only be called when the
* message number in argc is met.
* 3. wantall = 0, argv != NULL, argc = # of pointers in argv. 'fn'
* will be called each time the 'wanted' function is true for a msg.
*/
/* was a const int, but tcc objects */
#define WalkStrLength 256
int
walk(char *p, char *end, int wantall, MsgFn fn, int argc, char *argv[])
{
int num = 0;
while (1) {
while ( *p != 'F' )
p++;
if ( (p==end) && (refill(&p, &end) != 0) )
break;
if (*(p-1) != '\n')
p++;
else {
char s[WalkStrLength];
getstring(&p, &end, s, sizeof(s));
while (strncmp(s, "From ", 5) == 0) {
num++;
if ( wantall ||
( (argv == NULL) && (argc == num) ) ||
( (argv != NULL) && wanted(num, argc, argv, 0) )
)
fn(num, &p, &end, s); /* correct calling syntax? */
else
break;
}
}
}
return num;
}
/* -------------------------------------------------------------------- */
static int sm_wantheader;
static FILE *sm_fp;
static int
savemsg(int num, char **start, char **end, char *line)
{
if (!sm_wantheader) {
char *argv[MAXHDR];
if ( parseheader(start, end, argv) == -1) {
fprintf(stderr, "savemsg: bad header on message %d\n", num);
freeheader(argv);
return -1;
}
freeheader(argv);
}
while (getstring(start, end, line, WalkStrLength) != NULL)
if (strncmp(line, "From ", 5) == 0)
break; /* have hit next message */
else {
if (line[0] != '\0') /* fputs returns EOF on being asked to */
/* write an empty string... */
if ( fputs(line, sm_fp) == EOF ) {
fprintf(stderr, "savemsg: error writing message # %d\n", num);
return -1;
}
if ( fputc('\n', sm_fp) == EOF) {
fprintf(stderr, "savemsg: error writing message # %d\n", num);
return -1;
}
}
return 0;
}
int
msg2file(char *p, char *end, FILE *fp, int msg, int wantheader)
{
sm_fp = fp;
sm_wantheader = wantheader;
return walk(p, end, 0, savemsg, msg, NULL);
}
int
savemsgs(int argc, char *argv[], char *filename, int wantheaders)
{
char *s, *p, *end;
int msg;
if (setupbm()==-1)
return -1;
if (getcurrent(argc, argv, &s, &msg) == -1)
return -1;
if (loadmail("savemsgs", s, &p, &end) == -1)
return -1;
if ( (sm_fp = fopen(filename, "a")) == NULL) {
fprintf(stderr, "savemsg: can't open %s\n", filename);
return -1;
}
sm_wantheader = wantheaders;
if (argc == 1)
walk(p, end, 0, savemsg, msg, NULL);
else
walk(p, end, 0, savemsg, argc, argv);
return fclose(sm_fp);
}
/* -------------------------------------------------------------------- */
#ifdef BUFFER_PROG
int
main(int argc, char *argv[])
{
char *start, *end;
printf("coreleft before creating buffer= %u\n", coreleft() );
if (loadbuf(argv[1], &start, &end, NULL) == -1) {
fprintf(stderr, "Problem\n");
exit(-1);
}
printf("coreleft after buffer is allocated= %u\n", coreleft() );
while (start<end)
putchar(start++);
return 0;
}
#endif