2.9BSD/usr/contrib/notes/bnewsinput.c

Compare this file to the similar file:
Show the results in this format:

static char *sccsid = "@(#)bnewsinput.c	1.2 2/2/83";

#include <sys/types.h>
#include "parms.h"
#include "structs.h"
#include "globs.h"
#include "newsgate.h"
#include "bnews.h"
/*
 *	bnewsinput.c
 *
 *	This program will accept an article according the the
 *	'B' protocol for news(I).  The article will then be inserted in
 *	the notefile(s) which match the newsgroup(s).  
 *
 *	Modified April 1982:
 *	The newer version is somewhat more streamlined.
 *	So, the other major difference in the new version is that if the
 *	title is of the form:
 *		some title - (nf)
 *	(or if the suffix is "- (nf)"
 *	we decide that it has been generated by notesfiles. This means that
 *	we are allowed to skip text up to a # and then we have a special 
 *	ALMOST generic notesfile format. The header information is 
 *	slightly different.
 *	see canon.h for the new format examples
 *
 *	Original Coding:	Ray Essick		Feb 1982
 *	Modified extensively:	Ray Essick		April 1982
 *	Modified to add some neat things
 *				Malcolm Slaney 		July 1982
 *	added code to catch misformed articles
 *				Ray Essick		July 27, 1982
 *	Modified to add even more neat things
 *				Rick L Spickelmier, UCB 1982
 *	Added the B news parser and multiple groups
 *				Rick L Spickelmier
 *
 */

extern char longtitle[WDLEN];   /* storage for titles longer the TITLEN */
#define min(A,B) ((A) > (B) ? (B) : (A))

