|
|
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 n
Length: 23526 (0x5be6)
Types: TextFile
Names: »nntplink.c«
└─⟦9ae75bfbd⟧ Bits:30007242 EUUGD3: Starter Kit
└─⟦f91e15335⟧ »EurOpenD3/news/nntp/nntplink2.0.0.tar.Z«
└─⟦2c70c5e6b⟧
└─⟦this⟧ »nntplink.c«
/** nntplink - transmit netnews articles across the internet with nntp,
** holding the link open semi-permanently.
**
** Derived from nntpxmit.c (by Erik Fair) by Warren Lavallee.
**
** Copyright (c) 1989 Samsung Software America, Inc. All rights reserved.
**
** Permission is hereby granted to copy, reproduce, redistribute or
** otherwise use this software as long as: (1) there is no monetary
** profit gained specifically from the use or reproduction of this
** software, (2) it is not sold, rented, traded, or otherwise marketed,
** (3) the above copyright notice and this paragraph is included
** prominently in an copy made, and (4) that the name of Samsung
** is not used to endorse or promote products derived from this software
** without the specific prior written permission of Samsung Software America.
** THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
** IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
** WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
**
**
** Version history:
** 1.01.0 - 11-02-89 - SVR3 compatible?
** 1.01.1 - 11-03-89 - Cnews batchfile compatibility (coolidge@cs.uiuc.edu)
** 1.01.2 - 11-05-89 - Removed -x option. It is always set now.
** Very small change to safecopy().
** 1.01.3 - 11-08-89 - Fix dprintf bug (big bug) <fletcher@cs.utexas.edu>
** 1.01.4 - 11-10-89 - Added HP/UX support. <icsu6000@cs.montana.edu>
** 1.10.0 - 11-11-89 - Initial public release
** 1.10.2 - 11-15-89 - Fixes major bug (dropped articles)---
** linked lists removed.
** - 11-19-89 - Added -L and -C options, reorganized stats
** gathering. <lamy@ai.utoronto.ca>
** 1.10.3 - 11-20-89 - Removed one-shot feature-- doesn't apply.
** Added -S option <coolidge@cs.uiuc.edu>
** 1.10.4 - 11-23-89 - Added -I (idling time out) <lamy@ai.utoronto.ca>
** 1.10.5 - 11-27-89 - Split up nntplink.c to several smaller files.
** Message-id is now save in rewrite()
** Code to check C-news .vs. B-news (spots cfg
** errors)
**
** Contributors/Testers:
** karl@tut.cis.ohio-state.edu (Karl Kleinpaste)
** fletcher@cs.utexas.edu (Fletcher Mattox)
** mcooper@usc.edu (Micheal Cooper)
** alden@gem.mps.ohio-state.edu (Dave Alden)
** icsu6000@caesar.cs.montana.edu (Mathisen)
** lamy@ai.utoronto.ca (Jean-Francois Lamy)
** coolidge@cs.uiuc.edu (John Coolidge)
**
** Testers:
** dubois@uakari.primate.wisc.edu (Paul Dubois)
** coolidge@casca.cs.uiuc.edu (John Coolidge)
** lloyd@aplcen.jhu.edu (Lloyd W. Taylor)
** tale@pawl.rpi.edu (David C Lawrence)
** mb@rex.cs.tulane.edu (Mark Benard)
** asp@uunet.uu.net (Andrew Partan)
**
** OPERATING SYSTEMS:
** Pyramid DualPort OSx4.4c
** Dynix 3.0 (Symmetry + Balance)
** HP-UX 6.01
** Sun OS {4.0,3.5}
** Ultrix 3.?
** 4.3tahoe (uVAX III)
**
**/
#include "conf.h"
#include <stdio.h>
#include <errno.h>
#include <ctype.h>
#include <sys/types.h>
#ifdef BSD4_2
#include <sys/time.h>
#include <sys/resource.h>
#include <sys/ioctl.h>
#include <sys/file.h>
#else
#include <sys/times.h>
extern time_t time();
#endif BSD4_2
#include <fcntl.h>
#include <signal.h>
#ifdef USG
#include "sysexits.h"
#else
#include <sysexits.h>
#endif
#ifdef SYSLOG
#include <syslog.h>
#endif SYSLOG
#include "nntp.h"
#ifdef BSD4_2
#include <sys/wait.h>
#endif
#include <sys/stat.h>
#define MAXFNAME BUFSIZ /* maximum filename size - big enough? */
#define FCLOSE(fp) (void) fclose(fp); (fp) = (FILE *)NULL
FILE *getfp();
char *errmsg();
void requeue();
void catchsig();
void logstats();
void log();
void usage();
int interrupted();
void waitingfor();
/*
** Globals that certain things need.
**
** Various subroutines want the program name to report errors.
** The queue file, queue file pointer and current article name are
** there to write out the state of the queue file from a signal handler
** (that is, the list of unsent and (possibly) failed articles) so
** that when next we try sending to a given remote site, we don't send
** stuff we've already sent.
*/
char *Pname; /* this program's invocation name */
char *Host; /* current remote host */
char *TQfile; /* BOGUS HACK - BETA RELEASE ONLY */
char Qfile[MAXFNAME]; /* current queue file we're operating on */
FILE *Qfp; /* the (FILE *) for above */
char Article[MAXFNAME]; /* current article filename */
char FailedArticle[MAXFNAME];/* article to requeue */
int resetstats = TRUE; /* true after a logstats() */
unsigned short connected = 0;
char nntpfile[MAXFNAME];
#ifdef CNEWS
int cnews = 1;
#else
int cnews = 0;
#endif
char *safecopy();
int Use_Log_File = FALSE;
int In_Log_File = FALSE;
char logline[MAXLOGLENGTH] = "";
char old_logline[MAXLOGLENGTH] = "";
char orig_Qfile[MAXFNAME];
char orig_nntpfile[MAXFNAME];
char sysname[MAXSYSNAME];
/*
** Some flags, toggled by arguments
*/
#define TOGGLE(boolean) (boolean) = !(boolean)
char Debug = FALSE;
char Report_Stats = TRUE;
char ReQueue_Fails = TRUE;
/*
** Numeric arguments
*/
int Close_After=CLOSE_AFTER; /* close connection to remote at next
pause if we've offered this many
articles since last pause */
int Log_After = LOG_AFTER; /* log stats at next pause if we've
proposed this many aritcles since
last pause */
int Sleep_Time = SLEEP_INT;
/* Sleep Sleep_Time seconds between
checks of the queue file. */
char CheckIdleTimeout = FALSE;
long IdleTimeOut; /* if we've been waiting for batch file
for longer than this many seconds,
close link while waiting */
char CheckExitTimeout = FALSE;
long ExitTimeOut;
char *USAGE = "usage: nntplink [-d][-s][-r][-T][-F][-D][-Sn][-Cn][-Ln][-In][-En][-Xsysname] hostname|hostname:file [...]";
char *Fmt = "%s localhost %s[%d]: %s\n";
char *E_fopen = "fopen(%s, \"%s\"): %s";
char *E_unlk = "unlink(%s): %s";
#ifdef USELOG
char *NNTPlog = USELOG; /* yet another external log file */
FILE *Logfp = (FILE *)NULL;
int fd;
#endif USELOG
struct {
u_long offered;
u_long accepted;
u_long rejected;
u_long failed;
u_long since_close;
} Stats = {0L, 0L, 0L, 0L, 0L};
double Tbegin, Tend; /* transfer timestamps */
double ouser = 0.0, osys = 0.0;
double user, sys;
extern int errno;
extern int strncmp();
extern char *rindex();
extern char *index();
extern char *mktemp();
extern char *strcpy();
#ifdef USG
void
bzero(s, l)
register caddr_t s;
register int l;
{
while(l-- > 0) *s++ = 0;
}
#endif USG
extern char *compiled, *version;
/*
** Former parts of main(), now externals.
*/
int i;
int transport = T_IP_TCP; /* default is IP/TCP */
#ifdef USELOG
char *amode = "a";
#endif USELOG
#ifdef BSD4_2
struct timeval tod;
struct timezone tz;
#endif BSD4_2
main(ac, av)
int ac;
char *av[];
{
#ifdef BSD4_2
(void) gettimeofday(&tod, &tz);
Tend = Tbegin = tod.tv_sec + (double)tod.tv_usec/1000000.;
#else
Tend = Tbegin = (double) time((time_t *)NULL);
#endif BSD4_2
#ifdef BATCH_DIR
chdir (BATCH_DIR);
#endif
Pname = ((Pname = rindex(av[0],'/')) ? Pname + 1 : av[0]);
if (ac < 2) {
usage();
}
#ifdef SYSLOG
/* 4.2 BSD openlog has only two args */
#ifdef LOG_LOCAL7
(void) openlog(Pname, LOG_PID, LOG_LINK);
#else
(void) openlog(Pname, LOG_PID);
#endif LOG_LOCAL_7
#endif SYSLOG
#ifdef USELOG
fd = open(NNTPlog,O_APPEND|O_CREAT|O_WRONLY);
if ((Logfp = fdopen(fd, amode)) == (FILE *)NULL) {
char buf[BUFSIZ];
sprintf(buf, E_fopen, NNTPlog, amode, errmsg(errno));
log(L_NOTICE, buf);
}
#endif USELOG
for(i = 1; i < ac; i++) {
if (av[i][0] == '-') {
switch(av[i][1]) {
case 'T':
transport = T_IP_TCP;
break;
case 'D':
transport = T_DECNET;
break;
case 'F':
transport = T_FD;
break;
case 's':
TOGGLE(Report_Stats);
break;
case 'd':
TOGGLE(Debug);
break;
case 'r':
TOGGLE(ReQueue_Fails);
break;
case 'C':
Close_After = atoi(av[i]+2);
break;
case 'L':
Log_After = atoi(av[i]+2);
break;
case 'S':
Sleep_Time = atoi(av[i]+2);
break;
case 'I':
CheckIdleTimeout = TRUE;
IdleTimeOut = atoi(av[i]+2);
break;
case 'E':
CheckExitTimeout = TRUE;
ExitTimeOut = atoi(av[i]+2);
break;
case 'X':
strcpy(sysname, " "); /* We want to make sure that we */
strcat(sysname, av[i]+2); /* don't match part of another */
strcat(sysname, " "); /* sysname, so we pad with spaces */
Use_Log_File = TRUE;
break;
case 'v':
default:
fprintf(stderr, "%s: no such option: -%c\n",
Pname, av[i][1]);
usage();
}
continue;
}
/*
** OK, it wasn't an option, therefore it must be a
** hostname, filename pair.
**
** If the user typed host::file, then it's DECNET,
** whether they remembered the "-D" option or not.
*/
Host = av[i];
if ((TQfile = index(Host, ':')) != (char *)NULL) {
if (TQfile[1] == ':') {
transport = T_DECNET;
*TQfile++ = '\0';
} else if (transport != T_FD)
transport = T_IP_TCP;
*TQfile++ = '\0';
} else
TQfile = Host;
strcpy(Qfile, TQfile);
strcpy(orig_Qfile, TQfile);
/*
* If we're not debugging, then we should fade into the
* background completely, disconnecting from the terminal,
* and shutting off signals.
*/
if (!Debug)
{
#ifdef TIOCNOTTY
int fd;
#endif
#ifdef AUTOBACKGROUND
int p;
if ((p = fork()) < 0) /* ah-oo-gah! Dive, dive! */
{
(void) fprintf(stderr, "%s: fork failed\n", Pname);
exit(1);
}
if (p != 0)
exit(0); /* parent exit, child continues */
(void) signal(SIGHUP, SIG_IGN); /* shut down signals */
(void) signal(SIGINT, SIG_IGN);
(void) signal(SIGQUIT, SIG_IGN);
#ifdef SIGTSTP
(void) signal(SIGTSTP, SIG_IGN);
#endif /* SIGTSTP */
#endif
#ifdef TIOCNOTTY
fd = open("/dev/tty", 2); /* disconnect from the tty */
if (fd >= 0)
{
(void) ioctl(fd, (int) TIOCNOTTY, (char *) 0);
(void) close(fd);
}
#endif /* TIOCNOTTY */
(void) setpgrp(0, 0);
} else {
fprintf(stderr, "%s\n", version+4);
fprintf(stderr, "%s\n", compiled+4);
fprintf(stderr, "\nConfiguration info:\n\n");
fprintf(stderr, "Host: %s Queue file: %s\n",
Host, Qfile);
fprintf(stderr, "Connection type: ");
switch (transport) {
case T_IP_TCP:
fprintf(stderr, "TCP/IP\n");
break;
case T_DECNET:
fprintf(stderr, "DECNET\n");
break;
case T_FD:
fprintf(stderr, "FD\n");
break;
default:
fprintf(stderr, "Unknown\n");
break;
}
if (Report_Stats) fprintf(stderr, "Statistics will %s.\n",
#ifdef USELOG
"be reported via UNIX file"
#else
#ifdef LOG_LINK
"be reported via 4.3BSD syslog"
#else
"not be reported"
#endif
#endif
);
if (ReQueue_Fails)
fprintf(stderr, "Failed articles will be requeued.\n");
else
fprintf(stderr, "Failed articles will NOT be requeued.\n");
if (Close_After) {
fprintf(stderr, "Connection will be closed after %d articles have been offered\n",
Close_After);
}
if (Log_After)
fprintf(stderr, "Will log stats locally after %d articles have been processed.\n",
Log_After);
else
fprintf(stderr, "Will log xfer stats after each queue file is finished.\n");
if (Sleep_Time)
fprintf(stderr, "Will sleep %d second%s between checks for queue file.\n", Sleep_Time, (Sleep_Time == 1) ? "" : "s");
if (CheckIdleTimeout)
fprintf(stderr, "Will close the connection when idle for more than %d seconds.\n",
IdleTimeOut);
if (CheckExitTimeout)
fprintf(stderr, "Will exit when idle for more than %d seconds.\n",
ExitTimeOut);
fprintf(stderr, "\n");
fflush(stderr);
}
bzero((caddr_t)&Stats, sizeof(Stats));
#ifndef DONT_WATCH
{
register ret;
int pid;
retry:
ret = fork();
if (!ret) /** child startup **/
{
sleep(2); /* allow some time for debugging msgs to flush */
#endif
while(1)
{
dprintf(stderr, "Looping forever\n");
think();
}
#ifndef DONT_WATCH
}
if (ret == -1) /** fork failed **/
{
sleep(15); /* back off */
goto retry;
}
dprintf(stderr, "Waiting for child process to die.\n");
pid = wait(0);
fprintf(stderr, "child process no longer alive.\n");
goto retry;
}
#endif
}
exit(EX_OK);
}
void
usage()
{
(void) fprintf(stderr, "%s: %s\n", Pname, USAGE);
exit(EX_USAGE);
}
think ()
{
int naptime = NAP_TIME;
catchsig(interrupted);
for (;;)
{
if (!sendnews(Host, transport, safecopy(Qfile)))
{
dprintf(stderr, "sendnews returned an error... sleeping for %d seconds...\n", naptime);
sleep(naptime);
if (naptime < 600)
naptime *= 2;
}
else
naptime = NAP_TIME;
dprintf(stderr, "Back from Sendnews. %s\n",
connected ? "Still Connected." : "Not connected");
}
}
char *
errmsg(code)
int code;
{
extern int sys_nerr;
extern char *sys_errlist[];
static char ebuf[6+5+1];
if (code > sys_nerr || code < 0) {
(void) sprintf(ebuf, "Error %d", code);
return ebuf;
} else
return sys_errlist[code];
}
/*
** strip leading and trailing spaces
*/
char *
sp_strip(s)
register char *s;
{
register char *cp;
if (s == NULL)
return(NULL);
if (*s == '\0')
return(s);
cp = &s[strlen(s) - 1];
while(cp > s && isspace(*cp))
cp--;
*++cp = '\0'; /* zap trailing spaces */
for(cp = s; *cp && isspace(*cp); cp++)
continue;
return(cp); /* return pointer to first non-space */
}
/*
** convert `s' to lower case
*/
char *
lcase(s)
register char *s;
{
register char *cp;
if (s == (char *)NULL)
return(s);
for(cp = s; *cp != '\0'; cp++)
if (isupper(*cp))
*cp = tolower(*cp);
return(s);
}
/*
** Get the message-id header field data with a minimum of fuss.
*/
char *
getmsgid(fp)
FILE *fp;
{
static char buf[BUFSIZ];
static char *msgid = "message-id";
register char *cp, *cp2;
while(fgets(buf, sizeof(buf), fp) != (char *)NULL) {
switch(buf[0]) {
case '\n':
return((char *)NULL); /* EOH, we failed */
case 'M':
case 'm':
if ((cp = index(buf, ':')) == (char *)NULL)
continue;
*cp++ = '\0';
if (strncmp(lcase(buf), msgid, sizeof(*msgid)) == 0) {
/* dump extraneous trash - umass.bitnet */
/* hope nobody quotes an '>' in a msgid */
if ((cp2 = index(cp, '>')) != (char *)NULL)
*++cp2 = '\0';
return(sp_strip(cp));
}
break;
}
}
return((char *)NULL); /* EOF, we failed */
}
#ifdef notdef /* nobody obeys the triply damned protocol anyway! */
/*
** Special characters, see RFC822, appendix D.
*/
isspecial(c)
char c;
{
char *specials = "()<>@,;:\\\".[]";
return(index(specials, c) != (char *)NULL ? TRUE : FALSE);
}
/*
** Check on the validity of an RFC822 message-id
**
** By The Book, RFC822 Appendix D.
** msg-id = "<" addr-spec ">"
** addr-spec = local-part "@" domain
** local-part = word *("." word)
** word = atom / quoted-string
** domain = sub-domain *("." sub-domain)
** sub-domain = domain-ref / domain-literal
** domain-ref = atom
** domain-literal = "[" *(dtext / quoted-pair) "]"
**
** NOTE: close reading of the RFC822 spec indicates that a fully
** qualified domain name (i.e. one with at least one dot) is
** NOT required in the domain part of the addr-spec. However,
** I've decided to be an asshole and require them, since we'll
** all die a slow death later on if I don't at this juncture.
** To disable, if you disagree with me, see the last return
** statement. - Erik E. Fair <fair@ucbarpa.berkeley.edu>
** May 30, 1986
*/
msgid_ok(id)
register char *id;
{
register Langle = FALSE;
register Rangle = FALSE;
register local_part = FALSE;
register at = FALSE;
register dot = FALSE;
/* skip up to the opening angle bracket */
if (id == (char *)NULL || (id = index(id, '<')) == (char *)NULL)
return(FALSE); /* don't waste my time! */
for(; *id != '\0'; id++) {
switch(*id) {
case '<':
if (Langle) return(FALSE);
Langle = local_part = TRUE;
break;
case '>':
if (Rangle || !Langle || !at) return(FALSE);
else Rangle = TRUE;
break;
case '@': /* should be a domain spec */
at = TRUE;
local_part = FALSE;
break;
case '.':
dot = at;
break;
case '\\':
/*
** quoted pair; this disallows NULs, but how
** many mailers would die if someone used one?
*/
if (!local_part || (*++id) == '\0') return(FALSE);
break;
case '"':
/*
** quoted string
*/
if (!local_part) return(FALSE);
do {
switch(*++id) {
case '\\':
if ((*++id) == '\0') return(FALSE);
break;
case '\r':
return(FALSE);
}
} while(*id != '\0' && *id != '"');
break;
case '[':
/*
** domain literal
*/
if (local_part) return(FALSE);
do {
switch(*++id) {
case '\\':
if ((*++id) == '\0') return(FALSE);
break;
case '\r':
return(FALSE);
}
} while(*id != '\0' && *id != ']');
break;
default:
if (!isascii(*id) || iscntrl(*id) || isspace(*id) || isspecial(*id))
return(FALSE); /* quit immediately */
break;
}
}
return(at && dot && Langle && Rangle);
}
#else notdef
/*
** Simpleton's check for message ID syntax.
** A concession to the realities of the ARPA Internet.
*/
msgid_ok(s)
register char *s;
{
register char c;
register in_msgid = FALSE;
if (s == (char *)NULL)
return(FALSE);
while((c = *s++) != '\0') {
if (!isascii(c) || iscntrl(c) || isspace(c))
return(FALSE);
switch(c) {
case '<':
in_msgid = TRUE;
break;
case '>':
return(in_msgid);
}
}
return(FALSE);
}
#endif notdef
/*
** Read the header of a netnews article, snatch the message-id therefrom,
** and ask the remote if they have that one already.
*/
ihave(fp, mesgid)
FILE *fp;
char *mesgid;
{
register int code;
register char *id;
char buf[BUFSIZ];
dprintf(stderr,"%s: entering ihave\n", Pname);fflush(stderr);
if (strlen(mesgid) > 0) {
id = mesgid;
} else {
if ((id = getmsgid(fp)) == (char *)NULL || *id == '\0') {
/*
** something botched locally with the article
** so we don't send it, but we don't break off
** communications with the remote either.
*/
sprintf(buf, "%s: message-id missing!", Article);
log(L_DEBUG, buf);
return(ERR_GOTIT);
}
strcpy(mesgid,id);
}
if (!msgid_ok(id)) {
sprintf(buf, "%s: message-id syntax error: %s", Article, id);
log(L_DEBUG, buf);
return(ERR_GOTIT);
}
sprintf(buf, "IHAVE %s", id);
Stats.offered++;
Stats.since_close++;
switch(code = converse(buf, sizeof(buf))) {
case CONT_XFER:
Stats.accepted++;
rewind(fp);
return(code);
case ERR_GOTIT:
Stats.rejected++;
return(code);
default:
strcpy(mesgid,id);
return(code);
}
}
/*
** Given that fp points to an open file containing filenames,
** open and return a file pointer to the next filename in the file.
** Don't you love indirection?
**
** Returns a valid FILE pointer or NULL if end of file.
*/
FILE *
getfp(fp, filename, fnlen, mesgid, host)
register FILE *fp;
char *filename;
register int fnlen;
char *mesgid;
char *host;
{
register FILE *newfp = (FILE *)NULL;
register char *cp;
char *mode = "r";
char buffer[255];
char shortfn[255];
char *p;
if (Stats.offered >= Log_After && Report_Stats) {
logstats();
resetstats = FALSE;
dprintf(stderr, "resetting timers\n");
Tbegin = Tend;
ouser = user;
osys = sys;
Stats.offered = Stats.accepted = Stats.rejected = Stats.failed = 0L;
}
if ((Stats.since_close >= Close_After) && connected) {
dprintf(stderr,
"%s: %d articles sent; closing link for remote stats.\n",
Pname, Stats.since_close); fflush(stderr);
goodbye(WAIT);
connected = 0;
Stats.since_close = 0L;
}
if( In_Log_File ) {
do {
do {
strcpy(old_logline, logline);
(void)my_fgets(logline, MAXLOGLENGTH, fp);
for (p = logline; *p && *p != '<'; p++);
} while( !*p || (*(p-2) == '-') || (strnindex(p, sysname, 0) == -1));
for (i = 0; *p && *p != '>'; mesgid[i++] = *p, p++);
mesgid[i++] = *p; /* go ahead and add the ">" */
mesgid[i] = '\0';
for (p += 2, i = 0; *p && (*p !=' '); shortfn[i++] = *p, p++);
shortfn[i] = '\0';
strcpy(filename, SPOOL_DIR);
strcat(filename, shortfn);
dprintf(stderr, "fn=%s, id=%s\n", filename, mesgid);
if ((newfp = fopen(filename, mode)) == (FILE *)NULL) {
/*
** The only permissible error is `file non-existant'
** anything else indicates something is seriously
** wrong, and we should go away to let the shell
** script clean up.
*/
if (errno != ENOENT) {
char buf[BUFSIZ];
sprintf(buf, E_fopen, filename, mode, errmsg(errno));
/*
log(L_WARNING, buf);
*/
goodbye(DONT_WAIT);
exit(EX_OSERR);
}
}
} while (newfp == (FILE *)NULL);
} else while(newfp == (FILE *)NULL) {
if (fgets(filename, fnlen, fp) == (char *)NULL) {
dprintf(stderr,"%s: getfp: at EOF\n", Pname);
/* return((FILE *)NULL); /* EOF, tell caller */
break;
}
filename[fnlen - 1] = '\0'; /* make sure */
/* if fgets() ever forgets the '\n', we're fucked */
if (*(cp = &filename[strlen(filename) - 1]) == '\n')
*cp = '\0';
if (filename[0] == '\0')
continue;
/**
** I don't care if it's separated by a space, or a tab, but I want
** the message-Id if it's in there.
**/
if (index(filename, ' ') != NULL) { /** Ala C-news **/
sscanf(filename, "%s %s", buffer, mesgid);
strcpy(filename, buffer);
if (!cnews) {
++cnews;
dprintf(stderr, "Hmmm... Config error, configed for B-news, but\n");
dprintf(stderr, " running C-news.\n");
}
} else if (index(filename, '\t') != NULL) {
sscanf(filename, "%s\t%s", buffer, mesgid); /** Ala B-news **/
strcpy(filename, buffer);
if (cnews) {
cnews = 0;
dprintf(stderr, "Hmmm... Config error, configed for C-news, but\n");
dprintf(stderr, " running B-news.\n");
}
} else strcpy(mesgid, "");
if ((newfp = fopen(filename, mode)) == (FILE *)NULL) {
/*
** The only permissible error is `file non-existant'
** anything else indicates something is seriously
** wrong, and we should go away to let the shell
** script clean up.
*/
if (errno != ENOENT) {
char buf[BUFSIZ];
sprintf(buf, E_fopen, filename, mode, errmsg(errno));
/*
log(L_WARNING, buf);
*/
goodbye(DONT_WAIT);
exit(EX_OSERR);
}
}
}
if (!connected)
if (hello(host, transport) == FAIL) {
sleep(Sleep_Time);
return(NULL);
} else
connected = TRUE;
return(newfp);
}