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
/
cnews.orig.lzh
/
relay
/
ihave.c
< prev
next >
Wrap
C/C++ Source or Header
|
1989-06-27
|
6KB
|
213 lines
/*
* Implement the Usenet ihave/sendme control messages,
* as per RFC 1036 (nee 850).
*/
#include <stdio.h>
#include <ctype.h>
#include <sys/types.h>
#include "libc.h"
#include "news.h"
#include "config.h"
#include "headers.h"
#include "article.h"
#include "history.h"
#include "fgetmfs.h"
#include "msgs.h"
#include "transmit.h"
#ifndef SENDMEDISTR
#define SENDMEDISTR "sendme" /* kludge: distinguished distribution for sendmes
/
#endif
#ifndef IHAVEDISTR
#define IHAVEDISTR "ihave" /* kludge: distinguished distribution for ihaves */
#endif
#ifndef AVEARTSIZE
#define AVEARTSIZE 3000
#endif
#define PROTO_IHAVE 0
#define PROTO_SENDME 1
/* static forwards */
FORWARD void doproto(), procmsgids(), procbodymsgids();
FORWARD statust faketrans();
/*
* Read message-IDs from args or control message body,
* look them up in history, post a sendme to to.remotesys (via the batcher
* to avoid deadlock) consisting of the message-IDs not in history.
* The "posting" consists of transmitting to a system matching
* "to.remotesys" in sys, which had better have the I flag on.
* ihave message-ID-list remotesys generate a sendme from message-ID-list
*/
void
ihave(args, art)
char *args;
struct article *art;
{
doproto(args, art, IHAVEDISTR, PROTO_IHAVE);
}
/*
* Read message-IDs from args or control message body,
* transmit the corresponding articles to a system matching
* "to.remotesys/sendme" in sys, which will typically name a batch file.
* sendme message-ID-list remotesys send articles named to remotesys
*/
void
sendme(args, art)
char *args;
struct article *art;
{
doproto(args, art, SENDMEDISTR, PROTO_SENDME);
}
static void
doproto(args, art, distr, proto)
char *args;
register struct article *art;
char *distr;
int proto;
{
register char *argscp = skipsp(args), *remotesys;
if (*argscp == '\n' || *argscp == '\0') /* no args */
return;
argscp = strsave(argscp);
/* dig out the remote system name */
remotesys = rindex(argscp, ' ');
if (remotesys == NULL) /* no msg-ids in command */
remotesys = argscp;
else {
remotesys = argscp + strlen(argscp) - 1; /* last byte */
while (isascii(*remotesys) && isspace(*remotesys))
*remotesys-- = '\0'; /* back up to non-whitespace */
remotesys = rindex(argscp, ' ');
if (remotesys == NULL) /* no msg-ids in command */
remotesys = argscp;
else
*remotesys++ = '\0'; /* separate msg-ids & sys name */
}
if (strcmp(remotesys, hostname()) != 0) /* remotesys may not be me */
if (remotesys != argscp) /* msg-ids in command */
procmsgids(art, argscp, remotesys, distr, proto);
else
procbodymsgids(art, remotesys, distr, proto);
free(argscp);
}
/*
* Process a list of message-ids in msgidln: look them up
* and "transmit" the articles to to.remotesys.
*/
static void
procmsgids(art, msgidln, remotesys, distr, proto)
struct article *art;
char *msgidln, *remotesys, *distr;
int proto;
{
char *cpmsgid = strsave(skipsp(msgidln));
register char *msgid = cpmsgid, *endmsgid;
register int save, sendit;
for (; *msgid != '\n' && *msgid != '\0'; msgid = skipsp(endmsgid)) {
for (endmsgid = msgid; *endmsgid != '\0' &&
isascii(*endmsgid) && !isspace(*endmsgid); ++endmsgid)
; /* skip msgid */
save = *endmsgid;
*endmsgid = '\0'; /* terminate msgid at whitespace */
if (proto == PROTO_IHAVE)
sendit = !alreadyseen(msgid); /* sendme from remotesys */
else
sendit = alreadyseen(msgid); /* sendme to remotesys */
if (sendit)
art->a_status |= faketrans(msgid, remotesys, distr, proto);
*endmsgid = save;
}
free(cpmsgid);
}
static void
procbodymsgids(art, remotesys, distr, proto)
register struct article *art;
char *remotesys, *distr;
int proto;
{
register FILE *arttext;
arttext = fopenwclex(art->a_tmpf, "r");
if (arttext != NULL) {
char *line;
while ((line = fgetms(arttext)) != NULL && *line != '\n')
nnfree(&line); /* skip header */
if (line != NULL) { /* article body exists */
nnfree(&line); /* toss blank separating line */
while ((line = fgetms(arttext)) != NULL) {
procmsgids(art, line, remotesys, distr, proto);
nnfree(&line);
}
}
(void) nfclose(arttext);
}
}
/*
* Fake up a minimal article struct for msgid using group to.remotesys and
* distribution distr, then invoke transmit(). If there is a history
* entry for msgid, supply the list of file names too.
* Generate a log entry for each message-id transmitted.
*/
static statust
faketrans(msgid, remotesys, distr, proto)
register char *msgid, *remotesys;
char *distr;
int proto;
{
struct article fakeart;
register char *ng;
register char *histent;
register struct article *fap = &fakeart;
time_t now;
statust status = ST_OKAY;
ng = nemalloc((unsigned)(STRLEN("to.") + strlen(remotesys) + 1));
(void) strcpy(ng, "to.");
(void) strcat(ng, remotesys);
artinit(fap);
fap->h.h_ngs = ng;
fap->h.h_distr = (distr != NULL? distr: ng);
fap->h.h_msgid = msgid;
fap->h.h_path = hostname();
fap->a_charswritten = AVEARTSIZE;
histent = gethistory(msgid);
if (histent == NULL || (fap->a_files = findfiles(histent)) == NULL)
fap->a_files = "no.such.article!";
timestamp(stdout, &now); /* start log line */
if (printf(" %s %c %s", sendersite(nullify(fap->h.h_path)),
(proto == PROTO_IHAVE? 'i': 's'), fap->h.h_msgid) == EOF)
fulldisk(fap, "stdout");
transmit(fap, ""); /* write on batch file; write sys name on stdout */
(void) putchar('\n'); /* end log line */
status |= fap->a_status; /* pass back failure writing batch file */
fap->h.h_ngs = NULL;
fap->h.h_distr = NULL;
fap->h.h_msgid = NULL;
fap->h.h_path = NULL;
fap->a_files = NULL;
artfree(fap);
free(ng);
return status;
}