main (argc, argv)
int argc;
char  **argv;
{
    struct io_f io;
    char    title[TITLEN + 40];			/* title */
    char    nf[NNLEN];				/* the notefile */
    char    fname[WDLEN];			/* hold scratch file name */
    char    ngroup[WDLEN][NUMGROUPS];			/* newsgroups name */
    char    fromsys[SYSSZ],
            origsys[SYSSZ];
    char   *p,
           *q,
           *r;
    char   *suffix;
    int     count,
            atcount,				/* count ARPA hosts */
            status;
    int     c;
    int     i,
            j,
            stat,
            length,				/* of title */
            notenum;
    struct note_f   note;
    struct note_f   note2;
    struct auth_f   auth;
    long newsseq;
    struct id_f respid;
    struct when_f   entered,
                    whentime;
    struct id_f newsid;
    char    line[CMDLEN];		/* scratch */
    struct daddr_f  where;
    FILE *rawnews;			/* raw news read from here */
    FILE *scr;				/* scratch file for holding article */
    FILE *hread();
    struct hbuf *hp;

#include "main.i"			/* common init code and such */

    rawnews = stdin;			/* read from the right file */

    /* Parse the header */
    hp = (struct hbuf *) malloc(sizeof(struct hbuf));
    rawnews = hread(hp, rawnews);

    /* get origsys and newsseq */
    sscanf(hp->ident,"%[^.].%ld",origsys,&newsseq);

    /* get the fromsys and author line */
    strcpy(line,hp->path);

    /* parse the path */
    i = strlen(line);				/* start at rhs */
    for (j = 0; j < i; j++)
	if (line[j] == ' ')
	    break;
    while (j && (line[j] != '!') && (line[j] != ':') && (line[j] != '.')) {
	j--;					/* back to sys */
    }
    atcount = 0;				/* count ARPA hosts parsed */
    if (j == 0) j = -1;

    for (i = 0, j++; (i < NAMESZ); i++) {
	if ((auth.aname[i] = line[j + i]) == '@' && atcount++) {
	    auth.aname[i] = '\0';
	    break;				/* only parse 1 ARPA host */
	} else {
	    if (auth.aname[i] == ' ') {
		auth.aname[i] = '\0';		/* null terminate */
		break;				/* and get out of here */
	    } else {
		if (auth.aname[i] == 0) {
		    break;
		}
	    }
	}
    }

    /* build the from system */
    for (i = 0; (i < SYSSZ - 1) && line[i] != '!' && line[i] != ':' && line[i] != '.'; i++) {
	fromsys[i] = line[i];
    }
    fromsys[i] = '\0';

    /* get the title and longtitle */
    strcpy(longtitle,hp->title);
    strncpy(title,longtitle,TITLEN+39);
    strcat(longtitle,"\n\n");
    title[min(TITLEN+39,strlen(longtitle))] = '\0';

    /* get the date */
    getdate(hp->subdate,&entered);

    /* get the newsgroups */
    sscanf(hp->nbuf,"%[^,\n]",ngroup[0]);

    /*
     * The header is now parsed, all left is text.
     * Check existence of the notesfile, permission
     * to write and other things like that
     */

    newsgroup (ngroup[0], nf, NEWSNF);		/* alias the bugger */
    
    if (init(&io, nf) < 0) {		/* well is it there? */
	printf("Non-existant notesfile: %s\n", nf);
#ifdef AUTOCREATE
	/* try to create the notes file - RLS */
	sprintf(line,"%s/%s/mknf -on %s",MSTDIR,UTILITY,nf);
	system(line);
	if (init(&io, nf) < 0) {
	    sprintf(line, "notesfile: %s, newsgroup %s\n", ngroup[0], nf);
	    nfcomment(NOSUCHWARN, line, "Failure", 0, 0);
	    exit(BAD);
	}
	    
	sprintf(line, "Created: %s\n", nf);
	nfcomment(NOSUCHWARN, line, line, 0, 0);
#else
	sprintf(line, "notesfile: %s, newsgroup %s\n", ngroup[0], nf);
	nfcomment(NOSUCHWARN, line, "Failure", 0, 0);
	exit(BAD);
#endif
    }

    if ((io.descr.d_stat & NETWRKD) == 0) {		/* networked ? */
	printf("Notesfile %s is not networked\n", nf);
	exit (BAD);
    }

    r = q = title;
    while (*r) {		/* look for last '-' */
	if (*r == '-') {
	    q = r;		/* this is new last */
	}
	r++;			/* on to the next */
    }
    suffix = q;		/* save the pointer for possible later use */
			/* like misformed articles with "- (nf)" */
    length = q - title;		/* non-nulls before '-' */
    if (strcmp(q, NFSUFFIX) != 0 && strcmp(q, OLDSUFFIX) != 0) {
					/* so is not nf generated */
/*
 *	we come back up to here if the article had the notesfile
 *	suffix and was not properly formatted.
 *	This is a stopgap measure due to the fact that I misdesigned
 *	the system so that notes used a right associative rule
 *	to determine its articles, while news programs used a
 *	left associative rule. Oh well. 
 *		- Ray Essick	July 27, 1982
 */

badform: 		/* come here if no "#" in a "- (nf)" article */

	getperms(&io, 1, origsys);
	if (allow(&io, WRITOK) == 0) {
	    printf("System %s not allowed to write notes\n", origsys);
	    exit (BAD);
	}


	strmove(origsys, newsid.sys);		/* build uniq id */
	newsid.uniqid = (-newsseq * 100) - 1;
						/* is not there yet */
	strmove(origsys, note.n_id.sys);
	note.n_id.uniqid = (-100 * newsseq);	/* build the note descriptor */
	copydate(&entered, &note.n_date);
	strmove(fromsys, note.n_from);
	stat = FRMNEWS;			/* came from news system */

	i = 0;				/* fix up the title */
	while (title[i++]);			/* get to the end */
	for (i--; i < TITLEN; i++) {
	    title[i] = ' ';			/* space pad */
	}

	lock(&io, 'n');

	if ((notenum = chknote (&io, &note.n_id, &note2)) == 0) {
	    if (!strncmp (title, "Re:", 3)) {  /* see if a "followup" */
		p = title;
		do {
		    p += 3;
		    while (*p == ' ')
			p++;			/* Skip Spaces */
		} while (!strncmp (p, "Re:", 3));   /* get all re's */
		strcpy(io.xstring, p);
		notenum = findtitle(&io, io.descr.d_nnote);
		if (notenum > 0 && !chkresp(&io, &newsid, &note2, notenum)) {
    		    longtitle[0] = '\0';
		    pagein(&io, rawnews, &where);
		    gettime(&whentime);
		    putresp(&io, &where, stat, notenum, &entered, &auth,
			    &note, NOLOCKIT, &newsid, NOADDID, fromsys, ADDTIME,
			    &whentime);
		} else {
		    if (notenum < 1) {
			pagein(&io, rawnews, &where);
			notenum = putnote(&io, &where, title, stat, &note, &auth,
				NOPOLICY, NOLOCKIT, NOADDID, fromsys, ADDTIME);
			io.nnotrcvd++;	/* count as networked in */
		    } else {
			printf("Duplicate Response handed back by news\n");
		    }
		}
	    } else {
		pagein(&io, rawnews, &where);
		notenum = putnote(&io, &where, title, stat, &note, &auth,
			NOPOLICY, NOLOCKIT, NOADDID, fromsys, ADDTIME);
		io.nnotrcvd++;		/* count as networked in */
	    }
	} else if (note2.n_stat & ORPHND) {	/* replace foster parent */
		pagein(&io, rawnews, &note2.n_addr);   /* collect text */
		gettime(&note2.n_rcvd);		/* current tod */
		gettime(&note2.n_lmod);		/* last touched */
		copyauth(&auth, &note2.n_auth);	/* fill in the author */
		note2.n_stat |= FRMNEWS;		/* brand it */
		for (i = 0; i < TITLEN; i++) {
		    note2.ntitle[i] = title[i];	/* move new title */
		}
		copydate(&entered, &note2.n_date);  /* written date */
		strcpy(note2.n_from, fromsys);   /* and who gave it to us */
		putnrec(&io, notenum, &note2);	/* and replace */
	    } else {
		printf("Duplicate news article received\n");
	    }

	unlock(&io, 'n');

    } else {				/* nf generated article */
	sprintf(fname, "/tmp/nfn%d", getpid ());     /* generate name */
	scr = fopen(fname, "w");		/* open scratch file */
	while ((c = getc(rawnews)) != '#' && c != EOF) { /* find start */
	    if (scr != NULL) {
		putc(c, scr);	/* hold it in the scratch file */
	    }
	}
	if (c == EOF) {
	    fclose(scr);		/* flush what is there */
	    if ((rawnews = fopen(fname, "r")) == NULL) {
		printf("Article lost in file system: %s\n", fname);
		unlink(fname);	/* remove the file */
		closenf(&io);	/* close the notesfile */
		exit(BAD);
	    }
	    *--suffix = '\0';	/* remove " - (nf)" suffix */
	    unlink(fname);	/* only link is the file descriptor */
	    goto badform;	/* reparse as a news article */
	}

	fclose(scr);		/* close and */
	unlink(fname);		/* toss the scratch file */

	switch (getc(rawnews)) {
	    case 'N': 		/* base note coming through news */
		if (fscanf(rawnews, ":%[^:]:%ld:%o:%d", note.n_id.sys,
			    &note.n_id.uniqid, &status, &count) != 4)
		    goto toobad;	/* bad form */
		while (getc(rawnews) != '\n');		/* skip eol */

		for (i = length; i < TITLEN; i++) {
		    title[i] = ' ';			/* space fill */
		}

		/* skip sys name, got elsewhere */
		while ((c = getc(rawnews)) != '!');  

		for (i = 0; (i < NAMESZ - 1) && ((c = getc (rawnews)) != ' '); i++)
		    auth.aname[i] = c;		/* get the author */

		i = 0;
		while ((line[i] = getc(rawnews)) != '\n');
							/* grab date */
		getdate(line, &note.n_date);

		/* loop in case trash on line */
		/* in theory this line is empty */
		while (getc(rawnews) != '\n');

		getperms(&io, 1, note.n_id.sys);    /* see if he's allowed */
		if (allow(&io, WRITOK) == 0) {	/* not a chance */
		    closenf(&io);
		    exit(BAD);
		}

		lock(&io, 'n');
		if ((notenum = chknote(&io, &note.n_id, &note2)) == 0) {
					/* is it there? */
		    pagein(&io, rawnews, &where);   /* grab text */
		    status |= FRMNEWS;		/* came through news! */
		    strmove(fromsys, note.n_from);
		    putnote(&io, &where, title, status, &note, &auth, NOPOLICY,
			    NOLOCKIT, NOADDID, fromsys, ADDTIME);
		    io.nnotrcvd++;			/* count it */
		} else {
		    if ((note2.n_stat & ORPHND) && NOT (status & ORPHND)) {
			/* extant is orphan, new isnt */
			pagein(&io, rawnews, &note2.n_addr);
						/* grab text */
			gettime(&note2.n_rcvd);
			gettime(&note2.n_lmod);	/* time stamp it */
			copyauth(&auth, &note2.n_auth);
					     /* put correct author */
			note2.n_stat = status + FRMNEWS;
					     /* correct status */
			for (i = 0; i < TITLEN; i++) {
			    note2.ntitle[i] = title[i];
			}
			copydate(&entered, &note2.n_date);
			strmove(fromsys, note2.n_from);
			putnrec(&io, notenum, &note2); /* and replace */
		    } else {				/* duplicate */
			printf("Duplicate note handed back by news\n");
		    }
		}
		unlock(&io, 'n');
		break;

	    case 'R': 		/* response coming through news */
		if (fscanf(rawnews, ":%[^:]:%ld:%[^:]:%ld:%o:%d", note.n_id.sys,
			    &note.n_id.uniqid, respid.sys, &respid.uniqid, &status, &count) != 6)
		    goto toobad;			/* bad form */
		while (getc(rawnews) != '\n');		/* skip eol */

		getperms(&io, 1, respid.sys);  /* see if he's allowed */
		if (allow(&io, RESPOK) == 0) {	/* not a chance */
		    closenf(&io);
		    exit(BAD);
		}

		/* skip sys name, got elsewhere */
		while ((c = getc(rawnews)) != '!');
		for (i = 0; (i < NAMESZ - 1) && ((c = getc(rawnews)) != ' '); i++)
		    auth.aname[i] = c;		/* get the author */

		i = 0;
		/* grab date */
		while ((line[i] = getc(rawnews)) != '\n');
		getdate(line, &entered);

		/* loop in case trash on line */
		/* in theory this line is empty */
		while (getc(rawnews) != '\n');

		lock(&io, 'n');
		notenum = chknote(&io, &note.n_id, &note2);
		if (notenum == 0) {	/* build foster parent */
		    printf("Orphaned response handed in by news\n");
		    strmove(fromsys, note.n_from);
		    note.n_nresp = 0;
		    note.n_auth.aid = ANONUID;
		    strcpy(note.n_auth.aname, "Unknown");
		    copydate(&entered, &note.n_date);
		    gettime(&whentime);		/* get current time */
		    status = ORPHND + FRMNEWS;	/* combo there */
		    for (i = 0, p = "Orphaned Response"; (i < TITLEN) && *p; p++, i++)
			note.ntitle[i] = *p;
		    for (; i < TITLEN; i++) {
			note.ntitle[i] = ' ';	 /* pad */
		    }

		    where.addr = 0;			/* no text */
		    notenum = putnote(&io, &where, note.ntitle, status,
			    &note, &note.n_auth, NOPOLICY, NOLOCKIT,
			    NOADDID, fromsys, ADDTIME);
		    io.norphans++;			/* census of orphans */
		    getnrec(&io, notenum, &note2);     /* get good one */
		}
		if (chkresp(&io, &respid, &note2, notenum) == 0) {
						/* none, insert it */
    		    longtitle[0] = '\0';
		    status |= FRMNEWS;
		    pagein(&io, rawnews, &where);
		    putresp(&io, &where, status, notenum, &entered, &auth,
			    &note, NOLOCKIT, &respid, NOADDID, fromsys, ADDTIME, &whentime);
		    io.nrsprcvd++;		/* count him in */
		} else {
		    printf("Duplicate response handed back by news\n");
		}
		unlock(&io, 'n');
		break;

	    default:		/* bad news coming through news */
	toobad: 			/* label for bad format jumps */
		printf("Some sort of failure caused jump to toobad\n");
		closenf(&io);
		exit(BAD);
	}
    }					/* end of nf coming back in */

    lock(&io, 'n');
    getdscr(&io, &io.descr);
    io.descr.netwrkins++;		/* count as net in */
    putdscr(&io, &io.descr);
    unlock(&io, 'n');

    finish(&io);
    exit(GOOD);
}