From: utzoo!decvax!pur-ee!uiucdcs!essick Newsgroups: net.notes Title: Re: Bug in newsinput.c - (nf) Article-I.D.: uiucdcs.297 Posted: Fri Jul 30 10:28:39 1982 Received: Sat Jul 31 05:17:52 1982 #R:cmcl2:-808200:uiucdcs:23300010:004:15212 uiucdcs!essick Jul 30 09:48:00 1982 As promised, here is a version of newsinput that handles (maybe not perfectly, but a lot closer) the various problems that were there before. In particular, Malcolm Slaney was kind enough to provide the code to parse the "Re:" prefixes of news articles. The problem where articles having both "Re:" and "- (nf)" has also been taken care of. To use this new routine, one has to modify "tsearch.c", a copy of which is in another response. The makefile should also be modified so that "tsearch.o" is included as a dependency for newsinput and is loaded with newsinput. This version seems to be working for me. Ray Essick - - - - - - - #include "structs.h" #include "globs.h" #include "newsgate.h" /* * newsinput.c * * This program will accept an article according the the * 'A' protocol for news(I). The article will then be inserted in * the notefile which matches the newsgroup. * The program will not insert an article into multiple newsgroups! * * Modified April 1982: * The newer version is somewhat more streamlined. It still uses the * A protocol for intersystem transfer, but since the B news release * still accepts this stuff, I don't mind. I also am too lazy to bother * rewriting the header parser to grab the B format. ( someone could * probably figure a way to simply steal the code out of B news and * deposit it here, but I have other things I would rather do) * * 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 * */ main (argc, argv) 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[100]; /* newsgroup 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[WDLEN + 1]; /* scratch */ struct daddr_f where; FILE * rawnews; /* raw news read from here */ FILE * scr; /* scratch file for holding article */ #include "main.i" /* common init code and such */ rawnews = stdin; /* read from the right file */ /* Parse the header */ if (getc (rawnews) != 'A') { fprintf (stderr, "Article not protocol A\n"); exit (BAD); /* wrong protocol */ } fscanf (rawnews, "%[^.].%ld", origsys, &newsseq); while (getc (rawnews) != '\n'); /* skip to next line */ /* grab the 'newsgroup' */ for (i = 0; (i < 99) && ((c = getc (rawnews)) != '\n') && (c != ','); i++) ngroup[i] = c; ngroup[++i] = '\0'; /* null terminate */ if (c != '\n') while (getc (rawnews) != '\n'); /* skip to eol */ /* now the author line */ for (i = 0; (i < WDLEN) && ((c = getc (rawnews)) != '\n'); i++) line[i] = c; /* grab the whole line */ line[i] = '\0'; /* terminate it */ if (c != '\n') while (getc (rawnews) != '\n'); /* make sure is end */ j = i; /* start at rhs */ while (j && (line[j] != '!') && (line[j] != ':') && (line[j] != '.')) j--; /* back to sys */ atcount = 0; /* count ARPA hosts parsed */ 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 date written */ i = 0; while ((line[i++] = getc (rawnews)) != '\n'); line[i] = '\0'; /* build this line */ getdate (line, &entered); /* and grab it */ /* now the title line */ for (i = 0; (i < TITLEN + 39) && ((c = getc (rawnews)) != '\n'); i++) title[i] = c; title[i] = '\0'; /* null terminator there */ if (c != '\n') while (getc (rawnews) != '\n'); /* skip eol */ /* The header is now parsed, all left is text. Check existence * of the notesfile, permission to write and other things like that */ newsgroup (ngroup, nf, NEWSNF); /* alias the bugger */ if (init (&io, nf) < 0) /* well is it there? */ { printf ("No notesfile: %s\n", nf); #ifdef NOSUCHWARN sprintf (line, "Notesfile: %s, newsgroup %s\n", ngroup, nf); nfcomment (NOSUCHWARN, line, "unknown newsgroup", 0, 0); #endif #ifdef NEWNEWS /* save those new ones */ /* this code courtesy of malcolm... */ printf ("Inserting into nfmaint\n"); sprintf (title, "New Newsgroup: %s", nf); /* Blow away old title */ strcpy (nf, NEWNEWS); /* Change the newsgroup */ if (init (&io, nf) < 0) exit (BAD); /* Give UP */ printf ("Open of %s suceeded\n", nf); #else exit (BAD); /* apparently not */ #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 (streq (q, NFSUFFIX) != 0 && streq (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, ¬e.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, ¬e.n_id, ¬e2)) == 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, ¬e2, notenum)) { pagein (&io, rawnews, &where); gettime (&whentime); putresp (&io, &where, stat, notenum, &entered, &auth, ¬e, NOLOCKIT, &newsid, NOADDID, fromsys, ADDTIME, &whentime); } else if (notenum < 1) { pagein (&io, rawnews, &where); notenum = putnote (&io, &where, title, stat, ¬e, &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, ¬e, &auth, NOPOLICY, NOLOCKIT, NOADDID, fromsys, ADDTIME); io.nnotrcvd++; /* count as networked in */ } } else if (note2.n_stat & ORPHND) /* replace foste parent */ { pagein (&io, rawnews, ¬e2.n_addr); /* collect text */ gettime (¬e2.n_rcvd); /* current tod */ gettime (¬e2.n_lmod); /* last touched */ copyauth (&auth, ¬e2.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, ¬e2.n_date); /* written date */ strcpy (note2.n_from, fromsys); /* and who gave it to us */ putnrec (&io, notenum, ¬e2); /* 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, ¬e.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 */ while ((c = getc (rawnews)) != '!'); /* skip sys name, got elsewhere */ 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, ¬e.n_date); /* use secret decoder ring */ while (getc (rawnews) != '\n'); /* loop in case trash on line */ /* in theory this line is empty */ 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'); /* get exclusive mining rights */ if ((notenum = chknote (&io, ¬e.n_id, ¬e2)) == 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, ¬e, &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, ¬e2.n_addr); /* grab text */ gettime (¬e2.n_rcvd); gettime (¬e2.n_lmod); /* time stamp it */ copyauth (&auth, ¬e2.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, ¬e2.n_date); strmove (fromsys, note2.n_from); putnrec (&io, notenum, ¬e2); /* and replace */ } else { /* duplicate */ printf ("Duplicate note handed back by news\n"); } unlock (&io, 'n'); /* open to the rest of world */ break; case 'R': /* response coming through news */ if (fscanf (rawnews, ":%[^:]:%ld:%[^:]:%ld:%o:%d", note.n_id.sys, ¬e.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); } while ((c = getc (rawnews)) != '!'); /* skip sys name, got elsewhere */ 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, &entered); /* use secret decoder ring */ while (getc (rawnews) != '\n'); /* loop in case trash on line */ /* in theory this line is empty */ lock (&io, 'n'); /* lock it up */ notenum = chknote (&io, ¬e.n_id, ¬e2); 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, ¬e.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, ¬e, ¬e.n_auth, NOPOLICY, NOLOCKIT, NOADDID, fromsys, ADDTIME); io.norphans++; /* census of orphans */ getnrec (&io, notenum, ¬e2); /* get good one */ } if (chkresp (&io, &respid, ¬e2, notenum) == 0) { /* none, insert it */ status | = FRMNEWS; pagein (&io, rawnews, &where); putresp (&io, &where, status, notenum, &entered, &auth, ¬e, 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); }