|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T i
Length: 42311 (0xa547)
Types: TextFile
Names: »inews.c«
└─⟦9ae75bfbd⟧ Bits:30007242 EUUGD3: Starter Kit
└─⟦373604645⟧ »EurOpenD3/news/bnews.2.11/src.tar.Z«
└─⟦3beb569ac⟧
└─⟦this⟧ »src/inews.c«
/*
* This software is Copyright 1986, 1989 by Rick Adams.
*
* Permission is hereby granted to copy, reproduce, redistribute or
* otherwise use this software as long as: there is no monetary
* profit gained specifically from the use or reproduction or this
* software, it is not sold, rented, traded or otherwise marketed, and
* this copyright notice is included prominently in any copy
* made.
*
* The author make no claims as to the fitness or correctness of
* this software for any use whatsoever, and it is provided as is.
* Any use of this software is at the user's own risk.
*
* inews - insert, receive, and transmit news articles.
*
*/
#ifdef SCCSID
static char *SccsId = "@(#)inews.c 2.93 10/29/89";
#endif /* SCCSID */
#include "iparams.h"
# ifdef LOCKF
# include <unistd.h>
# include <fcntl.h>
# if defined(F_RDLCK) && defined(F_SETLK) && !defined(HP9K5)
struct flock news_lock;
# endif /* F_RDLCK && F_SETLK && !HP9K5 */
# endif /* LOCKF */
#ifdef BSD4_2
# include <sys/file.h>
#else /* !BSD4_2 */
# if defined(USG) && !defined(LOCKF)
# include <fcntl.h>
# endif /* USG */
#endif /* !BSD4_2 */
/* local defines for inews */
#define OPTION 0 /* pick up an option string */
#define STRING 1 /* pick up a string of arguments */
#define UNKNOWN 0001 /* possible modes for news program */
#define UNPROC 0002 /* Unprocessed input */
#define PROC 0004 /* Processed input */
#define CONTROL 0010 /* Control Message */
#define CREATENG 0020 /* Create a new newsgroup */
#define DONT_SPOOL 0
#define DO_SPOOL 1
#define EXPIRE_RUNNING 2
int spool_news = DONT_SPOOL;
static char *artlinks[32];
static int linkcount;
extern char histline[];
char forgedname[NAMELEN]; /* A user specified -f option. */
/* Fake sys line in case they forget their own system */
char *Progname = "inews"; /* used by xerror to identify failing program */
struct { /* options table. */
char optlet; /* option character. */
char filchar; /* if to pickup string, fill character. */
int flag; /* TRUE if have seen this opt. */
int oldmode; /* OR of legal input modes. */
int newmode; /* output mode. */
char *buf; /* string buffer */
} *optpt, options[] = { /*
optlet filchar flag oldmode newmode buf */
't', ' ', FALSE, UNPROC, UNKNOWN, header.title,
'n', NGDELIM, FALSE, UNPROC, UNKNOWN, header.nbuf,
'd', '\0', FALSE, UNPROC, UNKNOWN, header.distribution,
'e', ' ', FALSE, UNPROC, UNKNOWN, header.expdate,
'p', '\0', FALSE, UNKNOWN|PROC, PROC, filename,
'f', '\0', FALSE, UNPROC, UNKNOWN, forgedname,
'F', ' ', FALSE, UNPROC, UNKNOWN, header.followid,
'c', ' ', FALSE, UNKNOWN,UNKNOWN, header.ctlmsg,
#define COPT 'C'
COPT, ' ', FALSE, UNKNOWN,CREATENG, header.ctlmsg,
#define hflag options[9].flag
'h', '\0', FALSE, UNPROC, UNKNOWN, filename,
#define oflag options[10].flag
'o', '\0', FALSE, UNPROC, UNKNOWN, header.organization,
#define Mflag options[11].flag
'M', '\0', FALSE, UNPROC, UNKNOWN, filename,
'a', '\0', FALSE, UNPROC, UNKNOWN, header.approved,
'U', '\0', FALSE, PROC, PROC, filename,
#define Sflag options[14].flag
'S', '\0', FALSE, UNKNOWN|PROC, UNPROC, filename,
'x', '\0', FALSE, UNPROC, UNKNOWN, not_here,
'r', '\0', FALSE, UNPROC, UNKNOWN, header.replyto,
#define vflag options[17].flag
'v', '\0', FALSE, UNPROC, UNKNOWN, filename,
'\0', '\0', 0, 0, 0, (char *)NULL
};
FILE *mailhdr();
extern FILE *controlmail;
extern int errno, xxit();
char *infpbuf = NULL;
struct timeb Now;
/*
* Authors:
* Matt Glickman glickman@ucbarpa.Berkeley.ARPA
* Mark Horton mark@cbosgd.UUCP
* Stephen Daniels swd@mcnc.UUCP
* Tom Truscott trt@duke.UUCP
* Rick Adams rick@seismo.CSS.GOV
* IHCC version adapted by:
* Larry Marek larry@ihuxf.UUCP
*/
main(argc, argv)
int argc;
register char **argv;
{
int state; /* which type of argument to pick up */
int tlen, len; /* temps for string processing routine */
register char *ptr; /* pointer to rest of buffer */
int filchar; /* fill character (state = STRING) */
char *user = NULL, *home = NULL; /* environment temps */
struct passwd *pw; /* struct for pw lookup */
struct group *gp; /* struct for group lookup */
register int i;
FILE *mfd; /* mail file file-descriptor */
#if !defined(LOCKF) && !defined(BSD4_2)
struct stat stbuf;
#endif /* !LOCKF && ! BSD4_2 */
/* uuxqt doesn't close all its files */
for (i = 3; !close(i); i++)
;
/* set up defaults and initialize. */
mode = UNKNOWN;
infp = stdin;
pathinit();
savmask = umask(N_UMASK); /* set up mask */
ptr = rindex(*argv, '/');
if (!ptr)
ptr = *argv - 1;
#ifdef NFSCLIENT
actfp = xfopen(ACTIVE, "r");
#else /* !NFSCLIENT */
actfp = xfopen(ACTIVE, "r+");
#ifdef LOCKF
# if defined(F_RDLCK) && defined(F_SETLK) && !defined(HP9K5)
news_lock.l_type = F_RDLCK;
if (fcntl(fileno(actfp), F_SETLK, &news_lock) < 0) {
# else /* !(F_RDLCK && F_SETLK && !HP9K5) */
if (lockf(fileno(actfp), F_TLOCK, 0L) < 0) {
# endif /* !(F_RDLCK && F_SETLK && !HP9K5) */
if (errno != EAGAIN && errno != EACCES)
#else /* !LOCKF */
#ifdef BSD4_2
if (flock(fileno(actfp), LOCK_SH|LOCK_NB) < 0) {
if (errno != EWOULDBLOCK)
#else /* !BSD4_2 */
sprintf(bfr, "%s.lock", ACTIVE);
/* assume a dead lock if the active file is over 12 hours old */
if (LINK(ACTIVE, bfr) < 0 &&
(errno != EEXIST ||
(stat(bfr, &stbuf) == 0 &&
(time((char *)0) - stbuf.st_mtime) < DAYS/2))) {
if (errno != EEXIST)
#endif /* V7 */
#endif /* !BSD4_2 */
xerror("Can't lock %s: %s", ACTIVE, errmsg(errno));
spool_news = EXPIRE_RUNNING;
} else {
#ifdef SPOOLNEWS
if (argc > 1 && !STRCMP(*(argv+1), "-S")) {
argc--;
argv++;
Sflag = 1;
} else
spool_news = DO_SPOOL;
#endif /* SPOOLNEWS */
}
if (spool_news != EXPIRE_RUNNING) {
/* only unlock if we locked */
#ifdef LOCKF
(void) lockf(fileno(actfp), F_ULOCK, 0L);
#else /* !LOCKF */
#ifdef BSD4_2
(void) flock(fileno(actfp), LOCK_UN);
#else /* !BSD4_2 */
(void) UNLINK(bfr);
#endif /* V7 */
#endif /* !BSD4_2 */
} else { /* expire is running */
if (argc > 1 && !STRCMP(*(argv+1), "-S"))
exit(42); /* inform rnews -U by exit status */
}
(void) signal(SIGTERM, xxit);
if (argc > 1 && !STRCMP(*(argv+1), "-U")) {
/* can't unspool while things are locked */
if (spool_news == EXPIRE_RUNNING)
xxit(0);
dounspool();
/* NOT REACHED */
}
#endif /* !NFSCLIENT */
if (!STRNCMP(ptr+1, "rnews", 5)) {
#ifndef NFSCLIENT
mode = PROC;
if (spool_news != DONT_SPOOL) {
dospool((char *)NULL, FALSE);
/* NOT REACHED */
}
#else /* NFSCLIENT */
mfd = mailhdr((struct hbuf *)NULL, "Improper use of INEWS");
if (mfd != NULL) {
fprintf(mfd,"System: %s\n\nINEWS is running improperly as RNEWS on slave NFS site by user %s.\n", LOCALSYSNAME, username);
(void) mclose(mfd);
exit(1);
}
#endif /* NFSCLIENT */
#ifdef NICENESS
if ((i=nice(0)) < NICENESS)
(void) nice(NICENESS-i);
#endif /* NICENESS */
} else {
/* it's not rnews, so it must be inews */
if (argc < 2)
goto usage;
#ifndef SPOOLINEWS
if (spool_news == DO_SPOOL)
spool_news = DONT_SPOOL;
#endif /* SPOOLINEWS */
}
#ifdef MINFREE
if (space()) { /* check disk space */
spool_news = DO_SPOOL;
logerr("Out of space in %s.", SPOOLDIR);
}
#endif /* MINFREE */
state = OPTION;
header.title[0] = header.nbuf[0] = filename[0] = '\0';
/* check for existence of special files */
#ifdef DBM
chkfile(ARTFILE);
#else
chkdir(ARTFILE);
#endif /* DBM */
chkfile(ACTIVE);
SigTrap = FALSE; /* true if a signal has been caught */
if (mode != PROC) {
(void) signal(SIGHUP, onsig);
(void) signal(SIGINT, onsig);
}
/*
* Catch "filesize exceeded" signals on 4.2BSD systems
* - the history files may exceed this limit.
*/
#ifdef SIGXFSZ
(void) signal(SIGXFSZ, SIG_IGN);
#endif /* SIGXFSZ */
uid = getuid();
gid = getgid();
duid = geteuid();
dgid = getegid();
(void) ftime(&Now);
#ifndef NFSCLIENT
if (uid == 0 && duid == 0) {
#else /* NFSCLIENT */
if (duid == 0) {
#endif /* NFSCLIENT */
/*
* Must go through with this kludge since
* some systems do not honor the setuid bit
* when root invokes a setuid program.
*
* On NFS slave systems, inews is setuid to ROOT. This allows
* inews to setuid/gid (real and effective) to NEWSUSR and
* NEWSGRP respectively. This *must* happen so that the "rsh"
* program will run as user NEWSUSR and not as the user running
* inews. "rsh" runs as the "real" user even when the program
* calling it is setuid.
*/
if ((pw = getpwnam(NEWSUSR)) == NULL)
xerror("Cannot get NEWSU pw entry");
duid = pw->pw_uid;
if ((gp = getgrnam(NEWSGRP)) == NULL)
xerror("Cannot get NEWSG gr entry");
dgid = gp->gr_gid;
(void) setgid(dgid);
(void) setuid(duid);
}
/*
* Force the use of 'getuser()' to prevent forgery of articles
* by just changing $LOGNAME
*/
if (isatty(fileno(stderr))
#ifdef DOGETUSER
&& uid == 0 /* allow root to set name in any case */
#endif /* DOGETUSER */
) {
if ((user = getenv("USER")) == NULL)
user = getenv("LOGNAME");
if ((home = getenv("HOME")) == NULL)
home = getenv("LOGDIR");
}
if (user == NULL || home == NULL)
getuser();
else {
if (STRCMP(username, "Unknown") == 0 || username[0] == 0) {
username = AllocCpy(user);
}
userhome = AllocCpy(home);
}
getuser();
/* loop once per arg. */
++argv; /* skip first arg, which is prog name. */
while (--argc) {
if (state == OPTION) {
if (**argv != '-') {
xerror("Bad option string \"%s\"", *argv);
}
while (*++*argv != '\0') {
for (optpt = options; optpt->optlet != '\0'; ++optpt) {
if (optpt->optlet == **argv)
goto found;
}
/* unknown option letter */
usage:
fprintf(stderr, "usage: inews -t title");
fprintf(stderr, " [ -n newsgroups ]");
fprintf(stderr, " [ -e expiration date ]\n");
fprintf(stderr, "\t[ -f sender]\n\n");
xxit(1);
found:;
#ifdef NFSCLIENT
if (optpt->optlet == COPT) {
fprintf(stderr, "Cannot create new newsgroups from an NFS slave system.\n\n");
xxit(1);
}
#endif /* NFSCLIENT */
if (optpt->flag == TRUE || (mode != UNKNOWN &&
(mode&optpt->oldmode) == 0)) {
xerror("Bad %c option", **argv);
}
if (mode == UNKNOWN)
mode = optpt->newmode;
filchar = optpt->filchar;
optpt->flag = TRUE;
state = STRING;
ptr = optpt->buf;
len = BUFLEN;
}
argv++; /* done with this option arg. */
} else {
/*
* Pick up a piece of a string and put it into
* the appropriate buffer.
*/
if (**argv == '-') {
state = OPTION;
argc++; /* uncount this arg. */
continue;
}
if ((tlen = strlen(*argv)) >= len)
xerror("Argument string too long");
(void) strcpy(ptr, *argv++);
ptr += tlen;
if (*(ptr-1) != filchar)
*ptr++ = filchar;
len -= tlen + 1;
*ptr = '\0';
}
}
/*
* ALL of the command line has now been processed. (!)
*/
if (*filename) {
infp = freopen(filename, "r", stdin);
if (infp == NULL)
xerror("freopen(%s): %s", filename, errmsg(errno));
} else
infp = stdin;
tty = isatty(fileno(infp));
#ifndef NFSCLIENT
if (mode == CREATENG)
createng();
#endif /* !NFSCLIENT */
if (header.ctlmsg[0] != '\0' && header.title[0] == '\0')
(void) strcpy(header.title, header.ctlmsg);
if (*header.nbuf) {
lcase(header.nbuf);
ptr = index(header.nbuf, '\0');
if (ptr[-1] == NGDELIM)
*--ptr = '\0';
}
(void) nstrip(header.title);
(void) nstrip(header.expdate);
(void) nstrip(header.followid);
if (mode != PROC) {
if (hflag) {
header.path[0] = '\0';
(void) hread(&header, infp, FALSE);
/* there are certain fields we won't let him specify. */
if (header.from[0]) {
(void) fixfrom(&header);
if (Sflag && !Mflag && !header.approved[0] &
!header.sender[0]) {
register char *p;
strcpy(bfr, header.from);
p = strpbrk(bfr, "@ !");
if (p)
*p = '\0';
if ((pw = getpwnam(bfr)) != NULL) {
uid = pw->pw_uid;
gid = pw->pw_gid;
username = AllocCpy(bfr);
}
} else {
(void) strcpy(forgedname, header.from);
header.from[0] = '\0';
}
}
if (!header.approved[0])
Mflag = FALSE;
header.sender[0] = '\0';
if (header.subdate[0] && cgtdate(header.subdate) < 0)
header.subdate[0] = '\0';
}
if (header.ident[0] == '\0')
getident(&header);
if (forgedname[0]) {
register char *p1;
if (Mflag)
sprintf(header.path, "%s!%s",
PATHSYSNAME, username);
else if (!header.path[0]) {
if ((p1 = rindex(forgedname, '@')) == NULL)
(void) strcpy(header.path, forgedname);
else {
*p1 = '\0';
(void) sprintf(header.path, "%s!%s",
p1+1, forgedname);
*p1 = '@';
}
if ((p1 = strpbrk(header.path, " (<")) != NULL)
*p1 = '\0';
}
if (!Mflag && !strpbrk(forgedname, "@ (<"))
(void) sprintf(header.from,"%s@%s",
forgedname, FROMSYSNAME);
else
(void) strncpy(header.from, forgedname, BUFLEN);
(void) sprintf(header.sender, "%s@%s",
username, FROMSYSNAME);
} else {
gensender(&header, username);
}
#ifdef MYORG
if (header.organization[0] == '\0' && !Mflag &&
header.sender[0] == '\0') {
strncpy(header.organization, MYORG, BUFLEN);
if (STRNCMP(header.organization, "Frobozz", 7) == 0)
header.organization[0] = '\0';
if (ptr = getenv("ORGANIZATION"))
strncpy(header.organization, ptr, BUFLEN);
/*
* Note that the organization can also be turned off by
* setting it to the null string, either in MYORG or
* $ORGANIZATION in the environment.
*/
if (header.organization[0] == '/') {
mfd = fopen(header.organization, "r");
if (mfd) {
(void) fgets(header.organization, sizeof header.organization, mfd);
(void) fclose(mfd);
} else {
logerr("Couldn't open %s",
header.organization);
header.organization[0] = '\0';
}
ptr = index(header.organization, '\n');
if (ptr)
*ptr = '\0';
}
}
#endif /* MYORG */
}
/* Authorize newsgroups. */
if (mode == PROC) {
#ifdef NFSCLIENT
mfd = mailhdr((struct hbuf *)NULL, "Improper use of INEWS");
if (mfd != NULL) {
fprintf(mfd,"System: %s\n\nINEWS is running improperly as RNEWS on slave NFS site by user %s.\n", LOCALSYSNAME, username);
(void) mclose(mfd);
exit(1);
}
#else /* !NFSCLIENT */
checkbatch();
if (infpbuf == NULL) { /* make sure do buffered reads */
infpbuf = malloc((unsigned)BUFSIZ);
if (infpbuf != NULL)
setbuf(infp, infpbuf);
}
(void) signal(SIGHUP, SIG_IGN);
(void) signal(SIGINT, SIG_IGN);
(void) signal(SIGQUIT, SIG_IGN);
header.ident[0] = '\0';
if (hread(&header, infp, TRUE) == NULL)
xerror("%s: Inbound news is garbled", filename);
input(bfr[0] != '\n');
}
/* always check history */
if (history(&header)) {
log("Duplicate article %s rejected. Path: %s",
header.ident, header.path);
xxit(0);
#endif /* !NFSCLIENT */
}
/* Easy way to make control messages, since all.all.ctl is unblessed */
if (mode != PROC && PREFIX(header.title, "cmsg ") && header.ctlmsg[0] == 0)
(void) strcpy(header.ctlmsg, &header.title[5]);
is_ctl = mode != CREATENG &&
(ngmatch(header.nbuf, "all.all.ctl,") || header.ctlmsg[0]);
#ifdef DEBUG
fprintf(stderr,"is_ctl set to %d\n", is_ctl);
#endif
if (mode != CREATENG) {
if (!*header.title)
error("No title, ng %s from %s", header.nbuf,
header.from);
if (!*header.nbuf)
(void) strcpy(header.nbuf, DFLTNG);
}
if (mode <= UNPROC) {
#ifdef FASCIST
if (uid && uid != ROOTID && fascist(username, header.nbuf))
xerror("User %s is not authorized to post to newsgroup %s",
username, header.nbuf);
#endif /* FASCIST */
#ifndef NFSCLIENT
ctlcheck();
#endif /* !NFSCLIENT */
}
#ifndef NFSCLIENT
if (mode == CREATENG)
createng();
#endif /* !NFSCLIENT */
/* Determine input. */
if (mode != PROC)
input(FALSE);
if (header.intnumlines == 0 && !is_ctl)
error("%s rejected: no text lines", header.ident);
dates(&header);
/* Do the actual insertion. */
insert();
/* NOTREACHED */
}
/* check for existence of file */
static chkfile(f)
char *f;
{
FILE *mfd; /* mail file file-descriptor */
char cbuf[BUFLEN]; /* command buffer */
#ifndef NFSCLIENT
if (rwaccess(f))
return; /* everything is ok */
mfd = mailhdr((struct hbuf *)NULL,
exists(f) ? "Unwritable files!" : "Missing files!");
#else /* NFSCLIENT */
if (exists(f))
return; /* everything is ok */
mfd = mailhdr((struct hbuf *)NULL, "Missing files!");
#endif /* NFSCLIENT */
if (mfd == NULL)
return;
putc('\n', mfd);
fprintf(mfd, "System: %s\n\nThere was a problem with %s!!\n",
LOCALSYSNAME, f);
#ifndef NFSCLIENT
(void) sprintf(cbuf, "touch %s;chmod 666 %s", f, f);
(void) system(cbuf);
if (rwaccess(f))
fprintf(mfd, "The problem has been taken care of.\n");
else
fprintf(mfd, "Corrective action failed - check suid bits.\n");
#else /* NFSCLIENT */
fprintf(mfd, "Corrective action must take place on \"%s\", the master NFS news system.\n", NFSSYSNAME);
#endif /* NFSCLIENT */
(void) mclose(mfd);
}
#ifndef DBM
/* check for existence of directory */
static chkdir(d)
char *d;
{
FILE *mfd; /* mail file file-descriptor */
char dir[BUFLEN]; /* holds directory name */
sprintf(dir, "%s.d", d);
if (eaccess(dir, 07) == 0)
return; /* everything is ok */
mfd = mailhdr((struct hbuf *)NULL,
exists(dir) ? "Unwritable directories" : "Missing directories");
if (mfd == NULL)
return;
putc('\n', mfd);
fprintf(mfd, "System: %s\n\nThere was a problem with %s!\n",
LOCALSYSNAME, dir);
#ifndef NFSCLIENT
(void) mkdir(dir, 0775);
if (eaccess(dir, 07) == 0)
fprintf(mfd, "The problem has been taken care of.\n");
else
fprintf(mfd, "Corrective action failed - check suid bits.\n");
#else /* NFSCLIENT */
fprintf(mfd, "Corrective action must take place on \"%s\", the master NFS news system.\n", NFSSYSNAME);
#endif /* NFSCLIENT */
(void) mclose(mfd);
}
/*
* This version of access checks against effective uid and effective gid
*/
eaccess(name, mode)
register char *name;
register int mode;
{
struct stat statb;
int euserid = geteuid();
int egroupid = getegid();
if (stat(name, &statb) == 0) {
if (euserid == 0) {
if ((statb.st_mode&S_IFMT) != S_IFREG || mode != 1)
return 0;
/* root needs execute permission for someone */
mode = (S_IEXEC|(S_IEXEC>>3)|(S_IEXEC>>6));
}
else if (euserid == statb.st_uid)
mode <<= 6;
else if (egroupid == statb.st_gid)
mode <<= 3;
#ifdef BSD4_2
/* in BSD4_2 you can be in several groups */
else {
int groups[NGROUPS];
register int n;
n = getgroups(NGROUPS,groups);
while(--n >= 0) {
if(groups[n] == statb.st_gid) {
mode <<= 3;
break;
}
}
}
#endif /* BSD4_2 */
if (statb.st_mode & mode)
return 0;
}
return -1;
}
#endif /* DBM */
#ifndef NFSCLIENT
dospool(batchcmd, dolhwrite)
char *batchcmd;
int dolhwrite;
{
register int c;
register FILE *sp;
register struct tm *tp;
time_t t;
char buf[BUFLEN], sfile[BUFLEN];
extern struct tm *gmtime();
(void) sprintf(sfile, "%s/.tmp/spXXXXXX", SPOOL);
MKTEMP(sfile);
sp = xfopen(sfile, "w");
if (batchcmd != NULL) {
if (not_here[0] != '\0')
fprintf(sp, "%s -x %s\n", batchcmd, not_here);
else
fprintf(sp, "%s\n", batchcmd);
} else
if (not_here[0] != '\0')
fprintf(sp, "#! inews -x %s -p\n", not_here);
if (dolhwrite)
lhwrite(&header, sp);
while ((c = getc(infp)) != EOF)
putc(c, sp);
fclose(sp);
(void) time(&t);
tp = gmtime(&t);
/* This file name "has to" be unique (right?) */
#ifdef USG
(void) sprintf(buf, "%s/.rnews/%2.2d%2.2d%2.2d%2.2d%2.2d%x",
#else
#ifdef VMS
/* Eunice doesn't like dots in directory names */
(void) sprintf(buf, "%s/+rnews/%02d%02d%02d%02d%02d%x",
#else /* V7 */
(void) sprintf(buf, "%s/.rnews/%02d%02d%02d%02d%02d%x",
#endif /* V7 */
#endif /* VMS */
SPOOL,
tp->tm_year, tp->tm_mon+1, tp->tm_mday,
tp->tm_hour, tp->tm_min, getpid());
#ifdef IHCC
log("Spooling %s into %s", header.ident, (rindex(buf,'/') + 1));
#endif /* IHCC */
if (LINK(sfile, buf) < 0) {
char dbuf[BUFLEN];
#ifdef VMS
sprintf(dbuf, "%s/+rnews", SPOOL);
#else /* !VMS */
sprintf(dbuf, "%s/.rnews", SPOOL);
#endif /* !VMS */
if (mkdir(dbuf, 0777&~N_UMASK) < 0)
xerror("Cannot mkdir %s: %s", dbuf, errmsg(errno));
if (LINK(sfile, buf) < 0)
xerror("Cannot link(%s,%s): %s", sfile, buf,
errmsg(errno));
}
(void) UNLINK(sfile);
xxit(0);
/* NOTREACHED */
}
/*
* Create a newsgroup
*/
createng()
{
register char *cp;
/*
* Only certain users are allowed to create newsgroups
*/
if (uid != ROOTID && uid != duid && uid) {
logerr("Please contact one of the local netnews people");
xerror("to create group \"%s\" for you", header.ctlmsg);
}
if (header.distribution[0] == '\0')
#ifdef ORGDISTRIB
strcpy(header.distribution, ORGDISTRIB);
#else /* !ORGDISTRIB */
strcpy(header.distribution, "local");
#endif /* !ORGDISTRIB */
(void) strcpy(header.nbuf, header.ctlmsg);
if ((cp=index(header.nbuf, ' ')) != NULL)
*cp = '\0';
if (header.approved[0] == '\0')
(void) sprintf(header.approved, "%s@%s",
username, FROMSYSNAME);
(void) sprintf(bfr, "%s/inews -n %s.ctl -c newgroup %s -d %s -a \"%s\"",
LIB, header.nbuf, header.ctlmsg, header.distribution,
header.approved);
if (tty) {
printf("Please type in a paragraph describing the new newsgroup.\n");
printf("End with control D as usual.\n");
}
printf("%s\n", bfr);
(void) fflush(stdout);
(void) system(bfr);
exit(0);
/*NOTREACHED*/
}
char firstbufname[BUFLEN];
/*
* Link ARTICLE into dir for ngname and update active file.
*/
long
localize(ngname)
char *ngname;
{
char afline[BUFLEN];
long ngsize;
long fpos;
int e;
char *cp;
lock();
(void) rewind(actfp); clearerr(actfp);
for(;;) {
fpos = ftell(actfp);
if (fgets(afline, sizeof afline, actfp) == NULL) {
unlock();
logerr("Can't find \"%s\" in active file", ngname);
return FALSE; /* No such newsgroup locally */
}
if (PREFIX(afline, ngname)) {
(void) sscanf(afline, "%s %ld", bfr, &ngsize);
if (STRCMP(bfr, ngname) == 0) {
if (ngsize < 0 || ngsize > 9999998L) {
logerr("found bad ngsize %ld ng %s, setting to 1", ngsize, bfr);
ngsize = 1;
}
break;
}
}
}
for (;;) {
cp = dirname(ngname);
(void) sprintf(bfr, "%s/%ld", cp, ngsize+1);
#ifdef VMS
/*
* The effect of this code is to store the article in the first
* newsgroup's directory and to put symbolic links elsewhere.
* If this is the first group, firstbufname is not yet filled
* in. It should be portable to other link-less systems.
* epimass!jbuck
*/
if (firstbufname[0]) {
if (vmslink(firstbufname, bfr) == 0)
break;
} else if (rename(ARTICLE, bfr) == 0)
break;
#else /* !VMS */
if (link(ARTICLE, bfr) == 0)
break;
#endif /* !VMS */
if (!exists(cp))
mknewsg(cp, ngname);
#ifdef VMS
if (firstbufname[0]) {
if (vmslink(firstbufname, bfr) == 0)
break;
} else if (rename(ARTICLE, bfr) == 0)
break;
#else /* !VMS */
if (link(ARTICLE, bfr) == 0)
break;
#endif /* !VMS */
e = errno; /* keep log from clobbering it */
log("Cannot install article as %s: %s", bfr, errmsg(errno));
if (e != EEXIST) {
logerr("Link into %s failed (%s); check dir permissions.",
bfr, errmsg(e));
unlock();
return FALSE;
}
ngsize++;
}
/*
* Keep track of destination file names so we can delete
* the article files if the write-out fails.
*/
cp = malloc(strlen(bfr)+1);
(void) strcpy(cp, bfr);
artlinks[linkcount++] = cp;
/*
* This works around a bug in the 4.1bsd stdio
* on fseeks to non even offsets in r+w files
*/
if (fpos&1)
(void) rewind(actfp);
(void) fseek(actfp, fpos, 0);
/*
* Has to be same size as old because of %07d.
* This will overflow with 9,999,999 articles.
*/
fprintf(actfp, "%s %07ld", ngname, ngsize+1);
#if defined(USG) || defined(MG1)
/*
* U G L Y K L U D G E
* This utter piece of tripe is the only way I know of to get
* around the fact that ATT BROKE standard IO in System 5.2.
* Basically, you can't open a file for "r+" and then try and
* write to it. This works on all "real" USGUnix systems, It will
* probably break on some obscure look alike that doesnt use the
* real ATT stdio.h
* Don't blame me, blame ATT. stdio should have already done the
* following line for us, but it doesn't
* also broken in WCW MG-1 42nix 2.0
*/
actfp->_flag |= _IOWRT;
#endif /* USG */
(void) fflush(actfp);
if (ferror(actfp))
xerror("Active file write failed");
unlock();
if (firstbufname[0] == '\0')
(void) strcpy(firstbufname, bfr);
(void) sprintf(bfr, "%s/%ld ", ngname, ngsize+1);
addhist(bfr);
return ngsize+1;
}
#endif /* !NFSCLIENT */
/*
* Localize for each newsgroup and broadcast.
*/
insert()
{
register char *ptr;
register FILE *tfp;
register int c;
struct srec srec; /* struct for sys file lookup */
int is_invalid = FALSE;
int junked = FALSE;
int exitcode = 0;
long now;
#ifdef DOXREFS
register char *nextref = header.xref;
#endif /* DOXREFS */
/* Clean up Newsgroups: line */
if (!is_ctl && mode != CREATENG) {
#ifdef MODFILEONLY
if (mode <= UNPROC) header.approved[0] = '\0';
#endif /* MODFILEONLY */
is_invalid =
ngfcheck(username, mode == PROC, header.approved[0] != '\0');
}
sprintf(bfr, "%ld", time(&now));
addhist(bfr);
if (header.expdate[0]) {
sprintf(bfr,"~%ld",(long) cgtdate(header.expdate));
addhist(bfr);
}
addhist("\t");
log("%s %s ng %s subj '%s' from %s", spool_news != DONT_SPOOL
? "queued" : (mode==PROC ? "received" : "posted"),
header.ident, header.nbuf, header.title, header.from);
/* Write article to temp file. */
MKTEMP(ARTICLE);
tfp = xfopen(ARTICLE, "w");
linkcount = 0;
#ifndef NFSCLIENT
if (is_invalid) {
logerr("%s: No valid newsgroups found, moved to junk",
header.nbuf);
if (localize("junk")) {
savehist(histline);
junked = TRUE;
}
exitcode = 1;
goto writeout;
}
#ifdef ZAPNOTES
if (STRNCMP(header.title, "Re: Orphaned Response", 21) == 0) {
logerr("Orphaned Response, moved to junk");
if (localize("junk")) {
savehist(histline);
/*
junked = TRUE;
*/
}
exitcode = 1;
goto writeout;
}
#endif /* ZAPNOTES */
if (time((time_t *)0) > (cgtdate(header.subdate) + HISTEXP) ){
logerr("Article too old, moved to junk");
if (localize("junk")) {
savehist(histline);
junked = TRUE;
}
exitcode = 1;
goto writeout;
}
#endif /* !NFSCLIENT */
if (is_mod[0] != '\0' /* one of the groups is moderated */
&& header.approved[0] == '\0') { /* and unapproved */
if (is_mod_file_okay) {
(void) sprintf(header.approved, "%s@%s",
username, FROMSYSNAME);
} else {
struct hbuf mhdr;
FILE *mfd, *mhopen();
register char *p;
char modadd[BUFLEN], *replyname();
#ifndef NFSCLIENT
#ifdef DONTFOWARD
if(mode == PROC) {
logerr("Unapproved article in moderated group %s",
is_mod);
if (localize("junk"))
savehist(histline);
goto writeout;
}
#endif /* DONTFORWARD */
#endif /* !NFSCLIENT */
fprintf(stderr,"%s is moderated and may not ", is_mod);
fprintf(stderr,"be posted to directly.\nYour ");
fprintf(stderr, "article is being mailed to the ");
fprintf(stderr, "moderator who will post it for ");
fprintf(stderr, "you.\n");
/* Let's find a path to the backbone */
sprintf(bfr, "%s/mailpaths", LIB);
mfd = xfopen(bfr, "r");
do {
if (fscanf(mfd, "%s %s", bfr, modadd) != 2)
xerror("Can't find backbone in %s/mailpaths",
LIB);
} while (STRCMP(bfr, "backbone") != 0
&& !ngmatch(is_mod, bfr));
(void) fclose(mfd);
/* fake a header for mailhdr */
mhdr.from[0] = '\0';
mhdr.replyto[0] = '\0';
p = is_mod;
while (*++p)
if (*p == '.')
*p = '-';
sprintf(mhdr.path, modadd, is_mod);
mfd = mhopen(&mhdr);
if (mfd == NULL)
xerror("Can't send mail to %s", mhdr.path);
fprintf(mfd, "To: %s\n", replyname(&mhdr));
lhwrite(&header, mfd);
putc('\n', mfd);
while ((c = getc(infp)) != EOF)
putc(c, mfd);
mclose(mfd);
log("Article mailed to %s", mhdr.path);
xxit(0);
}
}
#ifndef NFSCLIENT
if (mode != PROC && spool_news != DONT_SPOOL) {
if (spool_news != EXPIRE_RUNNING
&& ngmatch(header.nbuf,"to.all.ctl"))
spool_news = DONT_SPOOL;
if (spool_news != DONT_SPOOL) {
fprintf(stderr,
"Your article has been spooled for later processing.\n");
dospool("#! inews -S -h", TRUE);
/* NOT REACHED */
}
}
#endif /* !NFSCLIENT */
if (is_ctl) {
exitcode = control(&header);
#ifndef NFSCLIENT
if (exitcode != 0)
savehist(histline);
else
localize("control");
} else {
if (s_find(&srec, LOCALPATHSYSNAME) == FALSE) {
logerr("Cannot find my name '%s' in %s",
LOCALPATHSYSNAME, SUBFILE);
strcpy(srec.s_name, "ME-dummy");
srec.s_nosend = NULL;
strcpy(srec.s_nbuf, "all");
srec.s_flags[0] = '\0';
srec.s_xmit[0] = '\0';
}
#ifdef DOXREFS
(void) strncpy(nextref, PATHSYSNAME, BUFLEN);
#endif /* DOXREFS */
for (ptr = nbuf; *ptr;) {
if (ngmatch(ptr,srec.s_nbuf) || index(ptr,'.') == NULL){
#ifdef DOXREFS
while (*nextref++)
;
(void) sprintf(--nextref, " %s:%ld", ptr, localize(ptr));
#else /* !DOXREFS */
(void) localize(ptr);
#endif /* !DOXREFS */
}
while (*ptr++)
;
}
if (firstbufname[0] == '\0') {
logerr("Newsgroups in active, but not sys");
(void) localize("junk");
}
#endif /* !NFSCLIENT */
}
#ifdef DOXREFS
if (index(header.nbuf, NGDELIM) == NULL)
header.xref[0] = '\0';
#endif /* DOXREFS */
writeout:
/* Part 1 of kludge to get around article truncation problem */
if ( (c=getc(infp)) != EOF) {
ungetc(c, infp);
if (c == ' ' || c == '\t') {
header.intnumlines++;
(void) sprintf(header.numlines, "%d",
header.intnumlines);
}
}
/* End of part 1 */
if (header.expdate[0] != '\0' && mode != PROC) {
/* Make sure it's fully qualified */
long t = cgtdate(header.expdate);
strcpy(header.expdate, arpadate(&t));
}
lhwrite(&header, tfp);
if ((c = getc(infp)) != EOF) {
/* Part 2 of kludge to get around article truncation problem */
if (c == ' ' || c == '\t' ) {
putc('\n', tfp);
if (controlmail)
putc('\n', controlmail);
}
/* End of part 2 */
ungetc(c, infp);
while (fgets(bfr, BUFLEN, infp) != NULL) {
fputs(bfr, tfp);
if (controlmail)
fputs(bfr, controlmail);
}
if (bfr[strlen(bfr)-1] != '\n') {
putc('\n', tfp);
if (controlmail)
putc('\n', controlmail);
}
}
if (controlmail)
(void) mclose(controlmail);
controlmail = NULL;
fflush(tfp);
if (ferror(tfp))
{
(void) UNLINK(ARTICLE);
for (c = 0; c < linkcount; c++)
(void) UNLINK(artlinks[c]);
xerror("Write failed for temp file");
}
else
{
for (c = 0; c < linkcount; c++)
free(artlinks[c]);
}
(void) fclose(tfp);
(void) fclose(infp);
if (infpbuf) {
(void) free(infpbuf);
infpbuf = NULL;
}
if(exitcode == 0) {
if (vflag) {
printf("%s\n", header.ident);
fflush(stdout);
}
/* article has passed all the checks, so work in background */
if (mode != PROC) {
#ifndef NFSCLIENT
int pid;
if ((pid=fork()) < 0)
xerror("Can't fork");
else if (pid > 0)
_exit(0);
}
#ifdef SIGTTOU
(void) signal(SIGTTOU, SIG_IGN);
#endif /* SIGTTOU */
savehist(histline);
if (header.supersedes[0] != '\0') {
char *av[2];
av[0] = "cancel";
av[1] = header.supersedes;
c_cancel(2, av);
}
broadcast(mode==PROC);
#else /* NFSCLIENT */
int status;
char command[LBUFLEN];
(void) sprintf(command, NFSCMDFORMAT, NFSCMDARGS);
status = system(command);
(void) unlink(ARTICLE);
exit(status);
}
#endif /* NFSCLIENT */
}
xxit((mode == PROC && filename[0] == '\0') ? 0 :
(exitcode < 0 || junked ? 0 : exitcode));
}
input(usegunk)
{
register char *cp;
register int c;
register int empty = TRUE;
FILE *tmpfp;
int consec_newlines = 0;
int linecount = 0;
int linserted = 0;
MKTEMP(INFILE);
tmpfp = xfopen(INFILE, "w");
for ( ; ; ) {
if (SigTrap)
break;
if (usegunk)
usegunk = FALSE;
else if (fgets(bfr, BUFLEN, infp) != bfr)
break;
#ifndef NFSCLIENT
if (mode == PROC) { /* zap trailing empty lines */
#ifdef ZAPNOTES
if (empty && bfr[0] == '#' && bfr[2] == ':'
&& header.nf_id[0] == '\0'
&& header.nf_from[0] == '\0' ) {
(void) strcpy(header.nf_id, bfr);
(void) nstrip(header.nf_id);
(void) fgets(bfr, BUFLEN, infp);
(void) strcpy(header.nf_from, bfr);
(void) nstrip(header.nf_from);
(void) fgets(bfr, BUFLEN, infp);
if (header.numlines[0]) {
header.intnumlines -= 2;
(void) sprintf(header.numlines, "%d", header.intnumlines);
}
/* Strip trailing " - (nf)" */
if ((cp = rindex(header.title, '-')) != NULL
&& !STRCMP(--cp, " - (nf)"))
*cp = '\0';
log("Stripped notes header on %s", header.ident);
continue;
}
#endif /* ZAPNOTES */
if (bfr[0] == '\n' ||
/* Bandage for older versions of inews */
bfr[1] == '\n' && !isascii(bfr[0])) {
consec_newlines++; /* count it, in case */
continue; /* but don't write it*/
}
/* foo! a non-empty line. write out all saved lines. */
while (consec_newlines > 0) {
putc('\n', tmpfp);
consec_newlines--;
linecount++;
}
}
#endif /* !NFSCLIENT */
if (mode != PROC && tty && STRCMP(bfr, ".\n") == 0)
break;
for (cp = bfr; c = toascii(*cp); cp++) {
if (isprint(c) || isspace(c) || c == '\b')
putc(c, tmpfp);
if (c == '\n')
linecount++;
}
if (bfr[0] == '>')
linserted++;
if (bfr[0] == '<') /* kludge to allow diff's to be posted */
linserted--;
empty = FALSE;
}
if (*filename) {
(void) fclose(infp);
if (infpbuf) {
(void) free(infpbuf);
infpbuf = NULL;
}
}
if (mode != PROC &&
index(header.nbuf,',') != NULL &&
strlen(header.followto) == 0) {
/*
* they didn't give us a followup-to
* so we'll make one for them
*/
char *comma;
/* just use the first newsgroup in the Newsgroups: line */
strcpy(header.followto, header.nbuf);
comma = index(header.followto, ',');
if (comma != NULL) { /* this should always be true! */
*comma = '\0';
}
}
if (mode != PROC &&
linecount > LNCNT && linserted > (linecount-linserted))
error("Article rejected: %s included more text than new text",
username);
if (mode != PROC && !is_ctl && header.sender[0] == '\0' && !Sflag) {
int siglines = 0;
char sbuf[BUFLEN];
(void) sprintf(bfr, "%s/%s", userhome, ".signature");
if (access(bfr, 4) == 0) {
if ((infp = fopen(bfr, "r")) == NULL) {
(void) fprintf(stderr,
"inews: \"%s\" left off (must be readable by \"inews\" owner)\n", bfr);
goto finish;
}
while (fgets(sbuf, sizeof sbuf, infp) != NULL)
if (++siglines > 4)
break;
else if (index(sbuf, '\n') == 0) {
fprintf(stderr, ".signature not included (long or unterminated line)\n");
siglines = -1;
break;
}
if (siglines > 4)
fprintf(stderr,".signature not included (> 4 lines)\n");
else if (siglines == 0)
fprintf(stderr,".signature not included (empty)\n");
else if (siglines > 0) {
rewind(infp);
fprintf(tmpfp, "-- \n"); /* To separate */
linecount++;
while ((c = getc(infp)) != EOF) {
putc(c, tmpfp);
if (c == '\n')
linecount++;
}
}
(void) fclose(infp);
}
}
finish:
if (ferror(tmpfp))
xerror("write failed to temp file");
(void) fclose(tmpfp);
if (SigTrap) {
if (tty)
fprintf(stderr, "Interrupt\n");
if (tty && !empty)
fwait(fsubr(newssave, (char *) NULL, (char *) NULL));
if (!tty)
log("Blown away by an interrupt %d", SigTrap);
xxit(1);
}
if (tty)
fprintf(stderr, "EOT\n");
fflush(stdout);
infp = fopen(INFILE, "r");
if (header.numlines[0]) {
/*
* Check line count if there's already one attached to
* the article. Could make this a fatal error -
* throwing it away if it got chopped, in hopes that
* another copy will come in later with a correct
* line count. But that seems a bit much for now.
*/
if (linecount != header.intnumlines) {
if (linecount == 0)
error("%s rejected. linecount expected %d, got 0", header.ident, header.intnumlines);
if (linecount > header.intnumlines ||
linecount+consec_newlines < header.intnumlines)
log("linecount expected %d, got %d", header.intnumlines, linecount+consec_newlines);
}
/* adjust count for blank lines we stripped off */
if (consec_newlines) {
header.intnumlines -= consec_newlines;
if (header.intnumlines < 0 )
header.intnumlines = 0; /* paranoia */
(void) sprintf(header.numlines, "%d", header.intnumlines);
}
} else {
/* Attach a line count to the article. */
header.intnumlines = linecount;
(void) sprintf(header.numlines, "%d", linecount);
}
}
#ifndef NFSCLIENT
/*
* Make the directory for a new newsgroup. ngname should be the
* full pathname of the directory. Do the other stuff too.
* The various games with setuid and chown are to try to make sure
* the directory is owned by NEWSUSR and NEWSGRP, which is tough to
* do if you aren't root. This will work on a UCB system (which allows
* setuid(geteuid()) or a USG system (which allows you to give away files
* you own with chown), otherwise you have to change your kernel to allow
* one of these things or run with your dirs 777 so that it doesn't matter
* who owns them.
*/
mknewsg(fulldir, ngname)
char *fulldir;
char *ngname;
{
#ifdef USG
register char *p;
char parent[200];
char sysbuf[200];
struct stat sbuf;
#endif /* USG */
if (ngname == NULL || !isalpha(ngname[0]))
xerror("Tried to make illegal newsgroup %s", ngname);
#ifdef USG
/*
* If the parent is 755 the setuid(getuid)
* will fail, and since mkdir is suid, and our real uid is random,
* the mkdir will fail. So we have to temporarily chmod it to 777.
*/
(void) strcpy(parent, fulldir);
while (p = rindex(parent, '/')) {
*p = '\0';
if (stat(parent, &sbuf) == 0) {
(void) chmod(parent, 0777);
break;
}
}
#endif /* USG */
/* Create the directory */
mkparents(fulldir);
if (mkdir(fulldir, 0777) < 0)
xerror("Cannot mkdir %s: %s", fulldir, errmsg(errno));
#ifdef USG
/*
* Give away the directories we just created which were assigned
* our real uid.
*/
(void) setuid(uid);
(void) chown(fulldir, duid, dgid);
(void) strcpy(sysbuf, fulldir);
while (p = rindex(sysbuf, '/')) {
*p = '\0';
/* stop when get to last known good parent */
if (STRCMP(sysbuf, parent) == 0)
break;
(void) chown(sysbuf, duid, dgid);
}
(void) setuid(duid);
(void) chmod(parent, (int)sbuf.st_mode); /* put it back */
#endif /* USG */
log("make newsgroup %s in dir %s", ngname, fulldir);
}
/*
* If any parent directories of this dir don't exist, create them.
*/
mkparents(dname)
char *dname;
{
char buf[200];
register char *p;
(void) strcpy(buf, dname);
p = rindex(buf, '/');
if (p)
*p = '\0';
if (exists(buf))
return;
mkparents(buf);
if (mkdir(buf, 0777) < 0)
xerror("Can not mkdir %s: %s", buf, errmsg(errno));
}
dounspool()
{
register DIR *dirp;
register DIRECTORY_STRUCT *dir;
register int foundsome;
int pid, status, ret;
char spbuf[BUFLEN];
#ifdef LOCKF
FILE* LockFd;
#endif /* LOCKF */
#if !defined(LOCKF) && !defined(BSD4_2)
struct stat stbuf;
#endif /* !LOCKF && ! BSD4_2 */
#ifdef VMS
sprintf(spbuf, "%s/+rnews", SPOOL);
#else /* !VMS */
sprintf(spbuf, "%s/.rnews", SPOOL);
#endif /* !VMS */
if (chdir(spbuf) < 0)
xerror("chdir(%s):%s", spbuf, errmsg(errno));
dirp = opendir(".");
if (dirp == NULL) /* Boy are things screwed up */
xerror("opendir can't open .:%s", errmsg(errno));
#ifdef LOCKF
LockFd = xfopen(SEQFILE, "r+w");
/* The lseek is kludge for systems with mandatory locking */
lseek(fileno(LockFd), 512L, 0);
if (lockf(fileno(LockFd), F_TLOCK, 0L) < 0) {
if (errno != EAGAIN && errno != EACCES)
#else /* !LOCKF */
#ifdef BSD4_2
if (flock(dirp->dd_fd, LOCK_EX|LOCK_NB) < 0) {
if (errno != EWOULDBLOCK)
#else /* V7 */
strcat(spbuf, ".lock");
sprintf(bfr, "%s.tmp", spbuf);
(void) close(creat(bfr, 0666));
ret = LINK(bfr, spbuf);
status = errno;
(void) UNLINK(bfr);
errno = status;
/* assume a dead lock if the active file is over 12 hours old */
if (ret < 0 &&
(errno != EEXIST ||
(stat(bfr, &stbuf) == 0 &&
(time((char *)0) - stbuf.st_mtime) < DAYS/2))) {
if (errno != EEXIST)
#endif /* V7 */
#endif /* !LOCKF */
xerror("Can't lock %s: %s", spbuf, errmsg(errno));
xxit(3); /* another rnews -U is running */
}
do {
foundsome = 0;
while ((dir=readdir(dirp)) != NULL) {
if (dir->d_name[0] == '.')
continue;
#ifdef IHCC
log("Unspooling from %s", dir->d_name);
#endif /* IHCC */
if ((pid=vfork()) == -1)
xerror("Can't fork: %s", errmsg(errno));
if (pid == 0) {
#ifdef LOGDIR
char bufr[BUFSIZ];
sprintf(bufr, "%s/%s", logdir(HOME), RNEWS);
execl(bufr, "rnews", "-S", "-p", dir->d_name,
(char *) NULL);
#else /* !LOGDIR */
execl(RNEWS, "rnews", "-S", "-p", dir->d_name,
(char *) NULL);
#endif /* !LOGDIR */
_exit(1);
}
while ((ret=wait(&status)) != pid && ret != -1)
/* continue */;
if (((status>>8)&0177) == 42) {
/* expire has started up, shutdown rnews -U */
break;
}
if (status != 0) {
sprintf(bfr, "../.bad/%s", dir->d_name);
(void) LINK(dir->d_name, bfr);
logerr("rnews failed, status %ld. Batch saved in %s/.bad/%s",
(long)status, SPOOL, dir->d_name);
}
(void) unlink(dir->d_name);
foundsome++;
}
rewinddir(dirp);
} while (foundsome); /* keep rereading the directory until it's empty */
#ifndef LOCKF
#ifndef BSD4_2
(void) UNLINK(spbuf);
#endif
#endif
xxit(0);
}
#endif /* !NFSCLIENT */
#ifdef MINFREE
#include <ustat.h>
/*
* determine if there is enough free space on the device
* return 0 if there is and
* anything appropriate if there is not
* written by Stan Barber (sob@bcm.tmc.edu)
*/
space()
{
struct stat file;
struct ustat device;
if (stat(SPOOLDIR,&file))
return 1; /* can't stat spool */
if (ustat(file.st_dev, &device))
return 1; /* can't stat the device */
if(device.f_tfree < MINFREE)
return 1;
return 0;
}
#else
int space()
{
/* I'll figure this out for BSD some other time */
return(0);
}
#endif /* MINFREE */