home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Gold Fish 1
/
GoldFishApril1994_CD2.img
/
d4xx
/
d473
/
cnewssrc
/
cnews_src.lzh
/
relay
/
trbatch.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-05-28
|
5KB
|
200 lines
/* :ts=4
* transmit batch file management
*
* $Log$
*/
#include <stdio.h>
#ifdef unix
# include <sys/types.h>
#endif /* unix */
#include "libc.h"
#include "news.h"
#include "msgs.h"
#include "trbatch.h"
/* tunable parameters */
#ifndef FLUSHEVERY
#define FLUSHEVERY 1 /* fflush batch files every this many lines */
#endif /* FLUSHEVERY */
#ifndef NOPENBFS
#define NOPENBFS 10 /* # batchfiles kept open for batching (arbitrary) */
#endif /* NOPENBFS */
static struct batchfile batchfile[NOPENBFS]; /* try to keep open always */
#define lastbf &batchfile[NOPENBFS-1]
/*
* More than one pointer in ordtobfs may point at a given batchfile,
* to permit sharing of open batch files among multiple sys entries.
* ordtobfs[ordinal # of batch sys entry] -> (usually open) batch file,
* if the index is in range.
*/
static struct batchfile *ordtobfs[NOPENBFS];
static struct batchfile fakebatf; /* for non-cached batch files */
/* forwards */
FORWARD statust bfclose(), bfrclose();
FORWARD struct batchfile *bfincache(), *fakebf();
/*
* open "name" for appending, for batch sys entry with ordinal # "ord".
*
* if ord is too big, see if any batchfile has been assigned to "name" yet;
* if not, set up a fake batchfile for temporary use. if ord is in range,
* ensure that (name, ord) are mapped to a batchfile.
*
* if an attempt to open the batchfile's stream fails, close an arbitrary
* batchfile stream and retry the open.
*/
struct batchfile *
bfopen(name, ord)
register char *name;
register int ord;
{
register struct batchfile *bf;
if (ord >= NOPENBFS) { /* no mapping possible */
bf = bfisopen(name);
if (bf == NULL)
bf = fakebf((FILE *)NULL, name);
} else
bf = bfincache(name, ord);
if (bf->bf_str == NULL)
bf->bf_str = fopenclex(name, "a");
if (bf->bf_str == NULL) {
if (bfrclose() != ST_OKAY)
return NULL;
bf->bf_str = fopenwclex(name, "a"); /* retry, may bitch */
}
return bf;
}
/*
* returns a batchfile, never NULL, corresponding to name and ord.
* if ord isn't mapped, search the batchfile cache for name;
* if missing, initialise batchfile[ord] and map ord to it.
* if ord wasn't mapped, but name was in the cache, map ord to the cache hit.
*/
STATIC struct batchfile *
bfincache(name, ord)
char *name;
int ord;
{
register struct batchfile *bf = ordtobfs[ord];
if (bf == NULL) {
bf = bfisopen(name);
if (bf == NULL) {
/* establish new mapping for a new file */
bf = &batchfile[ord];
bf->bf_name = strsave(name);
bf->bf_str = NULL; /* paranoia */
#ifdef notdef
bf->bf_ref = 0;
#endif
bf->bf_lines = FLUSHEVERY;
}
ordtobfs[ord] = bf;
}
/* mapping is now set (ord -> bf) */
return bf;
}
/* ARGSUSED ord */
statust
bffkclose(ord) /* close current (ord's) batchfile, if fake */
int ord;
{
register statust status = ST_OKAY;
if (fakebatf.bf_str != NULL)
status |= bfclose(&fakebatf);
return status;
}
STATIC statust
bfclose(bf)
register struct batchfile *bf;
{
register statust status = ST_OKAY;
if (nfclose(bf->bf_str) == EOF)
status = prfulldisk(bf->bf_name);
bf->bf_str = NULL; /* prevent accidents; mark as closed */
return status;
}
STATIC struct batchfile *
fakebf(stream, name)
FILE *stream;
char *name;
{
fakebatf.bf_name = name;
fakebatf.bf_str = stream;
return &fakebatf;
}
/*
* search the batchfile cache for "name"; return the hit, if any.
*/
struct batchfile *
bfisopen(name)
register char *name;
{
register struct batchfile *bf;
for (bf = batchfile; bf <= lastbf; bf++)
if (bf->bf_name != NULL && STREQ(name, bf->bf_name))
return bf;
return NULL;
}
/*
* a performance hack: only fflush bf->bf_str every FLUSHEVERY calls.
*/
int
bfflush(bf)
register struct batchfile *bf;
{
register int ret = 0;
if (--bf->bf_lines <= 0) {
bf->bf_lines = FLUSHEVERY;
ret = fflush(bf->bf_str);
}
return ret;
}
STATIC statust
bfrclose() /* close an arbitrary batchfile */
{
register struct batchfile *bf;
register statust status = ST_OKAY;
for (bf = batchfile; bf <= lastbf; bf++)
if (bf->bf_str != NULL) {
status |= bfclose(bf);
break;
}
return status;
}
statust
bfrealclose() /* close all open batch files */
{
register struct batchfile *bf;
register statust status = ST_OKAY;
for (bf = batchfile; bf <= lastbf; bf++) {
if (bf->bf_str != NULL) /* batch file stream open */
status |= bfclose(bf);
nnfree(&bf->bf_name);
#ifdef notdef
bf->bf_ref = 0;
#endif
ordtobfs[bf - batchfile] = NULL; /* unmap batch file */
}
return status;
}