|
|
BSD 4.3
#define MAINLINE
#include "parms.h"
#include "structs.h"
#include "newsgate.h"
#ifdef RCSIDENT
static char rcsid[] = "$Header: /var/lib/cvsd/repos/CSRG/43BSD/contrib/notes/src/newsinput.c,v 1.1.1.1 2018/04/24 16:12:54 root Exp $";
#endif RCSIDENT
/*
* newsinput
*
* A total re-coding of the original. Makes use of the
* work that Lou Salkind and Tw Cook have done. Lou rearranged
* a bunch of stuff and Tw put the notes headers into the
* news header.
*/
static char title[TITLEN + 1]; /* hold titles */
extern char fromsys[SYSSZ + 1]; /* gave it to us */
static struct when_f entered; /* date written */
extern char origsys[SYSSZ + 1]; /* originator */
extern char authname[NAMESZ + 1]; /* author */
static int has_suffix = 0; /* had -(nf) suffix */
#define dprintf if (0) printf
main (argc, argv)
int argc;
char **argv;
{
FILE * rawnews;
FILE * body;
char pathname[BUFSIZ];
struct io_f io;
struct hbuf header;
char nf[WDLEN];
struct nflist_f *nfptr; /* expand newsgroups */
int c;
int onechar;
char *tail;
int fid; /* for close */
setuid (geteuid ()); /* force to "notes" */
startup (argc, argv); /* comon init */
rawnews = stdin; /* usually here */
for (fid = 3; fid < 20; fid++) /* close all extras */
close (fid);
/*
* Parse the Header. Follow all the USENET standards
* for doing this. Result is left in a fun little
* structure.
* Internalize some of the information to help us figure out
* some things quickly.
*/
if (!newsheader (&header, rawnews, TRUE)) /* read the headers */
{
printf ("Incoming News mangled more than usual\n");
exit (BAD);
}
/*
* Parse things like origsys, fromsys, author, date written
*/
parsepath (header.path, header.from); /* systems, authors */
parsetime (header.subdate, &entered); /* submitted */
sprintf (pathname, "/tmp/nfxx%d", getpid ());
dprintf ("Origsys: %s\n", origsys);
dprintf ("fromsys: %s\n", fromsys);
dprintf ("Date Written:");
#ifdef notdef
prdate (&entered);
#endif
dprintf ("\nauthor: %s\n", authname);
/*
* See if this might be a control message. Notes readers don't
* care to see these.
*
* News code also recognizes titles with first 5 characters set
* to "cmsg " as control messages. We should clean them up too.
*/
if (header.ctlmsg[0] != '\0') /* is control */
{
printf ("Control message (ignored): %s\n", header.ctlmsg);
exit (0); /* "success" */
}
/*
* Save the body of the article somewhere safe (like not in
* memory).
*/
if ((body = fopen (pathname, "w")) == NULL) /* failed */
{
printf ("Had problems creating/opening file %s\n", pathname);
exit (BAD); /* die */
}
while ((onechar = getc (rawnews)) != EOF) /* save it */
putc (onechar, body);
fflush (body); /* make sure */
fclose (body); /* and close it */
/*
* Now run through the specified list of newsgroups,
* re-scan the body and such each time.
*/
expand (header.nbuf); /* expand groups */
while ((nfptr = nextgroup ()) != (struct nflist_f *) NULL)
{
newsgroup (nfptr -> nf_name, nf, NEWSNF); /* map it */
dprintf ("Newsgroup %s maps to notesfile %s\n", nfptr -> nf_name, nf);
tail = rindex (nfptr -> nf_name, '.'); /* catch ctl msgs */
if (tail != (char *) NULL && !strcmp (tail, CTL))/* it is one */
{
char pbuf[256]; /* for title fixing */
strcpy (nf, NFMAINT); /* map it */
dprintf ("Control newsgroup %s mapped to %s\n",
nfptr -> nf_name, nf);
sprintf (pbuf, "%s:%s", nfptr -> nf_name, header.title);
strncpy (header.title, pbuf, BUFLEN); /* prefix title */
header.title[BUFLEN - 1] = '\0'; /* ensure terminater */
}
if ((body = fopen (pathname, "r")) == NULL)
{
goto failed; /* shit */
}
if (init (&io, nf) < 0) /* open the nf */
{
char pbuf[512];
char tbuf[128];
#ifdef AUTOCREATE
sprintf (pbuf,
"Notesfile: %s\nNewsgroup: %s\n\nCreated by newsinput\n",
nf, nfptr -> nf_name);
sprintf (tbuf, "New NF: %s", nf);
nfcomment (NFMAINT, pbuf, tbuf, TRUE, 0);
buildnf (nf, Mstdir, 0, 1, 1); /* open and networked */
x (init (&io, nf) < 0, "newsinput: open newly created notesfile");
#else
sprintf (pbuf, "Notesfile: %s, newsgroup %s\n",
nf, nfptr -> nf_name);
sprintf (tbuf, "New newsgroup %s", nfptr -> nf_name);
nfcomment (NFMAINT, pbuf, tbuf, 0, 0);
printf ("Inserting into %s\n", NEWNEWS);
strcpy (nf, NEWNEWS); /* Change newsgroup */
if (init (&io, nf) < 0)
exit (BAD); /* Give up */
printf ("Open of %s suceeded\n", nf);
#endif AUTOCREATE
}
if (nfgen (&io, &header, body, pathname) < 0) /* not from notes */
{
dprintf ("Nfgen returns failure\n");
fclose (body); /* give bnewsgen */
body = fopen (pathname, "r"); /* a clean copy */
if (bnewsgen (&io, &header, body) < 0) /* or news */
{
dprintf ("bnewsgen returns failure\n");
goto failed; /* drop out */
}
}
fclose (body); /* ready for loop */
finish (&io);
}
unlink (pathname);
exit (GOOD);
/*
* jump here on totally screwed up article.
*/
failed:
dprintf ("Jumped to failed\n");
unlink (pathname); /* body of article */
exit (BAD);
}
/*
* nfgen(&io,&header,&FILE,pathname)
*
* parse a notesfile-generated article. Check the fields of
* header and look for # lines in the body of the article to
* determine if it came from notes.
*
* returns: 0 no permission for author
* > 0 signifies note or response where it wound up
* -1 if the article wasn't generated by notes
*/
nfgen (io, header, body, pathname)
struct io_f *io;
struct hbuf *header;
FILE * body;
char *pathname;
{
register int i;
register char *p;
struct note_f note;
struct note_f note2;
struct id_f respid;
struct daddr_f where;
struct when_f whentime;
struct auth_f auth; /* author */
int oldstyle = 0;
int found;
char line[CMDLEN]; /* scratch */
char *suffix;
int notenum;
int status;
int fosterstat; /* for foster parents */
int count;
char hline1[BUFLEN]; /* in-text header */
char hline2[BUFLEN]; /* in-text header 2 */
int onechar; /* scratch character */
char field1[100], /* scanf tmps */
field2[100];
/*
* Check for titles ending in "- nf".
* We always remove these.
*/
suffix = rindex (header -> title, '-'); /* find last */
if (!strcmp (suffix, NFSUFFIX) || !strcmp (suffix, OLDSUFFIX))
{
if (--suffix > header -> title) /* if we can */
*suffix = '\0'; /* strip "- (nf)" */
has_suffix++; /* flag it */
}
/*
* at this point we should check for embodied #N.... lines and
* remove them. This is conditional on having a "- (nf)" in the
* title of the note.
*/
strcpy (hline1, ""); /* empty these */
strcpy (hline2, "");
if (has_suffix) /* look for embedded */
{
long position, /* place marker */
ftell (); /* for types */
position = ftell (body); /* save it */
while (fgets (hline1, sizeof hline1, body) != NULL)
if (hline1[0] == '#')
break; /* found one */
if (hline1[0] != '#') /* actually didn't */
{
fseek (body, position, 0); /* rewind */
strcpy (hline1, ""); /* empty it */
}
else
{ /* grab line 2 */
fgets (hline2, sizeof hline2, body);
while ((onechar = getc (body)) != '\n' && onechar != EOF)
; /* zap separator line */
}
}
if (strlen (header -> nline1) == 0) /* no new headers */
{
/*
* No notes header in the B news article header...
* If title ends with "- nf", look for the
* header in the body of the text.
* (for backwards compatability)
*/
if (has_suffix == 0) /* not from notes */
{
dprintf ("No NFSUFFIX and no header lines\n");
return (-1);
}
oldstyle = 1;
found = 0;
if (hline1[0] == '#') /* got them earlier */
{
strcpy (header -> nline1, hline1); /* first line */
strcpy (header -> nline2, hline2); /* second line */
found++; /* and mark it */
}
while (!found && /* search body */
fgets (header -> nline1, sizeof header -> nline1, body))
{
if (header -> nline1[0] == '#') /* bingo */
{
found++;
break;
}
}
if (!found ||
fgets (header -> nline2, sizeof header -> nline2, body) == NULL)
{
dprintf ("no header lines in text body\n");
return (-1); /* not from notes */
}
}
/*
* We now have the header lines.
* Check validity and do the appropriate action.
*/
if (header -> nline1[0] != '#')
{
dprintf ("Invalid first header line\n");
return (-1);
}
dprintf ("First line is: %s\n", header -> nline1);
dprintf ("Second line is: %s\n", header -> nline2);
strncpy (title, header -> title, TITLEN); /* get title */
title[TITLEN - 1] = '\0'; /* terminate for sure */
switch (header -> nline1[1]) /* parse it */
{
case 'N': /* base note */
if (sscanf (header -> nline1, "#N:%99[^:]:%ld:%o:%d", field1,
¬e.n_id.uniqid, &status, &count) != 4)
{
return (-1); /* no good */
}
strncpy (note.n_id.sys, field1, SYSSZ); /* copy */
note.n_id.sys[SYSSZ - 1] = '\0'; /* and terminate */
status |= FRMNEWS; /* it's been there */
/*
* parse the second header line
*/
p = header -> nline2;
for (i = 0; (i < HOMESYSSZ - 1) && (*p != '!' && *p != '\0'); i++)
auth.asystem[i] = *p++; /* get the author */
auth.asystem[i] = '\0'; /* terminate */
while (*p != '!' && *p != '\0')
p++; /* skip to end of system */
if (*p == '!')
p++; /* skip the ! */
for (i = 0; (i < NAMESZ - 1) && (*p != ' ' && *p != '\0'); i++)
auth.aname[i] = *p++; /* get the author */
auth.aname[i] = '\0'; /* terminate */
auth.aid = Anonuid;
while (*p != ' ' && *p)
p++; /* drop rest of author */
while (*p == ' ') /* find the date */
p++;
parsetime (p, ¬e.n_date); /* and parse it */
getperms (io, 1, note.n_id.sys); /* check permissions */
if (allow (io, WRITOK) == 0) /* not a chance */
return (0); /* sort of success */
locknf (io, DSCRLOCK); /* MUTEX */
if ((notenum = chknote (io, ¬e.n_id, ¬e2)) == 0)
{ /* not in data base */
pagein (io, body, &where); /* grab text */
status |= FRMNEWS; /* through news */
strcpy (note.n_from, fromsys); /* who gave it to us */
i = putnote (io, &where, title, status, ¬e, &auth,
NOPOLICY, NOLOCKIT, NOADDID, fromsys, ADDTIME);
io -> nnotrcvd++; /* count it */
unlocknf (io, DSCRLOCK); /* MUTEX done */
return (i); /* return notenum */
}
if ((note2.n_stat & ORPHND) && (status & ORPHND) == 0)
{ /* replace foster */
/* with true parent */
pagein (io, body, ¬e2.n_addr); /* the text */
gettime (¬e2.n_rcvd); /* update timestamp */
gettime (¬e2.n_lmod); /* time stamp it */
copyauth (&auth, ¬e2.n_auth); /* correct author */
note2.n_stat = status | FRMNEWS; /* and status bits */
strncpy (note2.ntitle, title, TITLEN);
note2.n_date = entered;
strcpy (note2.n_from, fromsys);
putnrec (io, notenum, ¬e2); /* and replace */
io -> adopted++; /* count adoption */
io -> nnotrcvd++; /* count in */
unlocknf (io, DSCRLOCK);
printf ("Orphaned response chain adopted\n");
return (notenum); /* note number */
}
else
printf ("Duplicate note handed back by news\n");
unlocknf (io, DSCRLOCK);
return (0); /* mark resolved */
case 'R': /* response */
if (sscanf (header -> nline1, "#R:%99[^:]:%ld:%99[^:]:%ld:%o:%d",
field1, ¬e.n_id.uniqid, field2,
&respid.uniqid, &status, &count) != 6)
{
return (-1); /* no good */
}
strncpy (note.n_id.sys, field1, SYSSZ); /* copy them */
strncpy (respid.sys, field2, SYSSZ); /* both and */
note.n_id.sys[SYSSZ - 1] = respid.sys[SYSSZ - 1] = '\0';/* stop */
status |= FRMNEWS; /* it's been there */
getperms (io, 1, respid.sys); /* check modes */
if (allow (io, RESPOK) == 0) /* not a chance */
return (0); /* resolved */
p = header -> nline2; /* second line */
for (i = 0; (i < HOMESYSSZ - 1) && (*p != '!' && *p != '\0'); i++)
auth.asystem[i] = *p++; /* get the author */
auth.asystem[i] = '\0'; /* terminate */
while (*p != '!' && *p != '\0')
p++; /* skip to end of system */
if (*p == '!')
p++; /* skip the ! */
for (i = 0; (i < NAMESZ - 1) && (*p != ' ' && *p != '\0'); i++)
auth.aname[i] = *p++; /* parse author */
auth.aname[i] = '\0'; /* terminate */
auth.aid = Anonuid; /* default */
while (*p != ' ' && *p)
p++; /* rest of author */
while (*p == ' ') /* find the date */
p++;
parsetime (p, &entered); /* and parse it */
locknf (io, DSCRLOCK); /* MUTEX */
notenum = chknote (io, ¬e.n_id, ¬e2);
if (notenum == 0) /* found parent? */
{ /* build foster */
printf ("Orphaned response handed in by news\n");
strcpy (note.n_from, fromsys); /* make basic info */
note.n_nresp = 0;
note.n_auth.aid = Anonuid;
strcpy (note.n_auth.aname, "Unknown");
strcpy (note.n_auth.asystem, note.n_id.sys);/* system */
note.n_date = entered;
gettime (&whentime); /* current time */
fosterstat = ORPHND | FRMNEWS; /* combo there */
#ifdef notdef
strcpy (note.ntitle, "(Orphan) "); /* prefix */
#else
strcpy (note.ntitle, ""); /* empty */
#endif
i = strlen (note.ntitle); /* index */
for (p = header -> title; i < TITLEN && *p; i++, p++)/* rest of title */
note.ntitle[i] = *p; /* basic title */
if (i < TITLEN)
note.ntitle[i] = '\0'; /* null it */
else
note.ntitle[TITLEN - 1] = '\0'; /* null */
where.addr = 0; /* no text */
where.textlen = 0; /* still no text */
notenum = putnote (io, &where, note.ntitle, fosterstat,
¬e, ¬e.n_auth, NOPOLICY, NOLOCKIT, NOADDID,
fromsys, ADDTIME); /* insert him */
io -> norphans++; /* orphan census */
getnrec (io, notenum, ¬e2); /* get good one */
}
/*
* At this point we know we have a parent because if there wasn't
* one before, we built a foster parent.
*/
if (chkresp (io, &respid, ¬e2, notenum) == 0)
{ /* none, insert it */
status |= FRMNEWS;
pagein (io, body, &where);
i = putresp (io, &where, status, notenum, &entered, &auth,
¬e, NOLOCKIT, &respid, NOADDID, fromsys,
ADDTIME, &whentime);
io -> nrsprcvd++; /* count him in */
unlocknf (io, DSCRLOCK); /* UNMUTEX */
return (i); /* resp number */
}
else
printf ("Duplicate response handed back by news\n");
unlocknf (io, DSCRLOCK);
return (0); /* resolved */
default: /* bad news */
return (-1);
} /* NOTREACHED */
return (0);
}
/*
* bnewsgen(&io,&header,&FILE)
*
* parse an article that came through B-news. We've already
* checked to see if it was a notesfile generated article
* so all we have to do is decide if it's a note/response
* and put it in the appropriate place.
*/
bnewsgen (io, header, body)
struct io_f *io;
struct hbuf *header;
FILE * body;
{
register int i;
char *p;
struct note_f note;
struct note_f note2;
struct when_f whentime;
struct daddr_f where;
int notenum;
int status;
char pbuf[BUFLEN]; /* scratch */
long newsseq;
char newssys[SYSSZ];
struct id_f newsid;
struct auth_f auth;
char *lead,
*trail; /* references */
char basesys[SYSSZ]; /* references */
long baseseq; /* ditto */
struct id_f baseid; /* ditto ditto */
char field1[100], /* scanf tmps */
field2[100];
getperms (io, 1, origsys);
if (allow (io, WRITOK) == 0) /* let him* */
{
printf ("System %s not allowed to write notes\n", origsys);
return (0); /* NO! */
}
i = sscanf (header -> ident, "<%ld@%99[^>]>", &newsseq, field1, pbuf);
if (i < 2) /* try old */
{
i = sscanf (header -> ident, "%99[^.].%ld", field1, &newsseq);
}
if (i < 2) /* no id */
{
#ifdef NFMAINT
char pbuf[BUFSIZ];
sprintf (pbuf,
"Message-ID: %s\nPath: %s\nFrom: %s\nNewsgroups: %s\n",
header -> ident, header -> path,
header -> from, header -> nbuf);
nfcomment (NFMAINT, pbuf, "Unfathomable Article ID", 0, 0);
#endif NFMAINT
dprintf ("can't fathom article ID: %s\n", header -> ident);
return (-1); /* mark bogus */
}
strncpy (newssys, field1, SYSSZ); /* copy */
newssys[SYSSZ - 1] = '\0'; /* and truncate */
note.n_date = entered;
strcpy (note.n_from, fromsys);
strncpy (auth.aname, authname, NAMESZ); /* fill in author */
strncpy (auth.asystem, origsys, HOMESYSSZ); /* system */
auth.asystem[HOMESYSSZ - 1] = auth.aname[NAMESZ - 1] = '\0';
auth.aid = Anonuid;
status = FRMNEWS; /* came through news */
strncpy (title, header -> title, TITLEN); /* move new title */
title[TITLEN - 1] = '\0'; /* sure it stops */
locknf (io, DSCRLOCK); /* MUTEX */
/*
* first thing is to see if it's a base note somewhere.
*/
strcpy (newsid.sys, newssys); /* build uniq id */
strcpy (note.n_id.sys, newssys); /* build descriptor */
note.n_id.uniqid = newsid.uniqid = newsseq;
notenum = chknote (io, ¬e.n_id, ¬e2); /* try normal */
if (notenum == 0) /* try -100 trick */
{
note.n_id.uniqid = newsid.uniqid = newsseq * -100;
notenum = chknote (io, ¬e.n_id, ¬e2);
}
if (notenum != 0)
{
if (!(note2.n_stat & ORPHND))
{
printf ("Duplicate news article received\n");
io -> nnotdrop++; /* count as dropped */
unlocknf (io, DSCRLOCK);
return (0); /* done with it */
}
/*
* replace foster parent
*/
pagein (io, body, ¬e2.n_addr); /* collect text */
gettime (¬e2.n_rcvd); /* current tod */
gettime (¬e2.n_lmod); /* last touched */
copyauth (&auth, note2.n_auth); /* fill in author */
note2.n_stat |= FRMNEWS; /* brand it */
strncpy (note2.ntitle, title, TITLEN); /* move title */
note2.n_date = entered;
strcpy (note2.n_from, fromsys); /* who sent it to us */
putnrec (io, notenum, ¬e2); /* and replace */
io -> adopted++; /* count it */
io -> nnotrcvd++; /* count in */
unlocknf (io, DSCRLOCK);
printf ("Orphaned Response Chain adopted\n");
return (notenum); /* correctly placed */
}
/*
* See if we can turn this into a response to some base note.
* First priority is to match it to any of the articles listed
* in a References field if there is one.
*/
notenum = 0; /* init to not found */
if (header -> followid[0]) /* references */
{
trail = header -> followid;
while ((lead = index (trail, '<')) && (trail = index (lead, '>')))
{ /* delimited id */
i = sscanf (lead, "<%ld@%99[^>]>", &baseseq, field1, pbuf);
if (i < 2) /* try old format */
i = sscanf (lead, "%99[^.].%ld", field1, &baseseq);
if (i < 2)
continue; /* try next one */
strncpy (basesys, field1, SYSSZ);
basesys[SYSSZ - 1] = '\0'; /* and truncate */
strcpy (baseid.sys, basesys); /* build goal */
baseid.uniqid = baseseq; /* try notes source */
if ((notenum = chknote (io, &baseid, ¬e2)))/* WANT ASSIGN */
break; /* yes! */
baseid.uniqid = baseseq * -100; /* try news source */
if ((notenum = chknote (io, &baseid, ¬e2)))/* WANT ASSIGN */
break; /* yes! */
notenum = 0; /* ensure "unfound" */
}
}
/*
* If References did any good, "notenum" is positive non-zero.
* Otherwise it didn't help out at all and we have to resort to
* parsing the title for "re:" prefixes
* If we can find a base title, use the title search code to
* scan for it.
*/
if (notenum == 0 && /* not found */
!strncmp (header -> title, "re: ", 4) || /* and looks like */
!strncmp (header -> title, "Re: ", 4) || /* a response */
!strncmp (header -> title, "RE: ", 4))
{
dprintf ("Looking at titles\n");
p = header -> title;
do
{
for (p += 3; *p == ' ' || *p == '\t'; p++); /* drop spaces */
} while (!strncmp (p, "re: ", 4) ||
!strncmp (p, "Re: ", 4) ||
!strncmp (p, "RE: ", 4));
strncpy (io -> xstring, p, TITLEN); /* load it */
io -> xstring[TITLEN - 1] = '\0'; /* and terminate it */
notenum = findtitle (io, io -> descr.d_nnote, FALSE);/* start at back */
if (notenum > 0) /* found one */
getnrec (io, notenum, ¬e2); /* get a ptr to it */
}
/*
* OK. By now, we have a "notenum" if the article can be pegged
* as a response to one of our notes.
* Otherwise, notenum==0 and we'll have to turn it into
* a base note.
*/
if (notenum > 0)
{
dprintf ("Looking in response chain for note %d\n", notenum);
if (!chkresp (io, &newsid, ¬e2, notenum))
{ /* no copy here */
pagein (io, body, &where);
gettime (&whentime);
i = putresp (io, &where, status, notenum, &entered, &auth, ¬e,
NOLOCKIT, &newsid, NOADDID, fromsys, ADDTIME, &whentime);
unlocknf (io, DSCRLOCK); /* un-MUTEX */
return (i);
}
else
{ /* copy there */
unlocknf (io, DSCRLOCK); /* all done */
printf ("Duplicate Response handed back by news\n");
io -> nrspdrop++; /* bong it */
return (0); /* count as done */
}
}
/*
* If we are going to do things this way, here is the point
* where we should check about turning a news-generated
* article into an orphaned response.
*
* Basically, look for a non-empty references line and
* make a foster parent with the first article id on that
* line.
*/
/*
* by this point, it's obvious that we can't turn the note into
* a response. We can skip the check to see if it is already
* there because we did that at the very top of this loop
* and since we've locked the notesfile up while we're doing this,
* we know that nobody added a note.
*/
dprintf ("Processing article as a base note\n");
pagein (io, body, &where);
notenum = putnote (io, &where, title, status, ¬e,
&auth, NOPOLICY, NOLOCKIT, NOADDID, fromsys, ADDTIME);
io -> nnotrcvd++; /* count it */
unlocknf (io, DSCRLOCK);
return (notenum);
}
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.