home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Fred Fish Collection 1.5
/
ffcollection-1-5-1992-11.iso
/
ff_disks
/
300-399
/
ff319.lzh
/
CNewsSrc
/
uupc.lzh
/
uupc
/
rnews.c
< prev
next >
Wrap
C/C++ Source or Header
|
1990-01-16
|
8KB
|
351 lines
/*
* newsspool - copy incoming news into incoming directory
*
* The -i option relies on the parent setting (and exporting) $PATH.
*
* $Id: rnews.c,v 1.2 90/01/16 10:27:09 crash Exp Locker: crash $
*/
#ifndef lint
static char RCSid[] = "$Id: rnews.c,v 1.2 90/01/16 10:27:09 crash Exp Locker: crash $";
#endif /* lint */
#ifdef AMIGA
/*
* If being compiled for an Amiga, then this code should be linked into
* the executable for UUPC to replace the built-in "rnews" command.
* Note that this bypasses the "rnews.{batch,immed}" script.
*/
# define MAIN rnews
# define LOCAL static
#else
# define MAIN main
# define LOCAL
#endif
#include <stdio.h>
#ifndef AMIGA
# include <sys/types.h>
# include <sys/stat.h>
#else
# include <time.h>
# include <libraries/dos.h>
# define stat FileInfoBlock
# define st_mode fib_DirEntryType
extern struct FileLock *Lock();
#endif /* AMIGA */
#include <string.h>
#include <errno.h>
#include "libc.h"
#include "news.h"
#include "config.h"
#ifndef lint
static char RCSid[] = "$Id: rnews.c,v 1.2 90/01/16 10:27:09 crash Exp Locker: crash $";
#endif
#ifndef MAXTRIES
# define MAXTRIES 100 /* limit on attempts to make links */
#endif
extern int debuglevel;
int debug = 0;
char *progname;
extern void error(), exit();
#ifdef UTZOOERR
extern char *mkprogname();
#else
#define mkprogname(a) (a)
#endif
char buf[BUFSIZ*16]; /* try to get a batch in a few gulps */
int immed = 0; /* try an immediate newsrun? */
void process();
FILE *outopen();
void outclose();
extern time_t time();
char *outname();
/*
* main - parse arguments and handle options
* when used with UUPC, this becomes "rnews( argc, argv )"
* which is called by RNews() in the ulib.c module
*/
MAIN (argc, argv)
int argc;
char *argv[];
{
int c;
int errflg = 0;
FILE *in;
struct stat statbuf;
extern int optind;
extern char *optarg;
extern FILE *efopen();
void process();
printmsg(3, "calling mkprogname(\"%s\")", *argv);
progname = mkprogname(argv[0]);
printmsg(3, "parsing command line");
while ((c = getopt(argc, argv, "id")) != EOF)
switch (c) {
case 'i': /* try immediate newsrun */
immed++;
break;
case 'd': /* Debugging. */
debug++;
setbuf(stderr, (char *)NULL);
break;
case '?':
default:
errflg++;
break;
}
if (errflg) {
fprintf(stderr, "Usage: %s [file] ...\n", progname);
exit(2);
}
/* probe to get unprivileged() called if necessary */
(void) ctlfile((char *)NULL);
/* mktemp() uses access(2) [ARGH!] so minimize chances of trouble */
printmsg(3, "doing setuid()/getuid() funniness...");
(void) setgid(getegid());
(void) setuid(geteuid());
(void) umask(newsumask());
if (optind >= argc)
process(stdin, "stdin");
else
for (; optind < argc; optind++)
if (STREQ(argv[optind], "-"))
process(stdin, "-");
else {
#ifdef AMIGA
struct FileLock *lock;
printmsg(2, "checking input file's mode");
if (lock = Lock(argv[optind], ACCESS_READ)) {
Examine(lock, &statbuf);
UnLock(lock);
} else
statbuf.st_mode = -1;
in = efopen(argv[optind], "r");
if (statbuf.st_mode > 0) /* AmigaDOS directory */
error("`%s' is directory!", argv[optind]);
#else
in = efopen(argv[optind], "r");
if (fstat(fileno(in), &statbuf) < 0)
error("can't fstat `%s'", argv[optind]);
if ((statbuf.st_mode & S_IFMT) == S_IFDIR)
error("`%s' is directory!", argv[optind]);
#endif /* AMIGA */
process(in, argv[optind]);
(void) fclose(in);
}
#ifndef AMIGA
if (immed) {
execlp("newsrun", "newsrun", (char *)NULL);
error("attempt to run newsrun failed!", "");
}
exit(0);
#else /* AMIGA */
return( 0 ); /* exit() isn't called from anywhere else... */
#endif /* AMIGA */
}
/*
* process - process input file
*/
/* ARGSUSED */
LOCAL void process(in, inname)
FILE *in;
char *inname;
{
register int count;
register int firstblock;
FILE *out;
register char *p;
register int n;
char *name;
name = outname();
out = outopen(name);
/* do the copying */
printmsg(4, "performing file copy...");
firstblock = 1;
while ((count = fread(buf, sizeof(char), sizeof(buf), in)) > 0) {
if (firstblock) {
n = cunskip(buf, count);
p = buf + n;
count -= n;
firstblock = 0;
} else
p = buf;
n = fwrite(p, sizeof(char), count, out);
if (n != count)
error("write error in output to `%s'", name);
}
outclose(out, name);
}
/*
* outname - construct name for the temporary output file
*/
LOCAL char *outname()
{
register char *p;
p = strsave(fullartfile("in.coming/nspool.XXXXXX"));
mktemp(p);
printmsg(5, "temporary output file is '%s'", p);
return(p);
}
/*
* outopen - acquire an output file
*/
LOCAL FILE *outopen(name)
char *name;
{
FILE *f;
f = fopen(name, "w");
if (f == NULL)
error("unable to create temporary `%s'", name);
printmsg(4, "output into '%s'", name);
return(f);
}
/*
* outclose - close output file, moving it to the right place
*
* Names are based on the current time in hopes of keeping input in order.
*/
LOCAL void outclose(f, tmpname)
FILE *f;
char *tmpname;
{
register char *p;
register char *name;
register int ntries;
time_t now;
extern int errno;
if (fclose(f) == EOF)
error("fclose error on file `%s'", tmpname);
p = fullartfile("in.coming/");
name = emalloc(strlen(p) + 20); /* plenty for a number */
(void) strcpy(name, p);
p = name + strlen(name);
ntries = 0;
for (;;) {
now = time((time_t *)NULL);
#ifdef AMIGA
sprintf(p, "%ld.z", now);
printmsg(7, "\ttrying '%s'", name);
/*
* Try the normal "rename(from, to)" function...
* This *should* be okay since the directory is
* the same (because "fullartfile()" was used) so that
* only possible error is EEXIST (?).
*/
if (rename(tmpname, name) == 0)
break;
#else
sprintf(p, "%ld", now);
if (debug)
fprintf(stderr, "trying to rename to %s\n", name);
if (link(tmpname, name) >= 0)
break; /* NOTE BREAK OUT */
#endif /* AMIGA */
if (errno != EEXIST) /* something strange is wrong */
error("unable to link `%s'", tmpname);
errno = 0;
if (ntries > MAXTRIES) /* sanity check */
error("too many attempts to link `%s'", tmpname);
if (debug)
fprintf(stderr, "failed\n");
sleep(2); /* avoid rumored race in 1-sec sleep */
ntries++;
}
printmsg(6, "destination file is '%s'", name);
if (debug)
fprintf(stderr, "succeeded\n");
/*
* If running on an Amiga, we wouldn't be here unless the
* rename() function, above, worked and so we *know* that
* this unlink() is going to fail. ...who cares?
*/
(void) unlink(tmpname);
}
/*
* cunskip - inspect block for silly #! cunbatch headers
*
* number of chars at start to skip
*/
LOCAL int cunskip(bufp, count)
char *bufp;
int count;
{
static char goop[] = "cunbatch";
# define GOOPLEN (sizeof(goop)-1) /* strlen(goop) */
static char goop2[] = "c7unbatch";
# define GOOP2LEN (sizeof(goop2)-1) /* strlen(goop2) */
register char *p;
register int nleft;
nleft = count;
p = bufp;
if (nleft < 2) /* no room for a header */
return(0);
if (*p++ != '#' || *p++ != '!') /* doesn't start with #! */
return(0);
nleft -= 2;
/* skip space */
while (nleft > 0 && (*p == ' ' || *p == '\t')) {
p++;
nleft--;
}
/* recognize headers (the +1s ensure room for the newline) */
if (nleft >= GOOPLEN+1 && STREQN(p, goop, GOOPLEN)) {
p += GOOPLEN;
nleft -= GOOPLEN;
} else if (nleft >= GOOP2LEN+1 && STREQN(p, goop2, GOOP2LEN)) {
p += GOOP2LEN;
nleft -= GOOP2LEN;
} else /* no header */
return(0);
/* skip more space */
while (nleft > 0 && (*p == ' ' || *p == '\t')) {
p++;
nleft--;
}
if (nleft == 0 || *p++ != '\n') /* didn't end properly */
return(0);
return(p - bufp);
}
/*
* unprivileged - drop setuid-ness if configuration is overridden
*/
void unprivileged()
{
setgid(getgid());
setuid(getuid());
}